asp-plot 2.2.0__tar.gz → 3.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {asp_plot-2.2.0 → asp_plot-3.1.0}/AGENTS.md +2 -2
- {asp_plot-2.2.0 → asp_plot-3.1.0}/ARCHITECTURE.md +27 -27
- {asp_plot-2.2.0 → asp_plot-3.1.0}/CHANGELOG.md +25 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/PKG-INFO +2 -2
- {asp_plot-2.2.0 → asp_plot-3.1.0}/README.md +1 -1
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/alignment.py +53 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/altimetry.py +8 -8
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/bundle_adjust.py +14 -5
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/cli/asp_report.py +43 -48
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/cli/csm_camera_plot.py +31 -31
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/cli/gallery.py +9 -8
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/cli/request_planetary_altimetry.py +4 -4
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/cli/stereo_geom.py +9 -9
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/processing_parameters.py +15 -2
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/report.py +125 -33
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/report_captions.py +37 -20
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/report_pipeline.py +74 -36
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/stereo.py +114 -22
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/utils.py +36 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/pyproject.toml +1 -1
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.flake8 +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.github/ISSUE_TEMPLATE/problem-report.yml +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.github/workflows/claude-code-review.yml +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.github/workflows/claude.yml +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.github/workflows/release.yml +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.github/workflows/run-tests.yml +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.gitignore +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.pre-commit-config.yaml +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/.readthedocs.yaml +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/CLAUDE.md +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/LICENSE +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/__init__.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/altimetry_plots.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/altimetry_source.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/asp_log.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/bodies.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/cli/__init__.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/csm_analysis.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/csm_camera.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/csm_io.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/gallery.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/icesat2_source.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/mapproject.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/planetary_source.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/scenes.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/selections.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/sensors/__init__.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/sensors/aster.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/sensors/base.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/sensors/dimap.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/sensors/dimap_v1.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/sensors/rpc.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/sensors/worldview.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/stereo_geometry.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/asp_plot/stereopair_metadata_parser.py +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/conda-forge-recipe/meta.yaml +0 -0
- {asp_plot-2.2.0 → asp_plot-3.1.0}/environment.yml +0 -0
|
@@ -54,7 +54,7 @@ sphinx-autobuild docs docs/_build/html --open-browser # or sphinx-build for a
|
|
|
54
54
|
## External Data Sources
|
|
55
55
|
|
|
56
56
|
- **ICESat-2 ATL06-SR** (Earth): requested through the SlideRule API; results cached as parquet next to the report.
|
|
57
|
-
- **LOLA (Moon) / MOLA (Mars)**: async queries to the ODE GDS REST API via the `request_planetary_altimetry` CLI — the user gets a download link by email, then passes the CSV to `asp_report --
|
|
57
|
+
- **LOLA (Moon) / MOLA (Mars)**: async queries to the ODE GDS REST API via the `request_planetary_altimetry` CLI — the user gets a download link by email, then passes the CSV to `asp_report --altimetry-csv`. Coordinates are east-positive 0–360 longitude, planetocentric latitude.
|
|
58
58
|
|
|
59
59
|
## Testing
|
|
60
60
|
|
|
@@ -76,7 +76,7 @@ The rest is automated: `release.yml` detects the version bump, creates a GitHub
|
|
|
76
76
|
ASP output files follow specific naming patterns (find them with the `glob_file()` utility):
|
|
77
77
|
- DEMs: `*-DEM.tif` or `*_dem.tif`
|
|
78
78
|
- Disparity: `*-F.tif`
|
|
79
|
-
- Match files: `*.match`
|
|
79
|
+
- Match files: `*.match` (binary) or `*__*.txt` (plain text, from ASP >= 3.7.0 `--matches-as-txt`; binary preferred when both exist)
|
|
80
80
|
- Bundle adjust residuals: `*-initial_residuals_pointmap.csv`, `*-final_residuals_pointmap.csv`
|
|
81
81
|
- Log files: `*log-bundle_adjust*.txt`, `*log-stereo*.txt`, `*log-point2dem*.txt`
|
|
82
82
|
|
|
@@ -42,24 +42,24 @@ The package is organized by functionality, with each module focused on a specifi
|
|
|
42
42
|
- `pixel_window_to_bbox()` / `bbox_to_pixel_offset()`: convert a detailed-hillshade clip between a DEM-CRS map bbox and a top-left pixel offset. `bbox_to_pixel_offset` uses `rowcol(..., op=round)` (round-to-nearest, **not** floor) so a replayed clip doesn't drift by a pixel from floating-point error
|
|
43
43
|
- `reproject_bbox(bbox, src_crs, dst_crs)`: reprojects a clip bbox between CRSs (via `rasterio.warp.transform_bounds`) so clip reuse works across stereo variants in different projections (e.g. MOC non-mapproj Stereographic vs mapproj Sinusoidal). `plot_detailed_hillshade(clip_windows_crs=...)` passes the manifest's `dem_crs`; reprojection is a no-op when CRSs match
|
|
44
44
|
- Deliberately imports nothing from `report.py` / `fpdf`, so it is safe to use from notebooks
|
|
45
|
-
- The `asp_report` CLI always writes `<report_stem>_figure_selections.yml` next to the report; `--
|
|
45
|
+
- The `asp_report` CLI always writes `<report_stem>_figure_selections.yml` next to the report; `--reuse-selections PATH` replays a prior run's choices
|
|
46
46
|
|
|
47
47
|
**`report.py`** - PDF report generation using fpdf2
|
|
48
48
|
- `ReportSection`: Dataclass representing a report figure (title, image path, caption)
|
|
49
|
-
- `AlignmentReportPage`: Dataclass for the pc_align +
|
|
49
|
+
- `AlignmentReportPage`: Dataclass for the pc_align + altimetry alignment workflow (title, parameters dict, flat stats dict from `pc_align_report()`, description paragraph, status message, optional figure + caption). Rendered alongside `ReportSection` by `compile_report()`. Body text blocks are left-aligned (not justified) to avoid word-spacing gaps on long lines. `_add_alignment_stats_tables()` splits the flat stats dict (`_split_alignment_stats()`) into two side-by-side tables: "Error Statistics (m)" with one row per `<stat>_beg`/`<stat>_end` pair and Before / After / Change columns (row labels via `_ALIGNMENT_STAT_LABELS`, Change from `_fmt_pct_change()`), and "Translation (m)" with one row per remaining key (`north_shift` → `North`, … `translation_magnitude` → `Magnitude |T|` via `_ALIGNMENT_TRANSLATION_LABELS`). Either table takes the full width when the other is empty.
|
|
50
50
|
- `ReportMetadata`: Dataclass for DEM metadata displayed on the title page (dimensions, GSD, CRS, nodata %, elevation range, DEM filename, reference DEM, acquisition dates). The "Acquisition Date(s)" row is added to the summary table only when `acquisition_dates` is non-empty.
|
|
51
51
|
- `ASPReportPDF`: FPDF subclass with custom header/footer and page numbers
|
|
52
52
|
- `compile_report()`: Assembles title page, Processing Parameters (page 2), figure sections with captions, and any trailing alignment pages into a PDF. Accepts optional `report_command` string to record the CLI invocation. Figures are automatically scaled to fit page dimensions, preventing overflow/cutoff. `sections` is a mixed list of `ReportSection | AlignmentReportPage`; dispatch is by `isinstance` check.
|
|
53
53
|
- `_add_processing_parameters_page()`: helper that renders the runtime summary table plus the bundle_adjust / stereo / point2dem / report commands on page 2 (moved from the trailing page as of v1.13.0). Also renders the reconstructed `mapproject` command(s) (from the optional `mapproject` list key; see `mapproject.py`) with a "reconstructed from output metadata" note.
|
|
54
54
|
- `_fmt_sig()`: formats a number compactly — 2 decimals for |x| < 10, 1 decimal for 10 ≤ |x| < 100, 0 decimals above, "n/a" for non-finite. Used for alignment stats.
|
|
55
55
|
- Title page displays: processing date, ASP version (from logs), asp_plot version (from package metadata)
|
|
56
|
-
- Page order: title + DEM summary → Processing Parameters → diagnostic figures → (if
|
|
56
|
+
- Page order: title + DEM summary → Processing Parameters → diagnostic figures → (if the `pc_align` step ran) alignment report page + aligned-DEM figures.
|
|
57
57
|
- `report.py` is fed declaratively by `report_pipeline.py`; it was **not** rewritten in #128.
|
|
58
58
|
|
|
59
59
|
**`report_pipeline.py`** - Declarative report pipeline behind the `asp_report` CLI (issue #128)
|
|
60
60
|
- `ReportConfig`: dataclass packing the ~18 CLI options into one Click-free object (field names/defaults mirror the options one-for-one, guarded by a test)
|
|
61
61
|
- `run_report(config)`: importable/callable from notebooks and tests with no Click context; returns the written PDF path
|
|
62
|
-
- A declarative section registry (`REPORT_SECTIONS`) of `ReportSpec`s replaces the old inline plot-and-append wall: each spec pairs an `enabled(ctx)` predicate with a `build(ctx)` function returning the sections to append. `--
|
|
62
|
+
- A declarative section registry (`REPORT_SECTIONS`) of `ReportSpec`s replaces the old inline plot-and-append wall: each spec pairs an `enabled(ctx)` predicate with a `build(ctx)` function returning the sections to append. `--no-geometry` / `--no-altimetry` / `--no-pc-align` gating are predicates; figure numbering comes from a per-run counter on the shared `ReportContext`, so section order and numbering are data, not source-line position. The alignment "Page B/C/D" follow-ups are one spec emitting several sections
|
|
63
63
|
- Section builders: `_build_input_scenes`, `_build_stereo_geometry`, `_build_match_points`, `_build_bundle_adjust`, `_build_disparity`, `_build_dem_results`, `_build_detailed_hillshade`, `_build_altimetry` (→ `_build_altimetry_earth` / `_build_altimetry_planetary`)
|
|
64
64
|
- `_numbered_sections()`: shared helper turning a plotter's saved-filename list into one `ReportSection` per figure (first gets the caption, continuations are titled "... (continued)") — used by the scenes/geometry/match/disparity builders, whose plotters save one figure per pair on multi-view runs (issue #160)
|
|
65
65
|
|
|
@@ -109,6 +109,7 @@ The package is organized by functionality, with each module focused on a specifi
|
|
|
109
109
|
- Detects map-projection status via `Raster.transform` check
|
|
110
110
|
- For non-mapprojected scenes: match points are overlaid on images using alignment transform matrices (`run-align-{L,R}.txt` loaded via `np.loadtxt`), and disparity plots use pixel-unit scalebar instead of GSD-based. Exception: when the match file is named for the aligned images themselves (`run-L__R.match`, older ASP raw-image runs that write `.exr` alignment matrices), the coordinates are already aligned — detected via `_ip_on_aligned_images()` (match stem's left name == L image stem) — and are only rescaled
|
|
111
111
|
- **Raw interest point overlay** (issue #8): `StereoFiles` also discovers the per-image `.vwip` files (named after the images the match file pairs — `<A>__<B>.match` ↔ `<A>.vwip`/`<prefix>-<B>.vwip` — derived from the match stem, with a `*-L.vwip`/`*-R.vwip` glob fallback when no match file exists; either side may be absent). `get_vwip_df()` parses the binary format (a uint64 count then the same interest point records as `.match`); `plot_match_points()` underlays them in blue beneath the red matches through the same per-side coordinate transform (layers denser than 10,000 points are thinned by seeded random sampling for display; titles report true counts), renders interest-points-only when the match file is missing, and falls back to the previous matches-only figure when the `.vwip` files are gone
|
|
112
|
+
- **Plain-text match files** (issue #147): ASP >= 3.7.0 writes `<A>__<B>.txt` (one `x1 y1 unc1 x2 y2 unc2` line per match) *instead of* `.match` when run with `--matches-as-txt`, so `StereoFiles._find_match_file()` globs both `*.match` and `*__*.txt` (the `__` anchor plus a first-row check — six numeric fields, `_opens_with_match_row()` — keeps logs and alignment matrices out even when the run prefix itself contains `__`), preferring binary when both coexist. `get_match_point_df()` detects the format from the bytes (`_is_text_match_file()`: the binary header's uint64 counts contain NULs, text never does — so a renamed file still parses) and routes text through `_read_text_match_file()` — read directly, uncertainties dropped, never via the `.csv` cache a binary conversion leaves behind — while the binary path keeps its CSV conversion. `.vwip` files stay binary-only: stereo never writes text ones (`ipfind --binary-to-txt` is a manual conversion)
|
|
112
113
|
- **Multi-view aware** (issue #160): `StereoFiles` resolves each `<prefix>-pairN/` subdirectory into a `PairStereoFiles` (field names mirror the top-level attributes so the per-figure helpers consume either, duck-typed); `plot_match_points()` / `plot_disparity()` render one figure per pair (`<stem>_pairN.png`) and return the saved filename list — `[fig_fn]` for a standard run — mirroring the `stereo_geom_plot()` N-scene contract
|
|
113
114
|
- Detects the imagery rights-holder via the `attribution` attribute (`detect_satellite_attribution`); adds the copyright overlay to optical imagery in `plot_match_points()` and `plot_detailed_hillshade()`
|
|
114
115
|
- `plot_detailed_hillshade()` auto-selects three subset clips from intersection-error variance (low/medium/high) via `_auto_hillshade_clip_offsets()`. Accepts `clip_windows` (DEM-CRS bboxes) + `clip_windows_crs` to pin/replay clips for run-to-run comparison (issue #121); records the boxes it drew on `self.detailed_hillshade_clips`. Out-of-bounds pinned boxes warn and fall back to auto.
|
|
@@ -180,7 +181,7 @@ The package is organized by functionality, with each module focused on a specifi
|
|
|
180
181
|
- `pc_align_dem_to_atl06sr()`: ICESat-2 path, csv-format `1:lon 2:lat 3:height_above_datum`
|
|
181
182
|
- `pc_align_dem_to_planetary_csv(planetary_csv, body, ...)`: MOLA/LOLA path. Uses csv-format `1:lon 2:lat 3:radius_m` and `--datum D_MARS`/`D_MOON` (per ASAP-Stereo's CTX cookbook). Default `max_displacement=500` m
|
|
182
183
|
- Both public methods keep their signatures/validation/errors and delegate to a shared `_run_pc_align(csv, csv_format, max_displacement, datum=...)` (#127); generated argv is byte-identical to before, with `--datum` emitted only on the planetary path
|
|
183
|
-
- `pc_align_report()`: Extracts begin/end percentiles
|
|
184
|
+
- `pc_align_report()`: Extracts begin/end percentiles, the ASP >= 3.7.0 Mean/StdDev/RMSE/Median/NMAD summary (keys absent for older logs), and the N-E-D translation from the pc_align log; the report page shows Median/NMAD/RMSE + translation when the log has them, else the percentiles (`report_pipeline._stats_row_from_result()`)
|
|
184
185
|
- `apply_dem_translation()`: Applies pc_align's Cartesian translation to the DEM (geotransform shift + scalar add to pixel values, no resampling). Picks the right body-centered geocentric source CRS via the module-level `_GEOCENTRIC_PROJ` dict — Earth uses EPSG:4978, Mars/Moon use PROJ strings (`+proj=geocent +R=...`) because PROJ refuses to convert across celestial bodies
|
|
185
186
|
- Used by `Altimetry` class for DEM-to-altimetry alignment on Earth, Mars, and Moon
|
|
186
187
|
|
|
@@ -218,28 +219,27 @@ All CLI tools are in `asp_plot/cli/` and use Click for argument parsing:
|
|
|
218
219
|
**`asp_report.py`** - Main CLI tool (`asp_report` command)
|
|
219
220
|
- Generates comprehensive PDF reports of ASP processing
|
|
220
221
|
- A **thin Click wrapper** (issue #128): parses the ~18 options into a `ReportConfig` and calls `report_pipeline.run_report(config)`. All orchestration lives in `report_pipeline.py` (see the module structure section); the CLI file itself is now just option definitions + the `ReportConfig` build
|
|
221
|
-
- Accepts
|
|
222
|
+
- Accepts a directory for stereo outputs and a directory or ASP-style prefix for bundle_adjust outputs; trailing slashes are tolerated (issue #60)
|
|
222
223
|
- Options for reference DEMs, ICESat-2 comparisons, basemaps
|
|
223
224
|
- Report section order: Input Scenes → Stereo Geometry → Match Points → Bundle Adjust panels (Log/Linear Residuals, Map-Projected Residuals, Geodiff) → Disparity → DEM Results → Detailed Hillshade → Altimetry panels. Disparity follows Bundle Adjust (not Hillshade) and DEM Results precedes Hillshade, so the title page → inputs → per-step diagnostics → final DEM products narrative reads top-down.
|
|
224
225
|
- Title-page `ReportMetadata` is populated here; `get_acquisition_dates()` is called with the main directory plus stereo/BA subdirs as `extra_dirs` so the Acquisition Date(s) row appears on both raw-input layouts (WV XMLs at top level) and layouts where XMLs live one level deep.
|
|
225
226
|
- `--directory`: Root ASP processing directory (default: `./`)
|
|
226
|
-
- `--
|
|
227
|
-
- `--
|
|
228
|
-
- `--
|
|
229
|
-
- `--
|
|
230
|
-
- `--
|
|
231
|
-
- `--
|
|
232
|
-
- `--
|
|
233
|
-
- `--
|
|
234
|
-
- `--
|
|
235
|
-
- `--
|
|
236
|
-
- `--
|
|
237
|
-
- `--
|
|
238
|
-
- `--
|
|
239
|
-
- `--
|
|
240
|
-
- `--
|
|
241
|
-
- `--
|
|
242
|
-
- `--report_title`: Custom report title (default: directory name)
|
|
227
|
+
- `--stereo-directory`: Stereo output subdirectory (default: `stereo`)
|
|
228
|
+
- `--bundle-adjust-prefix`: Optional BA output location — either a directory (`ba`) or an ASP-style output prefix (`ba/run`, as passed to stereo/mapproject); a prefix narrows file globs to that run's outputs
|
|
229
|
+
- `--dem-filename`: Custom DEM filename (default: auto-detect `*-DEM.tif`)
|
|
230
|
+
- `--dem-gsd`: Custom DEM ground sample distance
|
|
231
|
+
- `--map-crs`: Projection as `EPSG:XXXX` (default: auto-detect from DEM, fallback `EPSG:4326`)
|
|
232
|
+
- `--reference-dem`: Reference DEM path (auto-detected from logs if not supplied)
|
|
233
|
+
- `--no-basemap`: Skip the Esri WorldImagery basemaps added by default (which require internet)
|
|
234
|
+
- `--no-altimetry`: Skip the altimetry comparisons plotted by default. Auto-detects planetary body from DEM CRS: Earth → ICESat-2 (requires internet), Moon → LOLA, Mars → MOLA. For planetary DEMs, requires `--altimetry-csv`.
|
|
235
|
+
- `--altimetry-csv`: Path to a LOLA/MOLA CSV from the ODE GDS API. **Mars: must be the `*_pts_csv.csv` (not `*_topo_csv.csv`) — the loader requires the `PLANET_RAD` column to avoid the oblate-areoid offset.** Moon accepts either the `*_topo_simple_csv.csv` (results=u) or the `*_pts_csv.csv` (results=p). Obtained via the `request_planetary_altimetry` CLI tool.
|
|
236
|
+
- `--no-pc-align`: Skips the `pc_align` step; by default (when altimetry is on) the report runs `pc_align` against the reference altimetry (ICESat-2 for Earth, MOLA for Mars, LOLA for Moon) after the existing altimetry plots and appends an alignment report. **Earth success path**: adds four pages (alignment report page, pre/post landcover histogram, aligned profile, aligned best/worst segments). **Planetary success path**: adds three pages (alignment report page, pre/post mapview, pre/post histogram). `insufficient_points` and `no_improvement` outcomes emit a single alignment report page on either branch. Skipped automatically when `--no-altimetry` is set.
|
|
237
|
+
- `--no-geometry`: Skip the stereo geometry plots drawn by default (used for planetary missions)
|
|
238
|
+
- `--subset-km`: Hillshade subset size in km (default: 1.0)
|
|
239
|
+
- `--atl06sr-time-range`: Time range for ICESat-2 ATL06-SR requests. `"all"` (default) for full mission, `"auto"` for scene metadata ±1 year, `"START,END"` for a custom range, or a single date (buffered by ±1 year).
|
|
240
|
+
- `--reuse-selections`: Path to a `*_figure_selections.yml` from a prior run. Replays that run's ICESat-2 points (parquet), profile track, best/worst segments, and detailed-hillshade clips so re-processing runs (e.g. mapproj vs non-mapproj) are directly comparable (issue #121). Every run always writes `<report_stem>_figure_selections.yml` next to the report (the `regenerate_reports.sh` paired variants use this to reuse each other). Generated sidecars are gitignored (they hardcode absolute local paths); a sanitized example is in `docs/cli/asp_report.md`.
|
|
241
|
+
- `--report-filename`: PDF report filename or path. A bare filename saves in the stereo directory; a path (e.g. `reports/report.pdf`) is used as-is. Default is auto-generated as `asp_report_<report_title>_<UTC timestamp>.pdf`
|
|
242
|
+
- `--report-title`: Custom report title (default: directory name)
|
|
243
243
|
|
|
244
244
|
**`csm_camera_plot.py`** - CSM camera comparison tool (`csm_camera_plot` command)
|
|
245
245
|
- Wrapper for `csm_camera.py` functions
|
|
@@ -253,7 +253,7 @@ All CLI tools are in `asp_plot/cli/` and use Click for argument parsing:
|
|
|
253
253
|
- `--email`: Email for notification when query finishes (required)
|
|
254
254
|
- `--channels`: LOLA detector channels (Moon only, default `tffff` = channel 1 only)
|
|
255
255
|
- Saves request metadata as `altimetry_request_info.yml` alongside the DEM
|
|
256
|
-
- Workflow: submit query → receive email → download/unzip → pass `*_pts_csv.csv` (Mars) or `*_topo_simple_csv.csv`/`*_pts_csv.csv` (Moon) to `asp_report --
|
|
256
|
+
- Workflow: submit query → receive email → download/unzip → pass `*_pts_csv.csv` (Mars) or `*_topo_simple_csv.csv`/`*_pts_csv.csv` (Moon) to `asp_report --altimetry-csv`
|
|
257
257
|
|
|
258
258
|
**`stereo_geom.py`** - Stereo geometry visualization tool (`stereo_geom` command)
|
|
259
259
|
- Wrapper for `StereoGeometryPlotter`
|
|
@@ -265,7 +265,7 @@ All CLI tools are in `asp_plot/cli/` and use Click for argument parsing:
|
|
|
265
265
|
**`gallery.py`** - DEM gallery tool (`gallery` command)
|
|
266
266
|
- Wrapper for `GalleryPlotter`; lays out many DEMs as a grid sharing one color scale
|
|
267
267
|
- `--directory` + `--pattern` (supports recursive `**` for subdirectories) or an explicit list of `FILES` (files take precedence)
|
|
268
|
-
- `--
|
|
268
|
+
- `--no-hillshade`, `--cmap`, `--downsample`, `--max-filesize-mb`, `--title`, `--output-directory/--output-filename`
|
|
269
269
|
- Saves `<dirname>_gallery.png` into the input directory by default
|
|
270
270
|
|
|
271
271
|
## Documentation Website
|
|
@@ -307,7 +307,7 @@ docs/
|
|
|
307
307
|
- **`html_extra_path`** is used to serve `notebooks/figures/` at the correct relative path for notebook `<img src>` references.
|
|
308
308
|
- **`docs/` is excluded from sdist** in `pyproject.toml` so docs never ship in the PyPI/conda package.
|
|
309
309
|
- **Changelog** uses `{include} ../CHANGELOG.md` so there's one source of truth.
|
|
310
|
-
- **Selective notebook exclusion**: `.readthedocs.yaml`'s `pre_build` copies every `notebooks/**/*.ipynb` into `docs/examples/notebooks/`, but specific notebooks can be dropped from the build by listing them in `exclude_patterns` in `docs/conf.py` (e.g., `worldview_utqiagvik_stereo.ipynb`). Inter-notebook links in the WorldView examples use fully-qualified `https://asp-plot.readthedocs.io/en/latest/...` URLs so they resolve both on RTD and in raw notebook previews. Report-link convention: each notebook's "Full Report Generation" section ends with a `#### See the resulting [report](https://asp-plot.readthedocs.io/en/latest/_static/reports/<filename>.pdf).` line that links directly to the PDF served from `_static/reports/`. The `<filename>` must match what the cell's `!asp_report --
|
|
310
|
+
- **Selective notebook exclusion**: `.readthedocs.yaml`'s `pre_build` copies every `notebooks/**/*.ipynb` into `docs/examples/notebooks/`, but specific notebooks can be dropped from the build by listing them in `exclude_patterns` in `docs/conf.py` (e.g., `worldview_utqiagvik_stereo.ipynb`). Inter-notebook links in the WorldView examples use fully-qualified `https://asp-plot.readthedocs.io/en/latest/...` URLs so they resolve both on RTD and in raw notebook previews. Report-link convention: each notebook's "Full Report Generation" section ends with a `#### See the resulting [report](https://asp-plot.readthedocs.io/en/latest/_static/reports/<filename>.pdf).` line that links directly to the PDF served from `_static/reports/`. The `<filename>` must match what the cell's `!asp_report --report-filename` writes (so the URL on RTD actually resolves).
|
|
311
311
|
|
|
312
312
|
### Dependencies
|
|
313
313
|
|
|
@@ -337,7 +337,7 @@ Docs dependencies are in `pyproject.toml` under `[project.optional-dependencies]
|
|
|
337
337
|
|
|
338
338
|
**ODE GDS REST API**: Base URL `https://oderest.rsl.wustl.edu/livegds`. Queries are submitted via `gds_query_async()` in async mode. The `request_planetary_altimetry` CLI submits the query and the user downloads results via email link. Coordinates use east-positive 0-360 longitude and planetocentric latitude.
|
|
339
339
|
|
|
340
|
-
**Basemaps**: Uses `contextily` to fetch Esri WorldImagery tiles (requires internet). Can be disabled with `--
|
|
340
|
+
**Basemaps**: Uses `contextily` to fetch Esri WorldImagery tiles (requires internet). Can be disabled with `--no-basemap`. Automatically skipped for planetary (non-Earth) DEMs.
|
|
341
341
|
|
|
342
342
|
## Example Notebooks
|
|
343
343
|
|
|
@@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.1.0] - 2026-08-27
|
|
9
|
+
|
|
10
|
+
A compatibility release for two things ASP 3.7.0 changed in the files the report reads. `pc_align` now writes Mean/StdDev/RMSE/Median/NMAD error statistics to its log, and the alignment page shows Median, NMAD and RMSE before and after alignment in place of the 16/50/84 percentiles ([#146](https://github.com/uw-cryo/asp_plot/issues/146)); older logs keep the percentiles, with no version sniffing. And a `parallel_stereo`/`bundle_adjust` run made with `--matches-as-txt` writes plain-text match files instead of binary `.match`, which previously left the match-point page with a "missing match file" placeholder — both formats are now discovered and parsed into the same DataFrame ([#147](https://github.com/uw-cryo/asp_plot/issues/147)). No new dependencies and no entry-point changes.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **`pc_align_report()` parses the error statistics ASP 3.7.0 added to the `pc_align` log** (issue [#146](https://github.com/uw-cryo/asp_plot/issues/146)): the `Input stats (meters):` / `Output stats (meters):` lines become `mean_beg/end`, `stddev_beg/end`, `rmse_beg/end`, `median_beg/end`, `nmad_beg/end` alongside the existing percentiles and translation, and flow into `Altimetry.alignment_report_df`. The alignment report page (ICESat-2 and LOLA/MOLA) now shows `Median`, `NMAD` and `RMSE` before/after alignment in place of the 16/50/84 percentiles, with the column description updated; `mean`/`stddev` stay in the dataframe only. Logs from ASP < 3.7.0 parse exactly as before, without the new keys, and the page keeps showing the percentiles for them — no version sniffing, the absence of the new stats is the signal. The seven committed example reports in `reports/` are regenerated with the new page.
|
|
14
|
+
- **The `pc_align` log parser is now regression-tested** against real logs from both generations — the existing 2024-11 fixtures and a new ASP 3.8.0-alpha LOLA log (`tests/test_data/pc_align/pc_align_lola-log-pc_align.txt`) — which also confirmed the percentile and translation lines we key off are unchanged in 3.8.0.
|
|
15
|
+
- **Plain-text ASP match files are discovered and parsed** (issue [#147](https://github.com/uw-cryo/asp_plot/issues/147)). ASP 3.7.0 added a text match-file format (`<prefix>-<A>__<B>.txt`, one `x1 y1 unc1 x2 y2 unc2` line per match), and `parallel_stereo`/`bundle_adjust --matches-as-txt` write it *instead of* `.match` — so a stereo directory produced with that switch previously got the "missing match file" placeholder on the match-point page. `StereoFiles` now also looks for `*__*.txt` (anchored on the `__` image-name separator and required to open with a six-field match row, so logs and alignment matrices are never mistaken for it — even with a run prefix like `my__run`), `StereoPlotter.get_match_point_df()` reads either format into the same `x1/y1/x2/y2` DataFrame, and the `.vwip` interest-point pairing works off the text stem too. The format is detected from the file's bytes (the binary header has NUL bytes; text never does), not the extension, so a renamed file still parses; when both forms coexist the binary file is preferred, as before; text files are read directly, never through the `.csv` cache a binary conversion leaves behind. A text twin of the raw-image fixture, converted with `ipmatch --binary-to-txt` (ASP 3.8.0-alpha), is committed so the two readers are checked against each other. `.vwip` files remain binary-only — stereo never writes text ones.
|
|
16
|
+
|
|
17
|
+
## [3.0.0] - 2026-08-24
|
|
18
|
+
|
|
19
|
+
A breaking standardization of the command-line interfaces ([#60](https://github.com/uw-cryo/asp_plot/issues/60)), done deliberately as a clean break — no aliases, no deprecation period — while the user base is small. Every multi-word option across the five CLIs (`asp_report`, `stereo_geom`, `csm_camera_plot`, `gallery`, `request_planetary_altimetry`) moves from underscores to the hyphenated style ASP itself uses (`--stereo_directory` → `--stereo-directory`), booleans become single switches for the non-default behavior (`--add_basemap False` → `--no-basemap`), and `--bundle_adjust_directory` becomes `--bundle-adjust-prefix`, matching both the name and the semantics of ASP's own option. The Python API is unchanged.
|
|
20
|
+
|
|
21
|
+
A major version because every existing `asp_report`/`stereo_geom`/`csm_camera_plot`/`gallery` invocation with a multi-word or boolean option needs editing. **Upgrade:** re-spell the flags per the entries below — the `--help` of each command lists the new names, and the committed example reports and notebooks show them in use. No new dependencies and no entry-point changes.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- **All CLI options are hyphenated** (issue [#60](https://github.com/uw-cryo/asp_plot/issues/60)). One-for-one renames: `--stereo-directory`, `--dem-filename`, `--dem-gsd`, `--map-crs`, `--reference-dem`, `--altimetry-csv`, `--subset-km`, `--atl06sr-time-range`, `--reuse-selections`, `--report-filename`, `--report-title` (asp_report); `--output-directory`, `--output-filename` (stereo_geom, gallery); `--max-filesize-mb` (gallery); `--original-cameras`, `--optimized-cameras`, `--map-crs`, `--upper-magnitude-percentile` (csm_camera_plot). Single-word options are untouched. The command recorded on the report's final page is emitted with the new spellings, so it stays re-runnable.
|
|
25
|
+
- **Boolean options are now single switches for the non-default behavior**, in the Unix idiom: where the default is on, only the negative switch exists — `--no-basemap`, `--no-altimetry`, `--no-pc-align`, `--no-geometry` (asp_report), `--no-basemap` (stereo_geom), `--no-trim` (csm_camera_plot), `--no-hillshade` (gallery, replacing the `--hillshade/--no-hillshade` pair) — and where the default is off, only the positive one — `--shared-scales`, `--log-scale-positions`, `--log-scale-angles`, `--add-basemap` (csm_camera_plot). Where you passed `--add_basemap False`, pass `--no-basemap`; the verb-y `plot`/`add` prefixes are dropped from the switch names.
|
|
26
|
+
- **`--bundle_adjust_directory` is now `--bundle-adjust-prefix`**, and accepts either the containing directory (`ba`, the previous behavior) or the same ASP-style output prefix passed to `stereo`/`mapproject` (`ba/run`). A prefix narrows the residuals/log file search to that run's outputs, so several bundle-adjust runs can share a directory. Internally, `ReportConfig.bundle_adjust_directory` is renamed to `bundle_adjust_prefix`.
|
|
27
|
+
- **`csm_camera_plot` options are harmonized with the other CLIs and ASP's `orbit_plot.py`**: `--save_dir` → `--output-directory`, `--fig_fn` → `--output-filename`, `--figsize` → `--figure-size`. The `csm_camera_summary_plot()` Python keyword arguments are unchanged.
|
|
28
|
+
- **Trailing slashes on directory options are stripped centrally** (`--directory`, `--stereo-directory`, `--bundle-adjust-prefix`), closing the last thread of issue [#60](https://github.com/uw-cryo/asp_plot/issues/60); the dg_mosaic `r100` concern from the same issue was resolved earlier by the sensor readers, which treat `*.r100.xml`/`*.r50.xml` as regenerable intermediates.
|
|
29
|
+
|
|
30
|
+
### Removed
|
|
31
|
+
- **The deprecated `--plot_icesat` alias** (deprecated in favor of `--plot_altimetry` in 1.10.0) is gone; altimetry is on by default and `--no-altimetry` disables it.
|
|
32
|
+
|
|
8
33
|
## [2.2.0] - 2026-08-18
|
|
9
34
|
|
|
10
35
|
A correctness release for the CSM camera comparison, and a new diagnostic layer under the match points.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: asp_plot
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: Package for plotting outputs Ames Stereo Pipeline processing
|
|
5
5
|
Project-URL: Homepage, https://github.com/uw-cryo/asp_plot
|
|
6
6
|
Project-URL: Documentation, https://asp-plot.readthedocs.io
|
|
@@ -74,7 +74,7 @@ See the [installation guide](https://asp-plot.readthedocs.io/en/latest/installat
|
|
|
74
74
|
Generate a PDF report from an ASP processing directory:
|
|
75
75
|
|
|
76
76
|
```
|
|
77
|
-
asp_report --directory ./ --
|
|
77
|
+
asp_report --directory ./ --stereo-directory stereo
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
See the [CLI documentation](https://asp-plot.readthedocs.io/en/latest/cli/index.html) for all options and additional tools (`stereo_geom`, `csm_camera_plot`).
|
|
@@ -30,7 +30,7 @@ See the [installation guide](https://asp-plot.readthedocs.io/en/latest/installat
|
|
|
30
30
|
Generate a PDF report from an ASP processing directory:
|
|
31
31
|
|
|
32
32
|
```
|
|
33
|
-
asp_report --directory ./ --
|
|
33
|
+
asp_report --directory ./ --stereo-directory stereo
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
See the [CLI documentation](https://asp-plot.readthedocs.io/en/latest/cli/index.html) for all options and additional tools (`stereo_geom`, `csm_camera_plot`).
|
|
@@ -17,6 +17,43 @@ logging.basicConfig(level=logging.WARNING)
|
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
# Labels ASP >= 3.7.0 prints on the "Input stats (meters):" / "Output stats
|
|
21
|
+
# (meters):" pc_align log lines, mapped to the keys pc_align_report() uses.
|
|
22
|
+
_PC_ALIGN_STATS_FIELDS = {
|
|
23
|
+
"Mean": "mean",
|
|
24
|
+
"StdDev": "stddev",
|
|
25
|
+
"RMSE": "rmse",
|
|
26
|
+
"Median": "median",
|
|
27
|
+
"NMAD": "nmad",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _parse_pc_align_stats_line(line, suffix):
|
|
32
|
+
"""Parse one ``Input/Output stats (meters):`` pc_align log line.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
line : str
|
|
37
|
+
e.g. ``"... Input stats (meters): Mean: 71.4632, StdDev: 134.758,
|
|
38
|
+
RMSE: 152.535, Median: 5.71217, NMAD: 3.20963"``
|
|
39
|
+
suffix : str
|
|
40
|
+
``"beg"`` for the Input line, ``"end"`` for the Output line.
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
dict
|
|
45
|
+
``{"mean_<suffix>": float, "stddev_<suffix>": float, ...}`` for every
|
|
46
|
+
label found on the line; labels that are missing are left out rather
|
|
47
|
+
than raising, so a future change to the line degrades gracefully.
|
|
48
|
+
"""
|
|
49
|
+
parsed = {}
|
|
50
|
+
for label, key in _PC_ALIGN_STATS_FIELDS.items():
|
|
51
|
+
match = re.search(rf"{label}: (-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?)", line)
|
|
52
|
+
if match:
|
|
53
|
+
parsed[f"{key}_{suffix}"] = float(match.group(1))
|
|
54
|
+
return parsed
|
|
55
|
+
|
|
56
|
+
|
|
20
57
|
class Alignment:
|
|
21
58
|
"""
|
|
22
59
|
Perform DEM alignment using point cloud alignment techniques.
|
|
@@ -274,11 +311,22 @@ class Alignment:
|
|
|
274
311
|
dict
|
|
275
312
|
Dictionary containing alignment metrics:
|
|
276
313
|
- p16_beg, p50_beg, p84_beg: Error percentiles before alignment
|
|
314
|
+
- mean_beg, stddev_beg, rmse_beg, median_beg, nmad_beg: Error
|
|
315
|
+
statistics before alignment (ASP >= 3.7.0 only; absent from
|
|
316
|
+
the dict when the log predates them)
|
|
277
317
|
- p16_end, p50_end, p84_end: Error percentiles after alignment
|
|
318
|
+
- mean_end, stddev_end, rmse_end, median_end, nmad_end: Error
|
|
319
|
+
statistics after alignment (ASP >= 3.7.0 only)
|
|
278
320
|
- north_shift, east_shift, down_shift: Translation vector components
|
|
279
321
|
in North-East-Down (NED) coordinate frame, in meters
|
|
280
322
|
- translation_magnitude: Magnitude of translation vector
|
|
281
323
|
|
|
324
|
+
All errors are the absolute point-to-point (or point-to-plane)
|
|
325
|
+
distances pc_align reports, in meters. ``median_*`` duplicates
|
|
326
|
+
``p50_*``; ``nmad_*`` is the robust spread and ``rmse_*`` the
|
|
327
|
+
outlier-sensitive one, so a large RMSE alongside a small NMAD flags
|
|
328
|
+
a tail of gross errors rather than a broad misfit.
|
|
329
|
+
|
|
282
330
|
Notes
|
|
283
331
|
-----
|
|
284
332
|
This method expects the log file to contain specific keyword patterns
|
|
@@ -317,6 +365,11 @@ class Alignment:
|
|
|
317
365
|
"p84_end": float(values[2]),
|
|
318
366
|
}
|
|
319
367
|
report = report | percentile_dict
|
|
368
|
+
# ASP >= 3.7.0 adds a one-line summary after each percentile line
|
|
369
|
+
if "Input stats (meters):" in line:
|
|
370
|
+
report = report | _parse_pc_align_stats_line(line, "beg")
|
|
371
|
+
if "Output stats (meters):" in line:
|
|
372
|
+
report = report | _parse_pc_align_stats_line(line, "end")
|
|
320
373
|
if "Translation vector (North-East-Down, meters):" in line:
|
|
321
374
|
ned_shift = np.genfromtxt(
|
|
322
375
|
[line.split("Vector3")[1][1:-2]], delimiter=","
|
|
@@ -59,10 +59,10 @@ class AlignmentResult:
|
|
|
59
59
|
One of:
|
|
60
60
|
- ``"insufficient_points"``: not enough ATL06-SR points for
|
|
61
61
|
pc_align to run (the aligned DEM is removed if one was written).
|
|
62
|
-
- ``"no_improvement"``: pc_align ran but p50 did not improve
|
|
62
|
+
- ``"no_improvement"``: pc_align ran but the median (p50) did not improve
|
|
63
63
|
toward 0 by more than the ``improvement_threshold_pct``; the
|
|
64
64
|
aligned DEM has been removed.
|
|
65
|
-
- ``"success"``: p50 improved by more than the threshold; the
|
|
65
|
+
- ``"success"``: the median (p50) improved by more than the threshold; the
|
|
66
66
|
aligned DEM is retained and ``Altimetry.aligned_dem_fn`` points
|
|
67
67
|
to it.
|
|
68
68
|
alignment_report_df : pandas.DataFrame
|
|
@@ -729,11 +729,11 @@ class Altimetry:
|
|
|
729
729
|
reason = (
|
|
730
730
|
f"Translation magnitude is below {min_translation_threshold*100:.0f}% "
|
|
731
731
|
"of the DEM GSD, so no aligned DEM was written despite a "
|
|
732
|
-
f"{improvement_repr}
|
|
732
|
+
f"{improvement_repr} median reduction."
|
|
733
733
|
)
|
|
734
734
|
else:
|
|
735
735
|
reason = (
|
|
736
|
-
f"
|
|
736
|
+
f"median {p50_beg:.2f} m -> {p50_end:.2f} m, "
|
|
737
737
|
f"{improvement_repr} <= {improvement_threshold_pct:.1f}% "
|
|
738
738
|
"threshold. Aligned DEM removed."
|
|
739
739
|
)
|
|
@@ -795,7 +795,7 @@ class Altimetry:
|
|
|
795
795
|
``--max-displacement`` for pc_align, in meters. Default 500
|
|
796
796
|
(ASAP-Stereo's CTX cookbook recommendation).
|
|
797
797
|
improvement_threshold_pct : float, optional
|
|
798
|
-
Minimum p50 reduction (%) required to keep the aligned DEM.
|
|
798
|
+
Minimum median (p50) reduction (%) required to keep the aligned DEM.
|
|
799
799
|
min_translation_threshold : float, optional
|
|
800
800
|
Minimum translation magnitude as a fraction of the DEM GSD.
|
|
801
801
|
minimum_points : int, optional
|
|
@@ -897,11 +897,11 @@ class Altimetry:
|
|
|
897
897
|
reason = (
|
|
898
898
|
f"Translation magnitude is below {min_translation_threshold*100:.0f}% "
|
|
899
899
|
f"of the DEM GSD ({gsd:.2f} m), so no aligned DEM was "
|
|
900
|
-
f"written despite a {improvement_repr}
|
|
900
|
+
f"written despite a {improvement_repr} median reduction."
|
|
901
901
|
)
|
|
902
902
|
else:
|
|
903
903
|
reason = (
|
|
904
|
-
f"
|
|
904
|
+
f"median {p50_beg:.2f} m -> {p50_end:.2f} m, "
|
|
905
905
|
f"{improvement_repr} <= {improvement_threshold_pct:.1f}% "
|
|
906
906
|
"threshold."
|
|
907
907
|
)
|
|
@@ -1034,7 +1034,7 @@ class Altimetry:
|
|
|
1034
1034
|
aligned_dem_fn=self.aligned_dem_fn,
|
|
1035
1035
|
improvement_pct=improvement_pct,
|
|
1036
1036
|
message=(
|
|
1037
|
-
f"
|
|
1037
|
+
f"Median improved from {p50_beg:.2f} m -> {p50_end:.2f} m "
|
|
1038
1038
|
f"({improvement_pct:.1f}% reduction). Aligned DEM written to "
|
|
1039
1039
|
f"{self.aligned_dem_fn}."
|
|
1040
1040
|
),
|
|
@@ -41,7 +41,7 @@ class ReadBundleAdjustFiles:
|
|
|
41
41
|
>>> mapproj_gdf = ba_reader.get_mapproj_residuals_gdf()
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
|
-
def __init__(self, directory, bundle_adjust_directory):
|
|
44
|
+
def __init__(self, directory, bundle_adjust_directory, stem=None):
|
|
45
45
|
"""
|
|
46
46
|
Initialize the ReadBundleAdjustFiles object.
|
|
47
47
|
|
|
@@ -51,10 +51,15 @@ class ReadBundleAdjustFiles:
|
|
|
51
51
|
Root directory of ASP processing
|
|
52
52
|
bundle_adjust_directory : str
|
|
53
53
|
Subdirectory containing bundle adjustment outputs
|
|
54
|
+
stem : str, optional
|
|
55
|
+
Run stem of an ASP output prefix (the ``run`` in ``ba/run``).
|
|
56
|
+
When given, file globs are narrowed to that run's outputs;
|
|
57
|
+
otherwise any run in the directory matches.
|
|
54
58
|
"""
|
|
55
59
|
self.directory = os.path.expanduser(directory)
|
|
56
60
|
self.bundle_adjust_directory = bundle_adjust_directory
|
|
57
61
|
self.full_directory = os.path.join(self.directory, bundle_adjust_directory)
|
|
62
|
+
self.stem_glob = stem if stem else "*"
|
|
58
63
|
|
|
59
64
|
def get_csv_paths(self, geodiff_files=False):
|
|
60
65
|
"""
|
|
@@ -86,8 +91,8 @@ class ReadBundleAdjustFiles:
|
|
|
86
91
|
will attempt to generate them using the geodiff ASP tool.
|
|
87
92
|
"""
|
|
88
93
|
filenames = [
|
|
89
|
-
"
|
|
90
|
-
"
|
|
94
|
+
f"{self.stem_glob}-initial_residuals_pointmap.csv",
|
|
95
|
+
f"{self.stem_glob}-final_residuals_pointmap.csv",
|
|
91
96
|
]
|
|
92
97
|
|
|
93
98
|
if geodiff_files:
|
|
@@ -371,7 +376,9 @@ class ReadBundleAdjustFiles:
|
|
|
371
376
|
the distance between matched interest points in the map-projected
|
|
372
377
|
images after bundle adjustment.
|
|
373
378
|
"""
|
|
374
|
-
path = glob_file(
|
|
379
|
+
path = glob_file(
|
|
380
|
+
self.full_directory, f"{self.stem_glob}-mapproj_match_offsets.txt"
|
|
381
|
+
)
|
|
375
382
|
if path is None:
|
|
376
383
|
raise ValueError("\n\nMapProj Residuals TXT file not found.\n\n")
|
|
377
384
|
|
|
@@ -411,7 +418,9 @@ class ReadBundleAdjustFiles:
|
|
|
411
418
|
the bundle adjustment residuals propagate to uncertainty in
|
|
412
419
|
triangulation. This is an estimate of the final DEM error.
|
|
413
420
|
"""
|
|
414
|
-
path = glob_file(
|
|
421
|
+
path = glob_file(
|
|
422
|
+
self.full_directory, f"{self.stem_glob}-triangulation_uncertainty.txt"
|
|
423
|
+
)
|
|
415
424
|
if path is None:
|
|
416
425
|
raise ValueError("\n\nTriangulation Uncertainty TXT file not found.\n\n")
|
|
417
426
|
|