RADAR 2A products#

First, let’s import the package required in this tutorial.

[1]:
import datetime

import gpm

Let’s have a look at the available RADAR products:

[2]:
gpm.available_products(product_categories="RADAR", product_levels="1B")
[2]:
['1B-Ka', '1B-Ku', '1B-PR']
[3]:
gpm.available_products(product_categories="RADAR", product_levels="2A")
[3]:
['2A-DPR',
 '2A-ENV-DPR',
 '2A-ENV-Ka',
 '2A-ENV-Ku',
 '2A-ENV-PR',
 '2A-GPM-SLH',
 '2A-Ka',
 '2A-Ku',
 '2A-PR',
 '2A-TRMM-SLH']

1. Data Download#

Now let’s download the 2A-DPR product over a couple of hours.

[4]:
# Specify the time period you are interested in
start_time = datetime.datetime.strptime("2020-07-05 02:00:00", "%Y-%m-%d %H:%M:%S")
end_time = datetime.datetime.strptime("2020-07-05 06:00:00", "%Y-%m-%d %H:%M:%S")
# Specify the product and product type
product = "2A-DPR"    # 2A-PR
product_type = "RS"
# Specify the version
version = 7
[5]:
# Download the data
gpm.download(
    product=product,
    product_type=product_type,
    version=version,
    start_time=start_time,
    end_time=end_time,
    force_download=False,
    verbose=True,
    progress_bar=True,
    check_integrity=False,
)

All the available GPM 2A-DPR product files are already on disk.

Once, the data are downloaded on disk, let’s load the 2A-DPR product and look at the dataset structure.

2. Data Loading#

[6]:
# Load the 2A-DPR dataset
# - If scan_mode is not specified, it automatically load one!
ds = gpm.open_dataset(
    product=product,
    product_type=product_type,
    version=version,
    start_time=start_time,
    end_time=end_time,
)
ds
'scan_mode' has not been specified. Default to FS.
[6]:
<xarray.Dataset>
Dimensions:                       (cross_track: 49, along_track: 20573,
                                   nfreqHI: 3, range: 176, nNode: 5,
                                   nbinSZP: 7, radar_frequency: 2, nNUBF: 3,
                                   method: 6, nsdew: 3, nearFar: 2, four: 4,
                                   nNP: 4, XYZ: 3)
Coordinates:
    height                        (cross_track, along_track, range) float32 dask.array<chunksize=(49, 5803, 176), meta=np.ndarray>
    lon                           (cross_track, along_track) float32 ...
    lat                           (cross_track, along_track) float32 ...
    time                          (along_track) datetime64[ns] 2020-07-05T02:...
    gpm_id                        (along_track) <U10 ...
    gpm_granule_id                (along_track) int64 ...
    gpm_cross_track_id            (cross_track) int64 ...
    gpm_along_track_id            (along_track) int64 ...
    gpm_range_id                  (range) int64 ...
  * radar_frequency               (radar_frequency) <U2 'Ku' 'Ka'
    crsWGS84                      int64 0
Dimensions without coordinates: cross_track, along_track, nfreqHI, range,
                                nNode, nbinSZP, nNUBF, method, nsdew, nearFar,
                                four, nNP, XYZ
Data variables: (12/140)
    sunLocalTime                  (cross_track, along_track) timedelta64[ns] dask.array<chunksize=(49, 5803), meta=np.ndarray>
    flagBB                        (cross_track, along_track) float64 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    binBBPeak                     (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    binBBTop                      (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    binDFRmMLBottom               (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    binDFRmMLTop                  (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    ...                            ...
    operationalMode               (along_track, radar_frequency) float32 dask.array<chunksize=(5803, 2), meta=np.ndarray>
    limitErrorFlag                (along_track, radar_frequency) float32 dask.array<chunksize=(5803, 2), meta=np.ndarray>
    FractionalGranuleNumber       (along_track) float64 dask.array<chunksize=(5803,), meta=np.ndarray>
    precipWaterIntegrated_Liquid  (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    precipWaterIntegrated_Solid   (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    precipWaterIntegrated         (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
Attributes: (12/23)
    FileName:              2A.GPM.DPR.V9-20211125.20200705-S013508-E030740.03...
    EphemerisFileName:
    AttitudeFileName:
    TotalQualityCode:      Good
    DielectricFactorKa:    0.8989
    DielectricFactorKu:    0.9255
    ...                    ...
    DataFormatVersion:     7h
    MetadataVersion:       7h
    ProcessingMode:        STD
    ScanMode:              FS
    history:               Created by ghiggi/gpm_api software on 2023-07-20 1...
    gpm_api_product:       2A-DPR

If you want to load another scan_mode, first have a look at the available ones:

[7]:
gpm.available_scan_modes(product=product, version=version)
[7]:
['FS', 'HS']

and then specify the scan_mode argument in open_dataset:

[8]:
ds = gpm.open_dataset(
    product=product,
    product_type=product_type,
    version=version,
    start_time=start_time,
    end_time=end_time,
    scan_mode="FS",
)
ds
[8]:
<xarray.Dataset>
Dimensions:                       (cross_track: 49, along_track: 20573,
                                   nfreqHI: 3, range: 176, nNode: 5,
                                   nbinSZP: 7, radar_frequency: 2, nNUBF: 3,
                                   method: 6, nsdew: 3, nearFar: 2, four: 4,
                                   nNP: 4, XYZ: 3)
Coordinates:
    height                        (cross_track, along_track, range) float32 dask.array<chunksize=(49, 5803, 176), meta=np.ndarray>
    lon                           (cross_track, along_track) float32 ...
    lat                           (cross_track, along_track) float32 ...
    time                          (along_track) datetime64[ns] 2020-07-05T02:...
    gpm_id                        (along_track) <U10 ...
    gpm_granule_id                (along_track) int64 ...
    gpm_cross_track_id            (cross_track) int64 ...
    gpm_along_track_id            (along_track) int64 ...
    gpm_range_id                  (range) int64 ...
  * radar_frequency               (radar_frequency) <U2 'Ku' 'Ka'
    crsWGS84                      int64 0
Dimensions without coordinates: cross_track, along_track, nfreqHI, range,
                                nNode, nbinSZP, nNUBF, method, nsdew, nearFar,
                                four, nNP, XYZ
Data variables: (12/140)
    sunLocalTime                  (cross_track, along_track) timedelta64[ns] dask.array<chunksize=(49, 5803), meta=np.ndarray>
    flagBB                        (cross_track, along_track) float64 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    binBBPeak                     (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    binBBTop                      (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    binDFRmMLBottom               (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    binDFRmMLTop                  (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    ...                            ...
    operationalMode               (along_track, radar_frequency) float32 dask.array<chunksize=(5803, 2), meta=np.ndarray>
    limitErrorFlag                (along_track, radar_frequency) float32 dask.array<chunksize=(5803, 2), meta=np.ndarray>
    FractionalGranuleNumber       (along_track) float64 dask.array<chunksize=(5803,), meta=np.ndarray>
    precipWaterIntegrated_Liquid  (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    precipWaterIntegrated_Solid   (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    precipWaterIntegrated         (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
Attributes: (12/23)
    FileName:              2A.GPM.DPR.V9-20211125.20200705-S013508-E030740.03...
    EphemerisFileName:
    AttitudeFileName:
    TotalQualityCode:      Good
    DielectricFactorKa:    0.8989
    DielectricFactorKu:    0.9255
    ...                    ...
    DataFormatVersion:     7h
    MetadataVersion:       7h
    ProcessingMode:        STD
    ScanMode:              FS
    history:               Created by ghiggi/gpm_api software on 2023-07-20 1...
    gpm_api_product:       2A-DPR

You can list variables, coordinates and dimensions with the following methods

[9]:
# Available variables
variables = list(ds.data_vars)
print("Available variables: ", variables)
# Available coordinates
coords = list(ds.coords)
print("Available coordinates: ", coords)
# Available dimensions
dims = list(ds.dims)
print("Available dimensions: ", dims)
Available variables:  ['sunLocalTime', 'flagBB', 'binBBPeak', 'binBBTop', 'binDFRmMLBottom', 'binDFRmMLTop', 'binBBBottom', 'binHeavyIcePrecipTop', 'binHeavyIcePrecipBottom', 'nHeavyIcePrecip', 'flagMLquality', 'heightBB', 'widthBB', 'qualityBB', 'typePrecip', 'qualityTypePrecip', 'flagShallowRain', 'flagHeavyIcePrecip', 'flagAnvil', 'flagHail', 'phase', 'binNode', 'paramRDm', 'precipRateESurface2', 'precipRateESurface2Status', 'sigmaZeroProfile', 'seaIceConcentration', 'flagSurfaceSnowfall', 'flagGraupelHail', 'binMixedPhaseTop', 'surfaceSnowfallIndex', 'flagEcho', 'qualityData', 'qualityFlag', 'flagSensor', 'flagScanPattern', 'elevation', 'landSurfaceType', 'localZenithAngle', 'flagPrecip', 'flagSigmaZeroSaturation', 'binRealSurface', 'binStormTop', 'heightStormTop', 'binClutterFreeBottom', 'sigmaZeroMeasured', 'zFactorMeasured', 'ellipsoidBinOffset', 'snRatioAtRealSurface', 'adjustFactor', 'snowIceCover', 'binMirrorImageL2', 'echoCountRealSurface', 'flagSLV', 'paramDSD', 'binEchoBottom', 'piaFinal', 'sigmaZeroCorrected', 'zFactorFinal', 'zFactorFinalESurface', 'zFactorFinalNearSurface', 'paramNUBF', 'precipRate', 'precipWater', 'qualitySLV', 'precipRateNearSurface', 'precipRateESurface', 'precipRateAve24', 'phaseNearSurface', 'epsilon', 'DFRforward1', 'piaOffset', 'pathAtten', 'PIAalt', 'PIAdw', 'PIAhb', 'PIAhybrid', 'piaExp', 'PIAweight', 'PIAweightHY', 'refScanID', 'reliabFactor', 'RFactorAlt', 'reliabFactorHY', 'reliabFlag', 'reliabFlagHY', 'stddevEff', 'stddevHY', 'zeta', 'NUBFindex', 'MSindex', 'MSindexKu', 'MSindexKa', 'MSsurfPeakIndexKu', 'MSsurfPeakIndexKa', 'MSkneeDFRindex', 'MSslopesKu', 'MSslopesKa', 'airTemperature', 'binZeroDeg', 'attenuationNP', 'piaNP', 'piaNPrainFree', 'sigmaZeroNPCorrected', 'heightZeroDeg', 'flagInversion', 'binZeroDegSecondary', 'scHeadingGround', 'scHeadingOrbital', 'scPos', 'scVel', 'scLat', 'scLon', 'scAlt', 'dprAlt', 'scAttRollGeoc', 'scAttPitchGeoc', 'scAttYawGeoc', 'scAttRollGeod', 'scAttPitchGeod', 'scAttYawGeod', 'greenHourAng', 'timeMidScan', 'timeMidScanOffset', 'dataQuality', 'dataWarning', 'missing', 'modeStatus', 'geoError', 'geoWarning', 'SCorientation', 'pointingStatus', 'acsModeMidScan', 'targetSelectionMidScan', 'operationalMode', 'limitErrorFlag', 'FractionalGranuleNumber', 'precipWaterIntegrated_Liquid', 'precipWaterIntegrated_Solid', 'precipWaterIntegrated']
Available coordinates:  ['height', 'lon', 'lat', 'time', 'gpm_id', 'gpm_granule_id', 'gpm_cross_track_id', 'gpm_along_track_id', 'gpm_range_id', 'radar_frequency', 'crsWGS84']
Available dimensions:  ['cross_track', 'along_track', 'nfreqHI', 'range', 'nNode', 'nbinSZP', 'radar_frequency', 'nNUBF', 'method', 'nsdew', 'nearFar', 'four', 'nNP', 'XYZ']

As you see, every variable has a prefix which indicates the group in the original HDF file where the variable is stored. You can remove the prefix when opening the dataset by specifying prefix_group=False. You can also directly load only a subset of variables, by specifying the variables argument.

[10]:
# List some variables of interest
variables = [
    "airTemperature",
    "precipRate",
    "paramDSD",
    "zFactorFinal",
    "zFactorMeasured",
    "precipRateNearSurface",
    "precipRateESurface",
    "precipRateESurface2",
    "zFactorFinalESurface",
    "zFactorFinalNearSurface",
    "heightZeroDeg",
    "binEchoBottom",
    "landSurfaceType",
]
# Load the dataset
ds = gpm.open_dataset(
    product=product,
    product_type=product_type,
    version=version,
    start_time=start_time,
    end_time=end_time,
    variables=variables,
    prefix_group=False,
)
ds
'scan_mode' has not been specified. Default to FS.
[10]:
<xarray.Dataset>
Dimensions:                  (cross_track: 49, along_track: 20573, range: 176,
                              radar_frequency: 2)
Coordinates:
    height                   (cross_track, along_track, range) float32 dask.array<chunksize=(49, 5803, 176), meta=np.ndarray>
    lon                      (cross_track, along_track) float32 ...
    lat                      (cross_track, along_track) float32 ...
    time                     (along_track) datetime64[ns] 2020-07-05T02:00:00...
    gpm_id                   (along_track) <U10 ...
    gpm_granule_id           (along_track) int64 ...
    gpm_cross_track_id       (cross_track) int64 ...
    gpm_along_track_id       (along_track) int64 ...
    gpm_range_id             (range) int64 ...
  * radar_frequency          (radar_frequency) <U2 'Ku' 'Ka'
    crsWGS84                 int64 0
Dimensions without coordinates: cross_track, along_track, range
Data variables: (12/13)
    precipRateESurface2      (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    landSurfaceType          (cross_track, along_track) float64 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    zFactorMeasured          (cross_track, along_track, range, radar_frequency) float32 dask.array<chunksize=(49, 5803, 176, 2), meta=np.ndarray>
    binEchoBottom            (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    paramDSD                 (cross_track, along_track, range, radar_frequency) float32 dask.array<chunksize=(49, 5803, 176, 2), meta=np.ndarray>
    precipRate               (cross_track, along_track, range) float32 dask.array<chunksize=(49, 5803, 176), meta=np.ndarray>
    ...                       ...
    precipRateNearSurface    (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
    zFactorFinal             (cross_track, along_track, range, radar_frequency) float32 dask.array<chunksize=(49, 5803, 176, 2), meta=np.ndarray>
    zFactorFinalESurface     (cross_track, along_track, radar_frequency) float32 dask.array<chunksize=(49, 5803, 2), meta=np.ndarray>
    zFactorFinalNearSurface  (cross_track, along_track, radar_frequency) float32 dask.array<chunksize=(49, 5803, 2), meta=np.ndarray>
    airTemperature           (cross_track, along_track, range) float32 dask.array<chunksize=(49, 5803, 176), meta=np.ndarray>
    heightZeroDeg            (cross_track, along_track) float32 dask.array<chunksize=(49, 5803), meta=np.ndarray>
Attributes: (12/23)
    FileName:              2A.GPM.DPR.V9-20211125.20200705-S013508-E030740.03...
    EphemerisFileName:
    AttitudeFileName:
    TotalQualityCode:      Good
    DielectricFactorKa:    0.8989
    DielectricFactorKu:    0.9255
    ...                    ...
    DataFormatVersion:     7h
    MetadataVersion:       7h
    ProcessingMode:        STD
    ScanMode:              FS
    history:               Created by ghiggi/gpm_api software on 2023-07-20 1...
    gpm_api_product:       2A-DPR

To select the DataArray corresponding to a single variable:

[11]:
variable = "precipRateNearSurface"
da = ds[variable]
da
[11]:
<xarray.DataArray 'precipRateNearSurface' (cross_track: 49, along_track: 20573)>
dask.array<getitem, shape=(49, 20573), dtype=float32, chunksize=(49, 7934), chunktype=numpy.ndarray>
Coordinates:
    lon                 (cross_track, along_track) float32 ...
    lat                 (cross_track, along_track) float32 ...
    time                (along_track) datetime64[ns] 2020-07-05T02:00:00 ... ...
    gpm_id              (along_track) <U10 ...
    gpm_granule_id      (along_track) int64 ...
    gpm_cross_track_id  (cross_track) int64 ...
    gpm_along_track_id  (along_track) int64 ...
    crsWGS84            int64 0
Dimensions without coordinates: cross_track, along_track
Attributes:
    units:            mm/hr
    gpm_api_product:  2A-DPR
    grid_mapping:     crsWGS84
    coordinates:      lat lon

To extract from the DataArray the numerical array you use:

[12]:
print("Data type of numerical array: ", type(da.data))
da.data
Data type of numerical array:  <class 'dask.array.core.Array'>
[12]:
Array Chunk
Bytes 3.85 MiB 1.48 MiB
Shape (49, 20573) (49, 7934)
Dask graph 3 chunks in 11 graph layers
Data type float32 numpy.ndarray
20573 49

If the numerical array data type is dask.Array, it means that the data are not yet loaded into RAM memory. To put the data into memory, you need to call the method compute, either on the xarray object or on the numerical array.

[13]:
# Option 1
da_opt1 = da.compute()
print("Data type of numerical array: ", type(da_opt1.data))
da_opt1.data
Data type of numerical array:  <class 'numpy.ndarray'>
[13]:
array([[0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]], dtype=float32)
[14]:
# Option 2
print("Data type of numerical array: ", type(da.data.compute()))
da.data.compute()
Data type of numerical array:  <class 'numpy.ndarray'>
[14]:
array([[0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]], dtype=float32)

3. Dataset Manipulations#

Now, let’s first have a look at the methods provided by GPM-API

[15]:
variable = "precipRateNearSurface"
da = ds[variable]
print("xr.Dataset gpm methods:", dir(ds.gpm))
print("")
print("xr.DataArray gpm methods:", dir(da.gpm))

xr.Dataset gpm methods: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_obj', 'crop', 'crop_by_continent', 'crop_by_country', 'end_time', 'extent', 'frequency_variables', 'get_crop_slices_by_continent', 'get_crop_slices_by_country', 'get_crop_slices_by_extent', 'get_slices_contiguous_granules', 'get_slices_contiguous_scans', 'get_slices_regular', 'get_slices_regular_time', 'get_slices_valid_geolocation', 'has_contiguous_scans', 'has_missing_granules', 'has_regular_time', 'has_valid_geolocation', 'is_grid', 'is_orbit', 'is_regular', 'is_spatial_2d', 'is_spatial_3d', 'plot_image', 'plot_map', 'plot_map_mesh', 'plot_map_mesh_centroids', 'plot_swath_lines', 'plot_transect_line', 'pyresample_area', 'spatial_2d_variables', 'spatial_3d_variables', 'start_time', 'subset_by_time', 'subset_by_time_slice', 'title', 'variables']

xr.DataArray gpm methods: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_obj', 'crop', 'crop_by_continent', 'crop_by_country', 'end_time', 'extent', 'frequency_variables', 'get_crop_slices_by_continent', 'get_crop_slices_by_country', 'get_crop_slices_by_extent', 'get_slices_contiguous_granules', 'get_slices_contiguous_scans', 'get_slices_regular', 'get_slices_regular_time', 'get_slices_valid_geolocation', 'get_slices_var_between', 'get_slices_var_equals', 'has_contiguous_scans', 'has_missing_granules', 'has_regular_time', 'has_valid_geolocation', 'is_grid', 'is_orbit', 'is_regular', 'is_spatial_2d', 'is_spatial_3d', 'plot_image', 'plot_map', 'plot_map_mesh', 'plot_map_mesh_centroids', 'plot_swath_lines', 'plot_transect_line', 'pyresample_area', 'spatial_2d_variables', 'spatial_3d_variables', 'start_time', 'subset_by_time', 'subset_by_time_slice', 'title', 'variables']

You can also select the reflectivity volumes at a given frequency with the sel method:

[17]:
ds["zFactorFinal"].sel(radar_frequency="Ka")
[17]:
<xarray.DataArray 'zFactorFinal' (cross_track: 49, along_track: 20573,
                                  range: 176)>
dask.array<getitem, shape=(49, 20573, 176), dtype=float32, chunksize=(49, 7934, 176), chunktype=numpy.ndarray>
Coordinates:
    height              (cross_track, along_track, range) float32 dask.array<chunksize=(49, 5803, 176), meta=np.ndarray>
    lon                 (cross_track, along_track) float32 ...
    lat                 (cross_track, along_track) float32 ...
    time                (along_track) datetime64[ns] 2020-07-05T02:00:00 ... ...
    gpm_id              (along_track) <U10 ...
    gpm_granule_id      (along_track) int64 ...
    gpm_cross_track_id  (cross_track) int64 ...
    gpm_along_track_id  (along_track) int64 ...
    gpm_range_id        (range) int64 ...
    radar_frequency     <U2 'Ka'
    crsWGS84            int64 0
Dimensions without coordinates: cross_track, along_track, range
Attributes:
    units:            dBZ
    gpm_api_product:  2A-DPR
    grid_mapping:     crsWGS84
    coordinates:      lat lon

The GPM products are either ORBIT (i.e. PMW and RADAR) or GRID (i.e. IMERG) based. You can check the support of the data with the methods is_grid and is_orbit.

[18]:
print("Is GPM ORBIT data?: ", ds.gpm.is_orbit)
print("Is GPM GRID data?: ", ds.gpm.is_grid)
Is GPM ORBIT data?:  True
Is GPM GRID data?:  False

To check Whether the loaded GPM 2A-DPR product has contiguous scans, you can use:

[19]:
print(ds.gpm.has_contiguous_scans)
print(ds.gpm.is_regular)
True
True

In case there are non-contiguous scans, you can obtain the along-track slices over which the dataset is regular:

[20]:
list_slices = ds.gpm.get_slices_contiguous_scans()
print(list_slices)
[slice(0, 20573, None)]

You can then select a regular portion of the dataset with:

[21]:
slc = list_slices[0]
print(slc)
slice(0, 20573, None)
[22]:
ds_regular = ds.isel(along_track=slc)

To instead check if the open dataset has a single or multiple timestep, you can use:

[23]:
ds.gpm.is_spatial_2d # because the xr.Dataset also contains the range and frequency dimensions !
[23]:
False
[26]:
ds["zFactorFinal"].isel(range=0).sel(radar_frequency="Ka").gpm.is_spatial_2d
[26]:
True
[27]:
ds["precipRateNearSurface"].gpm.is_spatial_2d
[27]:
True

4. Product Visualization#

The GPM-API provides two ways of displaying the data: - The plot_map method plot the data in a geographic projection using the Cartopy pcolormesh method - The plot_image method plot the data as an image using the Maplotlib imshow method

Let’s start by plotting the DPR scan in the geographic space

[28]:
ds[variable].gpm.plot_map()
[28]:
<cartopy.mpl.geocollection.GeoQuadMesh at 0x7f5eec1c8490>
../_images/tutorials_tutorial_02_RADAR_2A_49_1.png
[29]:
ds[variable].isel(along_track=slice(500,1200)).gpm.plot_map()
[29]:
<cartopy.mpl.geocollection.GeoQuadMesh at 0x7f5edf26a680>
../_images/tutorials_tutorial_02_RADAR_2A_50_1.png

and now as an image, in “swath” view:

[30]:
ds[variable].gpm.plot_image()
[30]:
<matplotlib.image.AxesImage at 0x7f5edf1a9810>
../_images/tutorials_tutorial_02_RADAR_2A_52_1.png
[31]:
ds[variable].isel(along_track=slice(500, 1000)).gpm.plot_image()
[31]:
<matplotlib.image.AxesImage at 0x7f5edf0b6920>
../_images/tutorials_tutorial_02_RADAR_2A_53_1.png

To facilitate the creation of a figure title, GPM-API also provide a title method:

[32]:
# Title for a single-timestep dataset
print(ds[variable].gpm.title(add_timestep=True))
print(ds[variable].gpm.title(add_timestep=False))
2A-DPR PrecipRateNearSurface (2020-07-05 04:00)
2A-DPR PrecipRateNearSurface

To instead zoom on a specific regions of a plot_map figure, you can use the axis method set_extent.

[33]:
from gpm.utils.geospatial import get_country_extent

title = ds.gpm.title(add_timestep=False)
extent = get_country_extent("United States")
print("Extent: ", extent)
da = ds[variable]
p = da.gpm.plot_map()
_ = p.axes.set_extent(extent)
_ = p.axes.set_title(label=title)
Extent:  (-171.99111060299998, -66.76465999999999, 18.71619, 71.5577635769)
../_images/tutorials_tutorial_02_RADAR_2A_57_1.png

You can also customize the geographic projection, by specifying the wished Cartopy projection. The available projections are listed here

[34]:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

from gpm.visualization.plot import plot_cartopy_background

# Define some figure options
dpi = 100
figsize = (12, 10)

# Example of Cartopy projections
crs_proj = ccrs.Robinson()

# Select a single variable
da = ds[variable]

# Create the map
fig, ax = plt.subplots(subplot_kw={"projection": crs_proj}, figsize=figsize, dpi=dpi)
plot_cartopy_background(ax)
da.gpm.plot_map(ax=ax)
ax.set_global()
../_images/tutorials_tutorial_02_RADAR_2A_59_0.png

It is possible to further customize these figures in multiply ways. For example by specifying the own colormap:

[35]:
da.gpm.plot_map(cmap="Spectral", vmin=0.1, vmax=100)
[35]:
<cartopy.mpl.geocollection.GeoQuadMesh at 0x7f5ede828490>
../_images/tutorials_tutorial_02_RADAR_2A_61_1.png
[36]:
da = ds[variable]
da.isel(along_track=slice(500, 1000)).gpm.plot_map(cmap="Spectral", vmin=0.1, vmax=100)
[36]:
<cartopy.mpl.geocollection.GeoQuadMesh at 0x7f5ede68fc10>
../_images/tutorials_tutorial_02_RADAR_2A_62_1.png

However, note that GPM-API can provide a large set of pre-defined colormaps and colorbar settings.

[37]:
plot_kwargs, cbar_kwargs =  gpm.get_plot_kwargs("IMERG_Liquid")
da.isel(along_track=slice(500, 1000)).gpm.plot_map(cbar_kwargs=cbar_kwargs, **plot_kwargs)
[37]:
<cartopy.mpl.geocollection.GeoQuadMesh at 0x7f5eec1a4c10>
../_images/tutorials_tutorial_02_RADAR_2A_64_1.png

5. Dataset Cropping#

GPM-API provides methods to easily spatially subset orbits by extent, country or continent. Note however, that an area can be crossed by multiple orbits. In other words, multiple orbit slices in along-track direction can intersect the area of interest. The method get_crop_slices_by_extent, get_crop_slices_by_country and get_crop_slices_by_continent enable to retrieve the orbit portions intersecting the area of interest.

[38]:
# Crop by extent
extent = (-172, -67, 19, 72) # (xmin, xmax, ymin, ymax)
list_isel_dict = ds.gpm.get_crop_slices_by_extent(extent)
print(list_isel_dict)
for isel_dict in list_isel_dict:
    da_subset = ds[variable].isel(isel_dict)
    slice_title = da_subset.gpm.title(add_timestep=True)
    p = da_subset.gpm.plot_map()
    p.axes.set_extent(extent)
    p.axes.set_title(label=slice_title)

[{'along_track': slice(1444, 3113, None)}, {'along_track': slice(9654, 11303, None)}, {'along_track': slice(17814, 19236, None)}]
../_images/tutorials_tutorial_02_RADAR_2A_67_1.png
../_images/tutorials_tutorial_02_RADAR_2A_67_2.png
../_images/tutorials_tutorial_02_RADAR_2A_67_3.png
[39]:
# Crop by country
# - Option 1
list_isel_dict = ds.gpm.get_crop_slices_by_country("United States")
print(list_isel_dict)
# - Option 2
from gpm.utils.geospatial import get_country_extent

extent = get_country_extent("United States")
list_isel_dict = ds.gpm.get_crop_slices_by_extent(extent)
print(list_isel_dict)
# - Plot the swath crossing the country
for isel_dict in list_isel_dict:
    da_subset = ds[variable].isel(isel_dict)
    slice_title = da_subset.gpm.title(add_timestep=True)
    p = da_subset.gpm.plot_map()
    p.axes.set_extent(extent)
    p.axes.set_title(label=slice_title)
[{'along_track': slice(1444, 3124, None)}, {'along_track': slice(9654, 11310, None)}, {'along_track': slice(17814, 19243, None)}]
[{'along_track': slice(1444, 3124, None)}, {'along_track': slice(9654, 11310, None)}, {'along_track': slice(17814, 19243, None)}]
../_images/tutorials_tutorial_02_RADAR_2A_68_1.png
../_images/tutorials_tutorial_02_RADAR_2A_68_2.png
../_images/tutorials_tutorial_02_RADAR_2A_68_3.png
[40]:
# Crop by continent
# - Option 1
list_isel_dict = ds.gpm.get_crop_slices_by_continent("South America")
print(list_isel_dict)
# - Option 2
from gpm.utils.geospatial import get_continent_extent

extent = get_continent_extent("South America")
list_isel_dict = ds.gpm.get_crop_slices_by_extent(extent)
print(list_isel_dict)
# - Plot the swath crossing the country
for isel_dict in list_isel_dict:
    da_subset = ds[variable].isel(isel_dict)
    slice_title = da_subset.gpm.title(add_timestep=True)
    p = da_subset.gpm.plot_map()
    p.axes.set_extent(extent)
    p.axes.set_title(label=slice_title)

[{'along_track': slice(3443, 4950, None)}, {'along_track': slice(11377, 13333, None)}, {'along_track': slice(20442, 20573, None)}]
[{'along_track': slice(3443, 4950, None)}, {'along_track': slice(11377, 13333, None)}, {'along_track': slice(20442, 20573, None)}]
../_images/tutorials_tutorial_02_RADAR_2A_69_1.png
../_images/tutorials_tutorial_02_RADAR_2A_69_2.png
../_images/tutorials_tutorial_02_RADAR_2A_69_3.png

6. Identify Precipitating Areas#

7. Extract Patches#

8. Run Retrievals#

GPM-API comes with utilities helping the extraction of precipitating areas. Go through the dedicated tutorial to discover all the details !!!