Tutorial 1 — ASTER Mt. Rainier#

An end-to-end ASP run. Single ASTER L1A scene to a 30 m DEM and a diagnostic PDF report.

We chose ASTER for the first tutorial because:

  • The data is fully open. We use a Zenodo-hosted V003 archive; no Earthdata login.

  • A single L1A scene contains both the nadir-looking and back-looking views, so there’s no “finding a pair” step.

What we’ll do#

  1. Download the L1A archive from Zenodo.

  2. Run aster2asp to extract the nadir and back-looking imagery and camera files.

  3. Run parallel_stereo (raw first pass) and point2dem.

  4. Inspect the rough DEM with asp_plot.

  5. Re-process with orthorectification for a higher-quality DEM.

  6. Generate a PDF report with asp_plot.

Scene: ASTER L1A acquired 2017-07-31 over Mt. Rainier, WA. UTM zone 10N (EPSG:32610).

Reference: ASP’s official ASTER example.

Note

ASP calls this step “mapprojection” in its toolchain (the binary is mapproject, the bundle-adjust flag is --mapproj-dem). We use “orthorectification” — the more standard photogrammetry term — for the concept while keeping ASP’s tool names verbatim.

from pathlib import Path

DATA = "../data/aster_rainier"

!mkdir -p {DATA}

1. Download the scene#

We use the V003 archive on Zenodo (preserved for tutorials after NASA decommissioned V003 in Dec 2025). The download_aster.sh script handles fetch + unzip; if the data is already there it’s a no-op.

!bash ../scripts/download_aster.sh {DATA}
!ls -1 {DATA}/dataDir/ | head

2. Sensor prep — aster2asp#

aster2asp reads the L1A archive and writes out four files: a nadir-view image (out-Band3N.tif), a back-looking image (out-Band3B.tif), and an XML camera file for each. After this step the data is in the standard “image.tif + image.xml” pair that the rest of ASP works with.

if Path(f"{DATA}/out-Band3N.tif").exists():
    print(f"{DATA}/out-Band3N.tif exists — skipping aster2asp. Delete out-Band3*.* to reprocess.")
else:
    !aster2asp {DATA}/dataDir -o {DATA}/out

!ls -1 {DATA}/out-Band3*.tif {DATA}/out-Band3*.xml

3. Stereo (no orthorectification) — first pass#

Run parallel_stereo on the raw imagery to produce a reference DEM for the orthorectified pass below. This DEM gets downsampled to 200 m as the grid for the next pass, so quality matters less than speed.

  • -t aster selects the ASTER session (knows about ASTER cameras).

  • --stereo-algorithm asp_bm: plain block matching, fast.

  • --subpixel-mode 1: parabolic subpixel refinement. Cheaper than mode 2 Bayes-EM, fine for a reference DEM.

  • --aster-use-csm uses the Community Sensor Model camera.

  • --processes 8 --threads-multiprocess 1 matches the 8-core Codespace.

if Path(f"{DATA}/stereo_bm_200m/run-DEM.tif").exists():
    print(f"{DATA}/stereo_bm_200m/run-DEM.tif exists — skipping first stereo pass. Delete {DATA}/stereo_bm_200m/ to reprocess.")
else:
    !parallel_stereo -t aster \
        --stereo-algorithm asp_bm \
        --subpixel-mode 1 \
        --aster-use-csm \
        --processes 8 --threads-multiprocess 1 \
        {DATA}/out-Band3N.tif {DATA}/out-Band3B.tif \
        {DATA}/out-Band3N.xml {DATA}/out-Band3B.xml \
        {DATA}/stereo_bm_200m/run

    !point2dem --tr 200 -r earth --auto-proj-center --errorimage {DATA}/stereo_bm_200m/run-PC.tif

!ls -lh {DATA}/stereo_bm_200m/run-DEM.tif

4. Inspect the rough DEM with asp_plot#

StereoPlotter.plot_detailed_hillshade() shows the DEM as a hillshade with a 5 km-wide subset zoom on Mt. Rainier itself.

from asp_plot.stereo import StereoPlotter

plotter = StereoPlotter(
    DATA,
    "stereo_bm_200m/",
    title="Rainier — first pass (no mapproj)",
)
plotter.plot_detailed_hillshade(subset_km=5)

ICESat-2 ATL06-SR vs the rough DEM.

from utils import icesat2_check
icesat2_check(f"{DATA}/stereo_bm_200m/run-DEM.tif", directory=DATA)

5. Orthorectified pass#

Use the rough 200 m DEM we just made, run mapproject to orthorectify the input images onto it, and re-run stereo on the orthorectified pair. The disparity is now much smaller because the rough DEM is locally accurate.

if Path(f"{DATA}/stereo_mp_mgm/run-DEM.tif").exists():
    print(f"{DATA}/stereo_mp_mgm/run-DEM.tif exists — skipping mapprojected pass. Delete {DATA}/stereo_mp_mgm/ to reprocess.")
else:
    # Mapproject both images onto the 200 m grid, output at 15 m
    !mapproject --tr 15 --aster-use-csm \
        {DATA}/stereo_bm_200m/run-DEM.tif \
        {DATA}/out-Band3N.tif {DATA}/out-Band3N.xml \
        {DATA}/out-Band3N_proj.tif

    !mapproject --tr 15 --aster-use-csm \
        {DATA}/stereo_bm_200m/run-DEM.tif \
        {DATA}/out-Band3B.tif {DATA}/out-Band3B.xml \
        {DATA}/out-Band3B_proj.tif

    # Stereo on the mapprojected images. The 200 m DEM is the reference grid.
    !parallel_stereo -t aster \
        --stereo-algorithm asp_mgm \
        --subpixel-mode 9 \
        --aster-use-csm \
        --processes 8 --threads-multiprocess 1 \
        {DATA}/out-Band3N_proj.tif {DATA}/out-Band3B_proj.tif \
        {DATA}/out-Band3N.xml {DATA}/out-Band3B.xml \
        {DATA}/stereo_mp_mgm/run \
        {DATA}/stereo_bm_200m/run-DEM.tif

    !point2dem --tr 30 -r earth --auto-proj-center --errorimage {DATA}/stereo_mp_mgm/run-PC.tif

!ls -lh {DATA}/stereo_mp_mgm/run-DEM.tif
plotter = StereoPlotter(
    DATA,
    "stereo_mp_mgm/",
    title="Rainier — mapprojected pass",
)
plotter.plot_detailed_hillshade(subset_km=5)

Same comparison against the orthorectified DEM.

icesat2_check(f"{DATA}/stereo_mp_mgm/run-DEM.tif", directory=DATA)

6. Generate the full PDF report#

Hand the whole directory to the asp_plot CLI to produce a PDF: input scenes, disparity, hillshades, dh-vs-reference, and an ICESat-2 altimetry comparison.

We disable --plot_geometry because ASTER doesn’t have the per-scene XML metadata that DigitalGlobe/Vantor provides for the stereo-geometry skyplot.

if Path(f"{DATA}/stereo_mp_mgm/rainier_aster_report.pdf").exists():
    print(f"{DATA}/stereo_mp_mgm/rainier_aster_report.pdf exists — skipping asp_plot CLI. Delete it to regenerate.")
else:
    !asp_plot \
        --directory {DATA} \
        --stereo_directory stereo_mp_mgm \
        --reference_dem {DATA}/stereo_bm_200m/run-DEM.tif \
        --plot_altimetry True \
        --plot_geometry False \
        --subset_km 5 \
        --report_filename rainier_aster_report.pdf

The report is at data/aster_rainier/stereo_mp_mgm/rainier_aster_report.pdf. Open it from the VS Code file tree.

What’s next#

Tutorial 2: WorldView-3 UCSD adds bundle adjustment and ICESat-2 alignment.

→ For deeper ASTER processing (jitter correction, full bundle adjust), see asp_plot’s ASTER notebooks.