/
checker.py
203 lines (172 loc) · 6.71 KB
/
checker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
from sentinelsat import SentinelAPI, geojson_to_wkt
from dotenv import load_dotenv
import os
from requests.auth import HTTPBasicAuth
import requests
import base64
load_dotenv() # Load environment variable from .env
coords = '-68.45317820662159 -26.35042608088762 -62.36675242537159 -26.35042608088762 -62.36675242537159 -22.002031348439377 -68.45317820662159 -22.002031348439377 -68.45317820662159 -26.35042608088762'
start = '20210920'
end = '20210922'
ingee = 'S2B_MSIL1C_20210920T143729_N0301_R096_T19JEL_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19JEM_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19JEN_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19JFL_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19JFM_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19JFN_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19KEP_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19KEQ_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19KER_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19KFP_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19KFQ_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19KFR_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19KGQ_20210920T180332 S2B_MSIL1C_20210920T143729_N0301_R096_T19KGR_20210920T180332 S2B_MSIL1C_20210921T141049_N0301_R110_T20JMS_20210921T172924 S2B_MSIL1C_20210921T141049_N0301_R110_T20KNU_20210921T172924'
level = 'toa'
MATCH = {
'identifier': 'PRODUCT_ID',
}
def get_api(user, password):
return SentinelAPI(user, password, 'https://apihub.copernicus.eu/apihub')
def _date_gee(date):
y = date[0:4]
m = date[4:6]
d = date[6:8]
return '{}-{}-{}'.format(y, m, d)
class Checker:
TEMPLATE = """
<table style="width:500px border:1px solid">
<tr>
<th>ESA ID</th>
<th>Is available in GEE?</th>
<th>Is online in S2 Hub?</th>
<th>Code Editor</th>
<th>Preview</th>
</tr>
{content}
</table>
"""
ROW = """
<tr style='background-color:{color}'>
<td>{esaid}</td>
<td>{ingee}</td>
<td>{online}</td>
<td>{codeeditor}</td>
<td>{preview}</td>
</tr>"""
def __init__(self, coords, start, end, level, ingee, api,
match='identifier'):
self.coords = coords
self.level = level
self.ingee = ingee
self.start = start
self.end = end
self.api = api
self.match = match
self._products = None
@property
def start_gee(self):
return _date_gee(self.start)
@property
def end_gee(self):
return _date_gee(self.end)
@property
def ingeelist(self):
return self.ingee.split(' ')
@property
def coordlist(self):
coordlist = self.coords.split(' ')
points = len(coordlist)
indices = range(0, int(points), 2)
final = []
for i in indices:
lon = float(coordlist[i])
lat = float(coordlist[i+1])
final.append((lon, lat))
return final
@property
def products(self):
if not self._products:
products = self.api.query(
self.footprint,
date = (self.start, self.end),
platformname = 'Sentinel-2',
processinglevel = self.plevel
)
self._products = products
return self._products
def preview_tag(self, pid):
""" Return a <img> tag for the requested product id """
data = self.api.get_product_odata(pid)
url = data['quicklook_url']
user = os.environ['HUB_USER']
password = os.environ['HUB_PASS']
r = requests.get(url, auth=HTTPBasicAuth(user, password))
c = r.content
c64 = base64.b64encode(c)
tag_template = '<img width="150" height="150" src="data:image/jpg;base64, {}">'
return tag_template.format(c64.decode('utf-8'))
def _isTOA(self):
if self.level.lower() in ['l1c', 'level-1c', 'toa', 'level1c']:
return True
else:
return False
@property
def plevel(self):
return 'Level-1C' if self._isTOA() else 'Level-2A'
def gee_ic_id(self):
""" return GEE image collection id """
toa = 'COPERNICUS/S2'
sr = 'COPERNICUS/S2_SR'
return toa if self._isTOA() else sr
def gee_ic(self):
return "ee.ImageCollection({})".format(self.gee_ic_id())
def _product_id_to_gee_id(self, pid):
pinfo = self.products[pid]
identifier = pinfo['identifier']
datastrip = pinfo['datastripidentifier']
one = identifier.split('_')[2]
two = datastrip.split('_')[7][1:]
three = identifier.split('_')[5]
return '{}_{}_{}'.format(one, two, three)
def gee_image(self, pid):
icid = self.gee_ic_id()
iid = self._product_id_to_gee_id(pid)
return "ee.Image('{}/{}')".format(icid, iid)
def code_editor(self, pid):
template = 'var i = {}; print(i)'
return template.format(self.gee_image(pid))
def _createGeoJSON(self):
polyDict = {
'type': 'Polygon',
'coordinates': [self.coordlist]
}
return polyDict
@property
def footprint(self):
""" Get footprint from coordinates """
# coords format: 'lon lat lon lat....'
geojson = self._createGeoJSON()
return geojson_to_wkt(geojson, 14)
def _get_hub_ids(self):
ids = []
for pid, v in dict(self.products).items():
for key, value in v.items():
if key == self.match:
if value not in ids:
ids.append([value, pid])
return ids
def check(self):
hubIDs = self._get_hub_ids()
data = []
for hid, pid in hubIDs:
online = self.api.is_online(pid)
code = self.code_editor(pid)
img = self.preview_tag(pid)
final = [hid, hid in self.ingeelist, online, code, img]
data.append(final)
return data
def _format_row(self, row):
esaid, ingee, online, code, img = row
av = 'YES' if ingee else 'NO'
onl = 'YES' if online else 'NO'
color = 'green' if ingee else 'red'
return self.ROW.format(color=color, esaid=esaid,
ingee=av, online=onl,
codeeditor=code, preview=img)
def create_html(self):
""" Products is a list of ((esaID, available on gee, online in ESA,
code in code editor), ...) """
rows = self.check()
htmlrows = ""
for row in rows:
data = self._format_row(row)
htmlrows += data
return self.TEMPLATE.format(content=htmlrows)