grdwindinversion 0.2.3.post7__tar.gz → 0.2.3.post8__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 (58) hide show
  1. {grdwindinversion-0.2.3.post7/grdwindinversion.egg-info → grdwindinversion-0.2.3.post8}/PKG-INFO +1 -1
  2. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/config_prod.yaml +4 -4
  3. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/config_prod_recal.yaml +4 -8
  4. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/inversion.py +353 -213
  5. grdwindinversion-0.2.3.post8/grdwindinversion/load_config.py +24 -0
  6. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/main.py +3 -16
  7. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8/grdwindinversion.egg-info}/PKG-INFO +1 -1
  8. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion.egg-info/SOURCES.txt +0 -4
  9. grdwindinversion-0.2.3.post7/grdwindinversion/config_RCM.yaml +0 -6
  10. grdwindinversion-0.2.3.post7/grdwindinversion/config_RS2.yaml +0 -6
  11. grdwindinversion-0.2.3.post7/grdwindinversion/config_S1.yaml +0 -12
  12. grdwindinversion-0.2.3.post7/grdwindinversion/config_hy2b.yaml +0 -24
  13. grdwindinversion-0.2.3.post7/grdwindinversion/load_config.py +0 -22
  14. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/.editorconfig +0 -0
  15. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/.github/dependabot.yml +0 -0
  16. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/.github/workflows/publish.yml +0 -0
  17. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/.gitignore +0 -0
  18. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/.pre-commit-config.yaml +0 -0
  19. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/AUTHORS.rst +0 -0
  20. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/CONTRIBUTING.rst +0 -0
  21. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/HISTORY.rst +0 -0
  22. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/LICENSE +0 -0
  23. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/MANIFEST.in +0 -0
  24. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/Makefile +0 -0
  25. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/README.md +0 -0
  26. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/ci/requirements/docs.yaml +0 -0
  27. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/ci/requirements/environment.yaml +0 -0
  28. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/Makefile +0 -0
  29. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/_static/css/grdwindinversion.css +0 -0
  30. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/algorithm.rst +0 -0
  31. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/authors.rst +0 -0
  32. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/conf.py +0 -0
  33. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/contributing.rst +0 -0
  34. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/examples/wind-inversion-from-grd.ipynb +0 -0
  35. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/history.rst +0 -0
  36. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/index.rst +0 -0
  37. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/installation.rst +0 -0
  38. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/make.bat +0 -0
  39. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/modules.rst +0 -0
  40. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/readme.rst +0 -0
  41. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/docs/usage.rst +0 -0
  42. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/.github/ISSUE_TEMPLATE.md +0 -0
  43. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/.gitignore +0 -0
  44. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/.travis.yml +0 -0
  45. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/__init__.py +0 -0
  46. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/data_config.yaml +0 -0
  47. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion/utils.py +0 -0
  48. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion.egg-info/dependency_links.txt +0 -0
  49. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion.egg-info/entry_points.txt +0 -0
  50. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion.egg-info/requires.txt +0 -0
  51. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/grdwindinversion.egg-info/top_level.txt +0 -0
  52. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/pyproject.toml +0 -0
  53. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/requirements_dev.txt +0 -0
  54. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/requirements_doc.txt +0 -0
  55. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/setup.cfg +0 -0
  56. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/tests/__init__.py +0 -0
  57. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/tests/test_grdwindinversion.py +0 -0
  58. {grdwindinversion-0.2.3.post7 → grdwindinversion-0.2.3.post8}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: grdwindinversion
3
- Version: 0.2.3.post7
3
+ Version: 0.2.3.post8
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
@@ -1,23 +1,23 @@
1
1
  S1A:
2
- GMF_VV_NAME: "cmod5n"
2
+ GMF_VV_NAME: "gmf_cmod5n"
3
3
  GMF_VH_NAME: "gmf_s1_v2"
4
4
  dsig_VH_NAME: "gmf_s1_v2"
5
5
  apply_flattening: True
6
6
  recalibration: False
7
7
  S1B:
8
- GMF_VV_NAME: "cmod5n"
8
+ GMF_VV_NAME: "gmf_cmod5n"
9
9
  GMF_VH_NAME: "gmf_s1_v2"
10
10
  dsig_VH_NAME: "gmf_s1_v2"
11
11
  apply_flattening: True
12
12
  recalibration: False
13
13
  RS2:
14
- GMF_VV_NAME: "cmod5n"
14
+ GMF_VV_NAME: "gmf_cmod5n"
15
15
  GMF_VH_NAME: "gmf_rs2_v2"
16
16
  dsig_VH_NAME: "gmf_rs2_v2"
17
17
  apply_flattening: False
18
18
  recalibration: False
19
19
  RCM:
20
- GMF_VV_NAME: "cmod5n"
20
+ GMF_VV_NAME: "gmf_cmod5n"
21
21
  GMF_VH_NAME: "gmf_rcm_noaa"
22
22
  dsig_VH_NAME: "gmf_s1_v2"
23
23
  apply_flattening: True
@@ -1,28 +1,24 @@
1
1
  S1A:
2
- GMF_VV_NAME: "cmod5n"
2
+ GMF_VV_NAME: "gmf_cmod5n"
3
3
  GMF_VH_NAME: "gmf_s1_v2"
4
4
  dsig_VH_NAME: "gmf_s1_v2"
5
5
  apply_flattening: True
6
6
  recalibration: True
7
- aux_config_name: "v_IPF_36"
8
7
  S1B:
9
- GMF_VV_NAME: "cmod5n"
8
+ GMF_VV_NAME: "gmf_cmod5n"
10
9
  GMF_VH_NAME: "gmf_s1_v2"
11
10
  dsig_VH_NAME: "gmf_s1_v2"
12
11
  apply_flattening: True
13
12
  recalibration: True
14
- aux_config_name: "v_IPF_36"
15
13
  RS2:
16
- GMF_VV_NAME: "cmod5n"
14
+ GMF_VV_NAME: "gmf_cmod5n"
17
15
  GMF_VH_NAME: "gmf_rs2_v2"
18
16
  dsig_VH_NAME: "gmf_rs2_v2"
19
17
  apply_flattening: False
20
18
  recalibration: True
21
- aux_config_name: "v_IPF_36"
22
19
  RCM:
23
- GMF_VV_NAME: "cmod5n"
20
+ GMF_VV_NAME: "gmf_cmod5n"
24
21
  GMF_VH_NAME: "gmf_rcm_noaa"
25
22
  dsig_VH_NAME: "gmf_s1_v2"
26
23
  apply_flattening: True
27
24
  recalibration: True
28
- aux_config_name: "v_IPF_36"
@@ -1,5 +1,3 @@
1
- import json
2
- import pdb
3
1
  import traceback
4
2
 
5
3
  import xsar
@@ -21,24 +19,24 @@ import os
21
19
  from grdwindinversion.load_config import getConf
22
20
  # optional debug messages
23
21
  import logging
24
-
25
22
  logging.basicConfig()
26
23
  logging.getLogger('xsarsea.windspeed').setLevel(
27
24
  logging.INFO) # or .setLevel(logging.INFO)
28
- # encode gcps as json string
29
-
30
-
31
- class JSONEncoder(json.JSONEncoder):
32
- def default(self, obj):
33
- if isinstance(obj, np.integer):
34
- return int(obj)
35
25
 
36
26
 
37
27
  def getSensorMetaDataset(filename):
38
28
  """
29
+ Find the sensor name and the corresponding meta and dataset functions
39
30
 
40
- :param filename: str SAR SAFE or equivalent
41
- :return:
31
+ Parameters
32
+ ----------
33
+ filename : str
34
+ input filename
35
+
36
+ Returns
37
+ -------
38
+ tuple
39
+ sensor name, sensor long name, meta function, dataset function
42
40
  """
43
41
  if ("S1A" in filename):
44
42
  return "S1A", "SENTINEL-1 A", xsar.Sentinel1Meta, xsar.Sentinel1Dataset
@@ -54,12 +52,23 @@ def getSensorMetaDataset(filename):
54
52
 
55
53
  def getOutputName2(input_file, out_folder, sensor, meta):
56
54
  """
57
-
58
- :param input_file: str
59
- :param out_folder: str
60
- :param sensor: str S1A or S1B
61
- :param meta: obj `xsar.Sentinel1Meta` (or any other supported SAR mission)
62
- :return:
55
+ Create output filename for L2-GRD product
56
+
57
+ Parameters
58
+ ----------
59
+ input_file : str
60
+ input filename
61
+ out_folder : str
62
+ output folder
63
+ sensor : str
64
+ sensor name
65
+ meta : obj `xsar.BaseMeta` (one of the supported SAR mission)
66
+ meta object
67
+
68
+ Returns
69
+ -------
70
+ outfile : str
71
+ output filename
63
72
  """
64
73
  basename = os.path.basename(input_file)
65
74
  basename_match = basename
@@ -107,91 +116,180 @@ def getOutputName2(input_file, out_folder, sensor, meta):
107
116
  "sensor must be S1A|S1B|RS2|RCM, got sensor %s" % sensor)
108
117
 
109
118
 
110
- def getAncillary(meta):
119
+ def getAncillary(meta, ancillary_name='ecmwf'):
120
+ """
121
+ Map ancillary wind from ECMWF.
122
+ This function is used to check if the ECMWF files are available and to map the model to the SAR data.
111
123
 
112
- logging.debug('conf: %s', getConf())
113
- ec01 = getConf()['ecmwf_0100_1h']
114
- ec0125 = getConf()['ecmwf_0125_1h']
115
- logging.debug('ec01 : %s', ec01)
116
- meta.set_raster('ecmwf_0100_1h', ec01)
117
- meta.set_raster('ecmwf_0125_1h', ec0125)
124
+ Parameters
125
+ ----------
126
+ meta: obj `xsar.BaseMeta` (one of the supported SAR mission)
118
127
 
119
- map_model = None
120
- # only keep best ecmwf (FIXME: it's hacky, and xsar should provide a better method to handle this)
121
- for ecmwf_name in ['ecmwf_0125_1h', 'ecmwf_0100_1h']:
122
- ecmwf_infos = meta.rasters.loc[ecmwf_name]
123
- try:
124
- ecmwf_file = ecmwf_infos['get_function'](ecmwf_infos['resource'],
125
- date=datetime.datetime.strptime(meta.start_date,
126
- '%Y-%m-%d %H:%M:%S.%f'))[1]
127
- # temporary for RCM issue https://github.com/umr-lops/xarray-safe-rcm/issues/34
128
- except Exception as e:
129
- ecmwf_file = ecmwf_infos['get_function'](ecmwf_infos['resource'],
130
- date=datetime.datetime.strptime(meta.start_date,
131
- '%Y-%m-%d %H:%M:%S'))[1]
132
-
133
- if not os.path.isfile(ecmwf_file):
134
- # temporary
135
- # if repro does not exist we look at not repro folder (only one will exist after)
136
- if ecmwf_name == "ecmwf_0100_1h":
137
- ecmwf_infos['resource'] = ecmwf_infos['resource'].replace(
138
- "netcdf_light_REPRO_tree", "netcdf_light")
139
- try:
140
- ecmwf_file = ecmwf_infos['get_function'](ecmwf_infos['resource'],
141
- date=datetime.datetime.strptime(meta.start_date,
142
- '%Y-%m-%d %H:%M:%S.%f'))[1]
143
- except Exception as e:
144
- ecmwf_file = ecmwf_infos['get_function'](ecmwf_infos['resource'],
145
- date=datetime.datetime.strptime(meta.start_date,
146
- '%Y-%m-%d %H:%M:%S'))[1]
147
-
148
- if not os.path.isfile(ecmwf_file):
149
- meta.rasters = meta.rasters.drop([ecmwf_name])
150
- else:
151
- map_model = {'%s_%s' % (ecmwf_name, uv): 'model_%s' % uv for uv in [
152
- 'U10', 'V10']}
128
+ Returns
129
+ -------
130
+ dict
131
+ map model to SAR data
132
+ """
153
133
 
154
- else:
134
+ if ancillary_name == 'ecmwf':
135
+
136
+ logging.debug('conf: %s', getConf())
137
+ ec01 = getConf()['ecmwf_0100_1h']
138
+ ec0125 = getConf()['ecmwf_0125_1h']
139
+ logging.debug('ec01 : %s', ec01)
140
+ meta.set_raster('ecmwf_0100_1h', ec01)
141
+ meta.set_raster('ecmwf_0125_1h', ec0125)
142
+
143
+ map_model = None
144
+ # only keep best ecmwf (FIXME: it's hacky, and xsar should provide a better method to handle this)
145
+ for ecmwf_name in ['ecmwf_0125_1h', 'ecmwf_0100_1h']:
146
+ ecmwf_infos = meta.rasters.loc[ecmwf_name]
147
+ try:
148
+ ecmwf_file = ecmwf_infos['get_function'](ecmwf_infos['resource'],
149
+ date=datetime.datetime.strptime(meta.start_date,
150
+ '%Y-%m-%d %H:%M:%S.%f'))[1]
151
+ # temporary for RCM issue https://github.com/umr-lops/xarray-safe-rcm/issues/34
152
+ except Exception as e:
153
+ ecmwf_file = ecmwf_infos['get_function'](ecmwf_infos['resource'],
154
+ date=datetime.datetime.strptime(meta.start_date,
155
+ '%Y-%m-%d %H:%M:%S'))[1]
156
+ if not os.path.isfile(ecmwf_file):
157
+ # temporary
158
+ # if repro does not exist we look at not repro folder (only one will exist after)
159
+ """
160
+ if ecmwf_name == "ecmwf_0100_1h":
161
+ ecmwf_infos['resource'] = ecmwf_infos['resource'].replace(
162
+ "netcdf_light_REPRO_tree", "netcdf_light")
163
+ try:
164
+ ecmwf_file = ecmwf_infos['get_function'](ecmwf_infos['resource'],
165
+ date=datetime.datetime.strptime(meta.start_date,
166
+ '%Y-%m-%d %H:%M:%S.%f'))[1]
167
+ except Exception as e:
168
+ ecmwf_file = ecmwf_infos['get_function'](ecmwf_infos['resource'],
169
+ date=datetime.datetime.strptime(meta.start_date,
170
+ '%Y-%m-%d %H:%M:%S'))[1]
171
+
172
+ if not os.path.isfile(ecmwf_file):
173
+ meta.rasters = meta.rasters.drop([ecmwf_name])
174
+ else:
175
+ map_model = {'%s_%s' % (ecmwf_name, uv): 'model_%s' % uv for uv in [
176
+ 'U10', 'V10']}
177
+
178
+ else:
179
+ """
155
180
  meta.rasters = meta.rasters.drop([ecmwf_name])
156
- else:
157
- map_model = {'%s_%s' % (ecmwf_name, uv): 'model_%s' %
158
- uv for uv in ['U10', 'V10']}
181
+ else:
182
+ map_model = {'%s_%s' % (ecmwf_name, uv): 'model_%s' %
183
+ uv for uv in ['U10', 'V10']}
159
184
 
160
- return map_model
185
+ return map_model
186
+
187
+ else:
188
+ raise ValueError("ancillary_name must be ecmwf, got %s" %
189
+ ancillary_name)
161
190
 
162
191
 
163
192
  def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_vv, model_vh):
193
+ """
194
+ Invert sigma0 to retrieve wind using model (lut or gmf).
195
+
196
+ Parameters
197
+ ----------
198
+ dual_pol: bool
199
+ True if dualpol, False if singlepol
200
+ inc: xarray.DataArray
201
+ incidence angle
202
+ sigma0: xarray.DataArray
203
+ sigma0 to be inverted
204
+ sigma0_dual: xarray.DataArray
205
+ sigma0 to be inverted for dualpol
206
+ ancillary_wind=: xarray.DataArray (numpy.complex28)
207
+ ancillary wind
208
+ | (for example ecmwf winds), in **model convention**
209
+ dsig_cr=: float or xarray.DataArray
210
+ parameters used for
211
+
212
+ | `Jsig_cr=((sigma0_gmf - sigma0) / dsig_cr) ** 2`
213
+ model_vv=: str
214
+ model to use for VV or HH polarization.
215
+ model_vh=: str
216
+ model to use for VH or HV polarization.
217
+
218
+ Returns
219
+ -------
220
+ xarray.DataArray or tuple
221
+ inverted wind in **gmf convention** .
222
+
223
+ See Also
224
+ --------
225
+ xsarsea documentation
226
+ https://cyclobs.ifremer.fr/static/sarwing_datarmor/xsarsea/examples/windspeed_inversion.html
227
+ """
164
228
  logging.debug("inversion")
165
- # 4 - Inversion
166
- windspeeds = windspeed.invert_from_model(
229
+
230
+ # add potential missing gmfs (only cmod7 & ms1ahw)
231
+
232
+ if (model_vv == "gmf_cmod7"):
233
+ windspeed.register_cmod7(getConf()["lut_cmod7_path"])
234
+
235
+ if (model_vh == "sarwing_lut_cmodms1ahw"):
236
+ windspeed.register_one_sarwing_lut(getConf()["lut_ms1ahw_path"])
237
+
238
+ winds = windspeed.invert_from_model(
167
239
  inc,
168
240
  sigma0,
169
241
  sigma0_dual,
170
- # ancillary_wind=-np.conj(xsar_dataset.dataset['ancillary_wind']),
171
- ancillary_wind=-ancillary_wind,
242
+ ancillary_wind=-np.conj(ancillary_wind),
172
243
  dsig_cr=dsig_cr,
173
244
  model=(model_vv, model_vh))
245
+
174
246
  if dual_pol:
175
- windspeed_co, windspeed_dual = windspeeds
176
-
177
- windspeed_cr = windspeed.invert_from_model(
247
+ wind_co, wind_dual = winds
248
+
249
+ wind_cross = windspeed.invert_from_model(
178
250
  inc.values,
179
251
  sigma0_dual.values,
180
- # ancillary_wind=-np.conj(xsar_dataset.dataset['ancillary_wind']),
181
252
  dsig_cr=dsig_cr.values,
182
253
  model=model_vh)
183
254
 
184
- return np.abs(windspeed_co), np.abs(windspeed_dual), np.abs(windspeed_cr)
255
+ return wind_co, wind_dual, wind_cross
185
256
  else:
186
- windspeed_co = windspeeds
187
-
188
- return np.abs(windspeed_co), None, None
189
-
257
+ wind_co = winds
190
258
 
259
+ return wind_co, None, None
191
260
 
192
261
 
193
262
  def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf, config):
194
- # rename to match sarwing naming
263
+ """
264
+ Rename xr_dataset variables and attributes to match naming convention.
265
+
266
+ Parameters
267
+ ----------
268
+ xr_dataset: xarray.Dataset
269
+ dataset to rename
270
+ dual_pol: bool
271
+ True if dualpol, False if singlepol
272
+ copol: str
273
+ copolarization name
274
+ crosspol: str
275
+ crosspolarization name
276
+ copol_gmf: str
277
+ copolarization GMF name
278
+ crosspol_gmf: str
279
+ crosspolarization GMF name
280
+ config: dict
281
+ configuration file
282
+
283
+ Returns
284
+ -------
285
+ xarray.Dataset
286
+ final dataset
287
+ dict
288
+ encoding dict
289
+
290
+ See Also
291
+ --------
292
+ """
195
293
 
196
294
  xr_dataset = xr_dataset.rename({
197
295
  'longitude': 'owiLon',
@@ -200,12 +298,17 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf,
200
298
  'elevation': 'owiElevationAngle',
201
299
  'ground_heading': 'owiHeading',
202
300
  'land_mask': 'owiLandFlag',
203
- 'mask' : 'owiMask',
301
+ 'offboresight': 'owiOffBoresightAngle',
302
+ 'mask': 'owiMask',
204
303
  'windspeed_co': 'owiWindSpeed_co',
205
304
  'windspeed_cross': 'owiWindSpeed_cross',
206
- 'windspeed_dual': 'owiWindSpeed',
305
+ 'windspeed_dual': 'owiWindSpeed',
306
+ 'winddir_co': 'owiWindDirection_co',
307
+ 'winddir_cross': 'owiWindDirection_cross',
308
+ 'winddir_dual': 'owiWindDirection',
309
+ 'ancillary_wind_speed': 'owiEcmwfWindSpeed',
310
+ 'ancillary_wind_direction': 'owiEcmwfWindDirection',
207
311
  })
208
-
209
312
  xr_dataset['owiNrcs'] = xr_dataset['sigma0_ocean'].sel(pol=copol)
210
313
  xr_dataset.owiNrcs.attrs = xr_dataset.sigma0_ocean.attrs
211
314
  xr_dataset.owiNrcs.attrs['units'] = 'm^2 / m^2'
@@ -224,36 +327,33 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf,
224
327
  xr_dataset.owiNrcs_no_noise_correction.attrs[
225
328
  'long_name'] = 'Normalized Radar Cross Section ; no noise correction applied'
226
329
  xr_dataset.owiNrcs_no_noise_correction.attrs[
227
- 'comment'] = 'owiNrcs_no_noise_correction ; no recalibration'
228
-
330
+ 'comment'] = 'owiNrcs_no_noise_correction ; no recalibration'
331
+
229
332
  if 'swath_number' in xr_dataset:
230
333
  xr_dataset = xr_dataset.rename({
231
- 'swath_number' : 'owiSwathNumber',
232
- 'swath_number_flag' : 'owiSwathNumberFlag'
233
- })
234
-
334
+ 'swath_number': 'owiSwathNumber',
335
+ 'swath_number_flag': 'owiSwathNumberFlag'
336
+ })
337
+
235
338
  if "sigma0_raw__corrected" in xr_dataset:
236
- xr_dataset['owiNrcs_no_noise_correction_recalibrated'] = xr_dataset['sigma0_raw__corrected'].sel(pol=copol)
339
+ xr_dataset['owiNrcs_no_noise_correction_recalibrated'] = xr_dataset['sigma0_raw__corrected'].sel(
340
+ pol=copol)
237
341
  xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs = xr_dataset.sigma0_raw__corrected.attrs
238
342
  xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs['units'] = 'm^2 / m^2'
239
343
  xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs[
240
344
  'long_name'] = 'Normalized Radar Cross Section, no noise correction applied'
241
345
  xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs[
242
- 'comment'] = 'owiNrcs_no_noise_correction ; recalibrated with kersten method'
243
-
244
- xr_dataset.owiNrcs.attrs['definition'] = 'owiNrcs_no_noise_correction_recalibrated - owiNesz'
245
-
246
-
346
+ 'comment'] = 'owiNrcs_no_noise_correction ; recalibrated with kersten method'
247
347
 
348
+ xr_dataset.owiNrcs.attrs['definition'] = 'owiNrcs_no_noise_correction_recalibrated - owiNesz'
248
349
 
249
-
250
350
  if dual_pol:
251
-
351
+
252
352
  xr_dataset = xr_dataset.rename({
253
353
  'dsig_cross': 'owiDsig_cross',
254
- 'nesz_cross_final' : 'owiNesz_cross_final'
255
- })
256
-
354
+ 'nesz_cross_final': 'owiNesz_cross_final'
355
+ })
356
+
257
357
  xr_dataset['owiNrcs_cross'] = xr_dataset['sigma0_ocean'].sel(
258
358
  pol=crosspol)
259
359
  xr_dataset.owiNrcs_cross.attrs['units'] = 'm^2 / m^2'
@@ -272,37 +372,35 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf,
272
372
  'long_name'] = 'Normalized Radar Cross Section, no noise correction applied'
273
373
 
274
374
  if "sigma0_raw__corrected" in xr_dataset:
275
- xr_dataset['owiNrcs_cross_no_noise_correction_recalibrated'] = xr_dataset['sigma0_raw__corrected'].sel(pol=crosspol)
375
+ xr_dataset['owiNrcs_cross_no_noise_correction_recalibrated'] = xr_dataset['sigma0_raw__corrected'].sel(
376
+ pol=crosspol)
276
377
  xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs = xr_dataset.sigma0_raw__corrected.attrs
277
378
  xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs['units'] = 'm^2 / m^2'
278
379
  xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs[
279
380
  'long_name'] = 'Normalized Radar Cross Section ; no noise correction applied'
280
381
  xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs[
281
- 'comment'] = 'owiNrcs_cross_no_noise_correction ; recalibrated with kersten method'
282
-
382
+ 'comment'] = 'owiNrcs_cross_no_noise_correction ; recalibrated with kersten method'
383
+
283
384
  xr_dataset.owiNrcs_cross.attrs['definition'] = 'owiNrcs_cross_no_noise_correction_recalibrated - owiNesz_cross'
284
385
 
285
-
286
-
287
386
  xr_dataset["owiWindSpeed_co"].attrs["comment"] = xr_dataset["owiWindSpeed_co"].attrs["comment"].replace(
288
387
  "wind speed and direction", "wind speed")
289
388
 
389
+ xr_dataset["owiWindDirection_co"].attrs["comment"] = "wind direction in meteorological convention, 0=North, 90=East"
390
+
290
391
  if dual_pol:
291
392
  xr_dataset["owiWindSpeed"].attrs["comment"] = xr_dataset["owiWindSpeed"].attrs["comment"].replace(
292
393
  "wind speed and direction", "wind speed")
394
+ xr_dataset["owiWindDirection"].attrs["comment"] = "wind direction in meteorological convention, 0=North, 90=East"
293
395
 
294
396
  xr_dataset["owiWindSpeed_cross"].attrs['comment'] = "wind speed inverted from model %s (%s)" % (
295
397
  crosspol_gmf, crosspol)
296
398
 
399
+ xr_dataset["owiWindDirection_cross"].attrs["comment"] = "wind direction in meteorological convention, 0=North, 90=East, copied from dualpol"
400
+
297
401
  xr_dataset.owiWindSpeed_cross.attrs['model'] = crosspol_gmf
298
402
  xr_dataset.owiWindSpeed_cross.attrs['units'] = 'm/s'
299
403
 
300
- xr_dataset = xr_dataset.assign(
301
- owiEcmwfWindSpeed=(['line', 'sample'], np.abs(xr_dataset['ancillary_wind'].data)))
302
- xr_dataset = xr_dataset.assign(
303
- owiEcmwfWindDirection=(['line', 'sample'], np.angle(xr_dataset['ancillary_wind'])))
304
- xr_dataset['owiEcmwfWindDirection'].attrs['comment'] = 'angle in radians, anticlockwise, 0=sample'
305
-
306
404
  xr_dataset['owiWindQuality'] = xr.full_like(xr_dataset.owiNrcs, 0)
307
405
  xr_dataset['owiWindQuality'].attrs[
308
406
  'long_name'] = "Quality flag taking into account the consistency_between_wind_inverted_and_NRCS_and_Doppler_measured"
@@ -323,14 +421,14 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf,
323
421
 
324
422
  xr_dataset = xr_dataset.rename(
325
423
  {"line": "owiAzSize", "sample": "owiRaSize"})
326
-
327
-
328
- xr_dataset = xr_dataset.drop_vars(['sigma0_ocean', 'sigma0', 'sigma0_ocean_raw','sigma0_raw', 'ancillary_wind','nesz','spatial_ref'])
424
+
425
+ xr_dataset = xr_dataset.drop_vars(
426
+ ['sigma0_ocean', 'sigma0', 'sigma0_ocean_raw', 'sigma0_raw', 'ancillary_wind', 'nesz', 'spatial_ref'])
329
427
  if 'sigma0_raw__corrected' in xr_dataset:
330
428
  xr_dataset = xr_dataset.drop_vars(["sigma0_raw__corrected"])
331
429
  xr_dataset = xr_dataset.drop_dims(['pol'])
332
-
333
- #attrs
430
+
431
+ # attrs
334
432
 
335
433
  xr_dataset.compute()
336
434
 
@@ -340,50 +438,44 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf,
340
438
  if "approx_transform" in xr_dataset.attrs:
341
439
  del xr_dataset.attrs["approx_transform"]
342
440
 
343
- xr_dataset.attrs["TITLE"] = "Sentinel-1 OWI Component"
344
- xr_dataset.attrs["missionPhase"] = "Test"
345
- xr_dataset.attrs["polarisation"] = xr_dataset.pols
346
- xr_dataset.attrs["acquisitionStation"] = "/"
347
- xr_dataset.attrs["softwareVersion"] = "/"
348
- xr_dataset.attrs["pythonVersion"] = str(
349
- sys.version_info.major)+'.'+str(sys.version_info.minor)
350
- xr_dataset.attrs["polarisationRatio"] = "/"
351
- xr_dataset.attrs["l2ProcessingUtcTime"] = datetime.datetime.now().strftime(
441
+ xr_dataset.attrs["TITLE"] = "Sentinel-1 OWI Component"
442
+ xr_dataset.attrs["missionPhase"] = "Test"
443
+ xr_dataset.attrs["acquisitionStation"] = "/"
444
+ xr_dataset.attrs["softwareVersion"] = "/"
445
+ xr_dataset.attrs["pythonVersion"] = str(
446
+ sys.version_info.major)+'.'+str(sys.version_info.minor)
447
+ xr_dataset.attrs["polarisationRatio"] = "/"
448
+ xr_dataset.attrs["l2ProcessingUtcTime"] = datetime.datetime.now().strftime(
449
+ "%Y-%m-%dT%H:%M:%SZ")
450
+ xr_dataset.attrs["processingCenter"] = "/"
451
+ try:
452
+ xr_dataset.attrs["firstMeasurementTime"] = datetime.datetime.strptime(xr_dataset.attrs['start_date'],
453
+ "%Y-%m-%d %H:%M:%S.%f").strftime(
352
454
  "%Y-%m-%dT%H:%M:%SZ")
353
- xr_dataset.attrs["processingCenter"] = "/"
354
- try:
355
- xr_dataset.attrs["firstMeasurementTime"] = datetime.datetime.strptime(xr_dataset.attrs['start_date'],
356
- "%Y-%m-%d %H:%M:%S.%f").strftime(
357
- "%Y-%m-%dT%H:%M:%SZ")
358
- xr_dataset.attrs["lastMeasurementTime"] = datetime.datetime.strptime(xr_dataset.attrs['stop_date'],
359
- "%Y-%m-%d %H:%M:%S.%f").strftime(
360
- "%Y-%m-%dT%H:%M:%SZ")
361
- except:
362
- xr_dataset.attrs["firstMeasurementTime"] = datetime.datetime.strptime(xr_dataset.attrs['start_date'],
363
- "%Y-%m-%d %H:%M:%S").strftime(
364
- "%Y-%m-%dT%H:%M:%SZ")
365
- xr_dataset.attrs["lastMeasurementTime"] = datetime.datetime.strptime(xr_dataset.attrs['stop_date'],
366
- "%Y-%m-%d %H:%M:%S").strftime(
367
- "%Y-%m-%dT%H:%M:%SZ")
368
- xr_dataset.attrs["clmSource"] = "/"
369
- xr_dataset.attrs["bathySource"] = "/"
370
- xr_dataset.attrs['oswAlgorithmName'] = 'grdwindinversion'
371
- xr_dataset.attrs["owiAlgorithmVersion"] = grdwindinversion.__version__
372
- xr_dataset.attrs["gmf"] = config['GMF_'+copol_gmf+'_NAME'] + \
373
- ", " + config["GMF_"+crosspol_gmf+"_NAME"]
374
- xr_dataset.attrs["iceSource"] = "/"
375
- xr_dataset.attrs["owiNoiseCorrection"] = "False"
376
- xr_dataset.attrs["inversionTabGMF"] = config['GMF_'+copol_gmf +
377
- '_NAME'] + ", " + config["GMF_"+crosspol_gmf+"_NAME"]
378
- xr_dataset.attrs["wnf_3km_average"] = "/"
379
- xr_dataset.attrs["owiWindSpeedSrc"] = "owiWindSpeed"
380
- xr_dataset.attrs["owiWindDirectionSrc"] = "/"
381
-
382
- for var in xr_dataset.variables:
383
- if "history" in xr_dataset[var].attrs:
384
- del xr_dataset[var].attrs["history"]
385
-
386
-
455
+ xr_dataset.attrs["lastMeasurementTime"] = datetime.datetime.strptime(xr_dataset.attrs['stop_date'],
456
+ "%Y-%m-%d %H:%M:%S.%f").strftime(
457
+ "%Y-%m-%dT%H:%M:%SZ")
458
+ except:
459
+ xr_dataset.attrs["firstMeasurementTime"] = datetime.datetime.strptime(xr_dataset.attrs['start_date'],
460
+ "%Y-%m-%d %H:%M:%S").strftime(
461
+ "%Y-%m-%dT%H:%M:%SZ")
462
+ xr_dataset.attrs["lastMeasurementTime"] = datetime.datetime.strptime(xr_dataset.attrs['stop_date'],
463
+ "%Y-%m-%d %H:%M:%S").strftime(
464
+ "%Y-%m-%dT%H:%M:%SZ")
465
+ xr_dataset.attrs["clmSource"] = "/"
466
+ xr_dataset.attrs["bathySource"] = "/"
467
+ xr_dataset.attrs['oswAlgorithmName'] = 'grdwindinversion'
468
+ xr_dataset.attrs["owiAlgorithmVersion"] = grdwindinversion.__version__
469
+ xr_dataset.attrs["gmf"] = config['GMF_'+copol_gmf+'_NAME'] + \
470
+ ", " + config["GMF_"+crosspol_gmf+"_NAME"]
471
+ xr_dataset.attrs["iceSource"] = "/"
472
+ xr_dataset.attrs["owiNoiseCorrection"] = "False"
473
+ xr_dataset.attrs["inversionTabGMF"] = config['GMF_'+copol_gmf +
474
+ '_NAME'] + ", " + config["GMF_"+crosspol_gmf+"_NAME"]
475
+ xr_dataset.attrs["wnf_3km_average"] = "/"
476
+ xr_dataset.attrs["owiWindSpeedSrc"] = "owiWindSpeed"
477
+ xr_dataset.attrs["owiWindDirectionSrc"] = "/"
478
+
387
479
  table_fillValue = {
388
480
  "owiWindQuality": -1,
389
481
  "owiHeading": 9999.99,
@@ -396,43 +488,51 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf,
396
488
  "owiWindSpeed_co": -9999.0,
397
489
  "owiWindSpeed_cross": -9999.0,
398
490
  }
399
-
491
+
400
492
  encoding = {}
401
493
  for var in list(set(xr_dataset.coords.keys()) | set(xr_dataset.keys())):
402
494
  encoding[var] = {}
403
495
  try:
404
- # sarwing_ds[var].attrs["_FillValue"] = table_fillValue[var]
405
496
  encoding[var].update({'_FillValue': table_fillValue[var]})
406
497
  except:
407
- # Nouvelles variables..
408
498
  if (var in ["owiWindSpeed_co", "owiWindSpeed_cross", "owiWindSpeed"]):
409
- # sarwing_ds[var].attrs["_FillValue"] = -9999.0
410
499
  encoding[var].update({'_FillValue': -9999.0})
411
500
  else:
412
501
  encoding[var].update({'_FillValue': None})
413
502
 
414
503
  xr_dataset.attrs["xsar_version"] = xsar.__version__
415
504
  xr_dataset.attrs["xsarsea_version"] = xsarsea.__version__
416
-
505
+
417
506
  return xr_dataset, encoding
418
507
 
419
508
 
420
509
  def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True, resolution='1000m'):
421
510
  """
422
-
423
- :param filename: str
424
- :param out_folder: str
425
- :param config_path: str
426
- :param overwrite: bool True -> existing files will be overwritten
427
- :return:
428
- out_file: str
429
- xr_dataset: xarray.Dataset final dataset with wind speed variables
511
+ Main function to generate L2 product.
512
+
513
+ Parameters
514
+ ----------
515
+ filename : str
516
+ input filename
517
+ out_folder : str
518
+ output folder
519
+ config_path : str
520
+ configuration file path
521
+ overwrite : bool, optional
522
+ overwrite existing file
523
+ generateCSV : bool, optional
524
+ generate CSV file
525
+ resolution : str, optional
526
+ working resolution
527
+
528
+ Returns
529
+ -------
530
+ str
531
+ output filename
532
+ xarray.Dataset
533
+ final dataset
430
534
  """
431
535
 
432
- # final xr.Dataset
433
-
434
- #  Step 1 - load L1 product
435
-
436
536
  sensor, sensor_longname, fct_meta, fct_dataset = getSensorMetaDataset(
437
537
  filename)
438
538
 
@@ -448,58 +548,65 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
448
548
  else:
449
549
  raise FileNotFoundError(
450
550
  'config_path do not exists, got %s ' % config_path)
451
-
551
+
452
552
  recalibration = config["recalibration"]
453
- if recalibration:
454
- aux_config_name=config["aux_config_name"]
455
-
456
553
  meta = fct_meta(filename)
457
554
  out_file = getOutputName2(filename, out_folder, sensor, meta)
458
555
 
459
-
460
556
  if os.path.exists(out_file) and overwrite is False:
461
- logging.info("out_file %s exists" % out_file)
557
+ logging.info("out_file %s exists ; returning empty Dataset" % out_file)
462
558
  return out_file, xr.Dataset()
463
559
 
464
- # get ancillary wind from ECMWF
465
- map_model = getAncillary(meta)
560
+ map_model = getAncillary(meta, ancillary_name=config["ancillary"])
466
561
  if map_model is None:
467
562
  raise Exception(
468
563
  'the weather model is not set `map_model` is None -> you probably don"t have access to ECMWF archive')
469
564
 
470
565
  try:
471
566
  if ((recalibration) & ("SENTINEL" in sensor_longname)):
472
- logging.info('recalibration is True : Kersten formula is applied')
567
+ logging.info(
568
+ f'recalibration is {recalibration} : Kersten formula is applied')
473
569
  xsar_dataset = fct_dataset(
474
- meta, resolution=resolution, recalibration=recalibration, aux_config_name = aux_config_name)
570
+ meta, resolution=resolution, recalibration=recalibration)
475
571
  xr_dataset = xsar_dataset.datatree['measurement'].to_dataset()
476
- xr_dataset = xr_dataset.merge(xsar_dataset.datatree["recalibration"].to_dataset()[['swath_number','swath_number_flag','sigma0_raw__corrected']])
477
-
572
+ xr_dataset = xr_dataset.merge(xsar_dataset.datatree["recalibration"].to_dataset()[
573
+ ['swath_number', 'swath_number_flag', 'sigma0_raw__corrected']])
574
+
478
575
  else:
479
576
  logging.info(
480
- 'recalibration is True : Kersten formula is not applied')
577
+ f'recalibration is {recalibration} : Kersten formula is not applied')
481
578
  if ("SENTINEL" in sensor_longname):
482
- xsar_dataset = fct_dataset(meta, resolution=resolution,recalibration=recalibration)
579
+ xsar_dataset = fct_dataset(
580
+ meta, resolution=resolution, recalibration=recalibration)
483
581
  xr_dataset = xsar_dataset.datatree['measurement'].to_dataset()
484
- xr_dataset = xr_dataset.merge(xsar_dataset.datatree["recalibration"].to_dataset()[['swath_number','swath_number_flag']])
582
+ xr_dataset = xr_dataset.merge(xsar_dataset.datatree["recalibration"].to_dataset()[
583
+ ['swath_number', 'swath_number_flag']])
485
584
 
486
- else:
585
+ else:
487
586
  xsar_dataset = fct_dataset(meta, resolution=resolution)
488
587
  xr_dataset = xsar_dataset.datatree['measurement'].to_dataset()
489
588
 
490
-
491
589
  xr_dataset = xr_dataset.rename(map_model)
492
590
  # add attributes
493
591
  xr_dataset.attrs = xsar_dataset.dataset.attrs
494
592
  xr_dataset.attrs['L1_path'] = xr_dataset.attrs.pop('name')
495
593
  xr_dataset.attrs["sourceProduct"] = sensor
496
594
  xr_dataset.attrs["missionName"] = sensor_longname
497
-
595
+ if ((recalibration) & ("SENTINEL" in sensor_longname)):
596
+ xr_dataset.attrs["path_aux_pp1_new"] = os.path.basename(os.path.dirname(
597
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_pp1_new'])))
598
+ xr_dataset.attrs["path_aux_cal_new"] = os.path.basename(os.path.dirname(
599
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_cal_new'])))
600
+
601
+ xr_dataset.attrs["path_aux_pp1_old"] = os.path.basename(os.path.dirname(
602
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_pp1_old'])))
603
+ xr_dataset.attrs["path_aux_cal_old"] = os.path.basename(os.path.dirname(
604
+ os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_cal_old'])))
605
+
498
606
  except Exception as e:
499
607
  logging.info('%s', traceback.format_exc())
500
608
  logging.error(e)
501
609
  sys.exit(-1)
502
-
503
610
 
504
611
  # defining dual_pol, and gmfs by channel
505
612
  if len(xr_dataset.pol.values) == 2:
@@ -553,11 +660,33 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
553
660
  xr_dataset.mask.attrs['flag_meanings'] = 'valid land ice no_valid'
554
661
 
555
662
  # ANCILLARY
556
- xr_dataset['ancillary_wind'] = (xr_dataset.model_U10 + 1j * xr_dataset.model_V10) * np.exp(
557
- 1j * np.deg2rad(xr_dataset.ground_heading))
663
+ xr_dataset['ancillary_wind_direction'] = (
664
+ 90. - np.rad2deg(np.arctan2(xr_dataset.model_V10, xr_dataset.model_U10)) + 180) % 360
665
+
666
+ xr_dataset['ancillary_wind_direction'] = xr.where(xr_dataset['mask'], np.nan,
667
+ xr_dataset['ancillary_wind_direction'].compute()).transpose(
668
+ *xr_dataset['ancillary_wind_direction'].dims)
669
+ xr_dataset['ancillary_wind_direction'].attrs = {}
670
+ xr_dataset['ancillary_wind_direction'].attrs['units'] = 'degrees_north'
671
+ xr_dataset['ancillary_wind_direction'].attrs[
672
+ 'long_name'] = 'ECMWF Wind direction (meteorological convention)'
673
+ xr_dataset['ancillary_wind_direction'].attrs['standart_name'] = 'wind_direction'
674
+
675
+ xr_dataset['ancillary_wind_speed'] = np.sqrt(
676
+ xr_dataset['model_U10']**2+xr_dataset['model_V10']**2)
677
+ xr_dataset['ancillary_wind_speed'] = xr.where(xr_dataset['mask'], np.nan,
678
+ xr_dataset['ancillary_wind_speed'].compute()).transpose(
679
+ *xr_dataset['ancillary_wind_speed'].dims)
680
+ xr_dataset['ancillary_wind_speed'].attrs = {}
681
+ xr_dataset['ancillary_wind_speed'].attrs['units'] = 'm s^-1'
682
+ xr_dataset['ancillary_wind_speed'].attrs[
683
+ 'long_name'] = 'ECMWF Wind speed'
684
+ xr_dataset['ancillary_wind_speed'].attrs['standart_name'] = 'wind_speed'
685
+
558
686
  xr_dataset['ancillary_wind'] = xr.where(xr_dataset['mask'], np.nan,
559
- xr_dataset['ancillary_wind'].compute()).transpose(
560
- *xr_dataset['ancillary_wind'].dims)
687
+ (xr_dataset.ancillary_wind_speed * np.exp(1j * xsarsea.dir_geo_to_sample(xr_dataset.ancillary_wind_direction, xr_dataset.ground_heading))).compute()).transpose(
688
+ *xr_dataset['ancillary_wind_speed'].dims)
689
+
561
690
  xr_dataset.attrs['ancillary_source'] = xr_dataset['model_U10'].attrs['history'].split('decoded: ')[
562
691
  1].strip()
563
692
  xr_dataset = xr_dataset.drop_vars(['model_U10', 'model_V10'])
@@ -567,7 +696,7 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
567
696
  xr_dataset['sigma0'].compute()).transpose(*xr_dataset['sigma0'].dims)
568
697
  xr_dataset['sigma0_ocean'] = xr.where(
569
698
  xr_dataset['sigma0_ocean'] <= 0, np.nan, xr_dataset['sigma0_ocean'])
570
-
699
+
571
700
  xr_dataset['sigma0_ocean'].attrs = xr_dataset['sigma0'].attrs
572
701
 
573
702
  xr_dataset['sigma0_ocean_raw'] = xr.where(xr_dataset['mask'], np.nan,
@@ -600,26 +729,37 @@ def makeL2(filename, out_folder, config_path, overwrite=False, generateCSV=True,
600
729
  sigma0_ocean_cross = None
601
730
  dsig_cross = 0.1 # default value set in xsarsea
602
731
 
603
- windspeed_co, windspeed_dual, windspeed_cr = inverse(dual_pol,
604
- inc=xr_dataset.incidence,
605
- sigma0=xr_dataset['sigma0_ocean'].sel(
606
- pol=copol),
607
- sigma0_dual=sigma0_ocean_cross,
608
- ancillary_wind=xr_dataset['ancillary_wind'],
609
- dsig_cr=dsig_cross,
610
- model_vv=config["GMF_" +
611
- copol_gmf+"_NAME"],
612
- model_vh=config["GMF_"+crosspol_gmf+"_NAME"])
613
-
614
- xr_dataset['windspeed_co'] = windspeed_co
615
- xr_dataset['windspeed_dual'] = windspeed_dual
732
+ wind_co, wind_dual, windspeed_cr = inverse(dual_pol,
733
+ inc=xr_dataset.incidence,
734
+ sigma0=xr_dataset['sigma0_ocean'].sel(
735
+ pol=copol),
736
+ sigma0_dual=sigma0_ocean_cross,
737
+ ancillary_wind=xr_dataset['ancillary_wind'],
738
+ dsig_cr=dsig_cross,
739
+ model_vv=config["GMF_" +
740
+ copol_gmf+"_NAME"],
741
+ model_vh=config["GMF_"+crosspol_gmf+"_NAME"])
742
+
743
+ #  get windspeeds
744
+ xr_dataset['windspeed_co'] = np.abs(wind_co)
745
+ xr_dataset['windspeed_dual'] = np.abs(wind_dual)
746
+
616
747
  if dual_pol:
617
748
  xr_dataset = xr_dataset.assign(
618
749
  windspeed_cross=(['line', 'sample'], windspeed_cr))
619
- else :
750
+ else:
620
751
  xr_dataset['windspeed_cross'] = windspeed_cr
621
752
 
622
- xr_dataset, encoding = makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf, config)
753
+ #  get winddirections
754
+ xr_dataset['winddir_co'] = (
755
+ 90 - (np.angle(-np.conj(wind_co), deg=True)) + xr_dataset.ground_heading) % 360
756
+
757
+ xr_dataset['winddir_dual'] = (
758
+ 90 - (np.angle(-np.conj(wind_dual), deg=True)) + xr_dataset.ground_heading) % 360
759
+ xr_dataset['winddir_cross'] = xr_dataset['winddir_dual'].copy()
760
+
761
+ xr_dataset, encoding = makeL2asOwi(
762
+ xr_dataset, dual_pol, copol, crosspol, copol_gmf, crosspol_gmf, config)
623
763
 
624
764
  os.makedirs(os.path.dirname(out_file), exist_ok=True)
625
765
 
@@ -0,0 +1,24 @@
1
+ from yaml import load
2
+ import logging
3
+ import os
4
+ import grdwindinversion
5
+ from yaml import CLoader as Loader
6
+ local_config_potential_path = os.path.expanduser(
7
+ '~/.grdwindinversion/data_config.yaml')
8
+
9
+ if os.path.exists(local_config_potential_path):
10
+ config_path = local_config_potential_path
11
+ else:
12
+ config_path = os.path.join(os.path.dirname(
13
+ grdwindinversion.__file__), 'data_config.yaml')
14
+ logging.info('config path: %s', config_path)
15
+ stream = open(config_path, 'r')
16
+ conf = load(stream, Loader=Loader)
17
+
18
+
19
+ def getConf():
20
+ """
21
+ if local_config_potential_path exists it will superseed config_path
22
+ :return:
23
+ """
24
+ return conf
@@ -13,7 +13,7 @@ def processor_starting_point():
13
13
  description='Perform inversion from S1(L1-GRD) SAFE, L1-RCM, L1-RS2 ; using xsar/xsarsea tools')
14
14
  parser.add_argument('--input_file', help='input file path', required=True)
15
15
  parser.add_argument('--config_file',
16
- help='config file path [if not provided will take config file based on input file]',required=False)
16
+ help='config file path [if not provided will take config file based on input file]',required=True)
17
17
 
18
18
  parser.add_argument('--resolution',required=False, default='1000m', help='set resolution ["full" | "1000m" | "xXxm"]')
19
19
 
@@ -43,21 +43,8 @@ def processor_starting_point():
43
43
  # if '1SSH' in input_file or '1SDH' in input_file or '_HH_HV' in input_file:
44
44
  # raise Exception('this processor only handle acquisitions with VV or VV+VH polarization for now.')
45
45
 
46
- if args.config_file is None:
47
- if 'S1' in input_file:
48
- config_file = os.path.join(os.path.dirname(grdwindinversion.__file__),'config_S1.yaml')
49
- elif 'RCM' in input_file:
50
- config_file = os.path.join(os.path.dirname(grdwindinversion.__file__),'config_RCM.yaml')
51
- elif 'RS2' in input_file:
52
- config_file = os.path.join(os.path.dirname(grdwindinversion.__file__),'config_RS2.yaml')
53
- elif 'hy2b' in input_file:
54
- config_file = os.path.join(os.path.dirname(grdwindinversion.__file__),'config_hy2b.yaml')
55
- else:
56
- raise Exception('config data file cannot be defined using the input filename')
57
- else:
58
- config_file = args.config_file
59
-
60
-
46
+
47
+ config_file = args.config_file
61
48
  out_folder = args.outputdir
62
49
  resolution = args.resolution
63
50
  if resolution == "full":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: grdwindinversion
3
- Version: 0.2.3.post7
3
+ Version: 0.2.3.post8
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,10 +33,6 @@ docs/examples/wind-inversion-from-grd.ipynb
33
33
  grdwindinversion/.gitignore
34
34
  grdwindinversion/.travis.yml
35
35
  grdwindinversion/__init__.py
36
- grdwindinversion/config_RCM.yaml
37
- grdwindinversion/config_RS2.yaml
38
- grdwindinversion/config_S1.yaml
39
- grdwindinversion/config_hy2b.yaml
40
36
  grdwindinversion/config_prod.yaml
41
37
  grdwindinversion/config_prod_recal.yaml
42
38
  grdwindinversion/data_config.yaml
@@ -1,6 +0,0 @@
1
- RCM:
2
- GMF_VV_NAME: "cmod5n"
3
- GMF_VH_NAME: "gmf_rcm_noaa"
4
- dsig_VH_NAME: "gmf_s1_v2"
5
- apply_flattening: True
6
- recalibration: False
@@ -1,6 +0,0 @@
1
- RS2:
2
- GMF_VV_NAME: "cmod5n"
3
- GMF_VH_NAME: "gmf_rs2_v2"
4
- dsig_VH_NAME: "gmf_rs2_v2"
5
- apply_flattening: False
6
- recalibration: False
@@ -1,12 +0,0 @@
1
- S1A:
2
- GMF_VV_NAME: "cmod5n"
3
- GMF_VH_NAME: "gmf_s1_v2"
4
- dsig_VH_NAME: "gmf_s1_v2"
5
- apply_flattening: True
6
- recalibration: False
7
- S1B:
8
- GMF_VV_NAME: "cmod5n"
9
- GMF_VH_NAME: "gmf_s1_v2"
10
- dsig_VH_NAME: "gmf_s1_v2"
11
- apply_flattening: True
12
- recalibration: False
@@ -1,24 +0,0 @@
1
- S1A:
2
- GMF_VV_NAME: "cmod5n"
3
- GMF_VH_NAME: "gmf_hy2B"
4
- dsig_VH_NAME: "gmf_s1_v2"
5
- apply_flattening: True
6
- recalibration: False
7
- S1B:
8
- GMF_VV_NAME: "cmod5n"
9
- GMF_VH_NAME: "gmf_hy2B"
10
- dsig_VH_NAME: "gmf_s1_v2"
11
- apply_flattening: True
12
- recalibration: False
13
- RS2:
14
- GMF_VV_NAME: "cmod5n"
15
- GMF_VH_NAME: "gmf_hy2B"
16
- dsig_VH_NAME: "gmf_s1_v2"
17
- apply_flattening: False
18
- recalibration: False
19
- RCM:
20
- GMF_VV_NAME: "cmod5n"
21
- GMF_VH_NAME: "gmf_hy2B"
22
- dsig_VH_NAME: "gmf_s1_v2"
23
- apply_flattening: True
24
- recalibration: False
@@ -1,22 +0,0 @@
1
- from yaml import load
2
- import logging
3
- import os
4
- import grdwindinversion
5
- from yaml import CLoader as Loader
6
- local_config_potential_path = os.path.join(os.path.dirname(grdwindinversion.__file__), 'local_data_config.yaml')
7
-
8
- if os.path.exists(local_config_potential_path):
9
- config_path = local_config_potential_path
10
- else:
11
- config_path = os.path.join(os.path.dirname(grdwindinversion.__file__), 'data_config.yaml')
12
- # config_path = "./data_config.yaml"
13
- logging.info('config path: %s',config_path)
14
- stream = open(config_path, 'r')
15
- conf = load(stream, Loader=Loader)
16
- def getConf():
17
-
18
- """
19
- if grdwindinversion/local_data_config.yaml exists it will superseed grdwindinversion/data_config.yaml
20
- :return:
21
- """
22
- return conf