• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ltelab / disdrodb / 12256475606

10 Dec 2024 12:50PM UTC coverage: 64.762% (-31.6%) from 96.4%
12256475606

Pull #220

github

web-flow
Merge de09ad97a into d970f7f09
Pull Request #220: Add routines for L1 and L2 processing

731 of 2610 new or added lines in 57 files covered. (28.01%)

93 existing lines in 2 files now uncovered.

3865 of 5968 relevant lines covered (64.76%)

0.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

52.05
/disdrodb/api/path.py
1
#!/usr/bin/env python3
2

3
# -----------------------------------------------------------------------------.
4
# Copyright (c) 2021-2023 DISDRODB developers
5
#
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
# -----------------------------------------------------------------------------.
19
"""Define paths within the DISDRODB infrastructure."""
20

21
import os
1✔
22

23
import pandas as pd
1✔
24

25
from disdrodb.configs import get_base_dir
1✔
26
from disdrodb.utils.directories import check_directory_exists
1✔
27

28
####--------------------------------------------------------------------------.
29
#### Paths from BASE_DIR
30

31

32
def get_disdrodb_path(
1✔
33
    base_dir,
34
    product,
35
    data_source="",
36
    campaign_name="",
37
    check_exists=True,
38
):
39
    """Return the directory in the DISDRODB infrastructure.
40

41
    If ``data_source`` and ``campaign_name`` are not specified it return the product directory.
42

43
    If ``data_source`` is specified, it returns the ``data_source`` directory.
44

45
    If ``campaign_source`` is specified, it returns the ``campaign_name`` directory.
46

47
    Parameters
48
    ----------
49
    base_dir : str
50
        The disdrodb base directory
51
    product : str
52
        The DISDRODB product. It can be ``"RAW"``, ``"L0A"``, or ``"L0B"``.
53
    data_source : str, optional
54
        The data source. Must be specified if ``campaign_name`` is specified.
55
    campaign_name : str, optional
56
        The campaign name.
57
    check_exists : bool, optional
58
        Whether to check if the directory exists. By default ``True``.
59

60
    Returns
61
    -------
62
    dir_path : str
63
        Directory path
64
    """
65
    from disdrodb.api.checks import check_base_dir
1✔
66

67
    # Check base_dir validity
68
    base_dir = check_base_dir(base_dir)
1✔
69
    if len(campaign_name) > 0 and len(data_source) == 0:
1✔
70
        raise ValueError("If campaign_name is specified, data_source must be specified.")
×
71

72
    # Get directory
73
    if product.upper() == "RAW":
1✔
74
        dir_path = os.path.join(base_dir, "Raw", data_source, campaign_name)
1✔
75
    else:
76
        dir_path = os.path.join(base_dir, "Processed", data_source, campaign_name)
1✔
77
    if check_exists:
1✔
78
        check_directory_exists(dir_path)
1✔
79
    return dir_path
1✔
80

81

82
def define_campaign_dir(
1✔
83
    product,
84
    data_source,
85
    campaign_name,
86
    base_dir=None,
87
    check_exists=False,
88
):
89
    """Return the campaign directory in the DISDRODB infrastructure.
90

91
    Parameters
92
    ----------
93
    product : str
94
        The DISDRODB product. It can be ``"RAW"``, ``"L0A"``, or ``"L0B"``.
95
    data_source : str
96
        The data source. Must be specified if ``campaign_name`` is specified.
97
    campaign_name : str
98
        The campaign name.
99
    base_dir : str, optional
100
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
101
        If not specified, the path specified in the DISDRODB active configuration will be used.
102
    check_exists : bool, optional
103
        Whether to check if the directory exists. By default ``False``.
104

105
    Returns
106
    -------
107
    station_dir : str
108
        Station data directory path
109
    """
110
    base_dir = get_base_dir(base_dir)
1✔
111
    campaign_dir = get_disdrodb_path(
1✔
112
        base_dir=base_dir,
113
        product=product,
114
        data_source=data_source,
115
        campaign_name=campaign_name,
116
        check_exists=check_exists,
117
    )
118
    return str(campaign_dir)
1✔
119

120

121
def define_metadata_dir(
1✔
122
    product,
123
    data_source,
124
    campaign_name,
125
    base_dir=None,
126
    check_exists=False,
127
):
128
    """Return the metadata directory in the DISDRODB infrastructure.
129

130
    Parameters
131
    ----------
132
    product : str
133
        The DISDRODB product. It can be ``"RAW"``, ``"L0A"``, or ``"L0B"``.
134
    data_source : str
135
        The data source.
136
    campaign_name : str
137
        The campaign name.
138
    base_dir : str, optional
139
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
140
        If not specified, the path specified in the DISDRODB active configuration will be used.
141
    check_exists : bool, optional
142
        Whether to check if the directory exists. By default ``False``.
143

144
    Returns
145
    -------
146
    metadata_dir : str
147
        Station data directory path
148
    """
149
    base_dir = get_base_dir(base_dir)
1✔
150
    campaign_dir = define_campaign_dir(
1✔
151
        base_dir=base_dir,
152
        product=product,
153
        data_source=data_source,
154
        campaign_name=campaign_name,
155
        check_exists=check_exists,
156
    )
157
    metadata_dir = os.path.join(campaign_dir, "metadata")
1✔
158
    if check_exists:
1✔
159
        check_directory_exists(metadata_dir)
×
160
    return str(metadata_dir)
1✔
161

162

163
def define_issue_dir(
1✔
164
    data_source,
165
    campaign_name,
166
    base_dir=None,
167
    check_exists=False,
168
):
169
    """Return the issue directory in the DISDRODB infrastructure.
170

171
    Parameters
172
    ----------
173
    data_source : str
174
        The data source.
175
    campaign_name : str
176
        The campaign name.
177
    base_dir : str, optional
178
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
179
        If not specified, the path specified in the DISDRODB active configuration will be used.
180
    check_exists : bool, optional
181
        Whether to check if the directory exists. By default ``False``.
182

183
    Returns
184
    -------
185
    issue_dir : str
186
        Station data directory path
187
    """
188
    base_dir = get_base_dir(base_dir)
1✔
189
    campaign_dir = define_campaign_dir(
1✔
190
        base_dir=base_dir,
191
        product="RAW",
192
        data_source=data_source,
193
        campaign_name=campaign_name,
194
        check_exists=check_exists,
195
    )
196
    issue_dir = os.path.join(campaign_dir, "issue")
1✔
197
    if check_exists:
1✔
198
        check_directory_exists(issue_dir)
×
199
    return str(issue_dir)
1✔
200

201

202
def define_metadata_filepath(
1✔
203
    product,
204
    data_source,
205
    campaign_name,
206
    station_name,
207
    base_dir=None,
208
    check_exists=False,
209
):
210
    """Return the station metadata filepath in the DISDRODB infrastructure.
211

212
    Parameters
213
    ----------
214
    product : str
215
        The DISDRODB product. It can be "RAW", "L0A", or "L0B".
216
    data_source : str
217
        The data source.
218
    campaign_name : str
219
        The campaign name.
220
    station_name : str
221
        The station name.
222
    base_dir : str, optional
223
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
224
        If not specified, the path specified in the DISDRODB active configuration will be used.
225
    check_exists : bool, optional
226
        Whether to check if the directory exists. By default ``False``.
227

228
    Returns
229
    -------
230
    metadata_dir : str
231
        Station data directory path
232
    """
233
    base_dir = get_base_dir(base_dir)
1✔
234
    metadata_dir = define_metadata_dir(
1✔
235
        base_dir=base_dir,
236
        product=product,
237
        data_source=data_source,
238
        campaign_name=campaign_name,
239
        check_exists=False,
240
    )
241
    metadata_filepath = os.path.join(metadata_dir, f"{station_name}.yml")
1✔
242
    if check_exists and not os.path.exists(metadata_filepath):
1✔
243
        raise ValueError(f"The metadata file for {station_name} at {metadata_filepath} does not exists.")
×
244

245
    return str(metadata_filepath)
1✔
246

247

248
def define_issue_filepath(
1✔
249
    data_source,
250
    campaign_name,
251
    station_name,
252
    base_dir=None,
253
    check_exists=False,
254
):
255
    """Return the station issue filepath in the DISDRODB infrastructure.
256

257
    Parameters
258
    ----------
259
    data_source : str
260
        The data source.
261
    campaign_name : str
262
        The campaign name.
263
    station_name : str
264
        The station name.
265
    base_dir : str, optional
266
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
267
        If not specified, the path specified in the DISDRODB active configuration will be used.
268
    check_exists : bool, optional
269
        Whether to check if the directory exists. By default ``False``.
270

271
    Returns
272
    -------
273
    issue_dir : str
274
        Station data directory path
275
    """
276
    base_dir = get_base_dir(base_dir)
1✔
277
    issue_dir = define_issue_dir(
1✔
278
        base_dir=base_dir,
279
        data_source=data_source,
280
        campaign_name=campaign_name,
281
        check_exists=False,
282
    )
283
    issue_filepath = os.path.join(issue_dir, f"{station_name}.yml")
1✔
284
    if check_exists and not os.path.exists(issue_filepath):
1✔
285
        raise ValueError(f"The issue file for {station_name} at {issue_filepath} does not exists.")
×
286

287
    return str(issue_filepath)
1✔
288

289

290
def define_config_dir(product):
1✔
291
    """Define the config directory path of a given DISDRODB product."""
292
    from disdrodb import __root_path__
1✔
293

294
    if product.upper() in ["RAW", "L0A", "L0B"]:
1✔
295
        dir_name = "l0"
1✔
296
    else:
297
        raise NotImplementedError(f"Product {product} not implemented.")
×
298
    config_dir = os.path.join(__root_path__, "disdrodb", dir_name, "configs")
1✔
299
    return config_dir
1✔
300

301

302
####--------------------------------------------------------------------------.
303
#### Directory/Filepaths L0A and L0B products
304

305

306
def check_sample_interval(sample_interval):
1✔
307
    """Check sample_interval argument validity."""
NEW
308
    if not isinstance(sample_interval, int):
×
NEW
309
        raise ValueError("'sample_interval' must be an integer.")
×
310

311

312
def check_distribution(distribution):
1✔
313
    """Check distribution argument validity."""
NEW
314
    valid_distributions = ["gamma", "normalized_gamma", "lognormal", "exponential"]
×
NEW
315
    if distribution not in valid_distributions:
×
NEW
316
        raise ValueError(f"Invalid 'distribution' {distribution}. Valid values are {valid_distributions}")
×
317

318

319
def check_rolling(rolling):
1✔
320
    """Check rolling argument validity."""
NEW
321
    if not isinstance(rolling, bool):
×
NEW
322
        raise ValueError("'rolling' must be a boolean.")
×
323

324

325
def define_product_dir_tree(
1✔
326
    product,
327
    distribution=None,
328
    sample_interval=None,
329
    rolling=None,
330
):
331
    """Return the product directory tree.
332

333
    Parameters
334
    ----------
335
    product : str
336
        The DISDRODB product. It can be ``"RAW"``, ``"L0A"``, or ``"L0B"``.
337
    sample_interval : int, optional
338
        The sampling interval in seconds of the product.
339
        It must be specified only for product L2E and L2M !
340
    rolling : bool, optional
341
        Whether the dataset has been resampled by aggregating or rolling.
342
        It must be specified only for product L2E and L2M !
343
    distribution : str
344
        The model of the statistical distribution for the DSD.
345
        It must be specified only for product L2M !
346

347
    Returns
348
    -------
349
    data_dir : str
350
        Station data directory path
351
    """
352
    if product.upper() == "RAW":
1✔
NEW
353
        return ""
×
354
    if product.upper() in ["L0A", "L0B", "L0C", "L1"]:
1✔
355
        return product
1✔
NEW
356
    if product == "L2E":
×
NEW
357
        check_rolling(rolling)
×
NEW
358
        check_sample_interval(sample_interval)
×
NEW
359
        sample_interval_acronym = get_sample_interval_acronym(seconds=sample_interval, rolling=rolling)
×
NEW
360
        return os.path.join(product, sample_interval_acronym)
×
NEW
361
    if product == "L2M":
×
NEW
362
        check_rolling(rolling)
×
NEW
363
        check_sample_interval(sample_interval)
×
NEW
364
        check_distribution(distribution)
×
NEW
365
        sample_interval_acronym = get_sample_interval_acronym(seconds=sample_interval, rolling=rolling)
×
NEW
366
        distribution_acronym = get_distribution_acronym(distribution)
×
NEW
367
        return os.path.join(product, distribution_acronym, sample_interval_acronym)
×
NEW
368
    raise ValueError(f"The product {product} is not defined.")
×
369

370

371
def define_station_dir_new(
1✔
372
    product,
373
    data_source,
374
    campaign_name,
375
    station_name,
376
    base_dir=None,
377
    check_exists=False,
378
):  # TODO: IN FUTURE without product --> campaign_dir/station_name/product !
379
    """Return the station data directory in the DISDRODB infrastructure.
380

381
    Parameters
382
    ----------
383
    product : str
384
        The DISDRODB product. It can be ``"RAW"``, ``"L0A"``, or ``"L0B"``.
385
    data_source : str
386
        The data source.
387
    campaign_name : str
388
        The campaign name.
389
    station_name : str
390
        The station name.
391
    base_dir : str, optional
392
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
393
        If not specified, the path specified in the DISDRODB active configuration will be used.
394
    check_exists : bool, optional
395
        Whether to check if the directory exists. By default ``False``.
396

397
    Returns
398
    -------
399
    station_dir : str
400
        Station data directory path
401
    """
NEW
402
    base_dir = get_base_dir(base_dir)
×
NEW
403
    campaign_dir = get_disdrodb_path(
×
404
        base_dir=base_dir,
405
        product=product,
406
        data_source=data_source,
407
        campaign_name=campaign_name,
408
        check_exists=check_exists,
409
    )
NEW
410
    if product.upper() == "RAW":
×
NEW
411
        station_dir = os.path.join(campaign_dir, "data", station_name)
×
412
    else:
NEW
413
        station_dir = os.path.join(campaign_dir, station_name, "data")
×
NEW
414
    if check_exists:
×
NEW
415
        check_directory_exists(station_dir)
×
NEW
416
    return str(station_dir)
×
417

418

419
def define_data_dir_new(
1✔
420
    product,
421
    data_source,
422
    campaign_name,
423
    station_name,
424
    distribution=None,
425
    sample_interval=None,
426
    rolling=None,
427
    base_dir=None,
428
    check_exists=False,
429
):
430
    """Return the station data directory in the DISDRODB infrastructure.
431

432
    Parameters
433
    ----------
434
    product : str
435
        The DISDRODB product. It can be ``"RAW"``, ``"L0A"``, or ``"L0B"``.
436
    data_source : str
437
        The data source.
438
    campaign_name : str
439
        The campaign name.
440
    station_name : str
441
        The station name.
442
    base_dir : str, optional
443
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
444
        If not specified, the path specified in the DISDRODB active configuration will be used.
445
    check_exists : bool, optional
446
        Whether to check if the directory exists. By default ``False``.
447

448
    Returns
449
    -------
450
    station_dir : str
451
        Station data directory path
452
    """
NEW
453
    station_dir = define_station_dir_new(
×
454
        base_dir=base_dir,
455
        product=product,
456
        data_source=data_source,
457
        campaign_name=campaign_name,
458
        station_name=station_name,
459
        check_exists=check_exists,
460
    )
NEW
461
    product_dir_tree = define_product_dir_tree(
×
462
        product=product,
463
        distribution=distribution,
464
        sample_interval=sample_interval,
465
        rolling=rolling,
466
    )
NEW
467
    data_dir = os.path.join(station_dir, product_dir_tree)
×
NEW
468
    if check_exists:
×
NEW
469
        check_directory_exists(data_dir)
×
NEW
470
    return str(data_dir)
×
471

472

473
def define_logs_dir(
1✔
474
    product,
475
    data_source,
476
    campaign_name,
477
    station_name,
478
    distribution=None,
479
    sample_interval=None,
480
    rolling=None,
481
    base_dir=None,
482
    check_exists=False,
483
):
484
    """Return the station log directory in the DISDRODB infrastructure.
485

486
    Parameters
487
    ----------
488
    product : str
489
        The DISDRODB product. It can be ``"RAW"``, ``"L0A"``, or ``"L0B"``.
490
    data_source : str
491
        The data source.
492
    campaign_name : str
493
        The campaign name.
494
    station_name : str
495
        The station name.
496
    base_dir : str, optional
497
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
498
        If not specified, the path specified in the DISDRODB active configuration will be used.
499
    check_exists : bool, optional
500
        Whether to check if the directory exists. By default ``False``.
501

502
    Returns
503
    -------
504
    station_dir : str
505
        Station data directory path
506
    """
507
    # station_dir = define_station_dir_new(
508
    #     base_dir=base_dir,
509
    #     product=product,
510
    #     data_source=data_source,
511
    #     campaign_name=campaign_name,
512
    #     check_exists=check_exists,
513
    # )
514
    campaign_dir = define_campaign_dir(
1✔
515
        base_dir=base_dir,
516
        product=product,
517
        data_source=data_source,
518
        campaign_name=campaign_name,
519
        check_exists=check_exists,
520
    )
521
    product_dir_tree = define_product_dir_tree(
1✔
522
        product=product,
523
        distribution=distribution,
524
        sample_interval=sample_interval,
525
        rolling=rolling,
526
    )
527
    logs_dir = os.path.join(campaign_dir, "logs", product_dir_tree, station_name)
1✔
528
    if check_exists:
1✔
NEW
529
        check_directory_exists(logs_dir)
×
530
    return str(logs_dir)
1✔
531

532

533
def define_data_dir(
1✔
534
    product,
535
    data_source,
536
    campaign_name,
537
    station_name,
538
    distribution=None,
539
    sample_interval=None,
540
    rolling=None,
541
    base_dir=None,
542
    check_exists=False,
543
):
544
    """Return the station data directory in the DISDRODB infrastructure.
545

546
    Parameters
547
    ----------
548
    product : str
549
        The DISDRODB product. It can be ``"RAW"``, ``"L0A"``, or ``"L0B"``.
550
    data_source : str
551
        The data source.
552
    campaign_name : str
553
        The campaign name.
554
    station_name : str
555
        The station name.
556
    base_dir : str, optional
557
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
558
        If not specified, the path specified in the DISDRODB active configuration will be used.
559
    check_exists : bool, optional
560
        Whether to check if the directory exists. By default ``False``.
561
    sample_interval : int, optional
562
        The sampling interval in seconds of the product.
563
        It must be specified only for product L2E and L2M !
564
    rolling : bool, optional
565
        Whether the dataset has been resampled by aggregating or rolling.
566
        It must be specified only for product L2E and L2M !
567
    distribution : str
568
        The model of the statistical distribution for the DSD.
569
        It must be specified only for product L2M !
570

571
    Returns
572
    -------
573
    data_dir : str
574
        Station data directory path
575
    """
576
    station_dir = define_station_dir(
1✔
577
        base_dir=base_dir,
578
        product=product,
579
        data_source=data_source,
580
        campaign_name=campaign_name,
581
        station_name=station_name,
582
        check_exists=check_exists,
583
    )
584
    if product.upper() in ["RAW", "L0A", "L0B", "L0C", "L1"]:
1✔
585
        data_dir = station_dir
1✔
NEW
586
    elif product == "L2E":
×
NEW
587
        check_rolling(rolling)
×
NEW
588
        check_sample_interval(sample_interval)
×
NEW
589
        sample_interval_acronym = get_sample_interval_acronym(seconds=sample_interval, rolling=rolling)
×
NEW
590
        data_dir = os.path.join(station_dir, sample_interval_acronym)
×
NEW
591
    elif product == "L2M":
×
NEW
592
        check_rolling(rolling)
×
NEW
593
        check_sample_interval(sample_interval)
×
NEW
594
        check_distribution(distribution)
×
NEW
595
        sample_interval_acronym = get_sample_interval_acronym(seconds=sample_interval, rolling=rolling)
×
NEW
596
        distribution_acronym = get_distribution_acronym(distribution)
×
NEW
597
        data_dir = os.path.join(station_dir, distribution_acronym, sample_interval_acronym)
×
598
    else:
NEW
599
        raise ValueError("TODO")  # CHECK Product on top !`
×
600
    if check_exists:
1✔
NEW
601
        check_directory_exists(data_dir)
×
602
    return str(data_dir)
1✔
603

604

605
def define_product_dir(campaign_dir: str, product: str) -> str:
1✔
606
    """Define product directory."""
607
    # TODO: this currently only works for L0A and L0B. Should be removed !
608
    # - Raw: <campaign>/data/<...>
609
    # - Processed: <campaign>/L0A/L0B>
610
    if product.upper() == "RAW":
1✔
611
        product_dir = os.path.join(campaign_dir, "data")
1✔
612
    else:
613
        product_dir = os.path.join(campaign_dir, product)
1✔
614
    return product_dir
1✔
615

616

617
def define_station_dir(
1✔
618
    product,
619
    data_source,
620
    campaign_name,
621
    station_name,
622
    base_dir=None,
623
    check_exists=False,
624
):  # TODO: IN FUTURE without product --> campaign_dir/station_name/product !
625
    """Return the station data directory in the DISDRODB infrastructure.
626

627
    Parameters
628
    ----------
629
    product : str
630
        The DISDRODB product. It can be ``"RAW"``, ``"L0A"``, or ``"L0B"``.
631
    data_source : str
632
        The data source.
633
    campaign_name : str
634
        The campaign name.
635
    station_name : str
636
        The station name.
637
    base_dir : str, optional
638
        The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
639
        If not specified, the path specified in the DISDRODB active configuration will be used.
640
    check_exists : bool, optional
641
        Whether to check if the directory exists. By default ``False``.
642

643
    Returns
644
    -------
645
    station_dir : str
646
        Station data directory path
647
    """
648
    base_dir = get_base_dir(base_dir)
1✔
649
    campaign_dir = get_disdrodb_path(
1✔
650
        base_dir=base_dir,
651
        product=product,
652
        data_source=data_source,
653
        campaign_name=campaign_name,
654
        check_exists=check_exists,
655
    )
656
    if product.upper() == "RAW":
1✔
657
        station_dir = os.path.join(campaign_dir, "data", station_name)
1✔
658
    else:
659
        station_dir = os.path.join(campaign_dir, product, station_name)
1✔
660
    if check_exists:
1✔
NEW
661
        check_directory_exists(station_dir)
×
662
    return str(station_dir)
1✔
663

664

665
####--------------------------------------------------------------------------.
666
#### Filenames for DISDRODB products
667

668

669
def define_l0a_filename(df, campaign_name: str, station_name: str) -> str:
1✔
670
    """Define L0A file name.
671

672
    Parameters
673
    ----------
674
    df : pandas.DataFrame
675
        L0A DataFrame.
676
    campaign_name : str
677
        Name of the campaign.
678
    station_name : str
679
        Name of the station.
680

681
    Returns
682
    -------
683
    str
684
        L0A file name.
685
    """
686
    from disdrodb import PRODUCT_VERSION
1✔
687
    from disdrodb.utils.pandas import get_dataframe_start_end_time
1✔
688

689
    starting_time, ending_time = get_dataframe_start_end_time(df)
1✔
690
    starting_time = pd.to_datetime(starting_time).strftime("%Y%m%d%H%M%S")
1✔
691
    ending_time = pd.to_datetime(ending_time).strftime("%Y%m%d%H%M%S")
1✔
692
    version = PRODUCT_VERSION
1✔
693
    filename = f"L0A.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.parquet"
1✔
694
    return filename
1✔
695

696

697
def define_l0b_filename(ds, campaign_name: str, station_name: str) -> str:
1✔
698
    """Define L0B file name.
699

700
    Parameters
701
    ----------
702
    ds  : xarray.Dataset
703
        L0B xarray Dataset.
704
    campaign_name : str
705
        Name of the campaign.
706
    station_name : str
707
        Name of the station.
708

709
    Returns
710
    -------
711
    str
712
        L0B file name.
713
    """
714
    from disdrodb import PRODUCT_VERSION
1✔
715
    from disdrodb.utils.xarray import get_dataset_start_end_time
1✔
716

717
    starting_time, ending_time = get_dataset_start_end_time(ds)
1✔
718
    starting_time = pd.to_datetime(starting_time).strftime("%Y%m%d%H%M%S")
1✔
719
    ending_time = pd.to_datetime(ending_time).strftime("%Y%m%d%H%M%S")
1✔
720
    version = PRODUCT_VERSION
1✔
721
    filename = f"L0B.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
1✔
722
    return filename
1✔
723

724

725
def define_l0c_filename(ds, campaign_name: str, station_name: str) -> str:
1✔
726
    """Define L0C file name.
727

728
    Parameters
729
    ----------
730
    ds  : xarray.Dataset
731
        L0B xarray Dataset
732
    campaign_name : str
733
        Name of the campaign
734
    station_name : str
735
        Name of the station
736

737
    Returns
738
    -------
739
    str
740
        L0B file name.
741
    """
742
    from disdrodb import PRODUCT_VERSION
1✔
743
    from disdrodb.utils.xarray import get_dataset_start_end_time
1✔
744

745
    starting_time, ending_time = get_dataset_start_end_time(ds)
1✔
746
    starting_time = pd.to_datetime(starting_time).strftime("%Y%m%d%H%M%S")
1✔
747
    ending_time = pd.to_datetime(ending_time).strftime("%Y%m%d%H%M%S")
1✔
748
    version = PRODUCT_VERSION
1✔
749
    filename = f"L0C.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
1✔
750
    return filename
1✔
751

752

753
def get_distribution_acronym(distribution):
1✔
754
    """Define DISDRODB L2M distribution acronym."""
NEW
755
    acronym_dict = {
×
756
        "lognorm": "LOGNORM",
757
        "normalized_gamma": "NGAMMA",
758
        "gamma": "GAMMA",
759
        "exponential": "EXP",
760
    }
NEW
761
    return acronym_dict[distribution]
×
762

763

764
def get_sample_interval_acronym(seconds, rolling=False):
1✔
765
    """
766
    Convert a duration in seconds to a readable string format (e.g., "1H30", "1D2H").
767

768
    Parameters
769
    ----------
770
    - seconds (int): The time duration in seconds.
771

772
    Returns
773
    -------
774
    - str: The duration as a string in a format like "30S", "1MIN30S", "1H30MIN", or "1D2H".
775
    """
NEW
776
    timedelta = pd.Timedelta(seconds=seconds)
×
NEW
777
    components = timedelta.components
×
778

NEW
779
    parts = []
×
NEW
780
    if components.days > 0:
×
NEW
781
        parts.append(f"{components.days}D")
×
NEW
782
    if components.hours > 0:
×
NEW
783
        parts.append(f"{components.hours}H")
×
NEW
784
    if components.minutes > 0:
×
NEW
785
        parts.append(f"{components.minutes}MIN")
×
NEW
786
    if components.seconds > 0:
×
NEW
787
        parts.append(f"{components.seconds}S")
×
NEW
788
    sample_interval_acronym = "".join(parts)
×
789
    # Prefix with ROLL if rolling=True
NEW
790
    if rolling:
×
NEW
791
        sample_interval_acronym = f"ROLL{sample_interval_acronym}"
×
NEW
792
    return sample_interval_acronym
×
793

794

795
def define_l1_filename(ds, campaign_name, station_name: str) -> str:
1✔
796
    """Define L1 file name.
797

798
    Parameters
799
    ----------
800
    ds  : xarray.Dataset
801
        L1 xarray Dataset
802
    processed_dir : str
803
        Path of the processed directory
804
    station_name : str
805
        Name of the station
806

807
    Returns
808
    -------
809
    str
810
        L0B file name.
811
    """
NEW
812
    from disdrodb import PRODUCT_VERSION
×
UNCOV
813
    from disdrodb.utils.xarray import get_dataset_start_end_time
×
814

UNCOV
815
    starting_time, ending_time = get_dataset_start_end_time(ds)
×
UNCOV
816
    starting_time = pd.to_datetime(starting_time).strftime("%Y%m%d%H%M%S")
×
UNCOV
817
    ending_time = pd.to_datetime(ending_time).strftime("%Y%m%d%H%M%S")
×
UNCOV
818
    version = PRODUCT_VERSION
×
NEW
819
    filename = f"L1.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
×
UNCOV
820
    return filename
×
821

822

823
def define_l2e_filename(ds, campaign_name: str, station_name: str, sample_interval: int, rolling: bool) -> str:
1✔
824
    """Define L2E file name.
825

826
    Parameters
827
    ----------
828
    ds  : xarray.Dataset
829
        L1 xarray Dataset
830
    processed_dir : str
831
        Path of the processed directory
832
    station_name : str
833
        Name of the station
834

835
    Returns
836
    -------
837
    str
838
        L0B file name.
839
    """
NEW
840
    from disdrodb import PRODUCT_VERSION
×
NEW
841
    from disdrodb.utils.xarray import get_dataset_start_end_time
×
842

NEW
843
    sample_interval_acronym = get_sample_interval_acronym(seconds=sample_interval)
×
NEW
844
    if rolling:
×
NEW
845
        sample_interval_acronym = f"ROLL{sample_interval_acronym}"
×
NEW
846
    starting_time, ending_time = get_dataset_start_end_time(ds)
×
NEW
847
    starting_time = pd.to_datetime(starting_time).strftime("%Y%m%d%H%M%S")
×
NEW
848
    ending_time = pd.to_datetime(ending_time).strftime("%Y%m%d%H%M%S")
×
NEW
849
    version = PRODUCT_VERSION
×
NEW
850
    filename = (
×
851
        f"L2E.{sample_interval_acronym}.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
852
    )
NEW
853
    return filename
×
854

855

856
def define_l2m_filename(
1✔
857
    ds,
858
    campaign_name: str,
859
    station_name: str,
860
    distribution: str,
861
    sample_interval: int,
862
    rolling: bool,
863
) -> str:
864
    """Define L2M file name.
865

866
    Parameters
867
    ----------
868
    ds  : xarray.Dataset
869
        L1 xarray Dataset
870
    processed_dir : str
871
        Path of the processed directory
872
    station_name : str
873
        Name of the station
874

875
    Returns
876
    -------
877
    str
878
        L0B file name.
879
    """
NEW
880
    from disdrodb import PRODUCT_VERSION
×
NEW
881
    from disdrodb.utils.xarray import get_dataset_start_end_time
×
882

NEW
883
    distribution_acronym = get_distribution_acronym(distribution)
×
NEW
884
    sample_interval_acronym = get_sample_interval_acronym(seconds=sample_interval)
×
NEW
885
    if rolling:
×
NEW
886
        sample_interval_acronym = f"ROLL{sample_interval_acronym}"
×
NEW
887
    starting_time, ending_time = get_dataset_start_end_time(ds)
×
NEW
888
    starting_time = pd.to_datetime(starting_time).strftime("%Y%m%d%H%M%S")
×
NEW
889
    ending_time = pd.to_datetime(ending_time).strftime("%Y%m%d%H%M%S")
×
NEW
890
    version = PRODUCT_VERSION
×
NEW
891
    filename = (
×
892
        f"L2M_{distribution_acronym}.{sample_interval_acronym}.{campaign_name}."
893
        + f"{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
894
    )
NEW
895
    return filename
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc