disdrodb 0.2.1__py3-none-any.whl → 0.4.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 +3 -1
- disdrodb/_config.py +2 -3
- disdrodb/_version.py +2 -2
- disdrodb/accessor/__init__.py +2 -1
- disdrodb/accessor/methods.py +10 -9
- disdrodb/api/checks.py +3 -7
- disdrodb/api/configs.py +1 -3
- disdrodb/api/create_directories.py +4 -6
- disdrodb/api/info.py +1 -3
- disdrodb/api/io.py +233 -32
- disdrodb/api/path.py +3 -7
- disdrodb/cli/disdrodb_check_metadata_archive.py +3 -2
- disdrodb/cli/disdrodb_check_products_options.py +45 -0
- disdrodb/cli/disdrodb_create_summary.py +54 -28
- disdrodb/cli/disdrodb_create_summary_station.py +41 -20
- disdrodb/cli/disdrodb_data_archive_directory.py +2 -3
- disdrodb/cli/disdrodb_download_archive.py +50 -30
- disdrodb/cli/disdrodb_download_metadata_archive.py +28 -16
- disdrodb/cli/disdrodb_download_station.py +58 -29
- disdrodb/cli/disdrodb_initialize_station.py +43 -23
- disdrodb/cli/disdrodb_metadata_archive_directory.py +2 -3
- disdrodb/cli/disdrodb_open_data_archive.py +17 -13
- disdrodb/cli/disdrodb_open_logs_directory.py +31 -21
- disdrodb/cli/disdrodb_open_metadata_archive.py +26 -13
- disdrodb/cli/disdrodb_open_metadata_directory.py +34 -23
- disdrodb/cli/disdrodb_open_product_directory.py +39 -23
- disdrodb/cli/disdrodb_open_readers_directory.py +2 -3
- disdrodb/cli/disdrodb_run.py +189 -0
- disdrodb/cli/disdrodb_run_l0.py +61 -70
- disdrodb/cli/disdrodb_run_l0_station.py +50 -55
- disdrodb/cli/disdrodb_run_l0a.py +53 -51
- disdrodb/cli/disdrodb_run_l0a_station.py +41 -40
- disdrodb/cli/disdrodb_run_l0b.py +51 -51
- disdrodb/cli/disdrodb_run_l0b_station.py +40 -39
- disdrodb/cli/disdrodb_run_l0c.py +56 -53
- disdrodb/cli/disdrodb_run_l0c_station.py +44 -41
- disdrodb/cli/disdrodb_run_l1.py +55 -51
- disdrodb/cli/disdrodb_run_l1_station.py +43 -40
- disdrodb/cli/disdrodb_run_l2e.py +56 -51
- disdrodb/cli/disdrodb_run_l2e_station.py +44 -40
- disdrodb/cli/disdrodb_run_l2m.py +55 -51
- disdrodb/cli/disdrodb_run_l2m_station.py +43 -40
- disdrodb/cli/disdrodb_run_station.py +184 -0
- disdrodb/cli/disdrodb_upload_archive.py +51 -42
- disdrodb/cli/disdrodb_upload_station.py +42 -36
- disdrodb/configs.py +20 -16
- disdrodb/constants.py +5 -2
- disdrodb/data_transfer/__init__.py +1 -3
- disdrodb/data_transfer/download_data.py +45 -61
- disdrodb/data_transfer/upload_data.py +7 -11
- disdrodb/data_transfer/zenodo.py +2 -4
- disdrodb/docs.py +1 -3
- disdrodb/etc/configs/attributes.yaml +52 -2
- disdrodb/etc/configs/encodings.yaml +45 -1
- disdrodb/etc/products/L0C/ODM470/global.yaml +5 -0
- disdrodb/etc/products/L0C/global.yaml +5 -0
- disdrodb/etc/products/L1/ODM470/global.yaml +6 -0
- disdrodb/etc/products/L1/global.yaml +0 -13
- disdrodb/etc/products/L2E/LPM/1MIN.yaml +1 -0
- disdrodb/etc/products/L2E/LPM/global.yaml +36 -0
- disdrodb/etc/products/L2E/LPM_V0/1MIN.yaml +1 -0
- disdrodb/etc/products/L2E/LPM_V0/global.yaml +36 -0
- disdrodb/etc/products/L2E/ODM470/1MIN.yaml +1 -0
- disdrodb/etc/products/L2E/ODM470/global.yaml +36 -0
- disdrodb/etc/products/L2E/PARSIVEL/1MIN.yaml +1 -0
- disdrodb/etc/products/L2E/PARSIVEL/global.yaml +36 -0
- disdrodb/etc/products/L2E/PARSIVEL2/1MIN.yaml +1 -0
- disdrodb/etc/products/L2E/PARSIVEL2/global.yaml +36 -0
- disdrodb/etc/products/L2E/PWS100/1MIN.yaml +1 -0
- disdrodb/etc/products/L2E/PWS100/global.yaml +36 -0
- disdrodb/etc/products/L2E/RD80/1MIN.yaml +19 -0
- disdrodb/etc/products/L2E/SWS250/1MIN.yaml +19 -0
- disdrodb/etc/products/L2E/global.yaml +16 -2
- disdrodb/fall_velocity/__init__.py +47 -0
- disdrodb/fall_velocity/graupel.py +484 -0
- disdrodb/fall_velocity/hail.py +288 -0
- disdrodb/{l1/fall_velocity.py → fall_velocity/rain.py} +265 -44
- disdrodb/issue/__init__.py +1 -3
- disdrodb/issue/checks.py +2 -3
- disdrodb/issue/reader.py +2 -3
- disdrodb/issue/writer.py +2 -5
- disdrodb/l0/__init__.py +2 -1
- disdrodb/l0/check_configs.py +36 -29
- disdrodb/l0/check_standards.py +1 -4
- disdrodb/l0/configs/LPM/l0a_encodings.yml +17 -17
- disdrodb/l0/configs/LPM/l0b_cf_attrs.yml +55 -55
- disdrodb/l0/configs/LPM/l0b_encodings.yml +17 -17
- disdrodb/l0/configs/LPM/raw_data_format.yml +17 -17
- disdrodb/l0/configs/LPM_V0/l0a_encodings.yml +2 -2
- disdrodb/l0/configs/LPM_V0/l0b_cf_attrs.yml +2 -2
- disdrodb/l0/configs/LPM_V0/l0b_encodings.yml +2 -2
- disdrodb/l0/configs/LPM_V0/raw_data_format.yml +2 -2
- disdrodb/l0/configs/ODM470/bins_diameter.yml +643 -0
- disdrodb/l0/configs/ODM470/bins_velocity.yml +0 -0
- disdrodb/l0/configs/ODM470/l0a_encodings.yml +11 -0
- disdrodb/l0/configs/ODM470/l0b_cf_attrs.yml +46 -0
- disdrodb/l0/configs/ODM470/l0b_encodings.yml +106 -0
- disdrodb/l0/configs/ODM470/raw_data_format.yml +111 -0
- disdrodb/l0/configs/PARSIVEL/l0b_cf_attrs.yml +1 -1
- disdrodb/l0/l0_reader.py +2 -3
- disdrodb/l0/l0a_processing.py +6 -8
- disdrodb/l0/l0b_nc_processing.py +3 -6
- disdrodb/l0/l0b_processing.py +2 -16
- disdrodb/l0/l0c_processing.py +29 -12
- disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +2 -1
- disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +18 -18
- disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +18 -18
- disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +18 -18
- disdrodb/l0/readers/LPM/GERMANY/DWD.py +244 -63
- disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +65 -23
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_AQ.py +277 -0
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_PI.py +19 -18
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_T.py +23 -19
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_W.py +19 -21
- disdrodb/l0/readers/LPM/KIT/CHWALA.py +19 -20
- disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_LPM_NC.py +1 -1
- disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_RWANDA_LPM_NC.py +18 -18
- disdrodb/l0/readers/LPM/NORWAY/HAUKELISETER_LPM.py +19 -20
- disdrodb/l0/readers/LPM/NORWAY/NMBU_LPM.py +19 -20
- disdrodb/l0/readers/LPM/SLOVENIA/ARSO.py +19 -20
- disdrodb/l0/readers/LPM/SLOVENIA/UL.py +19 -20
- disdrodb/l0/readers/LPM/SWITZERLAND/INNERERIZ_LPM.py +19 -20
- disdrodb/l0/readers/LPM/UK/DIVEN.py +1 -1
- disdrodb/l0/readers/LPM/UK/WITHWORTH_LPM.py +19 -20
- disdrodb/l0/readers/LPM/USA/CHARLESTON.py +19 -20
- disdrodb/l0/readers/LPM/USA/DEVEX.py +255 -0
- disdrodb/l0/readers/LPM_V0/BELGIUM/ULIEGE.py +3 -5
- disdrodb/l0/readers/LPM_V0/ITALY/GID_LPM_V0.py +4 -3
- disdrodb/l0/readers/ODM470/OCEAN/OCEANRAIN.py +124 -0
- disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +1 -1
- disdrodb/l0/readers/PARSIVEL/BASQUECOUNTRY/EUSKALMET_OTT.py +2 -1
- disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +2 -3
- disdrodb/l0/readers/PARSIVEL/EPFL/ARCTIC_2021.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/COMMON_2011.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/DAVOS_2009_2011.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_2009.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2008.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2011.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2012.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/GENEPI_2007.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007_2.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/HPICONET_2010.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP2.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP4.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/LOCARNO_2018.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/LOCARNO_2019.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/PARADISO_2014.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/PARSIVEL_2007.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/PLATO_2019.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019_WJF.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/RIETHOLZBACH_2011.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +2 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/UNIL_2022.py +2 -1
- disdrodb/l0/readers/PARSIVEL/JAPAN/JMA.py +1 -1
- disdrodb/l0/readers/PARSIVEL/KOREA/ICEPOP_MSC.py +159 -0
- disdrodb/l0/readers/PARSIVEL/NASA/LPVEX.py +1 -1
- disdrodb/l0/readers/PARSIVEL/NASA/MC3E.py +1 -1
- disdrodb/l0/readers/PARSIVEL/NCAR/CCOPE_2015.py +1 -1
- disdrodb/l0/readers/PARSIVEL/NCAR/OWLES_MIPS.py +1 -1
- disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +1 -1
- disdrodb/l0/readers/PARSIVEL/NCAR/PLOWS_MIPS.py +1 -1
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +1 -1
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +1 -3
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +1 -3
- disdrodb/l0/readers/PARSIVEL/SLOVENIA/UL.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/ARM/ARM_PARSIVEL2.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/BASQUECOUNTRY/EUSKALMET_OTT2.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/BELGIUM/ILVO.py +2 -3
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/CANADA/UQAM_NC.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/DENMARK/DTU.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_nc.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_raw.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/FINLAND/FMI_PARSIVEL2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/FRANCE/ENPC_PARSIVEL2.py +2 -3
- disdrodb/l0/readers/PARSIVEL2/FRANCE/OSUG.py +2 -2
- disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +1 -3
- disdrodb/l0/readers/PARSIVEL2/GREECE/NOA.py +4 -3
- disdrodb/l0/readers/PARSIVEL2/ITALY/GID_PARSIVEL2.py +1 -3
- disdrodb/l0/readers/PARSIVEL2/ITALY/HYDROX.py +6 -3
- disdrodb/l0/readers/PARSIVEL2/JAPAN/PRECIP.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/KIT/BURKINA_FASO.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/KIT/TEAMX.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/KOREA/ICEPOP_MSC.py +161 -0
- disdrodb/l0/readers/PARSIVEL2/KOREA/ICEPOP_UCLM.py +126 -0
- disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/MPI/BCO_PARSIVEL2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/MPI/BOWTIE.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NASA/APU.py +3 -1
- disdrodb/l0/readers/PARSIVEL2/NASA/NSSTC.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/FARM_PARSIVEL2.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_MIPS.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_MIPS.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_PIPS.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P1.py +2 -3
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT_NC.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NORWAY/UIB.py +10 -2
- disdrodb/l0/readers/PARSIVEL2/PHILIPPINES/PAGASA.py +2 -3
- disdrodb/l0/readers/PARSIVEL2/SPAIN/CENER.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/SPAIN/CR1000DL.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/SPAIN/GRANADA.py +2 -3
- disdrodb/l0/readers/PARSIVEL2/SPAIN/LIAISE.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/SWEDEN/SMHI.py +2 -1
- disdrodb/l0/readers/PARSIVEL2/USA/CSU.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/USA/CW3E.py +2 -1
- disdrodb/l0/readers/PWS100/AUSTRIA/HOAL.py +2 -3
- disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100.py +2 -3
- disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100_SIRTA.py +2 -1
- disdrodb/l0/readers/RD80/BRAZIL/ATTO_RD80.py +1 -3
- disdrodb/l0/readers/RD80/BRAZIL/CHUVA_RD80.py +1 -3
- disdrodb/l0/readers/RD80/BRAZIL/GOAMAZON_RD80.py +1 -3
- disdrodb/l0/readers/RD80/NCAR/CINDY_2011_RD80.py +1 -3
- disdrodb/l0/readers/RD80/NCAR/RELAMPAGO_RD80.py +1 -3
- disdrodb/l0/readers/RD80/NOAA/PSL_RD80.py +2 -3
- disdrodb/l0/readers/SWS250/BELGIUM/KMI.py +2 -3
- disdrodb/l0/readers/template_reader_raw_netcdf_data.py +2 -3
- disdrodb/l0/readers/template_reader_raw_text_data.py +2 -3
- disdrodb/l0/standards.py +4 -5
- disdrodb/l0/template_tools.py +7 -11
- disdrodb/l1/__init__.py +2 -1
- disdrodb/l1/classification.py +914 -0
- disdrodb/l1/processing.py +36 -106
- disdrodb/l1/resampling.py +13 -3
- disdrodb/l1_env/__init__.py +1 -1
- disdrodb/l1_env/routines.py +7 -6
- disdrodb/l2/__init__.py +2 -1
- disdrodb/l2/empirical_dsd.py +58 -31
- disdrodb/l2/processing.py +327 -61
- disdrodb/metadata/checks.py +10 -13
- disdrodb/metadata/download.py +5 -4
- disdrodb/metadata/geolocation.py +3 -4
- disdrodb/metadata/info.py +3 -5
- disdrodb/metadata/manipulation.py +1 -3
- disdrodb/metadata/reader.py +1 -3
- disdrodb/metadata/search.py +1 -4
- disdrodb/metadata/standards.py +1 -3
- disdrodb/metadata/writer.py +1 -3
- disdrodb/physics/__init__.py +17 -0
- disdrodb/physics/atmosphere.py +273 -0
- disdrodb/physics/water.py +131 -0
- disdrodb/physics/wrappers.py +63 -0
- disdrodb/psd/__init__.py +1 -2
- disdrodb/psd/fitting.py +23 -9
- disdrodb/psd/models.py +2 -1
- disdrodb/routines/__init__.py +6 -1
- disdrodb/routines/l0.py +39 -25
- disdrodb/routines/l1.py +23 -16
- disdrodb/routines/l2.py +12 -9
- disdrodb/routines/options.py +117 -73
- disdrodb/routines/options_validation.py +728 -0
- disdrodb/routines/wrappers.py +460 -40
- disdrodb/scattering/__init__.py +1 -2
- disdrodb/scattering/axis_ratio.py +6 -6
- disdrodb/scattering/permittivity.py +9 -8
- disdrodb/scattering/routines.py +33 -15
- disdrodb/summary/__init__.py +1 -1
- disdrodb/summary/routines.py +95 -30
- disdrodb/utils/__init__.py +1 -1
- disdrodb/utils/archiving.py +18 -10
- disdrodb/utils/attrs.py +7 -5
- disdrodb/utils/cli.py +8 -10
- disdrodb/utils/compression.py +10 -13
- disdrodb/utils/coords.py +45 -0
- disdrodb/utils/dask.py +7 -5
- disdrodb/utils/dataframe.py +5 -6
- disdrodb/utils/decorators.py +3 -4
- disdrodb/utils/dict.py +1 -1
- disdrodb/utils/directories.py +5 -7
- disdrodb/utils/encoding.py +4 -5
- disdrodb/utils/event.py +1 -1
- disdrodb/utils/list.py +1 -3
- disdrodb/utils/logger.py +1 -3
- disdrodb/utils/manipulations.py +175 -4
- disdrodb/utils/pydantic.py +81 -0
- disdrodb/utils/routines.py +2 -3
- disdrodb/utils/subsetting.py +1 -1
- disdrodb/utils/time.py +6 -4
- disdrodb/utils/warnings.py +2 -3
- disdrodb/utils/writer.py +5 -3
- disdrodb/utils/xarray.py +31 -3
- disdrodb/utils/yaml.py +1 -3
- disdrodb/viz/__init__.py +1 -1
- disdrodb/viz/plots.py +193 -18
- {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/METADATA +5 -4
- disdrodb-0.4.0.dist-info/RECORD +361 -0
- {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/entry_points.txt +3 -0
- disdrodb/etc/products/L1/1MIN.yaml +0 -13
- disdrodb/etc/products/L1/LPM/1MIN.yaml +0 -13
- disdrodb/etc/products/L1/LPM_V0/1MIN.yaml +0 -13
- disdrodb/etc/products/L1/PARSIVEL/1MIN.yaml +0 -13
- disdrodb/etc/products/L1/PARSIVEL2/1MIN.yaml +0 -13
- disdrodb/etc/products/L1/PWS100/1MIN.yaml +0 -13
- disdrodb/etc/products/L1/RD80/1MIN.yaml +0 -13
- disdrodb/etc/products/L1/SWS250/1MIN.yaml +0 -13
- disdrodb/etc/products/L2M/10MIN.yaml +0 -12
- disdrodb/l1/beard_model.py +0 -662
- disdrodb/l1/filters.py +0 -205
- disdrodb-0.2.1.dist-info/RECORD +0 -329
- {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/WHEEL +0 -0
- {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/top_level.txt +0 -0
disdrodb/__init__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------------.
|
|
2
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
3
3
|
#
|
|
4
4
|
# This program is free software: you can redistribute it and/or modify
|
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -20,6 +20,8 @@ import contextlib
|
|
|
20
20
|
import os
|
|
21
21
|
from importlib.metadata import PackageNotFoundError, version
|
|
22
22
|
|
|
23
|
+
os.environ["HDF5_USE_FILE_LOCKING"] = "FALSE"
|
|
24
|
+
|
|
23
25
|
import disdrodb.accessor # noqa
|
|
24
26
|
from disdrodb._config import config # noqa
|
|
25
27
|
from disdrodb.api.configs import available_sensor_names
|
disdrodb/_config.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# -----------------------------------------------------------------------------.
|
|
4
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
5
3
|
#
|
|
6
4
|
# This program is free software: you can redistribute it and/or modify
|
|
7
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -20,6 +18,7 @@
|
|
|
20
18
|
|
|
21
19
|
See https://donfig.readthedocs.io/en/latest/configuration.html for more info.
|
|
22
20
|
"""
|
|
21
|
+
|
|
23
22
|
from donfig import Config
|
|
24
23
|
|
|
25
24
|
from disdrodb.configs import read_configs
|
disdrodb/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0,
|
|
31
|
+
__version__ = version = '0.4.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 4, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
disdrodb/accessor/__init__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------------.
|
|
2
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
3
3
|
#
|
|
4
4
|
# This program is free software: you can redistribute it and/or modify
|
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
# -----------------------------------------------------------------------------.
|
|
17
17
|
"""This directory defines DISDRODB xarray accessors."""
|
|
18
|
+
|
|
18
19
|
from .methods import DISDRODB_DataArray_Accessor, DISDRODB_Dataset_Accessor
|
|
19
20
|
|
|
20
21
|
__all__ = ["DISDRODB_DataArray_Accessor", "DISDRODB_Dataset_Accessor"]
|
disdrodb/accessor/methods.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------------.
|
|
2
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
3
3
|
#
|
|
4
4
|
# This program is free software: you can redistribute it and/or modify
|
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
# -----------------------------------------------------------------------------.
|
|
17
17
|
"""This module defines DISDRODB xarray accessors."""
|
|
18
|
+
|
|
18
19
|
import xarray as xr
|
|
19
20
|
|
|
20
21
|
|
|
@@ -32,7 +33,7 @@ class DISDRODB_Base_Accessor:
|
|
|
32
33
|
from disdrodb.api.checks import check_time
|
|
33
34
|
|
|
34
35
|
if "time" in self._obj.coords:
|
|
35
|
-
start_time = self._obj["time"].to_numpy()
|
|
36
|
+
start_time = self._obj["time"].to_numpy().min()
|
|
36
37
|
else:
|
|
37
38
|
raise ValueError("Time coordinate not found")
|
|
38
39
|
return check_time(start_time)
|
|
@@ -43,7 +44,7 @@ class DISDRODB_Base_Accessor:
|
|
|
43
44
|
from disdrodb.api.checks import check_time
|
|
44
45
|
|
|
45
46
|
if "time" in self._obj.coords:
|
|
46
|
-
end_time = self._obj["time"].to_numpy()
|
|
47
|
+
end_time = self._obj["time"].to_numpy().max()
|
|
47
48
|
else:
|
|
48
49
|
raise ValueError("Time coordinate not found")
|
|
49
50
|
return check_time(end_time)
|
|
@@ -102,6 +103,12 @@ class DISDRODB_Base_Accessor:
|
|
|
102
103
|
|
|
103
104
|
return plot_spectrum(self._obj, **kwargs)
|
|
104
105
|
|
|
106
|
+
def plot_nd(self, **kwargs):
|
|
107
|
+
"""Plot drop number concentration N(D) timeseries."""
|
|
108
|
+
from disdrodb.viz.plots import plot_nd
|
|
109
|
+
|
|
110
|
+
return plot_nd(self._obj, **kwargs)
|
|
111
|
+
|
|
105
112
|
|
|
106
113
|
@xr.register_dataset_accessor("disdrodb")
|
|
107
114
|
class DISDRODB_Dataset_Accessor(DISDRODB_Base_Accessor):
|
|
@@ -122,12 +129,6 @@ class DISDRODB_Dataset_Accessor(DISDRODB_Base_Accessor):
|
|
|
122
129
|
)
|
|
123
130
|
return ds
|
|
124
131
|
|
|
125
|
-
def plot_nd(self, **kwargs):
|
|
126
|
-
"""Plot drop number concentration N(D) timeseries."""
|
|
127
|
-
from disdrodb.viz.plots import plot_nd
|
|
128
|
-
|
|
129
|
-
return plot_nd(self._obj, **kwargs)
|
|
130
|
-
|
|
131
132
|
def plot_raw_and_filtered_spectra(self, **kwargs):
|
|
132
133
|
"""Plot the raw and filtered spectra."""
|
|
133
134
|
from disdrodb.viz.plots import plot_raw_and_filtered_spectra
|
disdrodb/api/checks.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# -----------------------------------------------------------------------------.
|
|
4
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
5
3
|
#
|
|
6
4
|
# This program is free software: you can redistribute it and/or modify
|
|
7
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -17,12 +15,12 @@
|
|
|
17
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
16
|
# -----------------------------------------------------------------------------.
|
|
19
17
|
"""DISDRODB Checks Functions."""
|
|
18
|
+
|
|
20
19
|
import datetime
|
|
21
20
|
import difflib
|
|
22
21
|
import logging
|
|
23
22
|
import os
|
|
24
23
|
import re
|
|
25
|
-
import sys
|
|
26
24
|
import warnings
|
|
27
25
|
|
|
28
26
|
import numpy as np
|
|
@@ -567,9 +565,7 @@ def check_filepaths(filepaths):
|
|
|
567
565
|
|
|
568
566
|
def get_current_utc_time():
|
|
569
567
|
"""Get current UTC time."""
|
|
570
|
-
|
|
571
|
-
return datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
|
|
572
|
-
return datetime.datetime.utcnow()
|
|
568
|
+
return datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
|
|
573
569
|
|
|
574
570
|
|
|
575
571
|
def check_start_end_time(start_time, end_time):
|
disdrodb/api/configs.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# -----------------------------------------------------------------------------.
|
|
4
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
5
3
|
#
|
|
6
4
|
# This program is free software: you can redistribute it and/or modify
|
|
7
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# -----------------------------------------------------------------------------.
|
|
4
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
5
3
|
#
|
|
6
4
|
# This program is free software: you can redistribute it and/or modify
|
|
7
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -23,7 +21,6 @@
|
|
|
23
21
|
|
|
24
22
|
import logging
|
|
25
23
|
import os
|
|
26
|
-
import shutil
|
|
27
24
|
|
|
28
25
|
from disdrodb.api.checks import (
|
|
29
26
|
check_campaign_name,
|
|
@@ -46,6 +43,7 @@ from disdrodb.api.path import (
|
|
|
46
43
|
from disdrodb.configs import get_data_archive_dir, get_metadata_archive_dir
|
|
47
44
|
from disdrodb.utils.directories import (
|
|
48
45
|
create_directory,
|
|
46
|
+
remove_file_or_directories,
|
|
49
47
|
remove_if_exists,
|
|
50
48
|
)
|
|
51
49
|
|
|
@@ -59,7 +57,7 @@ def ensure_empty_data_dir(data_dir, force):
|
|
|
59
57
|
"""Remove the content of the data_dir directory."""
|
|
60
58
|
# If force=True, remove all the directory content
|
|
61
59
|
if force:
|
|
62
|
-
|
|
60
|
+
remove_file_or_directories(data_dir)
|
|
63
61
|
# Recreate the directory
|
|
64
62
|
create_directory(data_dir)
|
|
65
63
|
else:
|
|
@@ -258,7 +256,7 @@ def create_logs_directory(
|
|
|
258
256
|
|
|
259
257
|
# Ensure empty log directory
|
|
260
258
|
if os.path.isdir(logs_dir):
|
|
261
|
-
|
|
259
|
+
remove_file_or_directories(logs_dir)
|
|
262
260
|
|
|
263
261
|
# Create logs directory
|
|
264
262
|
os.makedirs(logs_dir, exist_ok=True)
|
disdrodb/api/info.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# -----------------------------------------------------------------------------.
|
|
4
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
5
3
|
#
|
|
6
4
|
# This program is free software: you can redistribute it and/or modify
|
|
7
5
|
# it under the terms of the GNU General Public License as published by
|
disdrodb/api/io.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# -----------------------------------------------------------------------------.
|
|
4
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
5
3
|
#
|
|
6
4
|
# This program is free software: you can redistribute it and/or modify
|
|
7
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -17,22 +15,23 @@
|
|
|
17
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
16
|
# -----------------------------------------------------------------------------.
|
|
19
17
|
"""Routines to list and open DISDRODB products."""
|
|
18
|
+
|
|
20
19
|
import datetime
|
|
20
|
+
import functools
|
|
21
21
|
import os
|
|
22
|
-
import shutil
|
|
23
22
|
import subprocess
|
|
24
23
|
import sys
|
|
25
24
|
from pathlib import Path
|
|
26
|
-
from typing import Optional
|
|
27
25
|
|
|
28
26
|
import numpy as np
|
|
29
27
|
|
|
30
28
|
from disdrodb.api.checks import (
|
|
31
29
|
check_filepaths,
|
|
32
30
|
check_start_end_time,
|
|
31
|
+
check_time,
|
|
33
32
|
get_current_utc_time,
|
|
34
33
|
)
|
|
35
|
-
from disdrodb.api.info import get_start_end_time_from_filepaths
|
|
34
|
+
from disdrodb.api.info import get_start_end_time_from_filepaths, group_filepaths
|
|
36
35
|
from disdrodb.api.path import (
|
|
37
36
|
define_campaign_dir,
|
|
38
37
|
define_data_dir,
|
|
@@ -41,7 +40,7 @@ from disdrodb.api.path import (
|
|
|
41
40
|
)
|
|
42
41
|
from disdrodb.l0.l0_reader import define_readers_directory
|
|
43
42
|
from disdrodb.utils.dict import extract_product_kwargs
|
|
44
|
-
from disdrodb.utils.directories import list_files
|
|
43
|
+
from disdrodb.utils.directories import list_files, remove_file_or_directories
|
|
45
44
|
from disdrodb.utils.logger import (
|
|
46
45
|
log_info,
|
|
47
46
|
)
|
|
@@ -133,8 +132,8 @@ def find_files(
|
|
|
133
132
|
station_name,
|
|
134
133
|
product,
|
|
135
134
|
debugging_mode: bool = False,
|
|
136
|
-
data_archive_dir:
|
|
137
|
-
metadata_archive_dir:
|
|
135
|
+
data_archive_dir: str | None = None,
|
|
136
|
+
metadata_archive_dir: str | None = None,
|
|
138
137
|
glob_pattern=None,
|
|
139
138
|
start_time=None,
|
|
140
139
|
end_time=None,
|
|
@@ -292,6 +291,42 @@ def _open_raw_files(filepaths, data_source, campaign_name, station_name, metadat
|
|
|
292
291
|
return ds
|
|
293
292
|
|
|
294
293
|
|
|
294
|
+
def list_coordinates_names(ds):
|
|
295
|
+
"""List coordinates of a xarray.Dataset not CF decoded !."""
|
|
296
|
+
coords = set()
|
|
297
|
+
for v in ds.variables:
|
|
298
|
+
attrs = ds[v].attrs
|
|
299
|
+
# auxiliary coordinates
|
|
300
|
+
if "coordinates" in attrs:
|
|
301
|
+
coords |= set(attrs["coordinates"].split())
|
|
302
|
+
# bounds variables
|
|
303
|
+
if "bounds" in attrs:
|
|
304
|
+
coords.add(attrs["bounds"])
|
|
305
|
+
# grid mapping
|
|
306
|
+
if "grid_mapping" in attrs:
|
|
307
|
+
coords.add(attrs["grid_mapping"])
|
|
308
|
+
return coords
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def subset_variables(ds, variables):
|
|
312
|
+
"""Subset variables while keeping coordinates."""
|
|
313
|
+
# Ensure list
|
|
314
|
+
variables = list(variables)
|
|
315
|
+
|
|
316
|
+
# Always keep dimension variables
|
|
317
|
+
dim_vars = list(ds.dims)
|
|
318
|
+
|
|
319
|
+
# Variables referenced by CF relationships
|
|
320
|
+
coords = list_coordinates_names(ds)
|
|
321
|
+
|
|
322
|
+
# Union of everything we must keep
|
|
323
|
+
keep = set(variables) | set(dim_vars) | coords
|
|
324
|
+
|
|
325
|
+
# Only keep variables that exist
|
|
326
|
+
keep = [v for v in keep if v in list(ds.variables)]
|
|
327
|
+
return ds[keep]
|
|
328
|
+
|
|
329
|
+
|
|
295
330
|
def filter_dataset_by_time(ds, start_time=None, end_time=None):
|
|
296
331
|
"""Subset an xarray.Dataset by time, robust to duplicated/non-monotonic indices.
|
|
297
332
|
|
|
@@ -321,6 +356,84 @@ def filter_dataset_by_time(ds, start_time=None, end_time=None):
|
|
|
321
356
|
return ds.isel(time=np.where(mask)[0])
|
|
322
357
|
|
|
323
358
|
|
|
359
|
+
def open_parquet_files(
|
|
360
|
+
filepaths,
|
|
361
|
+
variables=None,
|
|
362
|
+
start_time=None,
|
|
363
|
+
end_time=None,
|
|
364
|
+
time_col="time",
|
|
365
|
+
use_threads=True,
|
|
366
|
+
):
|
|
367
|
+
"""Open Parquet files."""
|
|
368
|
+
import pyarrow.dataset as ds
|
|
369
|
+
|
|
370
|
+
# Open dataset
|
|
371
|
+
dataset = ds.dataset(
|
|
372
|
+
filepaths,
|
|
373
|
+
format="parquet",
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
# Define filters
|
|
377
|
+
filters = []
|
|
378
|
+
if start_time is not None:
|
|
379
|
+
start_time = check_time(start_time)
|
|
380
|
+
filters.append(ds.field(time_col) >= start_time)
|
|
381
|
+
|
|
382
|
+
if end_time is not None:
|
|
383
|
+
end_time = check_time(end_time)
|
|
384
|
+
filters.append(ds.field(time_col) <= end_time)
|
|
385
|
+
|
|
386
|
+
# Combine filters if any exist
|
|
387
|
+
filter_expr = None
|
|
388
|
+
if filters:
|
|
389
|
+
filter_expr = filters[0]
|
|
390
|
+
for f in filters[1:]:
|
|
391
|
+
filter_expr = filter_expr & f
|
|
392
|
+
|
|
393
|
+
# Read table and convert to pandas
|
|
394
|
+
df = dataset.to_table(
|
|
395
|
+
columns=variables,
|
|
396
|
+
filter=filter_expr,
|
|
397
|
+
use_threads=use_threads,
|
|
398
|
+
).to_pandas()
|
|
399
|
+
return df
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def ensure_safe_open_mfdataset(function):
|
|
403
|
+
"""Decorator to ensure safe xarray open_mfdataset.
|
|
404
|
+
|
|
405
|
+
parallel argument is changed to False if:
|
|
406
|
+
- dask threading or single-threaded is active
|
|
407
|
+
- distributed multiprocessing with more than 1 thread per process
|
|
408
|
+
|
|
409
|
+
parallel argument is allowed to be True only if:
|
|
410
|
+
- distributed multiprocessing with only 1 thread per process
|
|
411
|
+
"""
|
|
412
|
+
import dask
|
|
413
|
+
|
|
414
|
+
from disdrodb.utils.dask import check_parallel_validity
|
|
415
|
+
|
|
416
|
+
@functools.wraps(function)
|
|
417
|
+
def wrapper(*args, **kwargs):
|
|
418
|
+
# Check if it must be a delayed function
|
|
419
|
+
parallel = kwargs.get("parallel", False)
|
|
420
|
+
parallel = check_parallel_validity(parallel)
|
|
421
|
+
kwargs["parallel"] = parallel
|
|
422
|
+
|
|
423
|
+
# If parallel is True at this stage, means being using
|
|
424
|
+
# multiprocessing or dask.distributed with single thread
|
|
425
|
+
if parallel:
|
|
426
|
+
return function(*args, **kwargs)
|
|
427
|
+
|
|
428
|
+
# Call function with single threading
|
|
429
|
+
with dask.config.set(scheduler="single-threaded"): # "synchronous"
|
|
430
|
+
result = function(*args, **kwargs)
|
|
431
|
+
return result
|
|
432
|
+
|
|
433
|
+
return wrapper
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
@ensure_safe_open_mfdataset
|
|
324
437
|
def open_netcdf_files(
|
|
325
438
|
filepaths,
|
|
326
439
|
chunks=-1,
|
|
@@ -329,46 +442,101 @@ def open_netcdf_files(
|
|
|
329
442
|
variables=None,
|
|
330
443
|
parallel=False,
|
|
331
444
|
compute=True,
|
|
445
|
+
engine="netcdf4",
|
|
332
446
|
**open_kwargs,
|
|
333
447
|
):
|
|
334
448
|
"""Open DISDRODB netCDF files using xarray.
|
|
335
449
|
|
|
336
|
-
Using
|
|
450
|
+
Using data_vars="minimal", coords="minimal", compat="override"
|
|
451
|
+
--> will only concatenate those variables with the time dimension,
|
|
452
|
+
--> will skip any checking for variables that don't have a time dimension
|
|
453
|
+
(simply pick the variable from the first file).
|
|
454
|
+
https://github.com/pydata/xarray/issues/1385#issuecomment-1958761334
|
|
455
|
+
|
|
456
|
+
Using combine="nested" and join="outer" ensure that duplicated timesteps
|
|
457
|
+
are not overwritten!
|
|
458
|
+
|
|
459
|
+
When decode_cf=False
|
|
460
|
+
--> lat,lon are data_vars and get concatenated without any checking or reading
|
|
461
|
+
When decode_cf=True
|
|
462
|
+
--> lat, lon are promoted to coords, then get checked for equality across all files
|
|
463
|
+
|
|
464
|
+
For L0B product, if sample_interval variable is present and varies with time,
|
|
465
|
+
this function concatenate the variable over time without problems.
|
|
466
|
+
For L0C product, if sample_interval changes across listed files,
|
|
467
|
+
only sample_interval of first file is reported.
|
|
468
|
+
--> open_dataset take care of just providing filepaths of files with same sample interval.
|
|
469
|
+
In L1 and L2 processing, only filepaths of files with same sample interval
|
|
470
|
+
must be passed to this function.
|
|
471
|
+
|
|
337
472
|
"""
|
|
338
473
|
import xarray as xr
|
|
339
474
|
|
|
340
475
|
# Ensure variables is a list
|
|
341
|
-
if variables is not None
|
|
342
|
-
variables
|
|
476
|
+
if variables is not None:
|
|
477
|
+
if isinstance(variables, str):
|
|
478
|
+
variables = [variables]
|
|
479
|
+
variables = np.unique(variables).tolist()
|
|
480
|
+
|
|
343
481
|
# Define preprocessing function for parallel opening
|
|
344
|
-
|
|
482
|
+
if parallel and variables is not None:
|
|
483
|
+
|
|
484
|
+
def preprocess(ds):
|
|
485
|
+
return subset_variables(ds, variables)
|
|
486
|
+
|
|
487
|
+
else:
|
|
488
|
+
preprocess = None
|
|
345
489
|
|
|
346
490
|
# Open netcdf
|
|
491
|
+
xr.set_options(use_new_combine_kwarg_defaults=True)
|
|
347
492
|
ds = xr.open_mfdataset(
|
|
348
493
|
filepaths,
|
|
349
494
|
chunks=chunks,
|
|
350
|
-
data_vars="all",
|
|
351
495
|
combine="nested",
|
|
352
|
-
join="outer",
|
|
353
496
|
concat_dim="time",
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
compat="no_conflicts"
|
|
497
|
+
data_vars="minimal", # ["sample_interval"], "all" would concat all across time
|
|
498
|
+
coords="minimal",
|
|
499
|
+
join="outer", # "exact"
|
|
500
|
+
compat="override", # "no_conflicts" slows down
|
|
358
501
|
combine_attrs="override",
|
|
359
|
-
|
|
502
|
+
preprocess=preprocess, # only if parallel=True
|
|
503
|
+
engine=engine,
|
|
504
|
+
parallel=parallel,
|
|
505
|
+
decode_cf=False, # assume encoding do not vary across files (e.g. "time" units)
|
|
506
|
+
decode_coords=False, # no effect if decode_cf=False
|
|
360
507
|
decode_timedelta=False,
|
|
361
508
|
cache=False,
|
|
362
509
|
autoclose=True,
|
|
363
510
|
**open_kwargs,
|
|
364
511
|
)
|
|
365
|
-
|
|
512
|
+
|
|
513
|
+
# Decode CF
|
|
514
|
+
# - Set to coordinates the variables
|
|
515
|
+
# - latitude/longitude/altitude
|
|
516
|
+
# - sample_interval
|
|
517
|
+
# - diameter/velocity bin width/upper/lower
|
|
518
|
+
ds = xr.decode_cf(ds, decode_times=True, decode_coords=True, decode_timedelta=False)
|
|
519
|
+
|
|
520
|
+
# Subset variables
|
|
521
|
+
# --> After decoding CF, when coordinates are properly set
|
|
522
|
+
# --> Othewerwise, coordinate variables would be removed unless listed in variables
|
|
366
523
|
if variables is not None and preprocess is None:
|
|
524
|
+
variables = [var for var in variables if var in ds]
|
|
367
525
|
ds = ds[variables]
|
|
368
|
-
|
|
526
|
+
|
|
527
|
+
# Subset time
|
|
369
528
|
if start_time is not None or end_time is not None:
|
|
370
529
|
ds = filter_dataset_by_time(ds, start_time=start_time, end_time=end_time)
|
|
371
|
-
|
|
530
|
+
|
|
531
|
+
# Ensure coordinates are already loaded in memory
|
|
532
|
+
for coord in list(ds.coords):
|
|
533
|
+
ds[coord] = ds[coord].load()
|
|
534
|
+
|
|
535
|
+
# Update time coverage attributes
|
|
536
|
+
ds.attrs["time_coverage_start"] = str(ds.disdrodb.start_time)
|
|
537
|
+
ds.attrs["time_coverage_end"] = str(ds.disdrodb.end_time)
|
|
538
|
+
|
|
539
|
+
# If compute=True, load in memory and close connections to files
|
|
372
540
|
if compute:
|
|
373
541
|
dataset = ds.compute()
|
|
374
542
|
ds.close()
|
|
@@ -386,8 +554,8 @@ def open_dataset(
|
|
|
386
554
|
product,
|
|
387
555
|
product_kwargs=None,
|
|
388
556
|
debugging_mode: bool = False,
|
|
389
|
-
data_archive_dir:
|
|
390
|
-
metadata_archive_dir:
|
|
557
|
+
data_archive_dir: str | None = None,
|
|
558
|
+
metadata_archive_dir: str | None = None,
|
|
391
559
|
chunks=-1,
|
|
392
560
|
parallel=False,
|
|
393
561
|
compute=False,
|
|
@@ -429,7 +597,7 @@ def open_dataset(
|
|
|
429
597
|
xarray.Dataset
|
|
430
598
|
|
|
431
599
|
"""
|
|
432
|
-
|
|
600
|
+
import xarray as xr
|
|
433
601
|
|
|
434
602
|
# Extract product kwargs from open_kwargs
|
|
435
603
|
product_kwargs = extract_product_kwargs(open_kwargs, product=product)
|
|
@@ -463,9 +631,46 @@ def open_dataset(
|
|
|
463
631
|
|
|
464
632
|
# Open L0A Parquet files
|
|
465
633
|
if product == "L0A":
|
|
466
|
-
|
|
634
|
+
df = open_parquet_files(
|
|
635
|
+
filepaths=filepaths,
|
|
636
|
+
variables=variables,
|
|
637
|
+
start_time=start_time,
|
|
638
|
+
end_time=end_time,
|
|
639
|
+
use_threads=parallel,
|
|
640
|
+
)
|
|
641
|
+
return df
|
|
467
642
|
|
|
468
643
|
# Open DISDRODB netCDF files using xarray
|
|
644
|
+
# - Special handling for L0C product with possible multiple sample intervals
|
|
645
|
+
if product == "L0C":
|
|
646
|
+
dict_sample_intervals = group_filepaths(filepaths, groups="sample_interval")
|
|
647
|
+
if len(dict_sample_intervals) > 1:
|
|
648
|
+
# Open separately each sample interval
|
|
649
|
+
list_ds = [
|
|
650
|
+
open_netcdf_files(
|
|
651
|
+
filepaths=filepaths,
|
|
652
|
+
chunks=chunks,
|
|
653
|
+
start_time=start_time,
|
|
654
|
+
end_time=end_time,
|
|
655
|
+
variables=variables,
|
|
656
|
+
parallel=parallel,
|
|
657
|
+
compute=compute,
|
|
658
|
+
**open_kwargs,
|
|
659
|
+
)
|
|
660
|
+
for filepaths in dict_sample_intervals.values()
|
|
661
|
+
]
|
|
662
|
+
# Expand sample_interval coordinate for each dataset
|
|
663
|
+
list_ds = [ds.assign_coords(sample_interval=ds.sample_interval.expand_dims(time=ds.time)) for ds in list_ds]
|
|
664
|
+
# Concatenate along time dimension and sort by time
|
|
665
|
+
ds = xr.concat(list_ds, dim="time")
|
|
666
|
+
ds.attrs["measurement_interval"] = list(dict_sample_intervals)
|
|
667
|
+
ds = ds.sortby("time")
|
|
668
|
+
# Update time coverage attributes
|
|
669
|
+
ds.attrs["time_coverage_start"] = str(ds.disdrodb.start_time)
|
|
670
|
+
ds.attrs["time_coverage_end"] = str(ds.disdrodb.end_time)
|
|
671
|
+
return ds
|
|
672
|
+
|
|
673
|
+
# Otherwise, open all files together
|
|
469
674
|
ds = open_netcdf_files(
|
|
470
675
|
filepaths=filepaths,
|
|
471
676
|
chunks=chunks,
|
|
@@ -476,10 +681,6 @@ def open_dataset(
|
|
|
476
681
|
compute=compute,
|
|
477
682
|
**open_kwargs,
|
|
478
683
|
)
|
|
479
|
-
|
|
480
|
-
# Ensure coordinates in memory
|
|
481
|
-
# for coord in list(ds.coords):
|
|
482
|
-
# ds[coord] = ds[coord].compute()
|
|
483
684
|
return ds
|
|
484
685
|
|
|
485
686
|
|
|
@@ -509,7 +710,7 @@ def remove_product(
|
|
|
509
710
|
**product_kwargs,
|
|
510
711
|
)
|
|
511
712
|
log_info(logger=logger, msg="Removal of {product} files started.", verbose=verbose)
|
|
512
|
-
|
|
713
|
+
remove_file_or_directories(data_dir)
|
|
513
714
|
log_info(logger=logger, msg="Removal of {product} files ended.", verbose=verbose)
|
|
514
715
|
|
|
515
716
|
|
disdrodb/api/path.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# -----------------------------------------------------------------------------.
|
|
4
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
5
3
|
#
|
|
6
4
|
# This program is free software: you can redistribute it and/or modify
|
|
7
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -17,13 +15,13 @@
|
|
|
17
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
16
|
# -----------------------------------------------------------------------------.
|
|
19
17
|
"""Define paths within the DISDRODB infrastructure."""
|
|
18
|
+
|
|
20
19
|
import os
|
|
21
20
|
|
|
22
21
|
from disdrodb.configs import get_data_archive_dir, get_metadata_archive_dir
|
|
23
22
|
from disdrodb.constants import ARCHIVE_VERSION
|
|
24
23
|
from disdrodb.utils.directories import check_directory_exists
|
|
25
24
|
from disdrodb.utils.time import (
|
|
26
|
-
ensure_sample_interval_in_seconds,
|
|
27
25
|
get_file_start_end_time,
|
|
28
26
|
seconds_to_temporal_resolution,
|
|
29
27
|
)
|
|
@@ -805,10 +803,8 @@ def define_l0b_filename(ds, campaign_name: str, station_name: str) -> str:
|
|
|
805
803
|
return filename
|
|
806
804
|
|
|
807
805
|
|
|
808
|
-
def define_l0c_filename(ds, campaign_name: str, station_name: str) -> str:
|
|
806
|
+
def define_l0c_filename(ds, campaign_name: str, station_name: str, sample_interval: str) -> str:
|
|
809
807
|
"""Define L0C file name."""
|
|
810
|
-
# TODO: add sample_interval as function argument
|
|
811
|
-
sample_interval = int(ensure_sample_interval_in_seconds(ds["sample_interval"]).data.item())
|
|
812
808
|
temporal_resolution = define_temporal_resolution(sample_interval, rolling=False)
|
|
813
809
|
starting_time, ending_time = get_file_start_end_time(ds)
|
|
814
810
|
starting_time = starting_time.strftime("%Y%m%d%H%M%S")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------------.
|
|
2
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
3
3
|
#
|
|
4
4
|
# This program is free software: you can redistribute it and/or modify
|
|
5
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
# -----------------------------------------------------------------------------.
|
|
17
17
|
"""Wrapper to check DISDRODB Metadata Archive Compliance from terminal."""
|
|
18
|
+
|
|
18
19
|
import sys
|
|
19
20
|
|
|
20
21
|
import click
|
|
@@ -34,7 +35,7 @@ sys.tracebacklimit = 0 # avoid full traceback error if occur
|
|
|
34
35
|
help="Whether to raise error of finish the check",
|
|
35
36
|
)
|
|
36
37
|
def disdrodb_check_metadata_archive(metadata_archive_dir=None, raise_error=True):
|
|
37
|
-
"""
|
|
38
|
+
"""Validate the DISDRODB Metadata Archive."""
|
|
38
39
|
from disdrodb.metadata.checks import check_metadata_archive
|
|
39
40
|
|
|
40
41
|
metadata_archive_dir = parse_archive_dir(metadata_archive_dir)
|