Skip to content

Reusable figure selections for run-to-run comparison (#121)#123

Merged
bpurinton merged 4 commits into
mainfrom
reuse-figure-selections-121
Jun 12, 2026
Merged

Reusable figure selections for run-to-run comparison (#121)#123
bpurinton merged 4 commits into
mainfrom
reuse-figure-selections-121

Conversation

@bpurinton

Copy link
Copy Markdown
Contributor

Summary

Closes #121.

When re-processing the same scene with different ASP parameters (the workflow in stereopipeline-quickstart and across our own mapproj-vs-no-mapproj example notebooks), the diagnostic figures silently changed what they showed between runs — making before/after comparison impossible:

  • a fresh ICESat-2 request returned a slightly different point set,
  • the "best" profile track (_select_best_track) flipped,
  • the best/worst agreement segments (_find_best_worst_segments) moved,
  • the detailed-hillshade clip boxes were re-selected from the re-processed intersection-error raster.

All of this selection logic is already deterministic given identical inputs — the non-determinism enters only through the re-fetched ICESat data and the re-processed DEM. So the fix is persist + replay, not seeding.

What changed

  • asp_plot/selections.py (new): FigureSelections dataclass + YAML read/write + clip-box ↔ pixel-window helpers. Imports nothing from report.py/fpdf, so it's safe from notebooks. bbox_to_pixel_offset rounds to nearest (not floor) so a replayed clip doesn't drift a pixel from floating-point error.
  • CLI asp_plot: always writes <report_stem>_figure_selections.yml next to the report; new --reuse_selections PATH flag replays a prior run's ICESat-2 points, profile track, best/worst segments, and hillshade clips. A single run now also resolves the best track once and shares it across the profile + segment figures.
  • StereoPlotter.plot_detailed_hillshade: new clip_windows= kwarg (DEM-CRS bboxes); records the drawn boxes on self.detailed_hillshade_clips. Out-of-bounds boxes warn and fall back to automatic selection.
  • Altimetry: load_atl06sr_from_parquet() reuses the exact prior points; plot_atl06sr_dem_profile/plot_best_worst_segments accept pinned rgt/cycle/spot + segments=; get_altimetry_selections() reports the choices. _find_best_worst_segments gains a segment_override.

Per the design discussion, this is one umbrella flag (not granular toggles), reuses the parquet points for exact reproduction, stores clips as projected coordinates, and resolves the intra-run best-track inconsistency. All new kwargs default to auto, so existing behavior is unchanged.

Testing

  • New tests/test_selections.py (12 tests): YAML round-trip, bbox↔pixel helpers, hillshade clip replay + out-of-bounds fallback, segment-override (+ bad-override fallback), parquet reuse, and get_altimetry_selections bundling. tests/test_imports.py updated.
  • Validated end-to-end on the Mars MOC example (planetary, no internet): run A → run B with --reuse_selections reproduces the detailed-hillshade clips exactly (this is what surfaced and fixed the floor-vs-round off-by-one).
  • Pre-existing test_altimetry failures in my local env are an unrelated broken PROJ database (DATABASE.LAYOUT.VERSION.MINOR = 5), identical on main; new tests avoid that path.

Version bumped to 1.16.0.

Notes for reviewers

  • Docs: added a "Comparing re-processing runs" section to docs/cli/asp_plot.md.
  • The schema is human-readable so a user can hand-edit it to force a particular track or clip.

@bpurinton bpurinton force-pushed the reuse-figure-selections-121 branch 2 times, most recently from df2b438 to f982138 Compare June 11, 2026 21:12
When re-processing the same scene with different ASP parameters, the
diagnostic figures silently changed what they showed between runs: a fresh
ICESat-2 request returned a slightly different point set, the best profile
track flipped, the best/worst agreement segments moved, and the detailed-
hillshade clip boxes were re-selected from the re-processed intersection-
error raster. That made before/after comparison impossible.

The asp_plot CLI now writes a <report_stem>_figure_selections.yml sidecar
recording every non-deterministic selection, and a new --reuse_selections
flag replays a prior run's choices so figures are directly comparable.

- New asp_plot/selections.py (FigureSelections dataclass + YAML read/write +
  clip-box <-> pixel-window helpers; no report/fpdf imports, notebook-safe).
  bbox_to_pixel_offset rounds to nearest (not floor) so replayed clips don't
  drift a pixel from floating-point error.
- StereoPlotter.plot_detailed_hillshade gains clip_windows= and records the
  drawn boxes on self.detailed_hillshade_clips (DEM-CRS bboxes; out-of-bounds
  boxes warn and fall back to auto).
- Altimetry: load_atl06sr_from_parquet reuses the exact prior points; profile
  track (rgt/cycle/spot) and best/worst segments (segments=) are pinnable
  through the plot methods; get_altimetry_selections() reports the choices.
  A single run resolves the best track once and shares it across the profile
  and segment figures.

Bumps version to 1.16.0.
@bpurinton bpurinton force-pushed the reuse-figure-selections-121 branch 2 times, most recently from ad62a1a to 6a11370 Compare June 11, 2026 21:43
…e range

Two fixes from comparing ASTER non-mapproj (run A) vs mapproj reuse (run B):

- Best/worst agreement segments were pinned by km-from-track-start, so when
  3-sigma outlier filtering against a different DEM dropped a different first
  point, the track start shifted and the 'same' segment landed on different
  ground. Pin by absolute along-track distance (x_atc) instead, which is a
  stable reference; km extents are kept for plot axes/readability, and legacy
  km-only manifests still work via fallback.
- The reuse path (load_atl06sr_from_parquet) didn't set self._t0/_t1, so plot
  titles lost their '<t0> to <t1>' date-range line. Restore the time range from
  the parquet's stored sliderule_parameters.

Adds tests: time-range restore from parquet, and segment selection robustness
to a shifted track start.
@bpurinton bpurinton force-pushed the reuse-figure-selections-121 branch from 6a11370 to 4dd7633 Compare June 11, 2026 21:59
It was emitting at the bottom because it was the last dataclass field (we dump
with sort_keys=False). Declare it first so it serializes at the top, where
schema/version metadata is expected.
Add an annotated example of a *_figure_selections.yml to the --reuse_selections
docs section so users can see the schema. Gitignore reports/*_figure_selections.yml
because the generated sidecars hardcode absolute local paths (dem_filename,
parquet_cache) and are regeneration byproducts.
@bpurinton bpurinton merged commit 509769c into main Jun 12, 2026
1 check passed
@bpurinton bpurinton deleted the reuse-figure-selections-121 branch June 12, 2026 00:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a flag to re-use icesat tracks and hillshade detail clip areas between runs

1 participant