# OID Analysis Pipeline

Observable-Inferred Decomposition (Schlegel et al. 2012) applied to correction fields of DRL-controlled fluidic pinball flows. Identifies which flow structures best predict forces and downstream sensor signatures, across 5 control tasks: steady cloak, Karman cloak, illusion at 0.75L/1.0L/1.5L target diameters.

## Pipeline Overview

```
Raw fields (GPU, pycuda_3_10)                     Analysis (CPU, sr_env)
═══════════════════════════════                   ════════════════════════

scripts/collect_*.py                              analysis/phase*.py
       │                                                  │
       ├── empty_channel ─── q_in ─────────┐              │
       ├── pinball_baseline ─ q_blk ───────┤              │
       └── controlled ─────── q_ctl ───────┤              │
                                           ▼              ▼
                              ┌─────────────────────────────┐
                              │ Phase 1: Δq_ctl = q_ctl−q_blk│
                              │   → correction-field POD    │
                              │   → rank sensitivity (6-16) │
                              └─────────────┬───────────────┘
                                            ▼
                              ┌─────────────────────────────┐
                              │ Phase 2: observable Y build  │
                              │   force_total, sensor_error, │
                              │   sensor_error_delayed       │
                              └─────────────┬───────────────┘
                                            ▼
                     ┌──────────────────────┴──────────────────────┐
                     ▼                                              ▼
        ┌──────────────────────┐                    ┌──────────────────────┐
        │ Phase 3: Force-OID   │                    │ Phase 4: Signature-OID│
        │ Y = force_total      │                    │ Y = delayed sensor err│
        │ SVD(C_AY) → U_f      │                    │ SVD(C_AY) → U_s      │
        └──────────┬───────────┘                    └──────────┬───────────┘
                   │                                          │
                   └──────────────┬───────────────────────────┘
                                  ▼
                    ┌──────────────────────────┐
                    │ Phase 5: Steady OID       │
                    │ (suppression / mean-wake) │
                    └──────────────┬───────────┘
                                   ▼
                    ┌──────────────────────────┐
                    │ Phase 6: POD vs OID vs PCD│
                    │   70/30 R² comparison    │
                    └──────────────┬───────────┘
                                   ▼
                    ┌──────────────────────────┐
                    │ Phase 7: White-box chain  │
                    │ obs→act / OID→act / ...  │
                    └──────────────────────────┘
```

## Scene Table

| Scene Key | Inflow | Controlled | Dist Cyl? | Sensors | Pinball X | SI | S_DIM |
|-----------|--------|-----------|:---:|--------|-----------|:---:|:---:|
| steady_cloak | Parabolic | Open-loop const ±5.1U0 | No | x=40 | 30/31.3 | 800 | 12 |
| karman_re100 | Parabolic + vor-tex street | PPO d1a3o12_re100 | Yes | x=40 | 30/31.3 | 800 | 12 |
| illusion_0.75L | Parabolic | PPO d1a3o14_075L_2U_400S | No | x=30 | 19/20.3 | 400 | 14 |
| illusion_1.0L | Parabolic | PPO d1a3o14_1L_2U_600S | No | x=30 | 19/20.3 | 600 | 14 |
| illusion_1.5L | Parabolic | PPO d1a3o14_15L_2U | No | x=30 | 19/20.3 | 800 | 14 |

Action biases: cloak [0,−4,4], illusion [0,−2,2]. Action scale: 8 for all.

## Quick Commands

```bash
# Full collection (GPU, ~1-2 hours per scene group)
conda run -n pycuda_3_10 python src/OID_analysis/scripts/collect_all_data.py

# Full analysis for one scene (CPU, ~5 min)
PYTHONPATH="src:$PYTHONPATH" conda run -n sr_env python3 \
  src/OID_analysis/analysis/run_full_analysis.py --scene karman_re100

# Robustness + figures
PYTHONPATH="src:$PYTHONPATH" conda run -n sr_env python3 \
  src/OID_analysis/analysis/robustness_analysis.py
PYTHONPATH="src:$PYTHONPATH" conda run -n sr_env python3 \
  src/OID_analysis/analysis/make_figures.py
```

## Key Conventions

| Convention | Rule |
|-----------|------|
| Re definition | Code Re uses 2D reference (=40). Physical Re_D = Re_code/2. Default: Re_code=100 → Re_D=50. |
| OID object | Always `Δq_ctl = q_ctl − q_blk`, NOT raw `q_ctl`. |
| Field storage | Full 1280×512 resolution. ROI mask applied ONLY at analysis stage (POD). |
| force-OID vs sig-OID | Reported separately. Their divergence is a mechanism result, not a failure. |
| Illusion q_blk | Uses separate geometry (pinball_x=19/20.3, sensor_x=30), NOT cloak q_blk. |
| Norm | Data-driven (force_norm_fact = 6·max|forces|, sens_norm = 5·max|sensor−mean|). Model-specific. |
| GPU | Karman on device 1, steady/illusion on device 3. Fresh context per scene. |
| Environment split | `pycuda_3_10` for GPU collection, `sr_env` for CPU analysis. |

## Where Results Live

```
data/derived/
├── pod/{scene}/           Phase 1: POD modes + coefficients
├── observables/{scene}/   Phase 2: Y matrices
├── oid/force/{scene}/     Phase 3: force-OID (U, S, z, modes)
├── oid/signature/{scene}/ Phase 4: sig-OID (delayed + current)
├── oid/pcd/{scene}/       Phase 4b: sig-PCD (whitened)
├── comparison/{scene}.json Phase 6: POD-vs-OID R² tables
├── whitebox/{scene}.json  Phase 7: action prediction R²
├── robustness/            Rank/tau_c/window sensitivity
├── master/master_table.json  Cross-scene canonical values
└── figures/               All 7 figures (PNG)
```

## Adding a New Scene

1. Register in `configs.py`: add scene dict with physics, geometry, control params
2. Collect fields: write GPU script (or use generic `collect_controlled.py` for PPO)
3. Run pipeline: `run_full_analysis.py --scene <new_scene> --force`
4. Update `master_table.json` with new overlap/R² values
5. Regenerate figures: `make_figures.py`

## Companion Documents

| File | Role |
|------|------|
| `OID_knowledge.md` | Hard rules, confirmed facts, full results table, bug history |
| `OID_notes.md` | Task tracking, open items, handover notes |
| `Final_Conclusions.md` | Six key questions answered |
| `README.md` | Entry point — scope, file map, pitfalls |
| `papers/Sch12.md` | Schlegel et al. (2012) — OID original paper |
| `papers/Li22b.md` | Li et al. (2022) — pinball state estimation paper |
| `docs/sch12_code_mapping.md` | Sch12 formula → code traceability |
| `docs/OID_analysis_results.md` | External report — methods, 7 figures, all results |
