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.SentinelMeta object

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

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

[3]:
sar_meta = xsar.SentinelMeta(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.0 * 10.0 meters (xtrack * atrack)
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

A xsar.SentinelMeta object handles all attributes and methods relative to the SAFE metadata that can’t be embdeded in a xarray.Dataset object.

It can be used to construct a xsar.SentinelDataset object.

[4]:
sar_ds_obj = xsar.SentinelDataset(sar_meta)
sar_ds_obj
[4]:
<xsar.Sentinel1.SentinelDataset at 0x7fcf1635aa00>

a xsar.SentinelDataset as a .dataset property that is the already known xarray.Dataset returned by xsar.open_dataset

So, those commands are equivalent:

ds = xsar.open_dataset(filename)
ds = xsar.SentinelDataset(xsar.SentinelMeta(filename)).dataset

By using the underlying objects, the user have access to properties and methods that are not available to the xarray.Dataset object.

Open a dataset at lower resolution

We can use xsar.SentinelMeta 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}
[6]:
sar_ds_obj = xsar.SentinelDataset(sar_meta, resolution = resolution)
{k:sar_ds_obj.dataset.attrs[k] for k in ['coverage','pixel_atrack_m','pixel_xtrack_m'] }
[6]:
{'coverage': '170km * 251km (atrack * xtrack )',
 'pixel_atrack_m': 203.06471107503256,
 'pixel_xtrack_m': 199.7315217724319}

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

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

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

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

The result is floating, because it’s the position inside the pixel. To get the real coordinates in an existing dataset, we can use xsar.SentinelDataset.ll2coords

[8]:
point_coords = sar_ds_obj.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': 500, 'xtrack': 500}
[10]:
# select 10*10 km around point_coords
sar_ds_obj.dataset = sar_ds_obj.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_obj.dataset
[10]:
<xarray.Dataset>
Dimensions:         (atrack: 51, pol: 2, xtrack: 51)
Coordinates:
  * pol             (pol) object 'VV' 'VH'
  * atrack          (atrack) float64 7.93e+03 7.95e+03 ... 8.91e+03 8.93e+03
  * xtrack          (xtrack) float64 1.209e+04 1.211e+04 ... 1.307e+04 1.309e+04
Data variables:
    digital_number  (pol, atrack, xtrack) uint16 dask.array<chunksize=(1, 51, 51), meta=np.ndarray>
    time            (atrack) datetime64[ns] 2017-09-07T10:30:32.763824384 ......
    longitude       (atrack, xtrack) float32 dask.array<chunksize=(51, 51), meta=np.ndarray>
    latitude        (atrack, xtrack) float32 dask.array<chunksize=(51, 51), meta=np.ndarray>
    elevation       (atrack, xtrack) float32 dask.array<chunksize=(51, 51), meta=np.ndarray>
    incidence       (atrack, xtrack) float32 dask.array<chunksize=(51, 51), meta=np.ndarray>
    sigma0_raw      (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 51, 51), meta=np.ndarray>
    nesz            (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 51, 51), meta=np.ndarray>
    gamma0_raw      (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 51, 51), meta=np.ndarray>
    negz            (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 51, 51), meta=np.ndarray>
    sigma0          (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 51, 51), meta=np.ndarray>
    gamma0          (pol, atrack, xtrack) float64 dask.array<chunksize=(1, 51, 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.12591138027886 20.21973939326448, -69.22...
    coverage:          10km * 10km (atrack * xtrack )
    pixel_atrack_m:    203.5818629367982
    pixel_xtrack_m:    199.7376649646133
    orbit_pass:        Descending
    platform_heading:  -167.7668824808032
[ ]: