disdrodb 0.0.21__py3-none-any.whl → 0.1.0__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 +132 -15
- disdrodb/_config.py +4 -2
- disdrodb/_version.py +9 -4
- disdrodb/api/checks.py +264 -237
- disdrodb/api/configs.py +4 -8
- disdrodb/api/create_directories.py +235 -290
- disdrodb/api/info.py +217 -26
- disdrodb/api/io.py +295 -269
- disdrodb/api/path.py +597 -173
- disdrodb/api/search.py +486 -0
- disdrodb/{metadata/scripts → cli}/disdrodb_check_metadata_archive.py +12 -7
- disdrodb/{utils/pandas.py → cli/disdrodb_data_archive_directory.py} +9 -18
- disdrodb/cli/disdrodb_download_archive.py +86 -0
- disdrodb/cli/disdrodb_download_metadata_archive.py +53 -0
- disdrodb/cli/disdrodb_download_station.py +84 -0
- disdrodb/{api/scripts → cli}/disdrodb_initialize_station.py +22 -10
- disdrodb/cli/disdrodb_metadata_archive_directory.py +32 -0
- disdrodb/{data_transfer/scripts/disdrodb_download_station.py → cli/disdrodb_open_data_archive.py} +22 -22
- disdrodb/cli/disdrodb_open_logs_directory.py +69 -0
- disdrodb/{data_transfer/scripts/disdrodb_upload_station.py → cli/disdrodb_open_metadata_archive.py} +22 -24
- disdrodb/cli/disdrodb_open_metadata_directory.py +71 -0
- disdrodb/cli/disdrodb_open_product_directory.py +74 -0
- disdrodb/cli/disdrodb_open_readers_directory.py +32 -0
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0.py +38 -31
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0_station.py +32 -30
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0a.py +30 -21
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0a_station.py +24 -33
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0b.py +30 -21
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0b_station.py +25 -34
- disdrodb/cli/disdrodb_run_l0c.py +130 -0
- disdrodb/cli/disdrodb_run_l0c_station.py +129 -0
- disdrodb/cli/disdrodb_run_l1.py +122 -0
- disdrodb/cli/disdrodb_run_l1_station.py +121 -0
- disdrodb/cli/disdrodb_run_l2e.py +122 -0
- disdrodb/cli/disdrodb_run_l2e_station.py +122 -0
- disdrodb/cli/disdrodb_run_l2m.py +122 -0
- disdrodb/cli/disdrodb_run_l2m_station.py +122 -0
- disdrodb/cli/disdrodb_upload_archive.py +105 -0
- disdrodb/cli/disdrodb_upload_station.py +98 -0
- disdrodb/configs.py +90 -25
- disdrodb/data_transfer/__init__.py +22 -0
- disdrodb/data_transfer/download_data.py +87 -90
- disdrodb/data_transfer/upload_data.py +64 -37
- disdrodb/data_transfer/zenodo.py +15 -18
- disdrodb/docs.py +1 -1
- disdrodb/issue/__init__.py +17 -4
- disdrodb/issue/checks.py +10 -23
- disdrodb/issue/reader.py +9 -12
- disdrodb/issue/writer.py +14 -17
- disdrodb/l0/__init__.py +17 -26
- disdrodb/l0/check_configs.py +35 -23
- disdrodb/l0/check_standards.py +32 -42
- disdrodb/l0/configs/{Thies_LPM → LPM}/bins_diameter.yml +44 -44
- disdrodb/l0/configs/{Thies_LPM → LPM}/bins_velocity.yml +40 -40
- disdrodb/l0/configs/LPM/l0a_encodings.yml +80 -0
- disdrodb/l0/configs/{Thies_LPM → LPM}/l0b_cf_attrs.yml +62 -59
- disdrodb/l0/configs/{Thies_LPM → LPM}/l0b_encodings.yml +9 -9
- disdrodb/l0/configs/{Thies_LPM → LPM}/raw_data_format.yml +245 -245
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/bins_diameter.yml +66 -66
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/bins_velocity.yml +64 -64
- disdrodb/l0/configs/PARSIVEL/l0a_encodings.yml +32 -0
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/l0b_cf_attrs.yml +22 -20
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/l0b_encodings.yml +17 -17
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/raw_data_format.yml +77 -77
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/bins_diameter.yml +64 -64
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/bins_velocity.yml +64 -64
- disdrodb/l0/configs/PARSIVEL2/l0a_encodings.yml +39 -0
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/l0b_cf_attrs.yml +24 -22
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/l0b_encodings.yml +20 -20
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/raw_data_format.yml +98 -98
- disdrodb/l0/configs/{RD_80 → RD80}/bins_diameter.yml +40 -40
- disdrodb/l0/configs/RD80/l0a_encodings.yml +16 -0
- disdrodb/l0/configs/{RD_80 → RD80}/l0b_cf_attrs.yml +3 -3
- disdrodb/l0/configs/RD80/l0b_encodings.yml +135 -0
- disdrodb/l0/configs/{RD_80 → RD80}/raw_data_format.yml +48 -48
- disdrodb/l0/l0_reader.py +216 -340
- disdrodb/l0/l0a_processing.py +237 -208
- disdrodb/l0/l0b_nc_processing.py +227 -80
- disdrodb/l0/l0b_processing.py +93 -173
- disdrodb/l0/l0c_processing.py +627 -0
- disdrodb/l0/readers/{ARM → LPM/ARM}/ARM_LPM.py +36 -58
- disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +226 -0
- disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +185 -0
- disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +183 -0
- disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +179 -0
- disdrodb/l0/readers/{UK → LPM/UK}/DIVEN.py +14 -35
- disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +157 -0
- disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +113 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/ARCTIC_2021.py +40 -57
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/COMMON_2011.py +37 -54
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/DAVOS_2009_2011.py +34 -51
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_2009.py +34 -51
- disdrodb/l0/readers/{EPFL/PARADISO_2014.py → PARSIVEL/EPFL/EPFL_ROOF_2008.py} +38 -50
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +105 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2011.py +34 -51
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2012.py +33 -51
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GENEPI_2007.py +25 -44
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007.py +25 -44
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007_2.py +25 -44
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HPICONET_2010.py +34 -51
- disdrodb/l0/readers/{EPFL/EPFL_ROOF_2010.py → PARSIVEL/EPFL/HYMEX_LTE_SOP2.py} +37 -50
- disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +111 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HYMEX_LTE_SOP4.py +36 -54
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2018.py +34 -52
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2019.py +38 -56
- disdrodb/l0/readers/PARSIVEL/EPFL/PARADISO_2014.py +105 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PARSIVEL_2007.py +27 -45
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PLATO_2019.py +24 -44
- disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +140 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RACLETS_2019_WJF.py +41 -59
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RIETHOLZBACH_2011.py +34 -51
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +117 -0
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +137 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/UNIL_2022.py +42 -55
- disdrodb/l0/readers/PARSIVEL/GPM/IFLOODS.py +104 -0
- disdrodb/l0/readers/{GPM → PARSIVEL/GPM}/LPVEX.py +29 -48
- disdrodb/l0/readers/PARSIVEL/GPM/MC3E.py +184 -0
- disdrodb/l0/readers/PARSIVEL/NCAR/CCOPE_2015.py +113 -0
- disdrodb/l0/readers/{NCAR/VORTEX_SE_2016_P1.py → PARSIVEL/NCAR/OWLES_MIPS.py} +46 -72
- disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +125 -0
- disdrodb/l0/readers/{NCAR/OWLES_MIPS.py → PARSIVEL/NCAR/PLOWS_MIPS.py} +45 -64
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +114 -0
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +176 -0
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +183 -0
- disdrodb/l0/readers/{ARM/ARM_LD.py → PARSIVEL2/ARM/ARM_PARSIVEL2.py} +27 -50
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +163 -0
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +163 -0
- disdrodb/l0/readers/{DENMARK → PARSIVEL2/DENMARK}/EROSION_nc.py +14 -35
- disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +119 -0
- disdrodb/l0/readers/PARSIVEL2/GPM/GCPEX.py +104 -0
- disdrodb/l0/readers/PARSIVEL2/GPM/NSSTC.py +176 -0
- disdrodb/l0/readers/PARSIVEL2/ITALY/GID_PARSIVEL2.py +32 -0
- disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +56 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +120 -0
- disdrodb/l0/readers/{NCAR → PARSIVEL2/NCAR}/PECAN_MIPS.py +45 -64
- disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +181 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +160 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +160 -0
- disdrodb/l0/readers/{NCAR/PLOWS_MIPS.py → PARSIVEL2/NCAR/VORTEX_SE_2016_P1.py} +49 -66
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +118 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +152 -0
- disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT.py +166 -0
- disdrodb/l0/readers/{NCAR/RELAMPAGO_RD80.py → RD80/BRAZIL/CHUVA_RD80.py} +36 -60
- disdrodb/l0/readers/{BRAZIL → RD80/BRAZIL}/GOAMAZON_RD80.py +36 -55
- disdrodb/l0/readers/{NCAR → RD80/NCAR}/CINDY_2011_RD80.py +35 -54
- disdrodb/l0/readers/{BRAZIL/CHUVA_RD80.py → RD80/NCAR/RELAMPAGO_RD80.py} +40 -54
- disdrodb/l0/readers/template_reader_raw_netcdf_data.py +62 -0
- disdrodb/l0/readers/{reader_template.py → template_reader_raw_text_data.py} +20 -44
- disdrodb/l0/routines.py +885 -581
- disdrodb/l0/standards.py +72 -236
- disdrodb/l0/template_tools.py +104 -109
- disdrodb/l1/__init__.py +17 -0
- disdrodb/l1/beard_model.py +716 -0
- disdrodb/l1/encoding_attrs.py +620 -0
- disdrodb/l1/fall_velocity.py +260 -0
- disdrodb/l1/filters.py +192 -0
- disdrodb/l1/processing.py +200 -0
- disdrodb/l1/resampling.py +236 -0
- disdrodb/l1/routines.py +357 -0
- disdrodb/l1_env/__init__.py +17 -0
- disdrodb/l1_env/routines.py +38 -0
- disdrodb/l2/__init__.py +17 -0
- disdrodb/l2/empirical_dsd.py +1735 -0
- disdrodb/l2/event.py +388 -0
- disdrodb/l2/processing.py +519 -0
- disdrodb/l2/processing_options.py +213 -0
- disdrodb/l2/routines.py +868 -0
- disdrodb/metadata/__init__.py +9 -2
- disdrodb/metadata/checks.py +165 -118
- disdrodb/metadata/download.py +81 -0
- disdrodb/metadata/geolocation.py +146 -0
- disdrodb/metadata/info.py +20 -13
- disdrodb/metadata/manipulation.py +1 -1
- disdrodb/metadata/reader.py +59 -8
- disdrodb/metadata/search.py +77 -144
- disdrodb/metadata/standards.py +7 -8
- disdrodb/metadata/writer.py +8 -14
- disdrodb/psd/__init__.py +38 -0
- disdrodb/psd/fitting.py +2146 -0
- disdrodb/psd/models.py +774 -0
- disdrodb/routines.py +1176 -0
- disdrodb/scattering/__init__.py +28 -0
- disdrodb/scattering/axis_ratio.py +344 -0
- disdrodb/scattering/routines.py +456 -0
- disdrodb/utils/__init__.py +17 -0
- disdrodb/utils/attrs.py +208 -0
- disdrodb/utils/cli.py +269 -0
- disdrodb/utils/compression.py +60 -42
- disdrodb/utils/dask.py +62 -0
- disdrodb/utils/decorators.py +110 -0
- disdrodb/utils/directories.py +107 -46
- disdrodb/utils/encoding.py +127 -0
- disdrodb/utils/list.py +29 -0
- disdrodb/utils/logger.py +168 -46
- disdrodb/utils/time.py +657 -0
- disdrodb/utils/warnings.py +30 -0
- disdrodb/utils/writer.py +57 -0
- disdrodb/utils/xarray.py +138 -47
- disdrodb/utils/yaml.py +0 -1
- disdrodb/viz/__init__.py +17 -0
- disdrodb/viz/plots.py +17 -0
- disdrodb-0.1.0.dist-info/METADATA +321 -0
- disdrodb-0.1.0.dist-info/RECORD +216 -0
- {disdrodb-0.0.21.dist-info → disdrodb-0.1.0.dist-info}/WHEEL +1 -1
- disdrodb-0.1.0.dist-info/entry_points.txt +30 -0
- disdrodb/data_transfer/scripts/disdrodb_download_archive.py +0 -53
- disdrodb/data_transfer/scripts/disdrodb_upload_archive.py +0 -57
- disdrodb/l0/configs/OTT_Parsivel/l0a_encodings.yml +0 -32
- disdrodb/l0/configs/OTT_Parsivel2/l0a_encodings.yml +0 -39
- disdrodb/l0/configs/RD_80/l0a_encodings.yml +0 -16
- disdrodb/l0/configs/RD_80/l0b_encodings.yml +0 -135
- disdrodb/l0/configs/Thies_LPM/l0a_encodings.yml +0 -80
- disdrodb/l0/io.py +0 -257
- disdrodb/l0/l0_processing.py +0 -1091
- disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_OTT.py +0 -178
- disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_THIES.py +0 -247
- disdrodb/l0/readers/BRAZIL/CHUVA_LPM.py +0 -204
- disdrodb/l0/readers/BRAZIL/CHUVA_OTT.py +0 -183
- disdrodb/l0/readers/BRAZIL/GOAMAZON_LPM.py +0 -204
- disdrodb/l0/readers/BRAZIL/GOAMAZON_OTT.py +0 -183
- disdrodb/l0/readers/CHINA/CHONGQING.py +0 -131
- disdrodb/l0/readers/EPFL/EPFL_ROOF_2008.py +0 -128
- disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP2.py +0 -127
- disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP3.py +0 -129
- disdrodb/l0/readers/EPFL/RACLETS_2019.py +0 -158
- disdrodb/l0/readers/EPFL/SAMOYLOV_2017.py +0 -136
- disdrodb/l0/readers/EPFL/SAMOYLOV_2019.py +0 -158
- disdrodb/l0/readers/FRANCE/SIRTA_OTT2.py +0 -138
- disdrodb/l0/readers/GPM/GCPEX.py +0 -123
- disdrodb/l0/readers/GPM/IFLOODS.py +0 -123
- disdrodb/l0/readers/GPM/MC3E.py +0 -123
- disdrodb/l0/readers/GPM/NSSTC.py +0 -164
- disdrodb/l0/readers/ITALY/GID.py +0 -199
- disdrodb/l0/readers/MEXICO/OH_IIUNAM_nc.py +0 -92
- disdrodb/l0/readers/NCAR/CCOPE_2015.py +0 -133
- disdrodb/l0/readers/NCAR/PECAN_FP3.py +0 -137
- disdrodb/l0/readers/NCAR/PECAN_MOBILE.py +0 -144
- disdrodb/l0/readers/NCAR/RELAMPAGO_OTT.py +0 -195
- disdrodb/l0/readers/NCAR/SNOWIE_PJ.py +0 -172
- disdrodb/l0/readers/NCAR/SNOWIE_SB.py +0 -179
- disdrodb/l0/readers/NCAR/VORTEX2_2009.py +0 -133
- disdrodb/l0/readers/NCAR/VORTEX2_2010.py +0 -188
- disdrodb/l0/readers/NCAR/VORTEX2_2010_UF.py +0 -191
- disdrodb/l0/readers/NCAR/VORTEX_SE_2016_P2.py +0 -135
- disdrodb/l0/readers/NCAR/VORTEX_SE_2016_PIPS.py +0 -170
- disdrodb/l0/readers/NETHERLANDS/DELFT.py +0 -187
- disdrodb/l0/readers/SPAIN/SBEGUERIA.py +0 -179
- disdrodb/l0/scripts/disdrodb_run_l0b_concat.py +0 -93
- disdrodb/l0/scripts/disdrodb_run_l0b_concat_station.py +0 -85
- disdrodb/utils/netcdf.py +0 -452
- disdrodb/utils/scripts.py +0 -102
- disdrodb-0.0.21.dist-info/AUTHORS.md +0 -18
- disdrodb-0.0.21.dist-info/METADATA +0 -186
- disdrodb-0.0.21.dist-info/RECORD +0 -168
- disdrodb-0.0.21.dist-info/entry_points.txt +0 -15
- /disdrodb/l0/configs/{RD_80 → RD80}/bins_velocity.yml +0 -0
- /disdrodb/l0/manuals/{Thies_LPM.pdf → LPM.pdf} +0 -0
- /disdrodb/l0/manuals/{ODM_470.pdf → ODM470.pdf} +0 -0
- /disdrodb/l0/manuals/{OTT_Parsivel.pdf → PARSIVEL.pdf} +0 -0
- /disdrodb/l0/manuals/{OTT_Parsivel2.pdf → PARSIVEL2.pdf} +0 -0
- /disdrodb/l0/manuals/{PWS_100.pdf → PWS100.pdf} +0 -0
- /disdrodb/l0/manuals/{RD_80.pdf → RD80.pdf} +0 -0
- {disdrodb-0.0.21.dist-info → disdrodb-0.1.0.dist-info/licenses}/LICENSE +0 -0
- {disdrodb-0.0.21.dist-info → disdrodb-0.1.0.dist-info}/top_level.txt +0 -0
disdrodb/utils/cli.py
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
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
|
+
"""DISDRODB command-line-interface scripts utilities."""
|
|
20
|
+
|
|
21
|
+
import click
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _execute_cmd(cmd, raise_error=False):
|
|
25
|
+
"""Execute command in the terminal, streaming output in python console."""
|
|
26
|
+
from subprocess import PIPE, CalledProcessError, Popen
|
|
27
|
+
|
|
28
|
+
with Popen(cmd, shell=True, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
|
|
29
|
+
for line in p.stdout:
|
|
30
|
+
print(line, end="")
|
|
31
|
+
|
|
32
|
+
# Raise error if command didn't run successfully
|
|
33
|
+
if p.returncode != 0 and raise_error:
|
|
34
|
+
raise CalledProcessError(p.returncode, p.args)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _parse_empty_string_and_none(args):
|
|
38
|
+
"""Utility to parse argument passed from the command line.
|
|
39
|
+
|
|
40
|
+
If ``args = ''``, returns None.
|
|
41
|
+
If ``args = 'None'`` returns None.
|
|
42
|
+
Otherwise return ``args``.
|
|
43
|
+
"""
|
|
44
|
+
# If '', set to 'None'
|
|
45
|
+
args = None if args == "" else args
|
|
46
|
+
# - If multiple arguments, split by space
|
|
47
|
+
if isinstance(args, str) and args == "None":
|
|
48
|
+
args = None
|
|
49
|
+
return args
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def parse_arg_to_list(args):
|
|
53
|
+
"""Utility to pass list to command line scripts.
|
|
54
|
+
|
|
55
|
+
If ``args = ''`` returns ``None``.
|
|
56
|
+
If ``args = 'None'`` returns ``None``.
|
|
57
|
+
If ``args = 'variable'`` returns ``[variable]``.
|
|
58
|
+
If ``args = 'variable1 variable2'`` returns ``[variable1, variable2]``.
|
|
59
|
+
"""
|
|
60
|
+
# If '' or 'None' --> Set to None
|
|
61
|
+
args = _parse_empty_string_and_none(args)
|
|
62
|
+
# - If multiple arguments, split by space
|
|
63
|
+
if isinstance(args, str):
|
|
64
|
+
# - Split by space
|
|
65
|
+
list_args = args.split(" ")
|
|
66
|
+
# - Remove '' (deal with multi space)
|
|
67
|
+
args = [args for args in list_args if len(args) > 0]
|
|
68
|
+
return args
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def parse_archive_dir(archive_dir: str):
|
|
72
|
+
"""Utility to parse archive directories provided by command line.
|
|
73
|
+
|
|
74
|
+
If ``archive_dir = 'None'`` returns ``None``.
|
|
75
|
+
If ``archive_dir = ''`` returns ``None``.
|
|
76
|
+
"""
|
|
77
|
+
# If '', set to 'None'
|
|
78
|
+
return _parse_empty_string_and_none(archive_dir)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def click_station_arguments(function: object):
|
|
82
|
+
"""Click command line arguments for DISDRODB station processing.
|
|
83
|
+
|
|
84
|
+
Parameters
|
|
85
|
+
----------
|
|
86
|
+
function : object
|
|
87
|
+
Function.
|
|
88
|
+
"""
|
|
89
|
+
function = click.argument("station_name", metavar="<station>")(function)
|
|
90
|
+
function = click.argument("campaign_name", metavar="<CAMPAIGN_NAME>")(function)
|
|
91
|
+
function = click.argument("data_source", metavar="<DATA_SOURCE>")(function)
|
|
92
|
+
return function
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def click_data_archive_dir_option(function: object):
|
|
96
|
+
"""Click command line argument for DISDRODB ``data_archive_dir``.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
function : object
|
|
101
|
+
Function.
|
|
102
|
+
"""
|
|
103
|
+
function = click.option(
|
|
104
|
+
"--data_archive_dir",
|
|
105
|
+
type=str,
|
|
106
|
+
show_default=True,
|
|
107
|
+
default=None,
|
|
108
|
+
help="DISDRODB base directory",
|
|
109
|
+
)(function)
|
|
110
|
+
return function
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def click_metadata_archive_dir_option(function: object):
|
|
114
|
+
"""Click command line argument for DISDRODB ``metadata_archive_dir``.
|
|
115
|
+
|
|
116
|
+
Parameters
|
|
117
|
+
----------
|
|
118
|
+
function : object
|
|
119
|
+
Function.
|
|
120
|
+
"""
|
|
121
|
+
function = click.option(
|
|
122
|
+
"--metadata_archive_dir",
|
|
123
|
+
type=str,
|
|
124
|
+
show_default=True,
|
|
125
|
+
default=None,
|
|
126
|
+
help="DISDRODB Metadata Archive Directory",
|
|
127
|
+
)(function)
|
|
128
|
+
return function
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def click_stations_options(function: object):
|
|
132
|
+
"""Click command line options for DISDRODB archive L0 processing.
|
|
133
|
+
|
|
134
|
+
Parameters
|
|
135
|
+
----------
|
|
136
|
+
function : object
|
|
137
|
+
Function.
|
|
138
|
+
"""
|
|
139
|
+
function = click.option(
|
|
140
|
+
"--data_sources",
|
|
141
|
+
type=str,
|
|
142
|
+
show_default=True,
|
|
143
|
+
default="",
|
|
144
|
+
help="DISDRODB data sources to process",
|
|
145
|
+
)(function)
|
|
146
|
+
function = click.option(
|
|
147
|
+
"--campaign_names",
|
|
148
|
+
type=str,
|
|
149
|
+
show_default=True,
|
|
150
|
+
default="",
|
|
151
|
+
help="DISDRODB campaign names to process",
|
|
152
|
+
)(function)
|
|
153
|
+
function = click.option(
|
|
154
|
+
"--station_names",
|
|
155
|
+
type=str,
|
|
156
|
+
show_default=True,
|
|
157
|
+
default="",
|
|
158
|
+
help="DISDRODB station names to process",
|
|
159
|
+
)(function)
|
|
160
|
+
return function
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def click_processing_options(function: object):
|
|
164
|
+
"""Click command line default parameters for L0 processing options.
|
|
165
|
+
|
|
166
|
+
Parameters
|
|
167
|
+
----------
|
|
168
|
+
function : object
|
|
169
|
+
Function.
|
|
170
|
+
"""
|
|
171
|
+
function = click.option(
|
|
172
|
+
"-p",
|
|
173
|
+
"--parallel",
|
|
174
|
+
type=bool,
|
|
175
|
+
show_default=True,
|
|
176
|
+
default=False,
|
|
177
|
+
help="Process files in parallel",
|
|
178
|
+
)(function)
|
|
179
|
+
function = click.option(
|
|
180
|
+
"-d",
|
|
181
|
+
"--debugging_mode",
|
|
182
|
+
type=bool,
|
|
183
|
+
show_default=True,
|
|
184
|
+
default=False,
|
|
185
|
+
help="Switch to debugging mode",
|
|
186
|
+
)(function)
|
|
187
|
+
function = click.option("-v", "--verbose", type=bool, show_default=True, default=True, help="Verbose")(function)
|
|
188
|
+
function = click.option(
|
|
189
|
+
"-f",
|
|
190
|
+
"--force",
|
|
191
|
+
type=bool,
|
|
192
|
+
show_default=True,
|
|
193
|
+
default=False,
|
|
194
|
+
help="Force overwriting",
|
|
195
|
+
)(function)
|
|
196
|
+
return function
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def click_remove_l0a_option(function: object):
|
|
200
|
+
"""Click command line argument for ``remove_l0a``."""
|
|
201
|
+
function = click.option(
|
|
202
|
+
"--remove_l0a",
|
|
203
|
+
type=bool,
|
|
204
|
+
show_default=True,
|
|
205
|
+
default=False,
|
|
206
|
+
help="If true, remove the L0A files once the L0B processing is terminated.",
|
|
207
|
+
)(function)
|
|
208
|
+
return function
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def click_remove_l0b_option(function: object):
|
|
212
|
+
"""Click command line argument for ``remove_l0b``."""
|
|
213
|
+
function = click.option(
|
|
214
|
+
"--remove_l0b",
|
|
215
|
+
type=bool,
|
|
216
|
+
show_default=True,
|
|
217
|
+
default=False,
|
|
218
|
+
help="If true, remove the L0B files once the L0C processing is terminated.",
|
|
219
|
+
)(function)
|
|
220
|
+
return function
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def click_l0_archive_options(function: object):
|
|
224
|
+
"""Click command line arguments for L0 processing archiving of a station.
|
|
225
|
+
|
|
226
|
+
Parameters
|
|
227
|
+
----------
|
|
228
|
+
function : object
|
|
229
|
+
Function.
|
|
230
|
+
"""
|
|
231
|
+
function = click.option(
|
|
232
|
+
"--remove_l0b",
|
|
233
|
+
type=bool,
|
|
234
|
+
show_default=True,
|
|
235
|
+
default=False,
|
|
236
|
+
help="If true, remove all source L0B files once L0B concatenation is terminated.",
|
|
237
|
+
)(function)
|
|
238
|
+
function = click.option(
|
|
239
|
+
"--remove_l0a",
|
|
240
|
+
type=bool,
|
|
241
|
+
show_default=True,
|
|
242
|
+
default=False,
|
|
243
|
+
help="If true, remove the L0A files once the L0B processing is terminated.",
|
|
244
|
+
)(function)
|
|
245
|
+
function = click.option(
|
|
246
|
+
"-l0c",
|
|
247
|
+
"--l0c_processing",
|
|
248
|
+
type=bool,
|
|
249
|
+
show_default=True,
|
|
250
|
+
default=True,
|
|
251
|
+
help="Perform L0C processing.",
|
|
252
|
+
)(function)
|
|
253
|
+
function = click.option(
|
|
254
|
+
"-l0b",
|
|
255
|
+
"--l0b_processing",
|
|
256
|
+
type=bool,
|
|
257
|
+
show_default=True,
|
|
258
|
+
default=True,
|
|
259
|
+
help="Perform L0B processing.",
|
|
260
|
+
)(function)
|
|
261
|
+
function = click.option(
|
|
262
|
+
"-l0a",
|
|
263
|
+
"--l0a_processing",
|
|
264
|
+
type=bool,
|
|
265
|
+
show_default=True,
|
|
266
|
+
default=True,
|
|
267
|
+
help="Perform L0A processing.",
|
|
268
|
+
)(function)
|
|
269
|
+
return function
|
disdrodb/utils/compression.py
CHANGED
|
@@ -26,9 +26,11 @@ import tempfile
|
|
|
26
26
|
import zipfile
|
|
27
27
|
from typing import Optional
|
|
28
28
|
|
|
29
|
-
from disdrodb.api.checks import
|
|
29
|
+
from disdrodb.api.checks import check_data_archive_dir
|
|
30
30
|
from disdrodb.api.path import define_station_dir
|
|
31
|
+
from disdrodb.configs import get_data_archive_dir
|
|
31
32
|
from disdrodb.utils.directories import list_files
|
|
33
|
+
from disdrodb.utils.yaml import read_yaml
|
|
32
34
|
|
|
33
35
|
COMPRESSION_OPTIONS = {
|
|
34
36
|
"zip": ".zip",
|
|
@@ -38,17 +40,15 @@ COMPRESSION_OPTIONS = {
|
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
def unzip_file(filepath: str, dest_path: str) -> None:
|
|
41
|
-
"""Unzip a file into a directory
|
|
43
|
+
"""Unzip a file into a directory.
|
|
42
44
|
|
|
43
45
|
Parameters
|
|
44
|
-
|
|
45
46
|
----------
|
|
46
47
|
filepath : str
|
|
47
|
-
Path of the file to unzip
|
|
48
|
+
Path of the file to unzip.
|
|
48
49
|
dest_path : str
|
|
49
|
-
Path of the destination directory
|
|
50
|
+
Path of the destination directory.
|
|
50
51
|
"""
|
|
51
|
-
|
|
52
52
|
with zipfile.ZipFile(filepath, "r") as zip_ref:
|
|
53
53
|
zip_ref.extractall(dest_path)
|
|
54
54
|
|
|
@@ -59,21 +59,29 @@ def _zip_dir(dir_path: str) -> str:
|
|
|
59
59
|
Parameters
|
|
60
60
|
----------
|
|
61
61
|
dir_path : str
|
|
62
|
-
Path of the directory to zip
|
|
62
|
+
Path of the directory to zip.
|
|
63
63
|
|
|
64
64
|
Returns
|
|
65
65
|
-------
|
|
66
66
|
str
|
|
67
|
-
Path of the zip archive
|
|
67
|
+
Path of the zip archive.
|
|
68
68
|
"""
|
|
69
|
-
|
|
70
69
|
output_path_without_extension = os.path.join(tempfile.gettempdir(), os.path.basename(dir_path))
|
|
71
70
|
output_path = output_path_without_extension + ".zip"
|
|
72
71
|
shutil.make_archive(output_path_without_extension, "zip", dir_path)
|
|
73
72
|
return output_path
|
|
74
73
|
|
|
75
74
|
|
|
76
|
-
def
|
|
75
|
+
def check_consistent_station_name(metadata_filepath, station_name):
|
|
76
|
+
"""Check consistent station_name between YAML file name and metadata key."""
|
|
77
|
+
# Check consistent station name
|
|
78
|
+
expected_station_name = os.path.basename(metadata_filepath).replace(".yml", "")
|
|
79
|
+
if station_name and str(station_name) != str(expected_station_name):
|
|
80
|
+
raise ValueError(f"Inconsistent station_name values in the {metadata_filepath} file. Download aborted.")
|
|
81
|
+
return station_name
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def archive_station_data(metadata_filepath: str, data_archive_dir: str) -> str:
|
|
77
85
|
"""Archive station data into a zip file for subsequent data upload.
|
|
78
86
|
|
|
79
87
|
It create a zip file into a temporary directory !
|
|
@@ -83,26 +91,42 @@ def archive_station_data(metadata_filepath: str) -> str:
|
|
|
83
91
|
metadata_filepath: str
|
|
84
92
|
Metadata file path.
|
|
85
93
|
|
|
86
|
-
Returns
|
|
87
|
-
-------
|
|
88
|
-
station_zip_filepath
|
|
89
|
-
Filepath of the zip file containing the station's data.
|
|
90
94
|
"""
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
# Open metadata file
|
|
96
|
+
metadata_dict = read_yaml(metadata_filepath)
|
|
97
|
+
# Retrieve station information
|
|
98
|
+
data_archive_dir = get_data_archive_dir(data_archive_dir)
|
|
99
|
+
data_source = metadata_dict["data_source"]
|
|
100
|
+
campaign_name = metadata_dict["campaign_name"]
|
|
101
|
+
station_name = metadata_dict["station_name"]
|
|
102
|
+
station_name = check_consistent_station_name(metadata_filepath, station_name)
|
|
103
|
+
# Define the destination local filepath path
|
|
104
|
+
station_dir = define_station_dir(
|
|
105
|
+
data_archive_dir=data_archive_dir,
|
|
106
|
+
data_source=data_source,
|
|
107
|
+
campaign_name=campaign_name,
|
|
108
|
+
station_name=station_name,
|
|
109
|
+
product="RAW",
|
|
110
|
+
)
|
|
111
|
+
# Zip station directory
|
|
112
|
+
station_zip_filepath = _zip_dir(station_dir)
|
|
94
113
|
return station_zip_filepath
|
|
95
114
|
|
|
96
115
|
|
|
97
116
|
def compress_station_files(
|
|
98
|
-
|
|
117
|
+
data_archive_dir: str,
|
|
118
|
+
data_source: str,
|
|
119
|
+
campaign_name: str,
|
|
120
|
+
station_name: str,
|
|
121
|
+
method: str = "gzip",
|
|
122
|
+
skip: bool = True,
|
|
99
123
|
) -> None:
|
|
100
124
|
"""Compress each raw file of a station.
|
|
101
125
|
|
|
102
126
|
Parameters
|
|
103
127
|
----------
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
data_archive_dir : str
|
|
129
|
+
DISDRODB Data Archive directory
|
|
106
130
|
data_source : str
|
|
107
131
|
Name of data source of interest.
|
|
108
132
|
campaign_name : str
|
|
@@ -110,19 +134,19 @@ def compress_station_files(
|
|
|
110
134
|
station_name : str
|
|
111
135
|
Station name of interest.
|
|
112
136
|
method : str
|
|
113
|
-
Compression method. "zip"
|
|
137
|
+
Compression method. ``"zip"``, ``"gzip"`` or ``"bzip2"``.
|
|
114
138
|
skip : bool
|
|
115
139
|
Whether to raise an error if a file is already compressed.
|
|
116
|
-
If True
|
|
117
|
-
If False
|
|
118
|
-
|
|
140
|
+
If ``True``, it does not raise an error and try to compress the other files.
|
|
141
|
+
If ``False``, it raise an error and stop the compression routine.
|
|
142
|
+
The default value is ``True``.
|
|
119
143
|
"""
|
|
120
144
|
if method not in COMPRESSION_OPTIONS:
|
|
121
145
|
raise ValueError(f"Invalid compression method {method}. Valid methods are {list(COMPRESSION_OPTIONS.keys())}")
|
|
122
146
|
|
|
123
|
-
|
|
147
|
+
data_archive_dir = check_data_archive_dir(data_archive_dir)
|
|
124
148
|
station_dir = define_station_dir(
|
|
125
|
-
|
|
149
|
+
data_archive_dir=data_archive_dir,
|
|
126
150
|
product="RAW",
|
|
127
151
|
data_source=data_source,
|
|
128
152
|
campaign_name=campaign_name,
|
|
@@ -137,7 +161,7 @@ def compress_station_files(
|
|
|
137
161
|
for filepath in filepaths:
|
|
138
162
|
_ = _compress_file(filepath, method, skip=skip)
|
|
139
163
|
|
|
140
|
-
print("All files of {data_source} {campaign_name} {station_name} have been compressed.")
|
|
164
|
+
print(f"All files of {data_source} {campaign_name} {station_name} have been compressed.")
|
|
141
165
|
print("Please now remember to update the glob_pattern of the reader ¨!")
|
|
142
166
|
|
|
143
167
|
|
|
@@ -151,11 +175,11 @@ def _compress_file(filepath: str, method: str, skip: bool) -> str:
|
|
|
151
175
|
filepath : str
|
|
152
176
|
Path of the file to compress.
|
|
153
177
|
method : str
|
|
154
|
-
Compression method. None
|
|
178
|
+
Compression method. ``None``, ``"zip"``, ``"gzip"`` or ``"bzip2"``.
|
|
155
179
|
skip : bool
|
|
156
180
|
Whether to raise an error if a file is already compressed.
|
|
157
|
-
If True
|
|
158
|
-
If False
|
|
181
|
+
If ``True``, it does not raise an error return the input filepath.
|
|
182
|
+
If ``False``, it raise an error.
|
|
159
183
|
|
|
160
184
|
Returns
|
|
161
185
|
-------
|
|
@@ -169,8 +193,7 @@ def _compress_file(filepath: str, method: str, skip: bool) -> str:
|
|
|
169
193
|
if skip:
|
|
170
194
|
print(f"File {filepath} is already compressed. Skipping.")
|
|
171
195
|
return filepath
|
|
172
|
-
|
|
173
|
-
raise ValueError(f"File {filepath} is already compressed !")
|
|
196
|
+
raise ValueError(f"File {filepath} is already compressed !")
|
|
174
197
|
|
|
175
198
|
extension = COMPRESSION_OPTIONS[method]
|
|
176
199
|
archive_name = os.path.basename(filepath) + extension
|
|
@@ -200,7 +223,7 @@ def _check_file_compression(filepath: str) -> Optional[str]:
|
|
|
200
223
|
Returns
|
|
201
224
|
-------
|
|
202
225
|
Optional[str]
|
|
203
|
-
Compression method. None
|
|
226
|
+
Compression method. ``None``, ``"zip"``, ``"gzip"`` or ``"bzip2"``.
|
|
204
227
|
|
|
205
228
|
"""
|
|
206
229
|
magic_dict = {
|
|
@@ -229,7 +252,6 @@ def _compress_file_zip(filepath: str, compressed_filepath: str) -> None:
|
|
|
229
252
|
Path of the compressed file.
|
|
230
253
|
|
|
231
254
|
"""
|
|
232
|
-
|
|
233
255
|
with zipfile.ZipFile(compressed_filepath, "w", compression=zipfile.ZIP_DEFLATED) as zipf:
|
|
234
256
|
zipf.write(filepath, os.path.basename(filepath))
|
|
235
257
|
|
|
@@ -246,10 +268,8 @@ def _compress_file_gzip(filepath: str, compressed_filepath: str) -> None:
|
|
|
246
268
|
Path of the compressed file.
|
|
247
269
|
|
|
248
270
|
"""
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
with gzip.open(compressed_filepath, "wb") as f_out:
|
|
252
|
-
f_out.writelines(f_in)
|
|
271
|
+
with open(filepath, "rb") as f_in, gzip.open(compressed_filepath, "wb") as f_out:
|
|
272
|
+
f_out.writelines(f_in)
|
|
253
273
|
|
|
254
274
|
|
|
255
275
|
def _compress_file_bzip2(filepath: str, compressed_filepath: str) -> None:
|
|
@@ -264,7 +284,5 @@ def _compress_file_bzip2(filepath: str, compressed_filepath: str) -> None:
|
|
|
264
284
|
Path of the compressed file.
|
|
265
285
|
|
|
266
286
|
"""
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
with bz2.open(compressed_filepath, "wb") as f_out:
|
|
270
|
-
f_out.writelines(f_in)
|
|
287
|
+
with open(filepath, "rb") as f_in, bz2.open(compressed_filepath, "wb") as f_out:
|
|
288
|
+
f_out.writelines(f_in)
|
disdrodb/utils/dask.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
"""Utilities for Dask Distributed computations."""
|
|
20
|
+
import logging
|
|
21
|
+
import os
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def initialize_dask_cluster():
|
|
25
|
+
"""Initialize Dask Cluster."""
|
|
26
|
+
import dask
|
|
27
|
+
from dask.distributed import Client, LocalCluster
|
|
28
|
+
|
|
29
|
+
# Set HDF5_USE_FILE_LOCKING to avoid going stuck with HDF
|
|
30
|
+
os.environ["HDF5_USE_FILE_LOCKING"] = "FALSE"
|
|
31
|
+
# Retrieve the number of process to run
|
|
32
|
+
available_workers = os.cpu_count() - 2 # if not set, all CPUs
|
|
33
|
+
num_workers = dask.config.get("num_workers", available_workers)
|
|
34
|
+
# Silence dask warnings
|
|
35
|
+
dask.config.set({"logging.distributed": "error"})
|
|
36
|
+
# dask.config.set({"distributed.admin.system-monitor.gil.enabled": False})
|
|
37
|
+
# Create dask.distributed local cluster
|
|
38
|
+
cluster = LocalCluster(
|
|
39
|
+
n_workers=num_workers,
|
|
40
|
+
threads_per_worker=1,
|
|
41
|
+
processes=True,
|
|
42
|
+
# memory_limit='8GB',
|
|
43
|
+
# silence_logs=False,
|
|
44
|
+
)
|
|
45
|
+
client = Client(cluster)
|
|
46
|
+
return cluster, client
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def close_dask_cluster(cluster, client):
|
|
50
|
+
"""Close Dask Cluster."""
|
|
51
|
+
logger = logging.getLogger()
|
|
52
|
+
# Backup current log level
|
|
53
|
+
original_level = logger.level
|
|
54
|
+
logger.setLevel(logging.CRITICAL + 1) # Set level to suppress all logs
|
|
55
|
+
# Close cluster
|
|
56
|
+
# - Avoid log 'distributed.worker - ERROR - Failed to communicate with scheduler during heartbeat.'
|
|
57
|
+
try:
|
|
58
|
+
cluster.close()
|
|
59
|
+
client.close()
|
|
60
|
+
finally:
|
|
61
|
+
# Restore the original log level
|
|
62
|
+
logger.setLevel(original_level)
|
|
@@ -0,0 +1,110 @@
|
|
|
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
|
+
"""DISDRODB decorators."""
|
|
20
|
+
import functools
|
|
21
|
+
import importlib
|
|
22
|
+
|
|
23
|
+
import dask
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def delayed_if_parallel(function):
|
|
27
|
+
"""Decorator to make the function delayed if its ``parallel`` argument is ``True``."""
|
|
28
|
+
|
|
29
|
+
@functools.wraps(function)
|
|
30
|
+
def wrapper(*args, **kwargs):
|
|
31
|
+
# Check if it must be a delayed function
|
|
32
|
+
parallel = kwargs.get("parallel")
|
|
33
|
+
# If parallel is True
|
|
34
|
+
if parallel:
|
|
35
|
+
# Enforce verbose to be False
|
|
36
|
+
kwargs["verbose"] = False
|
|
37
|
+
# Define the delayed task
|
|
38
|
+
result = dask.delayed(function)(*args, **kwargs)
|
|
39
|
+
else:
|
|
40
|
+
# Else run the function
|
|
41
|
+
result = function(*args, **kwargs)
|
|
42
|
+
return result
|
|
43
|
+
|
|
44
|
+
return wrapper
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def single_threaded_if_parallel(function):
|
|
48
|
+
"""Decorator to make a function use a single threadon delayed if its ``parallel`` argument is ``True``."""
|
|
49
|
+
|
|
50
|
+
@functools.wraps(function)
|
|
51
|
+
def wrapper(*args, **kwargs):
|
|
52
|
+
# Check if it must be a delayed function
|
|
53
|
+
parallel = kwargs.get("parallel")
|
|
54
|
+
# If parallel is True
|
|
55
|
+
if parallel:
|
|
56
|
+
# Call function with single thread
|
|
57
|
+
# with dask.config.set(scheduler='single-threaded'):
|
|
58
|
+
with dask.config.set(scheduler="synchronous"):
|
|
59
|
+
result = function(*args, **kwargs)
|
|
60
|
+
else:
|
|
61
|
+
# Else run the function as usual
|
|
62
|
+
result = function(*args, **kwargs)
|
|
63
|
+
return result
|
|
64
|
+
|
|
65
|
+
return wrapper
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def check_software_availability(software, conda_package):
|
|
69
|
+
"""A decorator to ensure that a software package is installed.
|
|
70
|
+
|
|
71
|
+
Parameters
|
|
72
|
+
----------
|
|
73
|
+
software : str
|
|
74
|
+
The package name as recognized by Python's import system.
|
|
75
|
+
conda_package : str
|
|
76
|
+
The package name as recognized by conda-forge.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def decorator(func):
|
|
80
|
+
@functools.wraps(func)
|
|
81
|
+
def wrapper(*args, **kwargs):
|
|
82
|
+
if not importlib.util.find_spec(software):
|
|
83
|
+
raise ImportError(
|
|
84
|
+
f"The '{software}' package is required but not found.\n"
|
|
85
|
+
"Please install it using conda:\n"
|
|
86
|
+
f" conda install -c conda-forge {conda_package}",
|
|
87
|
+
)
|
|
88
|
+
return func(*args, **kwargs)
|
|
89
|
+
|
|
90
|
+
return wrapper
|
|
91
|
+
|
|
92
|
+
return decorator
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def check_pytmatrix_availability(func):
|
|
96
|
+
"""Decorator to ensure that the 'pytmatrix' package is installed."""
|
|
97
|
+
|
|
98
|
+
@functools.wraps(func)
|
|
99
|
+
def wrapper(*args, **kwargs):
|
|
100
|
+
if not importlib.util.find_spec("pytmatrix"):
|
|
101
|
+
raise ImportError(
|
|
102
|
+
"The 'pytmatrix' package is required but not found. \n"
|
|
103
|
+
"Please install the following software: \n"
|
|
104
|
+
" conda install conda-forge gfortran \n"
|
|
105
|
+
" conda install conda-forge meson \n"
|
|
106
|
+
" pip install git+https://github.com/ltelab/pytmatrix-lte.git@main \n",
|
|
107
|
+
)
|
|
108
|
+
return func(*args, **kwargs)
|
|
109
|
+
|
|
110
|
+
return wrapper
|