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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------------.
|
|
2
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
3
3
|
#
|
|
4
4
|
# temperaturehis 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
|
"""Implement particle permittivity models."""
|
|
18
|
+
|
|
18
19
|
import numpy as np
|
|
19
20
|
import xarray as xr
|
|
20
21
|
|
|
@@ -56,7 +57,7 @@ def get_refractive_index_function(permittivity_model):
|
|
|
56
57
|
----------
|
|
57
58
|
model : str
|
|
58
59
|
The model to use for calculating the complex refractive index. Available models are:
|
|
59
|
-
'Liebe1991', 'Liebe1991v2', '
|
|
60
|
+
'Liebe1991', 'Liebe1991v2', 'Ellison2007', 'Turner2016', 'Turner2016SLC'.
|
|
60
61
|
|
|
61
62
|
Returns
|
|
62
63
|
-------
|
|
@@ -104,7 +105,7 @@ def get_refractive_index(temperature, frequency, permittivity_model):
|
|
|
104
105
|
Frequency in GHz.
|
|
105
106
|
permittivity_model : str
|
|
106
107
|
The permittivity model to use for calculating the complex refractive index.
|
|
107
|
-
Available models are: 'Liebe1991', 'Liebe1991v2', '
|
|
108
|
+
Available models are: 'Liebe1991', 'Liebe1991v2', 'Ellison2007', 'Turner2016', 'Turner2016SLC'.
|
|
108
109
|
See available models with ``disdrodb.scattering.available_permittivity_models()``.
|
|
109
110
|
|
|
110
111
|
Returns
|
|
@@ -309,7 +310,7 @@ def get_rain_refractive_index_liebe1991(temperature, frequency):
|
|
|
309
310
|
return m
|
|
310
311
|
|
|
311
312
|
|
|
312
|
-
def
|
|
313
|
+
def get_rain_refractive_index_ellison2007(temperature, frequency):
|
|
313
314
|
"""Compute the complex refractive index according to Ellison (2005) model.
|
|
314
315
|
|
|
315
316
|
Parameters
|
|
@@ -343,8 +344,8 @@ def get_rain_refractive_index_ellison2005(temperature, frequency):
|
|
|
343
344
|
temperature = ensure_array(temperature)
|
|
344
345
|
|
|
345
346
|
# Check frequency and temperature within validity range
|
|
346
|
-
temperature = check_temperature_validity_range(temperature, vmin=0, vmax=100, permittivity_model="
|
|
347
|
-
frequency = check_frequency_validity_range(frequency, vmin=0, vmax=1000, permittivity_model="
|
|
347
|
+
temperature = check_temperature_validity_range(temperature, vmin=0, vmax=100, permittivity_model="Ellison2007")
|
|
348
|
+
frequency = check_frequency_validity_range(frequency, vmin=0, vmax=1000, permittivity_model="Ellison2007")
|
|
348
349
|
|
|
349
350
|
# Conversion of frequency to Hz
|
|
350
351
|
frequency = frequency / 1e-9
|
|
@@ -479,7 +480,7 @@ def get_rain_refractive_index_turner2016(frequency, temperature):
|
|
|
479
480
|
def get_rayleigh_dielectric_factor(m):
|
|
480
481
|
"""Compute the Rayleigh dielectric factor |K|**2 from the complex refractive index.
|
|
481
482
|
|
|
482
|
-
The magnitude squared of the complex dielectric
|
|
483
|
+
The magnitude squared of the complex dielectric constant factor for liquid water,
|
|
483
484
|
relative to the surrounding medium (typically air).
|
|
484
485
|
|
|
485
486
|
This factor is used to compute the radar reflectivity.
|
|
@@ -505,6 +506,6 @@ def get_rayleigh_dielectric_factor(m):
|
|
|
505
506
|
REFRACTIVE_INDEX_MODELS = {
|
|
506
507
|
"Liebe1991": get_rain_refractive_index_liebe1991,
|
|
507
508
|
"Liebe1991single": get_rain_refractive_index_liebe1991_single,
|
|
508
|
-
"
|
|
509
|
+
"Ellison2007": get_rain_refractive_index_ellison2007,
|
|
509
510
|
"Turner2016": get_rain_refractive_index_turner2016,
|
|
510
511
|
}
|
disdrodb/scattering/routines.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
|
|
@@ -26,7 +26,6 @@ import xarray as xr
|
|
|
26
26
|
|
|
27
27
|
from disdrodb.configs import get_scattering_table_dir
|
|
28
28
|
from disdrodb.constants import DIAMETER_DIMENSION
|
|
29
|
-
from disdrodb.l1.filters import filter_diameter_bins
|
|
30
29
|
from disdrodb.psd.models import BinnedPSD, create_psd, get_required_parameters
|
|
31
30
|
from disdrodb.scattering.axis_ratio import check_axis_ratio_model, get_axis_ratio_model
|
|
32
31
|
from disdrodb.scattering.permittivity import (
|
|
@@ -35,7 +34,7 @@ from disdrodb.scattering.permittivity import (
|
|
|
35
34
|
get_refractive_index,
|
|
36
35
|
)
|
|
37
36
|
from disdrodb.utils.logger import log_info
|
|
38
|
-
from disdrodb.utils.manipulations import get_diameter_bin_edges
|
|
37
|
+
from disdrodb.utils.manipulations import filter_diameter_bins, get_diameter_bin_edges
|
|
39
38
|
from disdrodb.utils.warnings import suppress_warnings
|
|
40
39
|
|
|
41
40
|
logger = logging.getLogger(__name__)
|
|
@@ -76,20 +75,31 @@ def check_radar_band(radar_band):
|
|
|
76
75
|
return radar_band
|
|
77
76
|
|
|
78
77
|
|
|
78
|
+
def _is_valid_numeric_frequency(frequency):
|
|
79
|
+
numeric_value = float(frequency)
|
|
80
|
+
if numeric_value <= 0:
|
|
81
|
+
raise ValueError(f"Frequency must be positive, got {numeric_value}")
|
|
82
|
+
return numeric_value
|
|
83
|
+
|
|
84
|
+
|
|
79
85
|
def _check_frequency(frequency):
|
|
80
86
|
"""Check the validity of the specified frequency."""
|
|
81
87
|
if isinstance(frequency, str):
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
try:
|
|
89
|
+
frequency = float(frequency)
|
|
90
|
+
|
|
91
|
+
except ValueError:
|
|
92
|
+
# Not numeric, assume radar band name
|
|
93
|
+
frequency = check_radar_band(frequency)
|
|
94
|
+
frequency = frequency_dict[frequency]
|
|
95
|
+
if isinstance(frequency, (int, float, np.integer, np.floating)):
|
|
96
|
+
return _is_valid_numeric_frequency(frequency)
|
|
97
|
+
raise TypeError(f"Frequency {frequency} must be a string or a number.")
|
|
88
98
|
|
|
89
99
|
|
|
90
100
|
def ensure_numerical_frequency(frequency):
|
|
91
101
|
"""Ensure that the frequencies are numerical values in GHz."""
|
|
92
|
-
if isinstance(frequency, (str, int, float)):
|
|
102
|
+
if isinstance(frequency, (str, int, float, np.integer, np.floating)):
|
|
93
103
|
frequency = [frequency]
|
|
94
104
|
frequency = np.array([_check_frequency(f) for f in frequency])
|
|
95
105
|
return frequency.squeeze()
|
|
@@ -476,6 +486,11 @@ def compute_radar_variables(scatterer):
|
|
|
476
486
|
|
|
477
487
|
To speed up computations, this function should input a scatterer object with
|
|
478
488
|
a preinitialized scattering table.
|
|
489
|
+
|
|
490
|
+
Note
|
|
491
|
+
----
|
|
492
|
+
If this function is modified to compute additional radar variables, the global
|
|
493
|
+
variable RADAR_VARIABLES must be updated accordingly !
|
|
479
494
|
"""
|
|
480
495
|
from pytmatrix import radar
|
|
481
496
|
|
|
@@ -495,10 +510,13 @@ def compute_radar_variables(scatterer):
|
|
|
495
510
|
radar_vars["ZDR"] = 10 * np.log10(radar.Zdr(scatterer)) # dB
|
|
496
511
|
radar_vars["ZDR"] = np.where(np.isfinite(radar_vars["ZDR"]), radar_vars["ZDR"], np.nan)
|
|
497
512
|
|
|
498
|
-
radar_vars["
|
|
499
|
-
radar_vars["
|
|
513
|
+
radar_vars["LDRH"] = 10 * np.log10(radar.ldr(scatterer, h_pol=True)) # dBZ
|
|
514
|
+
radar_vars["LDRH"] = np.where(np.isfinite(radar_vars["LDRH"]), radar_vars["LDRH"], np.nan)
|
|
515
|
+
|
|
516
|
+
radar_vars["LDRV"] = 10 * np.log10(radar.ldr(scatterer, h_pol=False)) # dBZ
|
|
517
|
+
radar_vars["LDRV"] = np.where(np.isfinite(radar_vars["LDRV"]), radar_vars["LDRV"], np.nan)
|
|
500
518
|
|
|
501
|
-
radar_vars["RHOHV"] = radar.rho_hv(scatterer) #
|
|
519
|
+
radar_vars["RHOHV"] = radar.rho_hv(scatterer) # [-]
|
|
502
520
|
radar_vars["DELTAHV"] = radar.delta_hv(scatterer) * 180.0 / np.pi # [deg]
|
|
503
521
|
|
|
504
522
|
# Set forward scattering for attenuation and phase calculations
|
|
@@ -512,7 +530,7 @@ def compute_radar_variables(scatterer):
|
|
|
512
530
|
|
|
513
531
|
# Radar variables computed by DISDRODB
|
|
514
532
|
# - Must reflect dictionary order output of compute_radar_variables
|
|
515
|
-
RADAR_VARIABLES = ["DBZH", "DBZV", "ZDR", "
|
|
533
|
+
RADAR_VARIABLES = ["DBZH", "DBZV", "ZDR", "LDRH", "LDRV", "RHOHV", "DELTAHV", "KDP", "AH", "AV", "ADP"]
|
|
516
534
|
|
|
517
535
|
|
|
518
536
|
def _try_compute_radar_variables(scatterer):
|
|
@@ -544,7 +562,7 @@ def _estimate_model_radar_parameters(
|
|
|
544
562
|
scatterer,
|
|
545
563
|
):
|
|
546
564
|
# Assign PSD model to the scatterer object
|
|
547
|
-
parameters = dict(zip(psd_parameters_names, parameters))
|
|
565
|
+
parameters = dict(zip(psd_parameters_names, parameters, strict=True))
|
|
548
566
|
scatterer.psd = create_psd(psd_model, parameters)
|
|
549
567
|
|
|
550
568
|
# Get radar variables
|
disdrodb/summary/__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
|
disdrodb/summary/routines.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
|
"""Utilities to create summary statistics."""
|
|
18
|
+
|
|
18
19
|
import gc
|
|
19
20
|
import importlib
|
|
20
21
|
import os
|
|
@@ -223,6 +224,11 @@ def create_table_rain_summary(df, temporal_resolution):
|
|
|
223
224
|
table["n_minutes_Dmax_>7"] = np.sum(df["Dmax"] > 7).item() * accumulation_interval_minutes
|
|
224
225
|
table["n_minutes_Dmax_>8"] = np.sum(df["Dmax"] > 8).item() * accumulation_interval_minutes
|
|
225
226
|
table["n_minutes_Dmax_>9"] = np.sum(df["Dmax"] > 9).item() * accumulation_interval_minutes
|
|
227
|
+
|
|
228
|
+
# Convert all minutes columns to integer
|
|
229
|
+
for key in table:
|
|
230
|
+
if "minutes" in key:
|
|
231
|
+
table[key] = int(table[key])
|
|
226
232
|
return table
|
|
227
233
|
|
|
228
234
|
|
|
@@ -233,7 +239,7 @@ def create_table_dsd_summary(df):
|
|
|
233
239
|
df["log10(Nt)"] = np.log10(df["Nt"])
|
|
234
240
|
|
|
235
241
|
# List of variables to summarize
|
|
236
|
-
variables = ["
|
|
242
|
+
variables = ["LWC", "R", "Z", "D50", "Dm", "sigma_m", "Dmax", "Nw", "log10(Nw)", "Nt", "log10(Nt)"]
|
|
237
243
|
|
|
238
244
|
# Define subset dataframe
|
|
239
245
|
df_subset = df[variables]
|
|
@@ -356,9 +362,9 @@ def create_table_events_summary(df, temporal_resolution):
|
|
|
356
362
|
"mean_sigma_m": df_event["sigma_m"].mean(),
|
|
357
363
|
"median_sigma_m": df_event["sigma_m"].median(),
|
|
358
364
|
"max_sigma_m": df_event["sigma_m"].max(),
|
|
359
|
-
"
|
|
360
|
-
"
|
|
361
|
-
"
|
|
365
|
+
"mean_LWC": df_event["LWC"].mean(),
|
|
366
|
+
"median_LWC": df_event["LWC"].median(),
|
|
367
|
+
"max_LWC": df_event["LWC"].max(),
|
|
362
368
|
"max_Z": df_event["Z"].max(),
|
|
363
369
|
"mean_Nbins": int(df_event["Nbins"].mean()),
|
|
364
370
|
"max_Nbins": int(df_event["Nbins"].max()),
|
|
@@ -371,9 +377,22 @@ def create_table_events_summary(df, temporal_resolution):
|
|
|
371
377
|
|
|
372
378
|
df_events = pd.DataFrame.from_records(events_stats)
|
|
373
379
|
|
|
374
|
-
# Round
|
|
375
|
-
|
|
376
|
-
df_events[
|
|
380
|
+
# Round and cast columns
|
|
381
|
+
# - Round to 3 decimals
|
|
382
|
+
df_events["P_total"] = df_events["P_total"].round(decimals=3)
|
|
383
|
+
|
|
384
|
+
lwc_columns = [c for c in df_events.columns if "LWC" in c]
|
|
385
|
+
df_events[lwc_columns] = df_events[lwc_columns].round(decimals=3)
|
|
386
|
+
|
|
387
|
+
# - Cast to integer
|
|
388
|
+
df_events["duration"] = df_events["duration"].astype(int)
|
|
389
|
+
minutes_columns = [c for c in df_events.columns if "minutes" in c]
|
|
390
|
+
df_events[minutes_columns] = df_events[minutes_columns].astype(int)
|
|
391
|
+
|
|
392
|
+
# - Round to 2 decimals
|
|
393
|
+
for var in ["Dmax", "Dm", "sigma_m", "R", "Z"]:
|
|
394
|
+
names = [c for c in df_events.columns if var in c]
|
|
395
|
+
df_events[names] = df_events[names].round(decimals=2)
|
|
377
396
|
return df_events
|
|
378
397
|
|
|
379
398
|
|
|
@@ -385,7 +404,7 @@ def prepare_latex_table_dsd_summary(df):
|
|
|
385
404
|
df[numeric_cols] = df[numeric_cols].astype(str)
|
|
386
405
|
# Rename
|
|
387
406
|
rename_dict = {
|
|
388
|
-
"
|
|
407
|
+
"LWC": r"$LWC\,[\mathrm{g}\,\mathrm{m}^{-3}]$", # [g/m3]
|
|
389
408
|
"R": r"$R\,[\mathrm{mm}\,\mathrm{h}^{-1}]$", # [mm/hr]
|
|
390
409
|
"Z": r"$Z\,[\mathrm{dBZ}]$", # [dBZ]
|
|
391
410
|
"D50": r"$D_{50}\,[\mathrm{mm}]$", # [mm]
|
|
@@ -433,9 +452,9 @@ def prepare_latex_table_events_summary(df):
|
|
|
433
452
|
"mean_sigma_m": r"$\sigma_{m,\mathrm{mean}}$",
|
|
434
453
|
"median_sigma_m": r"$\sigma_{m,\mathrm{median}}$",
|
|
435
454
|
"max_sigma_m": r"$\sigma_{m,\max}$",
|
|
436
|
-
"
|
|
437
|
-
"
|
|
438
|
-
"
|
|
455
|
+
"mean_LWC": r"$LWC_{\mathrm{mean}}$",
|
|
456
|
+
"median_LWC": r"$LWC_{\mathrm{median}}$",
|
|
457
|
+
"max_LWC": r"$LWC_{\max}$",
|
|
439
458
|
"max_Z": r"$Z_{\max}$",
|
|
440
459
|
"mean_Nbins": r"$N_{\mathrm{bins},\mathrm{mean}}$",
|
|
441
460
|
"max_Nbins": r"$N_{\mathrm{bins},\max}$",
|
|
@@ -609,7 +628,7 @@ def fit_powerlaw(x, y, xbins, quantile=0.5, min_counts=10, x_in_db=False, use_ra
|
|
|
609
628
|
absolute_sigma=True,
|
|
610
629
|
maxfev=10_000, # max n iterations
|
|
611
630
|
)
|
|
612
|
-
|
|
631
|
+
a_std, b_std = np.sqrt(np.diag(pcov))
|
|
613
632
|
a_std = float(a_std)
|
|
614
633
|
b_std = float(b_std)
|
|
615
634
|
|
|
@@ -918,7 +937,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
918
937
|
df,
|
|
919
938
|
x="Dm",
|
|
920
939
|
y="Nw",
|
|
921
|
-
variables=["R", "
|
|
940
|
+
variables=["R", "LWC", "Nt"],
|
|
922
941
|
x_bins=np.arange(0, 8, 0.1),
|
|
923
942
|
y_bins=log_arange(10, 1_000_000, log_step=0.05, base=10),
|
|
924
943
|
)
|
|
@@ -927,7 +946,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
927
946
|
ds_Dm_LWC_stats = compute_2d_histogram(
|
|
928
947
|
df,
|
|
929
948
|
x="Dm",
|
|
930
|
-
y="
|
|
949
|
+
y="LWC",
|
|
931
950
|
variables=["R", "Nw", "Nt"],
|
|
932
951
|
x_bins=np.arange(0, 8, 0.1),
|
|
933
952
|
y_bins=log_arange(0.01, 10, log_step=0.05, base=10),
|
|
@@ -938,7 +957,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
938
957
|
df,
|
|
939
958
|
x="Dm",
|
|
940
959
|
y="R",
|
|
941
|
-
variables=["Nw", "
|
|
960
|
+
variables=["Nw", "LWC", "Nt"],
|
|
942
961
|
x_bins=np.arange(0, 8, 0.1),
|
|
943
962
|
y_bins=log_arange(0.1, 500, log_step=0.05, base=10),
|
|
944
963
|
)
|
|
@@ -948,7 +967,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
948
967
|
df,
|
|
949
968
|
x="Dm",
|
|
950
969
|
y="Nt",
|
|
951
|
-
variables=["R", "
|
|
970
|
+
variables=["R", "LWC", "Nw"],
|
|
952
971
|
x_bins=np.arange(0, 8, 0.1),
|
|
953
972
|
y_bins=log_arange(1, 100_000, log_step=0.05, base=10),
|
|
954
973
|
)
|
|
@@ -1019,7 +1038,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
1019
1038
|
axes[1, 0].set_ylim(nw_lim)
|
|
1020
1039
|
|
|
1021
1040
|
#### - LWC
|
|
1022
|
-
im_lwc = ds_Dm_Nw_stats["
|
|
1041
|
+
im_lwc = ds_Dm_Nw_stats["LWC_median"].plot.pcolormesh(
|
|
1023
1042
|
x="Dm",
|
|
1024
1043
|
y="Nw",
|
|
1025
1044
|
cmap=cmap_lwc,
|
|
@@ -1067,7 +1086,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
1067
1086
|
#### - Counts
|
|
1068
1087
|
ds_Dm_LWC_stats["count"].plot.pcolormesh(
|
|
1069
1088
|
x="Dm",
|
|
1070
|
-
y="
|
|
1089
|
+
y="LWC",
|
|
1071
1090
|
cmap=cmap_counts,
|
|
1072
1091
|
norm=norm_counts,
|
|
1073
1092
|
extend="max",
|
|
@@ -1083,7 +1102,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
1083
1102
|
# - Empty (diagonal where y-axis is W) - handled above in the loop
|
|
1084
1103
|
ds_Dm_LWC_stats["R_median"].plot.pcolormesh(
|
|
1085
1104
|
x="Dm",
|
|
1086
|
-
y="
|
|
1105
|
+
y="LWC",
|
|
1087
1106
|
cmap=cmap_r,
|
|
1088
1107
|
norm=norm_r,
|
|
1089
1108
|
alpha=0, # fully transparent
|
|
@@ -1099,7 +1118,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
1099
1118
|
#### - R
|
|
1100
1119
|
ds_Dm_LWC_stats["R_median"].plot.pcolormesh(
|
|
1101
1120
|
x="Dm",
|
|
1102
|
-
y="
|
|
1121
|
+
y="LWC",
|
|
1103
1122
|
cmap=cmap_r,
|
|
1104
1123
|
norm=norm_r,
|
|
1105
1124
|
extend="both",
|
|
@@ -1114,7 +1133,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
1114
1133
|
#### - Nt
|
|
1115
1134
|
im_nt = ds_Dm_LWC_stats["Nt_median"].plot.pcolormesh(
|
|
1116
1135
|
x="Dm",
|
|
1117
|
-
y="
|
|
1136
|
+
y="LWC",
|
|
1118
1137
|
cmap=cmap_nt,
|
|
1119
1138
|
norm=norm_nt,
|
|
1120
1139
|
extend="both",
|
|
@@ -1144,7 +1163,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
1144
1163
|
axes[3, 0].set_ylim(r_lim)
|
|
1145
1164
|
|
|
1146
1165
|
#### - LWC
|
|
1147
|
-
im_lwc = ds_Dm_R_stats["
|
|
1166
|
+
im_lwc = ds_Dm_R_stats["LWC_median"].plot.pcolormesh(
|
|
1148
1167
|
x="Dm",
|
|
1149
1168
|
y="R",
|
|
1150
1169
|
cmap=cmap_lwc,
|
|
@@ -1211,7 +1230,7 @@ def plot_dsd_params_relationships(df, add_nt=False, dpi=300):
|
|
|
1211
1230
|
axes[4, 0].set_ylim(nt_lim)
|
|
1212
1231
|
|
|
1213
1232
|
#### - LWC
|
|
1214
|
-
ds_Dm_Nt_stats["
|
|
1233
|
+
ds_Dm_Nt_stats["LWC_median"].plot.pcolormesh(
|
|
1215
1234
|
x="Dm",
|
|
1216
1235
|
y="Nt",
|
|
1217
1236
|
cmap=cmap_lwc,
|
|
@@ -1336,7 +1355,7 @@ def plot_dsd_params_density(df, log_dm=False, lwc=True, log_normalize=False, fig
|
|
|
1336
1355
|
norm = Normalize(0, 1) # Normalized data goes from 0 to 1
|
|
1337
1356
|
|
|
1338
1357
|
# Define the water variable based on lwc flag
|
|
1339
|
-
df["LWC"] = df["
|
|
1358
|
+
df["LWC"] = df["LWC"]
|
|
1340
1359
|
water_var = "LWC" if lwc else "R"
|
|
1341
1360
|
water_label = "LWC [g/m³]" if lwc else "R [mm/h]"
|
|
1342
1361
|
|
|
@@ -3731,7 +3750,7 @@ def define_filename(prefix, extension, data_source, campaign_name, station_name,
|
|
|
3731
3750
|
|
|
3732
3751
|
def create_l2_dataframe(ds):
|
|
3733
3752
|
"""Create pandas Dataframe for L2 analysis."""
|
|
3734
|
-
dims_to_drop = set(ds.dims).intersection({DIAMETER_DIMENSION, VELOCITY_DIMENSION})
|
|
3753
|
+
dims_to_drop = set(ds.dims).intersection({DIAMETER_DIMENSION, VELOCITY_DIMENSION, "crs"})
|
|
3735
3754
|
# - Drop array variables and convert to pandas
|
|
3736
3755
|
df = ds.drop_dims(dims_to_drop).to_pandas()
|
|
3737
3756
|
# - Drop coordinates
|
|
@@ -3742,7 +3761,7 @@ def create_l2_dataframe(ds):
|
|
|
3742
3761
|
return df
|
|
3743
3762
|
|
|
3744
3763
|
|
|
3745
|
-
def prepare_summary_dataset(ds, velocity_method="
|
|
3764
|
+
def prepare_summary_dataset(ds, velocity_method="theoretical_velocity", source="drop_number"):
|
|
3746
3765
|
"""Prepare the L2E or L2M dataset to be converted to a dataframe."""
|
|
3747
3766
|
# Select fall velocity method
|
|
3748
3767
|
if "velocity_method" in ds.dims:
|
|
@@ -3783,8 +3802,11 @@ def generate_station_summary(ds, summary_dir_path, data_source, campaign_name, s
|
|
|
3783
3802
|
# Ensure all data are in memory
|
|
3784
3803
|
ds = ds.compute()
|
|
3785
3804
|
|
|
3786
|
-
#
|
|
3787
|
-
|
|
3805
|
+
# Filter dataset to remove noisy timesteps
|
|
3806
|
+
# - Keep only timesteps with at least 3 Nbins to remove noise
|
|
3807
|
+
# - Keep only timesteps with sigma_m >= 0.2
|
|
3808
|
+
mask = (ds["Nbins"] >= 3) & (ds["sigma_m"] >= 0.2) & (ds["Nbins_missing_fraction"] <= 0.3) & (ds["Dmin"] <= 1)
|
|
3809
|
+
valid_idx = np.where(mask)[0]
|
|
3788
3810
|
ds = ds.isel(time=valid_idx)
|
|
3789
3811
|
|
|
3790
3812
|
####---------------------------------------------------------------------.
|
|
@@ -3795,7 +3817,10 @@ def generate_station_summary(ds, summary_dir_path, data_source, campaign_name, s
|
|
|
3795
3817
|
drop_number = ds["drop_number"].sum(dim="time")
|
|
3796
3818
|
|
|
3797
3819
|
# Define theoretical and measured average velocity
|
|
3798
|
-
|
|
3820
|
+
if "time" in ds["fall_velocity"].dims:
|
|
3821
|
+
theoretical_average_velocity = ds["fall_velocity"].mean(dim="time")
|
|
3822
|
+
else:
|
|
3823
|
+
theoretical_average_velocity = ds["fall_velocity"]
|
|
3799
3824
|
measured_average_velocity = get_drop_average_velocity(drop_number)
|
|
3800
3825
|
|
|
3801
3826
|
# Save raw and filtered spectrum over time & theoretical and measured average fall velocity
|
|
@@ -3909,6 +3934,7 @@ def generate_station_summary(ds, summary_dir_path, data_source, campaign_name, s
|
|
|
3909
3934
|
table_events_summary.to_csv(table_events_summary_csv_filepath)
|
|
3910
3935
|
# - Save table as pdf
|
|
3911
3936
|
if is_latex_engine_available():
|
|
3937
|
+
# Sorted by time
|
|
3912
3938
|
table_events_summary_pdf_filename = table_events_summary_csv_filename.replace(".csv", ".pdf")
|
|
3913
3939
|
table_events_summary_pdf_filepath = os.path.join(summary_dir_path, table_events_summary_pdf_filename)
|
|
3914
3940
|
save_table_to_pdf(
|
|
@@ -3919,6 +3945,45 @@ def generate_station_summary(ds, summary_dir_path, data_source, campaign_name, s
|
|
|
3919
3945
|
orientation="landscape",
|
|
3920
3946
|
)
|
|
3921
3947
|
|
|
3948
|
+
# Sorted by maximum rain intensity
|
|
3949
|
+
table_events_summary = table_events_summary.sort_values(by="max_R", ascending=False)
|
|
3950
|
+
table_events_summary = table_events_summary.reset_index(drop=True)
|
|
3951
|
+
table_events_summary_pdf_filename = define_filename(
|
|
3952
|
+
prefix="Events_Summary_Sorted_By_Rmax",
|
|
3953
|
+
extension="pdf",
|
|
3954
|
+
data_source=data_source,
|
|
3955
|
+
campaign_name=campaign_name,
|
|
3956
|
+
station_name=station_name,
|
|
3957
|
+
temporal_resolution=temporal_resolution,
|
|
3958
|
+
)
|
|
3959
|
+
table_events_summary_pdf_filepath = os.path.join(summary_dir_path, table_events_summary_pdf_filename)
|
|
3960
|
+
save_table_to_pdf(
|
|
3961
|
+
df=prepare_latex_table_events_summary(table_events_summary),
|
|
3962
|
+
filepath=table_events_summary_pdf_filepath,
|
|
3963
|
+
index=True,
|
|
3964
|
+
caption="Events Summary",
|
|
3965
|
+
orientation="landscape",
|
|
3966
|
+
)
|
|
3967
|
+
# Sorted by Ptotal
|
|
3968
|
+
table_events_summary = table_events_summary.sort_values(by="P_total", ascending=False)
|
|
3969
|
+
table_events_summary = table_events_summary.reset_index(drop=True)
|
|
3970
|
+
table_events_summary_pdf_filename = define_filename(
|
|
3971
|
+
prefix="Events_Summary_Sorted_By_Ptot",
|
|
3972
|
+
extension="pdf",
|
|
3973
|
+
data_source=data_source,
|
|
3974
|
+
campaign_name=campaign_name,
|
|
3975
|
+
station_name=station_name,
|
|
3976
|
+
temporal_resolution=temporal_resolution,
|
|
3977
|
+
)
|
|
3978
|
+
table_events_summary_pdf_filepath = os.path.join(summary_dir_path, table_events_summary_pdf_filename)
|
|
3979
|
+
save_table_to_pdf(
|
|
3980
|
+
df=prepare_latex_table_events_summary(table_events_summary),
|
|
3981
|
+
filepath=table_events_summary_pdf_filepath,
|
|
3982
|
+
index=True,
|
|
3983
|
+
caption="Events Summary",
|
|
3984
|
+
orientation="landscape",
|
|
3985
|
+
)
|
|
3986
|
+
|
|
3922
3987
|
# ---------------------------------------------------------------------.
|
|
3923
3988
|
#### Create table with integral DSD parameters statistics
|
|
3924
3989
|
table_dsd_summary = create_table_dsd_summary(df)
|
disdrodb/utils/__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
|
disdrodb/utils/archiving.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
|
"""Utility function for DISDRODB product archiving."""
|
|
18
|
+
|
|
18
19
|
import datetime
|
|
19
20
|
|
|
20
21
|
import numpy as np
|
|
@@ -111,17 +112,18 @@ def generate_time_blocks(
|
|
|
111
112
|
def identify_events(
|
|
112
113
|
filepaths,
|
|
113
114
|
parallel=False,
|
|
114
|
-
|
|
115
|
+
variable="N",
|
|
116
|
+
detection_threshold=5,
|
|
115
117
|
neighbor_min_size=2,
|
|
116
118
|
neighbor_time_interval="5MIN",
|
|
117
119
|
event_max_time_gap="6H",
|
|
118
120
|
event_min_duration="5MIN",
|
|
119
121
|
event_min_size=3,
|
|
120
122
|
):
|
|
121
|
-
"""Return a list of
|
|
123
|
+
"""Return a list of precipitating events.
|
|
122
124
|
|
|
123
|
-
|
|
124
|
-
Any
|
|
125
|
+
Precipitating events are defined when 'variable' > detection_threshold.
|
|
126
|
+
Any isolated timesteps with precipitation (based on neighborhood criteria) is removed.
|
|
125
127
|
Then, consecutive rainy timesteps are grouped into the same event if the time gap between them does not
|
|
126
128
|
exceed `event_max_time_gap`. Finally, events that do not meet minimum size or duration
|
|
127
129
|
requirements are filtered out.
|
|
@@ -130,6 +132,11 @@ def identify_events(
|
|
|
130
132
|
----------
|
|
131
133
|
filepaths: list
|
|
132
134
|
List of L1C file paths.
|
|
135
|
+
variable : str
|
|
136
|
+
Name of the variable to use to apply the event detection.
|
|
137
|
+
The default is "N".
|
|
138
|
+
detection_threshold : int
|
|
139
|
+
Minimum value of 'variable' to consider an event timestep.
|
|
133
140
|
parallel: bool
|
|
134
141
|
Whether to load the files in parallel.
|
|
135
142
|
Set parallel=True only in a multiprocessing environment.
|
|
@@ -163,11 +170,11 @@ def identify_events(
|
|
|
163
170
|
- "n_timesteps": int, number of valid timesteps in the event
|
|
164
171
|
"""
|
|
165
172
|
# Open datasets in parallel
|
|
166
|
-
ds = open_netcdf_files(filepaths, variables=["time",
|
|
173
|
+
ds = open_netcdf_files(filepaths, variables=["time", variable], parallel=parallel, compute=True)
|
|
167
174
|
# Sort dataset by time
|
|
168
175
|
ds = ensure_sorted_by_time(ds)
|
|
169
176
|
# Define candidate timesteps to group into events
|
|
170
|
-
idx_valid = ds[
|
|
177
|
+
idx_valid = ds[variable].to_numpy() > detection_threshold
|
|
171
178
|
timesteps = ds["time"].to_numpy()[idx_valid]
|
|
172
179
|
if "sample_interval" in ds:
|
|
173
180
|
sample_interval = ds["sample_interval"].compute().item()
|
|
@@ -263,8 +270,9 @@ def define_temporal_partitions(filepaths, strategy, parallel, strategy_options):
|
|
|
263
270
|
See identify_time_partitions for more information.
|
|
264
271
|
|
|
265
272
|
If ``strategy == 'event'``, supported options are:
|
|
266
|
-
|
|
267
|
-
|
|
273
|
+
- ``variable`` : str
|
|
274
|
+
Name of the variable to use to apply the event detection.
|
|
275
|
+
- ``detection_threshold`` : int
|
|
268
276
|
Minimum number of drops to consider a timestep.
|
|
269
277
|
- ``neighbor_min_size`` : int
|
|
270
278
|
Minimum cluster size for merging neighboring events.
|
|
@@ -317,7 +325,7 @@ def _map_files_to_blocks(files_start_time, files_end_time, filepaths, block_star
|
|
|
317
325
|
# Create a list with the a dictionary for each block
|
|
318
326
|
filepaths = np.array(filepaths)
|
|
319
327
|
results = []
|
|
320
|
-
for i, (start, end) in enumerate(zip(block_starts, block_ends)):
|
|
328
|
+
for i, (start, end) in enumerate(zip(block_starts, block_ends, strict=True)):
|
|
321
329
|
indices = np.where(mask[:, i])[0]
|
|
322
330
|
if indices.size > 0:
|
|
323
331
|
results.append(
|
disdrodb/utils/attrs.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,9 +15,10 @@
|
|
|
17
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
16
|
# -----------------------------------------------------------------------------.
|
|
19
17
|
"""DISDRODB netCDF4 attributes utilities."""
|
|
20
|
-
|
|
18
|
+
|
|
21
19
|
import os
|
|
22
20
|
|
|
21
|
+
from disdrodb.api.checks import get_current_utc_time
|
|
23
22
|
from disdrodb.constants import ARCHIVE_VERSION, CONVENTIONS, COORDINATES, SOFTWARE_VERSION
|
|
24
23
|
from disdrodb.utils.yaml import read_yaml
|
|
25
24
|
|
|
@@ -95,15 +94,18 @@ def update_disdrodb_attrs(ds, product: str):
|
|
|
95
94
|
# ----------------------------------------------
|
|
96
95
|
# Add time_coverage_start and time_coverage_end
|
|
97
96
|
if "time" in ds.dims:
|
|
97
|
+
encoding = ds["time"].encoding
|
|
98
98
|
ds["time"] = ds["time"].dt.floor("s") # ensure no sub-second values
|
|
99
99
|
ds["time"] = ds["time"].astype("datetime64[s]")
|
|
100
|
+
ds["time"].encoding = encoding # otherwise time encoding get lost !
|
|
101
|
+
|
|
100
102
|
attrs["time_coverage_start"] = str(ds["time"].data[0])
|
|
101
103
|
attrs["time_coverage_end"] = str(ds["time"].data[-1])
|
|
102
104
|
|
|
103
105
|
# ----------------------------------------------
|
|
104
106
|
# Set DISDRODDB attributes
|
|
105
107
|
# - Add DISDRODB processing info
|
|
106
|
-
now =
|
|
108
|
+
now = get_current_utc_time()
|
|
107
109
|
current_time = now.strftime("%Y-%m-%d %H:%M:%S")
|
|
108
110
|
attrs["disdrodb_processing_date"] = current_time
|
|
109
111
|
# - Add DISDRODB product and version
|