Download this notebook from github.


XSAR example

open a dataset with xsar.open_dataset

[1]:
import xsar
import os
import numpy as np
[2]:
# get test file. You can replace with an path to other SAFE
filename = xsar.get_test_file('S1A_IW_GRDH_1SDV_20170907T103020_20170907T103045_018268_01EB76_Z010.SAFE')

Open a dataset with a xsar.Sentinel1Meta object

A xsar.Sentinel1Meta object handles all attributes and methods that can’t be embdeded in a xarray.Dataset object. It can also replace a filename in xarray.open_dataset

When using it in a notebook, it also have an html representation.

[3]:
sar_meta = xsar.Sentinel1Meta(filename)
sar_meta
[3]:
Single dataset
SENTINEL1_DS:S1A_IW_GRDH_1SDV_20170907T103020_20170907T103045_018268_01EB76_Z010.SAFE:IW
ipf 2.84
platform SENTINEL-1A
swath IW
product GRDH
pols VV VH
orbit_pass Descending
pixel size 10.2 * 10.0 meters (atrack * xtrack)
coverage 170km * 251km (atrack * xtrack )
start_date 2017-09-07 10:30:20.936409
stop_date 2017-09-07 10:30:45.935264
dsid IW

sar_meta object is an xsar.Sentinel1Meta object that can be given to xarray.open_dataset or xsar.Sentinel1Dataset , as if it was a filename:

[4]:
sar_ds = xsar.Sentinel1Dataset(sar_meta)
sar_ds
[4]:
full dataset coverage
SENTINEL1_DS:S1A_IW_GRDH_1SDV_20170907T103020_20170907T103045_018268_01EB76_Z010.SAFE:IW
pixel size 10.2 * 10.0 meters (atrack * xtrack)
coverage 170km * 251km (atrack * xtrack )

Open a dataset at lower resolution

We can use sar_meta properties to compute the pixel count we need to average to get a resolution of 200*200 meters

[5]:
resolution = {'atrack' : int(np.round(200 / sar_meta.pixel_atrack_m)), 'xtrack': int(np.round(200 / sar_meta.pixel_xtrack_m))}
resolution
[5]:
{'atrack': 20, 'xtrack': 20}

Then we can instantiate a xsar.Sentinel1Dataset, with the given resolution. Note that the above pixel size has changed.

[6]:
sar_ds = xsar.Sentinel1Dataset(sar_meta, resolution=resolution)
sar_ds
[6]:
full dataset coverage
SENTINEL1_DS:S1A_IW_GRDH_1SDV_20170907T103020_20170907T103045_018268_01EB76_Z010.SAFE:IW
pixel size 203.1 * 199.7 meters (atrack * xtrack)
coverage 170km * 251km (atrack * xtrack )

Extract a sub image of 10*10km around a lon/lat point

Convert (lon,lat) to (atrack, xtrack)

we can use sar_meta.ll2coords to convert (lon,lat) to (atrack, xtrack):

[7]:
# from a shapely object
point_lonlat =  sar_meta.footprint.centroid
point_coords = sar_meta.ll2coords(point_lonlat.x, point_lonlat.y)
point_coords
[7]:
(8421.566059451987, 12589.902956209728)

The result is floating, because it is the position inside the pixel. If real indexes from existing dataset is needed, you’ll have to use sar_ds.ll2coords Result will be the nearest (atrack, xtrack) in the dataset

[8]:
point_coords = sar_ds.ll2coords(point_lonlat.x, point_lonlat.y)
point_coords
[8]:
(8430.0, 12590.0)

Extract the sub-image

[9]:
box_size = 10000 # 10km
dist = {'atrack' : int(np.round(box_size / 2 / sar_meta.pixel_atrack_m)), 'xtrack': int(np.round(box_size / 2 / sar_meta.pixel_xtrack_m))}
dist
[9]:
{'atrack': 490, 'xtrack': 500}

The xarray/dask dataset is available as a property : sar_ds.dataset. This attribute can be set to a new values, so the attributes like pixel spacing and coverage are correctly recomputed:

[10]:
# select 10*10 km around point_coords
sar_ds.dataset = sar_ds.dataset.sel(atrack=slice(point_coords[0] - dist['atrack'], point_coords[0] + dist['atrack']), xtrack=slice(point_coords[1] - dist['xtrack'], point_coords[1] + dist['xtrack']))
sar_ds
[10]:
dataset slice
SENTINEL1_DS:S1A_IW_GRDH_1SDV_20170907T103020_20170907T103045_018268_01EB76_Z010.SAFE:IW
pixel size 203.6 * 199.7 meters (atrack * xtrack)
coverage 9km * 10km (atrack * xtrack )
[11]:
sar_ds.dataset
[11]:
<xarray.Dataset>
Dimensions:         (atrack: 49, pol: 2, xtrack: 51)
Coordinates:
  * pol             (pol) object 'VV' 'VH'
  * atrack          (atrack) float64 7.95e+03 7.97e+03 ... 8.89e+03 8.91e+03
  * xtrack          (xtrack) float64 1.209e+04 1.211e+04 ... 1.307e+04 1.309e+04
Data variables: (12/14)
    digital_number  (pol, atrack, xtrack) uint16 dask.array<chunksize=(1, 49, 51), meta=np.ndarray>
    time            (atrack) datetime64[ns] 2017-09-07T10:30:32.793691648 ......
    longitude       (atrack, xtrack) float32 dask.array<chunksize=(49, 51), meta=np.ndarray>
    latitude        (atrack, xtrack) float32 dask.array<chunksize=(49, 51), meta=np.ndarray>
    land_mask       (atrack, xtrack) int8 dask.array<chunksize=(49, 51), meta=np.ndarray>
    ground_heading  (atrack, xtrack) float32 dask.array<chunksize=(49, 51), meta=np.ndarray>
    ...              ...
    sigma0_raw      (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 49, 51), meta=np.ndarray>
    nesz            (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 49, 51), meta=np.ndarray>
    gamma0_raw      (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 49, 51), meta=np.ndarray>
    negz            (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 49, 51), meta=np.ndarray>
    sigma0          (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 49, 51), meta=np.ndarray>
    gamma0          (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 49, 51), meta=np.ndarray>
Attributes: (12/14)
    ipf:               2.84
    platform:          SENTINEL-1A
    swath:             IW
    product:           GRDH
    pols:              VV VH
    name:              SENTINEL1_DS:/tmp/S1A_IW_GRDH_1SDV_20170907T103020_201...
    ...                ...
    footprint:         POLYGON ((-69.12627509838202 20.21794031159714, -69.22...
    coverage:          9km * 10km (atrack * xtrack )
    pixel_atrack_m:    203.5819198789976
    pixel_xtrack_m:    199.7376700425335
    orbit_pass:        Descending
    platform_heading:  -167.7668824808032