Download this notebook from github.


Sentinel-1 Level-1B IFREMER variables explanation

Although some variables need extra explanation about why there are present, how they are computed and how to properly use them.

A dedicated Python library is available to use IFREMER Sentinel-1 Level-1B products: https://slcl1butils.readthedocs.io

[1]:
from xsarslc.get_test_files import get_test_file
import xarray as xr
# https://cyclobs.ifremer.fr/static/sarwing_datarmor/xsardata/S1B_IW_XSP__1SDV_20200925T173737_20200925T173804_023535_02CB5D_E473.SAFE/s1b-iw1-slc-vv-20200925t173739-20200925t173804-023535-02cb5d-004_L1B_xspec_IFR_1.4k.nc.zip
#localpath = get_test_file('S1B_IW_XSP__1SDV_20200925T173737_20200925T173804_023535_02CB5D_E473.SAFE/s1b-iw1-slc-vv-20200925t173739-20200925t173804-023535-02cb5d-004_L1B_xspec_IFR_1.4k.nc')
localpath = get_test_file('s1b-iw1-slc-vv-20200925t173739-20200925t173804-023535-02cb5d-004_L1B_xspec_IFR_1.4k.nc')
localpath
[1]:
'/tmp/s1b-iw1-slc-vv-20200925t173739-20200925t173804-023535-02cb5d-004_L1B_xspec_IFR_1.4k.nc'
[2]:
import os
#localpath_tweaked = os.path.join(os.path.dirname(os.path.dirname(localpath)),os.path.basename(localpath))
#print(localpath_tweaked,os.path.exists(localpath_tweaked))
print(os.path.exists(localpath))
ds = xr.open_dataset(localpath,group='intraburst')
ds
True
[2]:
<xarray.Dataset> Size: 53MB
Dimensions:                 (burst: 9, tile_line: 1, tile_sample: 4,
                             freq_sample: 401, freq_line: 51, 0tau: 3, 1tau: 2,
                             2tau: 1, c_sample: 2, c_line: 2)
Coordinates:
    pol                     <U2 8B ...
  * burst                   (burst) int16 18B 0 1 2 3 4 5 6 7 8
    k_rg                    (burst, tile_sample, freq_sample) float32 58kB ...
    k_az                    (freq_line) float32 204B ...
    line                    (burst, tile_line) int16 18B ...
    sample                  (burst, tile_sample) int16 72B ...
    longitude               (burst, tile_line, tile_sample) float32 144B ...
    latitude                (burst, tile_line, tile_sample) float32 144B ...
Dimensions without coordinates: tile_line, tile_sample, freq_sample, freq_line,
                                0tau, 1tau, 2tau, c_sample, c_line
Data variables: (12/25)
    incidence               (burst, tile_line, tile_sample) float32 144B ...
    normalized_variance     (burst, tile_line, tile_sample) float32 144B ...
    sigma0                  (burst, tile_line, tile_sample) float32 144B ...
    nesz                    (burst, tile_line, tile_sample) float32 144B ...
    ground_heading          (burst, tile_line, tile_sample) float32 144B ...
    doppler_centroid        (burst, tile_line, tile_sample) float32 144B ...
    ...                      ...
    xspectra_0tau_Re        (burst, tile_line, tile_sample, freq_line, freq_sample, 0tau) float32 9MB ...
    xspectra_0tau_Im        (burst, tile_line, tile_sample, freq_line, freq_sample, 0tau) float32 9MB ...
    xspectra_1tau_Re        (burst, tile_line, tile_sample, freq_line, freq_sample, 1tau) float32 6MB ...
    xspectra_1tau_Im        (burst, tile_line, tile_sample, freq_line, freq_sample, 1tau) float32 6MB ...
    xspectra_2tau_Re        (burst, tile_line, tile_sample, freq_line, freq_sample, 2tau) float32 3MB ...
    xspectra_2tau_Im        (burst, tile_line, tile_sample, freq_line, freq_sample, 2tau) float32 3MB ...
Attributes: (12/27)
    name:                    SENTINEL1_DS:/home/datawork-cersat-public/projec...
    short_name:              SENTINEL1_DS:S1B_IW_SLC__1SDV_20200925T173737_20...
    product:                 SLC
    safe:                    S1B_IW_SLC__1SDV_20200925T173737_20200925T173804...
    swath:                   IW
    multidataset:            False
    ...                      ...
    tile_overlap_sample:     0
    tile_overlap_line:       0
    periodo_width_sample:    3540
    periodo_width_line:      3540
    periodo_overlap_sample:  1770
    periodo_overlap_line:    1770

wavenumbers in range axis: “k_rg”

“k_rg” variable slightly depends on each tile because the pixel spacing is not the same in the IW sub-swath.

We made the choice to have a constant dk (in range and azimuth) for all the tiles/cross-spectrum, and we achieved a 10e-3 consistency as a maximum point-to-point difference wavenumbers .

This strategy allows to compare a spectra to another.

[3]:
k_rg1 = ds['k_rg'].isel(burst=2,tile_sample=1)
k_rg2 = ds['k_rg'].isel(burst=2,tile_sample=3)
k_rg1
[3]:
<xarray.DataArray 'k_rg' (freq_sample: 401)> Size: 2kB
[401 values with dtype=float32]
Coordinates:
    pol      <U2 8B ...
    burst    int16 2B 2
    k_rg     (freq_sample) float32 2kB ...
    sample   int16 2B ...
Dimensions without coordinates: freq_sample
Attributes:
    long_name:  wavenumber in range direction
    units:      rad/m
[4]:
from matplotlib import pyplot as plt
k_rg1.plot(label="burst=2,tile_sample=1",linestyle='--',lw=5)
k_rg2.plot(label="burst=2,tile_sample=2")
plt.legend()
[4]:
<matplotlib.legend.Legend at 0x74865c57ac60>
../_images/examples_L1B_Sentinel1_variables_explanation_7_1.png
[5]:
(k_rg1-k_rg2).plot()
plt.title('difference between 2 different k_rg')
[5]:
Text(0.5, 1.0, 'difference between 2 different k_rg')
../_images/examples_L1B_Sentinel1_variables_explanation_8_1.png

The difference between the 2 vectors of wave numbers is super small but for users who might want to stack the different cross spectrum, a first step would be to assign a single k_rg to all the cross spectrum.

SAR image complexe cartesian cross spectrum

The “xpsectra_{0-1-2}tau_*” is split in real and imaginary part because netCDF4 file format does not allow to store complex values.

Also only half of the spectrum along the range wavenumbers is stored in the netCDF files to save space.

[6]:
# recompose complexe SAr image cross spectrum from real and imaginary part
for tautau in range(3):
    ds['xspectra_%stau'%tautau] = ds['xspectra_%stau_Re'%tautau] + 1j*ds['xspectra_%stau_Im'%tautau]
    #ds = ds.drop(['xspectra_%stau_Re'%tautau,'xspectra_%stau_Im'%tautau])
one_cartesian_xsp = ds['xspectra_2tau'].isel({'burst':6,'tile_line':0,'tile_sample':2,'2tau':0})
one_cartesian_xsp = one_cartesian_xsp.assign_coords({'freq_line':one_cartesian_xsp.k_az,'freq_sample':one_cartesian_xsp.k_rg})
one_cartesian_xsp
[6]:
<xarray.DataArray 'xspectra_2tau' (freq_line: 51, freq_sample: 401)> Size: 164kB
array([[-1.2477797 +0.5443525j ,  1.5725    -0.01272768j,
         0.4407456 -0.2429612j , ...,  0.00830453-0.3919062j ,
         0.1216751 +0.09071319j, -0.05311767+0.49395174j],
       [ 2.060735  +0.5237646j ,  0.2005456 +0.29838213j,
        -0.02560596-0.18570837j, ...,  0.05239271+0.30355382j,
         0.54826015-0.08569147j,  0.02144801-0.19576392j],
       [-1.4342278 +1.4327244j , -0.30036288+0.18255554j,
         0.6784638 -0.17505352j, ..., -0.04385818+0.16508722j,
        -0.375506  -0.16829075j, -0.24914488+0.21455552j],
       ...,
       [-1.4342278 -1.4327244j , -0.53528905+0.7241161j ,
        -1.539189  +0.64669746j, ...,  0.03286539+0.10321924j,
        -0.2948199 -0.2361605j , -0.47778353-0.54428077j],
       [ 2.060735  -0.5237646j , -0.2049799 -1.0952276j ,
         0.42247522+1.1954173j , ...,  0.15609382-0.17570984j,
         0.36818713-0.3684804j , -0.01811259-0.32531738j],
       [-1.2477797 -0.5443525j , -0.39482182+1.2361256j ,
        -0.9189708 +0.479853j  , ...,  0.360627  +0.5266922j ,
         0.07324556+0.2173959j ,  0.4194936 +0.03121182j]],
      dtype=complex64)
Coordinates:
    pol          <U2 8B 'VV'
    burst        int16 2B 6
    k_rg         (freq_sample) float32 2kB ...
    k_az         (freq_line) float32 204B ...
    line         int16 2B 9642
    sample       int16 2B 12215
    longitude    float32 4B 3.652
    latitude     float32 4B 40.42
  * freq_line    (freq_line) float32 204B -0.04414 -0.04238 ... 0.04238 0.04414
  * freq_sample  (freq_sample) float32 2kB 0.0 0.001775 0.00355 ... 0.7082 0.71
[7]:
from matplotlib import colors as mcolors
cmap = mcolors.LinearSegmentedColormap.from_list("", ["white","violet","mediumpurple","cyan","springgreen","yellow","red"])

abs(one_cartesian_xsp.real).plot(cmap=cmap)
plt.grid(True)
../_images/examples_L1B_Sentinel1_variables_explanation_13_0.png

landmask

The “land_flag” annotated in the sample of L1B product comes from cartopy 10 m resolution polygons.

cartopy/shapefiles/natural_earth/physical/: https://www.naturalearthdata.com/

[8]:
ds['land_flag'].plot()
[8]:
<matplotlib.collections.QuadMesh at 0x7486525c1910>
../_images/examples_L1B_Sentinel1_variables_explanation_16_1.png

variance of cross spectrum

“var_xspectra_{0-1-2}tau” is the variance of the different periodograms while “xpsectra_{0-1-2}tau” is the mean of the periodograms computed within a given tile.

These variables var_xspectra_{0-1-2}tau are defined on the same grid than the cross spectrum xpsectra_{0-1-2}tau. They are also splitted in Real part and Imaginary part in the netCDF files, and they are also stored on the half part of the wavenumer along range axis since they are symmetric.

[9]:
ds['var_xspectra_2tau'].isel(tile_line=0,tile_sample=0,burst=3).squeeze().plot(cmap=cmap)
[9]:
<matplotlib.collections.QuadMesh at 0x7486524c1f10>
../_images/examples_L1B_Sentinel1_variables_explanation_19_1.png