disdrodb 0.1.3__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 +4 -0
- disdrodb/_version.py +2 -2
- disdrodb/api/checks.py +70 -47
- disdrodb/api/configs.py +0 -2
- disdrodb/api/info.py +3 -3
- disdrodb/api/io.py +48 -8
- disdrodb/api/path.py +116 -133
- disdrodb/api/search.py +12 -3
- disdrodb/cli/disdrodb_create_summary.py +103 -0
- disdrodb/cli/disdrodb_create_summary_station.py +1 -1
- disdrodb/cli/disdrodb_run_l0a_station.py +1 -1
- disdrodb/cli/disdrodb_run_l0b_station.py +2 -2
- disdrodb/cli/disdrodb_run_l0c_station.py +2 -2
- 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/data_transfer/download_data.py +123 -7
- disdrodb/issue/writer.py +2 -0
- disdrodb/l0/l0a_processing.py +10 -5
- disdrodb/l0/l0b_nc_processing.py +10 -6
- disdrodb/l0/l0b_processing.py +26 -61
- disdrodb/l0/l0c_processing.py +369 -251
- disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +7 -0
- disdrodb/l0/readers/PARSIVEL2/ARM/ARM_PARSIVEL2.py +4 -0
- disdrodb/l0/readers/PARSIVEL2/CANADA/UQAM_NC.py +69 -0
- disdrodb/l0/readers/PARSIVEL2/MPI/BCO_PARSIVEL2.py +136 -0
- disdrodb/l0/readers/PARSIVEL2/MPI/BOWTIE.py +220 -0
- disdrodb/l0/readers/PARSIVEL2/NASA/LPVEX.py +109 -0
- disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT_NC.py +3 -0
- disdrodb/l1/fall_velocity.py +46 -0
- disdrodb/l1/processing.py +1 -1
- disdrodb/l2/processing.py +1 -1
- disdrodb/metadata/checks.py +132 -125
- disdrodb/psd/fitting.py +172 -205
- disdrodb/psd/models.py +1 -1
- disdrodb/routines/__init__.py +54 -0
- disdrodb/{l0/routines.py → routines/l0.py} +288 -418
- disdrodb/{l1/routines.py → routines/l1.py} +60 -92
- disdrodb/{l2/routines.py → routines/l2.py} +249 -462
- disdrodb/{routines.py → routines/wrappers.py} +95 -7
- disdrodb/scattering/axis_ratio.py +5 -1
- disdrodb/scattering/permittivity.py +18 -0
- disdrodb/scattering/routines.py +56 -36
- disdrodb/summary/routines.py +110 -34
- disdrodb/utils/archiving.py +434 -0
- disdrodb/utils/cli.py +5 -5
- disdrodb/utils/dask.py +62 -1
- disdrodb/utils/decorators.py +31 -0
- disdrodb/utils/encoding.py +5 -1
- disdrodb/{l2 → utils}/event.py +1 -66
- disdrodb/utils/logger.py +1 -1
- disdrodb/utils/manipulations.py +22 -12
- disdrodb/utils/routines.py +166 -0
- disdrodb/utils/time.py +3 -291
- disdrodb/utils/xarray.py +3 -0
- disdrodb/viz/plots.py +85 -14
- {disdrodb-0.1.3.dist-info → disdrodb-0.1.4.dist-info}/METADATA +2 -2
- {disdrodb-0.1.3.dist-info → disdrodb-0.1.4.dist-info}/RECORD +62 -54
- {disdrodb-0.1.3.dist-info → disdrodb-0.1.4.dist-info}/entry_points.txt +1 -0
- {disdrodb-0.1.3.dist-info → disdrodb-0.1.4.dist-info}/WHEEL +0 -0
- {disdrodb-0.1.3.dist-info → disdrodb-0.1.4.dist-info}/licenses/LICENSE +0 -0
- {disdrodb-0.1.3.dist-info → disdrodb-0.1.4.dist-info}/top_level.txt +0 -0
disdrodb/__init__.py
CHANGED
|
@@ -62,6 +62,8 @@ from disdrodb.metadata.checks import (
|
|
|
62
62
|
check_station_metadata,
|
|
63
63
|
)
|
|
64
64
|
from disdrodb.routines import (
|
|
65
|
+
create_summary,
|
|
66
|
+
create_summary_station,
|
|
65
67
|
run_l0,
|
|
66
68
|
run_l0_station,
|
|
67
69
|
run_l0a,
|
|
@@ -126,6 +128,8 @@ __all__ = [
|
|
|
126
128
|
"check_metadata_archive",
|
|
127
129
|
"check_metadata_archive_geolocation",
|
|
128
130
|
"check_station_metadata",
|
|
131
|
+
"create_summary",
|
|
132
|
+
"create_summary_station",
|
|
129
133
|
"decibel",
|
|
130
134
|
"define_configs",
|
|
131
135
|
"download_archive",
|
disdrodb/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.1.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
31
|
+
__version__ = version = '0.1.4'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 1, 4)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
disdrodb/api/checks.py
CHANGED
|
@@ -144,14 +144,14 @@ def check_measurement_intervals(measurement_intervals):
|
|
|
144
144
|
|
|
145
145
|
def check_sample_interval(sample_interval):
|
|
146
146
|
"""Check sample_interval argument validity."""
|
|
147
|
-
if not isinstance(sample_interval, int):
|
|
148
|
-
raise
|
|
147
|
+
if not isinstance(sample_interval, int) or isinstance(sample_interval, bool):
|
|
148
|
+
raise TypeError("'sample_interval' must be an integer.")
|
|
149
149
|
|
|
150
150
|
|
|
151
151
|
def check_rolling(rolling):
|
|
152
152
|
"""Check rolling argument validity."""
|
|
153
153
|
if not isinstance(rolling, bool):
|
|
154
|
-
raise
|
|
154
|
+
raise TypeError("'rolling' must be a boolean.")
|
|
155
155
|
|
|
156
156
|
|
|
157
157
|
def check_folder_partitioning(folder_partitioning):
|
|
@@ -163,12 +163,12 @@ def check_folder_partitioning(folder_partitioning):
|
|
|
163
163
|
folder_partitioning : str or None
|
|
164
164
|
Defines the subdirectory structure based on the dataset's start time.
|
|
165
165
|
Allowed values are:
|
|
166
|
-
- "": No additional subdirectories, files are saved directly in
|
|
167
|
-
- "year": Files are stored under a subdirectory for the year (<
|
|
168
|
-
- "year/month": Files are stored under subdirectories by year and month (<
|
|
169
|
-
- "year/month/day": Files are stored under subdirectories by year, month and day (<
|
|
170
|
-
- "year/month_name": Files are stored under subdirectories by year and month name (<
|
|
171
|
-
- "year/quarter": Files are stored under subdirectories by year and quarter (<
|
|
166
|
+
- "" or None: No additional subdirectories, files are saved directly in dir.
|
|
167
|
+
- "year": Files are stored under a subdirectory for the year (<dir>/2025).
|
|
168
|
+
- "year/month": Files are stored under subdirectories by year and month (<dir>/2025/04).
|
|
169
|
+
- "year/month/day": Files are stored under subdirectories by year, month and day (<dir>/2025/04/01).
|
|
170
|
+
- "year/month_name": Files are stored under subdirectories by year and month name (<dir>/2025/April).
|
|
171
|
+
- "year/quarter": Files are stored under subdirectories by year and quarter (<dir>/2025/Q2).
|
|
172
172
|
|
|
173
173
|
Returns
|
|
174
174
|
-------
|
|
@@ -176,6 +176,8 @@ def check_folder_partitioning(folder_partitioning):
|
|
|
176
176
|
The verified folder partitioning scheme.
|
|
177
177
|
"""
|
|
178
178
|
valid_options = ["", "year", "year/month", "year/month/day", "year/month_name", "year/quarter"]
|
|
179
|
+
if folder_partitioning is None:
|
|
180
|
+
folder_partitioning = ""
|
|
179
181
|
if folder_partitioning not in valid_options:
|
|
180
182
|
raise ValueError(
|
|
181
183
|
f"Invalid folder_partitioning scheme '{folder_partitioning}'. Valid options are: {valid_options}.",
|
|
@@ -331,16 +333,37 @@ def check_valid_fields(fields, available_fields, field_name, invalid_fields_poli
|
|
|
331
333
|
fields = [fields]
|
|
332
334
|
fields = np.unique(np.array(fields))
|
|
333
335
|
invalid_fields_policy = check_invalid_fields_policy(invalid_fields_policy)
|
|
336
|
+
|
|
334
337
|
# Check for invalid fields
|
|
335
338
|
fields = np.array(fields)
|
|
336
339
|
is_valid = np.isin(fields, available_fields)
|
|
337
340
|
invalid_fields_values = fields[~is_valid].tolist()
|
|
338
341
|
fields = fields[is_valid].tolist()
|
|
342
|
+
|
|
343
|
+
# If invalid fields, suggest corrections using difflib
|
|
344
|
+
if invalid_fields_values:
|
|
345
|
+
|
|
346
|
+
# Format invalid fields nicely (avoid single-element lists)
|
|
347
|
+
if len(invalid_fields_values) == 1:
|
|
348
|
+
invalid_fields_str = f"'{invalid_fields_values[0]}'"
|
|
349
|
+
else:
|
|
350
|
+
invalid_fields_str = f"{invalid_fields_values}"
|
|
351
|
+
|
|
352
|
+
# Prepare suggestion string
|
|
353
|
+
suggestions = []
|
|
354
|
+
for invalid in invalid_fields_values:
|
|
355
|
+
matches = difflib.get_close_matches(invalid, available_fields, n=1, cutoff=0.4)
|
|
356
|
+
if matches:
|
|
357
|
+
suggestions.append(f"Did you mean '{matches[0]}' instead of '{invalid}'?")
|
|
358
|
+
suggestion_msg = " " + " ".join(suggestions) if suggestions else ""
|
|
359
|
+
|
|
339
360
|
# Error handling for invalid fields were found
|
|
340
361
|
if invalid_fields_policy == "warn" and invalid_fields_values:
|
|
341
|
-
|
|
362
|
+
msg = f"Ignoring invalid {field_name}: {invalid_fields_str}.{suggestion_msg}"
|
|
363
|
+
warnings.warn(msg, UserWarning, stacklevel=2)
|
|
342
364
|
elif invalid_fields_policy == "raise" and invalid_fields_values:
|
|
343
|
-
|
|
365
|
+
msg = f"These {field_name} do not exist: {invalid_fields_str}.{suggestion_msg}"
|
|
366
|
+
raise ValueError(msg)
|
|
344
367
|
else: # "ignore" silently drop invalid entries
|
|
345
368
|
pass
|
|
346
369
|
# If no valid fields left, raise error
|
|
@@ -349,38 +372,6 @@ def check_valid_fields(fields, available_fields, field_name, invalid_fields_poli
|
|
|
349
372
|
return fields
|
|
350
373
|
|
|
351
374
|
|
|
352
|
-
def has_available_data(
|
|
353
|
-
data_source,
|
|
354
|
-
campaign_name,
|
|
355
|
-
station_name,
|
|
356
|
-
product,
|
|
357
|
-
data_archive_dir=None,
|
|
358
|
-
# Product Options
|
|
359
|
-
**product_kwargs,
|
|
360
|
-
):
|
|
361
|
-
"""Return ``True`` if data are available for the given product and station."""
|
|
362
|
-
# Define product directory
|
|
363
|
-
data_dir = define_data_dir(
|
|
364
|
-
product=product,
|
|
365
|
-
data_archive_dir=data_archive_dir,
|
|
366
|
-
data_source=data_source,
|
|
367
|
-
campaign_name=campaign_name,
|
|
368
|
-
station_name=station_name,
|
|
369
|
-
# Directory options
|
|
370
|
-
check_exists=False,
|
|
371
|
-
# Product Options
|
|
372
|
-
**product_kwargs,
|
|
373
|
-
)
|
|
374
|
-
# If the product directory does not exists, return False
|
|
375
|
-
if not os.path.isdir(data_dir):
|
|
376
|
-
return False
|
|
377
|
-
|
|
378
|
-
# If no files, return False
|
|
379
|
-
filepaths = list_files(data_dir, recursive=True)
|
|
380
|
-
nfiles = len(filepaths)
|
|
381
|
-
return nfiles >= 1
|
|
382
|
-
|
|
383
|
-
|
|
384
375
|
def check_station_inputs(
|
|
385
376
|
data_source,
|
|
386
377
|
campaign_name,
|
|
@@ -396,6 +387,7 @@ def check_station_inputs(
|
|
|
396
387
|
matches = difflib.get_close_matches(data_source, valid_data_sources, n=1, cutoff=0.4)
|
|
397
388
|
suggestion = f"Did you mean '{matches[0]}'?" if matches else ""
|
|
398
389
|
raise ValueError(f"DISDRODB does not include a data source named {data_source}. {suggestion}")
|
|
390
|
+
|
|
399
391
|
# Check campaign name
|
|
400
392
|
valid_campaigns = disdrodb.available_campaigns(data_sources=data_source, metadata_archive_dir=metadata_archive_dir)
|
|
401
393
|
if campaign_name not in valid_campaigns:
|
|
@@ -420,6 +412,38 @@ def check_station_inputs(
|
|
|
420
412
|
)
|
|
421
413
|
|
|
422
414
|
|
|
415
|
+
def has_available_data(
|
|
416
|
+
data_source,
|
|
417
|
+
campaign_name,
|
|
418
|
+
station_name,
|
|
419
|
+
product,
|
|
420
|
+
data_archive_dir=None,
|
|
421
|
+
# Product Options
|
|
422
|
+
**product_kwargs,
|
|
423
|
+
):
|
|
424
|
+
"""Return ``True`` if data are available for the given product and station."""
|
|
425
|
+
# Define product directory
|
|
426
|
+
data_dir = define_data_dir(
|
|
427
|
+
product=product,
|
|
428
|
+
data_archive_dir=data_archive_dir,
|
|
429
|
+
data_source=data_source,
|
|
430
|
+
campaign_name=campaign_name,
|
|
431
|
+
station_name=station_name,
|
|
432
|
+
# Directory options
|
|
433
|
+
check_exists=False,
|
|
434
|
+
# Product Options
|
|
435
|
+
**product_kwargs,
|
|
436
|
+
)
|
|
437
|
+
# If the product directory does not exists, return False
|
|
438
|
+
if not os.path.isdir(data_dir):
|
|
439
|
+
return False
|
|
440
|
+
|
|
441
|
+
# If no files, return False
|
|
442
|
+
filepaths = list_files(data_dir, recursive=True)
|
|
443
|
+
nfiles = len(filepaths)
|
|
444
|
+
return nfiles >= 1
|
|
445
|
+
|
|
446
|
+
|
|
423
447
|
def check_data_availability(
|
|
424
448
|
product,
|
|
425
449
|
data_source,
|
|
@@ -480,10 +504,9 @@ def check_issue_dir(data_source, campaign_name, metadata_archive_dir=None):
|
|
|
480
504
|
campaign_name=campaign_name,
|
|
481
505
|
check_exists=False,
|
|
482
506
|
)
|
|
483
|
-
if not os.path.exists(issue_dir)
|
|
484
|
-
msg = "The issue directory does not exist at {issue_dir}."
|
|
507
|
+
if not os.path.exists(issue_dir) or not os.path.isdir(issue_dir):
|
|
508
|
+
msg = f"The issue directory does not exist at {issue_dir}."
|
|
485
509
|
logger.error(msg)
|
|
486
|
-
raise ValueError(msg)
|
|
487
510
|
return issue_dir
|
|
488
511
|
|
|
489
512
|
|
|
@@ -504,7 +527,7 @@ def check_issue_file(data_source, campaign_name, station_name, metadata_archive_
|
|
|
504
527
|
station_name=station_name,
|
|
505
528
|
check_exists=False,
|
|
506
529
|
)
|
|
507
|
-
# Check existence
|
|
530
|
+
# Check existence. If not, create one !
|
|
508
531
|
if not os.path.exists(issue_filepath):
|
|
509
532
|
create_station_issue(
|
|
510
533
|
metadata_archive_dir=metadata_archive_dir,
|
disdrodb/api/configs.py
CHANGED
|
@@ -54,8 +54,6 @@ def get_sensor_configs_dir(sensor_name: str, product: str) -> str:
|
|
|
54
54
|
config_dir = define_config_dir(product=product)
|
|
55
55
|
config_sensor_dir = os.path.join(config_dir, sensor_name)
|
|
56
56
|
if not os.path.exists(config_sensor_dir):
|
|
57
|
-
list_sensors = sorted(list_directories(config_dir, recursive=False, return_paths=False))
|
|
58
|
-
print(f"Available sensor_name are {list_sensors}")
|
|
59
57
|
raise ValueError(f"The config directory {config_sensor_dir} does not exist.")
|
|
60
58
|
return config_sensor_dir
|
|
61
59
|
|
disdrodb/api/info.py
CHANGED
|
@@ -410,8 +410,8 @@ def get_time_component(time, component):
|
|
|
410
410
|
return str(func_dict[component](time))
|
|
411
411
|
|
|
412
412
|
|
|
413
|
-
def
|
|
414
|
-
"""Return
|
|
413
|
+
def get_groups_value(groups, filepath):
|
|
414
|
+
"""Return a string associated to the groups keys.
|
|
415
415
|
|
|
416
416
|
If multiple keys are specified, the value returned is a string of format: ``<group_value_1>/<group_value_2>/...``
|
|
417
417
|
|
|
@@ -463,5 +463,5 @@ def group_filepaths(filepaths, groups=None):
|
|
|
463
463
|
return filepaths
|
|
464
464
|
groups = check_groups(groups)
|
|
465
465
|
filepaths_dict = defaultdict(list)
|
|
466
|
-
_ = [filepaths_dict[
|
|
466
|
+
_ = [filepaths_dict[get_groups_value(groups, filepath)].append(filepath) for filepath in filepaths]
|
|
467
467
|
return dict(filepaths_dict)
|
disdrodb/api/io.py
CHANGED
|
@@ -133,6 +133,7 @@ def find_files(
|
|
|
133
133
|
product,
|
|
134
134
|
debugging_mode: bool = False,
|
|
135
135
|
data_archive_dir: Optional[str] = None,
|
|
136
|
+
metadata_archive_dir: Optional[str] = None,
|
|
136
137
|
glob_pattern=None,
|
|
137
138
|
start_time=None,
|
|
138
139
|
end_time=None,
|
|
@@ -198,6 +199,7 @@ def find_files(
|
|
|
198
199
|
data_source=data_source,
|
|
199
200
|
campaign_name=campaign_name,
|
|
200
201
|
station_name=station_name,
|
|
202
|
+
metadata_archive_dir=metadata_archive_dir,
|
|
201
203
|
)
|
|
202
204
|
glob_pattern = metadata.get("raw_data_glob_pattern", "")
|
|
203
205
|
|
|
@@ -232,7 +234,7 @@ def find_files(
|
|
|
232
234
|
#### DISDRODB Open Product Files
|
|
233
235
|
|
|
234
236
|
|
|
235
|
-
def
|
|
237
|
+
def _open_raw_files(filepaths, data_source, campaign_name, station_name, metadata_archive_dir):
|
|
236
238
|
"""Open raw files to DISDRODB L0A or L0B format.
|
|
237
239
|
|
|
238
240
|
Raw text files are opened into a DISDRODB L0A pandas Dataframe.
|
|
@@ -247,6 +249,7 @@ def open_raw_files(filepaths, data_source, campaign_name, station_name):
|
|
|
247
249
|
data_source=data_source,
|
|
248
250
|
campaign_name=campaign_name,
|
|
249
251
|
station_name=station_name,
|
|
252
|
+
metadata_archive_dir=metadata_archive_dir,
|
|
250
253
|
)
|
|
251
254
|
sensor_name = metadata["sensor_name"]
|
|
252
255
|
|
|
@@ -256,6 +259,7 @@ def open_raw_files(filepaths, data_source, campaign_name, station_name):
|
|
|
256
259
|
data_source=data_source,
|
|
257
260
|
campaign_name=campaign_name,
|
|
258
261
|
station_name=station_name,
|
|
262
|
+
metadata_archive_dir=metadata_archive_dir,
|
|
259
263
|
)
|
|
260
264
|
except Exception:
|
|
261
265
|
issue_dict = None
|
|
@@ -265,6 +269,7 @@ def open_raw_files(filepaths, data_source, campaign_name, station_name):
|
|
|
265
269
|
data_source=data_source,
|
|
266
270
|
campaign_name=campaign_name,
|
|
267
271
|
station_name=station_name,
|
|
272
|
+
metadata_archive_dir=metadata_archive_dir,
|
|
268
273
|
)
|
|
269
274
|
# Return DISDRODB L0A dataframe if raw text files
|
|
270
275
|
if metadata["raw_data_format"] == "txt":
|
|
@@ -289,6 +294,35 @@ def open_raw_files(filepaths, data_source, campaign_name, station_name):
|
|
|
289
294
|
return ds
|
|
290
295
|
|
|
291
296
|
|
|
297
|
+
def filter_dataset_by_time(ds, start_time=None, end_time=None):
|
|
298
|
+
"""Subset an xarray.Dataset by time, robust to duplicated/non-monotonic indices.
|
|
299
|
+
|
|
300
|
+
NOTE: ds.sel(time=slice(start_time, end_time)) fails in presence of duplicated
|
|
301
|
+
timesteps because time 'index is not monotonic increasing or decreasing'.
|
|
302
|
+
|
|
303
|
+
Parameters
|
|
304
|
+
----------
|
|
305
|
+
ds : xr.Dataset
|
|
306
|
+
Dataset with a `time` coordinate.
|
|
307
|
+
start_time : np.datetime64 or None
|
|
308
|
+
Inclusive start bound. If None, no lower bound is applied.
|
|
309
|
+
end_time : np.datetime64 or None
|
|
310
|
+
Inclusive end bound. If None, no upper bound is applied.
|
|
311
|
+
|
|
312
|
+
Returns
|
|
313
|
+
-------
|
|
314
|
+
xr.Dataset
|
|
315
|
+
Subset dataset with the same ordering of timesteps (duplicates preserved).
|
|
316
|
+
"""
|
|
317
|
+
time = ds["time"].to_numpy()
|
|
318
|
+
mask = np.ones(time.shape, dtype=bool)
|
|
319
|
+
if start_time is not None:
|
|
320
|
+
mask &= time >= np.array(start_time, dtype="datetime64[ns]")
|
|
321
|
+
if end_time is not None:
|
|
322
|
+
mask &= time <= np.array(end_time, dtype="datetime64[ns]")
|
|
323
|
+
return ds.isel(time=np.where(mask)[0])
|
|
324
|
+
|
|
325
|
+
|
|
292
326
|
def open_netcdf_files(
|
|
293
327
|
filepaths,
|
|
294
328
|
chunks=-1,
|
|
@@ -299,7 +333,10 @@ def open_netcdf_files(
|
|
|
299
333
|
compute=True,
|
|
300
334
|
**open_kwargs,
|
|
301
335
|
):
|
|
302
|
-
"""Open DISDRODB netCDF files using xarray.
|
|
336
|
+
"""Open DISDRODB netCDF files using xarray.
|
|
337
|
+
|
|
338
|
+
Using combine="nested" and join="outer" ensure that duplicated timesteps are not overwritten!
|
|
339
|
+
"""
|
|
303
340
|
import xarray as xr
|
|
304
341
|
|
|
305
342
|
# Ensure variables is a list
|
|
@@ -313,6 +350,7 @@ def open_netcdf_files(
|
|
|
313
350
|
filepaths,
|
|
314
351
|
chunks=chunks,
|
|
315
352
|
combine="nested",
|
|
353
|
+
join="outer",
|
|
316
354
|
concat_dim="time",
|
|
317
355
|
engine="netcdf4",
|
|
318
356
|
parallel=parallel,
|
|
@@ -329,7 +367,8 @@ def open_netcdf_files(
|
|
|
329
367
|
if variables is not None and preprocess is None:
|
|
330
368
|
ds = ds[variables]
|
|
331
369
|
# - Subset time
|
|
332
|
-
|
|
370
|
+
if start_time is not None or end_time is not None:
|
|
371
|
+
ds = filter_dataset_by_time(ds, start_time=start_time, end_time=end_time)
|
|
333
372
|
# - If compute=True, load in memory and close connections to files
|
|
334
373
|
if compute:
|
|
335
374
|
dataset = ds.compute()
|
|
@@ -349,6 +388,7 @@ def open_dataset(
|
|
|
349
388
|
product_kwargs=None,
|
|
350
389
|
debugging_mode: bool = False,
|
|
351
390
|
data_archive_dir: Optional[str] = None,
|
|
391
|
+
metadata_archive_dir: Optional[str] = None,
|
|
352
392
|
chunks=-1,
|
|
353
393
|
parallel=False,
|
|
354
394
|
compute=False,
|
|
@@ -399,6 +439,7 @@ def open_dataset(
|
|
|
399
439
|
# List product files
|
|
400
440
|
filepaths = find_files(
|
|
401
441
|
data_archive_dir=data_archive_dir,
|
|
442
|
+
metadata_archive_dir=metadata_archive_dir,
|
|
402
443
|
data_source=data_source,
|
|
403
444
|
campaign_name=campaign_name,
|
|
404
445
|
station_name=station_name,
|
|
@@ -413,11 +454,12 @@ def open_dataset(
|
|
|
413
454
|
# - For raw txt files return DISDRODB L0A dataframe
|
|
414
455
|
# - For raw netCDF files return DISDRODB L0B dataframe
|
|
415
456
|
if product == "RAW":
|
|
416
|
-
obj =
|
|
457
|
+
obj = _open_raw_files(
|
|
417
458
|
filepaths=filepaths,
|
|
418
459
|
data_source=data_source,
|
|
419
460
|
campaign_name=campaign_name,
|
|
420
461
|
station_name=station_name,
|
|
462
|
+
metadata_archive_dir=metadata_archive_dir,
|
|
421
463
|
)
|
|
422
464
|
return obj
|
|
423
465
|
|
|
@@ -464,11 +506,9 @@ def remove_product(
|
|
|
464
506
|
station_name=station_name,
|
|
465
507
|
**product_kwargs,
|
|
466
508
|
)
|
|
467
|
-
|
|
468
|
-
log_info(logger=logger, msg="Removal of {product} files started.", verbose=verbose)
|
|
509
|
+
log_info(logger=logger, msg="Removal of {product} files started.", verbose=verbose)
|
|
469
510
|
shutil.rmtree(data_dir)
|
|
470
|
-
|
|
471
|
-
log_info(logger=logger, msg="Removal of {product} files ended.", verbose=verbose)
|
|
511
|
+
log_info(logger=logger, msg="Removal of {product} files ended.", verbose=verbose)
|
|
472
512
|
|
|
473
513
|
|
|
474
514
|
####--------------------------------------------------------------------------.
|