grdwindinversion 0.2.3.post11__tar.gz → 0.2.3.post13__tar.gz

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.
Files changed (53) hide show
  1. {grdwindinversion-0.2.3.post11/grdwindinversion.egg-info → grdwindinversion-0.2.3.post13}/PKG-INFO +1 -1
  2. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/config_prod.yaml +9 -0
  3. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/config_prod_recal.yaml +20 -0
  4. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/inversion.py +122 -63
  5. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/main.py +13 -14
  6. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13/grdwindinversion.egg-info}/PKG-INFO +1 -1
  7. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/.editorconfig +0 -0
  8. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/.github/dependabot.yml +0 -0
  9. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/.github/workflows/publish.yml +0 -0
  10. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/.gitignore +0 -0
  11. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/.pre-commit-config.yaml +0 -0
  12. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/AUTHORS.rst +0 -0
  13. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/CONTRIBUTING.rst +0 -0
  14. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/HISTORY.rst +0 -0
  15. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/LICENSE +0 -0
  16. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/MANIFEST.in +0 -0
  17. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/Makefile +0 -0
  18. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/README.md +0 -0
  19. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/ci/requirements/docs.yaml +0 -0
  20. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/ci/requirements/environment.yaml +0 -0
  21. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/Makefile +0 -0
  22. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/_static/css/grdwindinversion.css +0 -0
  23. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/algorithm.rst +0 -0
  24. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/authors.rst +0 -0
  25. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/conf.py +0 -0
  26. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/contributing.rst +0 -0
  27. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/examples/wind-inversion-from-grd.ipynb +0 -0
  28. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/history.rst +0 -0
  29. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/index.rst +0 -0
  30. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/installation.rst +0 -0
  31. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/make.bat +0 -0
  32. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/modules.rst +0 -0
  33. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/readme.rst +0 -0
  34. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/docs/usage.rst +0 -0
  35. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/.github/ISSUE_TEMPLATE.md +0 -0
  36. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/.gitignore +0 -0
  37. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/.travis.yml +0 -0
  38. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/__init__.py +0 -0
  39. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/data_config.yaml +0 -0
  40. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/load_config.py +0 -0
  41. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion/utils.py +0 -0
  42. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion.egg-info/SOURCES.txt +0 -0
  43. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion.egg-info/dependency_links.txt +0 -0
  44. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion.egg-info/entry_points.txt +0 -0
  45. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion.egg-info/requires.txt +0 -0
  46. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/grdwindinversion.egg-info/top_level.txt +0 -0
  47. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/pyproject.toml +0 -0
  48. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/requirements_dev.txt +0 -0
  49. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/requirements_doc.txt +0 -0
  50. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/setup.cfg +0 -0
  51. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/tests/__init__.py +0 -0
  52. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/tests/test_grdwindinversion.py +0 -0
  53. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post13}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: grdwindinversion
3
- Version: 0.2.3.post11
3
+ Version: 0.2.3.post13
4
4
  Summary: Package to perform Wind inversion from GRD Level-1 SAR images
5
5
  License: MIT
6
6
  Classifier: Development Status :: 2 - Pre-Alpha
@@ -4,21 +4,30 @@ S1A:
4
4
  dsig_VH_NAME: "gmf_s1_v2"
5
5
  apply_flattening: True
6
6
  recalibration: False
7
+ ancillary: "ecmwf"
7
8
  S1B:
8
9
  GMF_VV_NAME: "gmf_cmod5n"
9
10
  GMF_VH_NAME: "gmf_s1_v2"
10
11
  dsig_VH_NAME: "gmf_s1_v2"
11
12
  apply_flattening: True
12
13
  recalibration: False
14
+ ancillary: "ecmwf"
13
15
  RS2:
14
16
  GMF_VV_NAME: "gmf_cmod5n"
15
17
  GMF_VH_NAME: "gmf_rs2_v2"
16
18
  dsig_VH_NAME: "gmf_rs2_v2"
17
19
  apply_flattening: False
18
20
  recalibration: False
21
+ ancillary: "ecmwf"
19
22
  RCM:
20
23
  GMF_VV_NAME: "gmf_cmod5n"
21
24
  GMF_VH_NAME: "gmf_rcm_noaa"
22
25
  dsig_VH_NAME: "gmf_s1_v2"
23
26
  apply_flattening: True
24
27
  recalibration: False
28
+ ancillary: "ecmwf"
29
+
30
+ inc_step: 0.1
31
+ wspd_step: 0.1
32
+ phi_step: 1.0
33
+ resolution: "high"
@@ -4,21 +4,41 @@ S1A:
4
4
  dsig_VH_NAME: "gmf_s1_v2"
5
5
  apply_flattening: True
6
6
  recalibration: True
7
+ ancillary: "ecmwf"
8
+ inc_step: 0.1
9
+ wspd_step: 0.1
10
+ phi_step: 1.0
11
+ resolution: "high"
7
12
  S1B:
8
13
  GMF_VV_NAME: "gmf_cmod5n"
9
14
  GMF_VH_NAME: "gmf_s1_v2"
10
15
  dsig_VH_NAME: "gmf_s1_v2"
11
16
  apply_flattening: True
12
17
  recalibration: True
18
+ ancillary: "ecmwf"
19
+ inc_step: 0.1
20
+ wspd_step: 0.1
21
+ phi_step: 1.0
22
+ resolution: "high"
13
23
  RS2:
14
24
  GMF_VV_NAME: "gmf_cmod5n"
15
25
  GMF_VH_NAME: "gmf_rs2_v2"
16
26
  dsig_VH_NAME: "gmf_rs2_v2"
17
27
  apply_flattening: False
18
28
  recalibration: True
29
+ ancillary: "ecmwf"
30
+ inc_step: 0.1
31
+ wspd_step: 0.1
32
+ phi_step: 1.0
33
+ resolution: "high"
19
34
  RCM:
20
35
  GMF_VV_NAME: "gmf_cmod5n"
21
36
  GMF_VH_NAME: "gmf_rcm_noaa"
22
37
  dsig_VH_NAME: "gmf_s1_v2"
23
38
  apply_flattening: True
24
39
  recalibration: True
40
+ ancillary: "ecmwf"
41
+ inc_step: 0.1
42
+ wspd_step: 0.1
43
+ phi_step: 1.0
44
+ resolution: "high"
@@ -10,7 +10,6 @@ import sys
10
10
  import datetime
11
11
  import os
12
12
  import yaml
13
- from pathlib import Path
14
13
  from scipy.ndimage import binary_dilation
15
14
 
16
15
  import re
@@ -50,7 +49,7 @@ def getSensorMetaDataset(filename):
50
49
  raise ValueError("must be S1A|S1B|RS2|RCM, got filename %s" % filename)
51
50
 
52
51
 
53
- def getOutputName2(input_file, out_folder, sensor, meta):
52
+ def getOutputName2(input_file, outdir, sensor, meta):
54
53
  """
55
54
  Create output filename for L2-GRD product
56
55
 
@@ -58,7 +57,7 @@ def getOutputName2(input_file, out_folder, sensor, meta):
58
57
  ----------
59
58
  input_file : str
60
59
  input filename
61
- out_folder : str
60
+ outdir : str
62
61
  output folder
63
62
  sensor : str
64
63
  sensor name
@@ -85,7 +84,7 @@ def getOutputName2(input_file, out_folder, sensor, meta):
85
84
  match = regex.match(basename_match)
86
85
  MISSIONID, BEAM, PRODUCT, RESOLUTION, LEVEL, CLASS, POL, STARTDATE, STOPDATE, ORBIT, TAKEID, PRODID = match.groups()
87
86
  new_format = f"{MISSIONID.lower()}-{BEAM.lower()}-owi-xx-{STARTDATE.lower()}-{STOPDATE.lower()}-{ORBIT}-{TAKEID}.nc"
88
- out_file = os.path.join(out_folder, basename, new_format)
87
+ out_file = os.path.join(outdir, basename, new_format)
89
88
  return out_file
90
89
 
91
90
  elif sensor == 'RS2':
@@ -97,7 +96,7 @@ def getOutputName2(input_file, out_folder, sensor, meta):
97
96
 
98
97
  MISSIONID, DATA1, DATA2, DATA3, DATA4, DATE, TIME, POLARIZATION, LAST = match.groups()
99
98
  new_format = f"{MISSIONID.lower()}--owi-xx-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
100
- out_file = os.path.join(out_folder, basename, new_format)
99
+ out_file = os.path.join(outdir, basename, new_format)
101
100
  return out_file
102
101
 
103
102
  elif sensor == 'RCM':
@@ -108,7 +107,7 @@ def getOutputName2(input_file, out_folder, sensor, meta):
108
107
  match = regex.match(basename_match)
109
108
  MISSIONID, DATA1, DATA2, DATA3, DATA4, DATE, TIME, POLARIZATION1, POLARIZATION2, LAST = match.groups()
110
109
  new_format = f"{MISSIONID.lower()}--owi-xx-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
111
- out_file = os.path.join(out_folder, basename, new_format)
110
+ out_file = os.path.join(outdir, basename, new_format)
112
111
  return out_file
113
112
 
114
113
  else:
@@ -212,7 +211,7 @@ def getAncillary(meta, ancillary_name='ecmwf'):
212
211
  ancillary_name)
213
212
 
214
213
 
215
- def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_vv, model_vh):
214
+ def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_vv, model_vh, **kwargs):
216
215
  """
217
216
  Invert sigma0 to retrieve wind using model (lut or gmf).
218
217
 
@@ -228,7 +227,7 @@ def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_v
228
227
  sigma0 to be inverted for dualpol
229
228
  ancillary_wind=: xarray.DataArray (numpy.complex28)
230
229
  ancillary wind
231
- | (for example ecmwf winds), in **model convention**
230
+ | (for example ecmwf winds), in **GMF convention** (-np.conj included),
232
231
  dsig_cr=: float or xarray.DataArray
233
232
  parameters used for
234
233
 
@@ -250,21 +249,23 @@ def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_v
250
249
  """
251
250
  logging.debug("inversion")
252
251
 
253
- # add potential missing gmfs (only cmod7 & ms1ahw)
254
-
255
- if (model_vv == "gmf_cmod7"):
256
- windspeed.register_cmod7(getConf()["lut_cmod7_path"])
257
-
258
- if (model_vh == "sarwing_lut_cmodms1ahw"):
259
- windspeed.register_one_sarwing_lut(getConf()["lut_ms1ahw_path"])
252
+ list_mods = windspeed.available_models().index.tolist(
253
+ ) + windspeed.available_models().alias.tolist() + [None]
254
+ if model_vv not in list_mods:
255
+ raise ValueError(
256
+ f"model_vv {model_vv} not in windspeed.available_models() : not going further")
257
+ if model_vh not in list_mods:
258
+ raise ValueError(
259
+ f"model_vh {model_vh} not in windspeed.available_models() : not going further")
260
260
 
261
261
  winds = windspeed.invert_from_model(
262
262
  inc,
263
263
  sigma0,
264
264
  sigma0_dual,
265
- ancillary_wind=-np.conj(ancillary_wind),
265
+ ancillary_wind=ancillary_wind,
266
266
  dsig_cr=dsig_cr,
267
- model=(model_vv, model_vh))
267
+ model=(model_vv, model_vh),
268
+ **kwargs)
268
269
 
269
270
  if dual_pol:
270
271
  wind_co, wind_dual = winds
@@ -273,7 +274,8 @@ def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_v
273
274
  inc.values,
274
275
  sigma0_dual.values,
275
276
  dsig_cr=dsig_cr.values,
276
- model=model_vh)
277
+ model=model_vh,
278
+ **kwargs)
277
279
 
278
280
  return wind_co, wind_dual, wind_cross
279
281
  else:
@@ -282,7 +284,7 @@ def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_v
282
284
  return wind_co, None, None
283
285
 
284
286
 
285
- def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf, config):
287
+ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol):
286
288
  """
287
289
  Rename xr_dataset variables and attributes to match naming convention.
288
290
 
@@ -296,12 +298,6 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf,
296
298
  copolarization name
297
299
  crosspol: str
298
300
  crosspolarization name
299
- copol_gmf: str
300
- copolarization GMF name
301
- crosspol_gmf: str
302
- crosspolarization GMF name
303
- config: dict
304
- configuration file
305
301
 
306
302
  Returns
307
303
  -------
@@ -462,8 +458,6 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf,
462
458
  xr_dataset = xr_dataset.drop_vars(["sigma0_raw__corrected"])
463
459
  xr_dataset = xr_dataset.drop_dims(['pol'])
464
460
 
465
- # attrs
466
-
467
461
  xr_dataset.compute()
468
462
 
469
463
  table_fillValue = {
@@ -493,7 +487,7 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf,
493
487
  return xr_dataset, encoding
494
488
 
495
489
 
496
- def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True, resolution='1000m'):
490
+ def preprocess(filename, outdir, config_path, overwrite=False, resolution='1000m'):
497
491
  """
498
492
  Main function to generate L2 product.
499
493
 
@@ -501,35 +495,32 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
501
495
  ----------
502
496
  filename : str
503
497
  input filename
504
- out_folder : str
498
+ outdir : str
505
499
  output folder
506
500
  config_path : str
507
501
  configuration file path
508
502
  overwrite : bool, optional
509
503
  overwrite existing file
510
- generateCSV : bool, optional
511
- generate CSV file
512
504
  resolution : str, optional
513
505
  working resolution
514
506
 
515
507
  Returns
516
508
  -------
517
- str
518
- output filename
519
509
  xarray.Dataset
520
- final dataset
510
+ final dataset
521
511
  """
522
512
 
523
513
  sensor, sensor_longname, fct_meta, fct_dataset = getSensorMetaDataset(
524
514
  filename)
525
515
 
526
- if Path(config_path).exists():
527
- config = yaml.load(
528
- Path(config_path).open(),
529
- Loader=yaml.FullLoader
530
- )
516
+ if os.path.exists(config_path):
517
+ with open(config_path, 'r') as file:
518
+ config_base = yaml.load(
519
+ file,
520
+ Loader=yaml.FullLoader
521
+ )
531
522
  try:
532
- config = config[sensor]
523
+ config = config_base[sensor]
533
524
  except Exception:
534
525
  raise KeyError("sensor %s not in this config" % sensor)
535
526
  else:
@@ -538,11 +529,10 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
538
529
 
539
530
  recalibration = config["recalibration"]
540
531
  meta = fct_meta(filename)
541
- out_file = getOutputName2(filename, out_folder, sensor, meta)
532
+ out_file = getOutputName2(filename, outdir, sensor, meta)
542
533
 
543
534
  if os.path.exists(out_file) and overwrite is False:
544
- logging.info("out_file %s exists ; returning empty Dataset" % out_file)
545
- return out_file, xr.Dataset()
535
+ raise FileExistsError("out_file %s exists already")
546
536
 
547
537
  ancillary_name = config["ancillary"]
548
538
  map_model = getAncillary(meta, ancillary_name)
@@ -594,12 +584,12 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
594
584
  copol_gmf = 'VV'
595
585
  crosspol_gmf = 'VH'
596
586
  else:
597
- logging.warning('for now this processor does not support HH+HV acquisitions\n '
598
- 'it wont crash but it will use VV+VH GMF for wind inversion -> wrong hypothesis\n '
599
- '!! WIND SPEED IS NOT USABLE !!')
587
+ logging.warning('for now this processor does not support entirely HH+HV acquisitions\n '
588
+ 'it wont crash but it will use HH+VH GMF for wind inversion -> wrong hypothesis\n '
589
+ '!! dual WIND SPEED IS NOT USABLE !! But co WIND SPEED IS USABLE !!')
600
590
  copol = 'HH'
601
591
  crosspol = 'HV'
602
- copol_gmf = 'VV'
592
+ copol_gmf = 'HH'
603
593
  crosspol_gmf = 'VH'
604
594
 
605
595
  #  Step 2 - clean and prepare dataset
@@ -666,7 +656,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
666
656
  xr_dataset['ancillary_wind_direction'].attrs = {}
667
657
  xr_dataset['ancillary_wind_direction'].attrs['units'] = 'degrees_north'
668
658
  xr_dataset['ancillary_wind_direction'].attrs[
669
- 'long_name'] = f'{ancillary_name} Wind direction (meteorological convention)'
659
+ 'long_name'] = f'{ancillary_name} wind direction (meteorological convention)'
670
660
  xr_dataset['ancillary_wind_direction'].attrs['standart_name'] = 'wind_direction'
671
661
 
672
662
  xr_dataset['ancillary_wind_speed'] = np.sqrt(
@@ -677,7 +667,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
677
667
  xr_dataset['ancillary_wind_speed'].attrs = {}
678
668
  xr_dataset['ancillary_wind_speed'].attrs['units'] = 'm s^-1'
679
669
  xr_dataset['ancillary_wind_speed'].attrs[
680
- 'long_name'] = f'{ancillary_name} Wind speed'
670
+ 'long_name'] = f'{ancillary_name} wind speed'
681
671
  xr_dataset['ancillary_wind_speed'].attrs['standart_name'] = 'wind_speed'
682
672
 
683
673
  xr_dataset['ancillary_wind'] = xr.where(xr_dataset['mask'], np.nan,
@@ -734,6 +724,77 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
734
724
  model_vv = config["GMF_"+copol_gmf+"_NAME"]
735
725
  model_vh = config["GMF_"+crosspol_gmf+"_NAME"]
736
726
 
727
+ if ((recalibration) & ("SENTINEL" in sensor_longname)):
728
+ xr_dataset["path_aux_pp1_new"] = os.path.basename(os.path.dirname(
729
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_pp1_new'])))
730
+ xr_dataset["path_aux_cal_new"] = os.path.basename(os.path.dirname(
731
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_cal_new'])))
732
+
733
+ xr_dataset["path_aux_pp1_old"] = os.path.basename(os.path.dirname(
734
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_pp1_old'])))
735
+ xr_dataset["path_aux_cal_old"] = os.path.basename(os.path.dirname(
736
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_cal_old'])))
737
+
738
+ return xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf, model_vv, model_vh, sigma0_ocean_cross, dsig_cross, sensor_longname, out_file, config
739
+
740
+
741
+ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, resolution='1000m'):
742
+ """
743
+ Main function to generate L2 product.
744
+
745
+ Parameters
746
+ ----------
747
+ filename : str
748
+ input filename
749
+ outdir : str
750
+ output folder
751
+ config_path : str
752
+ configuration file path
753
+ overwrite : bool, optional
754
+ overwrite existing file
755
+ generateCSV : bool, optional
756
+ generate CSV file
757
+ resolution : str, optional
758
+ working resolution
759
+
760
+ Returns
761
+ -------
762
+ str
763
+ output filename
764
+ xarray.Dataset
765
+ final dataset
766
+ """
767
+
768
+ xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf, model_vv, model_vh, sigma0_ocean_cross, dsig_cross, sensor_longname, out_file, config = preprocess(
769
+ filename, outdir, config_path, overwrite, resolution)
770
+
771
+ kwargs = {
772
+ "inc_step_lr": config.pop("inc_step_lr", None),
773
+ "wpsd_step_lr": config.pop("wspd_step_lr", None),
774
+ "phi_step_lr": config.pop("phi_step_lr", None),
775
+ "inc_step": config.pop("inc_step", None),
776
+ "wpsd_step": config.pop("wspd_step", None),
777
+ "phi_step": config.pop("phi_step", None),
778
+ "resolution": config.pop("resolution", None),
779
+ }
780
+
781
+ # need to load gmfs before
782
+
783
+ gmfs_impl = [x for x in [model_vv, model_vh] if "gmf_" in x]
784
+ windspeed.gmfs.GmfModel.activate_gmfs_impl(gmfs_impl)
785
+ sarwings_luts = [x for x in [model_vv, model_vh]
786
+ if x.startswith("sarwing_lut_")]
787
+ if len(sarwings_luts) > 0:
788
+ windspeed.register_sarwing_luts(getConf()["sarwing_luts_path"])
789
+
790
+ nc_luts = [x for x in [model_vv, model_vh] if x.startswith("nc_lut")]
791
+
792
+ if len(nc_luts) > 0:
793
+ windspeed.register_nc_luts(getConf()["nc_luts_path"])
794
+
795
+ if (model_vv == "gmf_cmod7"):
796
+ windspeed.register_cmod7(getConf()["lut_cmod7_path"])
797
+
737
798
  wind_co, wind_dual, windspeed_cr = inverse(dual_pol,
738
799
  inc=xr_dataset['incidence'],
739
800
  sigma0=xr_dataset['sigma0_ocean'].sel(
@@ -742,7 +803,8 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
742
803
  ancillary_wind=xr_dataset['ancillary_wind'],
743
804
  dsig_cr=dsig_cross,
744
805
  model_vv=model_vv,
745
- model_vh=model_vh)
806
+ model_vh=model_vh,
807
+ ** kwargs)
746
808
 
747
809
  # windspeed_co
748
810
  xr_dataset['windspeed_co'] = np.abs(wind_co)
@@ -755,7 +817,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
755
817
 
756
818
  # winddir_co
757
819
  xr_dataset['winddir_co'] = (
758
- 90 - (np.angle(-np.conj(wind_co), deg=True)) + xr_dataset.ground_heading) % 360
820
+ 90 - (np.angle(wind_co, deg=True)) + xr_dataset.ground_heading) % 360
759
821
  xr_dataset["winddir_co"].attrs["units"] = "degrees_north"
760
822
  xr_dataset["winddir_co"].attrs["long_name"] = "Wind direction in meteorological convention, 0=North, 90=East, inverted from model %s (%s)" % (
761
823
  model_vv, copol)
@@ -773,7 +835,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
773
835
  del xr_dataset["windspeed_dual"].attrs['comment']
774
836
 
775
837
  xr_dataset['winddir_dual'] = (
776
- 90 - (np.angle(-np.conj(wind_dual), deg=True)) + xr_dataset.ground_heading) % 360
838
+ 90 - (np.angle(wind_dual, deg=True)) + xr_dataset.ground_heading) % 360
777
839
  xr_dataset["winddir_dual"].attrs["units"] = "degrees_north"
778
840
  xr_dataset["winddir_dual"].attrs["long_name"] = "Wind direction in meteorological convention, 0=North, 90=East inverted from model %s (%s) & %s (%s)" % (
779
841
  model_vv, copol, model_vh, crosspol)
@@ -795,7 +857,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
795
857
  xr_dataset["winddir_cross"].attrs["model"] = "No model used ; content is a copy of dualpol wind direction"
796
858
 
797
859
  xr_dataset, encoding = makeL2asOwi(
798
- xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf, config)
860
+ xr_dataset, dual_pol, copol, crosspol)
799
861
 
800
862
  #  add attributes
801
863
  firstMeasurementTime = None
@@ -847,16 +909,9 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
847
909
  "ancillary_source": xr_dataset.attrs['ancillary_source']
848
910
  }
849
911
 
850
- if ((recalibration) & ("SENTINEL" in sensor_longname)):
851
- attrs["path_aux_pp1_new"] = os.path.basename(os.path.dirname(
852
- os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_pp1_new'])))
853
- attrs["path_aux_cal_new"] = os.path.basename(os.path.dirname(
854
- os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_cal_new'])))
855
-
856
- attrs["path_aux_pp1_old"] = os.path.basename(os.path.dirname(
857
- os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_pp1_old'])))
858
- attrs["path_aux_cal_old"] = os.path.basename(os.path.dirname(
859
- os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_cal_old'])))
912
+ for recalib_attrs in ["path_aux_pp1_new", 'path_aux_pp1_old', "path_aux_cal_new", "path_aux_cal_old"]:
913
+ if recalib_attrs in xr_dataset:
914
+ attrs[recalib_attrs] = xr_dataset.attrs[recalib_attrs]
860
915
 
861
916
  # new one to match convention
862
917
  _S1_added_attrs = ["product", "ipf", "multi_dataset", "footprint",
@@ -871,6 +926,10 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
871
926
  if var in attrs:
872
927
  attrs[var] = str(attrs[var])
873
928
 
929
+ # add in kwargs in attrs
930
+ for key in kwargs:
931
+ attrs["lut_params_"+key] = "/" if kwargs[key] is None else kwargs[key]
932
+
874
933
  xr_dataset.attrs = attrs
875
934
 
876
935
  os.makedirs(os.path.dirname(out_file), exist_ok=True)
@@ -6,24 +6,23 @@ import logging
6
6
 
7
7
 
8
8
  def processor_starting_point():
9
- import argparse, os
10
- from pathlib import Path
9
+ import argparse
11
10
 
12
11
  parser = argparse.ArgumentParser(
13
12
  description='Perform inversion from S1(L1-GRD) SAFE, L1-RCM, L1-RS2 ; using xsar/xsarsea tools')
14
13
  parser.add_argument('--input_file', help='input file path', required=True)
15
14
  parser.add_argument('--config_file',
16
- help='config file path [if not provided will take config file based on input file]',required=True)
17
-
18
- parser.add_argument('--resolution',required=False, default='1000m', help='set resolution ["full" | "1000m" | "xXxm"]')
19
-
15
+ help='config file path [if not provided will take config file based on input file]', required=True)
16
+ parser.add_argument('--resolution', required=False, default='1000m',
17
+ help='set resolution ["full" | "1000m" | "xXxm"]')
18
+
20
19
  parser.add_argument('--outputdir', required=True)
21
20
  parser.add_argument('--verbose', action='store_true', default=False)
22
21
  parser.add_argument('--overwrite', action='store_true', default=False,
23
22
  help='overwrite existing .nc files [default is False]', required=False)
24
23
 
25
- parser.add_argument('--no_generate_csv', action='store_false', help="En cas d'activation, désactive la génération du .csv")
26
-
24
+ parser.add_argument('--no_generate_csv', action='store_false',
25
+ help="En cas d'activation, désactive la génération du .csv")
27
26
 
28
27
  args = parser.parse_args()
29
28
  fmt = '%(asctime)s %(levelname)s %(filename)s(%(lineno)d) %(message)s'
@@ -36,21 +35,21 @@ def processor_starting_point():
36
35
  t0 = time.time()
37
36
  input_file = args.input_file.rstrip('/')
38
37
  logging.info('input file: %s', input_file)
39
-
40
-
38
+
41
39
  # if '1SDV' not in input_file and '_VV_VH' not in input_file:
42
40
  # raise Exception('this processor only handle dual polarization acquisitions VV+VH for now.')
43
41
  # if '1SSH' in input_file or '1SDH' in input_file or '_HH_HV' in input_file:
44
42
  # raise Exception('this processor only handle acquisitions with VV or VV+VH polarization for now.')
45
-
46
43
 
47
- config_file = args.config_file
44
+ config_file = args.config_file
48
45
  out_folder = args.outputdir
49
46
  resolution = args.resolution
50
47
  if resolution == "full":
51
48
  resolution = None
52
-
53
- out_file,outputds = makeL2(input_file, out_folder, config_file, overwrite=args.overwrite,resolution = resolution, generateCSV = args.no_generate_csv)
49
+
50
+ out_file, outputds = makeL2(input_file, out_folder, config_file,
51
+ overwrite=args.overwrite, resolution=resolution, generateCSV=args.no_generate_csv)
52
+
54
53
  logging.info('out_file: %s', out_file)
55
54
  logging.info('current memory usage: %s ', get_memory_usage(var='current'))
56
55
  logging.info('done in %1.3f min', (time.time() - t0) / 60.)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: grdwindinversion
3
- Version: 0.2.3.post11
3
+ Version: 0.2.3.post13
4
4
  Summary: Package to perform Wind inversion from GRD Level-1 SAR images
5
5
  License: MIT
6
6
  Classifier: Development Status :: 2 - Pre-Alpha