Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

NISAR Data Access

NISAR Data Access

This notebook demonstrates how to access and explore NISAR data in Python. NISAR products are distributed as HDF5 files, which can be opened using several different tools depending on the level of detail and functionality needed.

After searching for and downloading NISAR data, this workflow:

  • accesses data using h5py

  • accesses data using xarray.Dataset and xarray.DataTree

  • accesses data using ISCE3

These approaches highlight different options for accessing NISAR data, allowing users to compare methods based on their research questions and workflow.

2. Comparing Methods for Accessing NISAR Data

The approaches shown in this notebook provide different ways to access and work with NISAR HDF5 files, each with its own strengths.

MethodBest ForProsCons
h5pyDirect, low-level file accessMinimal dependencies, full control over HDF5 structure, can inspect datasets without loading valuesRequires long paths, manual navigation, slicing loads data immediately into memory
xarray.DatasetWorking with one HDF5 groupLabeled arrays, cleaner syntax, easier data handling, supports lazy loading with chunked arrays for large datasetsOpens one group at a time, requires knowing the group path
xarray.DatatreeWorking with multiple HDF5 groupsPreserves full HDF5 structure, supports lazy loading with chunking, useful for navigating unknown files and working across multiple groupsMore complex, less efficient for single group analysis
ISCE3SAR processing and NISAR-specific workflowsDesigned for NISAR data, understands radar geometry and metadataDoes not easily pull all types of metadata, requires additional installation, may not work in all environments

3. Selecting a NISAR Product

NISAR products are identified by a four-letter abbreviation. In the download example below, the product type is controlled by the processingLevel field. To learn more about invidicual products, see the NISAR Data User Guide.

For this walkthrough, we use:

  • GCOV — Geocoded Polarimetric Covariance Matrix

Other NISAR products include:

L0 Products

  • RRSD — Radar Raw Signal Data

L1 Products

  • RSLC — Range-Doppler Single Look Complex

  • RIFG — Range-Doppler Interferogram

  • ROFF — Range-Doppler Pixel Offsets

  • RUNW — Range-Doppler Unwrapped Interferogram

L2 Products

  • GSLC — Geocoded Single Look Complex

  • GOFF — Geocoded Pixel Offsets

  • GCOV — Geocoded Polarimetric Covariance Matrix

  • GUNW — Geocoded Unwrapped Interferogram

L3 Products

  • SME2 — Soil Moisture

To search for a different NISAR product, replace "GCOV" in the processingLevel field with the four-letter abbreviation for your product of interest.


4. Download a NISAR HDF5 file

4a. Search for NISAR data. For this examlpe, we will use a GCOV data.

import os
import asf_search as asf
from datetime import datetime
from getpass import getpass
from pathlib import Path

# authenticate with Earthdata Login
session = asf.ASFSession()
session.auth_with_creds(input('EDL Username'), getpass('EDL Password'))

# insert start and end dates. Note that dates and times are inclusive. 
start_date = datetime(2025, 12, 4)
end_date = datetime(2025, 12, 5)
area_of_interest = "POLYGON((40.9131 12.3904,41.8891 12.3904,41.8891 13.2454,40.9131 13.2454,40.9131 12.3904))" 

opts = asf.ASFSearchOptions(
    **{
        "maxResults": 250,                    # limit the number of returned results
        "intersectsWith": area_of_interest,   # spatial filter (WKT geometry)
        "start": start_date,                  # temporal filter (start)
        "end": end_date,                      # temporal filter (end)
        
        # to switch NISAR products, change the four letter abbreviation next to processingLevel
        "processingLevel": ["GCOV"],          # product type / processing level
        "dataset": ["NISAR"],                 # mission/dataset name
        "productionConfiguration": ["PR"],    # production config (e.g., provisional)
        "session": session,                   # use authenticated session from above
    }
)

response = asf.search(opts=opts)

pattern = r'^(?!.*QA_STATS).*'

h5_files = response.find_urls(extension='.h5', pattern=pattern, directAccess=False)
h5_files
EDL Username jwhite124
EDL Password ········
['https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_BETA_V1/NISAR_L2_PR_GCOV_006_172_A_008_2005_DHDH_A_20251204T024618_20251204T024653_X05007_N_F_J_001/NISAR_L2_PR_GCOV_006_172_A_008_2005_DHDH_A_20251204T024618_20251204T024653_X05007_N_F_J_001.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_BETA_V1/NISAR_L2_PR_GCOV_006_172_A_008_2005_DHDH_A_20251204T024618_20251204T024653_X05009_N_F_J_001/NISAR_L2_PR_GCOV_006_172_A_008_2005_DHDH_A_20251204T024618_20251204T024653_X05009_N_F_J_001.h5']

4b. Download the data

data_dir = Path.home() / "NISAR_data_access_example"
data_dir.mkdir(exist_ok=True)
print(f'data_dir: {data_dir}')

#download files
asf.download_urls(h5_files, data_dir, session=session, processes=4)
data_dir: /home/jovyan/NISAR_data_access_example

5. Opening NISAR Data with h5py

The h5py library allows you to access HDF5 files directly in Python. NISAR products are stored as hierarchical datasets, similar to folders and files.

In this example, we open a NISAR file, navigate to the metadata group, read the incidenceAngle dataset and print the shape.

First, we inspect the dataset shape without loading the data values into memory. Then, we load the full dataset using [:]. Finally, we read a smaller subset and calculate its mean.

Note: In h5py, accessing a dataset object does not load the data values into memory. Data are loaded when values are explicitly accessed, such as with [:] or slicing. Once sliced, the result is loaded into memory as a NumPy array.

5a. Inspect dataset without loading into memory

%%time

import h5py

h5_h5py = list(data_dir.glob("NISAR_L2_*_GCOV*.h5"))[0]

with h5py.File(h5_h5py, "r") as f:
    incidence = f["/science/LSAR/GCOV/metadata/radarGrid/incidenceAngle"]
    print("incidenceAngle shape:", incidence.shape)
incidenceAngle shape: (21, 680, 695)
CPU times: user 22.1 ms, sys: 0 ns, total: 22.1 ms
Wall time: 21 ms

5b. Full load: read dataset into memory

%%time

import h5py

h5_h5py = list(data_dir.glob("NISAR_L2_*_GCOV*.h5"))[0]

with h5py.File(h5_h5py, "r") as f:
    incidence = f["/science/LSAR/GCOV/metadata/radarGrid/incidenceAngle"][:]

print("incidenceAngle shape:", incidence.shape)
incidenceAngle shape: (21, 680, 695)
CPU times: user 135 ms, sys: 49.3 ms, total: 184 ms
Wall time: 183 ms

5c. Subset and compute mean

Note: The subset mean is used here only to demonstrate how data are loaded and processed. Because incidenceAngle is a 3D metadata grid, scientific interpretation should be done carefully, usually for a specific height level and spatial region.

%%time
# Subset load: read one height level and a small spatial subset, then compute a statistic

import h5py
import numpy as np

h5_h5py = list(data_dir.glob("NISAR_L2_*_GCOV*.h5"))[0]

with h5py.File(h5_h5py, "r") as f:
    incidence = f["/science/LSAR/GCOV/metadata/radarGrid/incidenceAngle"]

    subset = incidence[0, 0:100, 0:100]
    subset_mean = np.nanmean(subset)

print("subset mean:", subset_mean)
subset mean: 46.621464
CPU times: user 5.14 ms, sys: 3.12 ms, total: 8.25 ms
Wall time: 7.67 ms

6. Opening NISAR Data with xarray.Dataset and xarray.DataTree

The xarray package provides tools for working with labeled arrays. Here, we show two xarray data structures:

  • xarray.Dataset: useful when opening one specific group in a NISAR HDF5 file.

  • xarray.DataTree: useful when opening the full hierarchical file structure.

Both can support lazy loading workflows when opened with chunks={}.

6a. Opening NISAR Data with xarray.Dataset

Here, we open the NISAR metadata radarGrid group as an xarray.Dataset. This lets us access variables in the group, such as incidenceAngle, using shorter variable names.

We open the dataset with Dask chunking, chunks={}, which creates a Dask-backed xarray object. This allows operations to be queued without immediately loading the full array into memory. Although 8 MB chunks are generally recommended for larger NISAR direct-access workflows, the incidenceAngle dataset is small enough that the native chunk layout is sufficient.

For additional benchmarking and recommendations for NISAR direct-access workflows, see Henry Rodman’s Reading NISAR granules directly from S3.

Note that open_dataset only works for one group at a time. When accessing more than one group, use open_datatree.

# Ignore warnings
import warnings
warnings.filterwarnings("ignore")

import xarray as xr

h5_xarray = list(data_dir.glob("NISAR_L2_*_GCOV*.h5"))[0]

ds = xr.open_dataset(
    h5_xarray,
    group="/science/LSAR/GCOV/metadata/radarGrid",
    chunks={}
)

incidence = ds["incidenceAngle"]

print("incidenceAngle shape:", incidence.shape)
incidence
incidenceAngle shape: (21, 680, 695)
Loading...

Here, we select one height level and a small spatial subset, then calculate the mean. This operation is queued, but not computed yet.

%%time

subset_mean = (
    ds["incidenceAngle"]
    .isel(heightAboveEllipsoid=0, yCoordinates=slice(0, 100), xCoordinates=slice(0, 100))
    .mean()
)

subset_mean
CPU times: user 4.51 ms, sys: 0 ns, total: 4.51 ms
Wall time: 3.92 ms
Loading...

Calling .compute() triggers the actual read and calculation.

%%time

subset_mean_value = subset_mean.compute()

print("subset mean:", subset_mean_value.values)
subset mean: 46.621464
CPU times: user 92.7 ms, sys: 28.6 ms, total: 121 ms
Wall time: 121 ms
ds.close()

6b. Opening NISAR Data with xarray DataTree

An xarray.DataTree preserves the full hierarchical structure of the NISAR HDF5 file. This is useful when you want to work across multiple groups.

Here, we open the full file as a tree-like object and access the same incidenceAngle dataset through its group path.

# Ignore warnings
import warnings
warnings.filterwarnings("ignore")

import xarray as xr

h5_datatree = list(data_dir.glob("NISAR_L2_*_GCOV*.h5"))[0]

dt = xr.open_datatree(
    h5_datatree,
    engine="h5netcdf",
    chunks={}
)

incidence = dt["/science/LSAR/GCOV/metadata/radarGrid"]["incidenceAngle"]

print("incidenceAngle shape:", incidence.shape)
dt
incidenceAngle shape: (21, 680, 695)
Loading...
dt.close()

7. ISCE3

The NISAR product reader (part of ISCE3) provides a more complex interface for working with NISAR data. It understands the structure of NISAR products and includes built-in attributes and methods for accessing product information and image datasets.

Unlike h5py and xarray, which access datasets directly through the HDF5 structure, ISCE3 interacts with the data through class methods and member variables.

7a. Opening NISAR Metadata with ISCE3

In this example, we first access general product information, polarizations metadata, using reader member variables.

These values come from the product metadata, but are accessed differently than in the previous examples. Instead of navigating the file structure (as with h5py or xarray), ISCE3 exposes selected metadata through object attributes.

While some metadata can be accessed this way, many metadata datasets (such as incidenceAngle) are not available through a simple or consistent interface in ISCE3. For this reason, h5py or xarray may be more ideal for accessing metadata.

from nisar.products.readers import open_product

h5_isce3 = list(data_dir.glob("NISAR_L2_*.h5"))[0]

product = open_product(h5_isce3)

print("polarizations:", product.polarizations)
polarizations: {'A': ['HH', 'HV'], 'B': ['HH', 'HV']}

7b. Using ISCE3 to read image data

Next, we use the ISCE3 reader to access an image dataset using the getImageDataset() method.

This method provides a convenient way to access image layers (such as polarization datasets), which are central to many SAR and NISAR workflows. This type of access is a more common use of ISCE3, as it is designed to work with image data and SAR-specific processing rather than general metadata retrieval.

from nisar.products.readers import open_product

h5_hvhv = list(data_dir.glob("NISAR_L2_*_GCOV*.h5"))[0]

hvhv_data = open_product(h5_hvhv)

hvhv = hvhv_data.getImageDataset(frequency="A", polarization="HVHV")

print("HVHV shape:", hvhv[:, :].shape)
HVHV shape: (16704, 17064)

8. Summary

You have now three methods and examples for opening NISAR data.


9. Resources and references

Authors: Julia White, Alex Lewandowski