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.
Files changed (142) hide show
  1. disdrodb/__init__.py +68 -34
  2. disdrodb/_config.py +5 -4
  3. disdrodb/_version.py +16 -3
  4. disdrodb/accessor/__init__.py +20 -0
  5. disdrodb/accessor/methods.py +125 -0
  6. disdrodb/api/checks.py +177 -24
  7. disdrodb/api/configs.py +3 -3
  8. disdrodb/api/info.py +13 -13
  9. disdrodb/api/io.py +281 -22
  10. disdrodb/api/path.py +184 -195
  11. disdrodb/api/search.py +18 -9
  12. disdrodb/cli/disdrodb_create_summary.py +103 -0
  13. disdrodb/cli/disdrodb_create_summary_station.py +91 -0
  14. disdrodb/cli/disdrodb_run_l0.py +1 -1
  15. disdrodb/cli/disdrodb_run_l0_station.py +1 -1
  16. disdrodb/cli/disdrodb_run_l0a_station.py +1 -1
  17. disdrodb/cli/disdrodb_run_l0b.py +1 -1
  18. disdrodb/cli/disdrodb_run_l0b_station.py +3 -3
  19. disdrodb/cli/disdrodb_run_l0c.py +1 -1
  20. disdrodb/cli/disdrodb_run_l0c_station.py +3 -3
  21. disdrodb/cli/disdrodb_run_l1_station.py +2 -2
  22. disdrodb/cli/disdrodb_run_l2e_station.py +2 -2
  23. disdrodb/cli/disdrodb_run_l2m_station.py +2 -2
  24. disdrodb/configs.py +149 -4
  25. disdrodb/constants.py +61 -0
  26. disdrodb/data_transfer/download_data.py +127 -11
  27. disdrodb/etc/configs/attributes.yaml +339 -0
  28. disdrodb/etc/configs/encodings.yaml +473 -0
  29. disdrodb/etc/products/L1/global.yaml +13 -0
  30. disdrodb/etc/products/L2E/10MIN.yaml +12 -0
  31. disdrodb/etc/products/L2E/1MIN.yaml +1 -0
  32. disdrodb/etc/products/L2E/global.yaml +22 -0
  33. disdrodb/etc/products/L2M/10MIN.yaml +12 -0
  34. disdrodb/etc/products/L2M/GAMMA_ML.yaml +8 -0
  35. disdrodb/etc/products/L2M/NGAMMA_GS_LOG_ND_MAE.yaml +6 -0
  36. disdrodb/etc/products/L2M/NGAMMA_GS_ND_MAE.yaml +6 -0
  37. disdrodb/etc/products/L2M/NGAMMA_GS_Z_MAE.yaml +6 -0
  38. disdrodb/etc/products/L2M/global.yaml +26 -0
  39. disdrodb/issue/writer.py +2 -0
  40. disdrodb/l0/__init__.py +13 -0
  41. disdrodb/l0/configs/LPM/l0b_cf_attrs.yml +4 -4
  42. disdrodb/l0/configs/PARSIVEL/l0b_cf_attrs.yml +1 -1
  43. disdrodb/l0/configs/PARSIVEL/l0b_encodings.yml +3 -3
  44. disdrodb/l0/configs/PARSIVEL/raw_data_format.yml +1 -1
  45. disdrodb/l0/configs/PARSIVEL2/l0b_cf_attrs.yml +5 -5
  46. disdrodb/l0/configs/PARSIVEL2/l0b_encodings.yml +3 -3
  47. disdrodb/l0/configs/PARSIVEL2/raw_data_format.yml +1 -1
  48. disdrodb/l0/configs/PWS100/l0b_cf_attrs.yml +4 -4
  49. disdrodb/l0/configs/PWS100/raw_data_format.yml +1 -1
  50. disdrodb/l0/l0a_processing.py +37 -32
  51. disdrodb/l0/l0b_nc_processing.py +118 -8
  52. disdrodb/l0/l0b_processing.py +30 -65
  53. disdrodb/l0/l0c_processing.py +369 -259
  54. disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +7 -0
  55. disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_LPM_NC.py +66 -0
  56. disdrodb/l0/readers/LPM/SLOVENIA/{CRNI_VRH.py → UL.py} +3 -0
  57. disdrodb/l0/readers/LPM/SWITZERLAND/INNERERIZ_LPM.py +195 -0
  58. disdrodb/l0/readers/PARSIVEL/GPM/PIERS.py +0 -2
  59. disdrodb/l0/readers/PARSIVEL/JAPAN/JMA.py +4 -1
  60. disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +1 -1
  61. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +1 -1
  62. disdrodb/l0/readers/PARSIVEL2/ARM/ARM_PARSIVEL2.py +4 -0
  63. disdrodb/l0/readers/PARSIVEL2/BELGIUM/ILVO.py +168 -0
  64. disdrodb/l0/readers/PARSIVEL2/CANADA/UQAM_NC.py +69 -0
  65. disdrodb/l0/readers/PARSIVEL2/DENMARK/DTU.py +165 -0
  66. disdrodb/l0/readers/PARSIVEL2/FINLAND/FMI_PARSIVEL2.py +69 -0
  67. disdrodb/l0/readers/PARSIVEL2/FRANCE/ENPC_PARSIVEL2.py +255 -134
  68. disdrodb/l0/readers/PARSIVEL2/FRANCE/OSUG.py +525 -0
  69. disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +1 -1
  70. disdrodb/l0/readers/PARSIVEL2/GPM/GCPEX.py +9 -7
  71. disdrodb/l0/readers/PARSIVEL2/KIT/BURKINA_FASO.py +1 -1
  72. disdrodb/l0/readers/PARSIVEL2/KIT/TEAMX.py +123 -0
  73. disdrodb/l0/readers/PARSIVEL2/{NETHERLANDS/DELFT.py → MPI/BCO_PARSIVEL2.py} +41 -71
  74. disdrodb/l0/readers/PARSIVEL2/MPI/BOWTIE.py +220 -0
  75. disdrodb/l0/readers/PARSIVEL2/NASA/APU.py +120 -0
  76. disdrodb/l0/readers/PARSIVEL2/NASA/LPVEX.py +109 -0
  77. disdrodb/l0/readers/PARSIVEL2/NCAR/FARM_PARSIVEL2.py +1 -0
  78. disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +1 -1
  79. disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_MIPS.py +126 -0
  80. disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_PIPS.py +165 -0
  81. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +1 -1
  82. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +20 -12
  83. disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT_NC.py +5 -0
  84. disdrodb/l0/readers/PARSIVEL2/SPAIN/CENER.py +144 -0
  85. disdrodb/l0/readers/PARSIVEL2/SPAIN/CR1000DL.py +201 -0
  86. disdrodb/l0/readers/PARSIVEL2/SPAIN/LIAISE.py +137 -0
  87. disdrodb/l0/readers/PARSIVEL2/USA/C3WE.py +146 -0
  88. disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100.py +105 -99
  89. disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100_SIRTA.py +151 -0
  90. disdrodb/l1/__init__.py +5 -0
  91. disdrodb/l1/fall_velocity.py +46 -0
  92. disdrodb/l1/filters.py +34 -20
  93. disdrodb/l1/processing.py +46 -45
  94. disdrodb/l1/resampling.py +77 -66
  95. disdrodb/l1_env/routines.py +18 -3
  96. disdrodb/l2/__init__.py +7 -0
  97. disdrodb/l2/empirical_dsd.py +58 -10
  98. disdrodb/l2/processing.py +268 -117
  99. disdrodb/metadata/checks.py +132 -125
  100. disdrodb/metadata/standards.py +3 -1
  101. disdrodb/psd/fitting.py +631 -345
  102. disdrodb/psd/models.py +9 -6
  103. disdrodb/routines/__init__.py +54 -0
  104. disdrodb/{l0/routines.py → routines/l0.py} +316 -355
  105. disdrodb/{l1/routines.py → routines/l1.py} +76 -116
  106. disdrodb/routines/l2.py +1019 -0
  107. disdrodb/{routines.py → routines/wrappers.py} +98 -10
  108. disdrodb/scattering/__init__.py +16 -4
  109. disdrodb/scattering/axis_ratio.py +61 -37
  110. disdrodb/scattering/permittivity.py +504 -0
  111. disdrodb/scattering/routines.py +746 -184
  112. disdrodb/summary/__init__.py +17 -0
  113. disdrodb/summary/routines.py +4196 -0
  114. disdrodb/utils/archiving.py +434 -0
  115. disdrodb/utils/attrs.py +68 -125
  116. disdrodb/utils/cli.py +5 -5
  117. disdrodb/utils/compression.py +30 -1
  118. disdrodb/utils/dask.py +121 -9
  119. disdrodb/utils/dataframe.py +61 -7
  120. disdrodb/utils/decorators.py +31 -0
  121. disdrodb/utils/directories.py +35 -15
  122. disdrodb/utils/encoding.py +37 -19
  123. disdrodb/{l2 → utils}/event.py +15 -173
  124. disdrodb/utils/logger.py +14 -7
  125. disdrodb/utils/manipulations.py +81 -0
  126. disdrodb/utils/routines.py +166 -0
  127. disdrodb/utils/subsetting.py +214 -0
  128. disdrodb/utils/time.py +35 -177
  129. disdrodb/utils/writer.py +20 -7
  130. disdrodb/utils/xarray.py +5 -4
  131. disdrodb/viz/__init__.py +13 -0
  132. disdrodb/viz/plots.py +398 -0
  133. {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/METADATA +4 -3
  134. {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/RECORD +139 -98
  135. {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/entry_points.txt +2 -0
  136. disdrodb/l1/encoding_attrs.py +0 -642
  137. disdrodb/l2/processing_options.py +0 -213
  138. disdrodb/l2/routines.py +0 -868
  139. /disdrodb/l0/readers/PARSIVEL/SLOVENIA/{UL_FGG.py → UL.py} +0 -0
  140. {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/WHEEL +0 -0
  141. {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/licenses/LICENSE +0 -0
  142. {disdrodb-0.1.2.dist-info → disdrodb-0.1.4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,103 @@
1
+ # -----------------------------------------------------------------------------.
2
+ # Copyright (c) 2021-2023 DISDRODB developers
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ # -----------------------------------------------------------------------------.
17
+ """Script to create summary figures and tables for a DISDRODB stationn."""
18
+ import sys
19
+ from typing import Optional
20
+
21
+ import click
22
+
23
+ from disdrodb.utils.cli import (
24
+ click_data_archive_dir_option,
25
+ click_metadata_archive_dir_option,
26
+ click_stations_options,
27
+ parse_archive_dir,
28
+ parse_arg_to_list,
29
+ )
30
+
31
+ sys.tracebacklimit = 0 # avoid full traceback error if occur
32
+
33
+ # -------------------------------------------------------------------------.
34
+ # Click Command Line Interface decorator
35
+
36
+
37
+ @click.command()
38
+ @click_stations_options
39
+ @click_data_archive_dir_option
40
+ @click_metadata_archive_dir_option
41
+ @click.option("-p", "--parallel", type=bool, show_default=True, default=False, help="Read files in parallel")
42
+ def disdrodb_create_summary(
43
+ # Stations options
44
+ data_sources: Optional[str] = None,
45
+ campaign_names: Optional[str] = None,
46
+ station_names: Optional[str] = None,
47
+ # Processing options:
48
+ parallel=False,
49
+ # DISDRODB root directories
50
+ data_archive_dir: Optional[str] = None,
51
+ metadata_archive_dir: Optional[str] = None,
52
+ ):
53
+ r"""Create summary figures and tables for a specific set of DISDRODB stations.
54
+
55
+ Parameters \n
56
+ ---------- \n
57
+ data_sources : str
58
+ Name of data source(s) to process.
59
+ The name(s) must be UPPER CASE.
60
+ If campaign_names and station are not specified, process all stations.
61
+ To specify multiple data sources, write i.e.: --data_sources 'GPM EPFL NCAR'
62
+ campaign_names : str
63
+ Name of the campaign(s) for which to create stations summaries.
64
+ The name(s) must be UPPER CASE.
65
+ To specify multiple campaigns, write i.e.: --campaign_names 'IPEX IMPACTS'
66
+ station_names : str
67
+ Station names.
68
+ To specify multiple stations, write i.e.: --station_names 'station1 station2'
69
+ data_archive_dir : str \n
70
+ DISDRODB Data Archive directory \n
71
+ Format: <...>/DISDRODB \n
72
+ If not specified, uses path specified in the DISDRODB active configuration. \n
73
+ """
74
+ from disdrodb.routines import create_summary
75
+ from disdrodb.utils.dask import close_dask_cluster, initialize_dask_cluster
76
+
77
+ data_archive_dir = parse_archive_dir(data_archive_dir)
78
+ data_sources = parse_arg_to_list(data_sources)
79
+ campaign_names = parse_arg_to_list(campaign_names)
80
+ station_names = parse_arg_to_list(station_names)
81
+
82
+ # -------------------------------------------------------------------------.
83
+ # If parallel=True, set the dask environment
84
+ if parallel:
85
+ cluster, client = initialize_dask_cluster()
86
+
87
+ # -------------------------------------------------------------------------.
88
+ create_summary(
89
+ # Station arguments
90
+ data_sources=data_sources,
91
+ campaign_names=campaign_names,
92
+ station_names=station_names,
93
+ # Options
94
+ parallel=parallel,
95
+ # DISDRODB root directory
96
+ data_archive_dir=data_archive_dir,
97
+ metadata_archive_dir=metadata_archive_dir,
98
+ )
99
+
100
+ # -------------------------------------------------------------------------.
101
+ # Close the cluster
102
+ if parallel:
103
+ close_dask_cluster(cluster, client)
@@ -0,0 +1,91 @@
1
+ # -----------------------------------------------------------------------------.
2
+ # Copyright (c) 2021-2023 DISDRODB developers
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ # -----------------------------------------------------------------------------.
17
+ """Script to create summary figures and tables for a DISDRODB station."""
18
+ import sys
19
+ from typing import Optional
20
+
21
+ import click
22
+
23
+ from disdrodb.utils.cli import (
24
+ click_data_archive_dir_option,
25
+ click_station_arguments,
26
+ parse_archive_dir,
27
+ )
28
+
29
+ sys.tracebacklimit = 0 # avoid full traceback error if occur
30
+
31
+ # -------------------------------------------------------------------------.
32
+ # Click Command Line Interface decorator
33
+
34
+
35
+ @click.command()
36
+ @click_station_arguments
37
+ @click_data_archive_dir_option
38
+ @click.option("-p", "--parallel", type=bool, show_default=True, default=False, help="Read files in parallel")
39
+ def disdrodb_create_summary_station(
40
+ # Station arguments
41
+ data_source: str,
42
+ campaign_name: str,
43
+ station_name: str,
44
+ # Processing options:
45
+ parallel=False,
46
+ # DISDRODB root directories
47
+ data_archive_dir: Optional[str] = None,
48
+ ):
49
+ r"""Create summary figures and tables for a specific DISDRODB station.
50
+
51
+ Parameters \n
52
+ ---------- \n
53
+ data_source : str \n
54
+ Institution name (when campaign data spans more than 1 country),
55
+ or country (when all campaigns (or sensor networks) are inside a given country).\n
56
+ Must be UPPER CASE.\n
57
+ campaign_name : str \n
58
+ Campaign name. Must be UPPER CASE.\n
59
+ station_name : str \n
60
+ Station name \n
61
+ data_archive_dir : str \n
62
+ DISDRODB Data Archive directory \n
63
+ Format: <...>/DISDRODB \n
64
+ If not specified, uses path specified in the DISDRODB active configuration. \n
65
+ """
66
+ from disdrodb.summary.routines import create_station_summary
67
+ from disdrodb.utils.dask import close_dask_cluster, initialize_dask_cluster
68
+
69
+ data_archive_dir = parse_archive_dir(data_archive_dir)
70
+
71
+ # -------------------------------------------------------------------------.
72
+ # If parallel=True, set the dask environment
73
+ if parallel:
74
+ cluster, client = initialize_dask_cluster()
75
+
76
+ # -------------------------------------------------------------------------.
77
+ create_station_summary(
78
+ # Station arguments
79
+ data_source=data_source,
80
+ campaign_name=campaign_name,
81
+ station_name=station_name,
82
+ # Options
83
+ parallel=parallel,
84
+ # DISDRODB root directory
85
+ data_archive_dir=data_archive_dir,
86
+ )
87
+
88
+ # -------------------------------------------------------------------------.
89
+ # Close the cluster
90
+ if parallel:
91
+ close_dask_cluster(cluster, client)
@@ -115,7 +115,7 @@ def disdrodb_run_l0(
115
115
  debugging_mode : bool
116
116
  If True, it reduces the amount of data to process.
117
117
  For L0A, it processes just the first 3 raw data files.
118
- For L0B, it processes just the first 100 rows of 3 L0A files.
118
+ For L0B, it processes 100 rows sampled from 3 L0A files.
119
119
  The default is False.
120
120
  data_archive_dir : str
121
121
  DISDRODB Data Archive directory
@@ -105,7 +105,7 @@ def disdrodb_run_l0_station(
105
105
  debugging_mode : bool \n
106
106
  If True, it reduces the amount of data to process.\n
107
107
  For L0A, it processes just the first 3 raw data files for each station.\n
108
- For L0B, it processes just the first 100 rows of 3 L0A files for each station.\n
108
+ For L0B, it processes 100 rows sampled from 3 L0A files for each station.\n
109
109
  The default is False.\n
110
110
  data_archive_dir : str \n
111
111
  DISDRODB Data Archive directory \n
@@ -89,7 +89,7 @@ def disdrodb_run_l0a_station(
89
89
  Format: <...>/DISDRODB
90
90
  If not specified, uses path specified in the DISDRODB active configuration.
91
91
  """
92
- from disdrodb.l0.routines import run_l0a_station
92
+ from disdrodb.routines.l0 import run_l0a_station
93
93
  from disdrodb.utils.dask import close_dask_cluster, initialize_dask_cluster
94
94
 
95
95
  data_archive_dir = parse_archive_dir(data_archive_dir)
@@ -92,7 +92,7 @@ def disdrodb_run_l0b(
92
92
  If False, multi-threading is automatically exploited to speed up I/0 tasks.
93
93
  debugging_mode : bool
94
94
  If True, it reduces the amount of data to process.
95
- It processes just the first 100 rows of 3 L0A files for each station.
95
+ It processes 100 rows sampled from 3 L0A files for each station.
96
96
  The default is False.
97
97
  data_archive_dir : str
98
98
  DISDRODB Data Archive directory
@@ -84,14 +84,14 @@ def disdrodb_run_l0b_station(
84
84
  If False, multi-threading is automatically exploited to speed up I/0 tasks.
85
85
  debugging_mode : bool
86
86
  If True, it reduces the amount of data to process.
87
- It processes just the first 100 rows of 3 L0A files.
87
+ It processes 100 rows sampled from 3 L0A files.
88
88
  The default is False.
89
89
  data_archive_dir : str
90
90
  DISDRODB Data Archive directory
91
91
  Format: <...>/DISDRODB
92
92
  If not specified, uses path specified in the DISDRODB active configuration.
93
93
  """
94
- from disdrodb.l0.routines import run_l0b_station
94
+ from disdrodb.routines.l0 import run_l0b_station
95
95
  from disdrodb.utils.dask import close_dask_cluster, initialize_dask_cluster
96
96
 
97
97
  data_archive_dir = parse_archive_dir(data_archive_dir)
@@ -100,7 +100,7 @@ def disdrodb_run_l0b_station(
100
100
  # -------------------------------------------------------------------------.
101
101
  # If parallel=True, set the dask environment
102
102
  if parallel:
103
- cluster, client = initialize_dask_cluster()
103
+ cluster, client = initialize_dask_cluster(minimum_memory="4GB")
104
104
 
105
105
  # -------------------------------------------------------------------------.
106
106
  run_l0b_station(
@@ -93,7 +93,7 @@ def disdrodb_run_l0c(
93
93
  If False, multi-threading is automatically exploited to speed up I/0 tasks.
94
94
  debugging_mode : bool
95
95
  If True, it reduces the amount of data to process.
96
- It processes just the first 100 rows of 3 L0A files for each station.
96
+ It processes 100 rows sampled from 3 L0A files for each station.
97
97
  The default is False.
98
98
  remove_l0b: bool, optional
99
99
  Whether to remove the processed L0B files. The default value is ``False``.
@@ -85,7 +85,7 @@ def disdrodb_run_l0c_station(
85
85
  If False, multi-threading is automatically exploited to speed up I/0 tasks.
86
86
  debugging_mode : bool
87
87
  If True, it reduces the amount of data to process.
88
- It processes just the first 100 rows of 3 L0A files.
88
+ It processes 100 rows sampled from 3 L0A files.
89
89
  The default is False.
90
90
  remove_l0b: bool, optional
91
91
  Whether to remove the processed L0B files. The default value is ``False``.
@@ -94,7 +94,7 @@ def disdrodb_run_l0c_station(
94
94
  Format: <...>/DISDRODB
95
95
  If not specified, uses path specified in the DISDRODB active configuration.
96
96
  """
97
- from disdrodb.l0.routines import run_l0c_station
97
+ from disdrodb.routines.l0 import run_l0c_station
98
98
  from disdrodb.utils.dask import close_dask_cluster, initialize_dask_cluster
99
99
 
100
100
  data_archive_dir = parse_archive_dir(data_archive_dir)
@@ -103,7 +103,7 @@ def disdrodb_run_l0c_station(
103
103
  # -------------------------------------------------------------------------.
104
104
  # If parallel=True, set the dask environment
105
105
  if parallel:
106
- cluster, client = initialize_dask_cluster()
106
+ cluster, client = initialize_dask_cluster(minimum_memory="4GB")
107
107
 
108
108
  # -------------------------------------------------------------------------.
109
109
  run_l0c_station(
@@ -89,7 +89,7 @@ def disdrodb_run_l1_station(
89
89
  Format: <...>/DISDRODB
90
90
  If not specified, uses path specified in the DISDRODB active configuration.
91
91
  """
92
- from disdrodb.l1.routines import run_l1_station
92
+ from disdrodb.routines.l1 import run_l1_station
93
93
  from disdrodb.utils.dask import close_dask_cluster, initialize_dask_cluster
94
94
 
95
95
  data_archive_dir = parse_archive_dir(data_archive_dir)
@@ -97,7 +97,7 @@ def disdrodb_run_l1_station(
97
97
  # -------------------------------------------------------------------------.
98
98
  # If parallel=True, set the dask environment
99
99
  if parallel:
100
- cluster, client = initialize_dask_cluster()
100
+ cluster, client = initialize_dask_cluster(minimum_memory="4GB")
101
101
 
102
102
  # -------------------------------------------------------------------------.
103
103
  run_l1_station(
@@ -89,7 +89,7 @@ def disdrodb_run_l2e_station(
89
89
  Format: <...>/DISDRODB
90
90
  If not specified, uses path specified in the DISDRODB active configuration.
91
91
  """
92
- from disdrodb.l2.routines import run_l2e_station
92
+ from disdrodb.routines.l2 import run_l2e_station
93
93
  from disdrodb.utils.dask import close_dask_cluster, initialize_dask_cluster
94
94
 
95
95
  data_archive_dir = parse_archive_dir(data_archive_dir)
@@ -98,7 +98,7 @@ def disdrodb_run_l2e_station(
98
98
  # -------------------------------------------------------------------------.
99
99
  # If parallel=True, set the dask environment
100
100
  if parallel:
101
- cluster, client = initialize_dask_cluster()
101
+ cluster, client = initialize_dask_cluster(minimum_memory="4GB")
102
102
 
103
103
  # -------------------------------------------------------------------------.
104
104
  run_l2e_station(
@@ -89,7 +89,7 @@ def disdrodb_run_l2m_station(
89
89
  Format: <...>/DISDRODB
90
90
  If not specified, uses path specified in the DISDRODB active configuration.
91
91
  """
92
- from disdrodb.l2.routines import run_l2m_station
92
+ from disdrodb.routines.l2 import run_l2m_station
93
93
  from disdrodb.utils.dask import close_dask_cluster, initialize_dask_cluster
94
94
 
95
95
  data_archive_dir = parse_archive_dir(data_archive_dir)
@@ -98,7 +98,7 @@ def disdrodb_run_l2m_station(
98
98
  # -------------------------------------------------------------------------.
99
99
  # If parallel=True, set the dask environment
100
100
  if parallel:
101
- cluster, client = initialize_dask_cluster()
101
+ cluster, client = initialize_dask_cluster(minimum_memory="4GB")
102
102
 
103
103
  # -------------------------------------------------------------------------.
104
104
  run_l2m_station(
disdrodb/configs.py CHANGED
@@ -19,6 +19,7 @@
19
19
  """DISDRODB Configuration File functions."""
20
20
 
21
21
  import os
22
+ import shutil
22
23
  from typing import Optional
23
24
 
24
25
  from disdrodb.utils.yaml import read_yaml, write_yaml
@@ -32,9 +33,11 @@ def _define_config_filepath():
32
33
  return filepath
33
34
 
34
35
 
35
- def define_disdrodb_configs(
36
+ def define_configs(
36
37
  data_archive_dir: Optional[str] = None,
37
38
  metadata_archive_dir: Optional[str] = None,
39
+ scattering_table_dir: Optional[str] = None,
40
+ configs_path: Optional[str] = None,
38
41
  folder_partitioning: Optional[str] = None,
39
42
  zenodo_token: Optional[str] = None,
40
43
  zenodo_sandbox_token: Optional[str] = None,
@@ -48,6 +51,10 @@ def define_disdrodb_configs(
48
51
  The directory path where the DISDRODB Data Archive is located.
49
52
  metadata_archive_dir : str
50
53
  The directory path where the DISDRODB Metadata Archive is located.
54
+ scattering_table_dir : str
55
+ The directory path where to store DISDRODB T-Matrix scattering tables.
56
+ configs_path : str
57
+ The directory path where the custom DISDRODB products configurations files are defined.
51
58
  folder_partitioning : str
52
59
  The folder partitioning scheme used in the DISDRODB Data Archive.
53
60
  Allowed values are:
@@ -69,7 +76,13 @@ def define_disdrodb_configs(
69
76
  The configuration file is used to run the various DISDRODB operations.
70
77
 
71
78
  """
72
- from disdrodb.api.checks import check_data_archive_dir, check_folder_partitioning, check_metadata_archive_dir
79
+ import disdrodb
80
+ from disdrodb.api.checks import (
81
+ check_data_archive_dir,
82
+ check_folder_partitioning,
83
+ check_metadata_archive_dir,
84
+ check_scattering_table_dir,
85
+ )
73
86
 
74
87
  # Define path to .config_disdrodb.yaml file
75
88
  filepath = _define_config_filepath()
@@ -85,9 +98,16 @@ def define_disdrodb_configs(
85
98
  # Add DISDRODB Data Archive Directory
86
99
  if data_archive_dir is not None:
87
100
  config_dict["data_archive_dir"] = check_data_archive_dir(data_archive_dir)
101
+
88
102
  # Add DISDRODB Metadata Archive Directory
89
103
  if metadata_archive_dir is not None:
90
104
  config_dict["metadata_archive_dir"] = check_metadata_archive_dir(metadata_archive_dir)
105
+
106
+ # Add DISDRODB Scattering Table Directory
107
+ if scattering_table_dir is not None:
108
+ os.makedirs(scattering_table_dir, exist_ok=True)
109
+ config_dict["scattering_table_dir"] = check_scattering_table_dir(scattering_table_dir)
110
+
91
111
  # Add DISDRODB Folder Partitioning
92
112
  if folder_partitioning is not None:
93
113
  config_dict["folder_partitioning"] = check_folder_partitioning(folder_partitioning)
@@ -98,13 +118,21 @@ def define_disdrodb_configs(
98
118
  if zenodo_sandbox_token is not None:
99
119
  config_dict["zenodo_sandbox_token"] = zenodo_sandbox_token
100
120
 
121
+ if configs_path is not None:
122
+ config_dict["configs_path"] = configs_path
123
+
101
124
  # Write the DISDRODB config file
102
125
  write_yaml(config_dict, filepath, sort_keys=False)
103
126
 
104
127
  print(f"The DISDRODB config file has been {action_msg} successfully!")
105
128
 
129
+ # Now read the config file and set it as the active configuration
130
+ # - This avoid the need to restart a python session to take effect !
131
+ config_dict = read_configs()
132
+ disdrodb.config.update(config_dict)
133
+
106
134
 
107
- def read_disdrodb_configs() -> dict[str, str]:
135
+ def read_configs() -> dict[str, str]:
108
136
  """
109
137
  Reads the DISDRODB configuration file and returns a dictionary with the configuration settings.
110
138
 
@@ -158,6 +186,19 @@ def get_metadata_archive_dir(metadata_archive_dir=None):
158
186
  return metadata_archive_dir
159
187
 
160
188
 
189
+ def get_scattering_table_dir(scattering_table_dir=None):
190
+ """Return the directory where DISDRODB save pyTMatrix scattering tables."""
191
+ import disdrodb
192
+ from disdrodb.api.checks import check_scattering_table_dir
193
+
194
+ if scattering_table_dir is None:
195
+ scattering_table_dir = disdrodb.config.get("scattering_table_dir", None)
196
+ if scattering_table_dir is None:
197
+ raise ValueError("The directory where to save DISDRODB T-Matrix scattering tables is not specified.")
198
+ scattering_table_dir = check_scattering_table_dir(scattering_table_dir) # ensure Path converted to str
199
+ return scattering_table_dir
200
+
201
+
161
202
  def get_folder_partitioning():
162
203
  """Return the folder partitioning."""
163
204
  import disdrodb
@@ -182,7 +223,7 @@ def get_zenodo_token(sandbox: bool):
182
223
  host = "zenodo.org"
183
224
  token_name = "zenodo_token"
184
225
 
185
- # token = read_disdrodb_configs().get(token_name, None)
226
+ # token = read_configs().get(token_name, None)
186
227
  token = disdrodb.config.get(token_name, None)
187
228
 
188
229
  if token is None:
@@ -195,3 +236,107 @@ def get_zenodo_token(sandbox: bool):
195
236
  raise ValueError(f"Missing {token_name} in the DISDRODB config file !")
196
237
 
197
238
  return token
239
+
240
+
241
+ def get_product_default_configs_path():
242
+ """Return the paths where DISDRODB products configuration files are stored."""
243
+ import disdrodb
244
+
245
+ configs_path = os.path.join(disdrodb.__root_path__, "disdrodb", "etc", "products")
246
+ return configs_path
247
+
248
+
249
+ def check_availability_radar_simulations(options):
250
+ """Check radar simulations are possible for L2E and L2M products."""
251
+ import disdrodb
252
+
253
+ if "radar_enabled" in options and not disdrodb.is_pytmatrix_available():
254
+ options["radar_enabled"] = False
255
+ return options
256
+
257
+
258
+ def copy_product_default_configs(configs_path):
259
+ """Copy the default DISDRODB products configuration directory to a custom location.
260
+
261
+ This function duplicates the entire directory of default product settings
262
+ (located at ``disdrodb/etc/products``) into the user-specified
263
+ ``configs_path``. Once copied, you can safely edit these files without
264
+ modifying the library's built-in defaults. To have DISDRODB use your
265
+ custom settings, point the global configuration at this new directory
266
+ (e.g by specifying ``configs_path`` with the ``disdrodb.define_configs`` function).
267
+
268
+ Parameters
269
+ ----------
270
+ configs_path:
271
+ Destination directory where the default product configuration files
272
+ will be copied. This directory must not already exist, and later
273
+ needs to be referenced in your DISDRODB global configuration.
274
+
275
+ Returns
276
+ -------
277
+ configs_path
278
+ The path to the newly created custom product configuration directory.
279
+
280
+ """
281
+ source_dir_path = get_product_default_configs_path()
282
+ if os.path.exists(configs_path):
283
+ raise FileExistsError(f"The {configs_path} directory already exists!")
284
+ configs_path = shutil.copytree(source_dir_path, configs_path)
285
+ return configs_path
286
+
287
+
288
+ def get_product_options(product, temporal_resolution=None):
289
+ """Get options for DISDRODB products."""
290
+ import disdrodb
291
+ from disdrodb.api.checks import check_product
292
+
293
+ # Define configs path
294
+ if os.environ.get("PYTEST_CURRENT_TEST"):
295
+ configs_path = os.path.join(disdrodb.__root_path__, "disdrodb", "tests", "products")
296
+ else:
297
+ configs_path = disdrodb.config.get("configs_path", get_product_default_configs_path())
298
+
299
+ # Validate DISDRODB products configuration
300
+ validate_product_configuration(configs_path)
301
+
302
+ # Check product
303
+ check_product(product)
304
+
305
+ # Retrieve global product options
306
+ global_options = read_yaml(os.path.join(configs_path, product, "global.yaml"))
307
+ if temporal_resolution is None:
308
+ global_options = check_availability_radar_simulations(global_options)
309
+ return global_options
310
+
311
+ # If temporal resolutions are specified, drop 'temporal_resolutions' key
312
+ global_options.pop("temporal_resolutions", None)
313
+ custom_options_path = os.path.join(configs_path, product, f"{temporal_resolution}.yaml")
314
+ if not os.path.exists(custom_options_path):
315
+ return global_options
316
+ custom_options = read_yaml(custom_options_path)
317
+ options = global_options.copy()
318
+ options.update(custom_options)
319
+ options = check_availability_radar_simulations(options)
320
+ return options
321
+
322
+
323
+ def get_product_temporal_resolutions(product):
324
+ """Get DISDRODB L2 product temporal aggregations."""
325
+ # Check only L2E and L2M
326
+ return get_product_options(product)["temporal_resolutions"]
327
+
328
+
329
+ def get_model_options(product, model_name):
330
+ """Get DISDRODB L2M model options."""
331
+ import disdrodb
332
+
333
+ configs_path = disdrodb.config.get("configs_path", get_product_default_configs_path())
334
+ model_options_path = os.path.join(configs_path, product, f"{model_name}.yaml")
335
+ model_options = read_yaml(model_options_path)
336
+ return model_options
337
+
338
+
339
+ def validate_product_configuration(configs_path):
340
+ """Validate the DISDRODB products configuration files."""
341
+ # TODO: Implement validation of DISDRODB products configuration files with pydantic
342
+ pass
disdrodb/constants.py ADDED
@@ -0,0 +1,61 @@
1
+ # -----------------------------------------------------------------------------.
2
+ # Copyright (c) 2021-2023 DISDRODB developers
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ # -----------------------------------------------------------------------------.
17
+ """DISDRODB constants."""
18
+ import importlib
19
+
20
+ ARCHIVE_VERSION = "V0"
21
+ SOFTWARE_VERSION = "V" + importlib.metadata.version("disdrodb")
22
+ CONVENTIONS = "CF-1.10, ACDD-1.3"
23
+
24
+ # Define coordinates names
25
+ DIAMETER_COORDS = ["diameter_bin_center", "diameter_bin_width", "diameter_bin_lower", "diameter_bin_upper"]
26
+ VELOCITY_COORDS = ["velocity_bin_center", "velocity_bin_width", "velocity_bin_lower", "velocity_bin_upper"]
27
+ GEOLOCATION_COORDS = ["longitude", "latitude", "altitude"]
28
+ VELOCITY_DIMENSION = "velocity_bin_center"
29
+ DIAMETER_DIMENSION = "diameter_bin_center"
30
+ COORDINATES = [
31
+ "diameter_bin_center",
32
+ "diameter_bin_width",
33
+ "diameter_bin_upper",
34
+ "velocity_bin_lower",
35
+ "velocity_bin_center",
36
+ "velocity_bin_width",
37
+ "velocity_bin_upper",
38
+ "latitude",
39
+ "longitude",
40
+ "altitude",
41
+ "time",
42
+ "sample_interval",
43
+ ]
44
+ OPTICAL_SENSORS = ["PARSIVEL", "PARSIVEL2", "LPM", "PWS100"]
45
+ IMPACT_SENSORS = ["RD80"]
46
+
47
+ PRODUCTS = ["RAW", "L0A", "L0B", "L0C", "L1", "L2E", "L2M"]
48
+
49
+ PRODUCTS_ARGUMENTS = {
50
+ "L2E": ["rolling", "sample_interval"],
51
+ "L2M": ["rolling", "sample_interval", "model_name"],
52
+ }
53
+
54
+ PRODUCTS_REQUIREMENTS = {
55
+ "L0A": "RAW",
56
+ "L0B": "L0A",
57
+ "L0C": "L0B",
58
+ "L1": "L0C",
59
+ "L2E": "L1",
60
+ "L2M": "L2E",
61
+ }