grdwindinversion 0.2.6__py3-none-any.whl → 0.3.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/config_prod.yaml +6 -0
- grdwindinversion/config_prod_recal.yaml +7 -3
- grdwindinversion/config_prod_recal_streaks_nrcsmod.yaml +48 -0
- grdwindinversion/config_prod_streaks.yaml +52 -0
- grdwindinversion/config_prod_streaks_nrcsmod.yaml +52 -0
- grdwindinversion/data_config.yaml +7 -4
- grdwindinversion/gradientFeatures.py +448 -0
- grdwindinversion/inversion.py +270 -86
- grdwindinversion/load_config.py +7 -4
- grdwindinversion/utils.py +41 -1
- grdwindinversion-0.3.1.dist-info/METADATA +67 -0
- grdwindinversion-0.3.1.dist-info/RECORD +22 -0
- {grdwindinversion-0.2.6.dist-info → grdwindinversion-0.3.1.dist-info}/WHEEL +1 -1
- grdwindinversion/streaks.py +0 -79
- grdwindinversion-0.2.6.dist-info/METADATA +0 -83
- grdwindinversion-0.2.6.dist-info/RECORD +0 -19
- {grdwindinversion-0.2.6.dist-info → grdwindinversion-0.3.1.dist-info}/AUTHORS.rst +0 -0
- {grdwindinversion-0.2.6.dist-info → grdwindinversion-0.3.1.dist-info}/LICENSE +0 -0
- {grdwindinversion-0.2.6.dist-info → grdwindinversion-0.3.1.dist-info}/entry_points.txt +0 -0
- {grdwindinversion-0.2.6.dist-info → grdwindinversion-0.3.1.dist-info}/top_level.txt +0 -0
grdwindinversion/inversion.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import tempfile
|
|
1
2
|
import traceback
|
|
2
3
|
|
|
3
4
|
import xsar
|
|
@@ -15,14 +16,12 @@ from scipy.ndimage import binary_dilation
|
|
|
15
16
|
import re
|
|
16
17
|
import string
|
|
17
18
|
import os
|
|
18
|
-
from grdwindinversion.
|
|
19
|
-
from grdwindinversion.utils import check_incidence_range, get_pol_ratio_name
|
|
19
|
+
from grdwindinversion.utils import check_incidence_range, get_pol_ratio_name, timing
|
|
20
20
|
from grdwindinversion.load_config import getConf
|
|
21
21
|
# optional debug messages
|
|
22
22
|
import logging
|
|
23
|
-
logging.
|
|
24
|
-
logging.
|
|
25
|
-
logging.INFO) # or .setLevel(logging.INFO)
|
|
23
|
+
logger = logging.getLogger('grdwindinversion.inversion')
|
|
24
|
+
logger.addHandler(logging.NullHandler())
|
|
26
25
|
|
|
27
26
|
|
|
28
27
|
def getSensorMetaDataset(filename):
|
|
@@ -45,10 +44,16 @@ def getSensorMetaDataset(filename):
|
|
|
45
44
|
return "S1B", "SENTINEL-1 B", xsar.Sentinel1Meta, xsar.Sentinel1Dataset
|
|
46
45
|
elif ("RS2" in filename):
|
|
47
46
|
return "RS2", "RADARSAT-2", xsar.RadarSat2Meta, xsar.RadarSat2Dataset
|
|
48
|
-
elif ("
|
|
49
|
-
return "RCM", "RADARSAT Constellation", xsar.RcmMeta, xsar.RcmDataset
|
|
47
|
+
elif ("RCM1" in filename):
|
|
48
|
+
return "RCM", "RADARSAT Constellation 1", xsar.RcmMeta, xsar.RcmDataset
|
|
49
|
+
elif ("RCM2" in filename):
|
|
50
|
+
return "RCM", "RADARSAT Constellation 2", xsar.RcmMeta, xsar.RcmDataset
|
|
51
|
+
elif ("RCM3" in filename):
|
|
52
|
+
return "RCM", "RADARSAT Constellation 3", xsar.RcmMeta, xsar.RcmDataset
|
|
53
|
+
|
|
50
54
|
else:
|
|
51
|
-
raise ValueError(
|
|
55
|
+
raise ValueError(
|
|
56
|
+
"must be S1A|S1B|RS2|RCM1|RCM2|RCM3, got filename %s" % filename)
|
|
52
57
|
|
|
53
58
|
|
|
54
59
|
def getOutputName2(input_file, outdir, sensor, meta, subdir=True):
|
|
@@ -96,12 +101,10 @@ def getOutputName2(input_file, outdir, sensor, meta, subdir=True):
|
|
|
96
101
|
new_format = f"{MISSIONID.lower()}--owi-xx-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
|
|
97
102
|
elif sensor == 'RCM':
|
|
98
103
|
regex = re.compile(
|
|
99
|
-
"([
|
|
100
|
-
template = string.Template(
|
|
101
|
-
"${MISSIONID}_OK${DATA1}_PK${DATA2}_${DATA3}_${BEAM}_${DATE}_${TIME}_${POLARIZATION1}_${POLARIZATION2}_${PRODUCT}")
|
|
104
|
+
r"(RCM[0-9])_OK([0-9]+)_PK([0-9]+)_([0-9]+)_([A-Z]+)_(\d{8})_(\d{6})_([A-Z]{2}(?:_[A-Z]{2})?)_([A-Z]+)$")
|
|
102
105
|
match = regex.match(basename_match)
|
|
103
|
-
MISSIONID, DATA1, DATA2, DATA3,
|
|
104
|
-
new_format = f"{MISSIONID.lower()}-{
|
|
106
|
+
MISSIONID, DATA1, DATA2, DATA3, BEAM, DATE, TIME, POLARIZATION, PRODUCT = match.groups()
|
|
107
|
+
new_format = f"{MISSIONID.lower()}-{BEAM.lower()}-owi-xx-{meta_start_date.lower()}-{meta_stop_date.lower()}-_____-_____.nc"
|
|
105
108
|
else:
|
|
106
109
|
raise ValueError(
|
|
107
110
|
"sensor must be S1A|S1B|RS2|RCM, got sensor %s" % sensor)
|
|
@@ -209,6 +212,7 @@ def getAncillary(meta, ancillary_name='ecmwf'):
|
|
|
209
212
|
ancillary_name)
|
|
210
213
|
|
|
211
214
|
|
|
215
|
+
@timing(logger=logger.debug)
|
|
212
216
|
def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_co, model_cross, **kwargs):
|
|
213
217
|
"""
|
|
214
218
|
Invert sigma0 to retrieve wind using model (lut or gmf).
|
|
@@ -282,7 +286,8 @@ def inverse(dual_pol, inc, sigma0, sigma0_dual, ancillary_wind, dsig_cr, model_c
|
|
|
282
286
|
return wind_co, None, None
|
|
283
287
|
|
|
284
288
|
|
|
285
|
-
|
|
289
|
+
@timing(logger=logger.debug)
|
|
290
|
+
def makeL2asOwi(xr_dataset, config):
|
|
286
291
|
"""
|
|
287
292
|
Rename xr_dataset variables and attributes to match naming convention.
|
|
288
293
|
|
|
@@ -290,12 +295,8 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
290
295
|
----------
|
|
291
296
|
xr_dataset: xarray.Dataset
|
|
292
297
|
dataset to rename
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
copol: str
|
|
296
|
-
copolarization name
|
|
297
|
-
crosspol: str
|
|
298
|
-
crosspolarization name
|
|
298
|
+
config: dict
|
|
299
|
+
configuration dict
|
|
299
300
|
|
|
300
301
|
Returns
|
|
301
302
|
-------
|
|
@@ -320,13 +321,27 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
320
321
|
'winddir_co': 'owiWindDirection_co',
|
|
321
322
|
'ancillary_wind_speed': 'owiAncillaryWindSpeed',
|
|
322
323
|
'ancillary_wind_direction': 'owiAncillaryWindDirection',
|
|
323
|
-
'sigma0_detrend': 'owiNrcs_detrend'
|
|
324
|
+
'sigma0_detrend': 'owiNrcs_detrend',
|
|
324
325
|
})
|
|
325
326
|
|
|
326
327
|
if "offboresight" in xr_dataset:
|
|
327
328
|
xr_dataset = xr_dataset.rename(
|
|
328
329
|
{"offboresight": "owiOffboresightAngle"})
|
|
329
330
|
|
|
331
|
+
if config["add_nrcs_model"]:
|
|
332
|
+
xr_dataset = xr_dataset.rename(
|
|
333
|
+
{"ancillary_nrcs": "owiAncillaryNrcs"})
|
|
334
|
+
xr_dataset.owiAncillaryNrcs.attrs["units"] = "m^2 / m^2"
|
|
335
|
+
xr_dataset.owiAncillaryNrcs.attrs[
|
|
336
|
+
"long_name"] = f"Ancillary Normalized Radar Cross Section - simulated from {config['l2_params']['copol_gmf']} & ancillary wind"
|
|
337
|
+
|
|
338
|
+
if config["l2_params"]["dual_pol"]:
|
|
339
|
+
xr_dataset = xr_dataset.rename(
|
|
340
|
+
{"ancillary_nrcs_cross": "owiAncillaryNrcs_cross"})
|
|
341
|
+
xr_dataset.owiAncillaryNrcs_cross.attrs["units"] = "m^2 / m^2"
|
|
342
|
+
xr_dataset.owiAncillaryNrcs_cross.attrs[
|
|
343
|
+
"long_name"] = f"Ancillary Normalized Radar Cross Section - simulated from {config['l2_params']['crosspol_gmf']} & ancillary wind"
|
|
344
|
+
|
|
330
345
|
xr_dataset.owiLon.attrs["units"] = "degrees_east"
|
|
331
346
|
xr_dataset.owiLon.attrs["long_name"] = "Longitude at wind cell center"
|
|
332
347
|
xr_dataset.owiLon.attrs["standard_name"] = "longitude"
|
|
@@ -343,23 +358,25 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
343
358
|
xr_dataset.owiElevationAngle.attrs["long_name"] = "Elevation angle at wind cell center"
|
|
344
359
|
xr_dataset.owiElevationAngle.attrs["standard_name"] = "elevation"
|
|
345
360
|
|
|
346
|
-
xr_dataset['owiNrcs'] = xr_dataset['sigma0_ocean'].sel(
|
|
361
|
+
xr_dataset['owiNrcs'] = xr_dataset['sigma0_ocean'].sel(
|
|
362
|
+
pol=config["l2_params"]["copol"])
|
|
347
363
|
xr_dataset.owiNrcs.attrs = xr_dataset.sigma0_ocean.attrs
|
|
348
364
|
xr_dataset.owiNrcs.attrs['units'] = 'm^2 / m^2'
|
|
349
365
|
xr_dataset.owiNrcs.attrs['long_name'] = 'Normalized Radar Cross Section'
|
|
350
366
|
xr_dataset.owiNrcs.attrs['definition'] = 'owiNrcs_no_noise_correction - owiNesz'
|
|
351
367
|
|
|
352
|
-
xr_dataset['owiMask_Nrcs'] = xr_dataset['sigma0_mask'].sel(
|
|
368
|
+
xr_dataset['owiMask_Nrcs'] = xr_dataset['sigma0_mask'].sel(
|
|
369
|
+
pol=config["l2_params"]["copol"])
|
|
353
370
|
xr_dataset.owiMask_Nrcs.attrs = xr_dataset.sigma0_mask.attrs
|
|
354
371
|
|
|
355
372
|
# NESZ & DSIG
|
|
356
373
|
xr_dataset = xr_dataset.assign(
|
|
357
|
-
owiNesz=(['line', 'sample'], xr_dataset.nesz.sel(pol=copol).values))
|
|
374
|
+
owiNesz=(['line', 'sample'], xr_dataset.nesz.sel(pol=config["l2_params"]["copol"]).values))
|
|
358
375
|
xr_dataset.owiNesz.attrs['units'] = 'm^2 / m^2'
|
|
359
376
|
xr_dataset.owiNesz.attrs['long_name'] = 'Noise Equivalent SigmaNaught'
|
|
360
377
|
|
|
361
378
|
xr_dataset['owiNrcs_no_noise_correction'] = xr_dataset['sigma0_ocean_raw'].sel(
|
|
362
|
-
pol=copol)
|
|
379
|
+
pol=config["l2_params"]["copol"])
|
|
363
380
|
xr_dataset.owiNrcs_no_noise_correction.attrs = xr_dataset.sigma0_ocean_raw.attrs
|
|
364
381
|
xr_dataset.owiNrcs_no_noise_correction.attrs['units'] = 'm^2 / m^2'
|
|
365
382
|
xr_dataset.owiNrcs_no_noise_correction.attrs[
|
|
@@ -378,7 +395,7 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
378
395
|
# sigma0_raw__corrected cross
|
|
379
396
|
if "sigma0_raw__corrected" in xr_dataset:
|
|
380
397
|
xr_dataset['owiNrcs_no_noise_correction_recalibrated'] = xr_dataset['sigma0_raw__corrected'].sel(
|
|
381
|
-
pol=copol)
|
|
398
|
+
pol=config["l2_params"]["copol"])
|
|
382
399
|
xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs = xr_dataset.sigma0_raw__corrected.attrs
|
|
383
400
|
xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs['units'] = 'm^2 / m^2'
|
|
384
401
|
xr_dataset.owiNrcs_no_noise_correction_recalibrated.attrs[
|
|
@@ -388,7 +405,7 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
388
405
|
|
|
389
406
|
xr_dataset.owiNrcs.attrs['definition'] = 'owiNrcs_no_noise_correction_recalibrated - owiNesz'
|
|
390
407
|
|
|
391
|
-
if dual_pol:
|
|
408
|
+
if config["l2_params"]["dual_pol"]:
|
|
392
409
|
|
|
393
410
|
xr_dataset = xr_dataset.rename({
|
|
394
411
|
'dsig_cross': 'owiDsig_cross',
|
|
@@ -399,31 +416,31 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
399
416
|
'sigma0_detrend_cross': 'owiNrcs_detrend_cross'
|
|
400
417
|
})
|
|
401
418
|
|
|
402
|
-
if apply_flattening:
|
|
419
|
+
if config["apply_flattening"]:
|
|
403
420
|
xr_dataset = xr_dataset.rename({
|
|
404
421
|
'nesz_cross_flattened': 'owiNesz_cross_flattened',
|
|
405
422
|
})
|
|
406
423
|
|
|
407
424
|
# nrcs cross
|
|
408
425
|
xr_dataset['owiNrcs_cross'] = xr_dataset['sigma0_ocean'].sel(
|
|
409
|
-
pol=crosspol)
|
|
426
|
+
pol=config["l2_params"]["crosspol"])
|
|
410
427
|
|
|
411
428
|
xr_dataset.owiNrcs_cross.attrs['units'] = 'm^2 / m^2'
|
|
412
429
|
xr_dataset.owiNrcs_cross.attrs['long_name'] = 'Normalized Radar Cross Section'
|
|
413
430
|
xr_dataset.owiNrcs_cross.attrs['definition'] = 'owiNrcs_cross_no_noise_correction - owiNesz_cross'
|
|
414
431
|
|
|
415
432
|
xr_dataset['owiMask_Nrcs_cross'] = xr_dataset['sigma0_mask'].sel(
|
|
416
|
-
pol=crosspol)
|
|
433
|
+
pol=config["l2_params"]["crosspol"])
|
|
417
434
|
xr_dataset.owiMask_Nrcs_cross.attrs = xr_dataset.sigma0_mask.attrs
|
|
418
435
|
|
|
419
436
|
# nesz cross
|
|
420
437
|
xr_dataset = xr_dataset.assign(owiNesz_cross=(
|
|
421
|
-
['line', 'sample'], xr_dataset.nesz.sel(pol=crosspol).values)) # no flattening
|
|
438
|
+
['line', 'sample'], xr_dataset.nesz.sel(pol=config["l2_params"]["crosspol"]).values)) # no flattening
|
|
422
439
|
xr_dataset.owiNesz_cross.attrs['units'] = 'm^2 / m^2'
|
|
423
440
|
xr_dataset.owiNesz_cross.attrs['long_name'] = 'Noise Equivalent SigmaNaught'
|
|
424
441
|
|
|
425
442
|
xr_dataset['owiNrcs_cross_no_noise_correction'] = xr_dataset['sigma0_ocean_raw'].sel(
|
|
426
|
-
pol=crosspol)
|
|
443
|
+
pol=config["l2_params"]["crosspol"])
|
|
427
444
|
|
|
428
445
|
xr_dataset.owiNrcs_cross_no_noise_correction.attrs['units'] = 'm^2 / m^2'
|
|
429
446
|
xr_dataset.owiNrcs_cross_no_noise_correction.attrs[
|
|
@@ -432,7 +449,7 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
432
449
|
# sigma0_raw__corrected cross
|
|
433
450
|
if "sigma0_raw__corrected" in xr_dataset:
|
|
434
451
|
xr_dataset['owiNrcs_cross_no_noise_correction_recalibrated'] = xr_dataset['sigma0_raw__corrected'].sel(
|
|
435
|
-
pol=crosspol)
|
|
452
|
+
pol=config["l2_params"]["crosspol"])
|
|
436
453
|
xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs = xr_dataset.sigma0_raw__corrected.attrs
|
|
437
454
|
xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs['units'] = 'm^2 / m^2'
|
|
438
455
|
xr_dataset.owiNrcs_cross_no_noise_correction_recalibrated.attrs[
|
|
@@ -442,10 +459,18 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
442
459
|
|
|
443
460
|
xr_dataset.owiNrcs_cross.attrs['definition'] = 'owiNrcs_cross_no_noise_correction_recalibrated - owiNesz_cross'
|
|
444
461
|
|
|
445
|
-
if
|
|
462
|
+
if config["add_gradientsfeatures"]:
|
|
446
463
|
xr_dataset = xr_dataset.rename({
|
|
447
|
-
'
|
|
464
|
+
'heterogeneity_mask': 'owiWindFilter'
|
|
448
465
|
})
|
|
466
|
+
else:
|
|
467
|
+
xr_dataset['owiWindFilter'] = xr.full_like(xr_dataset.owiNrcs, 0)
|
|
468
|
+
xr_dataset['owiWindFilter'].attrs['long_name'] = "Quality flag taking into account the local heterogeneity"
|
|
469
|
+
xr_dataset['owiWindFilter'].attrs['valid_range'] = np.array([0, 3])
|
|
470
|
+
xr_dataset['owiWindFilter'].attrs['flag_values'] = np.array([
|
|
471
|
+
0, 1, 2, 3])
|
|
472
|
+
xr_dataset['owiWindFilter'].attrs[
|
|
473
|
+
'flag_meanings'] = "homogeneous_NRCS, heterogeneous_from_co-polarization_NRCS, heterogeneous_from_cross-polarization_NRCS, heterogeneous_from_dual-polarization_NRCS"
|
|
449
474
|
|
|
450
475
|
# other variables
|
|
451
476
|
|
|
@@ -458,15 +483,6 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
458
483
|
xr_dataset['owiWindQuality'].attrs['flag_meanings'] = "good medium low poor"
|
|
459
484
|
xr_dataset['owiWindQuality'].attrs['comment'] = 'NOT COMPUTED YET'
|
|
460
485
|
|
|
461
|
-
xr_dataset['owiWindFilter'] = xr.full_like(xr_dataset.owiNrcs, 0)
|
|
462
|
-
xr_dataset['owiWindFilter'].attrs['long_name'] = "Quality flag taking into account the local heterogeneity"
|
|
463
|
-
xr_dataset['owiWindFilter'].attrs['valid_range'] = np.array([0, 3])
|
|
464
|
-
xr_dataset['owiWindFilter'].attrs['flag_values'] = np.array([
|
|
465
|
-
0, 1, 2, 3])
|
|
466
|
-
xr_dataset['owiWindFilter'].attrs[
|
|
467
|
-
'flag_meanings'] = "homogeneous_NRCS, heterogeneous_from_co-polarization_NRCS, heterogeneous_from_cross-polarization_NRCS, heterogeneous_from_dual-polarization_NRCS"
|
|
468
|
-
xr_dataset['owiWindFilter'].attrs['comment'] = 'NOT COMPUTED YET'
|
|
469
|
-
|
|
470
486
|
xr_dataset = xr_dataset.rename(
|
|
471
487
|
{"line": "owiAzSize", "sample": "owiRaSize"})
|
|
472
488
|
|
|
@@ -476,8 +492,6 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
476
492
|
xr_dataset = xr_dataset.drop_vars(["sigma0_raw__corrected"])
|
|
477
493
|
xr_dataset = xr_dataset.drop_dims(['pol'])
|
|
478
494
|
|
|
479
|
-
xr_dataset.compute()
|
|
480
|
-
|
|
481
495
|
table_fillValue = {
|
|
482
496
|
"owiWindQuality": -1,
|
|
483
497
|
"owiHeading": 9999.99,
|
|
@@ -505,7 +519,7 @@ def makeL2asOwi(xr_dataset, dual_pol, copol, crosspol, add_streaks, apply_flatte
|
|
|
505
519
|
return xr_dataset, encoding
|
|
506
520
|
|
|
507
521
|
|
|
508
|
-
def preprocess(filename, outdir, config_path, overwrite=False,
|
|
522
|
+
def preprocess(filename, outdir, config_path, overwrite=False, add_gradientsfeatures=False, resolution='1000m'):
|
|
509
523
|
"""
|
|
510
524
|
Main function to generate L2 product.
|
|
511
525
|
|
|
@@ -549,6 +563,10 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
549
563
|
recalibration = config["recalibration"]
|
|
550
564
|
meta = fct_meta(filename)
|
|
551
565
|
|
|
566
|
+
# si une des deux n'est pas VV VH HH HV on ne fait rien
|
|
567
|
+
if not all([pol in ["VV", "VH", "HH", "HV"] for pol in meta.pols.split(' ')]):
|
|
568
|
+
raise ValueError(f"Polarisation non gérée : meta.pols = {meta.pols}")
|
|
569
|
+
|
|
552
570
|
no_subdir_cfg = config_base.get("no_subdir", False)
|
|
553
571
|
config["no_subdir"] = no_subdir_cfg
|
|
554
572
|
|
|
@@ -560,6 +578,26 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
560
578
|
f'Using meteorological convention because "winddir_convention" was not found in config.')
|
|
561
579
|
config["winddir_convention"] = winddir_convention
|
|
562
580
|
|
|
581
|
+
if "add_gradientsfeatures" in config_base:
|
|
582
|
+
add_gradientsfeatures = config_base["add_gradientsfeatures"]
|
|
583
|
+
else:
|
|
584
|
+
add_gradientsfeatures = False
|
|
585
|
+
logging.warning(
|
|
586
|
+
f'Not computing gradients by default')
|
|
587
|
+
config["add_gradientsfeatures"] = add_gradientsfeatures
|
|
588
|
+
|
|
589
|
+
if "add_nrcs_model" in config_base:
|
|
590
|
+
add_nrcs_model = config_base["add_nrcs_model"]
|
|
591
|
+
add_nrcs_model = False
|
|
592
|
+
logging.warning(
|
|
593
|
+
f'Force this variable to be false, before fixing the issue'
|
|
594
|
+
)
|
|
595
|
+
else:
|
|
596
|
+
add_nrcs_model = False
|
|
597
|
+
logging.warning(
|
|
598
|
+
f'Not computing nrcs from model by default')
|
|
599
|
+
config["add_nrcs_model"] = add_nrcs_model
|
|
600
|
+
|
|
563
601
|
# creating a dictionnary of parameters
|
|
564
602
|
config["l2_params"] = {}
|
|
565
603
|
|
|
@@ -607,6 +645,14 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
607
645
|
logging.error(e)
|
|
608
646
|
sys.exit(-1)
|
|
609
647
|
|
|
648
|
+
# add parameters in config
|
|
649
|
+
config["meta"] = meta
|
|
650
|
+
config["fct_dataset"] = fct_dataset
|
|
651
|
+
config["map_model"] = map_model
|
|
652
|
+
|
|
653
|
+
# load
|
|
654
|
+
xr_dataset = xr_dataset.load()
|
|
655
|
+
|
|
610
656
|
# defining dual_pol, and gmfs by channel
|
|
611
657
|
if len(xr_dataset.pol.values) == 2:
|
|
612
658
|
dual_pol = True
|
|
@@ -639,6 +685,7 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
639
685
|
config["l2_params"]["model_co"] = model_co
|
|
640
686
|
config["l2_params"]["model_cross"] = model_cross
|
|
641
687
|
config["sensor_longname"] = sensor_longname
|
|
688
|
+
config["sensor"] = sensor
|
|
642
689
|
|
|
643
690
|
# need to load LUTs before inversion
|
|
644
691
|
nc_luts = [x for x in [model_co, model_cross] if x.startswith("nc_lut")]
|
|
@@ -707,7 +754,7 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
707
754
|
90. - np.rad2deg(np.arctan2(xr_dataset.model_V10, xr_dataset.model_U10)) + 180) % 360
|
|
708
755
|
|
|
709
756
|
xr_dataset['ancillary_wind_direction'] = xr.where(xr_dataset['mask'], np.nan,
|
|
710
|
-
xr_dataset['ancillary_wind_direction']
|
|
757
|
+
xr_dataset['ancillary_wind_direction']).transpose(
|
|
711
758
|
*xr_dataset['ancillary_wind_direction'].dims)
|
|
712
759
|
xr_dataset['ancillary_wind_direction'].attrs = {}
|
|
713
760
|
xr_dataset['ancillary_wind_direction'].attrs['units'] = 'degrees_north'
|
|
@@ -718,7 +765,7 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
718
765
|
xr_dataset['ancillary_wind_speed'] = np.sqrt(
|
|
719
766
|
xr_dataset['model_U10']**2+xr_dataset['model_V10']**2)
|
|
720
767
|
xr_dataset['ancillary_wind_speed'] = xr.where(xr_dataset['mask'], np.nan,
|
|
721
|
-
xr_dataset['ancillary_wind_speed']
|
|
768
|
+
xr_dataset['ancillary_wind_speed']).transpose(
|
|
722
769
|
*xr_dataset['ancillary_wind_speed'].dims)
|
|
723
770
|
xr_dataset['ancillary_wind_speed'].attrs = {}
|
|
724
771
|
xr_dataset['ancillary_wind_speed'].attrs['units'] = 'm s^-1'
|
|
@@ -727,7 +774,7 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
727
774
|
xr_dataset['ancillary_wind_speed'].attrs['standart_name'] = 'wind_speed'
|
|
728
775
|
|
|
729
776
|
xr_dataset['ancillary_wind'] = xr.where(xr_dataset['mask'], np.nan,
|
|
730
|
-
(xr_dataset.ancillary_wind_speed * np.exp(1j * xsarsea.dir_meteo_to_sample(xr_dataset.ancillary_wind_direction, xr_dataset.ground_heading)))
|
|
777
|
+
(xr_dataset.ancillary_wind_speed * np.exp(1j * xsarsea.dir_meteo_to_sample(xr_dataset.ancillary_wind_direction, xr_dataset.ground_heading)))).transpose(
|
|
731
778
|
*xr_dataset['ancillary_wind_speed'].dims)
|
|
732
779
|
|
|
733
780
|
xr_dataset.attrs['ancillary_source'] = xr_dataset['model_U10'].attrs['history'].split('decoded: ')[
|
|
@@ -736,7 +783,7 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
736
783
|
|
|
737
784
|
# nrcs processing
|
|
738
785
|
xr_dataset['sigma0_ocean'] = xr.where(xr_dataset['mask'], np.nan,
|
|
739
|
-
xr_dataset['sigma0']
|
|
786
|
+
xr_dataset['sigma0']).transpose(*xr_dataset['sigma0'].dims)
|
|
740
787
|
xr_dataset['sigma0_ocean'].attrs = xr_dataset['sigma0'].attrs
|
|
741
788
|
# we forced it to 1e-15
|
|
742
789
|
xr_dataset['sigma0_ocean'].attrs['comment'] = "clipped, no values <=0 ; 1e-15 instread"
|
|
@@ -751,7 +798,7 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
751
798
|
xr_dataset['sigma0_ocean'] <= 0, 1e-15, xr_dataset['sigma0_ocean'])
|
|
752
799
|
|
|
753
800
|
xr_dataset['sigma0_ocean_raw'] = xr.where(xr_dataset['mask'], np.nan,
|
|
754
|
-
xr_dataset['sigma0_raw']
|
|
801
|
+
xr_dataset['sigma0_raw']).transpose(*xr_dataset['sigma0_raw'].dims)
|
|
755
802
|
|
|
756
803
|
xr_dataset['sigma0_ocean_raw'].attrs = xr_dataset['sigma0_raw'].attrs
|
|
757
804
|
|
|
@@ -765,7 +812,7 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
765
812
|
xr_dataset.sigma0.sel(pol=crosspol), xr_dataset.incidence, model=model_cross)
|
|
766
813
|
if config["apply_flattening"]:
|
|
767
814
|
xr_dataset = xr_dataset.assign(nesz_cross_flattened=(
|
|
768
|
-
['line', 'sample'], windspeed.nesz_flattening(xr_dataset.nesz.sel(pol=crosspol), xr_dataset.incidence)))
|
|
815
|
+
['line', 'sample'], windspeed.nesz_flattening(xr_dataset.nesz.sel(pol=crosspol), xr_dataset.incidence).data))
|
|
769
816
|
xr_dataset['nesz_cross_flattened'].attrs[
|
|
770
817
|
"comment"] = 'nesz has been flattened using windspeed.nesz_flattening'
|
|
771
818
|
# dsig
|
|
@@ -774,7 +821,7 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
774
821
|
else:
|
|
775
822
|
# dsig
|
|
776
823
|
xr_dataset["dsig_cross"] = windspeed.get_dsig(config["dsig_"+crosspol_gmf+"_NAME"], xr_dataset.incidence,
|
|
777
|
-
xr_dataset['sigma0_ocean'].sel(pol=crosspol), xr_dataset
|
|
824
|
+
xr_dataset['sigma0_ocean'].sel(pol=crosspol), xr_dataset.nesz.sel(pol=crosspol))
|
|
778
825
|
|
|
779
826
|
xr_dataset.dsig_cross.attrs['comment'] = 'variable used to ponderate copol and crosspol'
|
|
780
827
|
xr_dataset.dsig_cross.attrs['formula_used'] = config["dsig_" +
|
|
@@ -793,41 +840,155 @@ def preprocess(filename, outdir, config_path, overwrite=False, add_streaks=False
|
|
|
793
840
|
xr_dataset.attrs["path_aux_cal_old"] = os.path.basename(os.path.dirname(
|
|
794
841
|
os.path.dirname(xsar_dataset.datatree['recalibration'].attrs['path_aux_cal_old'])))
|
|
795
842
|
|
|
796
|
-
if
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
# adding sigma0 detrend
|
|
803
|
-
xr_dataset_100['sigma0_detrend'] = xsarsea.sigma0_detrend(
|
|
804
|
-
xr_dataset_100.sigma0.sel(pol=copol), xr_dataset_100.incidence, model=model_co)
|
|
843
|
+
if add_nrcs_model:
|
|
844
|
+
# add timing
|
|
845
|
+
phi = np.abs(
|
|
846
|
+
np.rad2deg(xsarsea.dir_meteo_to_sample(
|
|
847
|
+
xr_dataset["ancillary_wind_direction"], xr_dataset["ground_heading"]))
|
|
848
|
+
)
|
|
805
849
|
|
|
850
|
+
varnames = ["ancillary_nrcs"]
|
|
851
|
+
gmf_names = [model_co]
|
|
806
852
|
if dual_pol:
|
|
807
|
-
|
|
808
|
-
|
|
853
|
+
varnames.append("ancillary_nrcs_cross")
|
|
854
|
+
gmf_names.append(model_cross)
|
|
809
855
|
|
|
810
|
-
|
|
811
|
-
[xr_dataset_100['sigma0_detrend'],
|
|
812
|
-
xr_dataset_100['sigma0_detrend_cross']],
|
|
813
|
-
dim='pol'
|
|
814
|
-
)
|
|
815
|
-
sigma0_detrend_combined['pol'] = [copol, crosspol]
|
|
816
|
-
|
|
817
|
-
xr_dataset_100['sigma0_detrend'] = sigma0_detrend_combined
|
|
856
|
+
for idx, gmf_name in enumerate(gmf_names):
|
|
818
857
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
858
|
+
@timing(logger=logger.info)
|
|
859
|
+
def apply_lut_to_dataset():
|
|
860
|
+
lut = xsarsea.windspeed.get_model(
|
|
861
|
+
gmf_name).to_lut(unit="linear")
|
|
823
862
|
|
|
824
|
-
|
|
825
|
-
|
|
863
|
+
def lut_selection(incidence, wspd, phi):
|
|
864
|
+
if "phi" in lut.coords:
|
|
865
|
+
return lut.sel(
|
|
866
|
+
incidence=incidence, wspd=wspd, phi=phi, method="nearest"
|
|
867
|
+
)
|
|
868
|
+
else:
|
|
869
|
+
return lut.sel(
|
|
870
|
+
incidence=incidence, wspd=wspd, method="nearest"
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
xr_dataset[varnames[idx]] = xr.apply_ufunc(
|
|
874
|
+
lut_selection,
|
|
875
|
+
xr_dataset.incidence,
|
|
876
|
+
xr_dataset.ancillary_wind_speed,
|
|
877
|
+
phi,
|
|
878
|
+
vectorize=True,
|
|
879
|
+
dask="parallelized",
|
|
880
|
+
output_dtypes=[float],
|
|
881
|
+
)
|
|
882
|
+
|
|
883
|
+
apply_lut_to_dataset()
|
|
826
884
|
|
|
827
885
|
return xr_dataset, out_file, config
|
|
828
886
|
|
|
829
887
|
|
|
830
|
-
def
|
|
888
|
+
def process_gradients(xr_dataset, config):
|
|
889
|
+
"""
|
|
890
|
+
Function to process gradients features.
|
|
891
|
+
|
|
892
|
+
Parameters
|
|
893
|
+
----------
|
|
894
|
+
xr_dataset : xarray.Dataset
|
|
895
|
+
Main dataset to process.
|
|
896
|
+
meta : object
|
|
897
|
+
Metadata from the original dataset.
|
|
898
|
+
fct_dataset : callable
|
|
899
|
+
Function to load the dataset.
|
|
900
|
+
map_model : dict
|
|
901
|
+
Mapping model for renaming variables.
|
|
902
|
+
config : dict
|
|
903
|
+
Configuration dictionary.
|
|
904
|
+
|
|
905
|
+
Returns
|
|
906
|
+
-------
|
|
907
|
+
tuple
|
|
908
|
+
Updated xr_dataset and xr_dataset_streaks dataset.
|
|
909
|
+
"""
|
|
910
|
+
from grdwindinversion.gradientFeatures import GradientFeatures
|
|
911
|
+
|
|
912
|
+
meta = config["meta"]
|
|
913
|
+
fct_dataset = config["fct_dataset"]
|
|
914
|
+
map_model = config["map_model"]
|
|
915
|
+
|
|
916
|
+
model_co = config["l2_params"]["model_co"]
|
|
917
|
+
model_cross = config["l2_params"]["model_cross"]
|
|
918
|
+
copol = config["l2_params"]["copol"]
|
|
919
|
+
crosspol = config["l2_params"]["crosspol"]
|
|
920
|
+
dual_pol = config["l2_params"]["dual_pol"]
|
|
921
|
+
|
|
922
|
+
# Load the 100m dataset
|
|
923
|
+
xsar_dataset_100 = fct_dataset(
|
|
924
|
+
meta, resolution='100m')
|
|
925
|
+
|
|
926
|
+
xr_dataset_100 = xsar_dataset_100.datatree['measurement'].to_dataset()
|
|
927
|
+
xr_dataset_100 = xr_dataset_100.rename(map_model)
|
|
928
|
+
# load dataset
|
|
929
|
+
xr_dataset_100 = xr_dataset_100.load()
|
|
930
|
+
|
|
931
|
+
# adding sigma0 detrend
|
|
932
|
+
xr_dataset_100['sigma0_detrend'] = xsarsea.sigma0_detrend(
|
|
933
|
+
xr_dataset_100.sigma0.sel(pol=copol), xr_dataset_100.incidence, model=model_co)
|
|
934
|
+
|
|
935
|
+
if dual_pol:
|
|
936
|
+
xr_dataset_100['sigma0_detrend_cross'] = xsarsea.sigma0_detrend(
|
|
937
|
+
xr_dataset_100.sigma0.sel(pol=crosspol), xr_dataset_100.incidence, model=model_cross)
|
|
938
|
+
|
|
939
|
+
sigma0_detrend_combined = xr.concat(
|
|
940
|
+
[xr_dataset_100['sigma0_detrend'],
|
|
941
|
+
xr_dataset_100['sigma0_detrend_cross']],
|
|
942
|
+
dim='pol'
|
|
943
|
+
)
|
|
944
|
+
sigma0_detrend_combined['pol'] = [copol, crosspol]
|
|
945
|
+
|
|
946
|
+
xr_dataset_100['sigma0_detrend'] = sigma0_detrend_combined
|
|
947
|
+
|
|
948
|
+
xr_dataset_100.land_mask.values = binary_dilation(xr_dataset_100['land_mask'].values.astype('uint8'),
|
|
949
|
+
structure=np.ones((3, 3), np.uint8), iterations=3)
|
|
950
|
+
xr_dataset_100['sigma0_detrend'] = xr.where(
|
|
951
|
+
xr_dataset_100['land_mask'], np.nan, xr_dataset_100['sigma0']).transpose(*xr_dataset_100['sigma0'].dims)
|
|
952
|
+
|
|
953
|
+
xr_dataset_100['ancillary_wind'] = (
|
|
954
|
+
xr_dataset_100.model_U10 + 1j * xr_dataset_100.model_V10) * np.exp(1j * np.deg2rad(xr_dataset_100.ground_heading))
|
|
955
|
+
|
|
956
|
+
downscales_factors = [1, 2, 4, 8]
|
|
957
|
+
# 4 and 8 must be in downscales_factors
|
|
958
|
+
assert all([x in downscales_factors for x in [4, 8]])
|
|
959
|
+
|
|
960
|
+
gradientFeatures = GradientFeatures(
|
|
961
|
+
xr_dataset=xr_dataset,
|
|
962
|
+
xr_dataset_100=xr_dataset_100,
|
|
963
|
+
windows_sizes=[1600, 3200],
|
|
964
|
+
downscales_factors=downscales_factors,
|
|
965
|
+
window_step=1
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
# Compute heterogeneity mask and variables
|
|
969
|
+
dataArraysHeterogeneity = gradientFeatures.get_heterogeneity_mask(config)
|
|
970
|
+
xr_dataset = xr_dataset.merge(dataArraysHeterogeneity)
|
|
971
|
+
|
|
972
|
+
# Add streaks dataset
|
|
973
|
+
streaks_indiv = gradientFeatures.streaks_individual()
|
|
974
|
+
if 'longitude' in streaks_indiv:
|
|
975
|
+
xr_dataset_streaks = xr.Dataset({
|
|
976
|
+
'longitude': streaks_indiv.longitude,
|
|
977
|
+
'latitude': streaks_indiv.latitude,
|
|
978
|
+
'dir_smooth': streaks_indiv.angle,
|
|
979
|
+
'dir_mean_smooth': gradientFeatures.streaks_mean_smooth().angle,
|
|
980
|
+
'dir_smooth_mean': gradientFeatures.streaks_smooth_mean().angle,
|
|
981
|
+
})
|
|
982
|
+
else:
|
|
983
|
+
logger.warn(
|
|
984
|
+
"'longitude' not found in streaks_indiv : there is probably an error")
|
|
985
|
+
xr_dataset_streaks = None
|
|
986
|
+
|
|
987
|
+
return xr_dataset, xr_dataset_streaks
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
@timing(logger=logger.info)
|
|
991
|
+
def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, resolution='1000m'):
|
|
831
992
|
"""
|
|
832
993
|
Main function to generate L2 product.
|
|
833
994
|
|
|
@@ -855,7 +1016,13 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, add
|
|
|
855
1016
|
"""
|
|
856
1017
|
|
|
857
1018
|
xr_dataset, out_file, config = preprocess(
|
|
858
|
-
filename, outdir, config_path, overwrite,
|
|
1019
|
+
filename, outdir, config_path, overwrite, resolution)
|
|
1020
|
+
|
|
1021
|
+
if config["add_gradientsfeatures"]:
|
|
1022
|
+
xr_dataset, xr_dataset_streaks = process_gradients(
|
|
1023
|
+
xr_dataset, config)
|
|
1024
|
+
else:
|
|
1025
|
+
xr_dataset_streaks = None
|
|
859
1026
|
|
|
860
1027
|
model_co = config["l2_params"]["model_co"]
|
|
861
1028
|
model_cross = config["l2_params"]["model_cross"]
|
|
@@ -899,8 +1066,6 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, add
|
|
|
899
1066
|
model_co=model_co,
|
|
900
1067
|
model_cross=model_cross,
|
|
901
1068
|
** kwargs)
|
|
902
|
-
wind_co.compute()
|
|
903
|
-
|
|
904
1069
|
# windspeed_co
|
|
905
1070
|
xr_dataset['windspeed_co'] = np.abs(wind_co)
|
|
906
1071
|
xr_dataset["windspeed_co"].attrs["units"] = "m.s⁻1"
|
|
@@ -917,7 +1082,6 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, add
|
|
|
917
1082
|
|
|
918
1083
|
# windspeed_dual / windspeed_cr / /winddir_dual / winddir_cr
|
|
919
1084
|
if dual_pol and wind_dual is not None:
|
|
920
|
-
wind_dual.compute()
|
|
921
1085
|
xr_dataset['windspeed_dual'] = np.abs(wind_dual)
|
|
922
1086
|
xr_dataset["windspeed_dual"].attrs["units"] = "m.s⁻1"
|
|
923
1087
|
xr_dataset["windspeed_dual"].attrs["long_name"] = "Wind speed inverted from model %s (%s) & %s (%s)" % (
|
|
@@ -931,7 +1095,7 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, add
|
|
|
931
1095
|
xr_dataset["winddir_dual"].attrs["model"] = "winddir_dual is a copy of copol wind direction"
|
|
932
1096
|
|
|
933
1097
|
xr_dataset = xr_dataset.assign(
|
|
934
|
-
windspeed_cross=(['line', 'sample'], windspeed_cr))
|
|
1098
|
+
windspeed_cross=(['line', 'sample'], windspeed_cr.data))
|
|
935
1099
|
xr_dataset["windspeed_cross"].attrs["units"] = "m.s⁻1"
|
|
936
1100
|
xr_dataset["windspeed_cross"].attrs["long_name"] = "Wind Speed inverted from model %s (%s)" % (
|
|
937
1101
|
model_cross, crosspol)
|
|
@@ -951,8 +1115,9 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, add
|
|
|
951
1115
|
"long_name"] = f"{ancillary_name} wind direction in oceanographic convention (clockwise, to), ex: 0°=to north, 90°=to east"
|
|
952
1116
|
|
|
953
1117
|
xr_dataset, encoding = makeL2asOwi(
|
|
954
|
-
xr_dataset,
|
|
1118
|
+
xr_dataset, config)
|
|
955
1119
|
|
|
1120
|
+
xr_dataset = xr_dataset.compute()
|
|
956
1121
|
# add attributes
|
|
957
1122
|
firstMeasurementTime = None
|
|
958
1123
|
lastMeasurementTime = None
|
|
@@ -1035,7 +1200,26 @@ def makeL2(filename, outdir, config_path, overwrite=False, generateCSV=True, add
|
|
|
1035
1200
|
|
|
1036
1201
|
os.makedirs(os.path.dirname(out_file), exist_ok=True)
|
|
1037
1202
|
|
|
1203
|
+
# Sauvegarde de xr_dataset dans le fichier de sortie final
|
|
1038
1204
|
xr_dataset.to_netcdf(out_file, mode="w", encoding=encoding)
|
|
1205
|
+
|
|
1206
|
+
# Vérifier si le dataset de streaks est présent
|
|
1207
|
+
if xr_dataset_streaks is not None:
|
|
1208
|
+
# Créer un fichier temporaire pour le dataset streaks
|
|
1209
|
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".nc") as tmp_file:
|
|
1210
|
+
temp_out_file = tmp_file.name
|
|
1211
|
+
|
|
1212
|
+
# Écrire xr_dataset_streaks dans le fichier temporaire
|
|
1213
|
+
xr_dataset_streaks.to_netcdf(
|
|
1214
|
+
temp_out_file, mode="w", group="owiWindStreaks")
|
|
1215
|
+
|
|
1216
|
+
# Charger le fichier temporaire et l'ajouter au fichier final en tant que groupe
|
|
1217
|
+
with xr.open_dataset(temp_out_file, group="owiWindStreaks") as ds_streaks:
|
|
1218
|
+
ds_streaks.to_netcdf(out_file, mode="a", group="owiWindStreaks")
|
|
1219
|
+
|
|
1220
|
+
# Supprimer le fichier temporaire après l'opération
|
|
1221
|
+
os.remove(temp_out_file)
|
|
1222
|
+
|
|
1039
1223
|
if generateCSV:
|
|
1040
1224
|
df = xr_dataset.to_dataframe()
|
|
1041
1225
|
df = df[df.owiMask == False]
|
grdwindinversion/load_config.py
CHANGED
|
@@ -3,11 +3,14 @@ import logging
|
|
|
3
3
|
import os
|
|
4
4
|
import grdwindinversion
|
|
5
5
|
from yaml import CLoader as Loader
|
|
6
|
-
|
|
6
|
+
local_config_potential_path1 = os.path.expanduser(
|
|
7
7
|
'~/.grdwindinversion/data_config.yaml')
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
local_config_potential_path2 = os.path.join(os.path.dirname(
|
|
9
|
+
grdwindinversion.__file__), 'local_data_config.yaml')
|
|
10
|
+
if os.path.exists(local_config_potential_path1):
|
|
11
|
+
config_path = local_config_potential_path1
|
|
12
|
+
elif os.path.exists(local_config_potential_path2):
|
|
13
|
+
config_path = local_config_potential_path2
|
|
11
14
|
else:
|
|
12
15
|
config_path = os.path.join(os.path.dirname(
|
|
13
16
|
grdwindinversion.__file__), 'data_config.yaml')
|