Copyright CNES

Read and plot a SWOT-HR Pixel Cloud netcdf products

In this notebook, we show how to read the SWOT-HR pixel cloud products with xarray and how to represent a variable on a map with cartopy.

Libraries

Please note that apart from the libraries listed in the cell below, you need to install the h5netcdf library (conda install -c conda-forge h5netcdf). This will be used by th xarray.open_dataset function to read the netcdf files.

[1]:
import xarray as xr
import os
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

1. Read a SWOT-HR Pixel Cloud netcdf product

Note this is an extraction of the original file for demonstration purpose. It does not contain all variables and groups

[20]:
dir_swot = "../docs/data/swot"
file_swot_pxc = os.path.join(dir_swot, "SWOT_L2_HR_PIXC", "SWOT_L2_HR_PIXC_015_033_163R_20240509T115817_20240509T115828_PIC0_01_extract.nc")
# read data with xarray, specifying a group in the netcdf structure
xr_pxc = xr.open_dataset(file_swot_pxc, group="pixel_cloud")

[21]:

# remove undefined values based on variable of interest xr_pxc = xr_pxc.where( (xr_pxc['classification']>=3) & (xr_pxc['sig0']>=20) & (xr_pxc['cross_track']>=10000) & ~np.isnan(xr_pxc['height']) ) xr_pxc['wse'] = xr_pxc['height'] - xr_pxc['geoid'] xr_pxc
[21]:
<xarray.Dataset>
Dimensions:         (points: 10001)
Coordinates:
    latitude        (points) float64 4.597 4.597 4.597 ... 4.653 4.652 4.652
    longitude       (points) float64 -53.06 -53.06 -53.06 ... -53.39 -53.39
Dimensions without coordinates: points
Data variables:
    classification  (points) float32 nan nan nan nan nan ... nan nan nan nan nan
    coherent_power  (points) float32 nan nan nan nan nan ... nan nan nan nan nan
    cross_track     (points) float32 nan nan nan nan nan ... nan nan nan nan nan
    geoid           (points) float32 nan nan nan nan nan ... nan nan nan nan nan
    height          (points) float32 nan nan nan nan nan ... nan nan nan nan nan
    sig0            (points) float32 nan nan nan nan nan ... nan nan nan nan nan
    wse             (points) float32 nan nan nan nan nan ... nan nan nan nan nan
Attributes:
    description:                 cloud of geolocated interferogram pixels
    interferogram_size_azimuth:  3277
    interferogram_size_range:    4694
    looks_to_efflooks:           1.55135648150391
    num_azimuth_looks:           7.0
    azimuth_offset:              7

3. Plot data on maps with cartopy

[22]:
import cartopy.crs as ccrs
import cartopy.feature as cfeature


def customize_map(ax, cb, label, crs=ccrs.PlateCarree()):
    """This function customizes a map with projection and returns the plt.axes instance"""

    ax.gridlines(
        crs=crs,
        draw_labels=True,
        color='.7',
        alpha=.6,
        linewidth=.4,
        linestyle='-',
        )

    # add a background_map (default, local image, WMTS...read the doc)
    # ax.stock_img()

    # add a labeled colorbar
    plt.colorbar(
        cb,
        ax=ax,
        orientation='horizontal',
        shrink=0.6,
        pad=.05,
        aspect=40,
        label=label)

    return ax


# 0. Create Figure and Axes
crs = ccrs.PlateCarree()
fig, ax = plt.subplots(
    subplot_kw={'projection': crs},
    figsize=(12,8),
    frameon=True,
    )

# 1. plot data on the map with scatter function
cb0 = ax.scatter(
    x=xr_pxc.longitude,
    y=xr_pxc.latitude,
    c=xr_pxc.wse,
    s=1,
    transform=crs,
    cmap='viridis',
    )
# Initiate a map with the function above for Pixel cloud
customize_map(ax, cb0, "Water Surface Height (m)")
# limit map boundaries based on actual data
ax.set_extent(
    [
        xr_pxc.longitude.min(),
        xr_pxc.longitude.max(),
        xr_pxc.latitude.min(),
        xr_pxc.latitude.max(),
    ],
    crs=crs
    )
ax.set_title("Pixel Cloud")
[22]:
Text(0.5, 1.0, 'Pixel Cloud')
../../_images/SWOT-Hydrology_BASIC_Read_SWOT_PixelCloud_7_1.png
[ ]: