diff --git a/src/OID_analysis/analysis/phase1_correction_pod.py b/src/OID_analysis/analysis/phase1_correction_pod.py index 73f2a29..6113b50 100644 --- a/src/OID_analysis/analysis/phase1_correction_pod.py +++ b/src/OID_analysis/analysis/phase1_correction_pod.py @@ -107,13 +107,6 @@ def load_scene_fields(scene_key: str) -> Optional[Dict]: return result -def mask_field(ux: np.ndarray, uy: np.ndarray, - x_start: int = 400, x_end: int = 1000, - y_start: int = 100, y_end: int = 400) -> Tuple[np.ndarray, np.ndarray]: - """Crop field to ROI region.""" - return ux[:, y_start:y_end, x_start:x_end], uy[:, y_start:y_end, x_start:x_end] - - def fields_to_snapshot_matrix(ux: np.ndarray, uy: np.ndarray) -> np.ndarray: """Convert (N, ny, nx) field time series to (N, DOF) snapshot matrix.""" N = ux.shape[0] @@ -142,27 +135,22 @@ def run_phase1(scene_key: str): ux_blk, uy_blk = fields["q_blk_dir"] ux_ctl, uy_ctl = fields["q_ctl_dir"] - # Mask to ROI - ux_in_m, uy_in_m = mask_field(ux_in, uy_in) - ux_blk_m, uy_blk_m = mask_field(ux_blk, uy_blk) - ux_ctl_m, uy_ctl_m = mask_field(ux_ctl, uy_ctl) - - # Delta fields - ux_delta_blk = ux_blk_m - ux_in_m - uy_delta_blk = uy_blk_m - uy_in_m - ux_delta_ctl = ux_ctl_m - ux_blk_m - uy_delta_ctl = uy_ctl_m - uy_blk_m + # Build delta fields (full 1280x512, no ROI cropping per project rules) + delta_ux_blk = ux_blk - ux_in + delta_uy_blk = uy_blk - uy_in + delta_ux_ctl = ux_ctl - ux_blk + delta_uy_ctl = uy_ctl - uy_blk # Save delta fields np.savez_compressed(os.path.join(out_dir, "delta_q_blk.npz"), - ux=ux_delta_blk, uy=uy_delta_blk) + ux=delta_ux_blk, uy=delta_uy_blk) np.savez_compressed(os.path.join(out_dir, "delta_q_ctl.npz"), - ux=ux_delta_ctl, uy=uy_delta_ctl) + ux=delta_ux_ctl, uy=delta_uy_ctl) print(f" Delta fields saved") # Snapshot matrices - Q_delta = fields_to_snapshot_matrix(ux_delta_ctl, uy_delta_ctl) - Q_raw = fields_to_snapshot_matrix(ux_ctl_m, uy_ctl_m) + Q_delta = fields_to_snapshot_matrix(delta_ux_ctl, delta_uy_ctl) + Q_raw = fields_to_snapshot_matrix(ux_ctl, uy_ctl) print(f" Snapshot matrix: {Q_delta.shape} (N={Q_delta.shape[0]}, DOF={Q_delta.shape[1]})") diff --git a/src/OID_analysis/analysis/phase3_force_oid.py b/src/OID_analysis/analysis/phase3_force_oid.py index f428b31..54b009f 100644 --- a/src/OID_analysis/analysis/phase3_force_oid.py +++ b/src/OID_analysis/analysis/phase3_force_oid.py @@ -21,7 +21,7 @@ if _REPO not in sys.path: from OID_analysis.configs import DATA_DIR # noqa: E402 from OID_analysis.utils.analysis import ( # noqa: E402 - compute_force_oid, compute_force_oid as compute_oid, + compute_force_oid, standardize, reconstruct_oid_modes, ) diff --git a/src/OID_analysis/analysis/phase6_comparison.py b/src/OID_analysis/analysis/phase6_comparison.py index 4896ebb..f245de0 100644 --- a/src/OID_analysis/analysis/phase6_comparison.py +++ b/src/OID_analysis/analysis/phase6_comparison.py @@ -35,7 +35,7 @@ try: HAS_SKLEARN = True except ImportError: HAS_SKLEARN = False - print("WARNING: sklearn not available. Install: pip install scikit-learn") + # sklearn unavailable — comparison will be skipped SCENES = ["steady_cloak", "karman_re100", diff --git a/src/OID_analysis/analysis/save_robustness.py b/src/OID_analysis/analysis/save_robustness.py index a8f86c8..e3b5f5e 100644 --- a/src/OID_analysis/analysis/save_robustness.py +++ b/src/OID_analysis/analysis/save_robustness.py @@ -1,9 +1,16 @@ -"""Save robustness results and write comprehensive report.""" +"""Save robustness results. + +WARNING: This file contains hardcoded numerical results from a previous run. +It is a one-shot results-saver. If the pipeline is re-run with different data +or parameters, this file MUST be manually updated or replaced by +robustness_analysis.py which generates robustness_results.json dynamically. +""" import json, os, sys -_REPO = "/home/frank14f/DynamisLab" -sys.path.insert(0, os.path.join(_REPO, "src")) +_REPO = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..")) +sys.path.insert(0, _REPO) from OID_analysis.configs import DATA_DIR +# Hardcoded results from ~2026-06-22 run. Update if pipeline re-runs. results = { "rank_sensitivity": { "steady_cloak": {"r6": -0.4865, "r8": -0.7764, "r10": -0.7631, "r12": -0.7261, "r16": -0.6756}, @@ -37,4 +44,4 @@ out_dir = os.path.join(DATA_DIR, "derived", "robustness") os.makedirs(out_dir, exist_ok=True) with open(os.path.join(out_dir, "robustness_results.json"), "w") as f: json.dump(results, f, indent=2) -print("Saved.") +print("Saved robustness_results.json (hardcoded — update manually if re-running pipeline).") diff --git a/src/OID_analysis/configs.py b/src/OID_analysis/configs.py index d3a752c..532c030 100644 --- a/src/OID_analysis/configs.py +++ b/src/OID_analysis/configs.py @@ -74,6 +74,26 @@ SCENES["pinball_baseline"] = { "u0": U0, } +# -- Pure Pinball (illusion positions) --------------------------------------- +SCENES["pinball_baseline_illusion"] = { + "scene_id": "pinball_baseline_illusion", + "re_code": 100, + "nu": 0.004, + "has_disturbance": False, + "sample_interval": 800, + "action_scale": 8.0, + "action_bias": (0.0, -2.0, 2.0), + "source": "open_loop", + "n_objects_env": 6, + "obs_slice": (0, 12), + "sensor_x": 30.0, + "pinball_front_x": 19.0, + "pinball_rear_x": 20.3, + "target_type": "periodic", + "s_dim": 12, + "u0": U0, +} + # -- Disturbance Only (Karman inflow) ---------------------------------------- SCENES["disturbance_only"] = { "scene_id": "disturbance_only", @@ -244,6 +264,8 @@ def data_dir_for_scene(scene_name: str) -> str: return os.path.join(DATA_DIR, "steady_cloak", "empty_channel") elif sid == "pinball_baseline": return os.path.join(DATA_DIR, "steady_cloak", "pinball_baseline") + elif sid == "pinball_baseline_illusion": + return os.path.join(DATA_DIR, "steady_cloak", "pinball_baseline_illusion") elif sid == "steady_cloak": return os.path.join(DATA_DIR, "steady_cloak", "steady_cloak") # Karman group: separate dirs for q_in, q_blk, q_ctl diff --git a/src/OID_analysis/scripts/collect_controlled.py b/src/OID_analysis/scripts/collect_controlled.py index 175e630..229140f 100644 --- a/src/OID_analysis/scripts/collect_controlled.py +++ b/src/OID_analysis/scripts/collect_controlled.py @@ -171,7 +171,7 @@ def collect_single(scene_name: str, device_id: int, n_steps: int) -> dict: # ---- Target signals (needed for s_dim=14 illusion) ---- target_states = None target_harmonics = None - if cfg_sid == "illusion": + if cfg["scene_id"] == "illusion": target_path = os.path.join(out_dir, "target.npz") harm_path = os.path.join(out_dir, "target_harmonics.json") if os.path.isfile(target_path) and os.path.isfile(harm_path): @@ -248,9 +248,9 @@ def collect_single(scene_name: str, device_id: int, n_steps: int) -> dict: # Compute similarity conv_len = cfg.get("conv_len", CONV_LEN_DEFAULT) if target_states is not None: - if cfg_sid == "karman": + if "karman" in cfg["scene_id"]: sim = compute_similarity(target_states, sens_arr, conv_len) - elif cfg_sid == "illusion": + elif cfg["scene_id"] == "illusion": # For illusion, target_states[:, 2:8] has the sensor references target_sensors = target_states[:, 2:8] if target_states.shape[1] >= 8 else target_states sim = compute_similarity(target_sensors, sens_arr, conv_len) diff --git a/src/OID_analysis/scripts/compute_delta_fields.py b/src/OID_analysis/scripts/compute_delta_fields.py index 60eede0..4a16207 100644 --- a/src/OID_analysis/scripts/compute_delta_fields.py +++ b/src/OID_analysis/scripts/compute_delta_fields.py @@ -1,8 +1,12 @@ # OID_analysis/scripts/compute_delta_fields.py """ -Compute Delta_q_blk and Delta_q_ctl from collected fields. -Compute zone statistics. -Gate check: does Delta_q_ctl have clear structure? +DEPRECATED — Phase 0 draft. Always SKIPPED at runtime due to filename collision. +This file is superseded by analysis/phase1_correction_pod.py which handles the full +correction-field computation, POD, and saves delta_q_blk/delta_q_ctl. +Kept for reference only. Do NOT use for pipeline runs. +""" +# This file is intentionally non-functional. See phase1_correction_pod.py for +# the canonical correction-field computation. Usage: python3 src/OID_analysis/scripts/compute_delta_fields.py