-
Notifications
You must be signed in to change notification settings - Fork 0
Phase 5: Body disc + body blob techniques #116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
d041455
Phase 5: Body disc + body blob techniques
rfrenchseti 33fdb83
Phase 5: integration seeding + spurious-gate + pytest cleanup
rfrenchseti 8486850
fix: BodyBlob covariance + at_edge, correlate self-ref, doc accuracy
rfrenchseti 34956a2
docs: mark Phase 5 complete and drop dead extfov fallback
rfrenchseti File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or 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,233 @@ | ||
| # Phase 5 — image library seed (operator instructions) | ||
|
|
||
| This file walks an operator through curating the 2–4 additional library | ||
| entries Phase 5 calls for. The two new techniques — | ||
| `BodyDiscCorrelateNav` and `BodyBlobNav` — both ship with end-to-end | ||
| unit tests against synthetic inputs, but the integration regression | ||
| suite needs new sidecars on real images that exercise their happy and | ||
| boundary paths. | ||
|
|
||
| The Phase 4 runbook (`PHASE4_LIBRARY_SEED.md`) covers the manual-nav | ||
| workflow, the `Save as Library Entry…` button, the `pds3://` URL | ||
| convention, and the `<image_id>` filename rule. **Read it first.** This | ||
| file only documents the Phase 5 scenario picks plus the | ||
| technique-specific gotchas for the two new features. | ||
|
|
||
| ## What's new in Phase 5 | ||
|
|
||
| - `BodyDiscCorrelateNav` consumes per-body `BODY_DISC` features (the | ||
| full-disc Lambert-shaded postage-stamp template). It is the right | ||
| technique for scenes where the body fits inside the FOV with a | ||
| well-lit, mostly visible disc — *not* the partial-overflow scenes the | ||
| Phase 4 limb runbook targeted. | ||
| - `BodyBlobNav` consumes `BODY_BLOB` features. The body extractor emits | ||
| `BODY_BLOB` instead of `LIMB_ARC` whenever | ||
| `limb_uncertainty_px > LIMB_ARC_MAX_UNCERTAINTY_PX` (default 3 px), | ||
| which fires on close-range irregular satellites and on under-resolved | ||
| bodies. So a Prometheus-at-approach scene goes through `BodyBlobNav`, | ||
| while Prometheus in a wide F-ring mosaic goes through `BodyLimbNav` — | ||
| same body, different per-image path. | ||
|
|
||
| ## Body extractor emission gate (recap) | ||
|
|
||
| The body NavModel decides per-image, per-body which feature(s) to emit: | ||
|
|
||
| ``` | ||
| if limb_uncertainty_px <= 3 px: # LIMB_ARC_MAX_UNCERTAINTY_PX | ||
| emit LIMB_ARC | ||
| if visible_lit_fraction >= 0.4 and overflow_fraction <= 0.3: | ||
| also emit BODY_DISC | ||
| elif predicted_diameter_px >= 8 px: # BODY_BLOB_MIN_DIAMETER_PX | ||
| emit BODY_BLOB | ||
| else: | ||
| emit nothing | ||
| ``` | ||
|
|
||
| The `BODY_DISC` companion gates ensure we only run NCC pyramids when the | ||
| body actually fills enough of the FOV for the correlation peak to be | ||
| sharp. A body that overflows by > 30 % falls back to LIMB_ARC alone. | ||
|
|
||
| ## Picking Phase 5 candidates | ||
|
|
||
| Aim for **2–4 sidecars**, choosing whichever subset of the four | ||
| scenarios below your holdings cover. Prioritise scenario **A** because | ||
| it exercises both Phase-5 techniques back-to-back (limb + disc on the | ||
| same body); scenario **C** is the cheap "blob-only" win on a small or | ||
| distant moon. Scenario **D** stretches the multi-body Z-buffer paint | ||
| path. | ||
|
|
||
| ### Scenario A — Body fills FOV with small overflow (`BodyDiscCorrelateNav` + `BodyLimbNav`) | ||
|
|
||
| A scene where one regular moon dominates the frame with `<= 30 %` | ||
| overflow and `>= 40 %` of the lit hemisphere visible. Both `BODY_DISC` | ||
| and `LIMB_ARC` get emitted; the ensemble combines them. | ||
|
|
||
| | Field | What to look for | | ||
| |---|---| | ||
| | Mission / camera | Cassini ISS, NAC | | ||
| | Body | Mimas, Enceladus, Tethys, Dione, Rhea, Iapetus | | ||
| | Body diameter | 800–1024 px (NAC frame is 1024 px) | | ||
| | Visible lit fraction | `>= 40 %` of the disc area | | ||
| | Overflow fraction | `<= 30 %` | | ||
| | Phase angle | < 60° (most of the disc is bright) | | ||
| | Other features | None preferred | | ||
|
|
||
| **Sidecar location**: | ||
| `tests/integration/image_library/images/body_full_fov/<IMAGE_ID>.yaml` | ||
|
|
||
| **Expected behavior**: | ||
| - `expected.status: ok` | ||
| - `expected.confidence_tier: high` | ||
| - `expected.primary_technique: BodyDiscCorrelateNav` (NCC against the | ||
| full disc usually wins on confidence; `BodyLimbNav` is the runner-up) | ||
| - `expected.techniques_must_run: [BodyDiscCorrelateNav, BodyLimbNav]` | ||
| - `expected.techniques_must_skip: [RingEdgeNav, StarFieldFromCatalogNav]` | ||
|
|
||
| ### Scenario B — Body partial overflow (`BodyLimbNav` only, no disc) | ||
|
|
||
| A scene where the body overflows the FOV by > 30 % but the limb is | ||
| sharp enough for `LIMB_ARC` to fire. The body extractor emits | ||
| `LIMB_ARC` only — the disc gate fails on overflow. This complements | ||
| the Phase 4 Tethys scene (`body_mostly_offscreen` was the | ||
| `BodyLimbNav`-LM-divergence test); pick a different body to broaden | ||
| the calibration sample. | ||
|
|
||
| | Field | What to look for | | ||
| |---|---| | ||
| | Mission / camera | Cassini ISS, NAC | | ||
| | Body | Different from the Phase 4 Tethys (Rhea / Dione / Mimas) | | ||
| | Body fraction in FOV | 50–80 % (overflow_fraction 0.2–0.5) | | ||
| | Limb visible | Long bright arc (`>= 60 px`) | | ||
| | Other features | None | | ||
|
|
||
| **Sidecar location**: | ||
| `tests/integration/image_library/images/body_partial_overflow/<IMAGE_ID>.yaml` | ||
|
|
||
| **Expected behavior**: | ||
| - `expected.status: ok` (or `failed` if the LM divergence pattern | ||
| re-fires on a heavily-cratered body — record honestly) | ||
| - `expected.primary_technique: BodyLimbNav` | ||
| - `expected.techniques_must_run: [BodyLimbNav]` | ||
| - `expected.techniques_must_skip: [BodyDiscCorrelateNav]` | ||
|
|
||
| ### Scenario C — Irregular body (`BodyBlobNav`) | ||
|
|
||
| A scene where the body's shape is too irregular for the ellipsoid | ||
| limb fit. The body extractor emits `BODY_BLOB` only. | ||
|
|
||
| > ⚠️ **Important — the gate is shape-uncertainty-based, not | ||
| > size-based.** The body extractor decides between LIMB_ARC and | ||
| > BODY_BLOB by computing | ||
| > `limb_uncertainty_px = ellipsoid_residual_km / km_per_px_at_limb`. | ||
| > Regular moons (Mimas, Tethys, Dione, Rhea, …) carry | ||
| > `ellipsoid_residual_km ≈ 1` so their limb uncertainty stays well | ||
| > below the 3 px threshold *at any reasonable resolution*, including | ||
| > when they show up at only 10–20 px diameter in the frame. On | ||
| > regular moons the extractor always emits LIMB_ARC; BodyBlobNav | ||
| > never fires. To exercise BodyBlobNav you must pick an | ||
| > **irregular** body whose `ellipsoid_residual_km` in the body-shape | ||
| > table is large enough that `1 km/px · ellipsoid_residual_km > 3 px` | ||
| > on the chosen image — i.e. Prometheus, Pandora, Atlas, Pan, | ||
| > Hyperion, or Phoebe at close range. | ||
|
|
||
| | Field | What to look for | | ||
| |---|---| | ||
| | Mission / camera | Cassini ISS, NAC | | ||
| | Body | Prometheus, Pandora, Atlas, Pan, Hyperion, Phoebe (highly_irregular shape class) | | ||
| | Body diameter in FOV | >= 8 px (so the BODY_BLOB diameter floor is satisfied) | | ||
| | Resolution | High enough that `limb_uncertainty_px > 3` for the chosen body — the more irregular the body, the higher km/px the gate accepts | | ||
| | Other bright sources | None inside the predicted bbox (otherwise the centroid is biased) | | ||
| | Background | Dark sky preferred | | ||
|
|
||
| **Sidecar location**: | ||
| `tests/integration/image_library/images/body_irregular/<IMAGE_ID>.yaml` | ||
| (use `body_irregular` — the `below_resolution_body` class is reserved | ||
| for the case where even the BODY_BLOB diameter floor is violated and | ||
| the extractor emits no body feature at all). | ||
|
|
||
| **Expected behavior**: | ||
| - `expected.status: ok` (or `failed` if calibration discovers the | ||
| centroid is too soft on the chosen frame; the confidence cap of 0.4 | ||
| may push the orchestrator below `min_confidence` — record honestly) | ||
| - `expected.confidence_tier: low` or `medium` (cap is 0.4 — never | ||
| `high`) | ||
| - `expected.primary_technique: BodyBlobNav` | ||
| - `expected.techniques_must_run: [BodyBlobNav]` | ||
| - `expected.techniques_must_skip: [BodyLimbNav, BodyDiscCorrelateNav]` | ||
|
|
||
| ### Scenario D — Multi-body Z-buffer paint (`BodyDiscCorrelateNav` joint fit) | ||
|
|
||
| Optional but high-value: a single Cassini frame with two visible | ||
| moons. The Z-buffer paint composes both per-body `BODY_DISC` templates | ||
| into one composite, and the joint NCC removes the swap-moon | ||
| ambiguity that solo correlation suffers from. The trickiest part is | ||
| finding a real Cassini frame with two non-trivially-sized moons in the | ||
| same FOV; mosaic frames around saturnian conjunctions are the natural | ||
| hunting ground. | ||
|
|
||
| | Field | What to look for | | ||
| |---|---| | ||
| | Mission / camera | Cassini ISS, NAC or WAC | | ||
| | Bodies | Two regular moons, both `>= 30 px` diameter, both inside FOV | | ||
| | Subject ranges | Different (so depth ordering is well-defined) | | ||
| | Other features | Saturn rings OK; star field OK | | ||
|
|
||
| **Sidecar location**: | ||
| `tests/integration/image_library/images/multi_body/<IMAGE_ID>.yaml` | ||
|
|
||
| **Expected behavior**: | ||
| - `expected.status: ok` | ||
| - `expected.primary_technique: BodyDiscCorrelateNav` (joint NCC) | ||
| - `expected.techniques_must_run: [BodyDiscCorrelateNav]` | ||
| - `expected.techniques_must_skip: []` (limb / blob may also fire — list | ||
| only the ones the orchestrator must NOT run) | ||
|
|
||
| ## Workflow per image | ||
|
|
||
| Same as the Phase 4 runbook (steps 1–7). The `Save as Library Entry…` | ||
| button writes a sidecar pre-filled with auto-derivable fields plus | ||
| `TODO_REPLACE_*` placeholders for the operator-curated entries. | ||
| Edit those, drop the file under the correct scene-class directory, and | ||
| run: | ||
|
|
||
| ```bash | ||
| pytest tests/integration/test_image_library.py -v | ||
| pytest tests/integration/test_autonomous_nav.py -v -k <IMAGE_ID> | ||
| ``` | ||
|
|
||
| Both must pass before you commit. | ||
|
|
||
| ## Confidence-formula calibration deferred | ||
|
|
||
| Phase 5 ships placeholder coefficients on both new techniques' confidence | ||
| specs. Phase 10 (image-library expansion + confidence calibration) is | ||
| when those alphas get retuned against the full ~50-image library. Until | ||
| then, expect the new sidecars to need conservative | ||
| `expected.confidence_tier` values: | ||
|
|
||
| - `BodyDiscCorrelateNav`: `low` to `medium` even on textbook-clean | ||
| scenes. | ||
| - `BodyBlobNav`: `low` (the 0.4 hard cap is permanent — even Phase 10 | ||
| calibration cannot push past it). | ||
|
|
||
| Record the actual orchestrator-reported tier in your sidecar's | ||
| `expected.confidence_tier` and let the regression test pin today's | ||
| behavior. When Phase 10 retunes the coefficients the sidecars will | ||
| need a corresponding `expected.confidence_tier` bump; that's a | ||
| bookkeeping pass, not a re-curation. | ||
|
|
||
| ## After the seed lands | ||
|
|
||
| - The new sidecars enter the regression suite the moment they are | ||
| committed; CI runs them on every PR via the `integration` mark | ||
| (gated on `PDS3_HOLDINGS_DIR` etc.). | ||
| - For each `expected.status: ok` sidecar, the operator may also seed a | ||
| baseline JSON under `tests/integration/baselines/<IMAGE_ID>.json` so | ||
| any orchestrator drift trips the byte-level regression test. Use | ||
| `python -c "from tests.integration.baseline import seed_baseline; …"` | ||
| or the helper Phase 4 documented. | ||
| - Phase 5 follow-ups uncovered during integration runs (e.g. a | ||
| `BodyDiscCorrelateNav` consistency value that calibration will need | ||
| to retune) belong in `AUTONAV_PLAN.md` under the new | ||
| "Phase 6 / Phase 10 follow-ups uncovered by Phase 5 integration" | ||
| subsection. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.