grdwindinversion 0.3.2__py3-none-any.whl → 0.3.5__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.
- grdwindinversion/__init__.py +1 -1
- grdwindinversion/gradientFeatures.py +204 -138
- grdwindinversion/inversion.py +730 -421
- grdwindinversion/load_config.py +10 -7
- grdwindinversion/main.py +71 -28
- grdwindinversion/utils.py +22 -16
- grdwindinversion/utils_memory.py +20 -22
- {grdwindinversion-0.3.2.dist-info → grdwindinversion-0.3.5.dist-info}/METADATA +2 -2
- grdwindinversion-0.3.5.dist-info/RECORD +22 -0
- {grdwindinversion-0.3.2.dist-info → grdwindinversion-0.3.5.dist-info}/WHEEL +1 -1
- grdwindinversion-0.3.2.dist-info/RECORD +0 -22
- {grdwindinversion-0.3.2.dist-info → grdwindinversion-0.3.5.dist-info}/AUTHORS.rst +0 -0
- {grdwindinversion-0.3.2.dist-info → grdwindinversion-0.3.5.dist-info}/LICENSE +0 -0
- {grdwindinversion-0.3.2.dist-info → grdwindinversion-0.3.5.dist-info}/entry_points.txt +0 -0
- {grdwindinversion-0.3.2.dist-info → grdwindinversion-0.3.5.dist-info}/top_level.txt +0 -0
grdwindinversion/inversion.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
# To place here in the code to not have errors with cv2.
|
|
2
|
+
# if placed in main => error ..
|
|
1
3
|
import tempfile
|
|
2
4
|
import traceback
|
|
3
|
-
|
|
4
5
|
import xsar
|
|
5
6
|
import xsarsea
|
|
6
7
|
from xsarsea import windspeed
|
|
@@ -9,17 +10,28 @@ import xarray as xr
|
|
|
9
10
|
import numpy as np
|
|
10
11
|
import sys
|
|
11
12
|
import datetime
|
|
12
|
-
import os
|
|
13
13
|
import yaml
|
|
14
14
|
from scipy.ndimage import binary_dilation
|
|
15
|
-
|
|
16
15
|
import re
|
|
17
16
|
import string
|
|
18
|
-
import os
|
|
19
17
|
from grdwindinversion.utils import check_incidence_range, get_pol_ratio_name, timing
|
|
20
18
|
from grdwindinversion.load_config import getConf
|
|
21
|
-
# optional debug messages
|
|
22
19
|
import logging
|
|
20
|
+
import os
|
|
21
|
+
|
|
22
|
+
os.environ["OMP_NUM_THREADS"] = "1"
|
|
23
|
+
os.environ["OPENBLAS_NUM_THREADS"] = "1"
|
|
24
|
+
os.environ["MKL_NUM_THREADS"] = "1"
|
|
25
|
+
os.environ["VECLIB_MAXIMUM_THREADS"] = "1"
|
|
26
|
+
os.environ["NUMEXPR_NUM_THREADS"] = "1"
|
|
27
|
+
try:
|
|
28
|
+
import cv2
|
|
29
|
+
except:
|
|
30
|
+
import cv2
|
|
31
|
+
cv2.setNumThreads(1)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# optional debug messages
|
|
23
35
|
logger = logging.getLogger('grdwindinversion.inversion')
|
|
24
36
|
logger.addHandler(logging.NullHandler())
|
|
25
37
|
|
|
@@ -38,25 +50,28 @@ def getSensorMetaDataset(filename):
|
|
|
38
50
|
tuple
|
|
39
51
|
sensor name, sensor long name, meta function, dataset function
|
|
40
52
|
"""
|
|
41
|
-
if
|
|
53
|
+
if "S1A" in filename:
|
|
42
54
|
return "S1A", "SENTINEL-1 A", xsar.Sentinel1Meta, xsar.Sentinel1Dataset
|
|
43
|
-
elif
|
|
55
|
+
elif "S1B" in filename:
|
|
44
56
|
return "S1B", "SENTINEL-1 B", xsar.Sentinel1Meta, xsar.Sentinel1Dataset
|
|
45
|
-
elif
|
|
57
|
+
elif "RS2" in filename:
|
|
46
58
|
return "RS2", "RADARSAT-2", xsar.RadarSat2Meta, xsar.RadarSat2Dataset
|
|
47
|
-
elif
|
|
59
|
+
elif "RCM1" in filename:
|
|
48
60
|
return "RCM", "RADARSAT Constellation 1", xsar.RcmMeta, xsar.RcmDataset
|
|
49
|
-
elif
|
|
61
|
+
elif "RCM2" in filename:
|
|
50
62
|
return "RCM", "RADARSAT Constellation 2", xsar.RcmMeta, xsar.RcmDataset
|
|
51
|
-
elif
|
|
63
|
+
elif "RCM3" in filename:
|
|
52
64
|
return "RCM", "RADARSAT Constellation 3", xsar.RcmMeta, xsar.RcmDataset
|
|
53
65
|
|
|
54
66
|
else:
|
|
55
67
|
raise ValueError(
|
|
56
|
-
"must be S1A|S1B|RS2|RCM1|RCM2|RCM3, got filename %s" % filename
|
|
68
|
+
"must be S1A|S1B|RS2|RCM1|RCM2|RCM3, got filename %s" % filename
|
|
69
|
+
)
|
|
57
70
|
|
|
58
71
|
|
|
59
|
-
def
|
|
72
|
+
def getOutputName(
|
|
73
|
+
input_file, outdir, sensor, meta_start_date, meta_stop_date, subdir=True
|
|
74
|
+
):
|
|
60
75
|
"""
|
|
61
76
|
Create output filename for L2-GRD product
|
|
62
77
|
|
|
@@ -68,8 +83,10 @@ def getOutputName2(input_file, outdir, sensor, meta, subdir=True):
|
|
|
68
83
|
output folder
|
|
69
84
|
sensor : str
|
|
70
85
|
sensor name
|
|
71
|
-
|
|
72
|
-
|
|
86
|
+
start_date : str
|
|
87
|
+
start date
|
|
88
|
+
stop_date : str
|
|
89
|
+
stop date
|
|
73
90
|
|
|
74
91
|
Returns
|
|
75
92
|
-------
|
|
@@ -78,33 +95,68 @@ def getOutputName2(input_file, outdir, sensor, meta, subdir=True):
|
|
|
78
95
|
"""
|
|
79
96
|
basename = os.path.basename(input_file)
|
|
80
97
|
basename_match = basename
|
|
81
|
-
meta_start_date = meta.start_date.split(".")[0].replace(
|
|
82
|
-
"-", "").replace(":", "").replace(" ", "t").replace("Z", "")
|
|
83
|
-
meta_stop_date = meta.stop_date.split(".")[0].replace(
|
|
84
|
-
"-", "").replace(":", "").replace(" ", "t").replace("Z", "")
|
|
85
98
|
|
|
86
|
-
if sensor ==
|
|
99
|
+
if sensor == "S1A" or sensor == "S1B":
|
|
87
100
|
regex = re.compile(
|
|
88
|
-
"(...)_(..)_(...)(.)_(.)(.)(..)_(........T......)_(........T......)_(......)_(......)_(....).SAFE"
|
|
101
|
+
"(...)_(..)_(...)(.)_(.)(.)(..)_(........T......)_(........T......)_(......)_(......)_(....).SAFE"
|
|
102
|
+
)
|
|
89
103
|
template = string.Template(
|
|
90
|
-
"${MISSIONID}_${BEAM}_${PRODUCT}${RESOLUTION}_${LEVEL}${CLASS}${POL}_${STARTDATE}_${STOPDATE}_${ORBIT}_${TAKEID}_${PRODID}.SAFE"
|
|
104
|
+
"${MISSIONID}_${BEAM}_${PRODUCT}${RESOLUTION}_${LEVEL}${CLASS}${POL}_${STARTDATE}_${STOPDATE}_${ORBIT}_${TAKEID}_${PRODID}.SAFE"
|
|
105
|
+
)
|
|
91
106
|
match = regex.match(basename_match)
|
|
92
|
-
|
|
107
|
+
if not match:
|
|
108
|
+
raise AttributeError(
|
|
109
|
+
f"S1 file {basename_match} does not match the expected pattern"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
(
|
|
113
|
+
MISSIONID,
|
|
114
|
+
BEAM,
|
|
115
|
+
PRODUCT,
|
|
116
|
+
RESOLUTION,
|
|
117
|
+
LEVEL,
|
|
118
|
+
CLASS,
|
|
119
|
+
POL,
|
|
120
|
+
STARTDATE,
|
|
121
|
+
STOPDATE,
|
|
122
|
+
ORBIT,
|
|
123
|
+
TAKEID,
|
|
124
|
+
PRODID,
|
|
125
|
+
) = match.groups()
|
|
93
126
|
new_format = f"{MISSIONID.lower()}-{BEAM.lower()}-owi-xx-{STARTDATE.lower()}-{STOPDATE.lower()}-{ORBIT}-{TAKEID}.nc"
|
|
94
|
-
elif sensor ==
|
|
127
|
+
elif sensor == "RS2":
|
|
95
128
|
regex = re.compile(
|
|
96
|
-
"(RS2)_OK([0-9]+)_PK([0-9]+)_DK([0-9]+)_(....)_(........)_(......)_(.._?.?.?)_(S.F)"
|
|
129
|
+
"(RS2)_OK([0-9]+)_PK([0-9]+)_DK([0-9]+)_(....)_(........)_(......)_(.._?.?.?)_(S.F)"
|
|
130
|
+
)
|
|
97
131
|
template = string.Template(
|
|
98
|
-
"${MISSIONID}_OK${DATA1}_PK${DATA2}_DK${DATA3}_${DATA4}_${DATE}_${TIME}_${POLARIZATION}_${LAST}"
|
|
132
|
+
"${MISSIONID}_OK${DATA1}_PK${DATA2}_DK${DATA3}_${DATA4}_${DATE}_${TIME}_${POLARIZATION}_${LAST}"
|
|
133
|
+
)
|
|
99
134
|
match = regex.match(basename_match)
|
|
100
|
-
|
|
135
|
+
if not match:
|
|
136
|
+
raise AttributeError(
|
|
137
|
+
f"RC2 file {basename_match} does not match the expected pattern"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
MISSIONID, DATA1, DATA2, DATA3, DATA4, DATE, TIME, POLARIZATION, LAST = (
|
|
141
|
+
match.groups()
|
|
142
|
+
)
|
|
101
143
|
new_format = f"{MISSIONID.lower()}--owi-xx-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
|
|
102
|
-
elif sensor ==
|
|
144
|
+
elif sensor == "RCM":
|
|
145
|
+
|
|
103
146
|
regex = re.compile(
|
|
104
|
-
r"(RCM[0-9])_OK([0-9]+)_PK([0-9]+)_([0-9]+)_([A-
|
|
147
|
+
r"(RCM[0-9])_OK([0-9]+)_PK([0-9]+)_([0-9]+)_([A-Z0-9]+)_(\d{8})_(\d{6})_([A-Z]{2}(?:_[A-Z]{2})?)_([A-Z]+)$"
|
|
148
|
+
)
|
|
105
149
|
match = regex.match(basename_match)
|
|
106
|
-
|
|
150
|
+
if not match:
|
|
151
|
+
raise AttributeError(
|
|
152
|
+
f"RCM file {basename_match} does not match the expected pattern"
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
MISSIONID, DATA1, DATA2, DATA3, BEAM, DATE, TIME, POLARIZATION, PRODUCT = (
|
|
156
|
+
match.groups()
|
|
157
|
+
)
|
|
107
158
|
new_format = f"{MISSIONID.lower()}-{BEAM.lower()}-owi-xx-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
|
|
159
|
+
|
|
108
160
|
else:
|
|
109
161
|
raise ValueError(
|
|
110
162
|
"sensor must be S1A|S1B|RS2|RCM, got sensor %s" % sensor)
|
|
@@ -116,7 +168,7 @@ def getOutputName2(input_file, outdir, sensor, meta, subdir=True):
|
|
|
116
168
|
return out_file
|
|
117
169
|
|
|
118
170
|
|
|
119
|
-
def getAncillary(meta, ancillary_name=
|
|
171
|
+
def getAncillary(meta, ancillary_name="ecmwf"):
|
|
120
172
|
"""
|
|
121
173
|
Map ancillary wind from ECMWF or ERA5.
|
|
122
174
|
This function is used to check if the model files are available and to map the model to the SAR data.
|
|
@@ -131,28 +183,34 @@ def getAncillary(meta, ancillary_name='ecmwf'):
|
|
|
131
183
|
map model to SAR data
|
|
132
184
|
"""
|
|
133
185
|
|
|
134
|
-
if ancillary_name ==
|
|
186
|
+
if ancillary_name == "ecmwf":
|
|
135
187
|
|
|
136
|
-
logging.debug(
|
|
137
|
-
ec01 = getConf()[
|
|
138
|
-
ec0125 = getConf()[
|
|
139
|
-
logging.debug(
|
|
140
|
-
meta.set_raster(
|
|
141
|
-
meta.set_raster(
|
|
188
|
+
logging.debug("conf: %s", getConf())
|
|
189
|
+
ec01 = getConf()["ecmwf_0100_1h"]
|
|
190
|
+
ec0125 = getConf()["ecmwf_0125_1h"]
|
|
191
|
+
logging.debug("ec01 : %s", ec01)
|
|
192
|
+
meta.set_raster("ecmwf_0100_1h", ec01)
|
|
193
|
+
meta.set_raster("ecmwf_0125_1h", ec0125)
|
|
142
194
|
|
|
143
195
|
map_model = None
|
|
144
196
|
# only keep best ecmwf (FIXME: it's hacky, and xsar should provide a better method to handle this)
|
|
145
|
-
for ecmwf_name in [
|
|
197
|
+
for ecmwf_name in ["ecmwf_0125_1h", "ecmwf_0100_1h"]:
|
|
146
198
|
ecmwf_infos = meta.rasters.loc[ecmwf_name]
|
|
147
199
|
try:
|
|
148
|
-
ecmwf_file = ecmwf_infos[
|
|
149
|
-
|
|
150
|
-
|
|
200
|
+
ecmwf_file = ecmwf_infos["get_function"](
|
|
201
|
+
ecmwf_infos["resource"],
|
|
202
|
+
date=datetime.datetime.strptime(
|
|
203
|
+
meta.start_date, "%Y-%m-%d %H:%M:%S.%f"
|
|
204
|
+
),
|
|
205
|
+
)[1]
|
|
151
206
|
# temporary for RCM issue https://github.com/umr-lops/xarray-safe-rcm/issues/34
|
|
152
207
|
except Exception as e:
|
|
153
|
-
ecmwf_file = ecmwf_infos[
|
|
154
|
-
|
|
155
|
-
|
|
208
|
+
ecmwf_file = ecmwf_infos["get_function"](
|
|
209
|
+
ecmwf_infos["resource"],
|
|
210
|
+
date=datetime.datetime.strptime(
|
|
211
|
+
meta.start_date, "%Y-%m-%d %H:%M:%S"
|
|
212
|
+
),
|
|
213
|
+
)[1]
|
|
156
214
|
if not os.path.isfile(ecmwf_file):
|
|
157
215
|
# temporary
|
|
158
216
|
# if repro does not exist we look at not repro folder (only one will exist after)
|
|
@@ -179,41 +237,58 @@ def getAncillary(meta, ancillary_name='ecmwf'):
|
|
|
179
237
|
"""
|
|
180
238
|
meta.rasters = meta.rasters.drop([ecmwf_name])
|
|
181
239
|
else:
|
|
182
|
-
map_model = {
|
|
183
|
-
|
|
240
|
+
map_model = {
|
|
241
|
+
"%s_%s" % (ecmwf_name, uv): "model_%s" % uv for uv in ["U10", "V10"]
|
|
242
|
+
}
|
|
184
243
|
|
|
185
244
|
return map_model
|
|
186
245
|
|
|
187
|
-
elif ancillary_name ==
|
|
246
|
+
elif ancillary_name == "era5":
|
|
188
247
|
era5_name = "era5_0250_1h"
|
|
189
|
-
logging.debug(
|
|
248
|
+
logging.debug("conf: %s", getConf())
|
|
190
249
|
era0250 = getConf()[era5_name]
|
|
191
|
-
logging.debug(
|
|
250
|
+
logging.debug("%s : %s", (era5_name, era0250))
|
|
192
251
|
meta.set_raster(era5_name, era0250)
|
|
193
252
|
|
|
194
253
|
era5_infos = meta.rasters.loc[era5_name]
|
|
195
254
|
try:
|
|
196
|
-
era5_file = era5_infos[
|
|
197
|
-
|
|
198
|
-
|
|
255
|
+
era5_file = era5_infos["get_function"](
|
|
256
|
+
era5_infos["resource"],
|
|
257
|
+
date=datetime.datetime.strptime(
|
|
258
|
+
meta.start_date, "%Y-%m-%d %H:%M:%S.%f"
|
|
259
|
+
),
|
|
260
|
+
)[1]
|
|
199
261
|
except Exception as e:
|
|
200
|
-
era5_file = era5_infos[
|
|
201
|
-
|
|
202
|
-
|
|
262
|
+
era5_file = era5_infos["get_function"](
|
|
263
|
+
era5_infos["resource"],
|
|
264
|
+
date=datetime.datetime.strptime(
|
|
265
|
+
meta.start_date, "%Y-%m-%d %H:%M:%S"),
|
|
266
|
+
)[1]
|
|
203
267
|
if not os.path.isfile(era5_file):
|
|
204
268
|
raise ValueError(f"era5 file {era5_file} not found")
|
|
205
269
|
|
|
206
|
-
map_model = {
|
|
207
|
-
|
|
270
|
+
map_model = {
|
|
271
|
+
"%s_%s" % (era5_name, uv): "model_%s" % uv for uv in ["U10", "V10"]
|
|
272
|
+
}
|
|
208
273
|
return map_model
|
|
209
274
|
|
|
210
275
|
else:
|
|
211
|
-
raise ValueError(
|
|
212
|
-
|
|
276
|
+
raise ValueError(
|
|
277
|
+
"ancillary_name must be ecmwf/era5, got %s" % ancillary_name)
|
|
213
278
|
|
|
214
279
|
|
|
215
280
|
@timing(logger=logger.debug)
|
|
216
|
-
def inverse(
|
|
281
|
+
def inverse(
|
|
282
|
+
dual_pol,
|
|
283
|
+
inc,
|
|
284
|
+
sigma0,
|
|
285
|
+
sigma0_dual,
|
|
286
|
+
ancillary_wind,
|
|
287
|
+
dsig_cr,
|
|
288
|
+
model_co,
|
|
289
|
+
model_cross,
|
|
290
|
+
**kwargs,
|
|
291
|
+
):
|
|
217
292
|
"""
|
|
218
293
|
Invert sigma0 to retrieve wind using model (lut or gmf).
|
|
219
294
|
|
|
@@ -251,14 +326,19 @@ def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_c
|
|
|
251
326
|
"""
|
|
252
327
|
logging.debug("inversion")
|
|
253
328
|
|
|
254
|
-
list_mods =
|
|
255
|
-
|
|
329
|
+
list_mods = (
|
|
330
|
+
windspeed.available_models().index.tolist()
|
|
331
|
+
+ windspeed.available_models().alias.tolist()
|
|
332
|
+
+ [None]
|
|
333
|
+
)
|
|
256
334
|
if model_co not in list_mods:
|
|
257
335
|
raise ValueError(
|
|
258
|
-
f"model_co {model_co} not in windspeed.available_models() : not going further"
|
|
336
|
+
f"model_co {model_co} not in windspeed.available_models() : not going further"
|
|
337
|
+
)
|
|
259
338
|
if model_cross not in list_mods:
|
|
260
339
|
raise ValueError(
|
|
261
|
-
f"model_cross {model_cross} not in windspeed.available_models() : not going further"
|
|
340
|
+
f"model_cross {model_cross} not in windspeed.available_models() : not going further"
|
|
341
|
+
)
|
|
262
342
|
|
|
263
343
|
winds = windspeed.invert_from_model(
|
|
264
344
|
inc,
|
|
@@ -267,7 +347,8 @@ def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_c
|
|
|
267
347
|
ancillary_wind=ancillary_wind,
|
|
268
348
|
dsig_cr=dsig_cr,
|
|
269
349
|
model=(model_co, model_cross),
|
|
270
|
-
**kwargs
|
|
350
|
+
**kwargs,
|
|
351
|
+
)
|
|
271
352
|
|
|
272
353
|
if dual_pol:
|
|
273
354
|
wind_co, wind_dual = winds
|
|
@@ -277,7 +358,8 @@ def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_c
|
|
|
277
358
|
sigma0_dual.values,
|
|
278
359
|
dsig_cr=dsig_cr.values,
|
|
279
360
|
model=model_cross,
|
|
280
|
-
**kwargs
|
|
361
|
+
**kwargs,
|
|
362
|
+
)
|
|
281
363
|
|
|
282
364
|
return wind_co, wind_dual, wind_cross
|
|
283
365
|
else:
|
|
@@ -309,38 +391,42 @@ def makeL2asOwi(xr_dataset, config):
|
|
|
309
391
|
--------
|
|
310
392
|
"""
|
|
311
393
|
|
|
312
|
-
xr_dataset = xr_dataset.rename(
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
394
|
+
xr_dataset = xr_dataset.rename(
|
|
395
|
+
{
|
|
396
|
+
"longitude": "owiLon",
|
|
397
|
+
"latitude": "owiLat",
|
|
398
|
+
"incidence": "owiIncidenceAngle",
|
|
399
|
+
"elevation": "owiElevationAngle",
|
|
400
|
+
"ground_heading": "owiHeading",
|
|
401
|
+
"land_mask": "owiLandFlag",
|
|
402
|
+
"mask": "owiMask",
|
|
403
|
+
"windspeed_co": "owiWindSpeed_co",
|
|
404
|
+
"winddir_co": "owiWindDirection_co",
|
|
405
|
+
"ancillary_wind_speed": "owiAncillaryWindSpeed",
|
|
406
|
+
"ancillary_wind_direction": "owiAncillaryWindDirection",
|
|
407
|
+
"sigma0_detrend": "owiNrcs_detrend",
|
|
408
|
+
}
|
|
409
|
+
)
|
|
326
410
|
|
|
327
411
|
if "offboresight" in xr_dataset:
|
|
328
412
|
xr_dataset = xr_dataset.rename(
|
|
329
413
|
{"offboresight": "owiOffboresightAngle"})
|
|
330
414
|
|
|
331
415
|
if config["add_nrcs_model"]:
|
|
332
|
-
xr_dataset = xr_dataset.rename(
|
|
333
|
-
{"ancillary_nrcs": "owiAncillaryNrcs"})
|
|
416
|
+
xr_dataset = xr_dataset.rename({"ancillary_nrcs": "owiAncillaryNrcs"})
|
|
334
417
|
xr_dataset.owiAncillaryNrcs.attrs["units"] = "m^2 / m^2"
|
|
335
|
-
xr_dataset.owiAncillaryNrcs.attrs[
|
|
336
|
-
|
|
418
|
+
xr_dataset.owiAncillaryNrcs.attrs["long_name"] = (
|
|
419
|
+
f"Ancillary Normalized Radar Cross Section - simulated from {config['l2_params']['copol_gmf']} & ancillary wind"
|
|
420
|
+
)
|
|
337
421
|
|
|
338
422
|
if config["l2_params"]["dual_pol"]:
|
|
339
423
|
xr_dataset = xr_dataset.rename(
|
|
340
|
-
{"ancillary_nrcs_cross": "owiAncillaryNrcs_cross"}
|
|
424
|
+
{"ancillary_nrcs_cross": "owiAncillaryNrcs_cross"}
|
|
425
|
+
)
|
|
341
426
|
xr_dataset.owiAncillaryNrcs_cross.attrs["units"] = "m^2 / m^2"
|
|
342
|
-
xr_dataset.owiAncillaryNrcs_cross.attrs[
|
|
343
|
-
|
|
427
|
+
xr_dataset.owiAncillaryNrcs_cross.attrs["long_name"] = (
|
|
428
|
+
f"Ancillary Normalized Radar Cross Section - simulated from {config['l2_params']['crosspol_gmf']} & ancillary wind"
|
|
429
|
+
)
|
|
344
430
|
|
|
345
431
|
xr_dataset.owiLon.attrs["units"] = "degrees_east"
|
|
346
432
|
xr_dataset.owiLon.attrs["long_name"] = "Longitude at wind cell center"
|
|
@@ -351,146 +437,196 @@ def makeL2asOwi(xr_dataset, config):
|
|
|
351
437
|
xr_dataset.owiLat.attrs["standard_name"] = "latitude"
|
|
352
438
|
|
|
353
439
|
xr_dataset.owiIncidenceAngle.attrs["units"] = "degrees"
|
|
354
|
-
xr_dataset.owiIncidenceAngle.attrs["long_name"] =
|
|
440
|
+
xr_dataset.owiIncidenceAngle.attrs["long_name"] = (
|
|
441
|
+
"Incidence angle at wind cell center"
|
|
442
|
+
)
|
|
355
443
|
xr_dataset.owiIncidenceAngle.attrs["standard_name"] = "incidence"
|
|
356
444
|
|
|
357
445
|
xr_dataset.owiElevationAngle.attrs["units"] = "degrees"
|
|
358
|
-
xr_dataset.owiElevationAngle.attrs["long_name"] =
|
|
446
|
+
xr_dataset.owiElevationAngle.attrs["long_name"] = (
|
|
447
|
+
"Elevation angle at wind cell center"
|
|
448
|
+
)
|
|
359
449
|
xr_dataset.owiElevationAngle.attrs["standard_name"] = "elevation"
|
|
360
450
|
|
|
361
|
-
xr_dataset[
|
|
362
|
-
pol=config["l2_params"]["copol"]
|
|
451
|
+
xr_dataset["owiNrcs"] = xr_dataset["sigma0_ocean"].sel(
|
|
452
|
+
pol=config["l2_params"]["copol"]
|
|
453
|
+
)
|
|
363
454
|
xr_dataset.owiNrcs.attrs = xr_dataset.sigma0_ocean.attrs
|
|
364
|
-
xr_dataset.owiNrcs.attrs[
|
|
365
|
-
xr_dataset.owiNrcs.attrs[
|
|
366
|
-
xr_dataset.owiNrcs.attrs[
|
|
455
|
+
xr_dataset.owiNrcs.attrs["units"] = "m^2 / m^2"
|
|
456
|
+
xr_dataset.owiNrcs.attrs["long_name"] = "Normalized Radar Cross Section"
|
|
457
|
+
xr_dataset.owiNrcs.attrs["definition"] = "owiNrcs_no_noise_correction - owiNesz"
|
|
367
458
|
|
|
368
|
-
xr_dataset[
|
|
369
|
-
pol=config["l2_params"]["copol"]
|
|
459
|
+
xr_dataset["owiMask_Nrcs"] = xr_dataset["sigma0_mask"].sel(
|
|
460
|
+
pol=config["l2_params"]["copol"]
|
|
461
|
+
)
|
|
370
462
|
xr_dataset.owiMask_Nrcs.attrs = xr_dataset.sigma0_mask.attrs
|
|
371
463
|
|
|
372
464
|
# NESZ & DSIG
|
|
373
465
|
xr_dataset = xr_dataset.assign(
|
|
374
|
-
owiNesz=(
|
|
375
|
-
|
|
376
|
-
|
|
466
|
+
owiNesz=(
|
|
467
|
+
["line", "sample"],
|
|
468
|
+
xr_dataset.nesz.sel(pol=config["l2_params"]["copol"]).values,
|
|
469
|
+
)
|
|
470
|
+
)
|
|
471
|
+
xr_dataset.owiNesz.attrs["units"] = "m^2 / m^2"
|
|
472
|
+
xr_dataset.owiNesz.attrs["long_name"] = "Noise Equivalent SigmaNaught"
|
|
377
473
|
|
|
378
|
-
xr_dataset[
|
|
379
|
-
pol=config["l2_params"]["copol"]
|
|
474
|
+
xr_dataset["owiNrcs_no_noise_correction"] = xr_dataset["sigma0_ocean_raw"].sel(
|
|
475
|
+
pol=config["l2_params"]["copol"]
|
|
476
|
+
)
|
|
380
477
|
xr_dataset.owiNrcs_no_noise_correction.attrs = xr_dataset.sigma0_ocean_raw.attrs
|
|
381
|
-
xr_dataset.owiNrcs_no_noise_correction.attrs[
|
|
382
|
-
xr_dataset.owiNrcs_no_noise_correction.attrs[
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
478
|
+
xr_dataset.owiNrcs_no_noise_correction.attrs["units"] = "m^2 / m^2"
|
|
479
|
+
xr_dataset.owiNrcs_no_noise_correction.attrs["long_name"] = (
|
|
480
|
+
"Normalized Radar Cross Section ; no noise correction applied"
|
|
481
|
+
)
|
|
482
|
+
xr_dataset.owiNrcs_no_noise_correction.attrs["comment"] = (
|
|
483
|
+
"owiNrcs_no_noise_correction ; no recalibration"
|
|
484
|
+
)
|
|
386
485
|
|
|
387
|
-
if
|
|
388
|
-
xr_dataset = xr_dataset.rename(
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
486
|
+
if "swath_number" in xr_dataset:
|
|
487
|
+
xr_dataset = xr_dataset.rename(
|
|
488
|
+
{
|
|
489
|
+
"swath_number": "owiSwathNumber",
|
|
490
|
+
"swath_number_flag": "owiSwathNumberFlag",
|
|
491
|
+
}
|
|
492
|
+
)
|
|
392
493
|
|
|
393
494
|
xr_dataset["owiSwathNumber"].attrs["standart_name"] = "swath number"
|
|
394
495
|
|
|
395
496
|
# sigma0_raw__corrected cross
|
|
396
497
|
if "sigma0_raw__corrected" in xr_dataset:
|
|
397
|
-
xr_dataset[
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs[
|
|
404
|
-
|
|
498
|
+
xr_dataset["owiNrcs_no_noise_correction_recalibrated"] = xr_dataset[
|
|
499
|
+
"sigma0_raw__corrected"
|
|
500
|
+
].sel(pol=config["l2_params"]["copol"])
|
|
501
|
+
xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs = (
|
|
502
|
+
xr_dataset.sigma0_raw__corrected.attrs
|
|
503
|
+
)
|
|
504
|
+
xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs["units"] = "m^2 / m^2"
|
|
505
|
+
xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs["long_name"] = (
|
|
506
|
+
"Normalized Radar Cross Section, no noise correction applied"
|
|
507
|
+
)
|
|
508
|
+
xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs["comment"] = (
|
|
509
|
+
"owiNrcs_no_noise_correction ; recalibrated with kersten method"
|
|
510
|
+
)
|
|
405
511
|
|
|
406
|
-
xr_dataset.owiNrcs.attrs[
|
|
512
|
+
xr_dataset.owiNrcs.attrs["definition"] = (
|
|
513
|
+
"owiNrcs_no_noise_correction_recalibrated - owiNesz"
|
|
514
|
+
)
|
|
407
515
|
|
|
408
516
|
if config["l2_params"]["dual_pol"]:
|
|
409
|
-
|
|
410
517
|
xr_dataset = xr_dataset.rename({
|
|
411
518
|
'dsig_cross': 'owiDsig_cross',
|
|
412
519
|
'winddir_cross': 'owiWindDirection_cross',
|
|
413
520
|
'winddir_dual': 'owiWindDirection',
|
|
414
521
|
'windspeed_cross': 'owiWindSpeed_cross',
|
|
415
522
|
'windspeed_dual': 'owiWindSpeed',
|
|
416
|
-
'sigma0_detrend_cross': 'owiNrcs_detrend_cross'
|
|
523
|
+
'sigma0_detrend_cross': 'owiNrcs_detrend_cross',
|
|
524
|
+
'nesz_cross_flattened': 'owiNesz_cross_flattened'
|
|
417
525
|
})
|
|
418
526
|
|
|
419
|
-
if config["apply_flattening"]:
|
|
420
|
-
xr_dataset = xr_dataset.rename({
|
|
421
|
-
'nesz_cross_flattened': 'owiNesz_cross_flattened',
|
|
422
|
-
})
|
|
423
|
-
|
|
424
527
|
# nrcs cross
|
|
425
|
-
xr_dataset[
|
|
426
|
-
pol=config["l2_params"]["crosspol"]
|
|
528
|
+
xr_dataset["owiNrcs_cross"] = xr_dataset["sigma0_ocean"].sel(
|
|
529
|
+
pol=config["l2_params"]["crosspol"]
|
|
530
|
+
)
|
|
427
531
|
|
|
428
|
-
xr_dataset.owiNrcs_cross.attrs[
|
|
429
|
-
xr_dataset.owiNrcs_cross.attrs[
|
|
430
|
-
xr_dataset.owiNrcs_cross.attrs[
|
|
532
|
+
xr_dataset.owiNrcs_cross.attrs["units"] = "m^2 / m^2"
|
|
533
|
+
xr_dataset.owiNrcs_cross.attrs["long_name"] = "Normalized Radar Cross Section"
|
|
534
|
+
xr_dataset.owiNrcs_cross.attrs["definition"] = (
|
|
535
|
+
"owiNrcs_cross_no_noise_correction - owiNesz_cross"
|
|
536
|
+
)
|
|
431
537
|
|
|
432
|
-
xr_dataset[
|
|
433
|
-
pol=config["l2_params"]["crosspol"]
|
|
538
|
+
xr_dataset["owiMask_Nrcs_cross"] = xr_dataset["sigma0_mask"].sel(
|
|
539
|
+
pol=config["l2_params"]["crosspol"]
|
|
540
|
+
)
|
|
434
541
|
xr_dataset.owiMask_Nrcs_cross.attrs = xr_dataset.sigma0_mask.attrs
|
|
435
542
|
|
|
436
543
|
# nesz cross
|
|
437
|
-
xr_dataset = xr_dataset.assign(
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
544
|
+
xr_dataset = xr_dataset.assign(
|
|
545
|
+
owiNesz_cross=(
|
|
546
|
+
["line", "sample"],
|
|
547
|
+
xr_dataset.nesz.sel(
|
|
548
|
+
pol=config["l2_params"]["crosspol"]).values,
|
|
549
|
+
)
|
|
550
|
+
) # no flattening
|
|
551
|
+
xr_dataset.owiNesz_cross.attrs["units"] = "m^2 / m^2"
|
|
552
|
+
xr_dataset.owiNesz_cross.attrs["long_name"] = "Noise Equivalent SigmaNaught"
|
|
553
|
+
|
|
554
|
+
xr_dataset.owiNesz_cross_flattened.attrs["units"] = "m^2 / m^2"
|
|
555
|
+
xr_dataset.owiNesz_cross_flattened.attrs["long_name"] = "Noise Equivalent SigmaNaught"
|
|
441
556
|
|
|
442
|
-
xr_dataset[
|
|
443
|
-
|
|
557
|
+
xr_dataset["owiNrcs_cross_no_noise_correction"] = xr_dataset[
|
|
558
|
+
"sigma0_ocean_raw"
|
|
559
|
+
].sel(pol=config["l2_params"]["crosspol"])
|
|
444
560
|
|
|
445
|
-
xr_dataset.owiNrcs_cross_no_noise_correction.attrs[
|
|
446
|
-
xr_dataset.owiNrcs_cross_no_noise_correction.attrs[
|
|
447
|
-
|
|
561
|
+
xr_dataset.owiNrcs_cross_no_noise_correction.attrs["units"] = "m^2 / m^2"
|
|
562
|
+
xr_dataset.owiNrcs_cross_no_noise_correction.attrs["long_name"] = (
|
|
563
|
+
"Normalized Radar Cross Section, no noise correction applied"
|
|
564
|
+
)
|
|
448
565
|
|
|
449
566
|
# sigma0_raw__corrected cross
|
|
450
567
|
if "sigma0_raw__corrected" in xr_dataset:
|
|
451
|
-
xr_dataset[
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs
|
|
568
|
+
xr_dataset["owiNrcs_cross_no_noise_correction_recalibrated"] = xr_dataset[
|
|
569
|
+
"sigma0_raw__corrected"
|
|
570
|
+
].sel(pol=config["l2_params"]["crosspol"])
|
|
571
|
+
xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs = (
|
|
572
|
+
xr_dataset.sigma0_raw__corrected.attrs
|
|
573
|
+
)
|
|
574
|
+
xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs["units"] = (
|
|
575
|
+
"m^2 / m^2"
|
|
576
|
+
)
|
|
455
577
|
xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs[
|
|
456
|
-
|
|
578
|
+
"long_name"
|
|
579
|
+
] = "Normalized Radar Cross Section ; no noise correction applied"
|
|
457
580
|
xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs[
|
|
458
|
-
|
|
581
|
+
"comment"
|
|
582
|
+
] = "owiNrcs_cross_no_noise_correction ; recalibrated with kersten method"
|
|
459
583
|
|
|
460
|
-
xr_dataset.owiNrcs_cross.attrs[
|
|
584
|
+
xr_dataset.owiNrcs_cross.attrs["definition"] = (
|
|
585
|
+
"owiNrcs_cross_no_noise_correction_recalibrated - owiNesz_cross"
|
|
586
|
+
)
|
|
461
587
|
|
|
462
588
|
if config["add_gradientsfeatures"]:
|
|
463
|
-
xr_dataset = xr_dataset.rename({
|
|
464
|
-
'heterogeneity_mask': 'owiWindFilter'
|
|
465
|
-
})
|
|
589
|
+
xr_dataset = xr_dataset.rename({"heterogeneity_mask": "owiWindFilter"})
|
|
466
590
|
else:
|
|
467
|
-
xr_dataset[
|
|
468
|
-
xr_dataset[
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
xr_dataset[
|
|
473
|
-
|
|
591
|
+
xr_dataset["owiWindFilter"] = xr.full_like(xr_dataset.owiNrcs, 0)
|
|
592
|
+
xr_dataset["owiWindFilter"].attrs[
|
|
593
|
+
"long_name"
|
|
594
|
+
] = "Quality flag taking into account the local heterogeneity"
|
|
595
|
+
xr_dataset["owiWindFilter"].attrs["valid_range"] = np.array([0, 3])
|
|
596
|
+
xr_dataset["owiWindFilter"].attrs["flag_values"] = np.array([
|
|
597
|
+
0, 1, 2, 3])
|
|
598
|
+
xr_dataset["owiWindFilter"].attrs[
|
|
599
|
+
"flag_meanings"
|
|
600
|
+
] = "homogeneous_NRCS, heterogeneous_from_co-polarization_NRCS, heterogeneous_from_cross-polarization_NRCS, heterogeneous_from_dual-polarization_NRCS"
|
|
474
601
|
|
|
475
602
|
# other variables
|
|
476
603
|
|
|
477
|
-
xr_dataset[
|
|
478
|
-
xr_dataset[
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
xr_dataset[
|
|
482
|
-
|
|
483
|
-
xr_dataset[
|
|
484
|
-
xr_dataset[
|
|
604
|
+
xr_dataset["owiWindQuality"] = xr.full_like(xr_dataset.owiNrcs, 0)
|
|
605
|
+
xr_dataset["owiWindQuality"].attrs[
|
|
606
|
+
"long_name"
|
|
607
|
+
] = "Quality flag taking into account the consistency_between_wind_inverted_and_NRCS_and_Doppler_measured"
|
|
608
|
+
xr_dataset["owiWindQuality"].attrs["valid_range"] = np.array([0, 3])
|
|
609
|
+
xr_dataset["owiWindQuality"].attrs["flag_values"] = np.array([0, 1, 2, 3])
|
|
610
|
+
xr_dataset["owiWindQuality"].attrs["flag_meanings"] = "good medium low poor"
|
|
611
|
+
xr_dataset["owiWindQuality"].attrs["comment"] = "NOT COMPUTED YET"
|
|
485
612
|
|
|
486
613
|
xr_dataset = xr_dataset.rename(
|
|
487
614
|
{"line": "owiAzSize", "sample": "owiRaSize"})
|
|
488
615
|
|
|
489
616
|
xr_dataset = xr_dataset.drop_vars(
|
|
490
|
-
[
|
|
491
|
-
|
|
617
|
+
[
|
|
618
|
+
"sigma0_ocean",
|
|
619
|
+
"sigma0",
|
|
620
|
+
"sigma0_ocean_raw",
|
|
621
|
+
"sigma0_raw",
|
|
622
|
+
"ancillary_wind",
|
|
623
|
+
"nesz",
|
|
624
|
+
"spatial_ref",
|
|
625
|
+
]
|
|
626
|
+
)
|
|
627
|
+
if "sigma0_raw__corrected" in xr_dataset:
|
|
492
628
|
xr_dataset = xr_dataset.drop_vars(["sigma0_raw__corrected"])
|
|
493
|
-
xr_dataset = xr_dataset.drop_dims([
|
|
629
|
+
xr_dataset = xr_dataset.drop_dims(["pol"])
|
|
494
630
|
|
|
495
631
|
table_fillValue = {
|
|
496
632
|
"owiWindQuality": -1,
|
|
@@ -509,17 +645,24 @@ def makeL2asOwi(xr_dataset, config):
|
|
|
509
645
|
for var in list(set(xr_dataset.coords.keys()) | set(xr_dataset.keys())):
|
|
510
646
|
encoding[var] = {}
|
|
511
647
|
try:
|
|
512
|
-
encoding[var].update({
|
|
648
|
+
encoding[var].update({"_FillValue": table_fillValue[var]})
|
|
513
649
|
except:
|
|
514
|
-
if
|
|
515
|
-
encoding[var].update({
|
|
650
|
+
if var in ["owiWindSpeed_co", "owiWindSpeed_cross", "owiWindSpeed"]:
|
|
651
|
+
encoding[var].update({"_FillValue": -9999.0})
|
|
516
652
|
else:
|
|
517
|
-
encoding[var].update({
|
|
653
|
+
encoding[var].update({"_FillValue": None})
|
|
518
654
|
|
|
519
655
|
return xr_dataset, encoding
|
|
520
656
|
|
|
521
657
|
|
|
522
|
-
def preprocess(
|
|
658
|
+
def preprocess(
|
|
659
|
+
filename,
|
|
660
|
+
outdir,
|
|
661
|
+
config_path,
|
|
662
|
+
overwrite=False,
|
|
663
|
+
add_gradientsfeatures=False,
|
|
664
|
+
resolution="1000m",
|
|
665
|
+
):
|
|
523
666
|
"""
|
|
524
667
|
Main function to generate L2 product.
|
|
525
668
|
|
|
@@ -546,11 +689,8 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_gradientsfeat
|
|
|
546
689
|
filename)
|
|
547
690
|
|
|
548
691
|
if os.path.exists(config_path):
|
|
549
|
-
with open(config_path,
|
|
550
|
-
config_base = yaml.load(
|
|
551
|
-
file,
|
|
552
|
-
Loader=yaml.FullLoader
|
|
553
|
-
)
|
|
692
|
+
with open(config_path, "r") as file:
|
|
693
|
+
config_base = yaml.load(file, Loader=yaml.FullLoader)
|
|
554
694
|
try:
|
|
555
695
|
# check if sensor is in the config
|
|
556
696
|
config = config_base[sensor]
|
|
@@ -558,15 +698,20 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_gradientsfeat
|
|
|
558
698
|
raise KeyError("sensor %s not in this config" % sensor)
|
|
559
699
|
else:
|
|
560
700
|
raise FileNotFoundError(
|
|
561
|
-
|
|
701
|
+
"config_path do not exists, got %s " % config_path)
|
|
562
702
|
|
|
563
703
|
recalibration = config["recalibration"]
|
|
564
704
|
meta = fct_meta(filename)
|
|
565
705
|
|
|
566
706
|
# si une des deux n'est pas VV VH HH HV on ne fait rien
|
|
567
|
-
if not all([pol in ["VV", "VH", "HH", "HV"] for pol in meta.pols.split(
|
|
707
|
+
if not all([pol in ["VV", "VH", "HH", "HV"] for pol in meta.pols.split(" ")]):
|
|
568
708
|
raise ValueError(f"Polarisation non gérée : meta.pols = {meta.pols}")
|
|
569
709
|
|
|
710
|
+
overwrite_cfg = config_base.get("overwrite", None)
|
|
711
|
+
# If overwrite is specified in config, it will overwrite the value given as argument (which defaults to False)
|
|
712
|
+
if overwrite_cfg is not None:
|
|
713
|
+
overwrite = overwrite_cfg
|
|
714
|
+
|
|
570
715
|
no_subdir_cfg = config_base.get("no_subdir", False)
|
|
571
716
|
config["no_subdir"] = no_subdir_cfg
|
|
572
717
|
|
|
@@ -575,34 +720,53 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_gradientsfeat
|
|
|
575
720
|
else:
|
|
576
721
|
winddir_convention = "meteorological"
|
|
577
722
|
logging.warning(
|
|
578
|
-
f'Using meteorological convention because "winddir_convention" was not found in config.'
|
|
723
|
+
f'Using meteorological convention because "winddir_convention" was not found in config.'
|
|
724
|
+
)
|
|
579
725
|
config["winddir_convention"] = winddir_convention
|
|
580
726
|
|
|
581
727
|
if "add_gradientsfeatures" in config_base:
|
|
582
728
|
add_gradientsfeatures = config_base["add_gradientsfeatures"]
|
|
583
729
|
else:
|
|
584
730
|
add_gradientsfeatures = False
|
|
585
|
-
logging.warning(
|
|
586
|
-
f'Not computing gradients by default')
|
|
731
|
+
logging.warning(f"Not computing gradients by default")
|
|
587
732
|
config["add_gradientsfeatures"] = add_gradientsfeatures
|
|
588
733
|
|
|
589
734
|
if "add_nrcs_model" in config_base:
|
|
590
735
|
add_nrcs_model = config_base["add_nrcs_model"]
|
|
591
736
|
add_nrcs_model = False
|
|
592
737
|
logging.warning(
|
|
593
|
-
f
|
|
594
|
-
)
|
|
738
|
+
f"Force add_nrcs_model to be false, before fixing an issue")
|
|
595
739
|
else:
|
|
596
740
|
add_nrcs_model = False
|
|
597
|
-
logging.warning(
|
|
598
|
-
f'Not computing nrcs from model by default')
|
|
741
|
+
logging.warning(f"Not computing nrcs from model by default")
|
|
599
742
|
config["add_nrcs_model"] = add_nrcs_model
|
|
600
743
|
|
|
601
744
|
# creating a dictionnary of parameters
|
|
602
745
|
config["l2_params"] = {}
|
|
603
746
|
|
|
604
|
-
|
|
605
|
-
|
|
747
|
+
meta_start_date = (
|
|
748
|
+
meta.start_date.split(".")[0]
|
|
749
|
+
.replace("-", "")
|
|
750
|
+
.replace(":", "")
|
|
751
|
+
.replace(" ", "t")
|
|
752
|
+
.replace("Z", "")
|
|
753
|
+
)
|
|
754
|
+
meta_stop_date = (
|
|
755
|
+
meta.stop_date.split(".")[0]
|
|
756
|
+
.replace("-", "")
|
|
757
|
+
.replace(":", "")
|
|
758
|
+
.replace(" ", "t")
|
|
759
|
+
.replace("Z", "")
|
|
760
|
+
)
|
|
761
|
+
|
|
762
|
+
out_file = getOutputName(
|
|
763
|
+
filename,
|
|
764
|
+
outdir,
|
|
765
|
+
sensor,
|
|
766
|
+
meta_start_date,
|
|
767
|
+
meta_stop_date,
|
|
768
|
+
subdir=not no_subdir_cfg,
|
|
769
|
+
)
|
|
606
770
|
|
|
607
771
|
if os.path.exists(out_file) and overwrite is False:
|
|
608
772
|
raise FileExistsError("outfile %s already exists" % out_file)
|
|
@@ -611,37 +775,48 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_gradientsfeat
|
|
|
611
775
|
map_model = getAncillary(meta, ancillary_name)
|
|
612
776
|
if map_model is None:
|
|
613
777
|
raise Exception(
|
|
614
|
-
f"the weather model is not set `map_model` is None -> you probably don't have access to {ancillary_name} archive"
|
|
778
|
+
f"the weather model is not set `map_model` is None -> you probably don't have access to {ancillary_name} archive"
|
|
779
|
+
)
|
|
615
780
|
|
|
616
781
|
try:
|
|
617
|
-
if (
|
|
782
|
+
if (recalibration) & ("SENTINEL" in sensor_longname):
|
|
618
783
|
logging.info(
|
|
619
|
-
f
|
|
784
|
+
f"recalibration is {recalibration} : Kersten formula is applied"
|
|
785
|
+
)
|
|
620
786
|
xsar_dataset = fct_dataset(
|
|
621
|
-
meta, resolution=resolution, recalibration=recalibration
|
|
622
|
-
|
|
623
|
-
xr_dataset =
|
|
624
|
-
|
|
787
|
+
meta, resolution=resolution, recalibration=recalibration
|
|
788
|
+
)
|
|
789
|
+
xr_dataset = xsar_dataset.datatree["measurement"].to_dataset()
|
|
790
|
+
xr_dataset = xr_dataset.merge(
|
|
791
|
+
xsar_dataset.datatree["recalibration"].to_dataset()[
|
|
792
|
+
["swath_number", "swath_number_flag", "sigma0_raw__corrected"]
|
|
793
|
+
]
|
|
794
|
+
)
|
|
625
795
|
|
|
626
796
|
else:
|
|
627
797
|
logging.info(
|
|
628
|
-
f
|
|
629
|
-
|
|
798
|
+
f"recalibration is {recalibration} : Kersten formula is not applied"
|
|
799
|
+
)
|
|
800
|
+
if "SENTINEL" in sensor_longname:
|
|
630
801
|
xsar_dataset = fct_dataset(
|
|
631
|
-
meta, resolution=resolution, recalibration=recalibration
|
|
632
|
-
|
|
633
|
-
xr_dataset =
|
|
634
|
-
|
|
802
|
+
meta, resolution=resolution, recalibration=recalibration
|
|
803
|
+
)
|
|
804
|
+
xr_dataset = xsar_dataset.datatree["measurement"].to_dataset()
|
|
805
|
+
xr_dataset = xr_dataset.merge(
|
|
806
|
+
xsar_dataset.datatree["recalibration"].to_dataset()[
|
|
807
|
+
["swath_number", "swath_number_flag"]
|
|
808
|
+
]
|
|
809
|
+
)
|
|
635
810
|
|
|
636
811
|
else:
|
|
637
812
|
xsar_dataset = fct_dataset(meta, resolution=resolution)
|
|
638
|
-
xr_dataset = xsar_dataset.datatree[
|
|
813
|
+
xr_dataset = xsar_dataset.datatree["measurement"].to_dataset()
|
|
639
814
|
|
|
640
815
|
xr_dataset = xr_dataset.rename(map_model)
|
|
641
816
|
xr_dataset.attrs = xsar_dataset.dataset.attrs
|
|
642
817
|
|
|
643
818
|
except Exception as e:
|
|
644
|
-
logging.info(
|
|
819
|
+
logging.info("%s", traceback.format_exc())
|
|
645
820
|
logging.error(e)
|
|
646
821
|
sys.exit(-1)
|
|
647
822
|
|
|
@@ -659,22 +834,24 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_gradientsfeat
|
|
|
659
834
|
else:
|
|
660
835
|
dual_pol = False
|
|
661
836
|
|
|
662
|
-
if
|
|
663
|
-
copol =
|
|
664
|
-
crosspol =
|
|
665
|
-
copol_gmf =
|
|
666
|
-
crosspol_gmf =
|
|
837
|
+
if "VV" in xr_dataset.pol.values:
|
|
838
|
+
copol = "VV"
|
|
839
|
+
crosspol = "VH"
|
|
840
|
+
copol_gmf = "VV"
|
|
841
|
+
crosspol_gmf = "VH"
|
|
667
842
|
else:
|
|
668
|
-
logging.warning(
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
843
|
+
logging.warning(
|
|
844
|
+
"for now this processor does not support entirely HH+HV acquisitions\n "
|
|
845
|
+
"it wont crash but it will use HH+VH GMF for wind inversion -> wrong hypothesis\n "
|
|
846
|
+
"!! dual WIND SPEED IS NOT USABLE !! But co WIND SPEED IS USABLE !!"
|
|
847
|
+
)
|
|
848
|
+
copol = "HH"
|
|
849
|
+
crosspol = "HV"
|
|
850
|
+
copol_gmf = "HH"
|
|
851
|
+
crosspol_gmf = "VH"
|
|
675
852
|
|
|
676
|
-
model_co = config["GMF_"+copol_gmf+"_NAME"]
|
|
677
|
-
model_cross = config["GMF_"+crosspol_gmf+"_NAME"]
|
|
853
|
+
model_co = config["GMF_" + copol_gmf + "_NAME"]
|
|
854
|
+
model_cross = config["GMF_" + crosspol_gmf + "_NAME"]
|
|
678
855
|
|
|
679
856
|
# register paramaters in config
|
|
680
857
|
config["l2_params"]["dual_pol"] = dual_pol
|
|
@@ -693,16 +870,37 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_gradientsfeat
|
|
|
693
870
|
if len(nc_luts) > 0:
|
|
694
871
|
windspeed.register_nc_luts(getConf()["nc_luts_path"])
|
|
695
872
|
|
|
696
|
-
if
|
|
873
|
+
if model_co == "gmf_cmod7":
|
|
697
874
|
windspeed.register_cmod7(getConf()["lut_cmod7_path"])
|
|
698
875
|
# Step 2 - clean and prepare dataset
|
|
699
876
|
|
|
700
877
|
# variables to not keep in the L2
|
|
701
|
-
black_list = [
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
878
|
+
black_list = [
|
|
879
|
+
"digital_number",
|
|
880
|
+
"gamma0_raw",
|
|
881
|
+
"negz",
|
|
882
|
+
"azimuth_time",
|
|
883
|
+
"slant_range_time",
|
|
884
|
+
"velocity",
|
|
885
|
+
"range_ground_spacing",
|
|
886
|
+
"gamma0",
|
|
887
|
+
"time",
|
|
888
|
+
"nd_co",
|
|
889
|
+
"nd_cr",
|
|
890
|
+
"gamma0_lut",
|
|
891
|
+
"sigma0_lut",
|
|
892
|
+
"noise_lut_range",
|
|
893
|
+
"lineSpacing",
|
|
894
|
+
"sampleSpacing",
|
|
895
|
+
"noise_lut",
|
|
896
|
+
"noise_lut_azi",
|
|
897
|
+
"nebz",
|
|
898
|
+
"beta0_raw",
|
|
899
|
+
"lines_flipped",
|
|
900
|
+
"samples_flipped",
|
|
901
|
+
"altitude",
|
|
902
|
+
"beta0",
|
|
903
|
+
]
|
|
706
904
|
variables = list(set(xr_dataset) - set(black_list))
|
|
707
905
|
xr_dataset = xr_dataset[variables]
|
|
708
906
|
|
|
@@ -729,122 +927,191 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_gradientsfeat
|
|
|
729
927
|
# TOREMOVE
|
|
730
928
|
if "offboresight" in xr_dataset:
|
|
731
929
|
xr_dataset.offboresight.attrs["units"] = "degrees"
|
|
732
|
-
xr_dataset.offboresight.attrs["long_name"] =
|
|
930
|
+
xr_dataset.offboresight.attrs["long_name"] = (
|
|
931
|
+
"Offboresight angle at wind cell center"
|
|
932
|
+
)
|
|
733
933
|
xr_dataset.elevation.attrs["standard_name"] = "offboresight"
|
|
734
934
|
|
|
735
935
|
# masks (no ice / no_valid)
|
|
736
|
-
xr_dataset.land_mask.values = binary_dilation(
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
xr_dataset.land_mask.attrs[
|
|
936
|
+
xr_dataset.land_mask.values = binary_dilation(
|
|
937
|
+
xr_dataset["land_mask"].values.astype("uint8"),
|
|
938
|
+
structure=np.ones((3, 3), np.uint8),
|
|
939
|
+
iterations=3,
|
|
940
|
+
)
|
|
941
|
+
xr_dataset.land_mask.attrs["long_name"] = "Mask of data"
|
|
942
|
+
xr_dataset.land_mask.attrs["valid_range"] = np.array([0, 1])
|
|
943
|
+
xr_dataset.land_mask.attrs["flag_values"] = np.array([0, 1])
|
|
944
|
+
xr_dataset.land_mask.attrs["flag_meanings"] = "valid no_valid"
|
|
742
945
|
|
|
743
946
|
logging.debug("mask is a copy of land_mask")
|
|
744
947
|
|
|
745
|
-
xr_dataset[
|
|
948
|
+
xr_dataset["mask"] = xr.DataArray(xr_dataset.land_mask)
|
|
746
949
|
xr_dataset.mask.attrs = {}
|
|
747
|
-
xr_dataset.mask.attrs[
|
|
748
|
-
xr_dataset.mask.attrs[
|
|
749
|
-
xr_dataset.mask.attrs[
|
|
750
|
-
xr_dataset.mask.attrs[
|
|
950
|
+
xr_dataset.mask.attrs["long_name"] = "Mask of data"
|
|
951
|
+
xr_dataset.mask.attrs["valid_range"] = np.array([0, 3])
|
|
952
|
+
xr_dataset.mask.attrs["flag_values"] = np.array([0, 1, 2, 3])
|
|
953
|
+
xr_dataset.mask.attrs["flag_meanings"] = "valid land ice no_valid"
|
|
751
954
|
|
|
752
955
|
# ancillary
|
|
753
|
-
xr_dataset[
|
|
754
|
-
90. - np.rad2deg(np.arctan2(xr_dataset.model_V10,
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
xr_dataset[
|
|
761
|
-
xr_dataset[
|
|
762
|
-
|
|
763
|
-
xr_dataset[
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
xr_dataset[
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
xr_dataset[
|
|
775
|
-
|
|
776
|
-
xr_dataset[
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
956
|
+
xr_dataset["ancillary_wind_direction"] = (
|
|
957
|
+
90.0 - np.rad2deg(np.arctan2(xr_dataset.model_V10,
|
|
958
|
+
xr_dataset.model_U10)) + 180
|
|
959
|
+
) % 360
|
|
960
|
+
|
|
961
|
+
xr_dataset["ancillary_wind_direction"] = xr.where(
|
|
962
|
+
xr_dataset["mask"], np.nan, xr_dataset["ancillary_wind_direction"]
|
|
963
|
+
).transpose(*xr_dataset["ancillary_wind_direction"].dims)
|
|
964
|
+
xr_dataset["ancillary_wind_direction"].attrs = {}
|
|
965
|
+
xr_dataset["ancillary_wind_direction"].attrs["units"] = "degrees_north"
|
|
966
|
+
xr_dataset["ancillary_wind_direction"].attrs[
|
|
967
|
+
"long_name"
|
|
968
|
+
] = f"{ancillary_name} wind direction in meteorological convention (clockwise, from), ex: 0°=from north, 90°=from east"
|
|
969
|
+
xr_dataset["ancillary_wind_direction"].attrs["standart_name"] = "wind_direction"
|
|
970
|
+
|
|
971
|
+
xr_dataset["ancillary_wind_speed"] = np.sqrt(
|
|
972
|
+
xr_dataset["model_U10"] ** 2 + xr_dataset["model_V10"] ** 2
|
|
973
|
+
)
|
|
974
|
+
xr_dataset["ancillary_wind_speed"] = xr.where(
|
|
975
|
+
xr_dataset["mask"], np.nan, xr_dataset["ancillary_wind_speed"]
|
|
976
|
+
).transpose(*xr_dataset["ancillary_wind_speed"].dims)
|
|
977
|
+
xr_dataset["ancillary_wind_speed"].attrs = {}
|
|
978
|
+
xr_dataset["ancillary_wind_speed"].attrs["units"] = "m s^-1"
|
|
979
|
+
xr_dataset["ancillary_wind_speed"].attrs[
|
|
980
|
+
"long_name"
|
|
981
|
+
] = f"{ancillary_name} wind speed"
|
|
982
|
+
xr_dataset["ancillary_wind_speed"].attrs["standart_name"] = "wind_speed"
|
|
983
|
+
|
|
984
|
+
xr_dataset["ancillary_wind"] = xr.where(
|
|
985
|
+
xr_dataset["mask"],
|
|
986
|
+
np.nan,
|
|
987
|
+
(
|
|
988
|
+
xr_dataset.ancillary_wind_speed
|
|
989
|
+
* np.exp(
|
|
990
|
+
1j
|
|
991
|
+
* xsarsea.dir_meteo_to_sample(
|
|
992
|
+
xr_dataset.ancillary_wind_direction, xr_dataset.ground_heading
|
|
993
|
+
)
|
|
994
|
+
)
|
|
995
|
+
),
|
|
996
|
+
).transpose(*xr_dataset["ancillary_wind_speed"].dims)
|
|
997
|
+
|
|
998
|
+
xr_dataset.attrs["ancillary_source"] = (
|
|
999
|
+
xr_dataset["model_U10"].attrs["history"].split("decoded: ")[1].strip()
|
|
1000
|
+
)
|
|
1001
|
+
xr_dataset = xr_dataset.drop_vars(["model_U10", "model_V10"])
|
|
783
1002
|
|
|
784
1003
|
# nrcs processing
|
|
785
|
-
xr_dataset[
|
|
786
|
-
|
|
787
|
-
|
|
1004
|
+
xr_dataset["sigma0_ocean"] = xr.where(
|
|
1005
|
+
xr_dataset["mask"], np.nan, xr_dataset["sigma0"]
|
|
1006
|
+
).transpose(*xr_dataset["sigma0"].dims)
|
|
1007
|
+
xr_dataset["sigma0_ocean"].attrs = xr_dataset["sigma0"].attrs
|
|
788
1008
|
# we forced it to 1e-15
|
|
789
|
-
xr_dataset[
|
|
1009
|
+
xr_dataset["sigma0_ocean"].attrs[
|
|
1010
|
+
"comment"
|
|
1011
|
+
] = "clipped, no values <=0 ; 1e-15 instread"
|
|
790
1012
|
|
|
791
1013
|
# rajout d'un mask pour les valeurs <=0:
|
|
792
|
-
xr_dataset[
|
|
793
|
-
xr_dataset[
|
|
794
|
-
xr_dataset
|
|
795
|
-
xr_dataset.sigma0_mask.attrs[
|
|
796
|
-
xr_dataset.sigma0_mask.attrs[
|
|
797
|
-
xr_dataset[
|
|
798
|
-
|
|
1014
|
+
xr_dataset["sigma0_mask"] = xr.where(
|
|
1015
|
+
xr_dataset["sigma0_ocean"] <= 0, 1, 0
|
|
1016
|
+
).transpose(*xr_dataset["sigma0"].dims)
|
|
1017
|
+
xr_dataset.sigma0_mask.attrs["valid_range"] = np.array([0, 1])
|
|
1018
|
+
xr_dataset.sigma0_mask.attrs["flag_values"] = np.array([0, 1])
|
|
1019
|
+
xr_dataset.sigma0_mask.attrs["flag_meanings"] = "valid no_valid"
|
|
1020
|
+
xr_dataset["sigma0_ocean"] = xr.where(
|
|
1021
|
+
xr_dataset["sigma0_ocean"] <= 0, 1e-15, xr_dataset["sigma0_ocean"]
|
|
1022
|
+
)
|
|
799
1023
|
|
|
800
|
-
xr_dataset[
|
|
801
|
-
|
|
1024
|
+
xr_dataset["sigma0_ocean_raw"] = xr.where(
|
|
1025
|
+
xr_dataset["mask"], np.nan, xr_dataset["sigma0_raw"]
|
|
1026
|
+
).transpose(*xr_dataset["sigma0_raw"].dims)
|
|
802
1027
|
|
|
803
|
-
xr_dataset[
|
|
1028
|
+
xr_dataset["sigma0_ocean_raw"].attrs = xr_dataset["sigma0_raw"].attrs
|
|
804
1029
|
|
|
805
|
-
xr_dataset[
|
|
806
|
-
xr_dataset.sigma0.sel(pol=copol), xr_dataset.incidence, model=model_co
|
|
1030
|
+
xr_dataset["sigma0_detrend"] = xsarsea.sigma0_detrend(
|
|
1031
|
+
xr_dataset.sigma0.sel(pol=copol), xr_dataset.incidence, model=model_co
|
|
1032
|
+
)
|
|
807
1033
|
|
|
808
1034
|
# processing
|
|
809
1035
|
if dual_pol:
|
|
810
1036
|
|
|
811
1037
|
xr_dataset['sigma0_detrend_cross'] = xsarsea.sigma0_detrend(
|
|
812
1038
|
xr_dataset.sigma0.sel(pol=crosspol), xr_dataset.incidence, model=model_cross)
|
|
1039
|
+
|
|
1040
|
+
xr_dataset = xr_dataset.assign(nesz_cross_flattened=(
|
|
1041
|
+
['line', 'sample'], windspeed.nesz_flattening(xr_dataset.nesz.sel(pol=crosspol), xr_dataset.incidence).data))
|
|
1042
|
+
|
|
1043
|
+
xr_dataset['nesz_cross_flattened'].attrs[
|
|
1044
|
+
"comment"] = 'nesz has been flattened using windspeed.nesz_flattening'
|
|
1045
|
+
|
|
813
1046
|
if config["apply_flattening"]:
|
|
814
|
-
xr_dataset = xr_dataset.assign(nesz_cross_flattened=(
|
|
815
|
-
['line', 'sample'], windspeed.nesz_flattening(xr_dataset.nesz.sel(pol=crosspol), xr_dataset.incidence).data))
|
|
816
|
-
xr_dataset['nesz_cross_flattened'].attrs[
|
|
817
|
-
"comment"] = 'nesz has been flattened using windspeed.nesz_flattening'
|
|
818
1047
|
# dsig
|
|
819
|
-
xr_dataset["dsig_cross"] = windspeed.get_dsig(
|
|
820
|
-
|
|
1048
|
+
xr_dataset["dsig_cross"] = windspeed.get_dsig(
|
|
1049
|
+
config["dsig_" + crosspol_gmf + "_NAME"],
|
|
1050
|
+
xr_dataset.incidence,
|
|
1051
|
+
xr_dataset["sigma0_ocean"].sel(pol=crosspol),
|
|
1052
|
+
xr_dataset.nesz_cross_flattened,
|
|
1053
|
+
)
|
|
1054
|
+
|
|
1055
|
+
xr_dataset.dsig_cross.attrs["formula_used"] = config[
|
|
1056
|
+
"dsig_" + crosspol_gmf + "_NAME"
|
|
1057
|
+
]
|
|
1058
|
+
|
|
821
1059
|
else:
|
|
822
1060
|
# dsig
|
|
823
|
-
xr_dataset["dsig_cross"] = windspeed.get_dsig(
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1061
|
+
xr_dataset["dsig_cross"] = windspeed.get_dsig(
|
|
1062
|
+
config["dsig_" + crosspol_gmf + "_NAME"],
|
|
1063
|
+
xr_dataset.incidence,
|
|
1064
|
+
xr_dataset["sigma0_ocean"].sel(pol=crosspol),
|
|
1065
|
+
xr_dataset.nesz.sel(pol=crosspol),
|
|
1066
|
+
)
|
|
1067
|
+
|
|
1068
|
+
xr_dataset.dsig_cross.attrs["comment"] = (
|
|
1069
|
+
"variable used to ponderate copol and crosspol"
|
|
1070
|
+
)
|
|
1071
|
+
|
|
1072
|
+
xr_dataset.dsig_cross.attrs["apply_flattening"] = str(
|
|
1073
|
+
config["apply_flattening"]
|
|
1074
|
+
)
|
|
1075
|
+
|
|
1076
|
+
if (recalibration) & ("SENTINEL" in sensor_longname):
|
|
1077
|
+
xr_dataset.attrs["path_aux_pp1_new"] = os.path.basename(
|
|
1078
|
+
os.path.dirname(
|
|
1079
|
+
os.path.dirname(
|
|
1080
|
+
xsar_dataset.datatree["recalibration"].attrs["path_aux_pp1_new"]
|
|
1081
|
+
)
|
|
1082
|
+
)
|
|
1083
|
+
)
|
|
1084
|
+
xr_dataset.attrs["path_aux_cal_new"] = os.path.basename(
|
|
1085
|
+
os.path.dirname(
|
|
1086
|
+
os.path.dirname(
|
|
1087
|
+
xsar_dataset.datatree["recalibration"].attrs["path_aux_cal_new"]
|
|
1088
|
+
)
|
|
1089
|
+
)
|
|
1090
|
+
)
|
|
1091
|
+
|
|
1092
|
+
xr_dataset.attrs["path_aux_pp1_old"] = os.path.basename(
|
|
1093
|
+
os.path.dirname(
|
|
1094
|
+
os.path.dirname(
|
|
1095
|
+
xsar_dataset.datatree["recalibration"].attrs["path_aux_pp1_old"]
|
|
1096
|
+
)
|
|
1097
|
+
)
|
|
1098
|
+
)
|
|
1099
|
+
xr_dataset.attrs["path_aux_cal_old"] = os.path.basename(
|
|
1100
|
+
os.path.dirname(
|
|
1101
|
+
os.path.dirname(
|
|
1102
|
+
xsar_dataset.datatree["recalibration"].attrs["path_aux_cal_old"]
|
|
1103
|
+
)
|
|
1104
|
+
)
|
|
1105
|
+
)
|
|
842
1106
|
|
|
843
1107
|
if add_nrcs_model:
|
|
844
1108
|
# add timing
|
|
845
1109
|
phi = np.abs(
|
|
846
|
-
np.rad2deg(
|
|
847
|
-
|
|
1110
|
+
np.rad2deg(
|
|
1111
|
+
xsarsea.dir_meteo_to_sample(
|
|
1112
|
+
xr_dataset["ancillary_wind_direction"], xr_dataset["ground_heading"]
|
|
1113
|
+
)
|
|
1114
|
+
)
|
|
848
1115
|
)
|
|
849
1116
|
|
|
850
1117
|
varnames = ["ancillary_nrcs"]
|
|
@@ -866,9 +1133,7 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_gradientsfeat
|
|
|
866
1133
|
incidence=incidence, wspd=wspd, phi=phi, method="nearest"
|
|
867
1134
|
)
|
|
868
1135
|
else:
|
|
869
|
-
return lut.sel(
|
|
870
|
-
incidence=incidence, wspd=wspd, method="nearest"
|
|
871
|
-
)
|
|
1136
|
+
return lut.sel(incidence=incidence, wspd=wspd, method="nearest")
|
|
872
1137
|
|
|
873
1138
|
xr_dataset[varnames[idx]] = xr.apply_ufunc(
|
|
874
1139
|
lut_selection,
|
|
@@ -920,38 +1185,46 @@ def process_gradients(xr_dataset, config):
|
|
|
920
1185
|
dual_pol = config["l2_params"]["dual_pol"]
|
|
921
1186
|
|
|
922
1187
|
# Load the 100m dataset
|
|
923
|
-
xsar_dataset_100 = fct_dataset(
|
|
924
|
-
meta, resolution='100m')
|
|
1188
|
+
xsar_dataset_100 = fct_dataset(meta, resolution="100m")
|
|
925
1189
|
|
|
926
|
-
xr_dataset_100 = xsar_dataset_100.datatree[
|
|
1190
|
+
xr_dataset_100 = xsar_dataset_100.datatree["measurement"].to_dataset()
|
|
927
1191
|
xr_dataset_100 = xr_dataset_100.rename(map_model)
|
|
928
1192
|
# load dataset
|
|
929
1193
|
xr_dataset_100 = xr_dataset_100.load()
|
|
930
1194
|
|
|
931
1195
|
# adding sigma0 detrend
|
|
932
|
-
xr_dataset_100[
|
|
933
|
-
xr_dataset_100.sigma0.sel(pol=copol), xr_dataset_100.incidence, model=model_co
|
|
1196
|
+
xr_dataset_100["sigma0_detrend"] = xsarsea.sigma0_detrend(
|
|
1197
|
+
xr_dataset_100.sigma0.sel(pol=copol), xr_dataset_100.incidence, model=model_co
|
|
1198
|
+
)
|
|
934
1199
|
|
|
935
1200
|
if dual_pol:
|
|
936
|
-
xr_dataset_100[
|
|
937
|
-
xr_dataset_100.sigma0.sel(pol=crosspol),
|
|
1201
|
+
xr_dataset_100["sigma0_detrend_cross"] = xsarsea.sigma0_detrend(
|
|
1202
|
+
xr_dataset_100.sigma0.sel(pol=crosspol),
|
|
1203
|
+
xr_dataset_100.incidence,
|
|
1204
|
+
model=model_cross,
|
|
1205
|
+
)
|
|
938
1206
|
|
|
939
1207
|
sigma0_detrend_combined = xr.concat(
|
|
940
|
-
[xr_dataset_100[
|
|
941
|
-
xr_dataset_100[
|
|
942
|
-
dim=
|
|
1208
|
+
[xr_dataset_100["sigma0_detrend"],
|
|
1209
|
+
xr_dataset_100["sigma0_detrend_cross"]],
|
|
1210
|
+
dim="pol",
|
|
943
1211
|
)
|
|
944
|
-
sigma0_detrend_combined[
|
|
1212
|
+
sigma0_detrend_combined["pol"] = [copol, crosspol]
|
|
945
1213
|
|
|
946
|
-
xr_dataset_100[
|
|
1214
|
+
xr_dataset_100["sigma0_detrend"] = sigma0_detrend_combined
|
|
947
1215
|
|
|
948
|
-
xr_dataset_100.land_mask.values = binary_dilation(
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
1216
|
+
xr_dataset_100.land_mask.values = binary_dilation(
|
|
1217
|
+
xr_dataset_100["land_mask"].values.astype("uint8"),
|
|
1218
|
+
structure=np.ones((3, 3), np.uint8),
|
|
1219
|
+
iterations=3,
|
|
1220
|
+
)
|
|
1221
|
+
xr_dataset_100["sigma0_detrend"] = xr.where(
|
|
1222
|
+
xr_dataset_100["land_mask"], np.nan, xr_dataset_100["sigma0"]
|
|
1223
|
+
).transpose(*xr_dataset_100["sigma0"].dims)
|
|
952
1224
|
|
|
953
|
-
xr_dataset_100[
|
|
954
|
-
xr_dataset_100.model_U10 + 1j * xr_dataset_100.model_V10
|
|
1225
|
+
xr_dataset_100["ancillary_wind"] = (
|
|
1226
|
+
xr_dataset_100.model_U10 + 1j * xr_dataset_100.model_V10
|
|
1227
|
+
) * np.exp(1j * np.deg2rad(xr_dataset_100.ground_heading))
|
|
955
1228
|
|
|
956
1229
|
downscales_factors = [1, 2, 4, 8]
|
|
957
1230
|
# 4 and 8 must be in downscales_factors
|
|
@@ -962,7 +1235,7 @@ def process_gradients(xr_dataset, config):
|
|
|
962
1235
|
xr_dataset_100=xr_dataset_100,
|
|
963
1236
|
windows_sizes=[1600, 3200],
|
|
964
1237
|
downscales_factors=downscales_factors,
|
|
965
|
-
window_step=1
|
|
1238
|
+
window_step=1,
|
|
966
1239
|
)
|
|
967
1240
|
|
|
968
1241
|
# Compute heterogeneity mask and variables
|
|
@@ -971,24 +1244,29 @@ def process_gradients(xr_dataset, config):
|
|
|
971
1244
|
|
|
972
1245
|
# Add streaks dataset
|
|
973
1246
|
streaks_indiv = gradientFeatures.streaks_individual()
|
|
974
|
-
if
|
|
975
|
-
xr_dataset_streaks = xr.Dataset(
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1247
|
+
if "longitude" in streaks_indiv:
|
|
1248
|
+
xr_dataset_streaks = xr.Dataset(
|
|
1249
|
+
{
|
|
1250
|
+
"longitude": streaks_indiv.longitude,
|
|
1251
|
+
"latitude": streaks_indiv.latitude,
|
|
1252
|
+
"dir_smooth": streaks_indiv.angle,
|
|
1253
|
+
"dir_mean_smooth": gradientFeatures.streaks_mean_smooth().angle,
|
|
1254
|
+
"dir_smooth_mean": gradientFeatures.streaks_smooth_mean().angle,
|
|
1255
|
+
}
|
|
1256
|
+
)
|
|
982
1257
|
else:
|
|
983
1258
|
logger.warn(
|
|
984
|
-
"'longitude' not found in streaks_indiv : there is probably an error"
|
|
1259
|
+
"'longitude' not found in streaks_indiv : there is probably an error"
|
|
1260
|
+
)
|
|
985
1261
|
xr_dataset_streaks = None
|
|
986
1262
|
|
|
987
1263
|
return xr_dataset, xr_dataset_streaks
|
|
988
1264
|
|
|
989
1265
|
|
|
990
1266
|
@timing(logger=logger.info)
|
|
991
|
-
def makeL2(
|
|
1267
|
+
def makeL2(
|
|
1268
|
+
filename, outdir, config_path, overwrite=False, generateCSV=True, resolution="1000m"
|
|
1269
|
+
):
|
|
992
1270
|
"""
|
|
993
1271
|
Main function to generate L2 product.
|
|
994
1272
|
|
|
@@ -1016,11 +1294,11 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, res
|
|
|
1016
1294
|
"""
|
|
1017
1295
|
|
|
1018
1296
|
xr_dataset, out_file, config = preprocess(
|
|
1019
|
-
filename, outdir, config_path, overwrite, resolution
|
|
1297
|
+
filename, outdir, config_path, overwrite, resolution
|
|
1298
|
+
)
|
|
1020
1299
|
|
|
1021
1300
|
if config["add_gradientsfeatures"]:
|
|
1022
|
-
xr_dataset, xr_dataset_streaks = process_gradients(
|
|
1023
|
-
xr_dataset, config)
|
|
1301
|
+
xr_dataset, xr_dataset_streaks = process_gradients(xr_dataset, config)
|
|
1024
1302
|
else:
|
|
1025
1303
|
xr_dataset_streaks = None
|
|
1026
1304
|
|
|
@@ -1035,8 +1313,8 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, res
|
|
|
1035
1313
|
sensor_longname = config["sensor_longname"]
|
|
1036
1314
|
|
|
1037
1315
|
if dual_pol:
|
|
1038
|
-
sigma0_ocean_cross = xr_dataset[
|
|
1039
|
-
dsig_cross = xr_dataset[
|
|
1316
|
+
sigma0_ocean_cross = xr_dataset["sigma0_ocean"].sel(pol=crosspol)
|
|
1317
|
+
dsig_cross = xr_dataset["dsig_cross"]
|
|
1040
1318
|
else:
|
|
1041
1319
|
sigma0_ocean_cross = None
|
|
1042
1320
|
dsig_cross = 0.1 # default value set in xsarsea
|
|
@@ -1054,97 +1332,119 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, res
|
|
|
1054
1332
|
logging.info("Checking incidence range within LUTS incidence range")
|
|
1055
1333
|
# warning if incidence is out of lut incidence range
|
|
1056
1334
|
inc_check_co, inc_check_cross = check_incidence_range(
|
|
1057
|
-
xr_dataset[
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1335
|
+
xr_dataset["incidence"], [model_co, model_cross], **kwargs
|
|
1336
|
+
)
|
|
1337
|
+
|
|
1338
|
+
wind_co, wind_dual, windspeed_cr = inverse(
|
|
1339
|
+
dual_pol,
|
|
1340
|
+
inc=xr_dataset["incidence"],
|
|
1341
|
+
sigma0=xr_dataset["sigma0_ocean"].sel(pol=copol),
|
|
1342
|
+
sigma0_dual=sigma0_ocean_cross,
|
|
1343
|
+
ancillary_wind=xr_dataset["ancillary_wind"],
|
|
1344
|
+
dsig_cr=dsig_cross,
|
|
1345
|
+
model_co=model_co,
|
|
1346
|
+
model_cross=model_cross,
|
|
1347
|
+
**kwargs,
|
|
1348
|
+
)
|
|
1069
1349
|
# windspeed_co
|
|
1070
|
-
xr_dataset[
|
|
1350
|
+
xr_dataset["windspeed_co"] = np.abs(wind_co)
|
|
1071
1351
|
xr_dataset["windspeed_co"].attrs["units"] = "m.s⁻1"
|
|
1072
|
-
xr_dataset["windspeed_co"].attrs["long_name"] =
|
|
1073
|
-
model_co, copol)
|
|
1352
|
+
xr_dataset["windspeed_co"].attrs["long_name"] = (
|
|
1353
|
+
"Wind speed inverted from model %s (%s)" % (model_co, copol)
|
|
1354
|
+
)
|
|
1074
1355
|
xr_dataset["windspeed_co"].attrs["standart_name"] = "wind_speed"
|
|
1075
1356
|
xr_dataset["windspeed_co"].attrs["model"] = wind_co.attrs["model"]
|
|
1076
|
-
del xr_dataset["windspeed_co"].attrs[
|
|
1357
|
+
del xr_dataset["windspeed_co"].attrs["comment"]
|
|
1077
1358
|
|
|
1078
1359
|
# winddir_co
|
|
1079
|
-
xr_dataset[
|
|
1080
|
-
wind_co,
|
|
1081
|
-
|
|
1360
|
+
xr_dataset["winddir_co"] = transform_winddir(
|
|
1361
|
+
wind_co,
|
|
1362
|
+
xr_dataset.ground_heading,
|
|
1363
|
+
winddir_convention=config["winddir_convention"],
|
|
1364
|
+
)
|
|
1365
|
+
xr_dataset["winddir_co"].attrs["model"] = "%s (%s)" % (model_co, copol)
|
|
1082
1366
|
|
|
1083
1367
|
# windspeed_dual / windspeed_cr / /winddir_dual / winddir_cr
|
|
1084
1368
|
if dual_pol and wind_dual is not None:
|
|
1085
|
-
xr_dataset[
|
|
1369
|
+
xr_dataset["windspeed_dual"] = np.abs(wind_dual)
|
|
1086
1370
|
xr_dataset["windspeed_dual"].attrs["units"] = "m.s⁻1"
|
|
1087
|
-
xr_dataset["windspeed_dual"].attrs["long_name"] =
|
|
1088
|
-
|
|
1371
|
+
xr_dataset["windspeed_dual"].attrs["long_name"] = (
|
|
1372
|
+
"Wind speed inverted from model %s (%s) & %s (%s)"
|
|
1373
|
+
% (model_co, copol, model_cross, crosspol)
|
|
1374
|
+
)
|
|
1089
1375
|
xr_dataset["windspeed_dual"].attrs["standart_name"] = "wind_speed"
|
|
1090
1376
|
xr_dataset["windspeed_dual"].attrs["model"] = wind_dual.attrs["model"]
|
|
1091
|
-
del xr_dataset["windspeed_dual"].attrs[
|
|
1377
|
+
del xr_dataset["windspeed_dual"].attrs["comment"]
|
|
1092
1378
|
|
|
1093
|
-
xr_dataset[
|
|
1094
|
-
wind_dual,
|
|
1095
|
-
|
|
1379
|
+
xr_dataset["winddir_dual"] = transform_winddir(
|
|
1380
|
+
wind_dual,
|
|
1381
|
+
xr_dataset.ground_heading,
|
|
1382
|
+
winddir_convention=config["winddir_convention"],
|
|
1383
|
+
)
|
|
1384
|
+
xr_dataset["winddir_dual"].attrs[
|
|
1385
|
+
"model"
|
|
1386
|
+
] = "winddir_dual is a copy of copol wind direction"
|
|
1096
1387
|
|
|
1097
1388
|
xr_dataset = xr_dataset.assign(
|
|
1098
|
-
windspeed_cross=([
|
|
1389
|
+
windspeed_cross=(["line", "sample"], windspeed_cr.data)
|
|
1390
|
+
)
|
|
1099
1391
|
xr_dataset["windspeed_cross"].attrs["units"] = "m.s⁻1"
|
|
1100
|
-
xr_dataset["windspeed_cross"].attrs["long_name"] =
|
|
1101
|
-
model_cross, crosspol)
|
|
1392
|
+
xr_dataset["windspeed_cross"].attrs["long_name"] = (
|
|
1393
|
+
"Wind Speed inverted from model %s (%s)" % (model_cross, crosspol)
|
|
1394
|
+
)
|
|
1102
1395
|
xr_dataset["windspeed_cross"].attrs["standart_name"] = "wind_speed"
|
|
1103
1396
|
xr_dataset["windspeed_cross"].attrs["model"] = "%s" % (model_cross)
|
|
1104
1397
|
|
|
1105
|
-
xr_dataset[
|
|
1106
|
-
xr_dataset[
|
|
1107
|
-
xr_dataset["winddir_cross"].attrs[
|
|
1398
|
+
xr_dataset["winddir_cross"] = xr_dataset["winddir_dual"].copy()
|
|
1399
|
+
xr_dataset["winddir_cross"].attrs = xr_dataset["winddir_dual"].attrs
|
|
1400
|
+
xr_dataset["winddir_cross"].attrs[
|
|
1401
|
+
"model"
|
|
1402
|
+
] = "winddir_cross is a copy of copol wind direction"
|
|
1108
1403
|
|
|
1109
1404
|
if config["winddir_convention"] == "oceanographic":
|
|
1110
|
-
attrs = xr_dataset[
|
|
1111
|
-
xr_dataset[
|
|
1112
|
-
xr_dataset[
|
|
1113
|
-
|
|
1114
|
-
xr_dataset[
|
|
1115
|
-
|
|
1405
|
+
attrs = xr_dataset["ancillary_wind_direction"].attrs
|
|
1406
|
+
xr_dataset["ancillary_wind_direction"] = xsarsea.dir_meteo_to_oceano(
|
|
1407
|
+
xr_dataset["ancillary_wind_direction"]
|
|
1408
|
+
)
|
|
1409
|
+
xr_dataset["ancillary_wind_direction"].attrs = attrs
|
|
1410
|
+
xr_dataset["ancillary_wind_direction"].attrs[
|
|
1411
|
+
"long_name"
|
|
1412
|
+
] = f"{ancillary_name} wind direction in oceanographic convention (clockwise, to), ex: 0°=to north, 90°=to east"
|
|
1116
1413
|
|
|
1117
|
-
xr_dataset, encoding = makeL2asOwi(
|
|
1118
|
-
xr_dataset, config)
|
|
1414
|
+
xr_dataset, encoding = makeL2asOwi(xr_dataset, config)
|
|
1119
1415
|
|
|
1120
1416
|
xr_dataset = xr_dataset.compute()
|
|
1121
1417
|
# add attributes
|
|
1122
1418
|
firstMeasurementTime = None
|
|
1123
1419
|
lastMeasurementTime = None
|
|
1124
1420
|
try:
|
|
1125
|
-
firstMeasurementTime = datetime.datetime.strptime(
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
lastMeasurementTime = datetime.datetime.strptime(
|
|
1129
|
-
|
|
1130
|
-
|
|
1421
|
+
firstMeasurementTime = datetime.datetime.strptime(
|
|
1422
|
+
xr_dataset.attrs["start_date"], "%Y-%m-%d %H:%M:%S.%f"
|
|
1423
|
+
).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
1424
|
+
lastMeasurementTime = datetime.datetime.strptime(
|
|
1425
|
+
xr_dataset.attrs["stop_date"], "%Y-%m-%d %H:%M:%S.%f"
|
|
1426
|
+
).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
1131
1427
|
except:
|
|
1132
|
-
firstMeasurementTime = datetime.datetime.strptime(
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
lastMeasurementTime = datetime.datetime.strptime(
|
|
1136
|
-
|
|
1137
|
-
|
|
1428
|
+
firstMeasurementTime = datetime.datetime.strptime(
|
|
1429
|
+
xr_dataset.attrs["start_date"], "%Y-%m-%d %H:%M:%S"
|
|
1430
|
+
).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
1431
|
+
lastMeasurementTime = datetime.datetime.strptime(
|
|
1432
|
+
xr_dataset.attrs["stop_date"], "%Y-%m-%d %H:%M:%S"
|
|
1433
|
+
).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
1138
1434
|
|
|
1139
1435
|
attrs = {
|
|
1140
1436
|
"TITLE": "Sentinel-1 OWI Component",
|
|
1141
1437
|
"productOwner": "IFREMER",
|
|
1142
|
-
"sourceProduct": (
|
|
1143
|
-
|
|
1438
|
+
"sourceProduct": (
|
|
1439
|
+
xr_dataset.attrs["safe"]
|
|
1440
|
+
if "safe" in xr_dataset.attrs
|
|
1441
|
+
else os.path.basename(xr_dataset.attrs["product_path"])
|
|
1442
|
+
),
|
|
1443
|
+
"sourceProduct_fullpath": xr_dataset.attrs.pop("name"),
|
|
1144
1444
|
"missionName": sensor_longname,
|
|
1145
|
-
"missionPhase":
|
|
1146
|
-
"polarisation": xr_dataset.attrs[
|
|
1147
|
-
"acquisitionStation":
|
|
1445
|
+
"missionPhase": "Operational",
|
|
1446
|
+
"polarisation": xr_dataset.attrs["pols"],
|
|
1447
|
+
"acquisitionStation": "",
|
|
1148
1448
|
"xsar_version": xsar.__version__,
|
|
1149
1449
|
"xsarsea_version": xsarsea.__version__,
|
|
1150
1450
|
"pythonVersion": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
|
|
@@ -1157,25 +1457,32 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, res
|
|
|
1157
1457
|
"bathySource": "/",
|
|
1158
1458
|
"oswAlgorithmName": "grdwindinversion",
|
|
1159
1459
|
"owiAlgorithmVersion": grdwindinversion.__version__,
|
|
1160
|
-
"gmf": config[
|
|
1460
|
+
"gmf": config["GMF_" + copol_gmf + "_NAME"]
|
|
1461
|
+
+ ", "
|
|
1462
|
+
+ config["GMF_" + crosspol_gmf + "_NAME"],
|
|
1161
1463
|
"iceSource": "/",
|
|
1162
1464
|
"owiNoiseCorrection": "True",
|
|
1163
|
-
"inversionTabGMF": config[
|
|
1164
|
-
|
|
1465
|
+
"inversionTabGMF": config["GMF_" + copol_gmf + "_NAME"]
|
|
1466
|
+
+ ", "
|
|
1467
|
+
+ config["GMF_" + crosspol_gmf + "_NAME"],
|
|
1165
1468
|
"wnf_3km_average": "False",
|
|
1166
1469
|
"owiWindSpeedSrc": "owiWindSpeed",
|
|
1167
1470
|
"owiWindDirectionSrc": "/",
|
|
1168
|
-
"ancillary_source": xr_dataset.attrs[
|
|
1471
|
+
"ancillary_source": xr_dataset.attrs["ancillary_source"],
|
|
1169
1472
|
"winddir_convention": config["winddir_convention"],
|
|
1170
1473
|
"incidence_within_lut_copol_incidence_range": str(inc_check_co),
|
|
1171
1474
|
"incidence_within_lut_crosspol_incidence_range": str(inc_check_cross),
|
|
1172
|
-
"swath": xr_dataset.attrs[
|
|
1173
|
-
"footprint": xr_dataset.attrs[
|
|
1174
|
-
"coverage": xr_dataset.attrs[
|
|
1175
|
-
|
|
1475
|
+
"swath": xr_dataset.attrs["swath"],
|
|
1476
|
+
"footprint": xr_dataset.attrs["footprint"],
|
|
1477
|
+
"coverage": xr_dataset.attrs["coverage"],
|
|
1176
1478
|
}
|
|
1177
1479
|
|
|
1178
|
-
for recalib_attrs in [
|
|
1480
|
+
for recalib_attrs in [
|
|
1481
|
+
"path_aux_pp1_new",
|
|
1482
|
+
"path_aux_pp1_old",
|
|
1483
|
+
"path_aux_cal_new",
|
|
1484
|
+
"path_aux_cal_old",
|
|
1485
|
+
]:
|
|
1179
1486
|
if recalib_attrs in xr_dataset.attrs:
|
|
1180
1487
|
attrs[recalib_attrs] = xr_dataset.attrs[recalib_attrs]
|
|
1181
1488
|
|
|
@@ -1190,11 +1497,11 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, res
|
|
|
1190
1497
|
if sup_attr in xr_dataset.attrs:
|
|
1191
1498
|
attrs[sup_attr] = xr_dataset.attrs[sup_attr]
|
|
1192
1499
|
|
|
1193
|
-
attrs[
|
|
1500
|
+
attrs["footprint"] = str(attrs["footprint"])
|
|
1194
1501
|
|
|
1195
1502
|
# add in kwargs in attrs
|
|
1196
1503
|
for key in kwargs:
|
|
1197
|
-
attrs["lut_params_"+key] = "/" if kwargs[key] is None else kwargs[key]
|
|
1504
|
+
attrs["lut_params_" + key] = "/" if kwargs[key] is None else kwargs[key]
|
|
1198
1505
|
|
|
1199
1506
|
xr_dataset.attrs = attrs
|
|
1200
1507
|
|
|
@@ -1233,7 +1540,7 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, res
|
|
|
1233
1540
|
return out_file, xr_dataset
|
|
1234
1541
|
|
|
1235
1542
|
|
|
1236
|
-
def transform_winddir(wind_cpx, ground_heading, winddir_convention=
|
|
1543
|
+
def transform_winddir(wind_cpx, ground_heading, winddir_convention="meteorological"):
|
|
1237
1544
|
"""
|
|
1238
1545
|
|
|
1239
1546
|
Parameters
|
|
@@ -1254,7 +1561,8 @@ def transform_winddir(wind_cpx, ground_heading, winddir_convention='meteorologic
|
|
|
1254
1561
|
"""
|
|
1255
1562
|
# to meteo winddir_convention
|
|
1256
1563
|
dataArray = xsarsea.dir_sample_to_meteo(
|
|
1257
|
-
np.angle(wind_cpx, deg=True), ground_heading
|
|
1564
|
+
np.angle(wind_cpx, deg=True), ground_heading
|
|
1565
|
+
)
|
|
1258
1566
|
long_name = "Wind direction in meteorological convention (clockwise, from), ex: 0°=from north, 90°=from east"
|
|
1259
1567
|
|
|
1260
1568
|
if winddir_convention == "meteorological":
|
|
@@ -1267,7 +1575,8 @@ def transform_winddir(wind_cpx, ground_heading, winddir_convention='meteorologic
|
|
|
1267
1575
|
else:
|
|
1268
1576
|
# warning
|
|
1269
1577
|
logging.warning(
|
|
1270
|
-
f"wind direction convention {winddir_convention} is not supported, using meteorological",
|
|
1578
|
+
f"wind direction convention {winddir_convention} is not supported, using meteorological",
|
|
1579
|
+
)
|
|
1271
1580
|
long_name = "Wind direction in meteorological convention (clockwise, from), ex: 0°=from north, 90°=from east"
|
|
1272
1581
|
|
|
1273
1582
|
dataArray = xsarsea.dir_to_360(dataArray)
|