disdrodb 0.2.0__py3-none-any.whl → 0.3.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 +1 -1
- disdrodb/_config.py +1 -3
- disdrodb/_version.py +2 -2
- disdrodb/accessor/__init__.py +1 -1
- disdrodb/accessor/methods.py +18 -11
- disdrodb/api/checks.py +2 -4
- disdrodb/api/configs.py +1 -3
- disdrodb/api/create_directories.py +4 -6
- disdrodb/api/info.py +1 -3
- disdrodb/api/io.py +15 -9
- disdrodb/api/path.py +1 -3
- disdrodb/cli/disdrodb_check_metadata_archive.py +2 -2
- disdrodb/cli/disdrodb_check_products_options.py +44 -0
- disdrodb/cli/disdrodb_create_summary.py +48 -22
- disdrodb/cli/disdrodb_create_summary_station.py +39 -18
- disdrodb/cli/disdrodb_data_archive_directory.py +1 -3
- disdrodb/cli/disdrodb_download_archive.py +45 -24
- disdrodb/cli/disdrodb_download_metadata_archive.py +27 -16
- disdrodb/cli/disdrodb_download_station.py +56 -26
- disdrodb/cli/disdrodb_initialize_station.py +40 -20
- disdrodb/cli/disdrodb_metadata_archive_directory.py +1 -3
- disdrodb/cli/disdrodb_open_data_archive.py +16 -11
- disdrodb/cli/disdrodb_open_logs_directory.py +29 -18
- disdrodb/cli/disdrodb_open_metadata_archive.py +25 -11
- disdrodb/cli/disdrodb_open_metadata_directory.py +32 -20
- disdrodb/cli/disdrodb_open_product_directory.py +38 -21
- disdrodb/cli/disdrodb_open_readers_directory.py +1 -3
- disdrodb/cli/disdrodb_run.py +189 -0
- disdrodb/cli/disdrodb_run_l0.py +55 -64
- disdrodb/cli/disdrodb_run_l0_station.py +47 -52
- disdrodb/cli/disdrodb_run_l0a.py +47 -45
- disdrodb/cli/disdrodb_run_l0a_station.py +38 -37
- disdrodb/cli/disdrodb_run_l0b.py +45 -45
- disdrodb/cli/disdrodb_run_l0b_station.py +37 -36
- disdrodb/cli/disdrodb_run_l0c.py +50 -47
- disdrodb/cli/disdrodb_run_l0c_station.py +41 -38
- disdrodb/cli/disdrodb_run_l1.py +49 -45
- disdrodb/cli/disdrodb_run_l1_station.py +40 -37
- disdrodb/cli/disdrodb_run_l2e.py +50 -45
- disdrodb/cli/disdrodb_run_l2e_station.py +41 -37
- disdrodb/cli/disdrodb_run_l2m.py +49 -45
- disdrodb/cli/disdrodb_run_l2m_station.py +40 -37
- disdrodb/cli/disdrodb_run_station.py +184 -0
- disdrodb/cli/disdrodb_upload_archive.py +45 -35
- disdrodb/cli/disdrodb_upload_station.py +39 -32
- disdrodb/configs.py +13 -8
- disdrodb/constants.py +4 -2
- disdrodb/data_transfer/__init__.py +1 -3
- disdrodb/data_transfer/download_data.py +38 -54
- disdrodb/data_transfer/upload_data.py +1 -3
- disdrodb/data_transfer/zenodo.py +1 -3
- 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 +1 -14
- 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 +17 -3
- disdrodb/etc/products/L2M/global.yaml +1 -1
- disdrodb/fall_velocity/__init__.py +46 -0
- disdrodb/fall_velocity/graupel.py +483 -0
- disdrodb/fall_velocity/hail.py +287 -0
- disdrodb/{l1/fall_velocity.py → fall_velocity/rain.py} +265 -50
- disdrodb/issue/__init__.py +1 -3
- disdrodb/issue/checks.py +3 -5
- disdrodb/issue/reader.py +1 -3
- disdrodb/issue/writer.py +1 -3
- disdrodb/l0/__init__.py +1 -1
- disdrodb/l0/check_configs.py +26 -17
- disdrodb/l0/check_standards.py +1 -3
- disdrodb/l0/configs/LPM/l0a_encodings.yml +0 -1
- disdrodb/l0/configs/LPM/l0b_cf_attrs.yml +0 -4
- disdrodb/l0/configs/LPM/l0b_encodings.yml +9 -9
- disdrodb/l0/configs/LPM/raw_data_format.yml +11 -11
- disdrodb/l0/configs/LPM_V0/bins_diameter.yml +103 -0
- disdrodb/l0/configs/LPM_V0/bins_velocity.yml +103 -0
- disdrodb/l0/configs/LPM_V0/l0a_encodings.yml +45 -0
- disdrodb/l0/configs/LPM_V0/l0b_cf_attrs.yml +180 -0
- disdrodb/l0/configs/LPM_V0/l0b_encodings.yml +410 -0
- disdrodb/l0/configs/LPM_V0/raw_data_format.yml +474 -0
- 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/configs/PARSIVEL/raw_data_format.yml +8 -8
- disdrodb/l0/configs/PARSIVEL2/raw_data_format.yml +9 -9
- disdrodb/l0/l0_reader.py +1 -3
- disdrodb/l0/l0a_processing.py +7 -5
- disdrodb/l0/l0b_nc_processing.py +2 -4
- disdrodb/l0/l0b_processing.py +27 -22
- disdrodb/l0/l0c_processing.py +37 -11
- disdrodb/l0/manuals/LPM_V0.pdf +0 -0
- disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +1 -1
- disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +1 -1
- disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +1 -1
- disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +1 -1
- disdrodb/l0/readers/LPM/GERMANY/DWD.py +190 -12
- disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +63 -14
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_PI.py +279 -0
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_T.py +279 -0
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_W.py +3 -5
- disdrodb/l0/readers/LPM/KIT/CHWALA.py +1 -3
- disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_LPM_NC.py +1 -1
- disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_RWANDA_LPM_NC.py +103 -0
- disdrodb/l0/readers/LPM/NORWAY/HAUKELISETER_LPM.py +214 -0
- disdrodb/l0/readers/LPM/NORWAY/NMBU_LPM.py +206 -0
- disdrodb/l0/readers/LPM/SLOVENIA/ARSO.py +1 -3
- disdrodb/l0/readers/LPM/SLOVENIA/UL.py +1 -3
- disdrodb/l0/readers/LPM/SWITZERLAND/INNERERIZ_LPM.py +1 -3
- disdrodb/l0/readers/LPM/UK/DIVEN.py +1 -1
- disdrodb/l0/readers/LPM/UK/WITHWORTH_LPM.py +217 -0
- disdrodb/l0/readers/LPM/USA/CHARLESTON.py +227 -0
- disdrodb/l0/readers/{LPM → LPM_V0}/BELGIUM/ULIEGE.py +34 -52
- disdrodb/l0/readers/LPM_V0/ITALY/GID_LPM_V0.py +240 -0
- disdrodb/l0/readers/ODM470/OCEAN/OCEANRAIN.py +123 -0
- disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +1 -1
- disdrodb/l0/readers/PARSIVEL/BASQUECOUNTRY/EUSKALMET_OTT.py +1 -1
- disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +1 -3
- disdrodb/l0/readers/PARSIVEL/EPFL/ARCTIC_2021.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/COMMON_2011.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/DAVOS_2009_2011.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_2009.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2008.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2011.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2012.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/GENEPI_2007.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007_2.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/HPICONET_2010.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP2.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP4.py +1 -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 +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/PARSIVEL_2007.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/PLATO_2019.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019_WJF.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/RIETHOLZBACH_2011.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +1 -1
- disdrodb/l0/readers/PARSIVEL/EPFL/UNIL_2022.py +1 -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 +26 -14
- disdrodb/l0/readers/PARSIVEL/NASA/MC3E.py +2 -2
- 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 +1 -1
- disdrodb/l0/readers/PARSIVEL2/ARM/ARM_PARSIVEL2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/BASQUECOUNTRY/EUSKALMET_OTT2.py +2 -2
- disdrodb/l0/readers/PARSIVEL2/BELGIUM/ILVO.py +1 -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 +1 -1
- disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_raw.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/FINLAND/FMI_PARSIVEL2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/FRANCE/ENPC_PARSIVEL2.py +1 -3
- disdrodb/l0/readers/PARSIVEL2/FRANCE/OSUG.py +1 -1
- 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 +5 -3
- disdrodb/l0/readers/PARSIVEL2/JAPAN/PRECIP.py +155 -0
- 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/{NASA/GCPEX.py → KOREA/ICEPOP_UCLM.py} +51 -31
- disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/MPI/BCO_PARSIVEL2.py +15 -8
- disdrodb/l0/readers/PARSIVEL2/MPI/BOWTIE.py +9 -4
- disdrodb/l0/readers/PARSIVEL2/NASA/APU.py +31 -6
- disdrodb/l0/readers/PARSIVEL2/NASA/NSSTC.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/FARM_PARSIVEL2.py +1 -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 +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_PIPS.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +2 -2
- 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 +1 -3
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT_NC.py +1 -1
- disdrodb/l0/readers/{PARSIVEL/NASA/PIERS.py → PARSIVEL2/NORWAY/UIB.py} +65 -31
- disdrodb/l0/readers/PARSIVEL2/PHILIPPINES/PAGASA.py +7 -6
- 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 +1 -3
- disdrodb/l0/readers/PARSIVEL2/SPAIN/LIAISE.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/SWEDEN/SMHI.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/USA/CSU.py +138 -0
- disdrodb/l0/readers/PARSIVEL2/USA/CW3E.py +49 -22
- disdrodb/l0/readers/PWS100/AUSTRIA/HOAL.py +1 -3
- disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100.py +1 -3
- disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100_SIRTA.py +1 -1
- disdrodb/l0/readers/{PARSIVEL/NASA/IFLOODS.py → RD80/BRAZIL/ATTO_RD80.py} +50 -36
- 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 +1 -3
- disdrodb/l0/readers/{SW250 → SWS250}/BELGIUM/KMI.py +2 -4
- disdrodb/l0/readers/template_reader_raw_netcdf_data.py +1 -3
- disdrodb/l0/readers/template_reader_raw_text_data.py +1 -3
- disdrodb/l0/standards.py +4 -5
- disdrodb/l0/template_tools.py +1 -3
- disdrodb/l1/__init__.py +1 -1
- disdrodb/l1/classification.py +913 -0
- disdrodb/l1/processing.py +36 -106
- disdrodb/l1/resampling.py +8 -3
- disdrodb/l1_env/__init__.py +1 -1
- disdrodb/l1_env/routines.py +6 -6
- disdrodb/l2/__init__.py +1 -1
- disdrodb/l2/empirical_dsd.py +61 -31
- disdrodb/l2/processing.py +327 -62
- disdrodb/metadata/checks.py +1 -3
- disdrodb/metadata/download.py +4 -4
- disdrodb/metadata/geolocation.py +1 -3
- disdrodb/metadata/info.py +1 -3
- disdrodb/metadata/manipulation.py +1 -3
- disdrodb/metadata/reader.py +1 -3
- disdrodb/metadata/search.py +1 -3
- disdrodb/metadata/standards.py +1 -3
- disdrodb/metadata/writer.py +1 -3
- disdrodb/physics/__init__.py +17 -0
- disdrodb/physics/atmosphere.py +272 -0
- disdrodb/physics/water.py +130 -0
- disdrodb/physics/wrappers.py +62 -0
- disdrodb/psd/__init__.py +1 -1
- disdrodb/psd/fitting.py +22 -9
- disdrodb/psd/models.py +1 -1
- disdrodb/routines/__init__.py +5 -1
- disdrodb/routines/l0.py +28 -18
- disdrodb/routines/l1.py +8 -6
- disdrodb/routines/l2.py +8 -4
- disdrodb/routines/options.py +116 -71
- disdrodb/routines/options_validation.py +728 -0
- disdrodb/routines/wrappers.py +431 -11
- disdrodb/scattering/__init__.py +1 -1
- disdrodb/scattering/axis_ratio.py +9 -6
- disdrodb/scattering/permittivity.py +8 -8
- disdrodb/scattering/routines.py +32 -14
- disdrodb/summary/__init__.py +1 -1
- disdrodb/summary/routines.py +146 -86
- disdrodb/utils/__init__.py +1 -1
- disdrodb/utils/archiving.py +16 -9
- disdrodb/utils/attrs.py +4 -3
- disdrodb/utils/cli.py +8 -10
- disdrodb/utils/compression.py +13 -13
- disdrodb/utils/dask.py +33 -14
- disdrodb/utils/dataframe.py +1 -3
- disdrodb/utils/decorators.py +1 -3
- disdrodb/utils/dict.py +1 -1
- disdrodb/utils/directories.py +3 -5
- disdrodb/utils/encoding.py +2 -4
- disdrodb/utils/event.py +1 -1
- disdrodb/utils/list.py +1 -3
- disdrodb/utils/logger.py +1 -3
- disdrodb/utils/manipulations.py +182 -6
- disdrodb/utils/pydantic.py +80 -0
- disdrodb/utils/routines.py +1 -3
- disdrodb/utils/subsetting.py +1 -1
- disdrodb/utils/time.py +3 -2
- disdrodb/utils/warnings.py +1 -3
- disdrodb/utils/writer.py +1 -3
- disdrodb/utils/xarray.py +30 -3
- disdrodb/utils/yaml.py +1 -3
- disdrodb/viz/__init__.py +1 -1
- disdrodb/viz/plots.py +197 -21
- {disdrodb-0.2.0.dist-info → disdrodb-0.3.0.dist-info}/METADATA +2 -2
- disdrodb-0.3.0.dist-info/RECORD +358 -0
- {disdrodb-0.2.0.dist-info → disdrodb-0.3.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/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 -618
- disdrodb/l1/filters.py +0 -203
- disdrodb-0.2.0.dist-info/RECORD +0 -312
- {disdrodb-0.2.0.dist-info → disdrodb-0.3.0.dist-info}/WHEEL +0 -0
- {disdrodb-0.2.0.dist-info → disdrodb-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {disdrodb-0.2.0.dist-info → disdrodb-0.3.0.dist-info}/top_level.txt +0 -0
disdrodb/utils/cli.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
|
|
@@ -105,7 +103,7 @@ def click_data_archive_dir_option(function: object):
|
|
|
105
103
|
type=str,
|
|
106
104
|
show_default=True,
|
|
107
105
|
default=None,
|
|
108
|
-
help="DISDRODB
|
|
106
|
+
help="DISDRODB Data Archive Directory. Format: <...>/DISDRODB",
|
|
109
107
|
)(function)
|
|
110
108
|
return function
|
|
111
109
|
|
|
@@ -123,7 +121,7 @@ def click_metadata_archive_dir_option(function: object):
|
|
|
123
121
|
type=str,
|
|
124
122
|
show_default=True,
|
|
125
123
|
default=None,
|
|
126
|
-
help="DISDRODB Metadata Archive Directory",
|
|
124
|
+
help="DISDRODB Metadata Archive Directory. Format: <...>/DISDRODB-METADATA/DISDRODB",
|
|
127
125
|
)(function)
|
|
128
126
|
return function
|
|
129
127
|
|
|
@@ -233,14 +231,14 @@ def click_l0_archive_options(function: object):
|
|
|
233
231
|
type=bool,
|
|
234
232
|
show_default=True,
|
|
235
233
|
default=False,
|
|
236
|
-
help="If
|
|
234
|
+
help="If True, remove L0B files after L0C.",
|
|
237
235
|
)(function)
|
|
238
236
|
function = click.option(
|
|
239
237
|
"--remove_l0a",
|
|
240
238
|
type=bool,
|
|
241
239
|
show_default=True,
|
|
242
240
|
default=False,
|
|
243
|
-
help="If
|
|
241
|
+
help="If True, remove L0A files after L0B.",
|
|
244
242
|
)(function)
|
|
245
243
|
function = click.option(
|
|
246
244
|
"-l0c",
|
|
@@ -248,7 +246,7 @@ def click_l0_archive_options(function: object):
|
|
|
248
246
|
type=bool,
|
|
249
247
|
show_default=True,
|
|
250
248
|
default=True,
|
|
251
|
-
help="
|
|
249
|
+
help="Run L0C processing",
|
|
252
250
|
)(function)
|
|
253
251
|
function = click.option(
|
|
254
252
|
"-l0b",
|
|
@@ -256,7 +254,7 @@ def click_l0_archive_options(function: object):
|
|
|
256
254
|
type=bool,
|
|
257
255
|
show_default=True,
|
|
258
256
|
default=True,
|
|
259
|
-
help="
|
|
257
|
+
help="Run L0B processing",
|
|
260
258
|
)(function)
|
|
261
259
|
function = click.option(
|
|
262
260
|
"-l0a",
|
|
@@ -264,6 +262,6 @@ def click_l0_archive_options(function: object):
|
|
|
264
262
|
type=bool,
|
|
265
263
|
show_default=True,
|
|
266
264
|
default=True,
|
|
267
|
-
help="
|
|
265
|
+
help="Run L0A processing",
|
|
268
266
|
)(function)
|
|
269
267
|
return function
|
disdrodb/utils/compression.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
|
|
@@ -82,7 +80,7 @@ def unzip_file_on_terminal(filepath: str, dest_path: str) -> str:
|
|
|
82
80
|
subprocess.run(cmd, check=True)
|
|
83
81
|
|
|
84
82
|
|
|
85
|
-
def _zip_dir(dir_path: str) -> str:
|
|
83
|
+
def _zip_dir(dir_path: str, dst_dir=None) -> str:
|
|
86
84
|
"""Zip a directory into a file located in the same directory.
|
|
87
85
|
|
|
88
86
|
Parameters
|
|
@@ -95,7 +93,9 @@ def _zip_dir(dir_path: str) -> str:
|
|
|
95
93
|
str
|
|
96
94
|
Path of the zip archive.
|
|
97
95
|
"""
|
|
98
|
-
|
|
96
|
+
if dst_dir is None:
|
|
97
|
+
dst_dir = tempfile.gettempdir()
|
|
98
|
+
output_path_without_extension = os.path.join(dst_dir, os.path.basename(dir_path))
|
|
99
99
|
output_path = output_path_without_extension + ".zip"
|
|
100
100
|
shutil.make_archive(output_path_without_extension, "zip", dir_path)
|
|
101
101
|
return output_path
|
|
@@ -188,13 +188,13 @@ def compress_station_files(
|
|
|
188
188
|
# Get list of files inside the station directory (in all nested directories)
|
|
189
189
|
filepaths = list_files(station_dir, recursive=True)
|
|
190
190
|
for filepath in filepaths:
|
|
191
|
-
_ =
|
|
191
|
+
_ = compress_file(filepath, method, skip=skip)
|
|
192
192
|
|
|
193
193
|
print(f"All files of {data_source} {campaign_name} {station_name} have been compressed.")
|
|
194
194
|
print("Please now remember to update the glob_pattern of the reader ¨!")
|
|
195
195
|
|
|
196
196
|
|
|
197
|
-
def
|
|
197
|
+
def compress_file(filepath: str, method: str, skip: bool) -> str:
|
|
198
198
|
"""Compress a file and delete the original.
|
|
199
199
|
|
|
200
200
|
If the file is already compressed, it is not compressed again.
|
|
@@ -228,9 +228,9 @@ def _compress_file(filepath: str, method: str, skip: bool) -> str:
|
|
|
228
228
|
archive_name = os.path.basename(filepath) + extension
|
|
229
229
|
compressed_filepath = os.path.join(os.path.dirname(filepath), archive_name)
|
|
230
230
|
compress_file_function = {
|
|
231
|
-
"zip":
|
|
232
|
-
"gzip":
|
|
233
|
-
"bzip2":
|
|
231
|
+
"zip": compress_file_zip,
|
|
232
|
+
"gzip": compress_file_gzip,
|
|
233
|
+
"bzip2": compress_file_bzip2,
|
|
234
234
|
}[method]
|
|
235
235
|
|
|
236
236
|
compress_file_function(filepath, compressed_filepath)
|
|
@@ -269,7 +269,7 @@ def _check_file_compression(filepath: str) -> Optional[str]:
|
|
|
269
269
|
return None
|
|
270
270
|
|
|
271
271
|
|
|
272
|
-
def
|
|
272
|
+
def compress_file_zip(filepath: str, compressed_filepath: str) -> None:
|
|
273
273
|
"""Compress a single file into a zip archive.
|
|
274
274
|
|
|
275
275
|
Parameters
|
|
@@ -285,7 +285,7 @@ def _compress_file_zip(filepath: str, compressed_filepath: str) -> None:
|
|
|
285
285
|
zipf.write(filepath, os.path.basename(filepath))
|
|
286
286
|
|
|
287
287
|
|
|
288
|
-
def
|
|
288
|
+
def compress_file_gzip(filepath: str, compressed_filepath: str) -> None:
|
|
289
289
|
"""Compress a single file into a gzip archive.
|
|
290
290
|
|
|
291
291
|
Parameters
|
|
@@ -301,7 +301,7 @@ def _compress_file_gzip(filepath: str, compressed_filepath: str) -> None:
|
|
|
301
301
|
f_out.writelines(f_in)
|
|
302
302
|
|
|
303
303
|
|
|
304
|
-
def
|
|
304
|
+
def compress_file_bzip2(filepath: str, compressed_filepath: str) -> None:
|
|
305
305
|
"""Compress a single file into a bzip2 archive.
|
|
306
306
|
|
|
307
307
|
Parameters
|
disdrodb/utils/dask.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
|
|
@@ -71,6 +69,7 @@ def initialize_dask_cluster(minimum_memory=None):
|
|
|
71
69
|
os.environ["HDF5_USE_FILE_LOCKING"] = "FALSE"
|
|
72
70
|
|
|
73
71
|
# Retrieve the number of processes to run
|
|
72
|
+
# --> If DASK_NUM_WORKERS is not set, use all CPUs minus 2
|
|
74
73
|
available_workers = os.cpu_count() - 2 # if not set, all CPUs minus 2
|
|
75
74
|
num_workers = dask.config.get("num_workers", available_workers)
|
|
76
75
|
|
|
@@ -113,7 +112,13 @@ def close_dask_cluster(cluster, client):
|
|
|
113
112
|
logger.setLevel(original_level)
|
|
114
113
|
|
|
115
114
|
|
|
116
|
-
def
|
|
115
|
+
def _batch_iterable(iterable, n):
|
|
116
|
+
"""Yield successive n-sized chunks from iterable."""
|
|
117
|
+
for i in range(0, len(iterable), n):
|
|
118
|
+
yield iterable[i : i + n]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def execute_tasks_safely(list_tasks, parallel: bool, logs_dir: str, max_tasks_per_batch=5_000):
|
|
117
122
|
"""
|
|
118
123
|
Execute Dask tasks and skip failed ones.
|
|
119
124
|
|
|
@@ -125,6 +130,9 @@ def execute_tasks_safely(list_tasks, parallel: bool, logs_dir: str):
|
|
|
125
130
|
Whether to execute in parallel with Dask or not.
|
|
126
131
|
logs_dir : str
|
|
127
132
|
Directory to store FAILED_TASKS.log.
|
|
133
|
+
max_tasks_per_batch : int or None, optional
|
|
134
|
+
Maximum number of tasks to submit to `client.compute()` at once.
|
|
135
|
+
The default is 5000. Dask struggle if more than 10_000 tasks are submitted.
|
|
128
136
|
|
|
129
137
|
Returns
|
|
130
138
|
-------
|
|
@@ -150,18 +158,29 @@ def execute_tasks_safely(list_tasks, parallel: bool, logs_dir: str):
|
|
|
150
158
|
except ValueError:
|
|
151
159
|
raise ValueError("No Dask Distributed Client found.")
|
|
152
160
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
161
|
+
all_results = []
|
|
162
|
+
failed_futures = []
|
|
163
|
+
|
|
164
|
+
# Batch execution
|
|
165
|
+
task_batches = list(_batch_iterable(list_tasks, max_tasks_per_batch)) if max_tasks_per_batch else [list_tasks]
|
|
166
|
+
|
|
167
|
+
for batch in task_batches:
|
|
168
|
+
# Compute tasks (all concurrently)
|
|
169
|
+
# - Runs tasks == num_workers * threads_per_worker (which is 1 for DISDRODB)
|
|
170
|
+
# - If errors occurs in some, skip it
|
|
171
|
+
futures = client.compute(batch)
|
|
172
|
+
results = client.gather(futures, errors="skip")
|
|
173
|
+
|
|
174
|
+
# Identify and collect failed futures
|
|
175
|
+
batch_failed = [f for f in futures if f.status != "finished"]
|
|
176
|
+
failed_futures.extend(batch_failed)
|
|
158
177
|
|
|
159
|
-
|
|
160
|
-
|
|
178
|
+
# Collect results from successful tasks
|
|
179
|
+
all_results.extend(results)
|
|
161
180
|
|
|
162
181
|
# If no tasks failed, return results
|
|
163
182
|
if not failed_futures:
|
|
164
|
-
return
|
|
183
|
+
return all_results
|
|
165
184
|
|
|
166
185
|
# Otherwise define log file listing failed tasks
|
|
167
186
|
with open(failed_log_path, "w") as f:
|
|
@@ -170,5 +189,5 @@ def execute_tasks_safely(list_tasks, parallel: bool, logs_dir: str):
|
|
|
170
189
|
f.write(f"ERROR - DASK TASK FAILURE - Task {fut.key} failed: {err}\n")
|
|
171
190
|
|
|
172
191
|
# Append to list of log filepaths (results) the dask failing log
|
|
173
|
-
|
|
174
|
-
return
|
|
192
|
+
all_results.append(failed_log_path)
|
|
193
|
+
return all_results
|
disdrodb/utils/dataframe.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/utils/decorators.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/utils/dict.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
|
disdrodb/utils/directories.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
|
|
@@ -212,7 +210,7 @@ def is_empty_directory(path, skip_hidden=True):
|
|
|
212
210
|
return len(paths) == 0
|
|
213
211
|
|
|
214
212
|
|
|
215
|
-
def
|
|
213
|
+
def remove_file_or_directories(path, logger=None):
|
|
216
214
|
"""Return the file/directory or subdirectories tree of ``path``.
|
|
217
215
|
|
|
218
216
|
Use this function with caution.
|
|
@@ -259,7 +257,7 @@ def remove_if_exists(path: str, force: bool = False, logger=None) -> None:
|
|
|
259
257
|
|
|
260
258
|
# If force=True, remove the file/directory or subdirectories and files !
|
|
261
259
|
try:
|
|
262
|
-
|
|
260
|
+
remove_file_or_directories(path, logger=logger)
|
|
263
261
|
except Exception as e:
|
|
264
262
|
msg = f"Can not delete file(s) at {path}. The error is: {e}"
|
|
265
263
|
raise ValueError(msg)
|
disdrodb/utils/encoding.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
|
|
@@ -144,7 +142,7 @@ def get_time_encoding() -> dict:
|
|
|
144
142
|
"""
|
|
145
143
|
encoding = {}
|
|
146
144
|
encoding["dtype"] = "int64" # if float trailing sub-seconds values
|
|
147
|
-
encoding["
|
|
145
|
+
encoding["_FillValue"] = np.iinfo(np.int64).max
|
|
148
146
|
encoding["units"] = EPOCH
|
|
149
147
|
encoding["calendar"] = "proleptic_gregorian"
|
|
150
148
|
return encoding
|
disdrodb/utils/event.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
|
disdrodb/utils/list.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/utils/logger.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/utils/manipulations.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,16 +15,194 @@
|
|
|
17
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
16
|
# -----------------------------------------------------------------------------.
|
|
19
17
|
"""Include functions helping for DISDRODB product manipulations."""
|
|
20
|
-
|
|
21
18
|
import numpy as np
|
|
19
|
+
import xarray as xr
|
|
22
20
|
|
|
23
|
-
from disdrodb.constants import DIAMETER_DIMENSION
|
|
21
|
+
from disdrodb.constants import DIAMETER_DIMENSION, VELOCITY_DIMENSION
|
|
24
22
|
from disdrodb.utils.xarray import unstack_datarray_dimension
|
|
25
23
|
|
|
26
24
|
|
|
25
|
+
def define_diameter_datarray(bounds):
|
|
26
|
+
"""Define diameter DataArray."""
|
|
27
|
+
diameters_bin_lower = bounds[:-1]
|
|
28
|
+
diameters_bin_upper = bounds[1:]
|
|
29
|
+
diameters_bin_width = diameters_bin_upper - diameters_bin_lower
|
|
30
|
+
diameters_bin_center = diameters_bin_lower + diameters_bin_width / 2
|
|
31
|
+
da = xr.DataArray(
|
|
32
|
+
diameters_bin_center,
|
|
33
|
+
dims="diameter_bin_center",
|
|
34
|
+
coords={
|
|
35
|
+
"diameter_bin_width": ("diameter_bin_center", diameters_bin_width),
|
|
36
|
+
"diameter_bin_lower": ("diameter_bin_center", diameters_bin_lower),
|
|
37
|
+
"diameter_bin_upper": ("diameter_bin_center", diameters_bin_upper),
|
|
38
|
+
"diameter_bin_center": ("diameter_bin_center", diameters_bin_center),
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
return da
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def define_velocity_datarray(bounds):
|
|
45
|
+
"""Define velocity DataArray."""
|
|
46
|
+
velocitys_bin_lower = bounds[:-1]
|
|
47
|
+
velocitys_bin_upper = bounds[1:]
|
|
48
|
+
velocitys_bin_width = velocitys_bin_upper - velocitys_bin_lower
|
|
49
|
+
velocitys_bin_center = velocitys_bin_lower + velocitys_bin_width / 2
|
|
50
|
+
da = xr.DataArray(
|
|
51
|
+
velocitys_bin_center,
|
|
52
|
+
dims="velocity_bin_center",
|
|
53
|
+
coords={
|
|
54
|
+
"velocity_bin_width": ("velocity_bin_center", velocitys_bin_width),
|
|
55
|
+
"velocity_bin_lower": ("velocity_bin_center", velocitys_bin_lower),
|
|
56
|
+
"velocity_bin_upper": ("velocity_bin_center", velocitys_bin_upper),
|
|
57
|
+
"velocity_bin_center": ("velocity_bin_center", velocitys_bin_center),
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
return da
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def define_diameter_array(diameter_min=0, diameter_max=10, diameter_spacing=0.05):
|
|
64
|
+
"""
|
|
65
|
+
Define an array of diameters and their corresponding bin properties.
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
diameter_min : float, optional
|
|
70
|
+
The minimum diameter value. The default value is 0 mm.
|
|
71
|
+
diameter_max : float, optional
|
|
72
|
+
The maximum diameter value. The default value is 10 mm.
|
|
73
|
+
diameter_spacing : float, optional
|
|
74
|
+
The spacing between diameter values. The default value is 0.05 mm.
|
|
75
|
+
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
78
|
+
xr.DataArray
|
|
79
|
+
A DataArray containing the center of each diameter bin, with coordinates for
|
|
80
|
+
the bin width, lower bound, upper bound, and center.
|
|
81
|
+
|
|
82
|
+
"""
|
|
83
|
+
diameters_bounds = np.arange(diameter_min, diameter_max + diameter_spacing / 2, step=diameter_spacing)
|
|
84
|
+
return define_diameter_datarray(diameters_bounds)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def define_velocity_array(velocity_min=0, velocity_max=10, velocity_spacing=0.05):
|
|
88
|
+
"""
|
|
89
|
+
Define an array of velocities and their corresponding bin properties.
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
velocity_min : float, optional
|
|
94
|
+
The minimum velocity value. The default value is 0 mm.
|
|
95
|
+
velocity_max : float, optional
|
|
96
|
+
The maximum velocity value. The default value is 10 mm.
|
|
97
|
+
velocity_spacing : float, optional
|
|
98
|
+
The spacing between velocity values. The default value is 0.05 mm.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
xr.DataArray
|
|
103
|
+
A DataArray containing the center of each velocity bin, with coordinates for
|
|
104
|
+
the bin width, lower bound, upper bound, and center.
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
velocitys_bounds = np.arange(velocity_min, velocity_max + velocity_spacing / 2, step=velocity_spacing)
|
|
108
|
+
return define_velocity_datarray(velocitys_bounds)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def filter_diameter_bins(ds, minimum_diameter=None, maximum_diameter=None):
|
|
112
|
+
"""
|
|
113
|
+
Filter the dataset to include only diameter bins within specified bounds.
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
ds : xarray.Dataset
|
|
118
|
+
The dataset containing diameter bin data.
|
|
119
|
+
minimum_diameter : float, optional
|
|
120
|
+
The minimum diameter to be included, in millimeters.
|
|
121
|
+
Defaults to the minimum value in `ds["diameter_bin_lower"]`.
|
|
122
|
+
maximum_diameter : float, optional
|
|
123
|
+
The maximum diameter to be included, in millimeters.
|
|
124
|
+
Defaults to the maximum value in `ds["diameter_bin_upper"]`.
|
|
125
|
+
|
|
126
|
+
Returns
|
|
127
|
+
-------
|
|
128
|
+
xarray.Dataset
|
|
129
|
+
The filtered dataset containing only the specified diameter bins.
|
|
130
|
+
"""
|
|
131
|
+
# Put data into memory
|
|
132
|
+
ds["diameter_bin_lower"] = ds["diameter_bin_lower"].compute()
|
|
133
|
+
ds["diameter_bin_upper"] = ds["diameter_bin_upper"].compute()
|
|
134
|
+
|
|
135
|
+
# Initialize default arguments
|
|
136
|
+
if minimum_diameter is None:
|
|
137
|
+
minimum_diameter = ds["diameter_bin_lower"].min().item()
|
|
138
|
+
if maximum_diameter is None:
|
|
139
|
+
maximum_diameter = ds["diameter_bin_upper"].max().item()
|
|
140
|
+
|
|
141
|
+
# Select bins which overlap the specified diameters
|
|
142
|
+
valid_indices = np.logical_and(
|
|
143
|
+
ds["diameter_bin_upper"] > minimum_diameter,
|
|
144
|
+
ds["diameter_bin_lower"] < maximum_diameter,
|
|
145
|
+
)
|
|
146
|
+
ds = ds.isel({DIAMETER_DIMENSION: valid_indices})
|
|
147
|
+
|
|
148
|
+
if ds.sizes[DIAMETER_DIMENSION] == 0:
|
|
149
|
+
msg = f"Filtering using {minimum_diameter=} removes all diameter bins."
|
|
150
|
+
raise ValueError(msg)
|
|
151
|
+
return ds
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def filter_velocity_bins(ds, minimum_velocity=None, maximum_velocity=None):
|
|
155
|
+
"""
|
|
156
|
+
Filter the dataset to include only velocity bins within specified bounds.
|
|
157
|
+
|
|
158
|
+
Parameters
|
|
159
|
+
----------
|
|
160
|
+
ds : xarray.Dataset
|
|
161
|
+
The dataset containing velocity bin data.
|
|
162
|
+
minimum_velocity : float, optional
|
|
163
|
+
The minimum velocity to include in the filter, in meters per second.
|
|
164
|
+
Defaults to the minimum value in `ds["velocity_bin_lower"]`.
|
|
165
|
+
maximum_velocity : float, optional
|
|
166
|
+
The maximum velocity to include in the filter, in meters per second.
|
|
167
|
+
Defaults to the maximum value in `ds["velocity_bin_upper"]`.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
xarray.Dataset
|
|
172
|
+
The filtered dataset containing only the specified velocity bins.
|
|
173
|
+
"""
|
|
174
|
+
# Put data into memory
|
|
175
|
+
ds["velocity_bin_lower"] = ds["velocity_bin_lower"].compute()
|
|
176
|
+
ds["velocity_bin_upper"] = ds["velocity_bin_upper"].compute()
|
|
177
|
+
|
|
178
|
+
# Initialize default arguments
|
|
179
|
+
if minimum_velocity is None:
|
|
180
|
+
minimum_velocity = ds["velocity_bin_lower"].min().item()
|
|
181
|
+
if maximum_velocity is None:
|
|
182
|
+
maximum_velocity = ds["velocity_bin_upper"].max().item()
|
|
183
|
+
|
|
184
|
+
# Select bins which overlap the specified velocities
|
|
185
|
+
valid_indices = np.logical_and(
|
|
186
|
+
ds["velocity_bin_upper"] > minimum_velocity,
|
|
187
|
+
ds["velocity_bin_lower"] < maximum_velocity,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
ds = ds.isel({VELOCITY_DIMENSION: valid_indices})
|
|
191
|
+
if ds.sizes[VELOCITY_DIMENSION] == 0:
|
|
192
|
+
msg = f"Filtering using {minimum_velocity=} removes all velocity bins."
|
|
193
|
+
raise ValueError(msg)
|
|
194
|
+
return ds
|
|
195
|
+
|
|
196
|
+
|
|
27
197
|
def get_diameter_bin_edges(ds):
|
|
28
198
|
"""Retrieve diameter bin edges."""
|
|
29
|
-
bin_edges = np.append(ds["diameter_bin_lower"].
|
|
199
|
+
bin_edges = np.append(ds["diameter_bin_lower"].to_numpy(), ds["diameter_bin_upper"].to_numpy()[-1])
|
|
200
|
+
return bin_edges
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def get_velocity_bin_edges(ds):
|
|
204
|
+
"""Retrieve velocity bin edges."""
|
|
205
|
+
bin_edges = np.append(ds["velocity_bin_lower"].to_numpy(), ds["velocity_bin_upper"].to_numpy()[-1])
|
|
30
206
|
return bin_edges
|
|
31
207
|
|
|
32
208
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------.
|
|
2
|
+
# Copyright (c) 2021-2026 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
|
+
"""Definition of pydantic validation custom class."""
|
|
18
|
+
from pydantic import BaseModel, ConfigDict, ValidationError
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def format_validation_error(validation_error: Exception) -> str:
|
|
22
|
+
"""Format a Pydantic ValidationError for better readability."""
|
|
23
|
+
if not isinstance(validation_error, ValidationError):
|
|
24
|
+
return str(validation_error)
|
|
25
|
+
|
|
26
|
+
def _shorten(value, max_len=200):
|
|
27
|
+
"""Safely truncate long inputs."""
|
|
28
|
+
text = repr(value)
|
|
29
|
+
if len(text) > max_len:
|
|
30
|
+
return text[: max_len - 5] + " ...]"
|
|
31
|
+
return text
|
|
32
|
+
|
|
33
|
+
model_name_attr = getattr(validation_error, "title", None)
|
|
34
|
+
model_name = model_name_attr() if callable(model_name_attr) else model_name_attr or "UnknownModel"
|
|
35
|
+
|
|
36
|
+
formatted_errors = [f"Validation errors in {model_name}:"]
|
|
37
|
+
|
|
38
|
+
for err in validation_error.errors():
|
|
39
|
+
path = ".".join(str(loc) for loc in err["loc"]) or "<model root>"
|
|
40
|
+
msg = err["msg"]
|
|
41
|
+
err_type = err["type"]
|
|
42
|
+
|
|
43
|
+
# Handles both "Value error, ..." and "Value error: ..."
|
|
44
|
+
if msg.lower().startswith("value error"):
|
|
45
|
+
msg = msg.split(",", 1)[-1] if "," in msg else msg.split(":", 1)[-1]
|
|
46
|
+
msg = msg.strip()
|
|
47
|
+
|
|
48
|
+
# Model-level (root) errors (raise in after or before)
|
|
49
|
+
if path == "<model root>":
|
|
50
|
+
formatted = f" • {msg}"
|
|
51
|
+
elif err_type == "missing":
|
|
52
|
+
formatted = f" • Missing field '{path}': {msg}"
|
|
53
|
+
elif "input" in err:
|
|
54
|
+
formatted = f" • Field '{path}': {msg} (got: {_shorten(err['input'])})"
|
|
55
|
+
else:
|
|
56
|
+
formatted = f" • Field '{path}': {msg}"
|
|
57
|
+
|
|
58
|
+
formatted_errors.append(formatted)
|
|
59
|
+
|
|
60
|
+
return "\n".join(formatted_errors)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class CustomBaseModel(BaseModel):
|
|
64
|
+
"""Custom pydantic BaseModel.
|
|
65
|
+
|
|
66
|
+
Forbid extra keys.
|
|
67
|
+
Hide URLs in error message.
|
|
68
|
+
Simplify error message.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
model_config = ConfigDict(extra="forbid", hide_error_urls=True)
|
|
72
|
+
|
|
73
|
+
# Override the standard ValidationError print behavior
|
|
74
|
+
def __init__(self, **data):
|
|
75
|
+
try:
|
|
76
|
+
super().__init__(**data)
|
|
77
|
+
except ValidationError as e:
|
|
78
|
+
formatted = format_validation_error(e)
|
|
79
|
+
# Raise a new simplified exception
|
|
80
|
+
raise ValueError(formatted) from None
|
disdrodb/utils/routines.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/utils/subsetting.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
|
disdrodb/utils/time.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
|
|
@@ -238,7 +238,7 @@ def regularize_dataset(
|
|
|
238
238
|
start_time=None,
|
|
239
239
|
end_time=None,
|
|
240
240
|
):
|
|
241
|
-
"""Regularize a
|
|
241
|
+
"""Regularize a xarray object across time dimension with uniform resolution.
|
|
242
242
|
|
|
243
243
|
Parameters
|
|
244
244
|
----------
|
|
@@ -274,6 +274,7 @@ def regularize_dataset(
|
|
|
274
274
|
start_time = start
|
|
275
275
|
if end_time is None:
|
|
276
276
|
end_time = end
|
|
277
|
+
xr_obj = xr_obj.sel({time_dim: slice(start_time, end_time)})
|
|
277
278
|
|
|
278
279
|
# Define new time index
|
|
279
280
|
new_time_index = pd.date_range(
|