asp_plot.dem_benchmark#
Benchmark many DEMs against one altimetry reference (issue #169).
The report scores one DEM against ICESat-2 (or LOLA/MOLA). This module
scores any number of DEMs – different scene combinations, joint multi-view
triangulation vs. pairwise stereo + dem_mosaic, parameter sweeps – against
the same fixed altimetry sample, so the numbers are directly comparable:
coverage inside a common area of interest (by default the intersection of all DEM footprints, so crop windows that differ per run compare fairly)
triangulation error, from the
*-IntersectionErr.tifpoint2demwrites next to each*-DEM.tif(absent for a mosaic)altimetry residuals (altimetry minus DEM: n, median, NMAD, RMSE) before and, optionally, after a
pc_align --compute-translation-onlyper DEM, with the translation that removedoptionally, each DEM’s difference against one of the candidates named as the reference (DEM minus reference median / NMAD)
Every DEM is scored with the same recipe the report uses for one DEM: the
cached ATL06-SR parquet is replayed (no SlideRule request), water returns are
dropped with the ESA WorldCover classes stored in the cache, and dh outliers
beyond 3σ are removed per DEM (after a gross-outlier cut at 30 NMAD). pc_align products and translated DEM copies
are kept out of the candidates’ folders, under
<directory>/dem_benchmark/<label>/, so nothing is written into the stereo runs.
Examples
>>> from asp_plot.dem_benchmark import DEMBenchmark
>>> bench = DEMBenchmark(
... directory="atlanta_mvs",
... dems={
... "MVS 3-scene": "atlanta_mvs/stereo_mvs3/run-DEM.tif",
... "MVS 5-scene": "atlanta_mvs/stereo_mvs5/run-DEM.tif",
... "3 pairs + mosaic": "atlanta_mvs/pairwise_mosaic-DEM.tif",
... },
... parquet="atlanta_mvs/atl06sr_all.parquet",
... )
>>> stats = bench.run()
>>> bench.summary_plot(save_dir="atlanta_mvs", fig_fn="dem_benchmark.png")
Attributes#
Classes#
Score many DEMs against one altimetry sample. |
Functions#
|
Path of the |
|
Derive a short label for a DEM from its path. |
|
Turn CLI-style DEM specs into an ordered |
Module Contents#
- class asp_plot.dem_benchmark.DEMBenchmark(directory, dems, parquet=None, altimetry_csv=None, key='all', reference=None, aoi='intersection', filter_out='water', n_sigma=3, title=None)#
Score many DEMs against one altimetry sample.
- Parameters:
directory (str) – Working folder. pc_align products, the pc_align CSV and the translated DEM copy for each candidate go under
<directory>/dem_benchmark/<label>/.dems (dict or list) –
{label: dem_fn}(order preserved), or a list of paths /"label=path"strings (seeparse_dem_specs()).parquet (str or dict, optional) – ICESat-2 ATL06-SR parquet cache written by a prior report or
Altimetry.request_atl06sr_multi_processing(save_to_parquet=True); either one path (used as processing levelkey) or a{key: path}mapping. Required for Earth DEMs.altimetry_csv (str, optional) – LOLA/MOLA CSV (see
request_planetary_altimetry). Required for Moon/Mars DEMs.key (str, optional) – ATL06-SR processing level to score against, default
"all".reference (str, optional) – Label of the candidate the others are differenced against for the
vs_ref_*columns. Default None (columns left NaN).aoi (str, tuple or None, optional) – Area for the coverage and triangulation-error statistics:
"intersection"(default) uses the common footprint of all DEMs; a(left, bottom, right, top)tuple is taken in the first DEM’s CRS; None uses each DEM’s own extent (not comparable across crops).filter_out (str or None, optional) – ESA WorldCover group dropped before differencing, default
"water"(the report’s setting). None keeps every return.n_sigma (float or None, optional) – Per-DEM dh outlier cut, default 3 (the report’s setting).
title (str, optional) – Figure title.
Notes
After
run(),stats_dfholds one row per DEM with the columns inSTATS_COLUMNS(residual columns are altimetry minus DEM, in meters);altimetrymaps each label to itsAltimetryobject, for per-DEM figures such asmapview_plot_atl06sr_to_dem()orhistogram_by_landcover(); anddh/dh_alignedmap each label to the residual series scored (aligned only when pc_align ran for it).- aoi_area_km2()#
Area of the coverage/IE window in km² (None when each DEM uses its own extent).
- histogram_plot(aligned='auto', bins=100, xlim=None, sort=True, save_dir=None, fig_fn=None, dpi=None)#
Overlaid residual histograms, one outline per DEM.
- Parameters:
aligned ({"auto", True, False}, optional) – Plot post-alignment residuals when every DEM has them (
"auto", default), always (True, DEMs without them fall back to pre-alignment), or never (False).bins (int, optional) – Histogram bins, default 100.
xlim (float, optional) – Half-width of the plotted range in meters; default 3× the largest NMAD among the DEMs. Residuals beyond it are not drawn (the legend counts all of them).
sort (bool, optional) – Order the legend best-first as in
summary_plot(), default True.
- Return type:
- label_directory(label)#
Working folder for one candidate.
- run(pc_align=True, minimum_points=500, max_displacement=None)#
Score every DEM and return the stats table.
- Parameters:
pc_align (bool, optional) – Also run
pc_align --compute-translation-onlyper DEM and re-score against the translated copy. Default True. Existing pc_align outputs under the benchmark folder are reused, so a re-run makes no pc_align call and works offline.minimum_points (int, optional) – Skip pc_align for a DEM with fewer valid dh points, default 500 (the report’s threshold).
max_displacement (float, optional) –
pc_align --max-displacementin meters. Default None: 20 m on Earth, 500 m on the Moon/Mars, matchingAlignment.
- Returns:
self.stats_df: one row per DEM, columnsSTATS_COLUMNS.- Return type:
pandas.DataFrame
- save_stats(csv_fn)#
Write
stats_dftocsv_fn(creating its folder) and return the path.
- summary_plot(sort=True, save_dir=None, fig_fn=None, dpi=None)#
One row per DEM, one panel per metric.
Panels: coverage (% valid inside the AOI, area printed), triangulation error (median, NMAD printed; omitted when no DEM has an IntersectionErr raster), and altimetry-minus-DEM median and NMAD – as dumbbells from before (open) to after (filled) pc_align when alignment ran. A translation-only pc_align leaves NMAD essentially unchanged by construction, so that panel’s two markers coincide; the median panel is where the alignment shows. Rows are sorted best-first by post-alignment NMAD (pre-alignment when pc_align did not run) unless
sort=False.- Return type:
- altimetry#
- altimetry_csv#
- property benchmark_directory#
Folder holding the per-label pc_align products and translated DEMs.
- body#
- dh#
- dh_aligned#
- directory#
- filter_out = 'water'#
- key = 'all'#
- n_sigma = 3#
- parquet#
- reference = None#
- stats_df = None#
- title = None#
- asp_plot.dem_benchmark.intersection_error_path(dem_fn)#
Path of the
point2dem --errorimagesibling of<prefix>-DEM.tif, or None.
- asp_plot.dem_benchmark.label_from_dem_path(dem_fn)#
Derive a short label for a DEM from its path.
Strips the ASP
-DEM.tifsuffix; when what remains is a generic ASP output prefix (run,out, …) the containing folder is used instead, since that is what distinguishes one run from another.Examples
>>> label_from_dem_path("atlanta_mvs/stereo_mvs3/run-DEM.tif") 'stereo_mvs3' >>> label_from_dem_path("atlanta_mvs/pairwise_mosaic-DEM.tif") 'pairwise_mosaic'
- asp_plot.dem_benchmark.parse_dem_specs(specs)#
Turn CLI-style DEM specs into an ordered
{label: path}mapping.Each spec is either a path (labelled via
label_from_dem_path()) orlabel=path. Duplicate labels are disambiguated with the containing folder so tworun-DEM.tifnever collapse into one row.
- asp_plot.dem_benchmark.GENERIC_STEMS#
- asp_plot.dem_benchmark.MAX_WINDOW_PIXELS = 16000000#
- asp_plot.dem_benchmark.STATS_COLUMNS = ['label', 'dem_fn', 'gsd_m', 'valid_pct', 'valid_area_km2', 'ie_median_m', 'ie_nmad_m',...#
- asp_plot.dem_benchmark.logger#