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.

Search and Stream NISAR GCOV Data with asf_search


asf_search is an open source Python package for searching SAR data archived at ASF. This notebook demonstrates how to search NISAR GCOV with asf_search, stream them directly over HTTPS or from S3 storage with s3fs, and load them into xarray data structures.

NISAR data products can be very large. It may be helpful to access the data directly from their S3 storage. This allows you to lazily load data into xarray data structures, subset, and perform operations on them with xarray, and then only save the data you need to memory. This avoids downloading many large products to a storage volume, only to subset and delete most of them. The caveat is that you must have enough RAM to hold your final subset and also run your workflow.


Overview

  1. Prerequisites

  2. Search for data

  3. Load a single GCOV product with HTTPS

  4. Load a single GCOV product from the S3 bucket

  5. Load multiple GCOV Products at once

  6. Stream a time series

  7. Close open files

  8. Summary

  9. Resources and references


1. Prerequisites

  • Rough Notebook Time Estimate: 10 minutes


Use asf_search to find GCOV data.

2a. Perform an asf_search.search() to identify your desired product URLs

Found 6 GCOV products:
['https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_021_172_A_008_2005_DHDH_A_20260602T024621_20260602T024656_P05023_N_F_J_001/NISAR_L2_PR_GCOV_021_172_A_008_2005_DHDH_A_20260602T024621_20260602T024656_P05023_N_F_J_001.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_022_172_A_008_2005_DHDH_A_20260614T024620_20260614T024655_P05023_N_F_J_001/NISAR_L2_PR_GCOV_022_172_A_008_2005_DHDH_A_20260614T024620_20260614T024655_P05023_N_F_J_001.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_023_172_A_008_2005_DHDH_A_20260626T024620_20260626T024654_P05023_N_F_J_001/NISAR_L2_PR_GCOV_023_172_A_008_2005_DHDH_A_20260626T024620_20260626T024654_P05023_N_F_J_001.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_023_172_A_008_2005_DHDH_A_20260626T024620_20260626T024654_P05023_N_F_J_002/NISAR_L2_PR_GCOV_023_172_A_008_2005_DHDH_A_20260626T024620_20260626T024654_P05023_N_F_J_002.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_024_172_A_008_2005_DHDH_A_20260708T024619_20260708T024654_P05023_N_F_J_001/NISAR_L2_PR_GCOV_024_172_A_008_2005_DHDH_A_20260708T024619_20260708T024654_P05023_N_F_J_001.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_025_172_A_008_2005_DHDH_A_20260720T024618_20260720T024653_P05023_N_F_J_001/NISAR_L2_PR_GCOV_025_172_A_008_2005_DHDH_A_20260720T024618_20260720T024653_P05023_N_F_J_001.h5']

2b. Retain only the URL for the most recent version of each product in the search results

Data is occasionally re-released with an updated version. Versions are recorded as a Composite Release Identifier (CRID) in a product’s filename. We can use the CRID to retain only the most recent version of each product in the list of URLs.

Retained 5 GCOV products:
['https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_021_172_A_008_2005_DHDH_A_20260602T024621_20260602T024656_P05023_N_F_J_001/NISAR_L2_PR_GCOV_021_172_A_008_2005_DHDH_A_20260602T024621_20260602T024656_P05023_N_F_J_001.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_022_172_A_008_2005_DHDH_A_20260614T024620_20260614T024655_P05023_N_F_J_001/NISAR_L2_PR_GCOV_022_172_A_008_2005_DHDH_A_20260614T024620_20260614T024655_P05023_N_F_J_001.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_023_172_A_008_2005_DHDH_A_20260626T024620_20260626T024654_P05023_N_F_J_001/NISAR_L2_PR_GCOV_023_172_A_008_2005_DHDH_A_20260626T024620_20260626T024654_P05023_N_F_J_001.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_024_172_A_008_2005_DHDH_A_20260708T024619_20260708T024654_P05023_N_F_J_001/NISAR_L2_PR_GCOV_024_172_A_008_2005_DHDH_A_20260708T024619_20260708T024654_P05023_N_F_J_001.h5', 'https://nisar.asf.earthdatacloud.nasa.gov/NISAR/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_025_172_A_008_2005_DHDH_A_20260720T024618_20260720T024653_P05023_N_F_J_001/NISAR_L2_PR_GCOV_025_172_A_008_2005_DHDH_A_20260720T024618_20260720T024653_P05023_N_F_J_001.h5']

2c. Provide your Earthdata Login (EDL) Bearer Token

Both HTTPS and S3 access require an EDL Bearer Token

Image of the Earthdata Login Generate Token web page

View or generate a Bearer Token in “Generate Token” tab of the Profile page in your Earthdata Login account: https://urs.earthdata.nasa.gov/profile

Enter your EDL Bearer Token ········

3. Load a single GCOV product with HTTPS

This example loads the data in a Python with statement.

3a. Open a GCOV file in a with block and compute the mean of an HHHH spatial subset

Note that any computation on the data (in this case a subset mean) must be performed inside the with block.

subset_hhhh_mean: 0.08685851097106934

CPU times: user 2.72 s, sys: 901 ms, total: 3.62 s
Wall time: 1min 5s

4. Load a single GCOV product from the S3 bucket

This example loads the data in a Python with statement.

4a. Convert the hdf5 URLs into S3 urls

['s3://sds-n-cumulus-prod-nisar-products/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_021_172_A_008_2005_DHDH_A_20260602T024621_20260602T024656_P05023_N_F_J_001/NISAR_L2_PR_GCOV_021_172_A_008_2005_DHDH_A_20260602T024621_20260602T024656_P05023_N_F_J_001.h5', 's3://sds-n-cumulus-prod-nisar-products/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_022_172_A_008_2005_DHDH_A_20260614T024620_20260614T024655_P05023_N_F_J_001/NISAR_L2_PR_GCOV_022_172_A_008_2005_DHDH_A_20260614T024620_20260614T024655_P05023_N_F_J_001.h5', 's3://sds-n-cumulus-prod-nisar-products/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_023_172_A_008_2005_DHDH_A_20260626T024620_20260626T024654_P05023_N_F_J_001/NISAR_L2_PR_GCOV_023_172_A_008_2005_DHDH_A_20260626T024620_20260626T024654_P05023_N_F_J_001.h5', 's3://sds-n-cumulus-prod-nisar-products/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_024_172_A_008_2005_DHDH_A_20260708T024619_20260708T024654_P05023_N_F_J_001/NISAR_L2_PR_GCOV_024_172_A_008_2005_DHDH_A_20260708T024619_20260708T024654_P05023_N_F_J_001.h5', 's3://sds-n-cumulus-prod-nisar-products/NISAR_L2_GCOV_PROVISIONAL_V1/NISAR_L2_PR_GCOV_025_172_A_008_2005_DHDH_A_20260720T024618_20260720T024653_P05023_N_F_J_001/NISAR_L2_PR_GCOV_025_172_A_008_2005_DHDH_A_20260720T024618_20260720T024653_P05023_N_F_J_001.h5']

4b. Use your EDL Bearer Token to get S3 bucket access credentials

The S3 credentials acquired below expire after 1 hour.

4c. Open a GCOV file in a with block and compute the mean of an HHHH spatial subset

Notes on Chunking

This notebook utilizes Dask chunking to break large arrays into smaller blocks. Chunking allows users to inspect and process subsets of a dataset without loading entire arrays into memory at once. This notebook uses a chunk size of 8 MB.

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

subset_hhhh_mean: 0.08685851097106934

CPU times: user 1.04 s, sys: 122 ms, total: 1.16 s
Wall time: 10.2 s

4d. View the DataTree

You can look at the DataTree outside the with block, but it only contains pointers to the data and the file is closed, so you can no longer access any of the data values to which it points

Loading...

4e. Try (and fail) to compute a value in the DataTree

The file was closed upon exiting the with block so trying to compute a value from the DataTree will fail with a ValueError: I/O operation on closed file.

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[15], line 1
----> 1 dt.compute()

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/datatree.py:2511, in DataTree.compute(self, **kwargs)
   2487 """Manually trigger loading and/or computation of this datatree's data
   2488 from disk or a remote source into memory and return a new datatree.
   2489 Unlike load, the original datatree is left unaltered.
   (...)   2508 dask.compute
   2509 """
   2510 new = self.copy(deep=False)
-> 2511 return new.load(**kwargs)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/datatree.py:2469, in DataTree.load(self, **kwargs)
   2466 chunkmanager = get_chunked_array_type(*flat_lazy_data.values())
   2468 # evaluate all the chunked arrays simultaneously
-> 2469 evaluated_data: tuple[np.ndarray[Any, Any], ...] = chunkmanager.compute(
   2470     *flat_lazy_data.values(), **kwargs
   2471 )
   2473 for (path, var_name), data in zip(
   2474     flat_lazy_data, evaluated_data, strict=False
   2475 ):
   2476     self[path].variables[var_name].data = data

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/namedarray/daskmanager.py:85, in DaskManager.compute(self, *data, **kwargs)
     80 def compute(
     81     self, *data: Any, **kwargs: Any
     82 ) -> tuple[np.ndarray[Any, _DType_co], ...]:
     83     from dask.array import compute
---> 85     return compute(*data, **kwargs)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/dask/base.py:686, in compute(traverse, optimize_graph, scheduler, get, *args, **kwargs)
    683     expr = expr.optimize()
    684     keys = list(flatten(expr.__dask_keys__()))
--> 686     results = schedule(expr, keys, **kwargs)
    688 return repack(results)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:686, in ImplicitToExplicitIndexingAdapter.__array__(self, dtype, copy)
    682 def __array__(
    683     self, dtype: DTypeLike | None = None, /, *, copy: bool | None = None
    684 ) -> np.ndarray:
    685     if Version(np.__version__) >= Version("2.0.0"):
--> 686         return np.asarray(self.get_duck_array(), dtype=dtype, copy=copy)
    687     else:
    688         return np.asarray(self.get_duck_array(), dtype=dtype)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:691, in ImplicitToExplicitIndexingAdapter.get_duck_array(self)
    690 def get_duck_array(self):
--> 691     return self.array.get_duck_array()

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:924, in CopyOnWriteArray.get_duck_array(self)
    923 def get_duck_array(self):
--> 924     return self.array.get_duck_array()

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:764, in LazilyIndexedArray.get_duck_array(self)
    761 from xarray.backends.common import BackendArray
    763 if isinstance(self.array, BackendArray):
--> 764     array = self.array[self.key]
    765 else:
    766     array = apply_indexer(self.array, self.key)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/backends/h5netcdf_.py:67, in H5NetCDFArrayWrapper.__getitem__(self, key)
     66 def __getitem__(self, key):
---> 67     return indexing.explicit_indexing_adapter(
     68         key, self.shape, indexing.IndexingSupport.OUTER_1VECTOR, self._getitem
     69     )

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:1156, in explicit_indexing_adapter(key, shape, indexing_support, raw_indexing_method)
   1134 """Support explicit indexing by delegating to a raw indexing method.
   1135 
   1136 Outer and/or vectorized indexers are supported by indexing a second time
   (...)   1153 Indexing result, in the form of a duck numpy-array.
   1154 """
   1155 raw_key, numpy_indices = decompose_indexer(key, shape, indexing_support)
-> 1156 result = raw_indexing_method(raw_key.tuple)
   1157 if numpy_indices.tuple:
   1158     # index the loaded duck array
   1159     indexable = as_indexable(result)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/backends/h5netcdf_.py:74, in H5NetCDFArrayWrapper._getitem(self, key)
     72 with self.datastore.lock:
     73     array = self.get_array(needs_lock=False)
---> 74     return array[key]

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/h5netcdf/core.py:729, in BaseVariable.__getitem__(self, key)
    727     return h5ds[key].view(view)
    728 else:
--> 729     return h5ds[key]

File h5py/_objects.pyx:54, in h5py._objects.with_phil.wrapper()
---> 54 'Could not get source, probably due dynamically evaluated source code.'

File h5py/_objects.pyx:55, in h5py._objects.with_phil.wrapper()
---> 55 'Could not get source, probably due dynamically evaluated source code.'

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/h5py/_hl/dataset.py:872, in Dataset.__getitem__(self, args, new_dtype)
    870 if self._fast_read_ok and (new_dtype is None):
    871     try:
--> 872         return self._fast_reader.read(args)
    873     except TypeError:
    874         pass  # Fall back to Python read pathway below

File h5py/_objects.pyx:54, in h5py._objects.with_phil.wrapper()
---> 54 'Could not get source, probably due dynamically evaluated source code.'

File h5py/_objects.pyx:55, in h5py._objects.with_phil.wrapper()
---> 55 'Could not get source, probably due dynamically evaluated source code.'

File h5py/_selector.pyx:393, in h5py._selector.Reader.read()
--> 393 'Could not get source, probably due dynamically evaluated source code.'

File h5py/h5fd.pyx:159, in h5py.h5fd.H5FD_fileobj_read()
--> 159 'Could not get source, probably due dynamically evaluated source code.'

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/fsspec/spec.py:2143, in AbstractBufferedFile.readinto(self, b)
   2138 """mirrors builtin file's readinto method
   2139 
   2140 https://docs.python.org/3/library/io.html#io.RawIOBase.readinto
   2141 """
   2142 out = memoryview(b).cast("B")
-> 2143 data = self.read(out.nbytes)
   2144 out[: len(data)] = data
   2145 return len(data)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/fsspec/spec.py:2121, in AbstractBufferedFile.read(self, length)
   2119     length = self.size - self.loc
   2120 if self.closed:
-> 2121     raise ValueError("I/O operation on closed file.")
   2122 if length == 0:
   2123     # don't even bother calling fetch
   2124     return b""

ValueError: I/O operation on closed file.

However, subset_hhhh_mean was computed and saved to memory inside the with block, so we can still see its value


5. Load multiple GCOV Products at once

5a. Iterate through a list of HDF5 S3 bucket URLs, and open the /science/LSAR/GCOV/grids/frequencyA for each

This leaves the files open for later use, which means you should manually close them when finished in order to prevent memory leaks.

CPU times: user 1.06 s, sys: 336 ms, total: 1.4 s
Wall time: 3.78 s

5b. Since the files remain open, we can access still access them and perform computations on their contents

Iterate through the DataTrees, calculating subset HHHH mean values

0.08685851097106934
0.08610351383686066
0.08567451685667038
0.08343092352151871
0.08564693480730057

6. Stream a time series

Use the multiple files we opened in Step 5 to create a GCOV time series

6a. Define a function to extract datetimes for a time dimension

6b. Create a list of datetimes for a time dimension

[datetime.datetime(2026, 6, 2, 2, 46, 21), datetime.datetime(2026, 6, 14, 2, 46, 20), datetime.datetime(2026, 6, 26, 2, 46, 20), datetime.datetime(2026, 7, 8, 2, 46, 19), datetime.datetime(2026, 7, 20, 2, 46, 18)]

6c. Create an xarray.DataArray containing a time dimension for each open GCOV group

Loading...
FrozenMappingWarningOnValuesAccess({'time': 1, 'yCoordinates': 16704, 'xCoordinates': 17064, 'phony_dim_0': 2})
FrozenMappingWarningOnValuesAccess({'time': 1, 'yCoordinates': 16704, 'xCoordinates': 17064, 'phony_dim_0': 2})
FrozenMappingWarningOnValuesAccess({'time': 1, 'yCoordinates': 16704, 'xCoordinates': 17064, 'phony_dim_0': 2})
FrozenMappingWarningOnValuesAccess({'time': 1, 'yCoordinates': 16704, 'xCoordinates': 17064, 'phony_dim_0': 2})
FrozenMappingWarningOnValuesAccess({'time': 1, 'yCoordinates': 16704, 'xCoordinates': 17064, 'phony_dim_0': 2})

6d. Concatenate the xarray.DataArrays into a single xarray.Dataset time series

Loading...

7. Close open files

Close all open files to prevent memory leaks.

7a. Close the files

7b. With closed files, we can no longer compute values in the xarray data structures that we have created

The cell below will return a ValueError: I/O operation on closed file.

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[24], line 1
----> 1 ts.compute()

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/dataset.py:803, in Dataset.compute(self, **kwargs)
    799         DataArray.compute
    800         Variable.compute
    801         """
    802         new = self.copy(deep=False)
--> 803         return new.load(**kwargs)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/dataset.py:569, in Dataset.load(self, **kwargs)
    565         if chunked_data:
    566             chunkmanager = get_chunked_array_type(*chunked_data.values())
    567 
    568             # evaluate all the chunked arrays simultaneously
--> 569             evaluated_data: tuple[np.ndarray[Any, Any], ...] = chunkmanager.compute(
    570                 *chunked_data.values(), **kwargs
    571             )
    572 

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/namedarray/daskmanager.py:85, in DaskManager.compute(self, *data, **kwargs)
     80 def compute(
     81     self, *data: Any, **kwargs: Any
     82 ) -> tuple[np.ndarray[Any, _DType_co], ...]:
     83     from dask.array import compute
---> 85     return compute(*data, **kwargs)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/dask/base.py:686, in compute(traverse, optimize_graph, scheduler, get, *args, **kwargs)
    683     expr = expr.optimize()
    684     keys = list(flatten(expr.__dask_keys__()))
--> 686     results = schedule(expr, keys, **kwargs)
    688 return repack(results)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:686, in ImplicitToExplicitIndexingAdapter.__array__(self, dtype, copy)
    682 def __array__(
    683     self, dtype: DTypeLike | None = None, /, *, copy: bool | None = None
    684 ) -> np.ndarray:
    685     if Version(np.__version__) >= Version("2.0.0"):
--> 686         return np.asarray(self.get_duck_array(), dtype=dtype, copy=copy)
    687     else:
    688         return np.asarray(self.get_duck_array(), dtype=dtype)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:691, in ImplicitToExplicitIndexingAdapter.get_duck_array(self)
    690 def get_duck_array(self):
--> 691     return self.array.get_duck_array()

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:924, in CopyOnWriteArray.get_duck_array(self)
    923 def get_duck_array(self):
--> 924     return self.array.get_duck_array()

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:764, in LazilyIndexedArray.get_duck_array(self)
    761 from xarray.backends.common import BackendArray
    763 if isinstance(self.array, BackendArray):
--> 764     array = self.array[self.key]
    765 else:
    766     array = apply_indexer(self.array, self.key)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/backends/h5netcdf_.py:67, in H5NetCDFArrayWrapper.__getitem__(self, key)
     66 def __getitem__(self, key):
---> 67     return indexing.explicit_indexing_adapter(
     68         key, self.shape, indexing.IndexingSupport.OUTER_1VECTOR, self._getitem
     69     )

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/core/indexing.py:1156, in explicit_indexing_adapter(key, shape, indexing_support, raw_indexing_method)
   1134 """Support explicit indexing by delegating to a raw indexing method.
   1135 
   1136 Outer and/or vectorized indexers are supported by indexing a second time
   (...)   1153 Indexing result, in the form of a duck numpy-array.
   1154 """
   1155 raw_key, numpy_indices = decompose_indexer(key, shape, indexing_support)
-> 1156 result = raw_indexing_method(raw_key.tuple)
   1157 if numpy_indices.tuple:
   1158     # index the loaded duck array
   1159     indexable = as_indexable(result)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/xarray/backends/h5netcdf_.py:74, in H5NetCDFArrayWrapper._getitem(self, key)
     72 with self.datastore.lock:
     73     array = self.get_array(needs_lock=False)
---> 74     return array[key]

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/h5netcdf/core.py:729, in BaseVariable.__getitem__(self, key)
    727     return h5ds[key].view(view)
    728 else:
--> 729     return h5ds[key]

File h5py/_objects.pyx:54, in h5py._objects.with_phil.wrapper()
---> 54 'Could not get source, probably due dynamically evaluated source code.'

File h5py/_objects.pyx:55, in h5py._objects.with_phil.wrapper()
---> 55 'Could not get source, probably due dynamically evaluated source code.'

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/h5py/_hl/dataset.py:872, in Dataset.__getitem__(self, args, new_dtype)
    870 if self._fast_read_ok and (new_dtype is None):
    871     try:
--> 872         return self._fast_reader.read(args)
    873     except TypeError:
    874         pass  # Fall back to Python read pathway below

File h5py/_objects.pyx:54, in h5py._objects.with_phil.wrapper()
---> 54 'Could not get source, probably due dynamically evaluated source code.'

File h5py/_objects.pyx:55, in h5py._objects.with_phil.wrapper()
---> 55 'Could not get source, probably due dynamically evaluated source code.'

File h5py/_selector.pyx:393, in h5py._selector.Reader.read()
--> 393 'Could not get source, probably due dynamically evaluated source code.'

File h5py/h5fd.pyx:159, in h5py.h5fd.H5FD_fileobj_read()
--> 159 'Could not get source, probably due dynamically evaluated source code.'

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/fsspec/spec.py:2143, in AbstractBufferedFile.readinto(self, b)
   2138 """mirrors builtin file's readinto method
   2139 
   2140 https://docs.python.org/3/library/io.html#io.RawIOBase.readinto
   2141 """
   2142 out = memoryview(b).cast("B")
-> 2143 data = self.read(out.nbytes)
   2144 out[: len(data)] = data
   2145 return len(data)

File ~/NISAR_Cookbook/.pixi/envs/isce3/lib/python3.13/site-packages/fsspec/spec.py:2121, in AbstractBufferedFile.read(self, length)
   2119     length = self.size - self.loc
   2120 if self.closed:
-> 2121     raise ValueError("I/O operation on closed file.")
   2122 if length == 0:
   2123     # don't even bother calling fetch
   2124     return b""

ValueError: I/O operation on closed file.

8. Summary

You now have the tools and knowledge that you need to search with asf_search, generate temporary S3 bucket credentials from an Earthdata Login Bearer Token, stream data from S3 with s3fs, and load them into xarray data structures.


9. Resources and references

Author: Alex Lewandowski