disdrodb 0.1.2__py3-none-any.whl → 0.1.4__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.
- disdrodb/__init__.py +68 -34
- disdrodb/_config.py +5 -4
- disdrodb/_version.py +16 -3
- disdrodb/accessor/__init__.py +20 -0
- disdrodb/accessor/methods.py +125 -0
- disdrodb/api/checks.py +177 -24
- disdrodb/api/configs.py +3 -3
- disdrodb/api/info.py +13 -13
- disdrodb/api/io.py +281 -22
- disdrodb/api/path.py +184 -195
- disdrodb/api/search.py +18 -9
- disdrodb/cli/disdrodb_create_summary.py +103 -0
- disdrodb/cli/disdrodb_create_summary_station.py +91 -0
- disdrodb/cli/disdrodb_run_l0.py +1 -1
- disdrodb/cli/disdrodb_run_l0_station.py +1 -1
- disdrodb/cli/disdrodb_run_l0a_station.py +1 -1
- disdrodb/cli/disdrodb_run_l0b.py +1 -1
- disdrodb/cli/disdrodb_run_l0b_station.py +3 -3
- disdrodb/cli/disdrodb_run_l0c.py +1 -1
- disdrodb/cli/disdrodb_run_l0c_station.py +3 -3
- disdrodb/cli/disdrodb_run_l1_station.py +2 -2
- disdrodb/cli/disdrodb_run_l2e_station.py +2 -2
- disdrodb/cli/disdrodb_run_l2m_station.py +2 -2
- disdrodb/configs.py +149 -4
- disdrodb/constants.py +61 -0
- disdrodb/data_transfer/download_data.py +127 -11
- disdrodb/etc/configs/attributes.yaml +339 -0
- disdrodb/etc/configs/encodings.yaml +473 -0
- disdrodb/etc/products/L1/global.yaml +13 -0
- disdrodb/etc/products/L2E/10MIN.yaml +12 -0
- disdrodb/etc/products/L2E/1MIN.yaml +1 -0
- disdrodb/etc/products/L2E/global.yaml +22 -0
- disdrodb/etc/products/L2M/10MIN.yaml +12 -0
- disdrodb/etc/products/L2M/GAMMA_ML.yaml +8 -0
- disdrodb/etc/products/L2M/NGAMMA_GS_LOG_ND_MAE.yaml +6 -0
- disdrodb/etc/products/L2M/NGAMMA_GS_ND_MAE.yaml +6 -0
- disdrodb/etc/products/L2M/NGAMMA_GS_Z_MAE.yaml +6 -0
- disdrodb/etc/products/L2M/global.yaml +26 -0
- disdrodb/issue/writer.py +2 -0
- disdrodb/l0/__init__.py +13 -0
- disdrodb/l0/configs/LPM/l0b_cf_attrs.yml +4 -4
- disdrodb/l0/configs/PARSIVEL/l0b_cf_attrs.yml +1 -1
- disdrodb/l0/configs/PARSIVEL/l0b_encodings.yml +3 -3
- disdrodb/l0/configs/PARSIVEL/raw_data_format.yml +1 -1
- disdrodb/l0/configs/PARSIVEL2/l0b_cf_attrs.yml +5 -5
- disdrodb/l0/configs/PARSIVEL2/l0b_encodings.yml +3 -3
- disdrodb/l0/configs/PARSIVEL2/raw_data_format.yml +1 -1
- disdrodb/l0/configs/PWS100/l0b_cf_attrs.yml +4 -4
- disdrodb/l0/configs/PWS100/raw_data_format.yml +1 -1
- disdrodb/l0/l0a_processing.py +37 -32
- disdrodb/l0/l0b_nc_processing.py +118 -8
- disdrodb/l0/l0b_processing.py +30 -65
- disdrodb/l0/l0c_processing.py +369 -259
- disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +7 -0
- disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_LPM_NC.py +66 -0
- disdrodb/l0/readers/LPM/SLOVENIA/{CRNI_VRH.py → UL.py} +3 -0
- disdrodb/l0/readers/LPM/SWITZERLAND/INNERERIZ_LPM.py +195 -0
- disdrodb/l0/readers/PARSIVEL/GPM/PIERS.py +0 -2
- disdrodb/l0/readers/PARSIVEL/JAPAN/JMA.py +4 -1
- disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +1 -1
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/ARM/ARM_PARSIVEL2.py +4 -0
- disdrodb/l0/readers/PARSIVEL2/BELGIUM/ILVO.py +168 -0
- disdrodb/l0/readers/PARSIVEL2/CANADA/UQAM_NC.py +69 -0
- disdrodb/l0/readers/PARSIVEL2/DENMARK/DTU.py +165 -0
- disdrodb/l0/readers/PARSIVEL2/FINLAND/FMI_PARSIVEL2.py +69 -0
- disdrodb/l0/readers/PARSIVEL2/FRANCE/ENPC_PARSIVEL2.py +255 -134
- disdrodb/l0/readers/PARSIVEL2/FRANCE/OSUG.py +525 -0
- disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/GPM/GCPEX.py +9 -7
- disdrodb/l0/readers/PARSIVEL2/KIT/BURKINA_FASO.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/KIT/TEAMX.py +123 -0
- disdrodb/l0/readers/PARSIVEL2/{NETHERLANDS/DELFT.py → MPI/BCO_PARSIVEL2.py} +41 -71
- disdrodb/l0/readers/PARSIVEL2/MPI/BOWTIE.py +220 -0
- disdrodb/l0/readers/PARSIVEL2/NASA/APU.py +120 -0
- disdrodb/l0/readers/PARSIVEL2/NASA/LPVEX.py +109 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/FARM_PARSIVEL2.py +1 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_MIPS.py +126 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_PIPS.py +165 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +20 -12
- disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT_NC.py +5 -0
- disdrodb/l0/readers/PARSIVEL2/SPAIN/CENER.py +144 -0
- disdrodb/l0/readers/PARSIVEL2/SPAIN/CR1000DL.py +201 -0
- disdrodb/l0/readers/PARSIVEL2/SPAIN/LIAISE.py +137 -0
- disdrodb/l0/readers/PARSIVEL2/USA/C3WE.py +146 -0
- disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100.py +105 -99
- disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100_SIRTA.py +151 -0
- disdrodb/l1/__init__.py +5 -0
- disdrodb/l1/fall_velocity.py +46 -0
- disdrodb/l1/filters.py +34 -20
- disdrodb/l1/processing.py +46 -45
- disdrodb/l1/resampling.py +77 -66
- disdrodb/l1_env/routines.py +18 -3
- disdrodb/l2/__init__.py +7 -0
- disdrodb/l2/empirical_dsd.py +58 -10
- disdrodb/l2/processing.py +268 -117
- disdrodb/metadata/checks.py +132 -125
- disdrodb/metadata/standards.py +3 -1
- disdrodb/psd/fitting.py +631 -345
- disdrodb/psd/models.py +9 -6
- disdrodb/routines/__init__.py +54 -0
- disdrodb/{l0/routines.py → routines/l0.py} +316 -355
- disdrodb/{l1/routines.py → routines/l1.py} +76 -116
- disdrodb/routines/l2.py +1019 -0
- disdrodb/{routines.py → routines/wrappers.py} +98 -10
- disdrodb/scattering/__init__.py +16 -4
- disdrodb/scattering/axis_ratio.py +61 -37
- disdrodb/scattering/permittivity.py +504 -0
- disdrodb/scattering/routines.py +746 -184
- disdrodb/summary/__init__.py +17 -0
- disdrodb/summary/routines.py +4196 -0
- disdrodb/utils/archiving.py +434 -0
- disdrodb/utils/attrs.py +68 -125
- disdrodb/utils/cli.py +5 -5
- disdrodb/utils/compression.py +30 -1
- disdrodb/utils/dask.py +121 -9
- disdrodb/utils/dataframe.py +61 -7
- disdrodb/utils/decorators.py +31 -0
- disdrodb/utils/directories.py +35 -15
- disdrodb/utils/encoding.py +37 -19
- disdrodb/{l2 → utils}/event.py +15 -173
- disdrodb/utils/logger.py +14 -7
- disdrodb/utils/manipulations.py +81 -0
- disdrodb/utils/routines.py +166 -0
- disdrodb/utils/subsetting.py +214 -0
- disdrodb/utils/time.py +35 -177
- disdrodb/utils/writer.py +20 -7
- disdrodb/utils/xarray.py +5 -4
- disdrodb/viz/__init__.py +13 -0
- disdrodb/viz/plots.py +398 -0
- {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/METADATA +4 -3
- {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/RECORD +139 -98
- {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/entry_points.txt +2 -0
- disdrodb/l1/encoding_attrs.py +0 -642
- disdrodb/l2/processing_options.py +0 -213
- disdrodb/l2/routines.py +0 -868
- /disdrodb/l0/readers/PARSIVEL/SLOVENIA/{UL_FGG.py → UL.py} +0 -0
- {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/WHEEL +0 -0
- {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/licenses/LICENSE +0 -0
- {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/top_level.txt +0 -0
disdrodb/api/path.py
CHANGED
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
import os
|
|
21
21
|
|
|
22
22
|
from disdrodb.configs import get_data_archive_dir, get_metadata_archive_dir
|
|
23
|
+
from disdrodb.constants import ARCHIVE_VERSION
|
|
23
24
|
from disdrodb.utils.directories import check_directory_exists
|
|
24
25
|
from disdrodb.utils.time import (
|
|
25
26
|
ensure_sample_interval_in_seconds,
|
|
26
27
|
get_file_start_end_time,
|
|
27
|
-
|
|
28
|
+
seconds_to_temporal_resolution,
|
|
28
29
|
)
|
|
29
30
|
|
|
30
31
|
####--------------------------------------------------------------------------.
|
|
@@ -62,14 +63,13 @@ def define_disdrodb_path(
|
|
|
62
63
|
The campaign name.
|
|
63
64
|
check_exists : bool, optional
|
|
64
65
|
Whether to check if the directory exists. The default value is ``True``.
|
|
66
|
+
Raise error if the directory does not exist.
|
|
65
67
|
|
|
66
68
|
Returns
|
|
67
69
|
-------
|
|
68
70
|
dir_path : str
|
|
69
71
|
Directory path
|
|
70
72
|
"""
|
|
71
|
-
from disdrodb import ARCHIVE_VERSION
|
|
72
|
-
|
|
73
73
|
if len(campaign_name) > 0 and len(data_source) == 0:
|
|
74
74
|
raise ValueError("If campaign_name is specified, data_source must be specified.")
|
|
75
75
|
|
|
@@ -82,7 +82,7 @@ def define_disdrodb_path(
|
|
|
82
82
|
dir_path = os.path.join(archive_dir, ARCHIVE_VERSION, data_source, campaign_name)
|
|
83
83
|
if check_exists:
|
|
84
84
|
check_directory_exists(dir_path)
|
|
85
|
-
return dir_path
|
|
85
|
+
return os.path.normpath(dir_path)
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
def define_data_source_dir(
|
|
@@ -108,6 +108,7 @@ def define_data_source_dir(
|
|
|
108
108
|
If not specified, the path specified in the DISDRODB active configuration will be used.
|
|
109
109
|
check_exists : bool, optional
|
|
110
110
|
Whether to check if the directory exists. The default value is ``False``.
|
|
111
|
+
Raise error if the directory does not exist.
|
|
111
112
|
|
|
112
113
|
Returns
|
|
113
114
|
-------
|
|
@@ -349,7 +350,56 @@ def define_config_dir(product):
|
|
|
349
350
|
#### Directory/Filepaths L0A and L0B products
|
|
350
351
|
|
|
351
352
|
|
|
352
|
-
def
|
|
353
|
+
def define_partitioning_tree(time, folder_partitioning):
|
|
354
|
+
"""Define the time directory tree given a timestep.
|
|
355
|
+
|
|
356
|
+
Parameters
|
|
357
|
+
----------
|
|
358
|
+
time : datetime.datetime
|
|
359
|
+
Timestep.
|
|
360
|
+
folder_partitioning : str or None
|
|
361
|
+
Define the subdirectory structure where saving files.
|
|
362
|
+
Allowed values are:
|
|
363
|
+
- None: Files are saved directly in data_dir.
|
|
364
|
+
- "year": Files are saved under a subdirectory for the year.
|
|
365
|
+
- "year/month": Files are saved under subdirectories for year and month.
|
|
366
|
+
- "year/month/day": Files are saved under subdirectories for year, month and day
|
|
367
|
+
- "year/month_name": Files are stored under subdirectories by year and month name
|
|
368
|
+
- "year/quarter": Files are saved under subdirectories for year and quarter.
|
|
369
|
+
|
|
370
|
+
Returns
|
|
371
|
+
-------
|
|
372
|
+
str
|
|
373
|
+
A time partitioned directory tree.
|
|
374
|
+
"""
|
|
375
|
+
if folder_partitioning == "":
|
|
376
|
+
return ""
|
|
377
|
+
if folder_partitioning == "year":
|
|
378
|
+
year = str(time.year)
|
|
379
|
+
return year
|
|
380
|
+
if folder_partitioning == "year/month":
|
|
381
|
+
year = str(time.year)
|
|
382
|
+
month = str(time.month).zfill(2)
|
|
383
|
+
return os.path.join(year, month)
|
|
384
|
+
if folder_partitioning == "year/month/day":
|
|
385
|
+
year = str(time.year)
|
|
386
|
+
month = str(time.month).zfill(2)
|
|
387
|
+
day = str(time.day).zfill(2)
|
|
388
|
+
return os.path.join(year, month, day)
|
|
389
|
+
if folder_partitioning == "year/month_name":
|
|
390
|
+
year = str(time.year)
|
|
391
|
+
month = time.strftime("%B")
|
|
392
|
+
return os.path.join(year, month)
|
|
393
|
+
if folder_partitioning == "year/quarter":
|
|
394
|
+
year = str(time.year)
|
|
395
|
+
# Calculate quarter: months 1-3 => Q1, 4-6 => Q2, etc.
|
|
396
|
+
quarter = (time.month - 1) // 3 + 1
|
|
397
|
+
quarter_dir = f"Q{quarter}"
|
|
398
|
+
return os.path.join(year, quarter_dir)
|
|
399
|
+
raise NotImplementedError(f"Unrecognized '{folder_partitioning}' folder partitioning scheme.")
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def define_file_folder_path(obj, dir_path, folder_partitioning):
|
|
353
403
|
"""
|
|
354
404
|
Define the folder path where saving a file based on the dataset's starting time.
|
|
355
405
|
|
|
@@ -357,12 +407,13 @@ def define_file_folder_path(obj, data_dir, folder_partitioning):
|
|
|
357
407
|
----------
|
|
358
408
|
ds : xarray.Dataset or pandas.DataFrame
|
|
359
409
|
The object containing time information.
|
|
360
|
-
|
|
410
|
+
dir : str
|
|
361
411
|
Directory within the DISDRODB Data Archive where DISDRODB product files are to be saved.
|
|
412
|
+
It can be a product directory or a logs directory.
|
|
362
413
|
folder_partitioning : str or None
|
|
363
414
|
Define the subdirectory structure where saving files.
|
|
364
415
|
Allowed values are:
|
|
365
|
-
- None: Files are saved directly in data_dir.
|
|
416
|
+
- None or "": Files are saved directly in data_dir.
|
|
366
417
|
- "year": Files are saved under a subdirectory for the year.
|
|
367
418
|
- "year/month": Files are saved under subdirectories for year and month.
|
|
368
419
|
- "year/month/day": Files are saved under subdirectories for year, month and day
|
|
@@ -382,32 +433,9 @@ def define_file_folder_path(obj, data_dir, folder_partitioning):
|
|
|
382
433
|
# Retrieve the starting time from the dataset.
|
|
383
434
|
starting_time, _ = get_file_start_end_time(obj)
|
|
384
435
|
|
|
385
|
-
# Build the folder path based on the chosen partition scheme
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
if folder_partitioning == "year":
|
|
389
|
-
year = str(starting_time.year)
|
|
390
|
-
return os.path.join(data_dir, year)
|
|
391
|
-
if folder_partitioning == "year/month":
|
|
392
|
-
year = str(starting_time.year)
|
|
393
|
-
month = str(starting_time.month).zfill(2)
|
|
394
|
-
return os.path.join(data_dir, year, month)
|
|
395
|
-
if folder_partitioning == "year/month/day":
|
|
396
|
-
year = str(starting_time.year)
|
|
397
|
-
month = str(starting_time.month).zfill(2)
|
|
398
|
-
day = str(starting_time.day).zfill(2)
|
|
399
|
-
return os.path.join(data_dir, year, month, day)
|
|
400
|
-
if folder_partitioning == "year/month_name":
|
|
401
|
-
year = str(starting_time.year)
|
|
402
|
-
month = str(starting_time.month_name())
|
|
403
|
-
return os.path.join(data_dir, year, month)
|
|
404
|
-
if folder_partitioning == "year/quarter":
|
|
405
|
-
year = str(starting_time.year)
|
|
406
|
-
# Calculate quarter: months 1-3 => Q1, 4-6 => Q2, etc.
|
|
407
|
-
quarter = (starting_time.month - 1) // 3 + 1
|
|
408
|
-
quarter_dir = f"Q{quarter}"
|
|
409
|
-
return os.path.join(data_dir, year, quarter_dir)
|
|
410
|
-
raise NotImplementedError(f"Unrecognized '{folder_partitioning}' folder partitioning scheme.")
|
|
436
|
+
# Build the folder path based on the chosen partition scheme
|
|
437
|
+
partitioning_tree = define_partitioning_tree(time=starting_time, folder_partitioning=folder_partitioning)
|
|
438
|
+
return os.path.normpath(os.path.join(dir_path, partitioning_tree))
|
|
411
439
|
|
|
412
440
|
|
|
413
441
|
def define_product_dir_tree(
|
|
@@ -448,17 +476,16 @@ def define_product_dir_tree(
|
|
|
448
476
|
sample_interval = product_kwargs.get("sample_interval")
|
|
449
477
|
check_rolling(rolling)
|
|
450
478
|
check_sample_interval(sample_interval)
|
|
451
|
-
|
|
452
|
-
return os.path.join(
|
|
453
|
-
if product == "L2M":
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
raise ValueError(f"The product {product} is not defined.")
|
|
479
|
+
temporal_resolution = define_temporal_resolution(seconds=sample_interval, rolling=rolling)
|
|
480
|
+
return os.path.join(temporal_resolution)
|
|
481
|
+
# L2M if product == "L2M":
|
|
482
|
+
rolling = product_kwargs.get("rolling")
|
|
483
|
+
sample_interval = product_kwargs.get("sample_interval")
|
|
484
|
+
model_name = product_kwargs.get("model_name")
|
|
485
|
+
check_rolling(rolling)
|
|
486
|
+
check_sample_interval(sample_interval)
|
|
487
|
+
temporal_resolution = define_temporal_resolution(seconds=sample_interval, rolling=rolling)
|
|
488
|
+
return os.path.join(model_name, temporal_resolution)
|
|
462
489
|
|
|
463
490
|
|
|
464
491
|
def define_logs_dir(
|
|
@@ -504,7 +531,7 @@ def define_logs_dir(
|
|
|
504
531
|
product=product,
|
|
505
532
|
**product_kwargs,
|
|
506
533
|
)
|
|
507
|
-
logs_dir = os.path.join(campaign_dir, "logs", "files", product, product_dir_tree, station_name)
|
|
534
|
+
logs_dir = os.path.normpath(os.path.join(campaign_dir, "logs", "files", product, product_dir_tree, station_name))
|
|
508
535
|
if check_exists:
|
|
509
536
|
check_directory_exists(logs_dir)
|
|
510
537
|
return str(logs_dir)
|
|
@@ -618,7 +645,7 @@ def define_data_dir(
|
|
|
618
645
|
**product_kwargs,
|
|
619
646
|
)
|
|
620
647
|
# Define data directory
|
|
621
|
-
data_dir = os.path.join(station_dir, product_dir_tree)
|
|
648
|
+
data_dir = os.path.normpath(os.path.join(station_dir, product_dir_tree))
|
|
622
649
|
# Check if directory exists
|
|
623
650
|
if check_exists:
|
|
624
651
|
check_directory_exists(data_dir)
|
|
@@ -629,15 +656,15 @@ def define_data_dir(
|
|
|
629
656
|
#### Filenames for DISDRODB products
|
|
630
657
|
|
|
631
658
|
|
|
632
|
-
def
|
|
633
|
-
"""Define the
|
|
659
|
+
def define_temporal_resolution(seconds, rolling):
|
|
660
|
+
"""Define the DISDRODB product temporal resolution.
|
|
634
661
|
|
|
635
|
-
Prefix the
|
|
662
|
+
Prefix the measurement interval with ROLL if rolling=True.
|
|
636
663
|
"""
|
|
637
|
-
|
|
664
|
+
temporal_resolution = seconds_to_temporal_resolution(seconds)
|
|
638
665
|
if rolling:
|
|
639
|
-
|
|
640
|
-
return
|
|
666
|
+
temporal_resolution = f"ROLL{temporal_resolution}"
|
|
667
|
+
return temporal_resolution
|
|
641
668
|
|
|
642
669
|
|
|
643
670
|
####--------------------------------------------------------------------------.
|
|
@@ -649,7 +676,8 @@ def define_filename(
|
|
|
649
676
|
campaign_name: str,
|
|
650
677
|
station_name: str,
|
|
651
678
|
# Filename options
|
|
652
|
-
|
|
679
|
+
start_time=None,
|
|
680
|
+
end_time=None,
|
|
653
681
|
add_version=True,
|
|
654
682
|
add_time_period=True,
|
|
655
683
|
add_extension=True,
|
|
@@ -663,19 +691,22 @@ def define_filename(
|
|
|
663
691
|
|
|
664
692
|
Parameters
|
|
665
693
|
----------
|
|
666
|
-
obj : xarray.Dataset or pandas.DataFrame
|
|
667
|
-
xarray Dataset or pandas DataFrame.
|
|
668
|
-
Required if add_time_period = True.
|
|
669
694
|
campaign_name : str
|
|
670
695
|
Name of the campaign.
|
|
671
696
|
station_name : str
|
|
672
697
|
Name of the station.
|
|
698
|
+
start_time : datetime.datatime, optional
|
|
699
|
+
Start time.
|
|
700
|
+
Required if add_time_period = True.
|
|
701
|
+
end_time : datetime.datatime, optional
|
|
702
|
+
End time.
|
|
703
|
+
Required if add_time_period = True.
|
|
673
704
|
sample_interval : int, optional
|
|
674
705
|
The sampling interval in seconds of the product.
|
|
675
|
-
It must be specified only for product L2E and L2M !
|
|
706
|
+
It must be specified only for product L0C, L1, L2E and L2M !
|
|
676
707
|
rolling : bool, optional
|
|
677
708
|
Whether the dataset has been resampled by aggregating or rolling.
|
|
678
|
-
It must be specified only for product L2E and L2M !
|
|
709
|
+
It must be specified only for product L1, L2E and L2M !
|
|
679
710
|
model_name : str
|
|
680
711
|
The model name of the fitted statistical distribution for the DSD.
|
|
681
712
|
It must be specified only for product L2M !
|
|
@@ -685,32 +716,37 @@ def define_filename(
|
|
|
685
716
|
str
|
|
686
717
|
L0B file name.
|
|
687
718
|
"""
|
|
688
|
-
from disdrodb import ARCHIVE_VERSION
|
|
689
719
|
from disdrodb.api.checks import check_product, check_product_kwargs
|
|
690
720
|
|
|
691
721
|
product = check_product(product)
|
|
692
722
|
product_kwargs = check_product_kwargs(product, product_kwargs)
|
|
693
723
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
# - ADD sample_interval_acronym also to L0A and L0B
|
|
697
|
-
# - Add sample_interval_acronym also to L0C and L1
|
|
724
|
+
if add_time_period and (start_time is None or end_time is None):
|
|
725
|
+
raise ValueError("If add_time_period=True, specify start_time and end_time.")
|
|
698
726
|
|
|
699
727
|
# -----------------------------------------.
|
|
700
|
-
# Define product
|
|
701
|
-
|
|
728
|
+
# Define product name
|
|
729
|
+
product_name = f"{product}"
|
|
730
|
+
|
|
731
|
+
# L0C ... sample interval known only per-file
|
|
732
|
+
# L1 ... in future known a priori
|
|
733
|
+
# if product in ["L1"]:
|
|
734
|
+
# # TODO: HACK FOR CURRENT L0C and L1 log files in create_product_logs
|
|
735
|
+
# sample_interval = product_kwargs.get("sample_interval", 0)
|
|
736
|
+
# temporal_resolution = define_temporal_resolution(seconds=sample_interval, rolling=False)
|
|
737
|
+
# product_name = f"{product}.{temporal_resolution}"
|
|
702
738
|
if product in ["L2E", "L2M"]:
|
|
703
739
|
rolling = product_kwargs.get("rolling")
|
|
704
740
|
sample_interval = product_kwargs.get("sample_interval")
|
|
705
|
-
|
|
706
|
-
|
|
741
|
+
temporal_resolution = define_temporal_resolution(seconds=sample_interval, rolling=rolling)
|
|
742
|
+
product_name = f"{product}.{temporal_resolution}"
|
|
707
743
|
if product in ["L2M"]:
|
|
708
744
|
model_name = product_kwargs.get("model_name")
|
|
709
|
-
|
|
745
|
+
product_name = f"L2M_{model_name}.{temporal_resolution}"
|
|
710
746
|
|
|
711
747
|
# -----------------------------------------.
|
|
712
748
|
# Define base filename
|
|
713
|
-
filename = f"{
|
|
749
|
+
filename = f"{product_name}.{campaign_name}.{station_name}"
|
|
714
750
|
|
|
715
751
|
# -----------------------------------------.
|
|
716
752
|
# Add prefix
|
|
@@ -720,10 +756,9 @@ def define_filename(
|
|
|
720
756
|
# -----------------------------------------.
|
|
721
757
|
# Add time period information
|
|
722
758
|
if add_time_period:
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
filename = f"{filename}.s{starting_time}.e{ending_time}"
|
|
759
|
+
start_time = start_time.strftime("%Y%m%d%H%M%S")
|
|
760
|
+
end_time = end_time.strftime("%Y%m%d%H%M%S")
|
|
761
|
+
filename = f"{filename}.s{start_time}.e{end_time}"
|
|
727
762
|
|
|
728
763
|
# -----------------------------------------.
|
|
729
764
|
# Add product version
|
|
@@ -759,133 +794,97 @@ def define_l0a_filename(df, campaign_name: str, station_name: str) -> str:
|
|
|
759
794
|
str
|
|
760
795
|
L0A file name.
|
|
761
796
|
"""
|
|
762
|
-
from disdrodb import ARCHIVE_VERSION
|
|
763
|
-
|
|
764
797
|
starting_time, ending_time = get_file_start_end_time(df)
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
798
|
+
filename = define_filename(
|
|
799
|
+
product="L0A",
|
|
800
|
+
campaign_name=campaign_name,
|
|
801
|
+
station_name=station_name,
|
|
802
|
+
# Filename options
|
|
803
|
+
start_time=starting_time,
|
|
804
|
+
end_time=ending_time,
|
|
805
|
+
add_version=True,
|
|
806
|
+
add_time_period=True,
|
|
807
|
+
add_extension=True,
|
|
808
|
+
)
|
|
769
809
|
return filename
|
|
770
810
|
|
|
771
811
|
|
|
772
812
|
def define_l0b_filename(ds, campaign_name: str, station_name: str) -> str:
|
|
773
|
-
"""Define L0B file name.
|
|
774
|
-
|
|
775
|
-
Parameters
|
|
776
|
-
----------
|
|
777
|
-
ds : xarray.Dataset
|
|
778
|
-
L0B xarray Dataset.
|
|
779
|
-
campaign_name : str
|
|
780
|
-
Name of the campaign.
|
|
781
|
-
station_name : str
|
|
782
|
-
Name of the station.
|
|
783
|
-
|
|
784
|
-
Returns
|
|
785
|
-
-------
|
|
786
|
-
str
|
|
787
|
-
L0B file name.
|
|
788
|
-
"""
|
|
789
|
-
from disdrodb import ARCHIVE_VERSION
|
|
790
|
-
|
|
813
|
+
"""Define L0B file name."""
|
|
791
814
|
starting_time, ending_time = get_file_start_end_time(ds)
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
815
|
+
filename = define_filename(
|
|
816
|
+
product="L0B",
|
|
817
|
+
campaign_name=campaign_name,
|
|
818
|
+
station_name=station_name,
|
|
819
|
+
# Filename options
|
|
820
|
+
start_time=starting_time,
|
|
821
|
+
end_time=ending_time,
|
|
822
|
+
add_version=True,
|
|
823
|
+
add_time_period=True,
|
|
824
|
+
add_extension=True,
|
|
825
|
+
)
|
|
796
826
|
return filename
|
|
797
827
|
|
|
798
828
|
|
|
799
829
|
def define_l0c_filename(ds, campaign_name: str, station_name: str) -> str:
|
|
800
|
-
"""Define L0C file name.
|
|
801
|
-
|
|
802
|
-
Parameters
|
|
803
|
-
----------
|
|
804
|
-
ds : xarray.Dataset
|
|
805
|
-
L0B xarray Dataset.
|
|
806
|
-
campaign_name : str
|
|
807
|
-
Name of the campaign.
|
|
808
|
-
station_name : str
|
|
809
|
-
Name of the station.
|
|
810
|
-
|
|
811
|
-
Returns
|
|
812
|
-
-------
|
|
813
|
-
str
|
|
814
|
-
L0B file name.
|
|
815
|
-
"""
|
|
816
|
-
from disdrodb import ARCHIVE_VERSION
|
|
817
|
-
|
|
818
|
-
# TODO: add sample_interval as argument
|
|
830
|
+
"""Define L0C file name."""
|
|
831
|
+
# TODO: add sample_interval as function argument s
|
|
819
832
|
sample_interval = int(ensure_sample_interval_in_seconds(ds["sample_interval"]).data.item())
|
|
820
|
-
|
|
833
|
+
temporal_resolution = define_temporal_resolution(sample_interval, rolling=False)
|
|
821
834
|
starting_time, ending_time = get_file_start_end_time(ds)
|
|
822
835
|
starting_time = starting_time.strftime("%Y%m%d%H%M%S")
|
|
823
836
|
ending_time = ending_time.strftime("%Y%m%d%H%M%S")
|
|
824
837
|
version = ARCHIVE_VERSION
|
|
825
|
-
filename =
|
|
826
|
-
f"L0C.{sample_interval_acronym}.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
|
|
827
|
-
)
|
|
838
|
+
filename = f"L0C.{temporal_resolution}.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
|
|
828
839
|
return filename
|
|
829
840
|
|
|
830
841
|
|
|
831
842
|
def define_l1_filename(ds, campaign_name, station_name: str) -> str:
|
|
832
|
-
"""Define L1 file name.
|
|
833
|
-
|
|
834
|
-
Parameters
|
|
835
|
-
----------
|
|
836
|
-
ds : xarray.Dataset
|
|
837
|
-
L1 xarray Dataset.
|
|
838
|
-
campaign_name : str
|
|
839
|
-
Name of the campaign.
|
|
840
|
-
station_name : str
|
|
841
|
-
Name of the station.
|
|
843
|
+
"""Define L1 file name."""
|
|
844
|
+
# TODO: add sample_interval and rolling as function argument
|
|
842
845
|
|
|
843
|
-
|
|
844
|
-
-------
|
|
845
|
-
str
|
|
846
|
-
L1 file name.
|
|
847
|
-
"""
|
|
848
|
-
from disdrodb import ARCHIVE_VERSION
|
|
849
|
-
|
|
850
|
-
# TODO: add sample_interval as argument
|
|
846
|
+
starting_time, ending_time = get_file_start_end_time(ds)
|
|
851
847
|
sample_interval = int(ensure_sample_interval_in_seconds(ds["sample_interval"]).data.item())
|
|
852
|
-
|
|
848
|
+
temporal_resolution = define_temporal_resolution(sample_interval, rolling=False)
|
|
853
849
|
starting_time, ending_time = get_file_start_end_time(ds)
|
|
854
850
|
starting_time = starting_time.strftime("%Y%m%d%H%M%S")
|
|
855
851
|
ending_time = ending_time.strftime("%Y%m%d%H%M%S")
|
|
856
852
|
version = ARCHIVE_VERSION
|
|
857
|
-
filename =
|
|
858
|
-
|
|
859
|
-
|
|
853
|
+
filename = f"L1.{temporal_resolution}.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
|
|
854
|
+
|
|
855
|
+
# filename = define_filename(
|
|
856
|
+
# product="L1",
|
|
857
|
+
# campaign_name=campaign_name,
|
|
858
|
+
# station_name=station_name,
|
|
859
|
+
# # Filename options
|
|
860
|
+
# start_time=starting_time,
|
|
861
|
+
# end_time=ending_time,
|
|
862
|
+
# add_version=True,
|
|
863
|
+
# add_time_period=True,
|
|
864
|
+
# add_extension=True,
|
|
865
|
+
# # Product options
|
|
866
|
+
# # sample_interval=sample_interval,
|
|
867
|
+
# # rolling=rolling,
|
|
868
|
+
# )
|
|
860
869
|
return filename
|
|
861
870
|
|
|
862
871
|
|
|
863
872
|
def define_l2e_filename(ds, campaign_name: str, station_name: str, sample_interval: int, rolling: bool) -> str:
|
|
864
|
-
"""Define L2E file name.
|
|
865
|
-
|
|
866
|
-
Parameters
|
|
867
|
-
----------
|
|
868
|
-
ds : xarray.Dataset
|
|
869
|
-
L1 xarray Dataset
|
|
870
|
-
campaign_name : str
|
|
871
|
-
Name of the campaign.
|
|
872
|
-
station_name : str
|
|
873
|
-
Name of the station
|
|
874
|
-
|
|
875
|
-
Returns
|
|
876
|
-
-------
|
|
877
|
-
str
|
|
878
|
-
L0B file name.
|
|
879
|
-
"""
|
|
880
|
-
from disdrodb import ARCHIVE_VERSION
|
|
881
|
-
|
|
882
|
-
sample_interval_acronym = define_accumulation_acronym(seconds=sample_interval, rolling=rolling)
|
|
873
|
+
"""Define L2E file name."""
|
|
883
874
|
starting_time, ending_time = get_file_start_end_time(ds)
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
875
|
+
filename = define_filename(
|
|
876
|
+
product="L2E",
|
|
877
|
+
campaign_name=campaign_name,
|
|
878
|
+
station_name=station_name,
|
|
879
|
+
# Filename options
|
|
880
|
+
start_time=starting_time,
|
|
881
|
+
end_time=ending_time,
|
|
882
|
+
add_version=True,
|
|
883
|
+
add_time_period=True,
|
|
884
|
+
add_extension=True,
|
|
885
|
+
# Product options
|
|
886
|
+
sample_interval=sample_interval,
|
|
887
|
+
rolling=rolling,
|
|
889
888
|
)
|
|
890
889
|
return filename
|
|
891
890
|
|
|
@@ -898,31 +897,21 @@ def define_l2m_filename(
|
|
|
898
897
|
rolling: bool,
|
|
899
898
|
model_name: str,
|
|
900
899
|
) -> str:
|
|
901
|
-
"""Define L2M file name.
|
|
902
|
-
|
|
903
|
-
Parameters
|
|
904
|
-
----------
|
|
905
|
-
ds : xarray.Dataset
|
|
906
|
-
L1 xarray Dataset
|
|
907
|
-
campaign_name : str
|
|
908
|
-
Name of the campaign.
|
|
909
|
-
station_name : str
|
|
910
|
-
Name of the station
|
|
911
|
-
|
|
912
|
-
Returns
|
|
913
|
-
-------
|
|
914
|
-
str
|
|
915
|
-
L0B file name.
|
|
916
|
-
"""
|
|
917
|
-
from disdrodb import ARCHIVE_VERSION
|
|
918
|
-
|
|
919
|
-
sample_interval_acronym = define_accumulation_acronym(seconds=sample_interval, rolling=rolling)
|
|
900
|
+
"""Define L2M file name."""
|
|
920
901
|
starting_time, ending_time = get_file_start_end_time(ds)
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
902
|
+
filename = define_filename(
|
|
903
|
+
product="L2M",
|
|
904
|
+
campaign_name=campaign_name,
|
|
905
|
+
station_name=station_name,
|
|
906
|
+
# Filename options
|
|
907
|
+
start_time=starting_time,
|
|
908
|
+
end_time=ending_time,
|
|
909
|
+
add_version=True,
|
|
910
|
+
add_time_period=True,
|
|
911
|
+
add_extension=True,
|
|
912
|
+
# Product options
|
|
913
|
+
sample_interval=sample_interval,
|
|
914
|
+
rolling=rolling,
|
|
915
|
+
model_name=model_name,
|
|
927
916
|
)
|
|
928
917
|
return filename
|
disdrodb/api/search.py
CHANGED
|
@@ -16,14 +16,15 @@ from disdrodb.api.path import (
|
|
|
16
16
|
define_station_dir,
|
|
17
17
|
)
|
|
18
18
|
from disdrodb.configs import get_data_archive_dir, get_metadata_archive_dir
|
|
19
|
-
from disdrodb.
|
|
19
|
+
from disdrodb.constants import PRODUCTS_REQUIREMENTS
|
|
20
|
+
from disdrodb.utils.directories import contains_files, contains_netcdf_or_parquet_files, list_directories, list_files
|
|
20
21
|
from disdrodb.utils.yaml import read_yaml
|
|
21
22
|
|
|
23
|
+
####-------------------------------------------------------------------------
|
|
24
|
+
|
|
22
25
|
|
|
23
26
|
def get_required_product(product):
|
|
24
27
|
"""Determine the required product for input product processing."""
|
|
25
|
-
from disdrodb import PRODUCTS_REQUIREMENTS
|
|
26
|
-
|
|
27
28
|
# Check input
|
|
28
29
|
check_product(product)
|
|
29
30
|
# Determine required product
|
|
@@ -32,12 +33,13 @@ def get_required_product(product):
|
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
####-------------------------------------------------------------------------
|
|
35
|
-
#### List DISDRODB
|
|
36
|
+
#### List DISDRODB Metadata directories
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
def list_data_sources(metadata_archive_dir, data_sources=None, invalid_fields_policy="raise"):
|
|
39
40
|
"""List data sources names in the DISDRODB Metadata Archive."""
|
|
40
|
-
|
|
41
|
+
path = os.path.join(metadata_archive_dir, "METADATA")
|
|
42
|
+
available_data_sources = sorted(list_directories(path, return_paths=False))
|
|
41
43
|
# Filter by optionally specified data_sources
|
|
42
44
|
if data_sources is not None:
|
|
43
45
|
available_data_sources = check_valid_fields(
|
|
@@ -52,7 +54,7 @@ def list_data_sources(metadata_archive_dir, data_sources=None, invalid_fields_po
|
|
|
52
54
|
|
|
53
55
|
def _list_campaign_names(metadata_archive_dir, data_source):
|
|
54
56
|
data_source_dir = define_data_source_dir(metadata_archive_dir, product="METADATA", data_source=data_source)
|
|
55
|
-
campaign_names =
|
|
57
|
+
campaign_names = sorted(list_directories(data_source_dir, return_paths=False))
|
|
56
58
|
return campaign_names
|
|
57
59
|
|
|
58
60
|
|
|
@@ -109,7 +111,7 @@ def _list_station_names(metadata_archive_dir, data_source, campaign_name):
|
|
|
109
111
|
data_source=data_source,
|
|
110
112
|
campaign_name=campaign_name,
|
|
111
113
|
)
|
|
112
|
-
metadata_filenames =
|
|
114
|
+
metadata_filenames = sorted(list_files(metadata_dir, glob_pattern="*.yml", return_paths=False))
|
|
113
115
|
station_names = [fname.replace(".yml", "").replace(".yaml", "") for fname in metadata_filenames]
|
|
114
116
|
return station_names
|
|
115
117
|
|
|
@@ -167,6 +169,10 @@ def list_station_names(
|
|
|
167
169
|
return station_names
|
|
168
170
|
|
|
169
171
|
|
|
172
|
+
####-------------------------------------------------------------------------
|
|
173
|
+
#### Filtering utilities for available_stations
|
|
174
|
+
|
|
175
|
+
|
|
170
176
|
def _finalize_output(list_info, return_tuple):
|
|
171
177
|
# - Return the (data_source, campaign_name, station_name) tuple
|
|
172
178
|
if return_tuple:
|
|
@@ -228,7 +234,6 @@ def keep_list_info_elements_with_product_data(data_archive_dir, product, list_in
|
|
|
228
234
|
checking_function = contains_files if product == "RAW" else contains_netcdf_or_parquet_files
|
|
229
235
|
|
|
230
236
|
# Check presence of data for each station
|
|
231
|
-
# TODO: - In parallel over stations to speed up ?
|
|
232
237
|
list_info_with_product_data = []
|
|
233
238
|
for data_source, campaign_name, station_name in list_info:
|
|
234
239
|
data_dir = define_data_dir(
|
|
@@ -362,10 +367,11 @@ def available_stations(
|
|
|
362
367
|
metadata_archive_dir = get_metadata_archive_dir(metadata_archive_dir)
|
|
363
368
|
product = check_product(product) if product is not None else None
|
|
364
369
|
invalid_fields_policy = check_invalid_fields_policy(invalid_fields_policy)
|
|
370
|
+
|
|
365
371
|
# Retrieve available stations from the Metadata Archive
|
|
366
372
|
# - Raise error if no stations availables !
|
|
367
373
|
list_info = list_station_names(
|
|
368
|
-
metadata_archive_dir,
|
|
374
|
+
metadata_archive_dir=metadata_archive_dir,
|
|
369
375
|
data_sources=data_sources,
|
|
370
376
|
campaign_names=campaign_names,
|
|
371
377
|
station_names=station_names,
|
|
@@ -484,3 +490,6 @@ def available_campaigns(
|
|
|
484
490
|
campaign_names = [info[1] for info in list_info]
|
|
485
491
|
campaign_names = np.unique(campaign_names).tolist()
|
|
486
492
|
return campaign_names
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
####-------------------------------------------------------------------------
|