Tutorial for simulated NISAR data access, reading, and visualizing amplitude and phase.

In the following tutorial, we are going to look at how to access and read simulated-NISAR data which is available from NISAR mission. This mission is supposed to be launched in 2024. At this time we are using modified UAVSAR data to simulate the data that we will get from NISAR satellite.

Before we start any work, we will need to prepare our Jupyter workspace with the necessary python packages. In this tutorial we rely on - h5py, numpy, glob, os, h5glance, osgeo, and matplotlib.

You might have some or all packages already installed. Follow the instructions below to check and install the packages required for this tutorial. The block below will check if your packages are available and install them if they are not.

[2]:
# ! pip install h5py numpy glob h5glance osgeo matplotlib

We also require that you have the gdal package installed out of the Jupyter environment to use: gdal_translate and gdalinfo. If on Mac OS, you might need to install the xcode package before being able to install gdal.

To install gdal outside the Jupyter environment, please follow the instructions here as it will vary by the OS you are using: https://gdal.org/download.html

Import installed packages to read the NISAR h5 files and look at the data structure.

[35]:
import h5py
import numpy as np
import glob
import os
from h5glance import H5Glance

NISAR data can be downloaded from https://uavsar.jpl.nasa.gov/cgi-bin/data.pl

At the time of this tutorial, there are 21033 NISAR products available through the above link. There are a few ways to download data that we can use. We can directly download an SLC file or we can download an H5 file and translate it to SLC to work with this tutorial. In this tutorial, we demonstrate how to get an H5 file, translate it to SLC and use it. Users can alternatively directly download SLC files.

To select a data file from the UAVSAR website, check the Simulated NISAR under specialized products. This will show the flight lines available on the map and list them to the right of the map.

UAVSAR NISAR Webpage

Click on one of the flight lines of interest or select them from the list.

|nisar\_select\_flight\_line.png|

Then click on “View”, next to the selected line from the list. This will open a data product page with optional components and instructions to download data in various formats. We will use the “wget” method as specified at the bottom of this page. Be mindful that these H5 files are huge and it will take some time to download on slower internet connections.

[36]:
!wget https://downloaduav.jpl.nasa.gov/Release2d/SanAnd_05518_18072_003_181002_L090_CX_03/SanAnd_05518_18072_003_181002_L090_CX_129_03.h5
--2023-03-08 17:36:30--  https://downloaduav.jpl.nasa.gov/Release2d/SanAnd_05518_18072_003_181002_L090_CX_03/SanAnd_05518_18072_003_181002_L090_CX_129_03.h5
Resolving downloaduav.jpl.nasa.gov (downloaduav.jpl.nasa.gov)... 137.78.249.121
Connecting to downloaduav.jpl.nasa.gov (downloaduav.jpl.nasa.gov)|137.78.249.121|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://uavsar.jpl.nasa.gov/Release2d/SanAnd_05518_18072_003_181002_L090_CX_03/SanAnd_05518_18072_003_181002_L090_CX_129_03.h5 [following]
--2023-03-08 17:36:31--  https://uavsar.jpl.nasa.gov/Release2d/SanAnd_05518_18072_003_181002_L090_CX_03/SanAnd_05518_18072_003_181002_L090_CX_129_03.h5
Resolving uavsar.jpl.nasa.gov (uavsar.jpl.nasa.gov)... 137.78.249.121
Connecting to uavsar.jpl.nasa.gov (uavsar.jpl.nasa.gov)|137.78.249.121|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3016099668 (2.8G)
Saving to: ‘SanAnd_05518_18072_003_181002_L090_CX_129_03.h5’

SanAnd_05518_18072_ 100%[===================>]   2.81G  56.1MB/s    in 54s

2023-03-08 17:37:44 (52.8 MB/s) - ‘SanAnd_05518_18072_003_181002_L090_CX_129_03.h5’ saved [3016099668/3016099668]

Once downloaded, the files will be saved in your current working directory.

[37]:
os.getcwd()
[37]:
'/projects/my-private-bucket/Nisar'

If you downloaded multiple H5 files, initialize an empty variable to store the names of all H5 files in the directory.

[38]:
nisar_list = []
[39]:
for file in glob.glob("*.h5"):
    nisar_list.append(file)
    print(file)
SanAnd_05518_18072_003_181002_L090_CX_129_03.h5

Explore the structure of NISAR *.H5 file using H5glance

[40]:
H5Glance(nisar_list[0])
[40]:
              • angularVelocity [📋]: 100 × 3 entries, dtype: float64
              • attitudeType [📋]: scalar entries, dtype: 10-byte ASCII string
              • eulerAngles [📋]: 100 × 3 entries, dtype: float64
              • quaternions [📋]: 100 × 4 entries, dtype: float64
              • time [📋]: 100 entries, dtype: float64
                  • elevationAntennaPattern [📋]: 603 × 225 entries, dtype: (r: float32, i: float32)
                  • nes0 [📋]: 603 × 225 entries, dtype: float32
                  • elevationAntennaPattern [📋]: 603 × 225 entries, dtype: (r: float32, i: float32)
                  • nes0 [📋]: 603 × 225 entries, dtype: float32
                  • elevationAntennaPattern [📋]: 603 × 225 entries, dtype: (r: float32, i: float32)
                  • nes0 [📋]: 603 × 225 entries, dtype: float32
                  • elevationAntennaPattern [📋]: 603 × 225 entries, dtype: (r: float32, i: float32)
                  • nes0 [📋]: 603 × 225 entries, dtype: float32
                  • elevationAntennaPattern [📋]: 603 × 225 entries, dtype: (r: float32, i: float32)
                  • nes0 [📋]: 603 × 225 entries, dtype: float32
                  • elevationAntennaPattern [📋]: 603 × 225 entries, dtype: (r: float32, i: float32)
                  • nes0 [📋]: 603 × 225 entries, dtype: float32
                  • elevationAntennaPattern [📋]: 603 × 225 entries, dtype: (r: float32, i: float32)
                  • nes0 [📋]: 603 × 225 entries, dtype: float32
                  • elevationAntennaPattern [📋]: 603 × 225 entries, dtype: (r: float32, i: float32)
                  • nes0 [📋]: 603 × 225 entries, dtype: float32
                • beta0 [📋]: 603 × 225 entries, dtype: float32
                • gamma0 [📋]: 603 × 225 entries, dtype: float32
                • sigma0 [📋]: 603 × 225 entries, dtype: float32
              • slantRange [📋]: 225 entries, dtype: float64
              • zeroDopplerTime [📋]: 603 entries, dtype: float64
              • alongTrackUnitVectorX [📋]: 6 × 603 × 225 entries, dtype: float32
              • alongTrackUnitVectorY [📋]: 6 × 603 × 225 entries, dtype: float32
              • coordinateX [📋]: 6 × 603 × 225 entries, dtype: float64
              • coordinateY [📋]: 6 × 603 × 225 entries, dtype: float64
              • elevationAngle [📋]: 6 × 603 × 225 entries, dtype: float32
              • epsg [📋]: scalar entries, dtype: int32
              • groundTrackVelocity [📋]: 6 × 603 × 225 entries, dtype: float32
              • heightAboveEllipsoid [📋]: 6 entries, dtype: float64
              • incidenceAngle [📋]: 6 × 603 × 225 entries, dtype: float32
              • losUnitVectorX [📋]: 6 × 603 × 225 entries, dtype: float32
              • losUnitVectorY [📋]: 6 × 603 × 225 entries, dtype: float32
              • slantRange [📋]: 225 entries, dtype: float64
              • zeroDopplerTime [📋]: 603 entries, dtype: float64
              • acceleration [📋]: 100 × 3 entries, dtype: float64
              • orbitType [📋]: scalar entries, dtype: 10-byte ASCII string
              • position [📋]: 100 × 3 entries, dtype: float64
              • time [📋]: 100 entries, dtype: float64
              • velocity [📋]: 100 × 3 entries, dtype: float64
                • ISCEVersion [📋]: scalar entries, dtype: 27-byte ASCII string
                • SWSTCorrection [📋]: scalar entries, dtype: 27-byte ASCII string
                • azimuthCompression [📋]: scalar entries, dtype: 27-byte ASCII string
                • azimuthPresumming [📋]: scalar entries, dtype: 27-byte ASCII string
                • dopplerCentroidEstimation [📋]: scalar entries, dtype: 27-byte ASCII string
                • driftCompensator [📋]: scalar entries, dtype: 27-byte ASCII string
                • elevationAntennaPatternCorrection [📋]: scalar entries, dtype: 27-byte ASCII string
                • internalCalibration [📋]: scalar entries, dtype: 27-byte ASCII string
                • patchProcessing [📋]: scalar entries, dtype: 27-byte ASCII string
                • postProcessing [📋]: scalar entries, dtype: 27-byte ASCII string
                • rangeCellMigration [📋]: scalar entries, dtype: 27-byte ASCII string
                • rangeCompression [📋]: scalar entries, dtype: 27-byte ASCII string
                • rangeDependentGainCorrection [📋]: scalar entries, dtype: 27-byte ASCII string
                • rangeReferenceFunctionGenerator [📋]: scalar entries, dtype: 27-byte ASCII string
                • rangeSpreadingLossCorrection [📋]: scalar entries, dtype: 27-byte ASCII string
                • secondaryRangeCompression [📋]: scalar entries, dtype: 27-byte ASCII string
                • attitudeFiles [📋]: 3 entries, dtype: 5-byte ASCII string
                • auxcalFiles [📋]: 5 entries, dtype: 7-byte ASCII string
                • configFiles [📋]: 7 entries, dtype: 11-byte ASCII string
                • demFiles [📋]: 11 entries, dtype: 13-byte ASCII string
                • l0bGranules [📋]: 23 entries, dtype: 29-byte ASCII string
                • orbitFiles [📋]: 29 entries, dtype: 3-byte ASCII string
                  • azimuthFMRate [📋]: 603 × 225 entries, dtype: float64
                  • dopplerCentroid [📋]: 603 × 225 entries, dtype: float64
                  • azimuthFMRate [📋]: 603 × 225 entries, dtype: float64
                  • dopplerCentroid [📋]: 603 × 225 entries, dtype: float64
                • azimuthChirpWeighting [📋]: 256 entries, dtype: float32
                • effectiveVelocity [📋]: 603 × 225 entries, dtype: float64
                • rangeChirpWeighting [📋]: 256 entries, dtype: float32
                • referenceTerrainHeight [📋]: 603 entries, dtype: float32
                • slantRange [📋]: 225 entries, dtype: float64
                • zeroDopplerTime [📋]: 603 entries, dtype: float64
              • HH [📋]: 26678 × 2640 entries, dtype: (r: float32, i: float32)
              • HV [📋]: 26678 × 2640 entries, dtype: (r: float32, i: float32)
              • VH [📋]: 26678 × 2640 entries, dtype: (r: float32, i: float32)
              • VV [📋]: 26678 × 2640 entries, dtype: (r: float32, i: float32)
              • acquiredCenterFrequency [📋]: scalar entries, dtype: float64
              • acquiredRangeBandwidth [📋]: scalar entries, dtype: float64
              • listOfPolarizations [📋]: 4 entries, dtype: 2-byte ASCII string
              • nominalAcquisitionPRF [📋]: scalar entries, dtype: float64
              • numberOfSubSwaths [📋]: scalar entries, dtype: uint8
              • processedAzimuthBandwidth [📋]: scalar entries, dtype: float64
              • processedCenterFrequency [📋]: scalar entries, dtype: float64
              • processedRangeBandwidth [📋]: scalar entries, dtype: float64
              • sceneCenterAlongTrackSpacing [📋]: scalar entries, dtype: float64
              • sceneCenterGroundRangeSpacing [📋]: scalar entries, dtype: float64
              • slantRange [📋]: 2640 entries, dtype: float64
              • slantRangeSpacing [📋]: scalar entries, dtype: float64
              • validSamplesSubSwath1 [📋]: 26678 × 2 entries, dtype: uint16
              • HH [📋]: 26678 × 660 entries, dtype: (r: float32, i: float32)
              • HV [📋]: 26678 × 660 entries, dtype: (r: float32, i: float32)
              • VH [📋]: 26678 × 660 entries, dtype: (r: float32, i: float32)
              • VV [📋]: 26678 × 660 entries, dtype: (r: float32, i: float32)
              • acquiredCenterFrequency [📋]: scalar entries, dtype: float64
              • acquiredRangeBandwidth [📋]: scalar entries, dtype: float64
              • listOfPolarizations [📋]: 4 entries, dtype: 2-byte ASCII string
              • nominalAcquisitionPRF [📋]: scalar entries, dtype: float64
              • numberOfSubSwaths [📋]: scalar entries, dtype: uint8
              • processedAzimuthBandwidth [📋]: scalar entries, dtype: float64
              • processedCenterFrequency [📋]: scalar entries, dtype: float64
              • processedRangeBandwidth [📋]: scalar entries, dtype: float64
              • sceneCenterAlongTrackSpacing [📋]: scalar entries, dtype: float64
              • sceneCenterGroundRangeSpacing [📋]: scalar entries, dtype: float64
              • slantRange [📋]: 660 entries, dtype: float64
              • slantRangeSpacing [📋]: scalar entries, dtype: float64
              • validSamplesSubSwath1 [📋]: 26678 × 2 entries, dtype: uint16
            • zeroDopplerTime [📋]: 26678 entries, dtype: float64
            • zeroDopplerTimeSpacing [📋]: scalar entries, dtype: float64
          • absoluteOrbitNumber [📋]: scalar entries, dtype: uint32
          • boundingPolygon [📋]: scalar entries, dtype: 95-byte ASCII string
          • cycleNumber [📋]: scalar entries, dtype: 1-byte ASCII string
          • diagnosticModeFlag [📋]: scalar entries, dtype: 11-byte ASCII string
          • frameNumber [📋]: scalar entries, dtype: uint16
          • isUrgentObservation [📋]: 5 entries, dtype: 5-byte ASCII string
          • listOfFrequencies [📋]: 2 entries, dtype: 2-byte ASCII string
          • lookDirection [📋]: scalar entries, dtype: 19-byte ASCII string
          • missionId [📋]: scalar entries, dtype: 13-byte ASCII string
          • orbitPassDirection [📋]: scalar entries, dtype: 23-byte ASCII string
          • plannedDatatakeId [📋]: 3 entries, dtype: 29-byte ASCII string
          • plannedObservationId [📋]: 5 entries, dtype: 3-byte ASCII string
          • processingType [📋]: scalar entries, dtype: 17-byte ASCII string
          • productType [📋]: scalar entries, dtype: 17-byte ASCII string
          • productVersion [📋]: scalar entries, dtype: 16-byte ASCII string
          • trackNumber [📋]: scalar entries, dtype: 5-byte ASCII string
          • zeroDopplerEndTime [📋]: scalar entries, dtype: 27-byte ASCII string
          • zeroDopplerStartTime [📋]: scalar entries, dtype: 27-byte ASCII string

Use gdal to convert HH polarization for frequencyA to ENVI SLC format and visualize it.

(More example notebooks are provided here: https://github.com/isce-framework/sds-ondemand)

Before we go ahead and convert the HH polarization, check out the metadata information associated with it.

[41]:
!gdalinfo HDF5:"/projects/my-private-bucket/Nisar/SanAnd_05518_18072_003_181002_L090_CX_129_03.h5"://science/LSAR/SLC/swaths/frequencyA/HH
Driver: HDF5Image/HDF5 Dataset
Files: /projects/my-private-bucket/Nisar/SanAnd_05518_18072_003_181002_L090_CX_129_03.h5
Size is 2640, 26678
Metadata:
  contact=nisarops@jpl.nasa.gov
  Conventions=CF-1.7
  institution=NASA JPL
  mission_name=NISAR
  reference_document=TBD
  title=NISAR L1 SLC Product
Corner Coordinates:
Upper Left  (    0.0,    0.0)
Lower Left  (    0.0,26678.0)
Upper Right ( 2640.0,    0.0)
Lower Right ( 2640.0,26678.0)
Center      ( 1320.0,13339.0)
Band 1 Block=128x128 Type=CFloat32, ColorInterp=Undefined
  Metadata:
    science_LSAR_SLC_swaths_frequencyA_HH_description=Focused SLC image (HH)
    science_LSAR_SLC_swaths_frequencyA_HH_units=DN

Translate the HH polarization into SLC files. SLC files are Single Look Complex files. More information can be found in the product description here.

[43]:
!gdal_translate -of ENVI HDF5:"/projects/my-private-bucket/Nisar/SanAnd_05518_18072_003_181002_L090_CX_129_03.h5"://science/LSAR/SLC/swaths/frequencyA/HH HH.slc
Input file size is 2640, 26678
0...10...20...30...40...50...60...70...80...90...100 - done.

Check the metadata again.

[44]:
!gdalinfo HH.slc
Driver: ENVI/ENVI .hdr Labelled
Files: HH.slc
       HH.slc.aux.xml
       HH.hdr
Size is 2640, 26678
Metadata:
  contact=nisarops@jpl.nasa.gov
  Conventions=CF-1.7
  institution=NASA JPL
  mission_name=NISAR
  reference_document=TBD
  title=NISAR L1 SLC Product
Image Structure Metadata:
  INTERLEAVE=BAND
Corner Coordinates:
Upper Left  (    0.0,    0.0)
Lower Left  (    0.0,26678.0)
Upper Right ( 2640.0,    0.0)
Lower Right ( 2640.0,26678.0)
Center      ( 1320.0,13339.0)
Band 1 Block=2640x1 Type=CFloat32, ColorInterp=Undefined
  Metadata:
    science_LSAR_SLC_swaths_frequencyA_HH_description=Focused SLC image (HH)
    science_LSAR_SLC_swaths_frequencyA_HH_units=DN

Plotting Amplitude and Phase

[45]:
import numpy as np
from osgeo import gdal
import matplotlib.pyplot as plt

ds = gdal.Open("HH.slc", gdal.GA_ReadOnly)

# Extract a subset of the SLC to display
x0 = 0
y0 = 10
x_offset = 1000
y_offset = 1000

slc = ds.GetRasterBand(1).ReadAsArray(x0, y0, x_offset, y_offset)
print(slc)


fig = plt.figure(figsize=(14, 12))

# Display amplitude of the slc
ax = fig.add_subplot(2,1,1)
ax.imshow(np.abs(slc), vmin = -2, vmax=2, cmap='gray')
ax.set_title("amplitude")

# Display phase of the slc
ax = fig.add_subplot(2,1,2)
ax.imshow(np.angle(slc))
ax.set_title("phase")

plt.show()
[[-0.05650587-0.00651771j  0.00275015-0.02713971j -0.01253977+0.01070294j
  ... -0.04617569-0.04110472j -0.00265791-0.05650726j
  -0.02567512+0.03241472j]
 [-0.04666522+0.00447277j -0.00942332-0.00897887j  0.04313291+0.05079061j
  ... -0.00320398+0.01296128j -0.04679057+0.07169638j
  -0.03488599+0.01855517j]
 [-0.03761201-0.02987598j  0.02749964+0.01824897j  0.02109917-0.0422815j
  ...  0.05811677+0.05686287j  0.02144936+0.04998003j
  -0.03564805+0.06198853j]
 ...
 [ 0.07378234+0.05721019j  0.35254684+0.08179998j  0.34999567-0.00636293j
  ... -0.03517671-0.06153427j -0.04970409-0.05051059j
  -0.06259989-0.03799874j]
 [-0.04348793-0.03808671j -0.04053086-0.5250713j   0.34176347-0.4646253j
  ... -0.0237219 -0.07149725j -0.0344082 -0.07497716j
   0.00491631+0.00245685j]
 [ 0.02678669-0.07999389j  0.19715716+0.11465938j  0.41922772+0.13021956j
  ... -0.00058665-0.08080925j -0.03730002-0.06477241j
   0.02169864+0.00241395j]]
../../_images/tutorials_NISAR_Nisar_access_explore_27_1.png
[ ]: