Skip to content

Improve NISAR GSLC product API and subset extraction#211

Draft
scottstanie wants to merge 3 commits intoopera-adt:mainfrom
scottstanie:improve-nisar-gslc-api
Draft

Improve NISAR GSLC product API and subset extraction#211
scottstanie wants to merge 3 commits intoopera-adt:mainfrom
scottstanie:improve-nisar-gslc-api

Conversation

@scottstanie
Copy link
Contributor

@scottstanie scottstanie commented Mar 2, 2026

After the subsetted download, we

  • didn't copy over the identification
  • hadn't set up the /complex64 after subsetting

also some of the read functions needed an h5file, which didn't make sense for instance methods. I saw there was no convenient wrapper to read in data, so you still had to copy the long path to .../HH.

Now we can do

p1 = nisar.GslcProduct.from_filename ("NISAR_L2_PR_GSLC_007_034_A_019_4005_DHDH_A_20251206T130825_20251206T130900_X05009_N_F_J_001.h5")
p2 = nisar.GslcProduct.from_filename( "NISAR_L2_PR_GSLC_009_034_A_019_4005_DHDH_A_20251230T130826_20251230T130901_X05009_N_F_J_001.h5")

utils.take_looks(
    p1.read_subset(None, None, polarization="HH")
    * p2.read_subset(None, None, polarization="HH").conj(),
    4,
    4,
)
image

(claude-generated summary):

Summary

  • Copy metadata into subset files: _extract_subset_from_h5 now copies /science/LSAR/identification, /science/LSAR/GSLC/metadata/orbit, and the complex64 root type into subset HDF5 files. The old comment claiming h5py's copy() doesn't work with fsspec was incorrect.
  • Simplify GslcProduct API: Remove h5file parameter from all methods (get_epsg, get_coordinates, get_shape, read_subset, lonlat_to_rowcol, get_available_polarizations, get_available_frequencies). Methods now open the file internally via open_h5(), which handles both local and remote files transparently.
  • Add convenience data accessors: New read(frequency, polarization) method and __getitem__ support (product["HH"] or product["A", "HV"]) for ergonomic data access.
  • Fix search() cycle_number filtering: The cycle_number parameter was accepted but never used for filtering. Now properly filters results.

Test plan

  • All 50 existing NISAR tests pass (test_nisar_product.py, test_nisar_download.py)
  • Pre-commit hooks pass (black, ruff, mypy)
  • Verified on real NISAR GSLC files: subset files contain identification, orbit, and complex64
  • Verified product["HH"], product.get_epsg(), etc. work on local subset files

🤖 Generated with Claude Code

- Copy identification, orbit metadata, and complex64 root type into
  subset files (h5py.copy works fine with fsspec, contrary to old comment)
- Remove h5file parameter from all GslcProduct methods; use open_h5()
  internally so methods work transparently with local and remote files
- Add read() method and __getitem__ for convenient data access
  (e.g. product["HH"] or product["A", "HV"])
- Fix search() to actually filter by cycle_number parameter
- Update tests to use new simplified API

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@scottstanie scottstanie marked this pull request as draft March 2, 2026 16:37
@mirzaees mirzaees self-requested a review March 3, 2026 17:11
Copy link
Contributor

@mirzaees mirzaees left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was testing the search api and the results are not what I expected:
opera-utils nisar-gslc-search --track-frame 007_156_D_070 > gslc.txt

the output is two products, though I expect it to be all the 7 products for both DHDH and QPDH:
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_007_156_D_070_2005_QPDH_A_20251215T004330_20251215T004340_X05009_N_P_J_001/NISAR_L2_PR_GSLC_007_156_D_070_2005_QPDH_A_20251215T004330_20251215T004340_X05009_N_P_J_001.h5 https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_007_156_D_070_4005_DHDH_A_20251215T004343_20251215T004405_X05009_N_P_J_001/NISAR_L2_PR_GSLC_007_156_D_070_4005_DHDH_A_20251215T004343_20251215T004405_X05009_N_P_J_001.h

@mirzaees
Copy link
Contributor

mirzaees commented Mar 3, 2026

I was testing the search api and the results are not what I expected: opera-utils nisar-gslc-search --track-frame 007_156_D_070 > gslc.txt

the output is two products, though I expect it to be all the 7 products for both DHDH and QPDH: https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_007_156_D_070_2005_QPDH_A_20251215T004330_20251215T004340_X05009_N_P_J_001/NISAR_L2_PR_GSLC_007_156_D_070_2005_QPDH_A_20251215T004330_20251215T004340_X05009_N_P_J_001.h5 https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_007_156_D_070_4005_DHDH_A_20251215T004343_20251215T004405_X05009_N_P_J_001/NISAR_L2_PR_GSLC_007_156_D_070_4005_DHDH_A_20251215T004343_20251215T004405_X05009_N_P_J_001.h

you might need to remove the cycle number and add the center frequency instead:
so instead of "CCC_RRR_D_TTT", do "RRR_D_TTT_FFFF"

@scottstanie
Copy link
Contributor Author

thanks for finding that, still getting used to the names.
what do you think of a --pol, like opera-utils nisar-gslc-search --track-frame 156_D_070 --pol QPDH?

$ opera-utils nisar-gslc-search --track-frame 156_D_070 --pol QPDH
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_003_156_D_070_2005_QPDH_A_20251028T004328_20251028T004337_X05009_N_P_J_001/NISAR_L2_PR_GSLC_003_156_D_070_2005_QPDH_A_20251028T004328_20251028T004337_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_004_156_D_070_2005_QPDH_A_20251109T004329_20251109T004338_X05009_N_P_J_001/NISAR_L2_PR_GSLC_004_156_D_070_2005_QPDH_A_20251109T004329_20251109T004338_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_005_156_D_070_2005_QPDH_A_20251121T004329_20251121T004338_X05009_N_P_J_001/NISAR_L2_PR_GSLC_005_156_D_070_2005_QPDH_A_20251121T004329_20251121T004338_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_006_156_D_070_2005_QPDH_A_20251203T004329_20251203T004339_X05009_N_P_J_001/NISAR_L2_PR_GSLC_006_156_D_070_2005_QPDH_A_20251203T004329_20251203T004339_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_007_156_D_070_2005_QPDH_A_20251215T004330_20251215T004340_X05009_N_P_J_001/NISAR_L2_PR_GSLC_007_156_D_070_2005_QPDH_A_20251215T004330_20251215T004340_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_008_156_D_070_2005_QPDH_A_20251227T004331_20251227T004340_X05009_N_P_J_001/NISAR_L2_PR_GSLC_008_156_D_070_2005_QPDH_A_20251227T004331_20251227T004340_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_009_156_D_070_2005_QPDH_A_20260108T004331_20260108T004341_X05009_N_P_J_001/NISAR_L2_PR_GSLC_009_156_D_070_2005_QPDH_A_20260108T004331_20260108T004341_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_010_156_D_070_2005_QPDH_A_20260120T004332_20260120T004341_X05010_N_P_J_001/NISAR_L2_PR_GSLC_010_156_D_070_2005_QPDH_A_20260120T004332_20260120T004341_X05010_N_P_J_001.h5
$ opera-utils nisar-gslc-search --track-frame 156_D_070 --pol DHDH
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_003_156_D_070_4005_DHDH_A_20251028T004341_20251028T004403_X05009_N_P_J_001/NISAR_L2_PR_GSLC_003_156_D_070_4005_DHDH_A_20251028T004341_20251028T004403_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_004_156_D_070_4005_DHDH_A_20251109T004341_20251109T004404_X05009_N_P_J_001/NISAR_L2_PR_GSLC_004_156_D_070_4005_DHDH_A_20251109T004341_20251109T004404_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_005_156_D_070_4005_DHDH_A_20251121T004341_20251121T004404_X05009_N_P_J_001/NISAR_L2_PR_GSLC_005_156_D_070_4005_DHDH_A_20251121T004341_20251121T004404_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_006_156_D_070_4005_DHDH_A_20251203T004342_20251203T004404_X05009_N_P_J_001/NISAR_L2_PR_GSLC_006_156_D_070_4005_DHDH_A_20251203T004342_20251203T004404_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_007_156_D_070_4005_DHDH_A_20251215T004343_20251215T004405_X05009_N_P_J_001/NISAR_L2_PR_GSLC_007_156_D_070_4005_DHDH_A_20251215T004343_20251215T004405_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_008_156_D_070_4005_DHDH_A_20251227T004343_20251227T004405_X05009_N_P_J_001/NISAR_L2_PR_GSLC_008_156_D_070_4005_DHDH_A_20251227T004343_20251227T004405_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_009_156_D_070_4005_DHDH_A_20260108T004344_20260108T004406_X05009_N_P_J_001/NISAR_L2_PR_GSLC_009_156_D_070_4005_DHDH_A_20260108T004344_20260108T004406_X05009_N_P_J_001.h5
https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GSLC_BETA_V1/NISAR_L2_PR_GSLC_010_156_D_070_4005_DHDH_A_20260120T004344_20260120T004407_X05010_N_P_J_001/NISAR_L2_PR_GSLC_010_156_D_070_4005_DHDH_A_20260120T004344_20260120T004407_X05010_N_P_J_001.h5

@mirzaees
Copy link
Contributor

mirzaees commented Mar 3, 2026

yeah I think --pol is a good addition

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.

2 participants