disdrodb 0.2.1__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 +9 -9
- disdrodb/api/checks.py +1 -3
- disdrodb/api/configs.py +1 -3
- disdrodb/api/create_directories.py +4 -6
- disdrodb/api/info.py +1 -3
- disdrodb/api/io.py +9 -8
- 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 +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 +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} +264 -44
- disdrodb/issue/__init__.py +1 -3
- disdrodb/issue/checks.py +1 -3
- disdrodb/issue/reader.py +1 -3
- disdrodb/issue/writer.py +1 -3
- disdrodb/l0/__init__.py +1 -1
- disdrodb/l0/check_configs.py +25 -16
- disdrodb/l0/check_standards.py +1 -3
- 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 +1 -3
- disdrodb/l0/l0a_processing.py +1 -3
- disdrodb/l0/l0b_nc_processing.py +2 -4
- disdrodb/l0/l0b_processing.py +1 -3
- disdrodb/l0/l0c_processing.py +27 -11
- 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 +47 -6
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_PI.py +1 -1
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_T.py +5 -2
- disdrodb/l0/readers/LPM/ITALY/GID_LPM_W.py +1 -3
- 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 +1 -1
- disdrodb/l0/readers/LPM/NORWAY/HAUKELISETER_LPM.py +1 -3
- disdrodb/l0/readers/LPM/NORWAY/NMBU_LPM.py +1 -3
- 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 +1 -3
- disdrodb/l0/readers/LPM/USA/CHARLESTON.py +1 -3
- disdrodb/l0/readers/LPM_V0/BELGIUM/ULIEGE.py +1 -3
- disdrodb/l0/readers/LPM_V0/ITALY/GID_LPM_V0.py +1 -1
- 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 +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 +1 -1
- disdrodb/l0/readers/PARSIVEL2/ARM/ARM_PARSIVEL2.py +1 -1
- disdrodb/l0/readers/PARSIVEL2/BASQUECOUNTRY/EUSKALMET_OTT2.py +1 -1
- 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 +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 +1 -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 +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 +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 +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/PARSIVEL2/NORWAY/UIB.py +10 -2
- disdrodb/l0/readers/PARSIVEL2/PHILIPPINES/PAGASA.py +1 -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 +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 +1 -1
- disdrodb/l0/readers/PARSIVEL2/USA/CW3E.py +1 -1
- 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/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 +1 -3
- disdrodb/l0/readers/SWS250/BELGIUM/KMI.py +1 -3
- 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 +57 -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 +26 -16
- disdrodb/routines/l1.py +8 -6
- disdrodb/routines/l2.py +8 -4
- disdrodb/routines/options.py +116 -73
- disdrodb/routines/options_validation.py +728 -0
- disdrodb/routines/wrappers.py +431 -11
- disdrodb/scattering/__init__.py +1 -1
- disdrodb/scattering/axis_ratio.py +6 -6
- disdrodb/scattering/permittivity.py +8 -8
- disdrodb/scattering/routines.py +31 -13
- disdrodb/summary/__init__.py +1 -1
- disdrodb/summary/routines.py +83 -25
- 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 +9 -11
- disdrodb/utils/dask.py +2 -3
- 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 +175 -5
- 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 +192 -18
- {disdrodb-0.2.1.dist-info → disdrodb-0.3.0.dist-info}/METADATA +2 -2
- disdrodb-0.3.0.dist-info/RECORD +358 -0
- {disdrodb-0.2.1.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/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.3.0.dist-info}/WHEEL +0 -0
- {disdrodb-0.2.1.dist-info → disdrodb-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {disdrodb-0.2.1.dist-info → disdrodb-0.3.0.dist-info}/top_level.txt +0 -0
disdrodb/l2/processing.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,12 +15,11 @@
|
|
|
15
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
# -----------------------------------------------------------------------------.
|
|
17
17
|
"""Implement DISDRODB L2 processing."""
|
|
18
|
-
|
|
19
18
|
import numpy as np
|
|
20
19
|
import xarray as xr
|
|
21
20
|
|
|
22
|
-
from disdrodb.constants import DIAMETER_DIMENSION
|
|
23
|
-
from disdrodb.
|
|
21
|
+
from disdrodb.constants import DIAMETER_DIMENSION, METEOROLOGICAL_VARIABLES, VELOCITY_DIMENSION
|
|
22
|
+
from disdrodb.fall_velocity import get_rain_fall_velocity, get_rain_fall_velocity_from_ds
|
|
24
23
|
from disdrodb.l1_env.routines import load_env_dataset
|
|
25
24
|
from disdrodb.l2.empirical_dsd import (
|
|
26
25
|
BINS_METRICS,
|
|
@@ -29,55 +28,23 @@ from disdrodb.l2.empirical_dsd import (
|
|
|
29
28
|
compute_spectrum_parameters,
|
|
30
29
|
get_drop_number_concentration,
|
|
31
30
|
get_effective_sampling_area,
|
|
31
|
+
get_effective_sampling_interval,
|
|
32
32
|
get_kinetic_energy_variables_from_drop_number,
|
|
33
|
+
get_min_max_diameter,
|
|
33
34
|
get_rain_accumulation,
|
|
34
35
|
get_rain_rate_from_drop_number,
|
|
35
36
|
)
|
|
36
37
|
from disdrodb.psd import create_psd, estimate_model_parameters
|
|
37
38
|
from disdrodb.psd.fitting import compute_gof_stats
|
|
38
39
|
from disdrodb.utils.decorators import check_pytmatrix_availability
|
|
39
|
-
from disdrodb.utils.
|
|
40
|
+
from disdrodb.utils.manipulations import (
|
|
41
|
+
define_diameter_array,
|
|
42
|
+
filter_diameter_bins,
|
|
43
|
+
filter_velocity_bins,
|
|
44
|
+
)
|
|
40
45
|
from disdrodb.utils.writer import finalize_product
|
|
41
46
|
|
|
42
47
|
|
|
43
|
-
def define_diameter_array(diameter_min=0, diameter_max=10, diameter_spacing=0.05):
|
|
44
|
-
"""
|
|
45
|
-
Define an array of diameters and their corresponding bin properties.
|
|
46
|
-
|
|
47
|
-
Parameters
|
|
48
|
-
----------
|
|
49
|
-
diameter_min : float, optional
|
|
50
|
-
The minimum diameter value. The default value is 0 mm.
|
|
51
|
-
diameter_max : float, optional
|
|
52
|
-
The maximum diameter value. The default value is 10 mm.
|
|
53
|
-
diameter_spacing : float, optional
|
|
54
|
-
The spacing between diameter values. The default value is 0.05 mm.
|
|
55
|
-
|
|
56
|
-
Returns
|
|
57
|
-
-------
|
|
58
|
-
xr.DataArray
|
|
59
|
-
A DataArray containing the center of each diameter bin, with coordinates for
|
|
60
|
-
the bin width, lower bound, upper bound, and center.
|
|
61
|
-
|
|
62
|
-
"""
|
|
63
|
-
diameters_bounds = np.arange(diameter_min, diameter_max + diameter_spacing / 2, step=diameter_spacing)
|
|
64
|
-
diameters_bin_lower = diameters_bounds[:-1]
|
|
65
|
-
diameters_bin_upper = diameters_bounds[1:]
|
|
66
|
-
diameters_bin_width = diameters_bin_upper - diameters_bin_lower
|
|
67
|
-
diameters_bin_center = diameters_bin_lower + diameters_bin_width / 2
|
|
68
|
-
da = xr.DataArray(
|
|
69
|
-
diameters_bin_center,
|
|
70
|
-
dims="diameter_bin_center",
|
|
71
|
-
coords={
|
|
72
|
-
"diameter_bin_width": ("diameter_bin_center", diameters_bin_width),
|
|
73
|
-
"diameter_bin_lower": ("diameter_bin_center", diameters_bin_lower),
|
|
74
|
-
"diameter_bin_upper": ("diameter_bin_center", diameters_bin_upper),
|
|
75
|
-
"diameter_bin_center": ("diameter_bin_center", diameters_bin_center),
|
|
76
|
-
},
|
|
77
|
-
)
|
|
78
|
-
return da
|
|
79
|
-
|
|
80
|
-
|
|
81
48
|
def define_velocity_array(ds):
|
|
82
49
|
"""
|
|
83
50
|
Create the fall velocity DataArray using various methods.
|
|
@@ -99,7 +66,7 @@ def define_velocity_array(ds):
|
|
|
99
66
|
if "velocity_bin_center" in ds.dims:
|
|
100
67
|
velocity = xr.Dataset(
|
|
101
68
|
{
|
|
102
|
-
"
|
|
69
|
+
"theoretical_velocity": xr.ones_like(drop_number) * ds["fall_velocity"],
|
|
103
70
|
"measured_velocity": xr.ones_like(drop_number) * ds["velocity_bin_center"],
|
|
104
71
|
},
|
|
105
72
|
).to_array(dim="velocity_method")
|
|
@@ -108,12 +75,183 @@ def define_velocity_array(ds):
|
|
|
108
75
|
return velocity
|
|
109
76
|
|
|
110
77
|
|
|
78
|
+
####--------------------------------------------------------------------------
|
|
79
|
+
#### Extract drop spectrum
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def retrieve_drop_spectrum(
|
|
83
|
+
ds,
|
|
84
|
+
ds_env,
|
|
85
|
+
above_velocity_fraction=None,
|
|
86
|
+
above_velocity_tolerance=None,
|
|
87
|
+
below_velocity_fraction=None,
|
|
88
|
+
below_velocity_tolerance=None,
|
|
89
|
+
maintain_drops_smaller_than=1,
|
|
90
|
+
maintain_drops_slower_than=2.5,
|
|
91
|
+
maintain_smallest_drops=False,
|
|
92
|
+
remove_splashing_drops=True,
|
|
93
|
+
fall_velocity_model="Beard1976",
|
|
94
|
+
):
|
|
95
|
+
"""Retrieve the drop spectrum from the DISDRODB L1 product."""
|
|
96
|
+
from disdrodb.fall_velocity.rain import get_rain_fall_velocity
|
|
97
|
+
|
|
98
|
+
# Retrieve spectrum
|
|
99
|
+
raw_spectrum = ds["raw_drop_number"].copy()
|
|
100
|
+
|
|
101
|
+
# Retrieve coordinates
|
|
102
|
+
diameter_upper = raw_spectrum["diameter_bin_upper"]
|
|
103
|
+
diameter_lower = raw_spectrum["diameter_bin_lower"]
|
|
104
|
+
velocity_upper = raw_spectrum["velocity_bin_upper"]
|
|
105
|
+
|
|
106
|
+
# Retrieve rainfall mask
|
|
107
|
+
raindrop_fall_velocity_upper = get_rain_fall_velocity(
|
|
108
|
+
diameter=diameter_upper,
|
|
109
|
+
model=fall_velocity_model,
|
|
110
|
+
ds_env=ds_env,
|
|
111
|
+
)
|
|
112
|
+
raindrop_fall_velocity_lower = get_rain_fall_velocity(
|
|
113
|
+
diameter=diameter_lower,
|
|
114
|
+
model=fall_velocity_model,
|
|
115
|
+
ds_env=ds_env,
|
|
116
|
+
)
|
|
117
|
+
rain_mask = define_rain_spectrum_mask(
|
|
118
|
+
drop_number=raw_spectrum,
|
|
119
|
+
fall_velocity_lower=raindrop_fall_velocity_lower,
|
|
120
|
+
fall_velocity_upper=raindrop_fall_velocity_upper,
|
|
121
|
+
above_velocity_fraction=above_velocity_fraction,
|
|
122
|
+
above_velocity_tolerance=above_velocity_tolerance,
|
|
123
|
+
below_velocity_fraction=below_velocity_fraction,
|
|
124
|
+
below_velocity_tolerance=below_velocity_tolerance,
|
|
125
|
+
maintain_drops_smaller_than=maintain_drops_smaller_than,
|
|
126
|
+
maintain_drops_slower_than=maintain_drops_slower_than,
|
|
127
|
+
maintain_smallest_drops=maintain_smallest_drops,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Set to 0 spectrum not classified as liquid or mixed
|
|
131
|
+
if "precipitation_type" in ds:
|
|
132
|
+
raw_spectrum = xr.where(ds["precipitation_type"].isin([0, 2]), raw_spectrum, 0)
|
|
133
|
+
|
|
134
|
+
# Retrieve drop spectrum
|
|
135
|
+
# - Liquid + Mixed
|
|
136
|
+
drop_spectrum = raw_spectrum.where(rain_mask, 0)
|
|
137
|
+
|
|
138
|
+
# Optionally mask area affected by splashing
|
|
139
|
+
if remove_splashing_drops and "flag_splashing" in ds:
|
|
140
|
+
flag_splashing = ds["flag_splashing"]
|
|
141
|
+
splash_mask = (diameter_lower >= 0.0) & (diameter_upper <= 6) & (velocity_upper <= 0.6)
|
|
142
|
+
|
|
143
|
+
drop_spectrum = xr.where(flag_splashing == 1, drop_spectrum.where(~splash_mask, 0), drop_spectrum)
|
|
144
|
+
return drop_spectrum
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def define_rain_spectrum_mask(
|
|
148
|
+
drop_number,
|
|
149
|
+
fall_velocity_lower,
|
|
150
|
+
fall_velocity_upper,
|
|
151
|
+
above_velocity_fraction=None,
|
|
152
|
+
above_velocity_tolerance=None,
|
|
153
|
+
below_velocity_fraction=None,
|
|
154
|
+
below_velocity_tolerance=None,
|
|
155
|
+
maintain_drops_smaller_than=1, # 1, # 2
|
|
156
|
+
maintain_drops_slower_than=2.5, # 2.5, # 3
|
|
157
|
+
maintain_smallest_drops=False,
|
|
158
|
+
):
|
|
159
|
+
"""Define a mask for the drop spectrum based on fall velocity thresholds.
|
|
160
|
+
|
|
161
|
+
Parameters
|
|
162
|
+
----------
|
|
163
|
+
drop_number : xarray.DataArray
|
|
164
|
+
Array of drop counts per diameter and velocity bins.
|
|
165
|
+
fall_velocity_lower : array-like
|
|
166
|
+
The expected terminal fall velocities lower bound for rain drops of given size interval.
|
|
167
|
+
fall_velocity_upper : array-like
|
|
168
|
+
The expected terminal fall velocities upper bound for rain drops of given size interval.
|
|
169
|
+
above_velocity_fraction : float, optional
|
|
170
|
+
Fraction of terminal fall velocity above which rain drops are considered too fast.
|
|
171
|
+
Either specify ``above_velocity_fraction`` or ``above_velocity_tolerance``.
|
|
172
|
+
above_velocity_tolerance : float, optional
|
|
173
|
+
Absolute tolerance above which rain drops terminal fall velocities are considered too fast.
|
|
174
|
+
Either specify ``above_velocity_fraction`` or ``above_velocity_tolerance``.
|
|
175
|
+
below_velocity_fraction : float, optional
|
|
176
|
+
Fraction of terminal fall velocity below which rain drops are considered too slow.
|
|
177
|
+
Either specify ``below_velocity_fraction`` or ``below_velocity_tolerance``.
|
|
178
|
+
below_velocity_tolerance : float, optional
|
|
179
|
+
Absolute tolerance below which rain drops terminal fall velocities are considered too slow.
|
|
180
|
+
Either specify ``below_velocity_fraction`` or ``below_velocity_tolerance``.
|
|
181
|
+
maintain_smallest : bool, optional
|
|
182
|
+
If True, ensures that the small rain drops in the spectrum are retained in the mask.
|
|
183
|
+
The smallest rain drops are characterized by ``maintain_drops_smaller_than``
|
|
184
|
+
and ``maintain_drops_slower_than`` arguments.
|
|
185
|
+
Defaults to False.
|
|
186
|
+
maintain_drops_smaller_than : float, optional
|
|
187
|
+
The diameter threshold to use for keeping the smallest rain drop.
|
|
188
|
+
Defaults to 1 mm.
|
|
189
|
+
maintain_drops_slower_than : float, optional
|
|
190
|
+
The fall velocity threshold to use for keeping the smallest rain drops.
|
|
191
|
+
Defaults to 2.5 m/s.
|
|
192
|
+
|
|
193
|
+
Returns
|
|
194
|
+
-------
|
|
195
|
+
xarray.DataArray
|
|
196
|
+
A boolean mask array indicating valid bins according to the specified criteria.
|
|
197
|
+
|
|
198
|
+
"""
|
|
199
|
+
# Ensure it creates a 2D mask if the fall_velocity does not vary over time
|
|
200
|
+
if "time" in drop_number.dims and "time" not in fall_velocity_lower.dims:
|
|
201
|
+
drop_number = drop_number.isel(time=0)
|
|
202
|
+
|
|
203
|
+
# Check arguments
|
|
204
|
+
if above_velocity_fraction is not None and above_velocity_tolerance is not None:
|
|
205
|
+
raise ValueError("Either specify 'above_velocity_fraction' or 'above_velocity_tolerance'.")
|
|
206
|
+
if below_velocity_fraction is not None and below_velocity_tolerance is not None:
|
|
207
|
+
raise ValueError("Either specify 'below_velocity_fraction' or 'below_velocity_tolerance'.")
|
|
208
|
+
|
|
209
|
+
# Define above/below velocity thresholds
|
|
210
|
+
if above_velocity_fraction is not None:
|
|
211
|
+
above_fall_velocity = fall_velocity_upper * (1 + above_velocity_fraction)
|
|
212
|
+
elif above_velocity_tolerance is not None:
|
|
213
|
+
above_fall_velocity = fall_velocity_upper + above_velocity_tolerance
|
|
214
|
+
else:
|
|
215
|
+
above_fall_velocity = np.inf
|
|
216
|
+
|
|
217
|
+
if below_velocity_fraction is not None:
|
|
218
|
+
below_fall_velocity = fall_velocity_lower * (1 - below_velocity_fraction)
|
|
219
|
+
elif below_velocity_tolerance is not None:
|
|
220
|
+
below_fall_velocity = fall_velocity_lower - below_velocity_tolerance
|
|
221
|
+
else:
|
|
222
|
+
below_fall_velocity = 0
|
|
223
|
+
|
|
224
|
+
# Define velocity 2D array
|
|
225
|
+
velocity_lower = xr.ones_like(drop_number) * drop_number["velocity_bin_lower"]
|
|
226
|
+
velocity_upper = xr.ones_like(drop_number) * drop_number["velocity_bin_upper"]
|
|
227
|
+
|
|
228
|
+
# Define mask
|
|
229
|
+
mask = np.logical_and(
|
|
230
|
+
velocity_upper > below_fall_velocity,
|
|
231
|
+
velocity_lower < above_fall_velocity,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# Maintant smallest drops
|
|
235
|
+
if maintain_smallest_drops:
|
|
236
|
+
mask_smallest = np.logical_and(
|
|
237
|
+
drop_number["diameter_bin_upper"] <= maintain_drops_smaller_than,
|
|
238
|
+
drop_number["velocity_bin_upper"] <= maintain_drops_slower_than,
|
|
239
|
+
)
|
|
240
|
+
mask = np.logical_or(mask, mask_smallest)
|
|
241
|
+
|
|
242
|
+
return mask
|
|
243
|
+
|
|
244
|
+
|
|
111
245
|
####--------------------------------------------------------------------------
|
|
112
246
|
#### Timesteps filtering functions
|
|
113
247
|
|
|
114
248
|
|
|
115
249
|
def select_timesteps_with_drops(ds, minimum_ndrops=0):
|
|
116
250
|
"""Select timesteps with at least the specified number of drops."""
|
|
251
|
+
# If not a unique time dimension, skip subsetting
|
|
252
|
+
if ds["N"].dims != ("time",):
|
|
253
|
+
return ds
|
|
254
|
+
# Otherwise subset time dimension
|
|
117
255
|
valid_timesteps = ds["N"].to_numpy() >= minimum_ndrops
|
|
118
256
|
if not valid_timesteps.any().item():
|
|
119
257
|
raise ValueError(f"No timesteps with N >= {minimum_ndrops}.")
|
|
@@ -124,6 +262,10 @@ def select_timesteps_with_drops(ds, minimum_ndrops=0):
|
|
|
124
262
|
|
|
125
263
|
def select_timesteps_with_minimum_nbins(ds, minimum_nbins):
|
|
126
264
|
"""Select timesteps with at least the specified number of diameter bins with drops."""
|
|
265
|
+
# If not a unique time dimension, skip subsetting
|
|
266
|
+
if ds["Nbins"].dims != ("time",):
|
|
267
|
+
return ds
|
|
268
|
+
# Otherwise subset time dimension
|
|
127
269
|
if minimum_nbins == 0:
|
|
128
270
|
return ds
|
|
129
271
|
valid_timesteps = ds["Nbins"].to_numpy() >= minimum_nbins
|
|
@@ -167,7 +309,7 @@ def check_l2e_input_dataset(ds):
|
|
|
167
309
|
from disdrodb.scattering import RADAR_OPTIONS
|
|
168
310
|
|
|
169
311
|
# Check minimum required variables, coordinates and dimensions are presents
|
|
170
|
-
required_variables = ["
|
|
312
|
+
required_variables = ["raw_drop_number"]
|
|
171
313
|
required_coords = [
|
|
172
314
|
"diameter_bin_center",
|
|
173
315
|
"diameter_bin_width",
|
|
@@ -194,9 +336,25 @@ def generate_l2e(
|
|
|
194
336
|
ds_env=None,
|
|
195
337
|
compute_spectra=False,
|
|
196
338
|
compute_percentage_contribution=False,
|
|
339
|
+
# Filtering options
|
|
197
340
|
minimum_ndrops=1,
|
|
198
341
|
minimum_nbins=1,
|
|
199
342
|
minimum_rain_rate=0.01,
|
|
343
|
+
minimum_diameter=0,
|
|
344
|
+
maximum_diameter=10,
|
|
345
|
+
minimum_velocity=0,
|
|
346
|
+
maximum_velocity=12,
|
|
347
|
+
keep_mixed_precipitation=False,
|
|
348
|
+
# Spectrum filtering options
|
|
349
|
+
fall_velocity_model="Beard1976",
|
|
350
|
+
above_velocity_fraction=0.5,
|
|
351
|
+
above_velocity_tolerance=None,
|
|
352
|
+
below_velocity_fraction=0.5,
|
|
353
|
+
below_velocity_tolerance=None,
|
|
354
|
+
maintain_drops_smaller_than=1, # 2
|
|
355
|
+
maintain_drops_slower_than=2.5, # 3
|
|
356
|
+
maintain_smallest_drops=True,
|
|
357
|
+
remove_splashing_drops=True,
|
|
200
358
|
):
|
|
201
359
|
"""Generate the DISDRODB L2E dataset from the DISDRODB L1 dataset.
|
|
202
360
|
|
|
@@ -205,15 +363,40 @@ def generate_l2e(
|
|
|
205
363
|
ds : xarray.Dataset
|
|
206
364
|
DISDRODB L1 dataset.
|
|
207
365
|
Alternatively, a xarray dataset with at least:
|
|
208
|
-
|
|
209
|
-
- variables: drop_number, fall_velocity
|
|
366
|
+
- variables: raw_drop_number
|
|
210
367
|
- dimension: DIAMETER_DIMENSION
|
|
211
368
|
- coordinates: diameter_bin_center, diameter_bin_width, sample_interval
|
|
212
369
|
- attributes: sensor_name
|
|
213
|
-
|
|
214
370
|
ds_env : xarray.Dataset, optional
|
|
215
371
|
Environmental dataset used for fall velocity and water density estimates.
|
|
216
372
|
If None, a default environment dataset will be loaded.
|
|
373
|
+
fall_velocity_model : str, optional
|
|
374
|
+
Model name to estimate drop fall velocity.
|
|
375
|
+
The default method is ``"Beard1976"``.
|
|
376
|
+
minimum_diameter : float, optional
|
|
377
|
+
Minimum diameter for filtering. The default value is 0 mm.
|
|
378
|
+
maximum_diameter : float, optional
|
|
379
|
+
Maximum diameter for filtering. The default value is 10 mm.
|
|
380
|
+
minimum_velocity : float, optional
|
|
381
|
+
Minimum velocity for filtering. The default value is 0 m/s.
|
|
382
|
+
maximum_velocity : float, optional
|
|
383
|
+
Maximum velocity for filtering. The default value is 12 m/s.
|
|
384
|
+
above_velocity_fraction : float, optional
|
|
385
|
+
Fraction of drops above velocity threshold. The default value is 0.5.
|
|
386
|
+
above_velocity_tolerance : float or None, optional
|
|
387
|
+
Tolerance for above velocity filtering. The default value is ``None``.
|
|
388
|
+
below_velocity_fraction : float, optional
|
|
389
|
+
Fraction of drops below velocity threshold. The default value is 0.5.
|
|
390
|
+
below_velocity_tolerance : float or None, optional
|
|
391
|
+
Tolerance for below velocity filtering. The default value is ``None``.
|
|
392
|
+
maintain_drops_smaller_than : float, optional
|
|
393
|
+
Threshold for small diameter drops. The default value is 1.
|
|
394
|
+
maintain_drops_slower_than : float, optional
|
|
395
|
+
Threshold for small velocity drops. The default value is 2.5.
|
|
396
|
+
maintain_smallest_drops : bool, optional
|
|
397
|
+
Whether to maintain the smallest drops. The default value is ``True``.
|
|
398
|
+
remove_splashing_drops: bool, optional
|
|
399
|
+
Whether to mask splashing drops. The default value is ``True``.
|
|
217
400
|
|
|
218
401
|
Returns
|
|
219
402
|
-------
|
|
@@ -223,6 +406,67 @@ def generate_l2e(
|
|
|
223
406
|
# Check and prepapre input dataset
|
|
224
407
|
ds = check_l2e_input_dataset(ds)
|
|
225
408
|
|
|
409
|
+
# Select only dry and rainy timesteps
|
|
410
|
+
if "precipitation_type" in ds:
|
|
411
|
+
if keep_mixed_precipitation: # class 4
|
|
412
|
+
ds = ds.isel(time=ds["precipitation_type"].isin([-1, 0, 4]), drop=True)
|
|
413
|
+
else:
|
|
414
|
+
ds = ds.isel(time=ds["precipitation_type"].isin([-1, 0]), drop=True)
|
|
415
|
+
|
|
416
|
+
# Determine if the velocity dimension is available
|
|
417
|
+
has_velocity_dimension = VELOCITY_DIMENSION in ds.dims
|
|
418
|
+
|
|
419
|
+
# - Filter diameter bins
|
|
420
|
+
ds = filter_diameter_bins(ds=ds, minimum_diameter=minimum_diameter, maximum_diameter=maximum_diameter)
|
|
421
|
+
# - Filter velocity bins
|
|
422
|
+
if has_velocity_dimension:
|
|
423
|
+
ds = filter_velocity_bins(ds=ds, minimum_velocity=minimum_velocity, maximum_velocity=maximum_velocity)
|
|
424
|
+
|
|
425
|
+
# -------------------------------------------------------------------------------------------
|
|
426
|
+
# Compute fall velocity
|
|
427
|
+
ds["fall_velocity"] = get_rain_fall_velocity_from_ds(ds=ds, ds_env=ds_env, model=fall_velocity_model)
|
|
428
|
+
|
|
429
|
+
# -------------------------------------------------------
|
|
430
|
+
# Retrieve filtered spectrum and drop counts (summing over velocity dimension if present)
|
|
431
|
+
if has_velocity_dimension:
|
|
432
|
+
drop_number = retrieve_drop_spectrum(
|
|
433
|
+
ds=ds,
|
|
434
|
+
ds_env=ds_env,
|
|
435
|
+
above_velocity_fraction=above_velocity_fraction,
|
|
436
|
+
above_velocity_tolerance=above_velocity_tolerance,
|
|
437
|
+
below_velocity_fraction=below_velocity_fraction,
|
|
438
|
+
below_velocity_tolerance=below_velocity_tolerance,
|
|
439
|
+
maintain_drops_smaller_than=maintain_drops_smaller_than,
|
|
440
|
+
maintain_drops_slower_than=maintain_drops_slower_than,
|
|
441
|
+
maintain_smallest_drops=maintain_smallest_drops,
|
|
442
|
+
remove_splashing_drops=remove_splashing_drops,
|
|
443
|
+
fall_velocity_model=fall_velocity_model,
|
|
444
|
+
)
|
|
445
|
+
drop_counts = drop_number.sum(dim=VELOCITY_DIMENSION) # 1D (diameter)
|
|
446
|
+
drop_counts_raw = ds["raw_drop_number"].sum(dim=VELOCITY_DIMENSION) # 1D (diameter)
|
|
447
|
+
else:
|
|
448
|
+
drop_number = ds["raw_drop_number"] # no filtering applied
|
|
449
|
+
drop_counts = ds["raw_drop_number"] # 1D (diameter)
|
|
450
|
+
drop_counts_raw = ds["raw_drop_number"]
|
|
451
|
+
|
|
452
|
+
ds["drop_number"] = drop_number
|
|
453
|
+
ds["drop_counts"] = drop_counts
|
|
454
|
+
|
|
455
|
+
# -------------------------------------------------------
|
|
456
|
+
# Compute drop statistics
|
|
457
|
+
# - Compute minimum and max drop diameter observed
|
|
458
|
+
min_drop_diameter, max_drop_diameter = get_min_max_diameter(drop_counts)
|
|
459
|
+
|
|
460
|
+
# - Add rain drop statistics
|
|
461
|
+
ds["Dmin"] = min_drop_diameter
|
|
462
|
+
ds["Dmax"] = max_drop_diameter
|
|
463
|
+
ds["N"] = drop_counts.sum(dim=DIAMETER_DIMENSION)
|
|
464
|
+
ds["Nraw"] = drop_counts_raw.sum(dim=DIAMETER_DIMENSION)
|
|
465
|
+
ds["Nremoved"] = ds["Nraw"] - ds["N"]
|
|
466
|
+
|
|
467
|
+
# - Add bins statistics
|
|
468
|
+
ds = add_bins_metrics(ds)
|
|
469
|
+
|
|
226
470
|
# -------------------------------------------------------
|
|
227
471
|
# Initialize L2E dataset
|
|
228
472
|
ds_l2 = xr.Dataset()
|
|
@@ -235,9 +479,6 @@ def generate_l2e(
|
|
|
235
479
|
# Select timesteps with at least the specified number of drops
|
|
236
480
|
ds = select_timesteps_with_drops(ds, minimum_ndrops=minimum_ndrops)
|
|
237
481
|
|
|
238
|
-
# Add bins metrics to resampled data if missing
|
|
239
|
-
ds = add_bins_metrics(ds)
|
|
240
|
-
|
|
241
482
|
# Remove timesteps with not enough bins with drops
|
|
242
483
|
ds = select_timesteps_with_minimum_nbins(ds, minimum_nbins=minimum_nbins)
|
|
243
484
|
|
|
@@ -256,24 +497,41 @@ def generate_l2e(
|
|
|
256
497
|
diameter = ds["diameter_bin_center"] / 1000 # m
|
|
257
498
|
diameter_bin_width = ds["diameter_bin_width"] # mm
|
|
258
499
|
drop_number = ds["drop_number"]
|
|
259
|
-
sample_interval = ensure_sample_interval_in_seconds(ds["sample_interval"]) # s
|
|
260
500
|
|
|
261
|
-
#
|
|
501
|
+
# Retrieve effective sampling interval [s]
|
|
502
|
+
sample_interval = get_effective_sampling_interval(ds, sensor_name=sensor_name) # s
|
|
503
|
+
|
|
504
|
+
# Retrieve effective sampling area [m2]
|
|
262
505
|
sampling_area = get_effective_sampling_area(sensor_name=sensor_name, diameter=diameter) # m2
|
|
263
506
|
|
|
264
507
|
# Copy relevant L1 variables to L2 product
|
|
265
508
|
variables = [
|
|
509
|
+
# L1 inputs
|
|
510
|
+
"sample_interval",
|
|
511
|
+
"fall_velocity",
|
|
266
512
|
"raw_drop_number", # 2D V x D
|
|
267
513
|
"drop_number", # 2D V x D
|
|
514
|
+
# Drop statistics
|
|
268
515
|
"drop_counts", # 1D D
|
|
269
|
-
"sample_interval",
|
|
270
516
|
"N",
|
|
271
517
|
"Nremoved",
|
|
518
|
+
"Nraw",
|
|
272
519
|
"Dmin",
|
|
273
520
|
"Dmax",
|
|
274
|
-
|
|
521
|
+
# L0C QC
|
|
522
|
+
"qc_time",
|
|
523
|
+
# L1 flags and variables
|
|
275
524
|
"qc_resampling",
|
|
276
|
-
"
|
|
525
|
+
"precipitation_type",
|
|
526
|
+
"hydrometeor_type",
|
|
527
|
+
"n_margin_fallers",
|
|
528
|
+
"n_splashing",
|
|
529
|
+
"flag_graupel",
|
|
530
|
+
"flag_hail",
|
|
531
|
+
"flag_spikes",
|
|
532
|
+
"flag_splashing",
|
|
533
|
+
"flag_wind_artefacts",
|
|
534
|
+
*METEOROLOGICAL_VARIABLES,
|
|
277
535
|
]
|
|
278
536
|
|
|
279
537
|
variables = [var for var in variables if var in ds]
|
|
@@ -289,6 +547,7 @@ def generate_l2e(
|
|
|
289
547
|
# -------------------------------------------------------------------------------------------
|
|
290
548
|
# Define velocity array with dimension 'velocity_method'
|
|
291
549
|
velocity = define_velocity_array(ds)
|
|
550
|
+
velocity = velocity.fillna(0)
|
|
292
551
|
|
|
293
552
|
# Compute drop number concentration (Nt) [#/m3/mm]
|
|
294
553
|
drop_number_concentration = get_drop_number_concentration(
|
|
@@ -398,7 +657,7 @@ def check_l2m_input_dataset(ds):
|
|
|
398
657
|
if "drop_number_concentration" not in ds:
|
|
399
658
|
if "drop_number" in ds:
|
|
400
659
|
check_l2e_input_dataset(ds)
|
|
401
|
-
sample_interval =
|
|
660
|
+
sample_interval = get_effective_sampling_interval(ds, sensor_name=ds.attrs["sensor_name"])
|
|
402
661
|
sampling_area = get_effective_sampling_area(
|
|
403
662
|
sensor_name=ds.attrs["sensor_name"],
|
|
404
663
|
diameter=ds["diameter_bin_center"] / 1000,
|
|
@@ -503,7 +762,7 @@ def generate_l2m(
|
|
|
503
762
|
|
|
504
763
|
# Retrieve measurement interval
|
|
505
764
|
# - If dataset is opened with decode_timedelta=False, sample_interval is already in seconds !
|
|
506
|
-
sample_interval =
|
|
765
|
+
sample_interval = get_effective_sampling_interval(ds, sensor_name=ds.attrs["sensor_name"])
|
|
507
766
|
|
|
508
767
|
# Select timesteps with at least the specified number of drops
|
|
509
768
|
ds = select_timesteps_with_drops(ds, minimum_ndrops=minimum_ndrops)
|
|
@@ -549,7 +808,7 @@ def generate_l2m(
|
|
|
549
808
|
drop_number_concentration = psd(diameter)
|
|
550
809
|
|
|
551
810
|
# Retrieve fall velocity for each new diameter bin
|
|
552
|
-
velocity =
|
|
811
|
+
velocity = get_rain_fall_velocity(diameter=diameter, model=fall_velocity_model, ds_env=ds_env) # mm
|
|
553
812
|
|
|
554
813
|
# Compute integral parameters
|
|
555
814
|
ds_params = compute_integral_parameters(
|
|
@@ -576,9 +835,15 @@ def generate_l2m(
|
|
|
576
835
|
|
|
577
836
|
# Add empirical drop_number_concentration and fall velocity
|
|
578
837
|
# - To reuse output dataset to create another L2M dataset or to compute other GOF metrics
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
838
|
+
# Copy relevant L1 variables to L2 product
|
|
839
|
+
variables = [
|
|
840
|
+
"drop_number_concentration",
|
|
841
|
+
"fall_velocity",
|
|
842
|
+
"N",
|
|
843
|
+
*METEOROLOGICAL_VARIABLES,
|
|
844
|
+
]
|
|
845
|
+
variables = [var for var in variables if var in ds]
|
|
846
|
+
ds_params.update(ds[variables])
|
|
582
847
|
ds_params.update(ds[BINS_METRICS])
|
|
583
848
|
|
|
584
849
|
#### ----------------------------------------------------------------------------.
|
disdrodb/metadata/checks.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# -----------------------------------------------------------------------------.
|
|
4
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
5
3
|
#
|
|
6
4
|
# This program is free software: you can redistribute it and/or modify
|
|
7
5
|
# it under the terms of the GNU General Public License as published by
|
disdrodb/metadata/download.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
|
|
@@ -23,6 +21,8 @@ import shutil
|
|
|
23
21
|
import urllib.request
|
|
24
22
|
import zipfile
|
|
25
23
|
|
|
24
|
+
from disdrodb.utils.directories import remove_file_or_directories
|
|
25
|
+
|
|
26
26
|
|
|
27
27
|
def download_metadata_archive(directory_path, force=False):
|
|
28
28
|
"""Download the DISDRODB Metadata Archive to the specified directory.
|
|
@@ -64,7 +64,7 @@ def download_metadata_archive(directory_path, force=False):
|
|
|
64
64
|
# Handle existing target directory
|
|
65
65
|
if os.path.exists(target_dir):
|
|
66
66
|
if force:
|
|
67
|
-
|
|
67
|
+
remove_file_or_directories(target_dir)
|
|
68
68
|
else:
|
|
69
69
|
raise FileExistsError(
|
|
70
70
|
f"A DISDRODB Metadata Archive already exists at '{target_dir}'. Use force=True to update it.",
|
disdrodb/metadata/geolocation.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/metadata/info.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
1
|
# -----------------------------------------------------------------------------.
|
|
4
|
-
# Copyright (c) 2021-
|
|
2
|
+
# Copyright (c) 2021-2026 DISDRODB developers
|
|
5
3
|
#
|
|
6
4
|
# This program is free software: you can redistribute it and/or modify
|
|
7
5
|
# it under the terms of the GNU General Public License as published by
|
|
@@ -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/metadata/reader.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/metadata/search.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/metadata/standards.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/metadata/writer.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
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
"""DISDRODB physics module."""
|