Add test coverage for the NISAR GUNW loader (prep_nisar) - #1507
Add test coverage for the NISAR GUNW loader (prep_nisar)#1507s-sasaki-earthsea-wizard wants to merge 1 commit into
Conversation
|
💖 Thanks for opening this pull request! Please check out our contributing guidelines. 💖 |
Reviewer's GuideThis PR adds a new synthetic-fixture unit test suite for the NISAR GUNW loader in prep_nisar, exercising frequency normalization, required-path discovery, metadata extraction, and regression coverage for the referenceSlantRange dataset without modifying production code. File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
@sourcery-ai |
|
A note on future NISAR product versions One known limitation of this test suite, for the record: the synthetic fixtures mirror the GUNW schema of the currently distributed products (beta/provisional era). NASA has announced an updated NISAR processor for fall 2026, followed by reprocessing of the forward stream and back-processing of earlier acquisitions, so a schema drift in validated products is a realistic possibility. Synthetic fixtures cannot detect that class of change by design — they pin the current contract so the code side cannot silently regress (the #1485 class of bug). If the schema does change, the fixture builders are plain code and cheap to update. As a follow-up (separate PR, production code), I'd propose a small version guard in |
prep_nisar (the NISAR GUNW loader added in insarlab#1487) had no automated test coverage. Add a synthetic-fixture suite for its frequency resolution and metadata parsing; no production code is changed. The primary motivation is regression coverage for the insarlab#1485 class of bug: the reader must read radarGrid/referenceSlantRange, not a bare slantRange dataset absent from real GUNW products. A bare-slantRange fixture is asserted to raise, and the constant that names the dataset is guarded. Fixtures are minimal synthetic GUNW HDF5 files built with h5py (a few KB, no GDAL, no network). Coverage: frequency normalization/resolution, required-path discovery per stack (ifgram/ion/tropo/set), and extract_metadata (UTM N/S and geographic EPSG 4326, half-pixel origin, common bounds, CENTER_LINE_UTC) including the insarlab#1485 regression. The GDAL warp path (_warp_to_grid_mem, DEM/mask reprojection) and the full load_nisar / prepare_* writers need a real projected raster and are out of scope; they are validated against a real sample GUNW product separately.
e9d10c2 to
7315fa2
Compare
|
Rebased onto current Real-data validation. The fixtures here are synthetic, so I wanted to check that they pin a contract that real products actually exercise. I ran the loader on a stack of 10 NISAR GUNW products (spec 1.5.0,
That is loader plumbing only -- no claim about the science of these products. Interaction with #1494. Since #1494 also reworks The new - slant_path = prep_nisar.PROCESSINFO["rdr_slant_range"]
+ slant_path = prep_nisar._processinfo()["rdr_slant_range"]which still resolves to So the two PRs are close to independent. I am glad to follow whichever order is easiest for you and for #1494 -- if #1494 lands first, I will push that one-line update here as soon as it does, and I am equally happy to hold this PR until then if that is simpler. |
Description of proposed changes
src/mintpy/prep_nisar.py(the NISAR GUNW loader added in #1487) currently has no automated test coverage. This PR adds a synthetic-fixture test suite for its frequency resolution and metadata parsing. No production code is changed — this is tests only.The primary motivation is regression coverage for the class of bug reported in #1485 (the reader must read
.../radarGrid/referenceSlantRange, not a bareslantRangedataset that does not exist in real GUNW products). The current code already readsreferenceSlantRange(addressed by #1487); these tests pin that behavior so it cannot silently regress.What is covered
Fixtures are minimal synthetic GUNW HDF5 files built with
h5py(a few KB, no GDAL warp and no network) that mirror the real GUNW schema: byte-string identification fields, scalar spacing/looks/EPSG datasets, and theradarGridlayout.tests/test_prep_nisar.pycovers:auto/A/B, missing frequency or polarization);ifgram/ion/tropo/set);extract_metadata— UTM (N/S) and geographic (EPSG 4326) metadata, half-pixelX_FIRST/Y_FIRST, common bounds,CENTER_LINE_UTC, and ascending/descending coordinate handling;slantRangefixture must raise, and the constant that names the dataset is guarded against reverting to the non-existent bare name.What is not covered (and why)
The GDAL warp path (
_warp_to_grid_mem, DEM/mask reprojection) and the fullload_nisar/prepare_*stack writers require a real projected DEM raster and are out of scope for this unit-test PR — a synthetic fixture cannot faithfully represent the 3-DradarGridcube or a GDAL reprojection. They were validated separately against a real product (below).Validation against a real product
The synthetic fixtures were cross-checked against a real JPL NISAR sample GUNW (ALOS-1 PALSAR surrogate, L-band, ~264 MB, no login required) to confirm they match the real file layout. On that product the GDAL-free readers resolve cleanly:
radarGrid/referenceSlantRangepresent, bareslantRangeabsent (Missing 'slantRange' dataset in NISAR GUNW files #1485)ifgram/ion/tropo/set) resolveextract_metadataparses: EPSG 32611 / UTM 11N / L-band λ 0.236 m / 1555 × 1136 / platform ALOS / starting range 727 292 mFull log (commit-pinned): https://github.com/s-sasaki-earthsea-wizard/mintpy-nisar-sample/blob/a2cd7dcaf86b72e1804f41548571ee2b412812be/reports/validation.md
Testing
pytest tests/test_prep_nisar.py).pre-commit run --all-filespasses.Mutation check — the tests fail when the loader regresses
"31 passed" alone cannot distinguish a meaningful suite from a vacuous one, so here is the falsification side: three single-line regressions applied to
prep_nisar.py(one at a time), each caught by the suite. Everything below runs locally against the synthetic fixtures — no NISAR product is needed — and each check takes under a minute: apply the diff, runpython -m pytest tests/test_prep_nisar.py -q, revert.Baseline on the unmodified branch: 31 passed.
Mutation 1 — revert the #1485 fix (read bare
slantRange) → 9 failedBoth dedicated slant-range regression tests fail, and so do all seven
extract_metadatatests — a regression of the #1485 class cannot slip through.Mutation 2 — drop the half-pixel shift in
X_FIRST→ 1 failedExactly the dedicated origin/bounds test fails and nothing else — the tests pin values independently instead of failing as a correlated cluster.
Mutation 3 — disable the required-path check in
_resolve_frequency→ 2 failedBoth error-path tests fail — the
*_raisestests are not vacuous.On #1485
#1485 is still open; its underlying cause was addressed by #1487. If this
regression coverage is acceptable, #1485 could likely be closed as fixed-and-guarded — I'll defer that judgment to the maintainers.
Disclosure: these tests were developed with AI assistance. All code was reviewed by the author and validated against a real GUNW sample product.
Summary by Sourcery
Add automated test coverage for the NISAR GUNW loader without changing production code.
Enhancements:
Tests: