grdwindinversion 0.3.6__tar.gz → 0.3.8__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 (66) hide show
  1. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/.github/workflows/build.yml +2 -2
  2. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/.github/workflows/ci.yml +7 -5
  3. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/.github/workflows/publish.yml +1 -1
  4. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/PKG-INFO +4 -2
  5. grdwindinversion-0.3.8/ci/requirements/environment.yaml +36 -0
  6. grdwindinversion-0.3.8/grdwindinversion/config_prod_v3.yaml +70 -0
  7. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/inversion.py +202 -45
  8. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion.egg-info/PKG-INFO +4 -2
  9. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion.egg-info/SOURCES.txt +1 -0
  10. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion.egg-info/requires.txt +1 -0
  11. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/pyproject.toml +1 -0
  12. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/recipe/meta.yaml +1 -0
  13. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/tests/config_test.yaml +4 -0
  14. grdwindinversion-0.3.6/ci/requirements/environment.yaml +0 -35
  15. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/.editorconfig +0 -0
  16. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/.github/dependabot.yml +0 -0
  17. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/.gitignore +0 -0
  18. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/.pre-commit-config.yaml +0 -0
  19. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/AUTHORS.rst +0 -0
  20. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/CONTRIBUTING.rst +0 -0
  21. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/HISTORY.rst +0 -0
  22. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/LICENSE +0 -0
  23. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/MANIFEST.in +0 -0
  24. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/Makefile +0 -0
  25. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/README.md +0 -0
  26. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/ci/requirements/docs.yaml +0 -0
  27. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/Makefile +0 -0
  28. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/_static/css/grdwindinversion.css +0 -0
  29. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/algorithm.rst +0 -0
  30. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/authors.rst +0 -0
  31. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/conf.py +0 -0
  32. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/contributing.rst +0 -0
  33. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/examples/streaks-display.ipynb +0 -0
  34. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/examples/wind-inversion-from-grd.ipynb +0 -0
  35. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/history.rst +0 -0
  36. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/index.rst +0 -0
  37. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/installation.rst +0 -0
  38. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/make.bat +0 -0
  39. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/modules.rst +0 -0
  40. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/docs/usage.rst +0 -0
  41. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/.github/ISSUE_TEMPLATE.md +0 -0
  42. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/.gitignore +0 -0
  43. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/__init__.py +0 -0
  44. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/config_prod.yaml +0 -0
  45. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/config_prod_recal.yaml +0 -0
  46. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/config_prod_recal_streaks_nrcsmod.yaml +0 -0
  47. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/config_prod_streaks.yaml +0 -0
  48. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/config_prod_streaks_nrcsmod.yaml +0 -0
  49. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/data_config.yaml +0 -0
  50. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/gradientFeatures.py +0 -0
  51. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/load_config.py +0 -0
  52. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/main.py +0 -0
  53. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/utils.py +0 -0
  54. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion/utils_memory.py +0 -0
  55. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion.egg-info/dependency_links.txt +0 -0
  56. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion.egg-info/entry_points.txt +0 -0
  57. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/grdwindinversion.egg-info/top_level.txt +0 -0
  58. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/requirements_dev.txt +0 -0
  59. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/requirements_doc.txt +0 -0
  60. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/setup.cfg +0 -0
  61. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/tests/__init__.py +0 -0
  62. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/tests/listing_rcm_safe.txt +0 -0
  63. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/tests/test_getOutputName.py +0 -0
  64. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/tests/test_grdwindinversion_ci.py +0 -0
  65. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/tests/test_simple_functions.py +0 -0
  66. {grdwindinversion-0.3.6 → grdwindinversion-0.3.8}/tox.ini +0 -0
@@ -11,7 +11,6 @@ jobs:
11
11
  build-and-upload-conda-package:
12
12
  if: contains(github.event.head_commit.message, '[force-build]') || startsWith(github.ref, 'refs/tags/')
13
13
  runs-on: ubuntu-latest
14
- #${{ github.event.workflow_run.conclusion == 'success' }}
15
14
  steps:
16
15
  - name: Checkout repository
17
16
  uses: actions/checkout@v3
@@ -34,7 +33,7 @@ jobs:
34
33
  - name: Set version without 'v'
35
34
  run: |
36
35
  if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
37
- VERSION=${GITHUB_REF_NAME#v}
36
+ VERSION=${GITHUB_REF_NAME#v} # Remove the 'v' prefix if it's there
38
37
  else
39
38
  VERSION="0.0.0" # Dummy version for testing
40
39
  fi
@@ -44,6 +43,7 @@ jobs:
44
43
  - name: Build and Upload Conda package
45
44
  env:
46
45
  ANACONDA_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
46
+ GIT_DESCRIBE_TAG: ${{ env.GIT_DESCRIBE_TAG }} # Pass GIT_DESCRIBE_TAG to the build step
47
47
  run: |
48
48
  cd recipe
49
49
  conda init
@@ -53,8 +53,8 @@ jobs:
53
53
  id: cache
54
54
  with:
55
55
  path: ./test_data
56
- key: test-data-v3
57
- restore-keys: test-data-v3
56
+ key: test-data-v4
57
+ restore-keys: test-data-v4
58
58
 
59
59
  # Download test data if not already cached
60
60
  - name: Download test data
@@ -65,15 +65,17 @@ jobs:
65
65
  unzip /tmp/ecmwf.zip -d ./test_data/
66
66
  wget https://cloud.ifremer.fr/index.php/s/kRgdOOPsjoZieZR/download -O /tmp/l1.zip
67
67
  unzip /tmp/l1.zip -d ./test_data/
68
+ wget https://cloud.ifremer.fr/index.php/s/RgloaQ8gi8svYOe/download -O /tmp/auxiliary.zip
69
+ unzip /tmp/auxiliary.zip -d ./test_data/
68
70
  timeout-minutes: 200 # Adjust depending on the size of your data
69
71
 
70
72
  # Set up xsar configuration
71
73
  - name: Setup xsar configuration
72
74
  run: |
73
75
  mkdir -p ~/.xsar
74
- echo "data_dir: /tmp" > ~/.xsar/config.yaml
75
- echo "auxiliary_dir: ./test_data/auxiliary" >> ~/.xsar/config.yaml
76
- echo "path_dataframe_aux: ./test_data/auxiliary/active_aux.csv" >> ~/.xsar/config.yaml
76
+ echo "data_dir: /tmp" > ~/.xsar/config.yml
77
+ echo "auxiliary_dir: ./test_data/auxiliary" >> ~/.xsar/config.yml
78
+ echo "path_dataframe_aux: ./test_data/auxiliary/active_aux.csv" >> ~/.xsar/config.yml
77
79
 
78
80
  # Set up grdwindinversion configuration
79
81
  - name: Setup grdwindinversion configuration
@@ -51,4 +51,4 @@ jobs:
51
51
  path: dist/
52
52
 
53
53
  - name: Publish to PyPI
54
- uses: pypa/gh-action-pypi-publish@81e9d935c883d0b210363ab89cf05f3894778450
54
+ uses: pypa/gh-action-pypi-publish@v1.12.4
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: grdwindinversion
3
- Version: 0.3.6
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/)
@@ -0,0 +1,36 @@
1
+ name: grdwindinversion-tests
2
+ channels:
3
+ - conda-forge
4
+ dependencies:
5
+ - python=3.10
6
+ # development
7
+ - ipython
8
+ - pre-commit
9
+ - jupyterlab
10
+ - jupyterlab_code_formatter
11
+ - isort
12
+ - black
13
+ - dask-labextension
14
+ # testing
15
+ - pytest
16
+ - pytest-reportlog
17
+ - hypothesis
18
+ - coverage
19
+ # I/O
20
+ - rioxarray
21
+ - h5netcdf
22
+ - zarr
23
+ - scipy
24
+ # data
25
+ - xarray
26
+ - xarray-datatree
27
+ - dask
28
+ - numpy
29
+ - pandas
30
+ - shapely
31
+ # processing
32
+ - more-itertools
33
+ - tqdm
34
+ - lxml
35
+ - importlib_resources
36
+ - xmlschema=3.4.3
@@ -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"
@@ -189,7 +189,6 @@ def getAncillary(meta, ancillary_name="ecmwf"):
189
189
  """
190
190
 
191
191
  if ancillary_name == "ecmwf":
192
-
193
192
  logging.debug("conf: %s", getConf())
194
193
  ec01 = getConf()["ecmwf_0100_1h"]
195
194
  ec0125 = getConf()["ecmwf_0125_1h"]
@@ -282,6 +281,93 @@ def getAncillary(meta, ancillary_name="ecmwf"):
282
281
  "ancillary_name must be ecmwf/era5, got %s" % ancillary_name)
283
282
 
284
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
+
285
371
  @timing(logger=logger.debug)
286
372
  def inverse(
287
373
  dual_pol,
@@ -321,8 +407,12 @@ def inverse(
321
407
 
322
408
  Returns
323
409
  -------
324
- xarray.DataArray or tuple
325
- 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** .
326
416
 
327
417
  See Also
328
418
  --------
@@ -519,8 +609,15 @@ def makeL2asOwi(xr_dataset, config):
519
609
  )
520
610
 
521
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
+ })
522
620
  xr_dataset = xr_dataset.rename({
523
- 'dsig_cross': 'owiDsig_cross',
524
621
  'winddir_cross': 'owiWindDirection_cross',
525
622
  'winddir_dual': 'owiWindDirection',
526
623
  'windspeed_cross': 'owiWindSpeed_cross',
@@ -784,6 +881,7 @@ def preprocess(
784
881
  )
785
882
 
786
883
  try:
884
+ logging.info(f"recalibration = {recalibration}")
787
885
  if (recalibration) & ("SENTINEL" in sensor_longname):
788
886
  logging.info(
789
887
  f"recalibration is {recalibration} : Kersten formula is applied"
@@ -855,8 +953,23 @@ def preprocess(
855
953
  copol_gmf = "HH"
856
954
  crosspol_gmf = "VH"
857
955
 
858
- model_co = config["GMF_" + copol_gmf + "_NAME"]
859
- 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"]
860
973
 
861
974
  # register paramaters in config
862
975
  config["l2_params"]["dual_pol"] = dual_pol
@@ -868,6 +981,9 @@ def preprocess(
868
981
  config["l2_params"]["model_cross"] = model_cross
869
982
  config["sensor_longname"] = sensor_longname
870
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
871
987
 
872
988
  # need to load LUTs before inversion
873
989
  nc_luts = [x for x in [model_co, model_cross] if x.startswith("nc_lut")]
@@ -1048,35 +1164,35 @@ def preprocess(
1048
1164
  xr_dataset['nesz_cross_flattened'].attrs[
1049
1165
  "comment"] = 'nesz has been flattened using windspeed.nesz_flattening'
1050
1166
 
1051
- if config["apply_flattening"]:
1167
+ if dsig_cr_step == "nrcs":
1052
1168
  # dsig
1053
- xr_dataset["dsig_cross"] = windspeed.get_dsig(
1054
- config["dsig_" + crosspol_gmf + "_NAME"],
1055
- xr_dataset.incidence,
1056
- xr_dataset["sigma0_ocean"].sel(pol=crosspol),
1057
- xr_dataset.nesz_cross_flattened,
1058
- )
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
+ )
1059
1176
 
1060
- xr_dataset.dsig_cross.attrs["formula_used"] = config[
1061
- "dsig_" + crosspol_gmf + "_NAME"
1062
- ]
1177
+ xr_dataset.dsig_cross.attrs["formula_used"] = config[
1178
+ "dsig_" + crosspol_gmf + "_NAME"
1179
+ ]
1063
1180
 
1064
- else:
1065
- # dsig
1066
- xr_dataset["dsig_cross"] = windspeed.get_dsig(
1067
- config["dsig_" + crosspol_gmf + "_NAME"],
1068
- xr_dataset.incidence,
1069
- xr_dataset["sigma0_ocean"].sel(pol=crosspol),
1070
- xr_dataset.nesz.sel(pol=crosspol),
1071
- )
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),
1187
+ )
1072
1188
 
1073
- xr_dataset.dsig_cross.attrs["comment"] = (
1074
- "variable used to ponderate copol and crosspol"
1075
- )
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"
1191
+ )
1076
1192
 
1077
- xr_dataset.dsig_cross.attrs["apply_flattening"] = str(
1078
- config["apply_flattening"]
1079
- )
1193
+ xr_dataset.dsig_cross.attrs["apply_flattening"] = str(
1194
+ apply_flattening
1195
+ )
1080
1196
 
1081
1197
  if (recalibration) & ("SENTINEL" in sensor_longname):
1082
1198
  xr_dataset.attrs["aux_cal_recal"] = xsar_dataset.datatree["recalibration"].attrs["aux_cal_new"]
@@ -1254,6 +1370,7 @@ def makeL2(
1254
1370
  input filename
1255
1371
  outdir : str
1256
1372
  output folder
1373
+
1257
1374
  config_path : str
1258
1375
  configuration file path
1259
1376
  overwrite : bool, optional
@@ -1289,10 +1406,15 @@ def makeL2(
1289
1406
  dual_pol = config["l2_params"]["dual_pol"]
1290
1407
  ancillary_name = config["ancillary"]
1291
1408
  sensor_longname = config["sensor_longname"]
1292
-
1409
+ dsig_cr_step = config["dsig_cr_step"]
1410
+ dsig_cr_name = config["dsig_cr_name"]
1411
+ apply_flattening = config["apply_flattening"]
1293
1412
  if dual_pol:
1294
1413
  sigma0_ocean_cross = xr_dataset["sigma0_ocean"].sel(pol=crosspol)
1295
- 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
1296
1418
  else:
1297
1419
  sigma0_ocean_cross = None
1298
1420
  dsig_cross = 0.1 # default value set in xsarsea
@@ -1312,18 +1434,50 @@ def makeL2(
1312
1434
  inc_check_co, inc_check_cross = check_incidence_range(
1313
1435
  xr_dataset["incidence"], [model_co, model_cross], **kwargs
1314
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}")
1315
1480
 
1316
- wind_co, wind_dual, windspeed_cr = inverse(
1317
- dual_pol,
1318
- inc=xr_dataset["incidence"],
1319
- sigma0=xr_dataset["sigma0_ocean"].sel(pol=copol),
1320
- sigma0_dual=sigma0_ocean_cross,
1321
- ancillary_wind=xr_dataset["ancillary_wind"],
1322
- dsig_cr=dsig_cross,
1323
- model_co=model_co,
1324
- model_cross=model_cross,
1325
- **kwargs,
1326
- )
1327
1481
  # windspeed_co
1328
1482
  xr_dataset["windspeed_co"] = np.abs(wind_co)
1329
1483
  xr_dataset["windspeed_co"].attrs["units"] = "m.s⁻1"
@@ -1351,8 +1505,11 @@ def makeL2(
1351
1505
  % (model_co, copol, model_cross, crosspol)
1352
1506
  )
1353
1507
  xr_dataset["windspeed_dual"].attrs["standart_name"] = "wind_speed"
1354
- xr_dataset["windspeed_dual"].attrs["model"] = wind_dual.attrs["model"]
1355
- 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"]
1356
1513
 
1357
1514
  xr_dataset["winddir_dual"] = transform_winddir(
1358
1515
  wind_dual,
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: grdwindinversion
3
- Version: 0.3.6
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/)
@@ -39,6 +39,7 @@ grdwindinversion/config_prod_recal.yaml
39
39
  grdwindinversion/config_prod_recal_streaks_nrcsmod.yaml
40
40
  grdwindinversion/config_prod_streaks.yaml
41
41
  grdwindinversion/config_prod_streaks_nrcsmod.yaml
42
+ grdwindinversion/config_prod_v3.yaml
42
43
  grdwindinversion/data_config.yaml
43
44
  grdwindinversion/gradientFeatures.py
44
45
  grdwindinversion/inversion.py
@@ -7,3 +7,4 @@ numpy
7
7
  scipy
8
8
  fsspec
9
9
  aiohttp
10
+ xmlschema==3.4.3
@@ -40,6 +40,7 @@ dependencies = [
40
40
  "scipy",
41
41
  "fsspec",
42
42
  "aiohttp",
43
+ "xmlschema==3.4.3"
43
44
  ]
44
45
 
45
46
  dynamic = ["version"]
@@ -30,6 +30,7 @@ requirements:
30
30
  - xarray-safe-s1
31
31
  - xarray-safe-rcm
32
32
  - xradarsat2
33
+ - xmlschema=3.4.3
33
34
 
34
35
  about:
35
36
  home: https://github.com/umr-lops/grdwindinversion
@@ -13,6 +13,7 @@ S1A:
13
13
  wspd_step: 0.1
14
14
  phi_step: 1.0
15
15
  resolution: "high"
16
+ dsig_cr_step: "nrcs"
16
17
  S1B:
17
18
  GMF_VV_NAME: "gmf_cmod5n"
18
19
  GMF_VH_NAME: "gmf_s1_v2"
@@ -24,6 +25,7 @@ S1B:
24
25
  wspd_step: 0.1
25
26
  phi_step: 1.0
26
27
  resolution: "high"
28
+ dsig_cr_step: "nrcs"
27
29
  RS2:
28
30
  GMF_VV_NAME: "gmf_cmod5n"
29
31
  GMF_VH_NAME: "gmf_rs2_v2"
@@ -35,6 +37,7 @@ RS2:
35
37
  wspd_step: 0.1
36
38
  phi_step: 1.0
37
39
  resolution: "high"
40
+ dsig_cr_step: "nrcs"
38
41
  RCM:
39
42
  GMF_VV_NAME: "gmf_cmod5n"
40
43
  GMF_VH_NAME: "gmf_rcm_noaa"
@@ -46,6 +49,7 @@ RCM:
46
49
  wspd_step: 0.1
47
50
  phi_step: 1.0
48
51
  resolution: "high"
52
+ dsig_cr_step: "nrcs"
49
53
 
50
54
  unit_test_s1_product: "./test_data/L1/S1A_IW_GRDH_1SDV_20210909T130650_20210909T130715_039605_04AE83_C34F.SAFE"
51
55
  unit_test_rcm_product: "./test_data/L1/RCM1_OK2767220_PK2769320_1_SCLND_20230930_214014_VV_VH_GRD"
@@ -1,35 +0,0 @@
1
- name: grdwindinversion-tests
2
- channels:
3
- - conda-forge
4
- dependencies:
5
- - python=3.10
6
- # development
7
- - ipython
8
- - pre-commit
9
- - jupyterlab
10
- - jupyterlab_code_formatter
11
- - isort
12
- - black
13
- - dask-labextension
14
- # testing
15
- - pytest
16
- - pytest-reportlog
17
- - hypothesis
18
- - coverage
19
- # I/O
20
- - rioxarray
21
- - h5netcdf
22
- - zarr
23
- - scipy
24
- # data
25
- - xarray
26
- - xarray-datatree
27
- - dask
28
- - numpy
29
- - pandas
30
- - shapely
31
- # processing
32
- - more-itertools
33
- - tqdm
34
- - lxml
35
- - importlib_resources