diff --git a/research/duetsch_re100_kc5/analyze.py b/research/duetsch_re100_kc5/analyze.py index 0061fbc..f089769 100644 --- a/research/duetsch_re100_kc5/analyze.py +++ b/research/duetsch_re100_kc5/analyze.py @@ -97,6 +97,8 @@ def hf_component(case, ks): mean CME waveform over cycles ks minus its two-basis Morison reconstruction, split at 20/T; cycle differencing does not remove it.""" T = case["T"] + if not ks: + return dict(label="unqualified phase-locked HF force component, not checked", cycles=[]) mean = np.mean([coarse_wave(case, k) for k in ks], axis=0) c_d, c_i = cycle_morison(case, ks) q = T // 4 @@ -125,13 +127,13 @@ def main(argv): if "--reference" in argv: i = argv.index("--reference") ref_path, argv = argv[i + 1], argv[:i] + argv[i + 2:] - horizon = p.LAST_SCORED # default cap: bit-for-bit the original scoring - if "--horizon" in argv: + horizon, explicit = p.LAST_SCORED, "--horizon" in argv # default: original scoring + if explicit: i = argv.index("--horizon") horizon, argv = int(argv[i + 1]), argv[:i] + argv[i + 2:] paths = argv if ref_path is None or ref_path in argv else argv + [ref_path] cases = [load(path) for path in paths] - for c in cases: # every scored cycle must be complete; never pad or shift + for c in cases if explicit else (): # complete cycles 1..N; never pad or shift if c["cycles"] < horizon or len(c["force"]) < round((0.25 + horizon) * c["T"]): raise SystemExit(f"{c['path']}: run does not contain complete cycles 1..{horizon}") ledgers = [ledger(c, horizon) for c in cases] @@ -147,7 +149,8 @@ def main(argv): entry.update(duration_T=case["steps"] / case["T"], K_case=k_case, pairs=pairs, coverage={k: coverage(case, k) for k in sorted(cycle_slices(case)) if k > p.DISCARD}, no_donor=float(case["diag"][:, 13].sum()), eq_only=float(case["diag"][:, 12].sum()), - hf_component=hf_component(case, window or tuple(range(horizon - 2, horizon + 1)))) + hf_component=hf_component(case, window or tuple( + [k for k in sorted(cycle_slices(case)) if p.DISCARD < k <= horizon][-3:]))) if window: # residual drift inside the scored window (pairs K..K+2) entry["window_drift"] = {key: max(pairs[k][key] for k in window) for key in ("wave", "profile", "morison")}