-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #96 from efiring/order_constit
Order constit
- Loading branch information
Showing
3 changed files
with
165 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import numpy as np | ||
import pytest | ||
|
||
from utide import reconstruct, solve | ||
from utide._ut_constants import constit_index_dict, ut_constants | ||
|
||
|
||
ts = 735604 | ||
duration = 35 | ||
|
||
time = np.linspace(ts, ts + duration, 842) | ||
tref = (time[-1] + time[0]) / 2 | ||
|
||
const = ut_constants.const | ||
|
||
amps = [1.0, 0.5, 0.6, 0.1] | ||
names = ["M2", "S2", "K1", "O1"] | ||
cpds = [24 * const.freq[constit_index_dict[name]] for name in names] | ||
sinusoids = [] | ||
for amp, cpd in zip(amps, cpds): | ||
arg = 2 * np.pi * (time - tref) * cpd | ||
sinusoids.append(amp * np.cos(arg)) | ||
tide = np.hstack(tuple(sinusoids)).sum(axis=0) | ||
|
||
np.random.seed(1234) | ||
noise = 1e-3 * np.random.randn(len(time)) | ||
|
||
time_series = tide + noise | ||
|
||
opts0 = { | ||
"constit": ["K1", "M2", "O1", "S2"], | ||
"order_constit": "frequency", | ||
"phase": "raw", | ||
"nodal": False, | ||
"trend": False, | ||
"method": "ols", | ||
"conf_int": "MC", | ||
"Rayleigh_min": 0.95, | ||
} | ||
|
||
|
||
@pytest.mark.parametrize("conf_int", ["none", "linear", "MC"]) | ||
def test_order(conf_int): | ||
|
||
orders = [None, "PE", "frequency", opts0["constit"]] | ||
if conf_int != "none": | ||
orders.append("SNR") | ||
elevs = [] | ||
ts_elevs = [] | ||
vels = [] | ||
ts_vels = [] | ||
for order in orders: | ||
opts = opts0.copy() | ||
opts["order_constit"] = order | ||
opts["conf_int"] = conf_int | ||
elevs.append(solve(time, time_series, lat=45, **opts)) | ||
vels.append(solve(time, time_series, time_series, lat=45, **opts)) | ||
ts_elevs.append(reconstruct(time, elevs[-1], min_SNR=0)) | ||
ts_vels.append(reconstruct(time, vels[-1], min_SNR=0)) | ||
|
||
# Are the reconstructions all the same? | ||
for i in range(1, len(elevs)): | ||
assert (ts_elevs[i].h == ts_elevs[0].h).all() | ||
assert (ts_vels[i].u == ts_vels[0].u).all() | ||
assert (ts_vels[i].v == ts_vels[0].v).all() | ||
|
||
# Is None equivalent to "PE"? (Just a spot check.) | ||
assert (elevs[0].name == elevs[1].name).all() | ||
assert (elevs[0].A == elevs[1].A).all() | ||
|
||
|
||
def test_invalid_snr(): | ||
opts = opts0.copy() | ||
opts["conf_int"] = "none" | ||
opts["order_constit"] = "SNR" | ||
with pytest.raises(ValueError): | ||
solve(time, time_series, lat=45, **opts) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,44 @@ | ||
import numpy as np | ||
|
||
|
||
def ut_diagn(coef, opt): | ||
|
||
if opt["RunTimeDisp"]: | ||
print("diagnostics ... ", end="") | ||
coef["diagn"] = {} | ||
def _PE(coef): | ||
""" | ||
Return the energy percentage for each constituent. | ||
""" | ||
if "Lsmaj" in coef: | ||
E = coef["Lsmaj"] ** 2 + coef["Lsmin"] ** 2 | ||
PE = (100 / np.sum(E)) * E | ||
else: | ||
PE = 100 * coef["A"] ** 2 / np.sum(coef["A"] ** 2) | ||
return PE | ||
|
||
if opt["twodim"]: | ||
PE = np.sum(coef["Lsmaj"] ** 2 + coef["Lsmin"] ** 2) | ||
PE = 100 * (coef["Lsmaj"] ** 2 + coef["Lsmin"] ** 2) / PE | ||
|
||
def _SNR(coef): | ||
""" | ||
Return the signal-to-noise ratio for each constituent. | ||
""" | ||
if "Lsmaj" in coef: | ||
SNR = (coef["Lsmaj"] ** 2 + coef["Lsmin"] ** 2) / ( | ||
(coef["Lsmaj_ci"] / 1.96) ** 2 + (coef["Lsmin_ci"] / 1.96) ** 2 | ||
) | ||
|
||
else: | ||
PE = 100 * coef["A"] ** 2 / np.sum(coef["A"] ** 2) | ||
SNR = (coef["A"] ** 2) / (coef["A_ci"] / 1.96) ** 2 | ||
return SNR | ||
|
||
|
||
def ut_diagn(coef): | ||
""" | ||
Add to coef the names, PE, and SNR, *always* sorted by energy. | ||
To be eliminated... | ||
""" | ||
coef["diagn"] = {} | ||
PE = _PE(coef) | ||
SNR = _SNR(coef) | ||
indPE = PE.argsort()[::-1] | ||
|
||
coef["diagn"]["name"] = coef["name"][indPE] | ||
coef["diagn"]["PE"] = PE[indPE] | ||
coef["diagn"]["SNR"] = SNR[indPE] | ||
|
||
return coef, indPE | ||
|
||
|
||
# [~,indPE] = sort(PE,'descend'); | ||
# coef.diagn.name = coef.name(indPE); | ||
# coef.diagn.PE = PE(indPE); | ||
# coef.diagn.SNR = SNR; % used in ut_diagntable; ordered by PE there | ||
# if opt.twodim | ||
# [coef.diagn,usnrc,vsnrc] = ut_diagntable(coef,cnstit,... | ||
# t,u,v,xmod,m,B,W,varMSM,Gall,Hall,elor,varcov_mCw,indPE); | ||
# else | ||
# [coef.diagn,usnrc,~] = ut_diagntable(coef,cnstit,... | ||
# t,u,[],xmod,m,B,W,varMSM,Gall,Hall,elor,varcov_mCw,indPE); | ||
# end | ||
# if opt.diagnplots | ||
# tmp = nan*ones(size(uin)); | ||
# tmp(uvgd) = usnrc; | ||
# usnrc = tmp; | ||
# tmp = nan*ones(size(uin)); | ||
# tmp(uvgd) = e; | ||
# e = tmp; | ||
# if opt.twodim | ||
# tmp = nan*ones(size(uin)); | ||
# tmp(uvgd) = vsnrc; | ||
# vsnrc = tmp; | ||
# ut_diagnfigs(coef,indPE,tin,uin,vin,usnrc,vsnrc,e); | ||
# else | ||
# ut_diagnfigs(coef,indPE,tin,uin,[],usnrc,[],e); | ||
# end | ||
# end | ||
# end | ||
return coef |