disdrodb 0.0.20__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- disdrodb/__init__.py +132 -15
- disdrodb/_config.py +4 -2
- disdrodb/_version.py +9 -4
- disdrodb/api/checks.py +264 -237
- disdrodb/api/configs.py +4 -8
- disdrodb/api/create_directories.py +235 -290
- disdrodb/api/info.py +217 -26
- disdrodb/api/io.py +295 -269
- disdrodb/api/path.py +597 -173
- disdrodb/api/search.py +486 -0
- disdrodb/{metadata/scripts → cli}/disdrodb_check_metadata_archive.py +12 -7
- disdrodb/{utils/pandas.py → cli/disdrodb_data_archive_directory.py} +9 -18
- disdrodb/cli/disdrodb_download_archive.py +86 -0
- disdrodb/cli/disdrodb_download_metadata_archive.py +53 -0
- disdrodb/cli/disdrodb_download_station.py +84 -0
- disdrodb/{api/scripts → cli}/disdrodb_initialize_station.py +22 -10
- disdrodb/cli/disdrodb_metadata_archive_directory.py +32 -0
- disdrodb/{data_transfer/scripts/disdrodb_download_station.py → cli/disdrodb_open_data_archive.py} +22 -22
- disdrodb/cli/disdrodb_open_logs_directory.py +69 -0
- disdrodb/{data_transfer/scripts/disdrodb_upload_station.py → cli/disdrodb_open_metadata_archive.py} +22 -24
- disdrodb/cli/disdrodb_open_metadata_directory.py +71 -0
- disdrodb/cli/disdrodb_open_product_directory.py +74 -0
- disdrodb/cli/disdrodb_open_readers_directory.py +32 -0
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0.py +38 -31
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0_station.py +32 -30
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0a.py +30 -21
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0a_station.py +24 -33
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0b.py +30 -21
- disdrodb/{l0/scripts → cli}/disdrodb_run_l0b_station.py +25 -34
- disdrodb/cli/disdrodb_run_l0c.py +130 -0
- disdrodb/cli/disdrodb_run_l0c_station.py +129 -0
- disdrodb/cli/disdrodb_run_l1.py +122 -0
- disdrodb/cli/disdrodb_run_l1_station.py +121 -0
- disdrodb/cli/disdrodb_run_l2e.py +122 -0
- disdrodb/cli/disdrodb_run_l2e_station.py +122 -0
- disdrodb/cli/disdrodb_run_l2m.py +122 -0
- disdrodb/cli/disdrodb_run_l2m_station.py +122 -0
- disdrodb/cli/disdrodb_upload_archive.py +105 -0
- disdrodb/cli/disdrodb_upload_station.py +98 -0
- disdrodb/configs.py +90 -25
- disdrodb/data_transfer/__init__.py +22 -0
- disdrodb/data_transfer/download_data.py +87 -90
- disdrodb/data_transfer/upload_data.py +64 -37
- disdrodb/data_transfer/zenodo.py +15 -18
- disdrodb/docs.py +1 -1
- disdrodb/issue/__init__.py +17 -4
- disdrodb/issue/checks.py +10 -23
- disdrodb/issue/reader.py +9 -12
- disdrodb/issue/writer.py +14 -17
- disdrodb/l0/__init__.py +17 -26
- disdrodb/l0/check_configs.py +35 -23
- disdrodb/l0/check_standards.py +32 -42
- disdrodb/l0/configs/{Thies_LPM → LPM}/bins_diameter.yml +44 -44
- disdrodb/l0/configs/{Thies_LPM → LPM}/bins_velocity.yml +40 -40
- disdrodb/l0/configs/LPM/l0a_encodings.yml +80 -0
- disdrodb/l0/configs/{Thies_LPM → LPM}/l0b_cf_attrs.yml +62 -59
- disdrodb/l0/configs/{Thies_LPM → LPM}/l0b_encodings.yml +9 -9
- disdrodb/l0/configs/{Thies_LPM → LPM}/raw_data_format.yml +245 -245
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/bins_diameter.yml +66 -66
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/bins_velocity.yml +64 -64
- disdrodb/l0/configs/PARSIVEL/l0a_encodings.yml +32 -0
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/l0b_cf_attrs.yml +22 -20
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/l0b_encodings.yml +17 -17
- disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/raw_data_format.yml +77 -77
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/bins_diameter.yml +64 -64
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/bins_velocity.yml +64 -64
- disdrodb/l0/configs/PARSIVEL2/l0a_encodings.yml +39 -0
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/l0b_cf_attrs.yml +24 -22
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/l0b_encodings.yml +20 -20
- disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/raw_data_format.yml +98 -98
- disdrodb/l0/configs/{RD_80 → RD80}/bins_diameter.yml +40 -40
- disdrodb/l0/configs/RD80/l0a_encodings.yml +16 -0
- disdrodb/l0/configs/{RD_80 → RD80}/l0b_cf_attrs.yml +3 -3
- disdrodb/l0/configs/RD80/l0b_encodings.yml +135 -0
- disdrodb/l0/configs/{RD_80 → RD80}/raw_data_format.yml +48 -48
- disdrodb/l0/l0_reader.py +216 -340
- disdrodb/l0/l0a_processing.py +237 -208
- disdrodb/l0/l0b_nc_processing.py +227 -80
- disdrodb/l0/l0b_processing.py +93 -173
- disdrodb/l0/l0c_processing.py +627 -0
- disdrodb/l0/readers/{ARM → LPM/ARM}/ARM_LPM.py +36 -58
- disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +226 -0
- disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +185 -0
- disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +183 -0
- disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +179 -0
- disdrodb/l0/readers/{UK → LPM/UK}/DIVEN.py +14 -35
- disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +157 -0
- disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +113 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/ARCTIC_2021.py +40 -57
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/COMMON_2011.py +37 -54
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/DAVOS_2009_2011.py +34 -51
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_2009.py +34 -51
- disdrodb/l0/readers/{EPFL/PARADISO_2014.py → PARSIVEL/EPFL/EPFL_ROOF_2008.py} +38 -50
- disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +105 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2011.py +34 -51
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2012.py +33 -51
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GENEPI_2007.py +25 -44
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007.py +25 -44
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007_2.py +25 -44
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HPICONET_2010.py +34 -51
- disdrodb/l0/readers/{EPFL/EPFL_ROOF_2010.py → PARSIVEL/EPFL/HYMEX_LTE_SOP2.py} +37 -50
- disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +111 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HYMEX_LTE_SOP4.py +36 -54
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2018.py +34 -52
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2019.py +38 -56
- disdrodb/l0/readers/PARSIVEL/EPFL/PARADISO_2014.py +105 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PARSIVEL_2007.py +27 -45
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PLATO_2019.py +24 -44
- disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +140 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RACLETS_2019_WJF.py +41 -59
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RIETHOLZBACH_2011.py +34 -51
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +117 -0
- disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +137 -0
- disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/UNIL_2022.py +42 -55
- disdrodb/l0/readers/PARSIVEL/GPM/IFLOODS.py +104 -0
- disdrodb/l0/readers/{GPM → PARSIVEL/GPM}/LPVEX.py +29 -48
- disdrodb/l0/readers/PARSIVEL/GPM/MC3E.py +184 -0
- disdrodb/l0/readers/PARSIVEL/NCAR/CCOPE_2015.py +113 -0
- disdrodb/l0/readers/{NCAR/VORTEX_SE_2016_P1.py → PARSIVEL/NCAR/OWLES_MIPS.py} +46 -72
- disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +125 -0
- disdrodb/l0/readers/{NCAR/OWLES_MIPS.py → PARSIVEL/NCAR/PLOWS_MIPS.py} +45 -64
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +114 -0
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +176 -0
- disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +183 -0
- disdrodb/l0/readers/{ARM/ARM_LD.py → PARSIVEL2/ARM/ARM_PARSIVEL2.py} +27 -50
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +163 -0
- disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +163 -0
- disdrodb/l0/readers/{DENMARK → PARSIVEL2/DENMARK}/EROSION_nc.py +14 -35
- disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +119 -0
- disdrodb/l0/readers/PARSIVEL2/GPM/GCPEX.py +104 -0
- disdrodb/l0/readers/PARSIVEL2/GPM/NSSTC.py +176 -0
- disdrodb/l0/readers/PARSIVEL2/ITALY/GID_PARSIVEL2.py +32 -0
- disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +56 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +120 -0
- disdrodb/l0/readers/{NCAR → PARSIVEL2/NCAR}/PECAN_MIPS.py +45 -64
- disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +181 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +160 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +160 -0
- disdrodb/l0/readers/{NCAR/PLOWS_MIPS.py → PARSIVEL2/NCAR/VORTEX_SE_2016_P1.py} +49 -66
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +118 -0
- disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +152 -0
- disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT.py +166 -0
- disdrodb/l0/readers/{NCAR/RELAMPAGO_RD80.py → RD80/BRAZIL/CHUVA_RD80.py} +36 -60
- disdrodb/l0/readers/{BRAZIL → RD80/BRAZIL}/GOAMAZON_RD80.py +36 -55
- disdrodb/l0/readers/{NCAR → RD80/NCAR}/CINDY_2011_RD80.py +35 -54
- disdrodb/l0/readers/{BRAZIL/CHUVA_RD80.py → RD80/NCAR/RELAMPAGO_RD80.py} +40 -54
- disdrodb/l0/readers/template_reader_raw_netcdf_data.py +62 -0
- disdrodb/l0/readers/{reader_template.py → template_reader_raw_text_data.py} +20 -44
- disdrodb/l0/routines.py +885 -581
- disdrodb/l0/standards.py +72 -236
- disdrodb/l0/template_tools.py +104 -109
- disdrodb/l1/__init__.py +17 -0
- disdrodb/l1/beard_model.py +716 -0
- disdrodb/l1/encoding_attrs.py +620 -0
- disdrodb/l1/fall_velocity.py +260 -0
- disdrodb/l1/filters.py +192 -0
- disdrodb/l1/processing.py +200 -0
- disdrodb/l1/resampling.py +236 -0
- disdrodb/l1/routines.py +357 -0
- disdrodb/l1_env/__init__.py +17 -0
- disdrodb/l1_env/routines.py +38 -0
- disdrodb/l2/__init__.py +17 -0
- disdrodb/l2/empirical_dsd.py +1735 -0
- disdrodb/l2/event.py +388 -0
- disdrodb/l2/processing.py +519 -0
- disdrodb/l2/processing_options.py +213 -0
- disdrodb/l2/routines.py +868 -0
- disdrodb/metadata/__init__.py +9 -2
- disdrodb/metadata/checks.py +165 -118
- disdrodb/metadata/download.py +81 -0
- disdrodb/metadata/geolocation.py +146 -0
- disdrodb/metadata/info.py +20 -13
- disdrodb/metadata/manipulation.py +1 -1
- disdrodb/metadata/reader.py +59 -8
- disdrodb/metadata/search.py +77 -144
- disdrodb/metadata/standards.py +7 -8
- disdrodb/metadata/writer.py +8 -14
- disdrodb/psd/__init__.py +38 -0
- disdrodb/psd/fitting.py +2146 -0
- disdrodb/psd/models.py +774 -0
- disdrodb/routines.py +1176 -0
- disdrodb/scattering/__init__.py +28 -0
- disdrodb/scattering/axis_ratio.py +344 -0
- disdrodb/scattering/routines.py +456 -0
- disdrodb/utils/__init__.py +17 -0
- disdrodb/utils/attrs.py +208 -0
- disdrodb/utils/cli.py +269 -0
- disdrodb/utils/compression.py +60 -42
- disdrodb/utils/dask.py +62 -0
- disdrodb/utils/decorators.py +110 -0
- disdrodb/utils/directories.py +107 -46
- disdrodb/utils/encoding.py +127 -0
- disdrodb/utils/list.py +29 -0
- disdrodb/utils/logger.py +168 -46
- disdrodb/utils/time.py +657 -0
- disdrodb/utils/warnings.py +30 -0
- disdrodb/utils/writer.py +57 -0
- disdrodb/utils/xarray.py +138 -47
- disdrodb/utils/yaml.py +0 -1
- disdrodb/viz/__init__.py +17 -0
- disdrodb/viz/plots.py +17 -0
- disdrodb-0.1.0.dist-info/METADATA +321 -0
- disdrodb-0.1.0.dist-info/RECORD +216 -0
- {disdrodb-0.0.20.dist-info → disdrodb-0.1.0.dist-info}/WHEEL +1 -1
- disdrodb-0.1.0.dist-info/entry_points.txt +30 -0
- disdrodb/data_transfer/scripts/disdrodb_download_archive.py +0 -53
- disdrodb/data_transfer/scripts/disdrodb_upload_archive.py +0 -57
- disdrodb/l0/configs/OTT_Parsivel/l0a_encodings.yml +0 -32
- disdrodb/l0/configs/OTT_Parsivel2/l0a_encodings.yml +0 -39
- disdrodb/l0/configs/RD_80/l0a_encodings.yml +0 -16
- disdrodb/l0/configs/RD_80/l0b_encodings.yml +0 -135
- disdrodb/l0/configs/Thies_LPM/l0a_encodings.yml +0 -80
- disdrodb/l0/io.py +0 -257
- disdrodb/l0/l0_processing.py +0 -1091
- disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_OTT.py +0 -178
- disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_THIES.py +0 -247
- disdrodb/l0/readers/BRAZIL/CHUVA_LPM.py +0 -204
- disdrodb/l0/readers/BRAZIL/CHUVA_OTT.py +0 -183
- disdrodb/l0/readers/BRAZIL/GOAMAZON_LPM.py +0 -204
- disdrodb/l0/readers/BRAZIL/GOAMAZON_OTT.py +0 -183
- disdrodb/l0/readers/CHINA/CHONGQING.py +0 -131
- disdrodb/l0/readers/EPFL/EPFL_ROOF_2008.py +0 -128
- disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP2.py +0 -127
- disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP3.py +0 -129
- disdrodb/l0/readers/EPFL/RACLETS_2019.py +0 -158
- disdrodb/l0/readers/EPFL/SAMOYLOV_2017.py +0 -136
- disdrodb/l0/readers/EPFL/SAMOYLOV_2019.py +0 -158
- disdrodb/l0/readers/FRANCE/SIRTA_OTT2.py +0 -138
- disdrodb/l0/readers/GPM/GCPEX.py +0 -123
- disdrodb/l0/readers/GPM/IFLOODS.py +0 -123
- disdrodb/l0/readers/GPM/MC3E.py +0 -123
- disdrodb/l0/readers/GPM/NSSTC.py +0 -164
- disdrodb/l0/readers/ITALY/GID.py +0 -199
- disdrodb/l0/readers/MEXICO/OH_IIUNAM_nc.py +0 -92
- disdrodb/l0/readers/NCAR/CCOPE_2015.py +0 -133
- disdrodb/l0/readers/NCAR/PECAN_FP3.py +0 -137
- disdrodb/l0/readers/NCAR/PECAN_MOBILE.py +0 -144
- disdrodb/l0/readers/NCAR/RELAMPAGO_OTT.py +0 -195
- disdrodb/l0/readers/NCAR/SNOWIE_PJ.py +0 -172
- disdrodb/l0/readers/NCAR/SNOWIE_SB.py +0 -179
- disdrodb/l0/readers/NCAR/VORTEX2_2009.py +0 -133
- disdrodb/l0/readers/NCAR/VORTEX2_2010.py +0 -188
- disdrodb/l0/readers/NCAR/VORTEX2_2010_UF.py +0 -191
- disdrodb/l0/readers/NCAR/VORTEX_SE_2016_P2.py +0 -135
- disdrodb/l0/readers/NCAR/VORTEX_SE_2016_PIPS.py +0 -170
- disdrodb/l0/readers/NETHERLANDS/DELFT.py +0 -187
- disdrodb/l0/readers/SPAIN/SBEGUERIA.py +0 -179
- disdrodb/l0/scripts/disdrodb_run_l0b_concat.py +0 -93
- disdrodb/l0/scripts/disdrodb_run_l0b_concat_station.py +0 -85
- disdrodb/utils/netcdf.py +0 -452
- disdrodb/utils/scripts.py +0 -102
- disdrodb-0.0.20.dist-info/AUTHORS.md +0 -18
- disdrodb-0.0.20.dist-info/METADATA +0 -186
- disdrodb-0.0.20.dist-info/RECORD +0 -168
- disdrodb-0.0.20.dist-info/entry_points.txt +0 -15
- /disdrodb/l0/configs/{RD_80 → RD80}/bins_velocity.yml +0 -0
- /disdrodb/l0/manuals/{Thies_LPM.pdf → LPM.pdf} +0 -0
- /disdrodb/l0/manuals/{ODM_470.pdf → ODM470.pdf} +0 -0
- /disdrodb/l0/manuals/{OTT_Parsivel.pdf → PARSIVEL.pdf} +0 -0
- /disdrodb/l0/manuals/{OTT_Parsivel2.pdf → PARSIVEL2.pdf} +0 -0
- /disdrodb/l0/manuals/{PWS_100.pdf → PWS100.pdf} +0 -0
- /disdrodb/l0/manuals/{RD_80.pdf → RD80.pdf} +0 -0
- {disdrodb-0.0.20.dist-info → disdrodb-0.1.0.dist-info/licenses}/LICENSE +0 -0
- {disdrodb-0.0.20.dist-info → disdrodb-0.1.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------.
|
|
2
|
+
# Copyright (c) 2021-2023 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
|
+
"""Theoretical models to estimate the drop fall velocity."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_fall_velocity_atlas_1973(diameter):
|
|
24
|
+
"""
|
|
25
|
+
Compute the fall velocity of raindrops using the Atlas et al. (1973) relationship.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
diameter : array-like
|
|
30
|
+
Diameter of the raindrops in millimeters.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
fall_velocity : array-like
|
|
35
|
+
Fall velocities corresponding to the input diameters, in meters per second.
|
|
36
|
+
|
|
37
|
+
References
|
|
38
|
+
----------
|
|
39
|
+
Atlas, D., Srivastava, R. C., & Sekhon, R. S. (1973).
|
|
40
|
+
Doppler radar characteristics of precipitation at vertical incidence.
|
|
41
|
+
Reviews of Geophysics, 11(1), 1-35.
|
|
42
|
+
https://doi.org/10.1029/RG011i001p00001
|
|
43
|
+
|
|
44
|
+
Atlas, D., & Ulbrich, C. W. (1977).
|
|
45
|
+
Path- and area-integrated rainfall measurement by microwave attenuation in the 1-3 cm band.
|
|
46
|
+
Journal of Applied Meteorology, 16(12), 1322-1331.
|
|
47
|
+
https://doi.org/10.1175/1520-0450(1977)016<1322:PAAIRM>2.0.CO;2
|
|
48
|
+
|
|
49
|
+
Gunn, R., & Kinzer, G. D. (1949).
|
|
50
|
+
The terminal velocity of fall for water droplets in stagnant air.
|
|
51
|
+
Journal of Meteorology, 6(4), 243-248.
|
|
52
|
+
https://doi.org/10.1175/1520-0469(1949)006<0243:TTVOFF>2.0.CO;2
|
|
53
|
+
|
|
54
|
+
"""
|
|
55
|
+
fall_velocity = 9.65 - 10.3 * np.exp(-0.6 * diameter) # clip to 0 !
|
|
56
|
+
fall_velocity = np.clip(fall_velocity, 0, None)
|
|
57
|
+
return fall_velocity
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_fall_velocity_brandes_2002(diameter):
|
|
61
|
+
"""
|
|
62
|
+
Compute the fall velocity of raindrops using the Brandes et al. (2002) relationship.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
diameter : array-like
|
|
67
|
+
Diameter of the raindrops in millimeters.
|
|
68
|
+
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
fall_velocity : array-like
|
|
72
|
+
Fall velocities in meters per second.
|
|
73
|
+
|
|
74
|
+
References
|
|
75
|
+
----------
|
|
76
|
+
Brandes, E. A., Zhang, G., & Vivekanandan, J. (2002).
|
|
77
|
+
Experiments in rainfall estimation with a polarimetric radar in a subtropical environment.
|
|
78
|
+
Journal of Applied Meteorology, 41(6), 674-685.
|
|
79
|
+
https://doi.org/10.1175/1520-0450(2002)041<0674:EIREWA>2.0.CO;2
|
|
80
|
+
|
|
81
|
+
"""
|
|
82
|
+
fall_velocity = -0.1021 + 4.932 * diameter - 0.9551 * diameter**2 + 0.07934 * diameter**3 - 0.002362 * diameter**4
|
|
83
|
+
return fall_velocity
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def get_fall_velocity_uplinger_1981(diameter):
|
|
87
|
+
"""
|
|
88
|
+
Compute the fall velocity of raindrops using Uplinger (1981) relationship.
|
|
89
|
+
|
|
90
|
+
Parameters
|
|
91
|
+
----------
|
|
92
|
+
diameter : array-like
|
|
93
|
+
Diameter of the raindrops in millimeters.
|
|
94
|
+
Valid for diameters between 0.1 mm and 7 mm.
|
|
95
|
+
|
|
96
|
+
Returns
|
|
97
|
+
-------
|
|
98
|
+
fall_velocity : array-like
|
|
99
|
+
Fall velocities in meters per second.
|
|
100
|
+
|
|
101
|
+
References
|
|
102
|
+
----------
|
|
103
|
+
Uplinger, C. W. (1981). A new formula for raindrop terminal velocity.
|
|
104
|
+
In Proceedings of the 20th Conference on Radar Meteorology (pp. 389-391).
|
|
105
|
+
AMS.
|
|
106
|
+
|
|
107
|
+
"""
|
|
108
|
+
# Valid between 0.1 and 7 mm
|
|
109
|
+
fall_velocity = 4.874 * diameter * np.exp(-0.195 * diameter)
|
|
110
|
+
return fall_velocity
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def get_fall_velocity_van_dijk_2002(diameter):
|
|
114
|
+
"""
|
|
115
|
+
Compute the fall velocity of raindrops using van Dijk et al. (2002) relationship.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
diameter : array-like
|
|
120
|
+
Diameter of the raindrops in millimeters.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
fall_velocity : array-like
|
|
125
|
+
Fall velocities in meters per second.
|
|
126
|
+
|
|
127
|
+
References
|
|
128
|
+
----------
|
|
129
|
+
van Dijk, A. I. J. M., Bruijnzeel, L. A., & Rosewell, C. J. (2002).
|
|
130
|
+
Rainfall intensity-kinetic energy relationships: a critical literature appraisal.
|
|
131
|
+
Journal of Hydrology, 261(1-4), 1-23.
|
|
132
|
+
https://doi.org/10.1016/S0022-1694(02)00020-3
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
fall_velocity = -0.254 + 5.03 * diameter - 0.912 * diameter**2 + 0.0561 * diameter**3
|
|
136
|
+
return fall_velocity
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def get_fall_velocity_beard_1976(diameter, ds_env):
|
|
140
|
+
"""Calculate the fall velocity of a particle using the Beard (1976) model.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
diameter : array-like
|
|
145
|
+
Diameter of the raindrops in millimeters.
|
|
146
|
+
ds_env : xr.Dataset
|
|
147
|
+
A dataset containing the following environmental variables:
|
|
148
|
+
- 'altitude' : Altitude in meters (m).
|
|
149
|
+
- 'latitude' : Latitude in degrees.
|
|
150
|
+
- 'temperature' : Temperature in degrees Celsius (°C).
|
|
151
|
+
- 'relative_humidity' : Relative humidity in percentage (%).
|
|
152
|
+
- 'sea_level_air_pressure' : Sea level air pressure in Pascals (Pa).
|
|
153
|
+
- 'lapse_rate' : Lapse rate in degrees Celsius per meter (°C/m).
|
|
154
|
+
|
|
155
|
+
Returns
|
|
156
|
+
-------
|
|
157
|
+
fall_velocity : array-like
|
|
158
|
+
The calculated fall velocities of the raindrops.
|
|
159
|
+
"""
|
|
160
|
+
from disdrodb.l1.beard_model import retrieve_fall_velocity
|
|
161
|
+
|
|
162
|
+
# Input diameter in mmm
|
|
163
|
+
fall_velocity = retrieve_fall_velocity(
|
|
164
|
+
diameter=diameter / 1000, # diameter expected in m !!!
|
|
165
|
+
altitude=ds_env["altitude"],
|
|
166
|
+
latitude=ds_env["latitude"],
|
|
167
|
+
temperature=ds_env["temperature"],
|
|
168
|
+
relative_humidity=ds_env["relative_humidity"],
|
|
169
|
+
# TODO: add air_pressure # TODO
|
|
170
|
+
sea_level_air_pressure=ds_env["sea_level_air_pressure"],
|
|
171
|
+
lapse_rate=ds_env["lapse_rate"],
|
|
172
|
+
)
|
|
173
|
+
return fall_velocity
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def ensure_valid_coordinates(ds, default_altitude=0, default_latitude=0, default_longitude=0):
|
|
177
|
+
"""Ensure dataset valid coordinates for altitude, latitude, and longitude.
|
|
178
|
+
|
|
179
|
+
Invalid values are np.nan and -9999.
|
|
180
|
+
|
|
181
|
+
Parameters
|
|
182
|
+
----------
|
|
183
|
+
ds : xarray.Dataset
|
|
184
|
+
The dataset for which to ensure valid geolocation coordinates.
|
|
185
|
+
default_altitude : float, optional
|
|
186
|
+
The default value to use for invalid altitude values. Defaults to 0.
|
|
187
|
+
default_latitude : float, optional
|
|
188
|
+
The default value to use for invalid latitude values. Defaults to 0.
|
|
189
|
+
default_longitude : float, optional
|
|
190
|
+
The default value to use for invalid longitude values. Defaults to 0.
|
|
191
|
+
|
|
192
|
+
Returns
|
|
193
|
+
-------
|
|
194
|
+
xarray.Dataset
|
|
195
|
+
The dataset with invalid coordinates replaced by default values.
|
|
196
|
+
|
|
197
|
+
"""
|
|
198
|
+
invalid_altitude = np.logical_or(np.isnan(ds["altitude"]), ds["altitude"] == -9999)
|
|
199
|
+
ds["altitude"] = ds["altitude"].where(~invalid_altitude, default_altitude)
|
|
200
|
+
|
|
201
|
+
invalid_lat = np.logical_or(np.isnan(ds["latitude"]), ds["latitude"] == -9999)
|
|
202
|
+
ds["latitude"] = ds["latitude"].where(~invalid_lat, default_latitude)
|
|
203
|
+
|
|
204
|
+
invalid_lon = np.logical_or(np.isnan(ds["longitude"]), ds["longitude"] == -9999)
|
|
205
|
+
ds["longitude"] = ds["longitude"].where(~invalid_lon, default_longitude)
|
|
206
|
+
return ds
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def get_raindrop_fall_velocity(diameter, method, ds_env=None):
|
|
210
|
+
"""Calculate the fall velocity of raindrops based on their diameter.
|
|
211
|
+
|
|
212
|
+
Parameters
|
|
213
|
+
----------
|
|
214
|
+
diameter : array-like
|
|
215
|
+
The diameter of the raindrops in millimeters.
|
|
216
|
+
method : str
|
|
217
|
+
The method to use for calculating the fall velocity. Must be one of the following:
|
|
218
|
+
'Atlas1973', 'Beard1976', 'Brandes2002', 'Uplinger1981', 'VanDijk2002'.
|
|
219
|
+
ds_env : xr.Dataset, optional
|
|
220
|
+
A dataset containing the following environmental variables:
|
|
221
|
+
- 'altitude' : Altitude in meters (m).
|
|
222
|
+
- 'latitude' : Latitude in degrees.
|
|
223
|
+
- 'temperature' : Temperature in degrees Celsius (°C).
|
|
224
|
+
- 'relative_humidity' : Relative humidity. A value between 0 and 1.
|
|
225
|
+
- 'sea_level_air_pressure' : Sea level air pressure in Pascals (Pa).
|
|
226
|
+
- 'lapse_rate' : Lapse rate in degrees Celsius per meter (°C/m).
|
|
227
|
+
It is required for for the 'Beard1976' method.
|
|
228
|
+
|
|
229
|
+
Returns
|
|
230
|
+
-------
|
|
231
|
+
fall_velocity : array-like
|
|
232
|
+
The calculated fall velocities of the raindrops.
|
|
233
|
+
|
|
234
|
+
Notes
|
|
235
|
+
-----
|
|
236
|
+
The 'Beard1976' method requires additional environmental parameters such as altitude and latitude.
|
|
237
|
+
These parameters can be provided through the `ds_env` argument. If not provided, default values will be used.
|
|
238
|
+
"""
|
|
239
|
+
# Input diameter in mm
|
|
240
|
+
dict_methods = {
|
|
241
|
+
"Atlas1973": get_fall_velocity_atlas_1973,
|
|
242
|
+
"Beard1976": get_fall_velocity_beard_1976,
|
|
243
|
+
"Brandes2002": get_fall_velocity_brandes_2002,
|
|
244
|
+
"Uplinger1981": get_fall_velocity_uplinger_1981,
|
|
245
|
+
"VanDijk2002": get_fall_velocity_van_dijk_2002,
|
|
246
|
+
}
|
|
247
|
+
# Check valid method
|
|
248
|
+
available_methods = list(dict_methods)
|
|
249
|
+
if method not in dict_methods:
|
|
250
|
+
raise ValueError(f"{method} is an invalid fall velocity method. Valid methods: {available_methods}.")
|
|
251
|
+
# Copy diameter
|
|
252
|
+
diameter = diameter.copy()
|
|
253
|
+
# Ensure valid altitude and geolocation (if missing set defaults)
|
|
254
|
+
# - altitude required by Beard
|
|
255
|
+
# - latitude required for gravity
|
|
256
|
+
ds_env = ensure_valid_coordinates(ds_env)
|
|
257
|
+
# Retrieve fall velocity
|
|
258
|
+
func = dict_methods[method]
|
|
259
|
+
fall_velocity = func(diameter, ds_env=ds_env) if method == "Beard1976" else func(diameter)
|
|
260
|
+
return fall_velocity
|
disdrodb/l1/filters.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------.
|
|
2
|
+
# Copyright (c) 2021-2023 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
|
+
"""Utilities for filtering the disdrometer raw drop spectra."""
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
import xarray as xr
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def filter_diameter_bins(ds, minimum_diameter=None, maximum_diameter=None):
|
|
24
|
+
"""
|
|
25
|
+
Filter the dataset to include only diameter bins within specified bounds.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
ds : xarray.Dataset
|
|
30
|
+
The dataset containing diameter bin data.
|
|
31
|
+
minimum_diameter : float, optional
|
|
32
|
+
The minimum diameter to include in the filter, in millimeters.
|
|
33
|
+
Defaults to the minimum value in `ds["diameter_bin_lower"]`.
|
|
34
|
+
maximum_diameter : float, optional
|
|
35
|
+
The maximum diameter to include in the filter, in millimeters.
|
|
36
|
+
Defaults to the maximum value in `ds["diameter_bin_upper"]`.
|
|
37
|
+
|
|
38
|
+
Returns
|
|
39
|
+
-------
|
|
40
|
+
xarray.Dataset
|
|
41
|
+
The filtered dataset containing only the specified diameter bins.
|
|
42
|
+
"""
|
|
43
|
+
# Initialize default arguments
|
|
44
|
+
if minimum_diameter is None:
|
|
45
|
+
minimum_diameter = ds["diameter_bin_lower"].min().item()
|
|
46
|
+
if maximum_diameter is None:
|
|
47
|
+
maximum_diameter = ds["diameter_bin_upper"].max().item()
|
|
48
|
+
# Select valid bins
|
|
49
|
+
valid_indices = np.logical_and(
|
|
50
|
+
ds["diameter_bin_lower"] >= minimum_diameter,
|
|
51
|
+
ds["diameter_bin_upper"] <= maximum_diameter,
|
|
52
|
+
)
|
|
53
|
+
ds = ds.isel({"diameter_bin_center": valid_indices})
|
|
54
|
+
# Update history
|
|
55
|
+
history = ds.attrs.get("history", "")
|
|
56
|
+
ds.attrs["history"] = (
|
|
57
|
+
history + f" Selected drops with diameters between {minimum_diameter} and {maximum_diameter} mm \n"
|
|
58
|
+
)
|
|
59
|
+
return ds
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def filter_velocity_bins(ds, minimum_velocity=0, maximum_velocity=12):
|
|
63
|
+
"""
|
|
64
|
+
Filter the dataset to include only velocity bins within specified bounds.
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
ds : xarray.Dataset
|
|
69
|
+
The dataset containing velocity bin data.
|
|
70
|
+
minimum_velocity : float, optional
|
|
71
|
+
The minimum velocity to include in the filter, in meters per second.
|
|
72
|
+
Defaults to 0 m/s.
|
|
73
|
+
maximum_velocity : float, optional
|
|
74
|
+
The maximum velocity to include in the filter, in meters per second.
|
|
75
|
+
Defaults to 12 m/s.
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
xarray.Dataset
|
|
80
|
+
The filtered dataset containing only the specified velocity bins.
|
|
81
|
+
"""
|
|
82
|
+
# Initialize default arguments
|
|
83
|
+
if minimum_velocity is None:
|
|
84
|
+
minimum_velocity = ds["velocity_bin_lower"].min().item()
|
|
85
|
+
if maximum_velocity is None:
|
|
86
|
+
maximum_velocity = ds["velocity_bin_upper"].max().item()
|
|
87
|
+
# Select valid bins
|
|
88
|
+
valid_indices = np.logical_and(
|
|
89
|
+
ds["velocity_bin_lower"] >= minimum_velocity,
|
|
90
|
+
ds["velocity_bin_upper"] <= maximum_velocity,
|
|
91
|
+
)
|
|
92
|
+
ds = ds.isel({"velocity_bin_center": valid_indices})
|
|
93
|
+
# Update history
|
|
94
|
+
history = ds.attrs.get("history", "")
|
|
95
|
+
ds.attrs["history"] = (
|
|
96
|
+
history + f" Selected drops with fall velocity between {minimum_velocity} and {maximum_velocity} m/s \n"
|
|
97
|
+
)
|
|
98
|
+
return ds
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def define_spectrum_mask(
|
|
102
|
+
drop_number,
|
|
103
|
+
fall_velocity,
|
|
104
|
+
above_velocity_fraction=None,
|
|
105
|
+
above_velocity_tolerance=None,
|
|
106
|
+
below_velocity_fraction=None,
|
|
107
|
+
below_velocity_tolerance=None,
|
|
108
|
+
small_diameter_threshold=1, # 1, # 2
|
|
109
|
+
small_velocity_threshold=2.5, # 2.5, # 3
|
|
110
|
+
maintain_smallest_drops=False,
|
|
111
|
+
):
|
|
112
|
+
"""Define a mask for the drop spectrum based on fall velocity thresholds.
|
|
113
|
+
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
drop_number : xarray.DataArray
|
|
117
|
+
Array of drop counts per diameter and velocity bins.
|
|
118
|
+
fall_velocity : array-like
|
|
119
|
+
The expected terminal fall velocities for drops of given sizes.
|
|
120
|
+
above_velocity_fraction : float, optional
|
|
121
|
+
Fraction of terminal fall velocity above which drops are considered too fast.
|
|
122
|
+
Either specify ``above_velocity_fraction`` or ``above_velocity_tolerance``.
|
|
123
|
+
above_velocity_tolerance : float, optional
|
|
124
|
+
Absolute tolerance above which drops terminal fall velocities are considered too fast.
|
|
125
|
+
Either specify ``above_velocity_fraction`` or ``above_velocity_tolerance``.
|
|
126
|
+
below_velocity_fraction : float, optional
|
|
127
|
+
Fraction of terminal fall velocity below which drops are considered too slow.
|
|
128
|
+
Either specify ``below_velocity_fraction`` or ``below_velocity_tolerance``.
|
|
129
|
+
below_velocity_tolerance : float, optional
|
|
130
|
+
Absolute tolerance below which drops terminal fall velocities are considered too slow.
|
|
131
|
+
Either specify ``below_velocity_fraction`` or ``below_velocity_tolerance``.
|
|
132
|
+
maintain_smallest : bool, optional
|
|
133
|
+
If True, ensures that the small drops in the spectrum are retained in the mask.
|
|
134
|
+
The smallest drops are characterized by ``small_diameter_threshold``
|
|
135
|
+
and ``small_velocity_threshold`` arguments.
|
|
136
|
+
Defaults to False.
|
|
137
|
+
small_diameter_threshold : float, optional
|
|
138
|
+
The diameter threshold to use for keeping the smallest drop.
|
|
139
|
+
Defaults to 1 mm.
|
|
140
|
+
small_velocity_threshold : float, optional
|
|
141
|
+
The fall velocity threshold to use for keeping the smallest drops.
|
|
142
|
+
Defaults to 2.5 m/s.
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
xarray.DataArray
|
|
147
|
+
A boolean mask array indicating valid bins according to the specified criteria.
|
|
148
|
+
|
|
149
|
+
"""
|
|
150
|
+
# Ensure it creates a 2D mask if the fall_velocity does not vary over time
|
|
151
|
+
if "time" in drop_number.dims and "time" not in fall_velocity.dims:
|
|
152
|
+
drop_number = drop_number.isel(time=0)
|
|
153
|
+
|
|
154
|
+
# Check arguments
|
|
155
|
+
if above_velocity_fraction is not None and above_velocity_tolerance is not None:
|
|
156
|
+
raise ValueError("Either specify 'above_velocity_fraction' or 'above_velocity_tolerance'.")
|
|
157
|
+
if below_velocity_fraction is not None and below_velocity_tolerance is not None:
|
|
158
|
+
raise ValueError("Either specify 'below_velocity_fraction' or 'below_velocity_tolerance'.")
|
|
159
|
+
|
|
160
|
+
# Define above/below velocity thresholds
|
|
161
|
+
if above_velocity_fraction is not None:
|
|
162
|
+
above_fall_velocity = fall_velocity * (1 + above_velocity_fraction)
|
|
163
|
+
elif above_velocity_tolerance is not None:
|
|
164
|
+
above_fall_velocity = fall_velocity + above_velocity_tolerance
|
|
165
|
+
else:
|
|
166
|
+
above_fall_velocity = np.inf
|
|
167
|
+
if below_velocity_fraction is not None:
|
|
168
|
+
below_fall_velocity = fall_velocity * (1 - below_velocity_fraction)
|
|
169
|
+
elif below_velocity_tolerance is not None:
|
|
170
|
+
below_fall_velocity = fall_velocity - below_velocity_tolerance
|
|
171
|
+
else:
|
|
172
|
+
below_fall_velocity = 0
|
|
173
|
+
|
|
174
|
+
# Define velocity 2D array
|
|
175
|
+
velocity_lower = xr.ones_like(drop_number) * drop_number["velocity_bin_lower"]
|
|
176
|
+
velocity_upper = xr.ones_like(drop_number) * drop_number["velocity_bin_upper"]
|
|
177
|
+
|
|
178
|
+
# Define mask
|
|
179
|
+
mask = np.logical_and(
|
|
180
|
+
np.logical_or(velocity_lower >= below_fall_velocity, velocity_upper >= below_fall_velocity),
|
|
181
|
+
np.logical_or(velocity_lower <= above_fall_velocity, velocity_upper <= above_fall_velocity),
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Maintant smallest drops
|
|
185
|
+
if maintain_smallest_drops:
|
|
186
|
+
mask_smallest = np.logical_and(
|
|
187
|
+
drop_number["diameter_bin_upper"] < small_diameter_threshold,
|
|
188
|
+
drop_number["velocity_bin_upper"] < small_velocity_threshold,
|
|
189
|
+
)
|
|
190
|
+
mask = np.logical_or(mask, mask_smallest)
|
|
191
|
+
|
|
192
|
+
return mask
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------.
|
|
2
|
+
# Copyright (c) 2021-2023 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
|
+
"""Core functions for DISDRODB L1 production."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
import xarray as xr
|
|
21
|
+
|
|
22
|
+
from disdrodb import DIAMETER_DIMENSION, VELOCITY_DIMENSION
|
|
23
|
+
from disdrodb.l1.encoding_attrs import get_attrs_dict, get_encoding_dict
|
|
24
|
+
from disdrodb.l1.fall_velocity import get_raindrop_fall_velocity
|
|
25
|
+
from disdrodb.l1.filters import define_spectrum_mask, filter_diameter_bins, filter_velocity_bins
|
|
26
|
+
from disdrodb.l1.resampling import add_sample_interval
|
|
27
|
+
from disdrodb.l1_env.routines import load_env_dataset
|
|
28
|
+
from disdrodb.l2.empirical_dsd import ( # TODO: maybe move out of L2
|
|
29
|
+
count_bins_with_drops,
|
|
30
|
+
get_min_max_diameter,
|
|
31
|
+
)
|
|
32
|
+
from disdrodb.utils.attrs import set_attrs
|
|
33
|
+
from disdrodb.utils.encoding import set_encodings
|
|
34
|
+
from disdrodb.utils.time import ensure_sample_interval_in_seconds, infer_sample_interval
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def generate_l1(
|
|
38
|
+
ds,
|
|
39
|
+
# Fall velocity option
|
|
40
|
+
fall_velocity_method="Beard1976",
|
|
41
|
+
# Diameter-Velocity Filtering Options
|
|
42
|
+
minimum_diameter=0,
|
|
43
|
+
maximum_diameter=10,
|
|
44
|
+
minimum_velocity=0,
|
|
45
|
+
maximum_velocity=12,
|
|
46
|
+
above_velocity_fraction=0.5,
|
|
47
|
+
above_velocity_tolerance=None,
|
|
48
|
+
below_velocity_fraction=0.5,
|
|
49
|
+
below_velocity_tolerance=None,
|
|
50
|
+
small_diameter_threshold=1, # 2
|
|
51
|
+
small_velocity_threshold=2.5, # 3
|
|
52
|
+
maintain_smallest_drops=True,
|
|
53
|
+
):
|
|
54
|
+
"""Generate the DISDRODB L1 dataset from the DISDRODB L0C dataset.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
ds : xarray.Dataset
|
|
59
|
+
DISDRODB L0C dataset.
|
|
60
|
+
fall_velocity_method : str, optional
|
|
61
|
+
Method to compute fall velocity.
|
|
62
|
+
The default method is ``"Beard1976"``.
|
|
63
|
+
minimum_diameter : float, optional
|
|
64
|
+
Minimum diameter for filtering. The default value is 0 mm.
|
|
65
|
+
maximum_diameter : float, optional
|
|
66
|
+
Maximum diameter for filtering. The default value is 10 mm.
|
|
67
|
+
minimum_velocity : float, optional
|
|
68
|
+
Minimum velocity for filtering. The default value is 0 m/s.
|
|
69
|
+
maximum_velocity : float, optional
|
|
70
|
+
Maximum velocity for filtering. The default value is 12 m/s.
|
|
71
|
+
above_velocity_fraction : float, optional
|
|
72
|
+
Fraction of drops above velocity threshold. The default value is 0.5.
|
|
73
|
+
above_velocity_tolerance : float or None, optional
|
|
74
|
+
Tolerance for above velocity filtering. The default value is ``None``.
|
|
75
|
+
below_velocity_fraction : float, optional
|
|
76
|
+
Fraction of drops below velocity threshold. The default value is 0.5.
|
|
77
|
+
below_velocity_tolerance : float or None, optional
|
|
78
|
+
Tolerance for below velocity filtering. The default value is ``None``.
|
|
79
|
+
small_diameter_threshold : float, optional
|
|
80
|
+
Threshold for small diameter drops. The default value is 1.
|
|
81
|
+
small_velocity_threshold : float, optional
|
|
82
|
+
Threshold for small velocity drops. The default value is 2.5.
|
|
83
|
+
maintain_smallest_drops : bool, optional
|
|
84
|
+
Whether to maintain the smallest drops. The default value is ``True``.
|
|
85
|
+
|
|
86
|
+
Returns
|
|
87
|
+
-------
|
|
88
|
+
xarray.Dataset
|
|
89
|
+
DISRODB L1 dataset.
|
|
90
|
+
"""
|
|
91
|
+
# Take as input an L0 !
|
|
92
|
+
|
|
93
|
+
# Retrieve source attributes
|
|
94
|
+
attrs = ds.attrs.copy()
|
|
95
|
+
|
|
96
|
+
# Determine if the velocity dimension is available
|
|
97
|
+
has_velocity_dimension = VELOCITY_DIMENSION in ds.dims
|
|
98
|
+
|
|
99
|
+
# Initialize L2 dataset
|
|
100
|
+
ds_l1 = xr.Dataset()
|
|
101
|
+
|
|
102
|
+
# Retrieve sample interval
|
|
103
|
+
# --> sample_interval is a coordinate of L0C products
|
|
104
|
+
if "sample_interval" in ds:
|
|
105
|
+
sample_interval = ensure_sample_interval_in_seconds(ds["sample_interval"].data)
|
|
106
|
+
else:
|
|
107
|
+
# This line is not called in the DISDRODB processing chain !
|
|
108
|
+
sample_interval = infer_sample_interval(ds, verbose=False)
|
|
109
|
+
|
|
110
|
+
# Re-add sample interval as coordinate (in seconds)
|
|
111
|
+
ds = add_sample_interval(ds, sample_interval=sample_interval)
|
|
112
|
+
|
|
113
|
+
# ---------------------------------------------------------------------------
|
|
114
|
+
# Retrieve ENV dataset or take defaults
|
|
115
|
+
# --> Used only for Beard fall velocity currently !
|
|
116
|
+
ds_env = load_env_dataset(ds)
|
|
117
|
+
|
|
118
|
+
# -------------------------------------------------------------------------------------------
|
|
119
|
+
# Filter dataset by diameter and velocity bins
|
|
120
|
+
# - Filter diameter bins
|
|
121
|
+
ds = filter_diameter_bins(ds=ds, minimum_diameter=minimum_diameter, maximum_diameter=maximum_diameter)
|
|
122
|
+
# - Filter velocity bins
|
|
123
|
+
if has_velocity_dimension:
|
|
124
|
+
ds = filter_velocity_bins(ds=ds, minimum_velocity=minimum_velocity, maximum_velocity=maximum_velocity)
|
|
125
|
+
|
|
126
|
+
# -------------------------------------------------------------------------------------------
|
|
127
|
+
# Compute fall velocity
|
|
128
|
+
fall_velocity = get_raindrop_fall_velocity(
|
|
129
|
+
diameter=ds["diameter_bin_center"],
|
|
130
|
+
method=fall_velocity_method,
|
|
131
|
+
ds_env=ds_env, # mm
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Add fall velocity
|
|
135
|
+
ds_l1["fall_velocity"] = fall_velocity
|
|
136
|
+
|
|
137
|
+
# -------------------------------------------------------------------------------------------
|
|
138
|
+
# Define filtering mask according to fall velocity
|
|
139
|
+
if has_velocity_dimension:
|
|
140
|
+
mask = define_spectrum_mask(
|
|
141
|
+
drop_number=ds["raw_drop_number"],
|
|
142
|
+
fall_velocity=fall_velocity,
|
|
143
|
+
above_velocity_fraction=above_velocity_fraction,
|
|
144
|
+
above_velocity_tolerance=above_velocity_tolerance,
|
|
145
|
+
below_velocity_fraction=below_velocity_fraction,
|
|
146
|
+
below_velocity_tolerance=below_velocity_tolerance,
|
|
147
|
+
small_diameter_threshold=small_diameter_threshold,
|
|
148
|
+
small_velocity_threshold=small_velocity_threshold,
|
|
149
|
+
maintain_smallest_drops=maintain_smallest_drops,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# -------------------------------------------------------------------------------------------
|
|
153
|
+
# Retrieve drop number and drop_counts arrays
|
|
154
|
+
if has_velocity_dimension:
|
|
155
|
+
drop_number = ds["raw_drop_number"].where(mask) # 2D (diameter, velocity)
|
|
156
|
+
drop_counts = drop_number.sum(dim=VELOCITY_DIMENSION) # 1D (diameter)
|
|
157
|
+
drop_counts_raw = ds["raw_drop_number"].sum(dim=VELOCITY_DIMENSION) # 1D (diameter)
|
|
158
|
+
|
|
159
|
+
else:
|
|
160
|
+
drop_number = ds["raw_drop_number"] # 1D (diameter)
|
|
161
|
+
drop_counts = ds["raw_drop_number"] # 1D (diameter)
|
|
162
|
+
drop_counts_raw = ds["raw_drop_number"]
|
|
163
|
+
|
|
164
|
+
# Add drop number and drop_counts
|
|
165
|
+
ds_l1["drop_number"] = drop_number
|
|
166
|
+
ds_l1["drop_counts"] = drop_counts
|
|
167
|
+
|
|
168
|
+
# -------------------------------------------------------------------------------------------
|
|
169
|
+
# Compute minimum and max drop diameter observed
|
|
170
|
+
min_drop_diameter, max_drop_diameter = get_min_max_diameter(drop_counts)
|
|
171
|
+
|
|
172
|
+
# Add drop statistics
|
|
173
|
+
ds_l1["Dmin"] = min_drop_diameter
|
|
174
|
+
ds_l1["Dmax"] = max_drop_diameter
|
|
175
|
+
ds_l1["n_drops_selected"] = drop_counts.sum(dim=DIAMETER_DIMENSION)
|
|
176
|
+
ds_l1["n_drops_discarded"] = drop_counts_raw.sum(dim=DIAMETER_DIMENSION) - ds_l1["n_drops_selected"]
|
|
177
|
+
ds_l1["n_bins_with_drops"] = count_bins_with_drops(ds_l1)
|
|
178
|
+
|
|
179
|
+
# -------------------------------------------------------------------------------------------
|
|
180
|
+
# Add quality flags
|
|
181
|
+
# TODO: snow_flags, insects_flag, ...
|
|
182
|
+
|
|
183
|
+
# -------------------------------------------------------------------------------------------
|
|
184
|
+
#### Add L0C coordinates that might got lost
|
|
185
|
+
if "time_qc" in ds:
|
|
186
|
+
ds_l1 = ds_l1.assign_coords({"time_qc": ds["time_qc"]})
|
|
187
|
+
|
|
188
|
+
#### ----------------------------------------------------------------------------.
|
|
189
|
+
#### Add encodings and attributes
|
|
190
|
+
# Add variables attributes
|
|
191
|
+
attrs_dict = get_attrs_dict()
|
|
192
|
+
ds_l1 = set_attrs(ds_l1, attrs_dict=attrs_dict)
|
|
193
|
+
|
|
194
|
+
# Add variables encoding
|
|
195
|
+
encoding_dict = get_encoding_dict()
|
|
196
|
+
ds_l1 = set_encodings(ds_l1, encoding_dict=encoding_dict)
|
|
197
|
+
|
|
198
|
+
# Add global attributes
|
|
199
|
+
ds_l1.attrs = attrs
|
|
200
|
+
return ds_l1
|