grdwindinversion 0.3.5__py3-none-any.whl → 0.3.8__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.
@@ -0,0 +1,70 @@
1
+ no_subdir: True
2
+ winddir_convention: "meteorological"
3
+ add_gradientsfeatures: False
4
+ add_nrcs_model: False
5
+ S1A:
6
+ GMF_HH_NAME: "nc_lut_gmf_cmod5n_Rhigh_hh_mouche1"
7
+ GMF_VV_NAME: "gmf_cmod5n"
8
+ GMF_VH_NAME: "gmf_s1_v2"
9
+ dsig_VH_NAME: "gmf_s1_v2"
10
+ dsig_cr_step: "nrcs"
11
+ apply_flattening: True
12
+ S1_EW_calG>20190731:
13
+ GMF_HH_NAME: "nc_lut_gmf_cmod5n_Rhigh_hh_mouche1"
14
+ GMF_VV_NAME: "gmf_cmod5n"
15
+ GMF_VH_NAME: "gmf_s1_v3_ew_rec"
16
+ dsig_VH_NAME: "dsig_wspd_s1_ew_rec_v3"
17
+ dsig_cr_step: "wspd"
18
+ apply_flattening: True
19
+ recalibration: False
20
+ ancillary: "ecmwf"
21
+ inc_step: 0.1
22
+ wspd_step: 0.1
23
+ phi_step: 1.0
24
+ resolution: "high"
25
+ S1B:
26
+ GMF_HH_NAME: "nc_lut_gmf_cmod5n_Rhigh_hh_mouche1"
27
+ GMF_VV_NAME: "gmf_cmod5n"
28
+ GMF_VH_NAME: "gmf_s1_v2"
29
+ dsig_VH_NAME: "gmf_s1_v2"
30
+ dsig_cr_step: "nrcs"
31
+ apply_flattening: True
32
+ S1_EW_calG>20190731:
33
+ GMF_HH_NAME: "nc_lut_gmf_cmod5n_Rhigh_hh_mouche1"
34
+ GMF_VV_NAME: "gmf_cmod5n"
35
+ GMF_VH_NAME: "gmf_s1_v3_ew_rec"
36
+ dsig_VH_NAME: "dsig_wspd_s1_ew_rec_v3"
37
+ dsig_cr_step: "wspd"
38
+ apply_flattening: True
39
+ recalibration: False
40
+ ancillary: "ecmwf"
41
+ inc_step: 0.1
42
+ wspd_step: 0.1
43
+ phi_step: 1.0
44
+ resolution: "high"
45
+ RS2:
46
+ GMF_HH_NAME: "nc_lut_gmf_cmod5n_Rhigh_hh_mouche1"
47
+ GMF_VV_NAME: "gmf_cmod5n"
48
+ GMF_VH_NAME: "gmf_rs2_v3"
49
+ dsig_VH_NAME: "dsig_wspd_rs2_v3"
50
+ dsig_cr_step: "wspd"
51
+ apply_flattening: False
52
+ recalibration: False
53
+ ancillary: "ecmwf"
54
+ inc_step: 0.1
55
+ wspd_step: 0.1
56
+ phi_step: 1.0
57
+ resolution: "high"
58
+ RCM:
59
+ GMF_HH_NAME: "nc_lut_gmf_cmod5n_Rhigh_hh_mouche1"
60
+ GMF_VV_NAME: "gmf_cmod5n"
61
+ GMF_VH_NAME: "gmf_rcm_v3"
62
+ dsig_VH_NAME: "dsig_wspd_rcm_v3"
63
+ dsig_cr_step: "wspd"
64
+ apply_flattening: True
65
+ recalibration: False
66
+ ancillary: "ecmwf"
67
+ inc_step: 0.1
68
+ wspd_step: 0.1
69
+ phi_step: 1.0
70
+ resolution: "high"
@@ -14,7 +14,7 @@ import yaml
14
14
  from scipy.ndimage import binary_dilation
15
15
  import re
16
16
  import string
17
- from grdwindinversion.utils import check_incidence_range, get_pol_ratio_name, timing
17
+ from grdwindinversion.utils import check_incidence_range, get_pol_ratio_name, timing, convert_polarization_name
18
18
  from grdwindinversion.load_config import getConf
19
19
  import logging
20
20
  import os
@@ -101,8 +101,9 @@ def getOutputName(
101
101
  "(...)_(..)_(...)(.)_(.)(.)(..)_(........T......)_(........T......)_(......)_(......)_(....).SAFE"
102
102
  )
103
103
  template = string.Template(
104
- "${MISSIONID}_${BEAM}_${PRODUCT}${RESOLUTION}_${LEVEL}${CLASS}${POL}_${STARTDATE}_${STOPDATE}_${ORBIT}_${TAKEID}_${PRODID}.SAFE"
104
+ "${MISSIONID}_${SWATH}_${PRODUCT}${RESOLUTION}_${LEVEL}${CLASS}${POLARIZATION}_${STARTDATE}_${STOPDATE}_${ORBIT}_${TAKEID}_${PRODID}.SAFE"
105
105
  )
106
+ # S1A_IW_GRDH_1SDV_20210909T130650_20210909T130715_039605_04AE83_C34F
106
107
  match = regex.match(basename_match)
107
108
  if not match:
108
109
  raise AttributeError(
@@ -111,25 +112,27 @@ def getOutputName(
111
112
 
112
113
  (
113
114
  MISSIONID,
114
- BEAM,
115
+ SWATH,
115
116
  PRODUCT,
116
117
  RESOLUTION,
117
118
  LEVEL,
118
119
  CLASS,
119
- POL,
120
+ POLARIZATION,
120
121
  STARTDATE,
121
122
  STOPDATE,
122
123
  ORBIT,
123
124
  TAKEID,
124
125
  PRODID,
125
126
  ) = match.groups()
126
- new_format = f"{MISSIONID.lower()}-{BEAM.lower()}-owi-xx-{STARTDATE.lower()}-{STOPDATE.lower()}-{ORBIT}-{TAKEID}.nc"
127
+ # last two terms of polarization are removed
128
+ new_format = f"{MISSIONID.lower()}-{SWATH.lower()}-owi-{POLARIZATION.lower()}-{STARTDATE.lower()}-{STOPDATE.lower()}-{ORBIT}-{TAKEID}.nc"
127
129
  elif sensor == "RS2":
128
130
  regex = re.compile(
129
131
  "(RS2)_OK([0-9]+)_PK([0-9]+)_DK([0-9]+)_(....)_(........)_(......)_(.._?.?.?)_(S.F)"
130
132
  )
133
+ # RS2_OK141302_PK1242223_DK1208537_SCWA_20220904_093402_VV_VH_SGF
131
134
  template = string.Template(
132
- "${MISSIONID}_OK${DATA1}_PK${DATA2}_DK${DATA3}_${DATA4}_${DATE}_${TIME}_${POLARIZATION}_${LAST}"
135
+ "${MISSIONID}_OK${DATA1}_PK${DATA2}_DK${DATA3}_${SWATH}_${DATE}_${TIME}_${POLARIZATION}_${LAST}"
133
136
  )
134
137
  match = regex.match(basename_match)
135
138
  if not match:
@@ -137,25 +140,27 @@ def getOutputName(
137
140
  f"RC2 file {basename_match} does not match the expected pattern"
138
141
  )
139
142
 
140
- MISSIONID, DATA1, DATA2, DATA3, DATA4, DATE, TIME, POLARIZATION, LAST = (
143
+ MISSIONID, DATA1, DATA2, DATA3, SWATH, DATE, TIME, POLARIZATION, LAST = (
141
144
  match.groups()
142
145
  )
143
- new_format = f"{MISSIONID.lower()}--owi-xx-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
146
+ new_format = f"{MISSIONID.lower()}-{SWATH.lower()}-owi-{convert_polarization_name(POLARIZATION)}-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
144
147
  elif sensor == "RCM":
145
148
 
146
149
  regex = re.compile(
147
150
  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
151
  )
152
+ # RCM1_OK2767220_PK2769320_1_SCLND_20230930_214014_VV_VH_GRD
153
+
149
154
  match = regex.match(basename_match)
150
155
  if not match:
151
156
  raise AttributeError(
152
157
  f"RCM file {basename_match} does not match the expected pattern"
153
158
  )
154
159
 
155
- MISSIONID, DATA1, DATA2, DATA3, BEAM, DATE, TIME, POLARIZATION, PRODUCT = (
160
+ MISSIONID, DATA1, DATA2, DATA3, SWATH, DATE, TIME, POLARIZATION, PRODUCT = (
156
161
  match.groups()
157
162
  )
158
- new_format = f"{MISSIONID.lower()}-{BEAM.lower()}-owi-xx-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
163
+ new_format = f"{MISSIONID.lower()}-{SWATH.lower()}-owi-{convert_polarization_name(POLARIZATION)}-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
159
164
 
160
165
  else:
161
166
  raise ValueError(
@@ -184,7 +189,6 @@ def getAncillary(meta, ancillary_name="ecmwf"):
184
189
  """
185
190
 
186
191
  if ancillary_name == "ecmwf":
187
-
188
192
  logging.debug("conf: %s", getConf())
189
193
  ec01 = getConf()["ecmwf_0100_1h"]
190
194
  ec0125 = getConf()["ecmwf_0125_1h"]
@@ -277,6 +281,93 @@ def getAncillary(meta, ancillary_name="ecmwf"):
277
281
  "ancillary_name must be ecmwf/era5, got %s" % ancillary_name)
278
282
 
279
283
 
284
+ @timing(logger=logger.debug)
285
+ def inverse_dsig_wspd(
286
+ dual_pol,
287
+ inc,
288
+ sigma0,
289
+ sigma0_dual,
290
+ ancillary_wind,
291
+ nesz_cr,
292
+ dsig_cr_name,
293
+ model_co,
294
+ model_cross,
295
+ **kwargs,
296
+ ):
297
+ """
298
+ Invert sigma0 to retrieve wind using model (lut or gmf).
299
+
300
+ Parameters
301
+ ----------
302
+ dual_pol: bool
303
+ True if dualpol, False if singlepol
304
+ inc: xarray.DataArray
305
+ incidence angle
306
+ sigma0: xarray.DataArray
307
+ sigma0 to be inverted
308
+ sigma0_dual: xarray.DataArray
309
+ sigma0 to be inverted for dualpol
310
+ ancillary_wind=: xarray.DataArray (numpy.complex28)
311
+ ancillary wind
312
+ | (for example ecmwf winds), in **ANTENNA convention**,
313
+ nesz_cr: xarray.DataArray
314
+ noise equivalent sigma0 | flattened or not
315
+ dsig_cr_name: str
316
+ dsig_cr name
317
+ model_co: str
318
+ model to use for VV or HH polarization.
319
+ model_cross: str
320
+ model to use for VH or HV polarization.
321
+
322
+ Returns
323
+ -------
324
+ xarray.DataArray
325
+ inverted wind in copol in ** antenna convention** .
326
+ xarray.DataArray
327
+ inverted wind in dualpol in ** antenna convention** .
328
+ xarray.DataArray
329
+ inverted wind in crosspol in ** antenna convention** .
330
+ xarray.DataArray | array
331
+ alpha (ponderation between co and crosspol)
332
+
333
+ See Also
334
+ --------
335
+ xsarsea documentation
336
+ https://cerweb.ifremer.fr/datarmor/doc_sphinx/xsarsea/
337
+ """
338
+
339
+ # dsig_cr_step == "wspd":
340
+
341
+ wind_co = xsarsea.windspeed.invert_from_model(
342
+ inc,
343
+ sigma0,
344
+ ancillary_wind=ancillary_wind,
345
+ model=model_co,
346
+ **kwargs
347
+ )
348
+
349
+ if dual_pol:
350
+
351
+ wind_cross = windspeed.invert_from_model(
352
+ inc.values,
353
+ sigma0_dual.values,
354
+ model=model_cross,
355
+ **kwargs,
356
+ )
357
+
358
+ wspd_co = np.abs(wind_co)
359
+ wspd_cross = np.abs(wind_cross)
360
+ SNR_cross = sigma0_dual.values/nesz_cr.values
361
+ alpha = windspeed.get_dsig_wspd(dsig_cr_name, wind_cross, SNR_cross)
362
+
363
+ wpsd_dual = alpha * wspd_co + (1 - alpha) * wspd_cross
364
+ wind_dual = wpsd_dual * np.exp(1j * np.angle(wind_co))
365
+
366
+ return wind_co, wind_dual, wind_cross, alpha
367
+
368
+ return wind_co, None, None, None
369
+
370
+
280
371
  @timing(logger=logger.debug)
281
372
  def inverse(
282
373
  dual_pol,
@@ -316,8 +407,12 @@ def inverse(
316
407
 
317
408
  Returns
318
409
  -------
319
- xarray.DataArray or tuple
320
- inverted wind in ** antenna convention** .
410
+ xarray.DataArray
411
+ inverted wind in copol in ** antenna convention** .
412
+ xarray.DataArray
413
+ inverted wind in dualpol in ** antenna convention** .
414
+ xarray.DataArray
415
+ inverted wind in crosspol in ** antenna convention** .
321
416
 
322
417
  See Also
323
418
  --------
@@ -514,8 +609,15 @@ def makeL2asOwi(xr_dataset, config):
514
609
  )
515
610
 
516
611
  if config["l2_params"]["dual_pol"]:
612
+ if config["dsig_cr_step"] == "nrcs":
613
+ xr_dataset = xr_dataset.rename({
614
+ 'dsig_cross': 'owiDsig_cross',
615
+ })
616
+ else:
617
+ xr_dataset = xr_dataset.rename({
618
+ 'alpha': 'owiAlpha',
619
+ })
517
620
  xr_dataset = xr_dataset.rename({
518
- 'dsig_cross': 'owiDsig_cross',
519
621
  'winddir_cross': 'owiWindDirection_cross',
520
622
  'winddir_dual': 'owiWindDirection',
521
623
  'windspeed_cross': 'owiWindSpeed_cross',
@@ -779,6 +881,7 @@ def preprocess(
779
881
  )
780
882
 
781
883
  try:
884
+ logging.info(f"recalibration = {recalibration}")
782
885
  if (recalibration) & ("SENTINEL" in sensor_longname):
783
886
  logging.info(
784
887
  f"recalibration is {recalibration} : Kersten formula is applied"
@@ -850,8 +953,23 @@ def preprocess(
850
953
  copol_gmf = "HH"
851
954
  crosspol_gmf = "VH"
852
955
 
853
- model_co = config["GMF_" + copol_gmf + "_NAME"]
854
- model_cross = config["GMF_" + crosspol_gmf + "_NAME"]
956
+ cond_aux_cal = (sensor == "S1A" or sensor == "S1B") and (
957
+ xsar_dataset.dataset.attrs["aux_cal"].split("_")[-1][1:9] > '20190731')
958
+ if cond_aux_cal and xr_dataset.attrs["swath"] == "EW" and "S1_EW_calG>20190731" in config.keys():
959
+ model_co = config["S1_EW_calG>20190731"]["GMF_" + copol_gmf + "_NAME"]
960
+ model_cross = config["S1_EW_calG>20190731"]["GMF_" +
961
+ crosspol_gmf + "_NAME"]
962
+ dsig_cr_name = config["S1_EW_calG>20190731"]["dsig_" +
963
+ crosspol_gmf + "_NAME"]
964
+ apply_flattening = config["S1_EW_calG>20190731"]["apply_flattening"]
965
+ dsig_cr_step = config["S1_EW_calG>20190731"]["dsig_cr_step"]
966
+
967
+ else:
968
+ model_co = config["GMF_" + copol_gmf + "_NAME"]
969
+ model_cross = config["GMF_" + crosspol_gmf + "_NAME"]
970
+ dsig_cr_name = config["dsig_" + crosspol_gmf + "_NAME"]
971
+ apply_flattening = config["apply_flattening"]
972
+ dsig_cr_step = config["dsig_cr_step"]
855
973
 
856
974
  # register paramaters in config
857
975
  config["l2_params"]["dual_pol"] = dual_pol
@@ -863,6 +981,9 @@ def preprocess(
863
981
  config["l2_params"]["model_cross"] = model_cross
864
982
  config["sensor_longname"] = sensor_longname
865
983
  config["sensor"] = sensor
984
+ config["dsig_cr_step"] = dsig_cr_step
985
+ config["dsig_cr_name"] = dsig_cr_name
986
+ config["apply_flattening"] = apply_flattening
866
987
 
867
988
  # need to load LUTs before inversion
868
989
  nc_luts = [x for x in [model_co, model_cross] if x.startswith("nc_lut")]
@@ -1043,66 +1164,39 @@ def preprocess(
1043
1164
  xr_dataset['nesz_cross_flattened'].attrs[
1044
1165
  "comment"] = 'nesz has been flattened using windspeed.nesz_flattening'
1045
1166
 
1046
- if config["apply_flattening"]:
1047
- # dsig
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
-
1059
- else:
1167
+ if dsig_cr_step == "nrcs":
1060
1168
  # dsig
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
- )
1169
+ if apply_flattening:
1170
+ xr_dataset["dsig_cross"] = windspeed.get_dsig(
1171
+ dsig_cr_name,
1172
+ xr_dataset.incidence,
1173
+ xr_dataset["sigma0_ocean"].sel(pol=crosspol),
1174
+ xr_dataset.nesz_cross_flattened,
1175
+ )
1071
1176
 
1072
- xr_dataset.dsig_cross.attrs["apply_flattening"] = str(
1073
- config["apply_flattening"]
1074
- )
1177
+ xr_dataset.dsig_cross.attrs["formula_used"] = config[
1178
+ "dsig_" + crosspol_gmf + "_NAME"
1179
+ ]
1075
1180
 
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"]
1181
+ else:
1182
+ xr_dataset["dsig_cross"] = windspeed.get_dsig(
1183
+ dsig_cr_name,
1184
+ xr_dataset.incidence,
1185
+ xr_dataset["sigma0_ocean"].sel(pol=crosspol),
1186
+ xr_dataset.nesz.sel(pol=crosspol),
1088
1187
  )
1089
- )
1090
- )
1091
1188
 
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
- )
1189
+ xr_dataset.dsig_cross.attrs["comment"] = (
1190
+ "variable used to ponderate copol and crosspol. this ponderation is done will combining cost functions during inversion process"
1097
1191
  )
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
- )
1192
+
1193
+ xr_dataset.dsig_cross.attrs["apply_flattening"] = str(
1194
+ apply_flattening
1104
1195
  )
1105
- )
1196
+
1197
+ if (recalibration) & ("SENTINEL" in sensor_longname):
1198
+ xr_dataset.attrs["aux_cal_recal"] = xsar_dataset.datatree["recalibration"].attrs["aux_cal_new"]
1199
+ xr_dataset.attrs["aux_pp1_recal"] = xsar_dataset.datatree["recalibration"].attrs["aux_pp1_new"]
1106
1200
 
1107
1201
  if add_nrcs_model:
1108
1202
  # add timing
@@ -1276,6 +1370,7 @@ def makeL2(
1276
1370
  input filename
1277
1371
  outdir : str
1278
1372
  output folder
1373
+
1279
1374
  config_path : str
1280
1375
  configuration file path
1281
1376
  overwrite : bool, optional
@@ -1311,10 +1406,15 @@ def makeL2(
1311
1406
  dual_pol = config["l2_params"]["dual_pol"]
1312
1407
  ancillary_name = config["ancillary"]
1313
1408
  sensor_longname = config["sensor_longname"]
1314
-
1409
+ dsig_cr_step = config["dsig_cr_step"]
1410
+ dsig_cr_name = config["dsig_cr_name"]
1411
+ apply_flattening = config["apply_flattening"]
1315
1412
  if dual_pol:
1316
1413
  sigma0_ocean_cross = xr_dataset["sigma0_ocean"].sel(pol=crosspol)
1317
- dsig_cross = xr_dataset["dsig_cross"]
1414
+ if dsig_cr_step == "nrcs":
1415
+ dsig_cross = xr_dataset["dsig_cross"]
1416
+ else:
1417
+ dsig_cross = 0.1
1318
1418
  else:
1319
1419
  sigma0_ocean_cross = None
1320
1420
  dsig_cross = 0.1 # default value set in xsarsea
@@ -1334,18 +1434,50 @@ def makeL2(
1334
1434
  inc_check_co, inc_check_cross = check_incidence_range(
1335
1435
  xr_dataset["incidence"], [model_co, model_cross], **kwargs
1336
1436
  )
1437
+ if dsig_cr_step == "nrcs":
1438
+ logging.info(
1439
+ "dsig_cr_step is nrcs : polarization are mixed at cost function step")
1440
+ wind_co, wind_dual, windspeed_cr = inverse(
1441
+ dual_pol,
1442
+ inc=xr_dataset["incidence"],
1443
+ sigma0=xr_dataset["sigma0_ocean"].sel(pol=copol),
1444
+ sigma0_dual=sigma0_ocean_cross,
1445
+ ancillary_wind=xr_dataset["ancillary_wind"],
1446
+ dsig_cr=dsig_cross,
1447
+ model_co=model_co,
1448
+ model_cross=model_cross,
1449
+ **kwargs,
1450
+ )
1451
+ elif dsig_cr_step == "wspd":
1452
+ logging.info(
1453
+ "dsig_cr_step is wspd : polarization are mixed at winds speed step")
1454
+
1455
+ if apply_flattening:
1456
+ nesz_cross = xr_dataset["nesz_cross_flattened"]
1457
+ else:
1458
+ nesz_cross = xr_dataset.nesz.sel(pol=crosspol)
1459
+
1460
+ wind_co, wind_dual, windspeed_cr, alpha = inverse_dsig_wspd(
1461
+ dual_pol,
1462
+ inc=xr_dataset["incidence"],
1463
+ sigma0=xr_dataset["sigma0_ocean"].sel(pol=copol),
1464
+ sigma0_dual=sigma0_ocean_cross,
1465
+ ancillary_wind=xr_dataset["ancillary_wind"],
1466
+ nesz_cr=nesz_cross,
1467
+ dsig_cr_name=dsig_cr_name,
1468
+ model_co=model_co,
1469
+ model_cross=model_cross,
1470
+ **kwargs
1471
+ )
1472
+ xr_dataset["alpha"] = xr.DataArray(
1473
+ data=alpha, dims=xr_dataset["incidence"].dims, coords=xr_dataset["incidence"].coords)
1474
+ xr_dataset["alpha"].attrs["apply_flattening"] = str(apply_flattening)
1475
+ xr_dataset["alpha"].attrs["comments"] = "alpha used to ponderate copol and crosspol. this ponderation is done will combining wind speeds."
1476
+
1477
+ else:
1478
+ raise ValueError(
1479
+ f"dsig_cr_step must be 'nrcs' or 'wspd', got {dsig_cr_step}")
1337
1480
 
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
- )
1349
1481
  # windspeed_co
1350
1482
  xr_dataset["windspeed_co"] = np.abs(wind_co)
1351
1483
  xr_dataset["windspeed_co"].attrs["units"] = "m.s⁻1"
@@ -1373,8 +1505,11 @@ def makeL2(
1373
1505
  % (model_co, copol, model_cross, crosspol)
1374
1506
  )
1375
1507
  xr_dataset["windspeed_dual"].attrs["standart_name"] = "wind_speed"
1376
- xr_dataset["windspeed_dual"].attrs["model"] = wind_dual.attrs["model"]
1377
- del xr_dataset["windspeed_dual"].attrs["comment"]
1508
+ xr_dataset["windspeed_dual"].attrs["model"] = (model_co, model_cross)
1509
+ xr_dataset["windspeed_dual"].attrs["combining_method"] = dsig_cr_step
1510
+
1511
+ if "comment" in xr_dataset["windspeed_dual"].attrs:
1512
+ del xr_dataset["windspeed_dual"].attrs["comment"]
1378
1513
 
1379
1514
  xr_dataset["winddir_dual"] = transform_winddir(
1380
1515
  wind_dual,
@@ -1477,12 +1612,7 @@ def makeL2(
1477
1612
  "coverage": xr_dataset.attrs["coverage"],
1478
1613
  }
1479
1614
 
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
- ]:
1615
+ for recalib_attrs in ["aux_pp1_recal", "aux_pp1", "aux_cal_recal", "aux_cal"]:
1486
1616
  if recalib_attrs in xr_dataset.attrs:
1487
1617
  attrs[recalib_attrs] = xr_dataset.attrs[recalib_attrs]
1488
1618
 
@@ -1490,7 +1620,7 @@ def makeL2(
1490
1620
  if arg in xr_dataset.attrs:
1491
1621
  attrs["passDirection"] = xr_dataset.attrs[arg]
1492
1622
 
1493
- _S1_added_attrs = ["ipf", "platform_heading"]
1623
+ _S1_added_attrs = ["ipf_version", "platform_heading"]
1494
1624
  _RCM_added_attrs = ["productId"]
1495
1625
 
1496
1626
  for sup_attr in _S1_added_attrs + _RCM_added_attrs:
grdwindinversion/utils.py CHANGED
@@ -18,6 +18,31 @@ except ImportError:
18
18
  mem_monitor = False
19
19
 
20
20
 
21
+ def convert_polarization_name(pol):
22
+ """
23
+ Convert polarization name to the format used in the output filename
24
+
25
+ Parameters
26
+ ----------
27
+ pol : str
28
+ polarization name
29
+
30
+ Returns
31
+ -------
32
+ str
33
+ polarization name in the format used in the output filename (dv/dh/sv/sh/xx)
34
+ """
35
+ if pol == "VV_VH":
36
+ return "dv"
37
+ elif pol == "HH_HV":
38
+ return "dh"
39
+ elif pol == "VV":
40
+ return "sv"
41
+ elif pol == "HH":
42
+ return "sh"
43
+ else:
44
+ return "xx"
45
+
21
46
  def check_incidence_range(incidence, models, **kwargs):
22
47
  """
23
48
  Check if the incidence range of the dataset is within the range of the LUT of the model.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: grdwindinversion
3
- Version: 0.3.5
3
+ Version: 0.3.8
4
4
  Summary: Package to perform Wind inversion from GRD Level-1 SAR images
5
5
  Author-email: Antoine Grouazel <antoine.grouazel@ifremer.fr>
6
6
  License: MIT
@@ -27,6 +27,8 @@ Requires-Dist: numpy
27
27
  Requires-Dist: scipy
28
28
  Requires-Dist: fsspec
29
29
  Requires-Dist: aiohttp
30
+ Requires-Dist: xmlschema==3.4.3
31
+ Dynamic: license-file
30
32
 
31
33
 
32
34
  [![Python Version](https://img.shields.io/pypi/pyversions/grdwindinversion.svg)](https://pypi.org/project/grdwindinversion/)
@@ -35,7 +37,7 @@ Requires-Dist: aiohttp
35
37
  Package to perform Wind inversion from GRD Level-1 SAR images
36
38
 
37
39
  - Free software: MIT license
38
- - Documentation: https://grdwindinversion.readthedocs.io.
40
+ - Documentation: https://cerweb.ifremer.fr/datarmor/doc_sphinx/grdwindinversion/index.html.
39
41
 
40
42
  ## Usage
41
43
 
@@ -5,18 +5,19 @@ grdwindinversion/config_prod_recal.yaml,sha256=74n2J4tzSx1I5vaat3ydwig1jyfDgxGTG
5
5
  grdwindinversion/config_prod_recal_streaks_nrcsmod.yaml,sha256=ob0YmzHrwkI4GLxaR9HzidYtXBrTOAlEYwPYdCK7AqA,1092
6
6
  grdwindinversion/config_prod_streaks.yaml,sha256=lJMl4qH6XYqO8ich7yW0WDQsQDrjmWThlLyx1xZy1DA,1313
7
7
  grdwindinversion/config_prod_streaks_nrcsmod.yaml,sha256=4yC4KcsC7rUumYHwhpKxM8_LDMe_Je-RIu4-9e1ayp8,1312
8
+ grdwindinversion/config_prod_v3.yaml,sha256=J6lb8swIa7M-P4DjnTqKP1Bzp3b2XWNZp_E1FCrPGXQ,1953
8
9
  grdwindinversion/data_config.yaml,sha256=FnglUHbAtGwHWg8w86hwZt3-vo-dY8uIjxqyI1jZpv8,567
9
10
  grdwindinversion/gradientFeatures.py,sha256=NIeAJzb1zrlJPBq1th7wjEZoNJMxwqDpNHLMWP6FQN0,18198
10
- grdwindinversion/inversion.py,sha256=rRqmDDL0byTJPu5PZIalTALSaQBNiIXYJpdS2eGYDiI,56525
11
+ grdwindinversion/inversion.py,sha256=4AM5CUyLexHW4yX7yMspfW2osA4DTGm8I0KTWZbPiUA,61752
11
12
  grdwindinversion/load_config.py,sha256=ZPozOWt0rf2Pmyc6P2D75cE_9wKUfKfr7RUzlE3WoiY,833
12
13
  grdwindinversion/main.py,sha256=Cwmxxz-PEt53JvpTL0Jx1WKLJpWvlIXZ9xtnyGKrGHY,3254
13
- grdwindinversion/utils.py,sha256=Jj2M433WC9z5Yk4yZaUxSnKwCskfCzB_EsIbVDW5PPw,3818
14
+ grdwindinversion/utils.py,sha256=2BRq_UEbKbP5yCy_0X-nV-SQFmmp4aKrFaRgrs5MqJo,4347
14
15
  grdwindinversion/utils_memory.py,sha256=NA0bvkpCTkEiqCcJuldG1XsrP40-3AQUUt3HLeoRpbY,1432
15
16
  grdwindinversion/.github/ISSUE_TEMPLATE.md,sha256=qiM_a7CCUz3fSrz3Q20Se1nwPNFS8QCc8tkwK_0DSCo,327
16
- grdwindinversion-0.3.5.dist-info/AUTHORS.rst,sha256=KmhW_5LBKGTIGwWEVkoTm1qx_bvdDR3yYL-1cwbDOFQ,218
17
- grdwindinversion-0.3.5.dist-info/LICENSE,sha256=-B8mBiTeY3J7OLuayiV1myqmc7yeijBc7s34kc8RTmg,1075
18
- grdwindinversion-0.3.5.dist-info/METADATA,sha256=Ox0BIVGEoEmbnEyv9a3SH7fQLwAXfo_RV7VeTXgZh7g,2441
19
- grdwindinversion-0.3.5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
20
- grdwindinversion-0.3.5.dist-info/entry_points.txt,sha256=2rjvlVCy0iasRXjOz3kOIGuy2OCGQ-VTNuwuViQ6cMM,95
21
- grdwindinversion-0.3.5.dist-info/top_level.txt,sha256=z6lPix3QPEYOo37qq8plA2hY7S3C8MQZY81agRlksMI,17
22
- grdwindinversion-0.3.5.dist-info/RECORD,,
17
+ grdwindinversion-0.3.8.dist-info/licenses/AUTHORS.rst,sha256=KmhW_5LBKGTIGwWEVkoTm1qx_bvdDR3yYL-1cwbDOFQ,218
18
+ grdwindinversion-0.3.8.dist-info/licenses/LICENSE,sha256=-B8mBiTeY3J7OLuayiV1myqmc7yeijBc7s34kc8RTmg,1075
19
+ grdwindinversion-0.3.8.dist-info/METADATA,sha256=Zhr0ANP7Ek5Kb5zzEBoh8cheWMmvI91EwfbclEOlens,2529
20
+ grdwindinversion-0.3.8.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
21
+ grdwindinversion-0.3.8.dist-info/entry_points.txt,sha256=2rjvlVCy0iasRXjOz3kOIGuy2OCGQ-VTNuwuViQ6cMM,95
22
+ grdwindinversion-0.3.8.dist-info/top_level.txt,sha256=z6lPix3QPEYOo37qq8plA2hY7S3C8MQZY81agRlksMI,17
23
+ grdwindinversion-0.3.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5