grdwindinversion 0.2.3.post11__tar.gz → 0.2.3.post12__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 (54) hide show
  1. {grdwindinversion-0.2.3.post11/grdwindinversion.egg-info → grdwindinversion-0.2.3.post12}/PKG-INFO +1 -1
  2. grdwindinversion-0.2.3.post12/grdwindinversion/config_luts.yaml +4 -0
  3. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/config_prod.yaml +4 -0
  4. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/config_prod_recal.yaml +4 -0
  5. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/inversion.py +136 -63
  6. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/main.py +16 -14
  7. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12/grdwindinversion.egg-info}/PKG-INFO +1 -1
  8. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion.egg-info/SOURCES.txt +1 -0
  9. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/.editorconfig +0 -0
  10. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/.github/dependabot.yml +0 -0
  11. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/.github/workflows/publish.yml +0 -0
  12. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/.gitignore +0 -0
  13. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/.pre-commit-config.yaml +0 -0
  14. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/AUTHORS.rst +0 -0
  15. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/CONTRIBUTING.rst +0 -0
  16. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/HISTORY.rst +0 -0
  17. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/LICENSE +0 -0
  18. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/MANIFEST.in +0 -0
  19. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/Makefile +0 -0
  20. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/README.md +0 -0
  21. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/ci/requirements/docs.yaml +0 -0
  22. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/ci/requirements/environment.yaml +0 -0
  23. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/Makefile +0 -0
  24. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/_static/css/grdwindinversion.css +0 -0
  25. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/algorithm.rst +0 -0
  26. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/authors.rst +0 -0
  27. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/conf.py +0 -0
  28. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/contributing.rst +0 -0
  29. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/examples/wind-inversion-from-grd.ipynb +0 -0
  30. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/history.rst +0 -0
  31. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/index.rst +0 -0
  32. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/installation.rst +0 -0
  33. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/make.bat +0 -0
  34. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/modules.rst +0 -0
  35. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/readme.rst +0 -0
  36. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/docs/usage.rst +0 -0
  37. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/.github/ISSUE_TEMPLATE.md +0 -0
  38. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/.gitignore +0 -0
  39. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/.travis.yml +0 -0
  40. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/__init__.py +0 -0
  41. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/data_config.yaml +0 -0
  42. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/load_config.py +0 -0
  43. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion/utils.py +0 -0
  44. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion.egg-info/dependency_links.txt +0 -0
  45. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion.egg-info/entry_points.txt +0 -0
  46. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion.egg-info/requires.txt +0 -0
  47. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/grdwindinversion.egg-info/top_level.txt +0 -0
  48. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/pyproject.toml +0 -0
  49. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/requirements_dev.txt +0 -0
  50. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/requirements_doc.txt +0 -0
  51. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/setup.cfg +0 -0
  52. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/tests/__init__.py +0 -0
  53. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/tests/test_grdwindinversion.py +0 -0
  54. {grdwindinversion-0.2.3.post11 → grdwindinversion-0.2.3.post12}/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.post12
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
@@ -0,0 +1,4 @@
1
+ inc_step: 0.1
2
+ wspd_step: 0.1
3
+ phi_step: 1.0
4
+ resolution: "high"
@@ -4,21 +4,25 @@ 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"
@@ -4,21 +4,25 @@ S1A:
4
4
  dsig_VH_NAME: "gmf_s1_v2"
5
5
  apply_flattening: True
6
6
  recalibration: True
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: True
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: True
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: True
28
+ ancillary: "ecmwf"
@@ -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, config_luts_path, overwrite=False, resolution='1000m'):
497
491
  """
498
492
  Main function to generate L2 product.
499
493
 
@@ -501,35 +495,44 @@ 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
502
+ config_luts_path : str
503
+ configuration LUTs file path
508
504
  overwrite : bool, optional
509
505
  overwrite existing file
510
- generateCSV : bool, optional
511
- generate CSV file
512
506
  resolution : str, optional
513
507
  working resolution
514
508
 
515
509
  Returns
516
510
  -------
517
- str
518
- output filename
519
511
  xarray.Dataset
520
- final dataset
512
+ final dataset
521
513
  """
522
514
 
523
515
  sensor, sensor_longname, fct_meta, fct_dataset = getSensorMetaDataset(
524
516
  filename)
525
517
 
526
- if Path(config_path).exists():
527
- config = yaml.load(
528
- Path(config_path).open(),
529
- Loader=yaml.FullLoader
530
- )
518
+ if os.path.exists(config_luts_path):
519
+ with open(config_luts_path, 'r') as file:
520
+ config_luts = yaml.load(
521
+ file,
522
+ Loader=yaml.FullLoader
523
+ )
524
+ else:
525
+ raise FileNotFoundError(
526
+ 'config_luts_path do not exists, got %s ' % config_luts_path)
527
+
528
+ if os.path.exists(config_path):
529
+ with open(config_path, 'r') as file:
530
+ config_base = yaml.load(
531
+ file,
532
+ Loader=yaml.FullLoader
533
+ )
531
534
  try:
532
- config = config[sensor]
535
+ config = config_base[sensor]
533
536
  except Exception:
534
537
  raise KeyError("sensor %s not in this config" % sensor)
535
538
  else:
@@ -538,11 +541,10 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
538
541
 
539
542
  recalibration = config["recalibration"]
540
543
  meta = fct_meta(filename)
541
- out_file = getOutputName2(filename, out_folder, sensor, meta)
544
+ out_file = getOutputName2(filename, outdir, sensor, meta)
542
545
 
543
546
  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()
547
+ raise FileExistsError("out_file %s exists already")
546
548
 
547
549
  ancillary_name = config["ancillary"]
548
550
  map_model = getAncillary(meta, ancillary_name)
@@ -594,12 +596,12 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
594
596
  copol_gmf = 'VV'
595
597
  crosspol_gmf = 'VH'
596
598
  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 !!')
599
+ logging.warning('for now this processor does not support entirely HH+HV acquisitions\n '
600
+ 'it wont crash but it will use HH+VH GMF for wind inversion -> wrong hypothesis\n '
601
+ '!! dual WIND SPEED IS NOT USABLE !! But co WIND SPEED IS USABLE !!')
600
602
  copol = 'HH'
601
603
  crosspol = 'HV'
602
- copol_gmf = 'VV'
604
+ copol_gmf = 'HH'
603
605
  crosspol_gmf = 'VH'
604
606
 
605
607
  #  Step 2 - clean and prepare dataset
@@ -666,7 +668,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
666
668
  xr_dataset['ancillary_wind_direction'].attrs = {}
667
669
  xr_dataset['ancillary_wind_direction'].attrs['units'] = 'degrees_north'
668
670
  xr_dataset['ancillary_wind_direction'].attrs[
669
- 'long_name'] = f'{ancillary_name} Wind direction (meteorological convention)'
671
+ 'long_name'] = f'{ancillary_name} wind direction (meteorological convention)'
670
672
  xr_dataset['ancillary_wind_direction'].attrs['standart_name'] = 'wind_direction'
671
673
 
672
674
  xr_dataset['ancillary_wind_speed'] = np.sqrt(
@@ -677,7 +679,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
677
679
  xr_dataset['ancillary_wind_speed'].attrs = {}
678
680
  xr_dataset['ancillary_wind_speed'].attrs['units'] = 'm s^-1'
679
681
  xr_dataset['ancillary_wind_speed'].attrs[
680
- 'long_name'] = f'{ancillary_name} Wind speed'
682
+ 'long_name'] = f'{ancillary_name} wind speed'
681
683
  xr_dataset['ancillary_wind_speed'].attrs['standart_name'] = 'wind_speed'
682
684
 
683
685
  xr_dataset['ancillary_wind'] = xr.where(xr_dataset['mask'], np.nan,
@@ -734,6 +736,79 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
734
736
  model_vv = config["GMF_"+copol_gmf+"_NAME"]
735
737
  model_vh = config["GMF_"+crosspol_gmf+"_NAME"]
736
738
 
739
+ if ((recalibration) & ("SENTINEL" in sensor_longname)):
740
+ xr_dataset["path_aux_pp1_new"] = os.path.basename(os.path.dirname(
741
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_pp1_new'])))
742
+ xr_dataset["path_aux_cal_new"] = os.path.basename(os.path.dirname(
743
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_cal_new'])))
744
+
745
+ xr_dataset["path_aux_pp1_old"] = os.path.basename(os.path.dirname(
746
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_pp1_old'])))
747
+ xr_dataset["path_aux_cal_old"] = os.path.basename(os.path.dirname(
748
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_cal_old'])))
749
+
750
+ 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, config_luts
751
+
752
+
753
+ def makeL2(filename, outdir, config_path, config_luts_path, overwrite=False, generateCSV=True, resolution='1000m'):
754
+ """
755
+ Main function to generate L2 product.
756
+
757
+ Parameters
758
+ ----------
759
+ filename : str
760
+ input filename
761
+ outdir : str
762
+ output folder
763
+ config_path : str
764
+ configuration file path
765
+ config_luts_path : str
766
+ configuration LUTs file path
767
+ overwrite : bool, optional
768
+ overwrite existing file
769
+ generateCSV : bool, optional
770
+ generate CSV file
771
+ resolution : str, optional
772
+ working resolution
773
+
774
+ Returns
775
+ -------
776
+ str
777
+ output filename
778
+ xarray.Dataset
779
+ final dataset
780
+ """
781
+
782
+ xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf, model_vv, model_vh, sigma0_ocean_cross, dsig_cross, sensor_longname, out_file, config, config_luts = preprocess(
783
+ filename, outdir, config_path, config_luts_path, overwrite, resolution)
784
+
785
+ kwargs = {
786
+ "inc_step_lr": config_luts.pop("inc_step_lr", None),
787
+ "wpsd_step_lr": config_luts.pop("wspd_step_lr", None),
788
+ "phi_step_lr": config_luts.pop("phi_step_lr", None),
789
+ "inc_step": config_luts.pop("inc_step", None),
790
+ "wpsd_step": config_luts.pop("wspd_step", None),
791
+ "phi_step": config_luts.pop("phi_step", None),
792
+ "resolution": config_luts.pop("resolution", None),
793
+ }
794
+
795
+ # need to load gmfs before
796
+
797
+ gmfs_impl = [x for x in [model_vv, model_vh] if "gmf_" in x]
798
+ windspeed.gmfs.GmfModel.activate_gmfs_impl(gmfs_impl)
799
+ sarwings_luts = [x for x in [model_vv, model_vh]
800
+ if x.startswith("sarwing_lut_")]
801
+ if len(sarwings_luts) > 0:
802
+ windspeed.register_sarwing_luts(getConf()["sarwing_luts_path"])
803
+
804
+ nc_luts = [x for x in [model_vv, model_vh] if x.startswith("nc_lut")]
805
+
806
+ if len(nc_luts) > 0:
807
+ windspeed.register_nc_luts(getConf()["nc_luts_path"])
808
+
809
+ if (model_vv == "gmf_cmod7"):
810
+ windspeed.register_cmod7(getConf()["lut_cmod7_path"])
811
+
737
812
  wind_co, wind_dual, windspeed_cr = inverse(dual_pol,
738
813
  inc=xr_dataset['incidence'],
739
814
  sigma0=xr_dataset['sigma0_ocean'].sel(
@@ -742,7 +817,8 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
742
817
  ancillary_wind=xr_dataset['ancillary_wind'],
743
818
  dsig_cr=dsig_cross,
744
819
  model_vv=model_vv,
745
- model_vh=model_vh)
820
+ model_vh=model_vh,
821
+ ** kwargs)
746
822
 
747
823
  # windspeed_co
748
824
  xr_dataset['windspeed_co'] = np.abs(wind_co)
@@ -755,7 +831,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
755
831
 
756
832
  # winddir_co
757
833
  xr_dataset['winddir_co'] = (
758
- 90 - (np.angle(-np.conj(wind_co), deg=True)) + xr_dataset.ground_heading) % 360
834
+ 90 - (np.angle(wind_co, deg=True)) + xr_dataset.ground_heading) % 360
759
835
  xr_dataset["winddir_co"].attrs["units"] = "degrees_north"
760
836
  xr_dataset["winddir_co"].attrs["long_name"] = "Wind direction in meteorological convention, 0=North, 90=East, inverted from model %s (%s)" % (
761
837
  model_vv, copol)
@@ -773,7 +849,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
773
849
  del xr_dataset["windspeed_dual"].attrs['comment']
774
850
 
775
851
  xr_dataset['winddir_dual'] = (
776
- 90 - (np.angle(-np.conj(wind_dual), deg=True)) + xr_dataset.ground_heading) % 360
852
+ 90 - (np.angle(wind_dual, deg=True)) + xr_dataset.ground_heading) % 360
777
853
  xr_dataset["winddir_dual"].attrs["units"] = "degrees_north"
778
854
  xr_dataset["winddir_dual"].attrs["long_name"] = "Wind direction in meteorological convention, 0=North, 90=East inverted from model %s (%s) & %s (%s)" % (
779
855
  model_vv, copol, model_vh, crosspol)
@@ -795,7 +871,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
795
871
  xr_dataset["winddir_cross"].attrs["model"] = "No model used ; content is a copy of dualpol wind direction"
796
872
 
797
873
  xr_dataset, encoding = makeL2asOwi(
798
- xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf, config)
874
+ xr_dataset, dual_pol, copol, crosspol)
799
875
 
800
876
  #  add attributes
801
877
  firstMeasurementTime = None
@@ -847,16 +923,9 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
847
923
  "ancillary_source": xr_dataset.attrs['ancillary_source']
848
924
  }
849
925
 
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'])))
926
+ for recalib_attrs in ["path_aux_pp1_new", 'path_aux_pp1_old', "path_aux_cal_new", "path_aux_cal_old"]:
927
+ if recalib_attrs in xr_dataset:
928
+ attrs[recalib_attrs] = xr_dataset.attrs[recalib_attrs]
860
929
 
861
930
  # new one to match convention
862
931
  _S1_added_attrs = ["product", "ipf", "multi_dataset", "footprint",
@@ -871,6 +940,10 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
871
940
  if var in attrs:
872
941
  attrs[var] = str(attrs[var])
873
942
 
943
+ # add in kwargs in attrs
944
+ for key in kwargs:
945
+ attrs["lut_params_"+key] = "/" if kwargs[key] is None else kwargs[key]
946
+
874
947
  xr_dataset.attrs = attrs
875
948
 
876
949
  os.makedirs(os.path.dirname(out_file), exist_ok=True)
@@ -6,24 +6,26 @@ 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('--config_file_luts',
17
+ help='config file (luts) path', required=True)
18
+
19
+ parser.add_argument('--resolution', required=False, default='1000m',
20
+ help='set resolution ["full" | "1000m" | "xXxm"]')
21
+
20
22
  parser.add_argument('--outputdir', required=True)
21
23
  parser.add_argument('--verbose', action='store_true', default=False)
22
24
  parser.add_argument('--overwrite', action='store_true', default=False,
23
25
  help='overwrite existing .nc files [default is False]', required=False)
24
26
 
25
- parser.add_argument('--no_generate_csv', action='store_false', help="En cas d'activation, désactive la génération du .csv")
26
-
27
+ parser.add_argument('--no_generate_csv', action='store_false',
28
+ help="En cas d'activation, désactive la génération du .csv")
27
29
 
28
30
  args = parser.parse_args()
29
31
  fmt = '%(asctime)s %(levelname)s %(filename)s(%(lineno)d) %(message)s'
@@ -36,21 +38,21 @@ def processor_starting_point():
36
38
  t0 = time.time()
37
39
  input_file = args.input_file.rstrip('/')
38
40
  logging.info('input file: %s', input_file)
39
-
40
-
41
+
41
42
  # if '1SDV' not in input_file and '_VV_VH' not in input_file:
42
43
  # raise Exception('this processor only handle dual polarization acquisitions VV+VH for now.')
43
44
  # if '1SSH' in input_file or '1SDH' in input_file or '_HH_HV' in input_file:
44
45
  # raise Exception('this processor only handle acquisitions with VV or VV+VH polarization for now.')
45
-
46
46
 
47
- config_file = args.config_file
47
+ config_file = args.config_file
48
+ config_file_luts = args.config_file_luts
48
49
  out_folder = args.outputdir
49
50
  resolution = args.resolution
50
51
  if resolution == "full":
51
52
  resolution = None
52
-
53
- out_file,outputds = makeL2(input_file, out_folder, config_file, overwrite=args.overwrite,resolution = resolution, generateCSV = args.no_generate_csv)
53
+
54
+ out_file, outputds = makeL2(input_file, out_folder, config_file, config_file_luts,
55
+ overwrite=args.overwrite, resolution=resolution, generateCSV=args.no_generate_csv)
54
56
  logging.info('out_file: %s', out_file)
55
57
  logging.info('current memory usage: %s ', get_memory_usage(var='current'))
56
58
  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.post12
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
@@ -33,6 +33,7 @@ docs/examples/wind-inversion-from-grd.ipynb
33
33
  grdwindinversion/.gitignore
34
34
  grdwindinversion/.travis.yml
35
35
  grdwindinversion/__init__.py
36
+ grdwindinversion/config_luts.yaml
36
37
  grdwindinversion/config_prod.yaml
37
38
  grdwindinversion/config_prod_recal.yaml
38
39
  grdwindinversion/data_config.yaml