Discover Sentinel-1 pairs for pre-seismic and coseismic coherence change analysis¶
- Import the Python packages
[1]:
%matplotlib inline
import warnings
warnings.filterwarnings("ignore")
import os
import sys
import glob
import cioppy
ciop = cioppy.Cioppy()
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from snappy import jpy
from snappy import ProductIO
from snappy import GPF
from snappy import HashMap
import gc
from shapely.geometry import box
from shapely.wkt import loads
import py_earthquakes
from datetime import datetime, timedelta
import dateutil.parser
import geopandas as gp
import folium
- Use an earthquake
[2]:
bbox=[21.944860, 36.940880,23.944860, 38.940880]
min_mag = 4.1
start_date = '2016-10-01'
stop_date = '2016-11-30'
[3]:
eq_search = py_earthquakes.EarthQuakes(start_date,
stop_date,
min_mag = min_mag,
bbox=bbox)
[4]:
eq_search.earthquakes[0].title
[4]:
'M 4.2 - 1km SSW of Makrakomi, Greece'
[5]:
eq_search.earthquakes[0].id
[5]:
'us20007gi7'
[6]:
eq_search.earthquakes[0].date
[6]:
'2016-10-25T00:09:56.590000Z'
Create a buffer of 0.5 degrees
[7]:
eq_search.earthquakes[0].wkt
[7]:
'POINT(22.1115 38.9244)'
[8]:
aoi_wkt = box(*loads(eq_search.earthquakes[0].wkt).buffer(0.5).bounds).wkt
[9]:
aoi_wkt
[9]:
'POLYGON ((22.6115 38.4244, 22.6115 39.4244, 21.6115 39.4244, 21.6115 38.4244, 22.6115 38.4244))'
- Search parameters
Set the catalogue endpoint to Sentinel-1:
[10]:
series = 'https://catalog.terradue.com/sentinel1/search'
Define the end of the time of interest:
[11]:
slave_search_stop_date = (dateutil.parser.parse(eq_search.earthquakes[0].date) + timedelta(days=6)).isoformat()
- Build and submit the catalog search
[12]:
search_params = dict([('geom', aoi_wkt),
('start', eq_search.earthquakes[0].date),
('stop', slave_search_stop_date),
('pt', 'SLC')])
[13]:
slave_search = ciop.search(end_point = series,
params = search_params,
output_fields='self,productType,track,enclosure,identifier,wkt,startdate',
model='EOP')
- Put all slaves in a geodataframe and plot the Sentinel-1 slave candidates
[14]:
aoi = loads(aoi_wkt)
[15]:
result = []
locations = []
for index, elem in enumerate(slave_search):
locations.append([t[::-1] for t in list(loads(elem['wkt']).exterior.coords)])
slave_wkt = loads(elem['wkt'])
result.append({'self' : elem['self'],
'identifier' : elem['identifier'],
'enclosure' : elem['enclosure'],
'date' : elem['startdate'],
'wkt': loads(elem['wkt']),
'aoi_intersec' : (slave_wkt.intersection(aoi).area/aoi.area) * 100,
'contains': slave_wkt.contains(aoi)
})
slaves = gp.GeoDataFrame(result)
[16]:
lat = loads(eq_search.earthquakes[0].wkt).y
lon = loads(eq_search.earthquakes[0].wkt).x
zoom_start = 7
m = folium.Map(location=[lat, lon], zoom_start=zoom_start)
radius = 4
folium.CircleMarker(
location=[lat, lon],
radius=radius,
color='#FF0000',
stroke=False,
fill=True,
fill_opacity=0.6,
opacity=1,
popup='{} pixels'.format(radius),
tooltip='I am in pixels',
).add_to(m)
folium.PolyLine(
locations=np.asarray([t[::-1] for t in list(loads(aoi_wkt).exterior.coords)]).tolist(),
color='#FF0000',
weight=2,
tooltip='Japan flooding',
).add_to(m)
folium.PolyLine(
locations=locations,
color='orange',
weight=1,
opacity=1,
smooth_factor=0,
).add_to(m)
m.save(os.path.join('results', '%s_search.html' % eq_search.earthquakes[0].id))
m
[16]:
[17]:
slaves
[17]:
aoi_intersec | contains | date | enclosure | identifier | self | wkt | |
---|---|---|---|---|---|---|---|
0 | 100.000000 | True | 2016-10-30T16:31:41.3695830Z | https://store.terradue.com/download/sentinel1/... | S1A_IW_SLC__1SDV_20161030T163141_20161030T1632... | https://catalog.terradue.com/sentinel1/search?... | POLYGON ((19.736723 39.341087, 22.701288 39.74... |
1 | 97.711574 | False | 2016-10-30T04:38:48.2069410Z | https://store.terradue.com/download/sentinel1/... | S1B_IW_SLC__1SDV_20161030T043848_20161030T0439... | https://catalog.terradue.com/sentinel1/search?... | POLYGON ((22.34882 37.795399, 19.450127 38.198... |
2 | 5.551913 | False | 2016-10-30T04:38:22.4261540Z | https://store.terradue.com/download/sentinel1/... | S1B_IW_SLC__1SDV_20161030T043822_20161030T0438... | https://catalog.terradue.com/sentinel1/search?... | POLYGON ((22.728542 39.285812, 19.762106 39.68... |
3 | 71.287095 | False | 2016-10-25T16:23:37.9832800Z | https://store.terradue.com/download/sentinel1/... | S1A_IW_SLC__1SDV_20161025T162337_20161025T1624... | https://catalog.terradue.com/sentinel1/search?... | POLYGON ((21.63916 39.960037, 24.634281 40.361... |
4 | 5.062699 | False | 2016-10-25T16:23:13.1686030Z | https://store.terradue.com/download/sentinel1/... | S1A_IW_SLC__1SDV_20161025T162313_20161025T1623... | https://catalog.terradue.com/sentinel1/search?... | POLYGON ((22.016951 38.469093, 24.94478 38.871... |
5 | 93.929883 | False | 2016-10-25T04:30:36.4692880Z | https://store.terradue.com/download/sentinel1/... | S1B_IW_SLC__1SDV_20161025T043036_20161025T0431... | https://catalog.terradue.com/sentinel1/search?... | POLYGON ((24.384764 37.672104, 21.492056 38.07... |
Select the slave that ‘best’ covers the AOI
[18]:
slave = slave_search[slaves['aoi_intersec'].idxmax()]
slave
[18]:
{'enclosure': 'https://store.terradue.com/download/sentinel1/files/v1/S1A_IW_SLC__1SDV_20161030T163141_20161030T163208_013722_01603F_4094',
'identifier': 'S1A_IW_SLC__1SDV_20161030T163141_20161030T163208_013722_01603F_4094',
'productType': 'SLC',
'self': 'https://catalog.terradue.com/sentinel1/search?format=atom&uid=S1A_IW_SLC__1SDV_20161030T163141_20161030T163208_013722_01603F_4094',
'startdate': '2016-10-30T16:31:41.3695830Z',
'track': '175',
'wkt': 'POLYGON((19.736723 39.341087,22.701288 39.742973,23.034481 38.123413,20.138891 37.720314,19.736723 39.341087))'}
[19]:
slave['startdate']
[19]:
'2016-10-30T16:31:41.3695830Z'
Search for the pre-event masters
[20]:
master_search_start_date = (dateutil.parser.parse(slave['startdate']) + timedelta(days=-24)).isoformat()
[21]:
master_search_stop_date = (dateutil.parser.parse(slave['startdate']) + timedelta(days=-1)).isoformat()
[22]:
master_search_params = dict([('geom', slave['wkt']),
('track', slave['track']),
('pt',slave['productType']),
('start', master_search_start_date),
('stop', master_search_stop_date)])
[23]:
try:
master_search = ciop.search(end_point=series,
params=master_search_params,
output_fields='identifier,enclosure,self,startdate,wkt',
model='EOP')
except IndexError:
print('no masters')
[24]:
result = []
for index, elem in enumerate(master_search):
master_wkt = loads(elem['wkt'])
result.append({'self' : elem['self'],
'identifier' : elem['identifier'],
'enclosure' : elem['enclosure'],
'wkt': loads(elem['wkt']),
'aoi_intersec' : (master_wkt.intersection(aoi).area/aoi.area) * 100,
'slave_intersec' : (master_wkt.intersection(loads(slave['wkt']))).area / loads(slave['wkt']).area * 100,
'contains': master_wkt.contains(aoi),
'days': (dateutil.parser.parse(slave['startdate']) - dateutil.parser.parse(elem['startdate'])).days
})
masters = gp.GeoDataFrame(result)
[25]:
masters
[25]:
aoi_intersec | contains | days | enclosure | identifier | self | slave_intersec | wkt | |
---|---|---|---|---|---|---|---|---|
0 | 68.636837 | False | 6 | https://store.terradue.com/download/sentinel1/... | S1B_IW_SLC__1SDV_20161024T163111_20161024T1631... | https://catalog.terradue.com/sentinel1/search?... | 55.755995 | POLYGON ((19.520258 40.118217, 22.542038 40.52... |
1 | 44.640286 | False | 6 | https://store.terradue.com/download/sentinel1/... | S1B_IW_SLC__1SDV_20161024T163046_20161024T1631... | https://catalog.terradue.com/sentinel1/search?... | 52.199313 | POLYGON ((19.906658 38.567837, 22.860817 38.97... |
2 | 0.000000 | False | 11 | https://store.terradue.com/download/sentinel1/... | S1A_IW_SLC__1SDV_20161018T163206_20161018T1632... | https://catalog.terradue.com/sentinel1/search?... | 7.893120 | POLYGON ((19.368031 40.835575, 22.396507 41.23... |
3 | 100.000000 | True | 12 | https://store.terradue.com/download/sentinel1/... | S1A_IW_SLC__1SDV_20161018T163141_20161018T1632... | https://catalog.terradue.com/sentinel1/search?... | 99.881697 | POLYGON ((19.736567 39.342892, 22.70108 39.744... |
4 | 0.000000 | False | 12 | https://store.terradue.com/download/sentinel1/... | S1A_IW_SLC__1SDV_20161018T163116_20161018T1631... | https://catalog.terradue.com/sentinel1/search?... | 7.974487 | POLYGON ((20.105968 37.850845, 23.007288 38.25... |
5 | 0.000000 | False | 23 | https://store.terradue.com/download/sentinel1/... | S1A_IW_SLC__1SDV_20161006T163206_20161006T1632... | https://catalog.terradue.com/sentinel1/search?... | 7.933108 | POLYGON ((19.367752 40.834766, 22.396078 41.23... |
6 | 100.000000 | True | 24 | https://store.terradue.com/download/sentinel1/... | S1A_IW_SLC__1SDV_20161006T163141_20161006T1632... | https://catalog.terradue.com/sentinel1/search?... | 99.917743 | POLYGON ((19.736254 39.342201, 22.700668 39.74... |
7 | 0.000000 | False | 24 | https://store.terradue.com/download/sentinel1/... | S1A_IW_SLC__1SDV_20161006T163116_20161006T1631... | https://catalog.terradue.com/sentinel1/search?... | 7.912009 | POLYGON ((20.105749 37.849777, 23.00696 38.252... |
- Select the two masters according to the ranking of AOI coverage and nearest cycles in time
[26]:
master_1 = master_search[masters.sort_values(['aoi_intersec', 'days'], ascending=[False, False]).iloc[1].name]
master_2 = master_search[masters.sort_values(['aoi_intersec', 'days'], ascending=[False, False]).iloc[0].name]
[34]:
s1_identifiers = []
s1_references = []
locations = []
for product in [slave, master_1, master_2]:
locations.append([t[::-1] for t in list(loads(product['wkt']).exterior.coords)])
s1_identifiers.append(product['identifier'])
s1_references.append(product['self'])
Plot the Sentinel-1 products (slave, master 1 and master 2), the earthquake point and its area of interest
[35]:
lat = loads(eq_search.earthquakes[0].wkt).y
lon = loads(eq_search.earthquakes[0].wkt).x
zoom_start = 7
m = folium.Map(location=[lat, lon], zoom_start=zoom_start)
radius = 4
folium.CircleMarker(
location=[lat, lon],
radius=radius,
color='#FF0000',
stroke=False,
fill=True,
fill_opacity=0.6,
opacity=1,
popup='{} pixels'.format(radius),
tooltip='I am in pixels',
).add_to(m)
folium.PolyLine(
locations=np.asarray([t[::-1] for t in list(loads(aoi_wkt).exterior.coords)]).tolist(),
color='#FF0000',
weight=2,
tooltip='Japan flooding',
).add_to(m)
folium.PolyLine(
locations=locations,
color='orange',
weight=1,
opacity=1,
smooth_factor=0,
).add_to(m)
m.save(os.path.join('results', '%s_final.html' % eq_search.earthquakes[0].id))
m
[35]:
[36]:
s1_references
[36]:
['https://catalog.terradue.com/sentinel1/search?format=atom&uid=S1A_IW_SLC__1SDV_20161030T163141_20161030T163208_013722_01603F_4094',
'https://catalog.terradue.com/sentinel1/search?format=atom&uid=S1A_IW_SLC__1SDV_20161018T163141_20161018T163208_013547_015AEB_5994',
'https://catalog.terradue.com/sentinel1/search?format=atom&uid=S1A_IW_SLC__1SDV_20161006T163141_20161006T163208_013372_01554F_F08D']
[37]:
pair_coseismic = [s1_references[0],
s1_references[1]]
pair_preseismic = [s1_references[1],
s1_references[2]]
[45]:
print ('aoi_wkt = \'%s\'' % aoi_wkt)
aoi_wkt = 'POLYGON ((22.6115 38.4244, 22.6115 39.4244, 21.6115 39.4244, 21.6115 38.4244, 22.6115 38.4244))'
[40]:
print ('pair_coseismic = %s' % pair_coseismic)
pair_coseismic = ['https://catalog.terradue.com/sentinel1/search?format=atom&uid=S1A_IW_SLC__1SDV_20161030T163141_20161030T163208_013722_01603F_4094', 'https://catalog.terradue.com/sentinel1/search?format=atom&uid=S1A_IW_SLC__1SDV_20161018T163141_20161018T163208_013547_015AEB_5994']
[41]:
print ('pair_preseismic = %s' % pair_preseismic)
pair_preseismic = ['https://catalog.terradue.com/sentinel1/search?format=atom&uid=S1A_IW_SLC__1SDV_20161018T163141_20161018T163208_013547_015AEB_5994', 'https://catalog.terradue.com/sentinel1/search?format=atom&uid=S1A_IW_SLC__1SDV_20161006T163141_20161006T163208_013372_01554F_F08D']
[ ]: