grdwindinversion 0.3.9__py3-none-any.whl → 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
grdwindinversion/main.py CHANGED
@@ -20,7 +20,6 @@ def processor_starting_point():
20
20
 
21
21
  from grdwindinversion.inversion import makeL2
22
22
  from grdwindinversion.utils_memory import get_memory_usage
23
- from grdwindinversion.load_config import config_path
24
23
  import grdwindinversion
25
24
 
26
25
  parser = argparse.ArgumentParser(
@@ -68,8 +67,6 @@ def processor_starting_point():
68
67
  )
69
68
  t0 = time.time()
70
69
 
71
- logging.info("config path: %s", config_path)
72
-
73
70
  input_file = args.input_file.rstrip("/")
74
71
  logging.info("input file: %s", input_file)
75
72
 
@@ -84,7 +81,7 @@ def processor_starting_point():
84
81
  if resolution == "full":
85
82
  resolution = None
86
83
 
87
- out_file, outputds = makeL2(
84
+ out_file, outputds, return_status = makeL2(
88
85
  input_file,
89
86
  out_folder,
90
87
  config_file,
@@ -97,6 +94,8 @@ def processor_starting_point():
97
94
  logging.info("current memory usage: %s ", get_memory_usage(var="current"))
98
95
  logging.info("done in %1.3f min", (time.time() - t0) / 60.0)
99
96
 
97
+ sys.exit(return_status)
98
+
100
99
 
101
100
  if __name__ == "__main__":
102
101
  processor_starting_point()
grdwindinversion/utils.py CHANGED
@@ -21,12 +21,12 @@ except ImportError:
21
21
  def convert_polarization_name(pol):
22
22
  """
23
23
  Convert polarization name to the format used in the output filename
24
-
24
+
25
25
  Parameters
26
26
  ----------
27
27
  pol : str
28
28
  polarization name
29
-
29
+
30
30
  Returns
31
31
  -------
32
32
  str
@@ -43,6 +43,7 @@ def convert_polarization_name(pol):
43
43
  else:
44
44
  return "xx"
45
45
 
46
+
46
47
  def check_incidence_range(incidence, models, **kwargs):
47
48
  """
48
49
  Check if the incidence range of the dataset is within the range of the LUT of the model.
@@ -80,8 +81,8 @@ def check_incidence_range(incidence, models, **kwargs):
80
81
  if inc_range[0] >= lut_range[0] and inc_range[1] <= lut_range[1]:
81
82
  rets.append(True)
82
83
  else:
83
- logging.warn(
84
- f"incidence range {inc_range} is not within the range of the LUT of the model {model_name} {lut_range} : inversion will be approximate using LUT minmium|maximum incidences"
84
+ logging.warning(
85
+ f"check_incidence_range warning : incidence range {inc_range} is not within the range of the LUT of the model {model_name} {lut_range} : inversion will be approximate using LUT minmium|maximum incidences"
85
86
  )
86
87
  rets.append(False)
87
88
 
@@ -115,7 +116,7 @@ def get_pol_ratio_name(model_co):
115
116
  vvgmf, res, polrationame = match.groups()
116
117
  return polrationame
117
118
  else:
118
- logging.warn(
119
+ logging.warning(
119
120
  f"String format is not correct for polarization ratio name = {s}\nReturning '/'"
120
121
  )
121
122
  return "/"
@@ -145,10 +146,114 @@ def timing(logger=logger.debug):
145
146
  if mem_monitor:
146
147
  endrss = process.memory_info().rss
147
148
  mem_str = "mem: %+.1fMb" % ((endrss - startrss) / (1024**2))
148
- logger("timing %s : %.2fs. %s" % (f.__name__, endtime - starttime, mem_str))
149
+ logger("timing %s : %.2fs. %s" %
150
+ (f.__name__, endtime - starttime, mem_str))
149
151
  return result
150
152
 
151
153
  wrapper.__doc__ = f.__doc__
152
154
  return wrapper
153
155
 
154
156
  return decorator
157
+
158
+
159
+ def test_config(config):
160
+ """
161
+ Validate configuration structure.
162
+
163
+ Checks that the configuration contains all required fields:
164
+ - ancillary_sources (with ecmwf or era5)
165
+ - nc_luts_path (required)
166
+ - lut_cmod7_path (optional - required only if using gmf_cmod7)
167
+ - lut_ms1ahw_path (optional - required only if using gmf_cmodms1ahw)
168
+ - masks (optional)
169
+
170
+ Note: If you use predefined LUTs (gmf_cmod7, gmf_cmodms1ahw, etc.),
171
+ they must be loaded with the corresponding path keywords:
172
+ - gmf_cmod7 requires lut_cmod7_path
173
+ - gmf_cmodms1ahw requires lut_ms1ahw_path
174
+
175
+ Parameters
176
+ ----------
177
+ config : dict
178
+ Configuration dictionary to validate
179
+
180
+ Raises
181
+ ------
182
+ ValueError
183
+ If configuration is missing required fields or has invalid structure
184
+ """
185
+ # Check ancillary_sources
186
+ if 'ancillary_sources' not in config:
187
+ raise ValueError("Configuration must contain 'ancillary_sources'")
188
+
189
+ if not isinstance(config['ancillary_sources'], dict):
190
+ raise ValueError("'ancillary_sources' must be a dictionary")
191
+
192
+ if not config['ancillary_sources']:
193
+ raise ValueError("'ancillary_sources' must not be empty")
194
+
195
+ # Check that at least ecmwf or era5 is configured
196
+ has_ecmwf = 'ecmwf' in config['ancillary_sources']
197
+ has_era5 = 'era5' in config['ancillary_sources']
198
+ if not (has_ecmwf or has_era5):
199
+ raise ValueError(
200
+ "'ancillary_sources' must contain at least 'ecmwf' or 'era5'")
201
+
202
+ # Validate ancillary sources structure
203
+ for ancillary_type, sources in config['ancillary_sources'].items():
204
+ if not isinstance(sources, list):
205
+ raise ValueError(
206
+ f"'ancillary_sources.{ancillary_type}' must be a list")
207
+ if not sources:
208
+ raise ValueError(
209
+ f"'ancillary_sources.{ancillary_type}' must not be empty")
210
+
211
+ for source in sources:
212
+ if 'name' not in source:
213
+ raise ValueError(
214
+ f"Each source in 'ancillary_sources.{ancillary_type}' must have a 'name' field")
215
+ if 'path' not in source:
216
+ raise ValueError(
217
+ f"Each source in 'ancillary_sources.{ancillary_type}' must have a 'path' field")
218
+ # Check LUT paths
219
+ if 'nc_luts_path' not in config:
220
+ raise ValueError("Configuration must contain 'nc_luts_path'")
221
+ else:
222
+ logger.debug(f"nc_luts_path found: {config['nc_luts_path']}")
223
+
224
+ # Optional LUT paths (only needed if using specific GMFs)
225
+ if 'lut_cmod7_path' in config:
226
+ logger.debug(f"lut_cmod7_path found: {config['lut_cmod7_path']}")
227
+ if 'lut_ms1ahw_path' in config:
228
+ logger.debug(f"lut_ms1ahw_path found: {config['lut_ms1ahw_path']}")
229
+
230
+ # Validate masks structure if present (optional)
231
+ if 'masks' in config:
232
+ if not isinstance(config['masks'], dict):
233
+ raise ValueError("'masks' must be a dictionary")
234
+
235
+ for category, mask_list in config['masks'].items():
236
+ if not isinstance(mask_list, list):
237
+ raise ValueError(f"'masks.{category}' must be a list")
238
+
239
+ for mask in mask_list:
240
+ if 'name' not in mask:
241
+ raise ValueError(
242
+ f"Each mask in 'masks.{category}' must have a 'name' field")
243
+ if 'path' not in mask:
244
+ raise ValueError(
245
+ f"Each mask in 'masks.{category}' must have a 'path' field")
246
+
247
+ logger.debug(f"Masks configured: {list(config['masks'].keys())}")
248
+ else:
249
+ logger.info("No masks configured (optional)")
250
+
251
+ # Check which sensors are configured
252
+ supported_sensors = ['S1A', 'S1B', 'S1C', 'S1D', 'RS2', 'RCM']
253
+ configured_sensors = [sensor for sensor in supported_sensors if sensor in config]
254
+ if configured_sensors:
255
+ logger.info(f"Sensors configured: {', '.join(configured_sensors)}")
256
+ else:
257
+ logger.warning("No sensors configured - at least one sensor (S1A, S1B, S1C, S1D, RS2, RCM) should be present")
258
+
259
+ logger.info("Configuration validation passed")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: grdwindinversion
3
- Version: 0.3.9
3
+ Version: 1.0.1
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
@@ -0,0 +1,20 @@
1
+ grdwindinversion/.gitignore,sha256=vmDRHGeESYckUdUztsPr7u6ZNfBYMCVR3GE3AJCBnsY,1204
2
+ grdwindinversion/__init__.py,sha256=WElmPGXfKJ2BbiiBiFLyJObZHEmglAgKZcso7Pl7NhU,331
3
+ grdwindinversion/config_prod_recal.yaml,sha256=Dg8VBZRIEVF0ASC6XLPbv06kwLgNzF13cUwwkjVLW-A,4533
4
+ grdwindinversion/config_prod_recal_streaks_nrcsmod.yaml,sha256=bMdnQnqLvwXVxymCAT0a19mYAgAVjeZgJP8OUHMDIMg,4531
5
+ grdwindinversion/config_prod_streaks.yaml,sha256=II4r-PIgtzAmjw4s307UQGkrfTwmgpympxC9Pmzhulw,4539
6
+ grdwindinversion/config_prod_streaks_nrcsmod.yaml,sha256=k18T5rXS7LRV3n69AOPrhBYWl1io9z4juJ-Z3cjo8ps,4537
7
+ grdwindinversion/config_prod_v3.yaml,sha256=BNXi8r5cF3GkdD126g7y1tAnSpyZwwWoThh87xIP6bQ,4540
8
+ grdwindinversion/gradientFeatures.py,sha256=NIeAJzb1zrlJPBq1th7wjEZoNJMxwqDpNHLMWP6FQN0,18198
9
+ grdwindinversion/inversion.py,sha256=R2PtzY8b94ouGRFLluwNP6_igGAg4YerqRhD1LGI-F8,73167
10
+ grdwindinversion/main.py,sha256=4i5ecjt_hkSYUavS7CxsqR0OfLaWUoxrxambzMWyPbA,3191
11
+ grdwindinversion/utils.py,sha256=9pQEyi6R3JUD0Deq3dJMOPnetyQZii7y8fgPO6wlIok,8496
12
+ grdwindinversion/utils_memory.py,sha256=NA0bvkpCTkEiqCcJuldG1XsrP40-3AQUUt3HLeoRpbY,1432
13
+ grdwindinversion/.github/ISSUE_TEMPLATE.md,sha256=qiM_a7CCUz3fSrz3Q20Se1nwPNFS8QCc8tkwK_0DSCo,327
14
+ grdwindinversion-1.0.1.dist-info/licenses/AUTHORS.rst,sha256=C9EFY6YdOu5qAe6pNIvCvviXH91vCej-WxOobYftoMk,155
15
+ grdwindinversion-1.0.1.dist-info/licenses/LICENSE,sha256=-B8mBiTeY3J7OLuayiV1myqmc7yeijBc7s34kc8RTmg,1075
16
+ grdwindinversion-1.0.1.dist-info/METADATA,sha256=eTuwlA87-8eB9gF3irr5qiyRiNFHocBfoBrbGEx9fdg,2529
17
+ grdwindinversion-1.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ grdwindinversion-1.0.1.dist-info/entry_points.txt,sha256=2rjvlVCy0iasRXjOz3kOIGuy2OCGQ-VTNuwuViQ6cMM,95
19
+ grdwindinversion-1.0.1.dist-info/top_level.txt,sha256=z6lPix3QPEYOo37qq8plA2hY7S3C8MQZY81agRlksMI,17
20
+ grdwindinversion-1.0.1.dist-info/RECORD,,
@@ -5,10 +5,6 @@ Authors
5
5
  Development Lead
6
6
  ----------------
7
7
 
8
- * Vincent Lheureux <vincent.lheureux@ifremer.fr>
8
+ * Vincent Lheureux <vinc.lheureux@gmail.com>
9
9
  * Antoine Grouazel <antoine.grouazel@ifremer.fr>
10
10
 
11
- Contributors
12
- ------------
13
-
14
- None yet. Why not be the first?
@@ -1,52 +0,0 @@
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
- apply_flattening: True
11
- recalibration: False
12
- ancillary: "ecmwf"
13
- inc_step: 0.1
14
- wspd_step: 0.1
15
- phi_step: 1.0
16
- resolution: "high"
17
- S1B:
18
- GMF_HH_NAME: "nc_lut_gmf_cmod5n_Rhigh_hh_mouche1"
19
- GMF_VV_NAME: "gmf_cmod5n"
20
- GMF_VH_NAME: "gmf_s1_v2"
21
- dsig_VH_NAME: "gmf_s1_v2"
22
- apply_flattening: True
23
- recalibration: False
24
- ancillary: "ecmwf"
25
- inc_step: 0.1
26
- wspd_step: 0.1
27
- phi_step: 1.0
28
- resolution: "high"
29
- RS2:
30
- GMF_HH_NAME: "nc_lut_gmf_cmod5n_Rhigh_hh_mouche1"
31
- GMF_VV_NAME: "gmf_cmod5n"
32
- GMF_VH_NAME: "gmf_rs2_v2"
33
- dsig_VH_NAME: "gmf_rs2_v2"
34
- apply_flattening: False
35
- recalibration: False
36
- ancillary: "ecmwf"
37
- inc_step: 0.1
38
- wspd_step: 0.1
39
- phi_step: 1.0
40
- resolution: "high"
41
- RCM:
42
- GMF_HH_NAME: "nc_lut_gmf_cmod5n_Rhigh_hh_mouche1"
43
- GMF_VV_NAME: "gmf_cmod5n"
44
- GMF_VH_NAME: "gmf_rcm_noaa"
45
- dsig_VH_NAME: "gmf_s1_v2"
46
- apply_flattening: True
47
- recalibration: False
48
- ancillary: "ecmwf"
49
- inc_step: 0.1
50
- wspd_step: 0.1
51
- phi_step: 1.0
52
- resolution: "high"
@@ -1,8 +0,0 @@
1
- 'ecmwf_0100_1h': '../ecmwf/forecast/hourly/0100deg/netcdf_light_REPRO_tree/%Y/%j/ECMWF_FORECAST_0100_%Y%m%d%H%M_10U_10V.nc'
2
- 'ecmwf_0125_1h': '../ecmwf/0.125deg/1h/forecasts/%Y/%j/ecmwf_%Y%m%d%H%M.nc'
3
-
4
-
5
- unit_test_s1_product: './sentinel-1a/L1/IW/S1A_IW_GRDH_1S/2021/252/S1A_IW_GRDH_1SDV_20210909T130650_20210909T130715_039605_04AE83_C34F.SAFE'
6
- unit_test_rcm_product: './l1/rcm/rcm-1/sclnd/2023/273/RCM1_OK2767220_PK2769320_1_SCLND_20230930_214014_VV_VH_GRD'
7
- unit_test_rs2_product: './L1/VV_VH/2022/247/RS2_OK141302_PK1242223_DK1208537_SCWA_20220904_093402_VV_VH_SGF'
8
-
@@ -1,30 +0,0 @@
1
- from yaml import load
2
- import logging
3
- import os
4
- import grdwindinversion
5
- from yaml import CLoader as Loader
6
-
7
- local_config_potential_path1 = os.path.expanduser(
8
- "~/.grdwindinversion/data_config.yaml"
9
- )
10
- local_config_potential_path2 = os.path.join(
11
- os.path.dirname(grdwindinversion.__file__), "local_data_config.yaml"
12
- )
13
- if os.path.exists(local_config_potential_path1):
14
- config_path = local_config_potential_path1
15
- elif os.path.exists(local_config_potential_path2):
16
- config_path = local_config_potential_path2
17
- else:
18
- config_path = os.path.join(
19
- os.path.dirname(grdwindinversion.__file__), "data_config.yaml"
20
- )
21
- stream = open(config_path, "r")
22
- conf = load(stream, Loader=Loader)
23
-
24
-
25
- def getConf():
26
- """
27
- if local_config_potential_path exists it will superseed config_path
28
- :return:
29
- """
30
- return conf
@@ -1,23 +0,0 @@
1
- grdwindinversion/.gitignore,sha256=vmDRHGeESYckUdUztsPr7u6ZNfBYMCVR3GE3AJCBnsY,1204
2
- grdwindinversion/__init__.py,sha256=LEeSGGPADHTtjujV48PD3lRVXxe-dg5_z1zWQTvBJNw,415
3
- grdwindinversion/config_prod.yaml,sha256=VEAgtJt894v3u4AhYOlcCWjb379vPDMfwBb4PKeDmAw,1314
4
- grdwindinversion/config_prod_recal.yaml,sha256=74n2J4tzSx1I5vaat3ydwig1jyfDgxGTGDxxw8ALC-U,1222
5
- grdwindinversion/config_prod_recal_streaks_nrcsmod.yaml,sha256=ob0YmzHrwkI4GLxaR9HzidYtXBrTOAlEYwPYdCK7AqA,1092
6
- grdwindinversion/config_prod_streaks.yaml,sha256=lJMl4qH6XYqO8ich7yW0WDQsQDrjmWThlLyx1xZy1DA,1313
7
- grdwindinversion/config_prod_streaks_nrcsmod.yaml,sha256=4yC4KcsC7rUumYHwhpKxM8_LDMe_Je-RIu4-9e1ayp8,1312
8
- grdwindinversion/config_prod_v3.yaml,sha256=YdIYJcQhX8bM2vhU4pDmT4BI8O0Mn4DVSS_LvB0CbgI,3136
9
- grdwindinversion/data_config.yaml,sha256=FnglUHbAtGwHWg8w86hwZt3-vo-dY8uIjxqyI1jZpv8,567
10
- grdwindinversion/gradientFeatures.py,sha256=NIeAJzb1zrlJPBq1th7wjEZoNJMxwqDpNHLMWP6FQN0,18198
11
- grdwindinversion/inversion.py,sha256=D8HQ4Ch2FvWXs7vkNfcSSl_ox1tf3WoemJZ9vZbR-Ww,62409
12
- grdwindinversion/load_config.py,sha256=ZPozOWt0rf2Pmyc6P2D75cE_9wKUfKfr7RUzlE3WoiY,833
13
- grdwindinversion/main.py,sha256=Cwmxxz-PEt53JvpTL0Jx1WKLJpWvlIXZ9xtnyGKrGHY,3254
14
- grdwindinversion/utils.py,sha256=2BRq_UEbKbP5yCy_0X-nV-SQFmmp4aKrFaRgrs5MqJo,4347
15
- grdwindinversion/utils_memory.py,sha256=NA0bvkpCTkEiqCcJuldG1XsrP40-3AQUUt3HLeoRpbY,1432
16
- grdwindinversion/.github/ISSUE_TEMPLATE.md,sha256=qiM_a7CCUz3fSrz3Q20Se1nwPNFS8QCc8tkwK_0DSCo,327
17
- grdwindinversion-0.3.9.dist-info/licenses/AUTHORS.rst,sha256=KmhW_5LBKGTIGwWEVkoTm1qx_bvdDR3yYL-1cwbDOFQ,218
18
- grdwindinversion-0.3.9.dist-info/licenses/LICENSE,sha256=-B8mBiTeY3J7OLuayiV1myqmc7yeijBc7s34kc8RTmg,1075
19
- grdwindinversion-0.3.9.dist-info/METADATA,sha256=6Om_Kjm7yZYOylA7puJhcumBy9UwmIIq0xoxf_3W5d0,2529
20
- grdwindinversion-0.3.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
- grdwindinversion-0.3.9.dist-info/entry_points.txt,sha256=2rjvlVCy0iasRXjOz3kOIGuy2OCGQ-VTNuwuViQ6cMM,95
22
- grdwindinversion-0.3.9.dist-info/top_level.txt,sha256=z6lPix3QPEYOo37qq8plA2hY7S3C8MQZY81agRlksMI,17
23
- grdwindinversion-0.3.9.dist-info/RECORD,,