s2-rut-python 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docs/conf.py +149 -0
- examples/run_example.py +117 -0
- examples/temporary_example.py +202 -0
- s2_rut_python/__init__.py +9 -0
- s2_rut_python/_vendor.py +19 -0
- s2_rut_python/_version.py +21 -0
- s2_rut_python/interface.py +500 -0
- s2_rut_python/tests/__init__.py +0 -0
- s2_rut_python/tests/test_interface.py +291 -0
- s2_rut_python-0.0.1.dist-info/METADATA +127 -0
- s2_rut_python-0.0.1.dist-info/RECORD +18 -0
- s2_rut_python-0.0.1.dist-info/WHEEL +5 -0
- s2_rut_python-0.0.1.dist-info/licenses/LICENSE +165 -0
- s2_rut_python-0.0.1.dist-info/top_level.txt +4 -0
- third-party/Source/S2RUT.py +477 -0
- third-party/Source/S2Reader.py +695 -0
- third-party/Source/S2Reader_band.py +675 -0
- third-party/run_rut.py +303 -0
third-party/run_rut.py
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
#!/bin/python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
@author: aderu
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os, sys
|
|
8
|
+
import json
|
|
9
|
+
import argparse
|
|
10
|
+
import shutil
|
|
11
|
+
from matplotlib import pyplot as plt
|
|
12
|
+
import numpy as np
|
|
13
|
+
import netCDF4 as nc
|
|
14
|
+
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
|
15
|
+
from Source.S2Reader import S2Processor
|
|
16
|
+
from Source.S2RUT import S2RUT_L1
|
|
17
|
+
|
|
18
|
+
S2_BAND_NAMES = [
|
|
19
|
+
"B01",
|
|
20
|
+
"B02",
|
|
21
|
+
"B03",
|
|
22
|
+
"B04",
|
|
23
|
+
"B05",
|
|
24
|
+
"B06",
|
|
25
|
+
"B07",
|
|
26
|
+
"B08",
|
|
27
|
+
"B8A",
|
|
28
|
+
"B09",
|
|
29
|
+
"B10",
|
|
30
|
+
"B11",
|
|
31
|
+
"B12",
|
|
32
|
+
]
|
|
33
|
+
S2_BAND_SAMPLING = {
|
|
34
|
+
"B01": 60,
|
|
35
|
+
"B02": 10,
|
|
36
|
+
"B03": 10,
|
|
37
|
+
"B04": 10,
|
|
38
|
+
"B05": 20,
|
|
39
|
+
"B06": 20,
|
|
40
|
+
"B07": 20,
|
|
41
|
+
"B08": 10,
|
|
42
|
+
"B8A": 20,
|
|
43
|
+
"B09": 60,
|
|
44
|
+
"B10": 60,
|
|
45
|
+
"B11": 20,
|
|
46
|
+
"B12": 20,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def json_none(param):
|
|
51
|
+
if param == "None" or param == "":
|
|
52
|
+
return None
|
|
53
|
+
else:
|
|
54
|
+
return float(param)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def run_s2rut_image(config):
|
|
58
|
+
"""
|
|
59
|
+
S2-L1C uncertainty computation for full image or AOI, without spectral error correlation.
|
|
60
|
+
Work band per band to minimize RAM consumption.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
config : str, path of config file
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
-------
|
|
68
|
+
Save uncertainty product in reflectance dimension
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
# check if inputs bands are not none
|
|
73
|
+
if config["input_bands"] is None:
|
|
74
|
+
bandlist = S2_BAND_NAMES
|
|
75
|
+
else:
|
|
76
|
+
bandlist = config["input_bands"]
|
|
77
|
+
|
|
78
|
+
# check uncertainty type to output
|
|
79
|
+
fname = os.path.basename(config["input_L1C"]).split(".")[0]
|
|
80
|
+
|
|
81
|
+
print("S2 RUT L1: image/AOI uncertainty")
|
|
82
|
+
print("Processing:", os.path.basename(config["input_L1C"]))
|
|
83
|
+
print("Processing bands:", bandlist)
|
|
84
|
+
do_plot = config["doplot"]
|
|
85
|
+
do_cont = config["unc_per_contributor"]
|
|
86
|
+
if do_cont:
|
|
87
|
+
print("warning: computing unc contributors takes a long time!")
|
|
88
|
+
|
|
89
|
+
# process individually each band to avoid RAM consumption in case of full image
|
|
90
|
+
for i, band in enumerate(bandlist):
|
|
91
|
+
print(band)
|
|
92
|
+
s2proc = S2Processor()
|
|
93
|
+
s2proc.product = config["input_L1C"]
|
|
94
|
+
s2proc.noise_model = config["input_noise_model"]
|
|
95
|
+
s2proc.output = config["path_output"]
|
|
96
|
+
s2proc.selected_bands = [band]
|
|
97
|
+
s2proc.lat_centre = json_none(config["roi_lat"])
|
|
98
|
+
s2proc.lon_centre = json_none(config["roi_lon"])
|
|
99
|
+
s2proc.w = json_none(config["roi_width"])
|
|
100
|
+
s2proc.h = json_none(config["roi_height"])
|
|
101
|
+
|
|
102
|
+
# check if roi size is larger than 1 pixel
|
|
103
|
+
roi_pix_x = json_none(config["roi_width"]) / S2_BAND_SAMPLING[band]
|
|
104
|
+
roi_pix_y = json_none(config["roi_height"]) / S2_BAND_SAMPLING[band]
|
|
105
|
+
if roi_pix_x < 2 or roi_pix_y < 2:
|
|
106
|
+
print("ERROR: ROI size is less than 2 pixels, skipping band")
|
|
107
|
+
continue
|
|
108
|
+
|
|
109
|
+
# retrieve L1C radiometry
|
|
110
|
+
s2proc.get_data(get_va=False, doplot=False)
|
|
111
|
+
img = s2proc.L1C_ref[0]
|
|
112
|
+
|
|
113
|
+
# Compute uncertainty (absolute value, in reflectance dimension)
|
|
114
|
+
RUTl1 = S2RUT_L1(config["input_contributors"])
|
|
115
|
+
u_ref, u_cont = RUTl1.unc_calculation_abs(
|
|
116
|
+
img, band, 0, s2proc.metadatadict, s2proc.sun_zenith, do_contributor=do_cont
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# write output product
|
|
120
|
+
newfile = os.path.join(s2proc.output, fname, band + "_unc_abs.jp2")
|
|
121
|
+
s2proc.write_unc(u_ref, newfile, band, s2proc.ds_profile[0])
|
|
122
|
+
if do_cont:
|
|
123
|
+
# write each contributor
|
|
124
|
+
for u in u_cont.keys():
|
|
125
|
+
print(" ", u)
|
|
126
|
+
newfile = os.path.join(
|
|
127
|
+
s2proc.output, fname, "contributors", band + "_" + u + ".jp2"
|
|
128
|
+
)
|
|
129
|
+
s2proc.write_unc(u_cont[u], newfile, band, s2proc.ds_profile[0])
|
|
130
|
+
|
|
131
|
+
# copy input parameter for tracing configuration
|
|
132
|
+
shutil.copy2(config["input_contributors"], os.path.dirname(newfile))
|
|
133
|
+
|
|
134
|
+
# Plot
|
|
135
|
+
if do_plot:
|
|
136
|
+
fig1, ax1 = plt.subplots(1, 2, figsize=(8, 5))
|
|
137
|
+
plt.subplots_adjust(
|
|
138
|
+
left=0.05, bottom=0.1, right=0.9, top=0.9, wspace=0.3, hspace=0.1
|
|
139
|
+
)
|
|
140
|
+
im0 = ax1[0].imshow(img, interpolation="None")
|
|
141
|
+
ax1[0].set_title(band + " Reflectance")
|
|
142
|
+
divider = make_axes_locatable(ax1[0])
|
|
143
|
+
cax = divider.append_axes("right", size="5%", pad=0.05)
|
|
144
|
+
cb = fig1.colorbar(
|
|
145
|
+
im0, cax=cax, orientation="vertical", label="Reflectance"
|
|
146
|
+
)
|
|
147
|
+
cb.ax.tick_params(labelsize=8)
|
|
148
|
+
|
|
149
|
+
img[img == 0] = np.nan
|
|
150
|
+
im1 = ax1[1].imshow(
|
|
151
|
+
u_ref * 100 / img,
|
|
152
|
+
interpolation="None",
|
|
153
|
+
vmax=np.nanmean(u_ref * 100 / img) * 3,
|
|
154
|
+
)
|
|
155
|
+
ax1[1].set_title(band + " Uncertainties ")
|
|
156
|
+
divider = make_axes_locatable(ax1[1])
|
|
157
|
+
cax = divider.append_axes("right", size="5%", pad=0.05)
|
|
158
|
+
cb = fig1.colorbar(im1, cax=cax, orientation="vertical", label="unc [%]")
|
|
159
|
+
cb.ax.tick_params(labelsize=8)
|
|
160
|
+
|
|
161
|
+
for ax in ax1:
|
|
162
|
+
ax.tick_params(axis="both", which="major", labelsize=8)
|
|
163
|
+
fig1.savefig(os.path.join(s2proc.output, fname, band + "_unc_plot.png"))
|
|
164
|
+
|
|
165
|
+
del u_ref, u_cont
|
|
166
|
+
|
|
167
|
+
# Show all plots at once
|
|
168
|
+
plt.show()
|
|
169
|
+
print("Output files written in", config["path_output"])
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def run_s2rut_spectralcorr(config):
|
|
173
|
+
"""
|
|
174
|
+
S2-L1C uncertainty computation with spectral error correlation.
|
|
175
|
+
Uncetainties computed for all bands, but only for a single pixel.
|
|
176
|
+
!!! NOT AVAILABLE YET !!!
|
|
177
|
+
|
|
178
|
+
Parameters
|
|
179
|
+
----------
|
|
180
|
+
config : str, path of config file
|
|
181
|
+
|
|
182
|
+
Returns
|
|
183
|
+
-------
|
|
184
|
+
None.
|
|
185
|
+
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
print("S2 RUT L1: spectral error correlation uncertainty")
|
|
189
|
+
print("Only available for a single pixel : AOI size set to 1 pixel")
|
|
190
|
+
do_plot = config["doplot"]
|
|
191
|
+
|
|
192
|
+
s2proc = S2Processor()
|
|
193
|
+
s2proc.product = config["input_L1C"]
|
|
194
|
+
s2proc.noise_model = config["input_noise_model"]
|
|
195
|
+
s2proc.output = config["path_output"]
|
|
196
|
+
s2proc.lat_centre = json_none(config["roi_lat"])
|
|
197
|
+
s2proc.lon_centre = json_none(config["roi_lon"])
|
|
198
|
+
|
|
199
|
+
# hard coded parameters in this mode
|
|
200
|
+
s2proc.selected_bands = [
|
|
201
|
+
"B01",
|
|
202
|
+
"B02",
|
|
203
|
+
"B03",
|
|
204
|
+
"B04",
|
|
205
|
+
"B05",
|
|
206
|
+
"B06",
|
|
207
|
+
"B07",
|
|
208
|
+
"B08",
|
|
209
|
+
"B09",
|
|
210
|
+
"B10",
|
|
211
|
+
"B11",
|
|
212
|
+
"B12",
|
|
213
|
+
]
|
|
214
|
+
s2proc.w = 1
|
|
215
|
+
s2proc.h = 1
|
|
216
|
+
|
|
217
|
+
# Retrieve L1C radiometry
|
|
218
|
+
s2proc.get_data(get_va=False, doplot=False)
|
|
219
|
+
|
|
220
|
+
# Compute uncertainty
|
|
221
|
+
RUTl1 = S2RUT_L1(config["input_contributors"])
|
|
222
|
+
unc = []
|
|
223
|
+
for i, band in enumerate(s2proc.selected_bands):
|
|
224
|
+
# u_ref, u_sig, u_sys, u_cont = RUTl1.unc_calculation(s2proc.L1C_ref[i], band, s2proc.metadatadict, s2proc.sun_zenith)
|
|
225
|
+
u_ref = RUTl1.unc_calculation(
|
|
226
|
+
s2proc.L1C_ref[i], band, i, s2proc.metadatadict, s2proc.sun_zenith
|
|
227
|
+
)
|
|
228
|
+
unc.append(u_ref)
|
|
229
|
+
|
|
230
|
+
# Compute Spectral Error correlation
|
|
231
|
+
nsamp = config["SEC_sample"]
|
|
232
|
+
u_corr = np.array(
|
|
233
|
+
RUTl1.unc_spectralcorrelation(s2proc.L1C_rad, s2proc.metadatadict, nsamp)
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# write output
|
|
237
|
+
fname = os.path.basename(config["input_L1C"]).split(".")[0]
|
|
238
|
+
new_file = os.path.join(
|
|
239
|
+
config["path_output"], fname, "spectral_err_corr_" + str(nsamp) + ".nc"
|
|
240
|
+
)
|
|
241
|
+
s2proc.write_spectral_corr_error(unc, u_corr, new_file)
|
|
242
|
+
|
|
243
|
+
if do_plot:
|
|
244
|
+
plt.figure()
|
|
245
|
+
plt.plot(np.squeeze(unc))
|
|
246
|
+
plt.title("unc for given pixel")
|
|
247
|
+
plt.xlabel("bands")
|
|
248
|
+
plt.ylabel("unc [%]")
|
|
249
|
+
|
|
250
|
+
plt.figure()
|
|
251
|
+
for i in range(nsamp):
|
|
252
|
+
plt.plot(u_corr[:, i])
|
|
253
|
+
plt.title("unc spectral correlation per band")
|
|
254
|
+
plt.xlabel("bands")
|
|
255
|
+
plt.ylabel("unc [%]")
|
|
256
|
+
|
|
257
|
+
# Show all plots at once
|
|
258
|
+
plt.show()
|
|
259
|
+
|
|
260
|
+
fname = os.path.join(
|
|
261
|
+
config["path_output"],
|
|
262
|
+
os.path.basename(config["input_L1C"]).split(".")[0] + ".nc",
|
|
263
|
+
)
|
|
264
|
+
f = nc.Dataset(fname, "w", format="NETCDF4")
|
|
265
|
+
f.createDimension("bands", len(s2proc.selected_bands))
|
|
266
|
+
f.createDimension("sample", config["SEC_sample"])
|
|
267
|
+
var1 = f.createVariable("pixel_unc", "f4", ("bands"))
|
|
268
|
+
var2 = f.createVariable("spectral_correlation_error", "f4", ("bands", "sample"))
|
|
269
|
+
var1[:] = np.squeeze(unc)
|
|
270
|
+
var2[:] = u_corr
|
|
271
|
+
f.history = "S2-RUT-L1 spectrale correlation error"
|
|
272
|
+
f.close()
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
#### MAIN
|
|
276
|
+
if __name__ == "__main__":
|
|
277
|
+
parser = argparse.ArgumentParser(
|
|
278
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
279
|
+
description="S2-RUT-L1C tool",
|
|
280
|
+
)
|
|
281
|
+
parser.add_argument("config_file", help="path of RUT config file")
|
|
282
|
+
args = parser.parse_args()
|
|
283
|
+
|
|
284
|
+
# try:
|
|
285
|
+
# Read config file
|
|
286
|
+
with open(args.config_file) as f:
|
|
287
|
+
config = json.load(f)
|
|
288
|
+
|
|
289
|
+
# check if contributor file exists
|
|
290
|
+
fcontrib = config["input_contributors"]
|
|
291
|
+
if not os.path.exists(fcontrib):
|
|
292
|
+
print("ERROR: uncertainty contributor file is missing")
|
|
293
|
+
print("check Data/input_contributors.json in repository")
|
|
294
|
+
sys.exit()
|
|
295
|
+
|
|
296
|
+
# launch RUT
|
|
297
|
+
run_s2rut_image(config)
|
|
298
|
+
|
|
299
|
+
# except Exception as error:
|
|
300
|
+
# print("An error occurred:", error)
|
|
301
|
+
# exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
302
|
+
# fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
|
|
303
|
+
# print(exc_type, fname, exc_tb.tb_lineno)
|