disdrodb 0.2.1__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. disdrodb/__init__.py +3 -1
  2. disdrodb/_config.py +2 -3
  3. disdrodb/_version.py +2 -2
  4. disdrodb/accessor/__init__.py +2 -1
  5. disdrodb/accessor/methods.py +10 -9
  6. disdrodb/api/checks.py +3 -7
  7. disdrodb/api/configs.py +1 -3
  8. disdrodb/api/create_directories.py +4 -6
  9. disdrodb/api/info.py +1 -3
  10. disdrodb/api/io.py +233 -32
  11. disdrodb/api/path.py +3 -7
  12. disdrodb/cli/disdrodb_check_metadata_archive.py +3 -2
  13. disdrodb/cli/disdrodb_check_products_options.py +45 -0
  14. disdrodb/cli/disdrodb_create_summary.py +54 -28
  15. disdrodb/cli/disdrodb_create_summary_station.py +41 -20
  16. disdrodb/cli/disdrodb_data_archive_directory.py +2 -3
  17. disdrodb/cli/disdrodb_download_archive.py +50 -30
  18. disdrodb/cli/disdrodb_download_metadata_archive.py +28 -16
  19. disdrodb/cli/disdrodb_download_station.py +58 -29
  20. disdrodb/cli/disdrodb_initialize_station.py +43 -23
  21. disdrodb/cli/disdrodb_metadata_archive_directory.py +2 -3
  22. disdrodb/cli/disdrodb_open_data_archive.py +17 -13
  23. disdrodb/cli/disdrodb_open_logs_directory.py +31 -21
  24. disdrodb/cli/disdrodb_open_metadata_archive.py +26 -13
  25. disdrodb/cli/disdrodb_open_metadata_directory.py +34 -23
  26. disdrodb/cli/disdrodb_open_product_directory.py +39 -23
  27. disdrodb/cli/disdrodb_open_readers_directory.py +2 -3
  28. disdrodb/cli/disdrodb_run.py +189 -0
  29. disdrodb/cli/disdrodb_run_l0.py +61 -70
  30. disdrodb/cli/disdrodb_run_l0_station.py +50 -55
  31. disdrodb/cli/disdrodb_run_l0a.py +53 -51
  32. disdrodb/cli/disdrodb_run_l0a_station.py +41 -40
  33. disdrodb/cli/disdrodb_run_l0b.py +51 -51
  34. disdrodb/cli/disdrodb_run_l0b_station.py +40 -39
  35. disdrodb/cli/disdrodb_run_l0c.py +56 -53
  36. disdrodb/cli/disdrodb_run_l0c_station.py +44 -41
  37. disdrodb/cli/disdrodb_run_l1.py +55 -51
  38. disdrodb/cli/disdrodb_run_l1_station.py +43 -40
  39. disdrodb/cli/disdrodb_run_l2e.py +56 -51
  40. disdrodb/cli/disdrodb_run_l2e_station.py +44 -40
  41. disdrodb/cli/disdrodb_run_l2m.py +55 -51
  42. disdrodb/cli/disdrodb_run_l2m_station.py +43 -40
  43. disdrodb/cli/disdrodb_run_station.py +184 -0
  44. disdrodb/cli/disdrodb_upload_archive.py +51 -42
  45. disdrodb/cli/disdrodb_upload_station.py +42 -36
  46. disdrodb/configs.py +20 -16
  47. disdrodb/constants.py +5 -2
  48. disdrodb/data_transfer/__init__.py +1 -3
  49. disdrodb/data_transfer/download_data.py +45 -61
  50. disdrodb/data_transfer/upload_data.py +7 -11
  51. disdrodb/data_transfer/zenodo.py +2 -4
  52. disdrodb/docs.py +1 -3
  53. disdrodb/etc/configs/attributes.yaml +52 -2
  54. disdrodb/etc/configs/encodings.yaml +45 -1
  55. disdrodb/etc/products/L0C/ODM470/global.yaml +5 -0
  56. disdrodb/etc/products/L0C/global.yaml +5 -0
  57. disdrodb/etc/products/L1/ODM470/global.yaml +6 -0
  58. disdrodb/etc/products/L1/global.yaml +0 -13
  59. disdrodb/etc/products/L2E/LPM/1MIN.yaml +1 -0
  60. disdrodb/etc/products/L2E/LPM/global.yaml +36 -0
  61. disdrodb/etc/products/L2E/LPM_V0/1MIN.yaml +1 -0
  62. disdrodb/etc/products/L2E/LPM_V0/global.yaml +36 -0
  63. disdrodb/etc/products/L2E/ODM470/1MIN.yaml +1 -0
  64. disdrodb/etc/products/L2E/ODM470/global.yaml +36 -0
  65. disdrodb/etc/products/L2E/PARSIVEL/1MIN.yaml +1 -0
  66. disdrodb/etc/products/L2E/PARSIVEL/global.yaml +36 -0
  67. disdrodb/etc/products/L2E/PARSIVEL2/1MIN.yaml +1 -0
  68. disdrodb/etc/products/L2E/PARSIVEL2/global.yaml +36 -0
  69. disdrodb/etc/products/L2E/PWS100/1MIN.yaml +1 -0
  70. disdrodb/etc/products/L2E/PWS100/global.yaml +36 -0
  71. disdrodb/etc/products/L2E/RD80/1MIN.yaml +19 -0
  72. disdrodb/etc/products/L2E/SWS250/1MIN.yaml +19 -0
  73. disdrodb/etc/products/L2E/global.yaml +16 -2
  74. disdrodb/fall_velocity/__init__.py +47 -0
  75. disdrodb/fall_velocity/graupel.py +484 -0
  76. disdrodb/fall_velocity/hail.py +288 -0
  77. disdrodb/{l1/fall_velocity.py → fall_velocity/rain.py} +265 -44
  78. disdrodb/issue/__init__.py +1 -3
  79. disdrodb/issue/checks.py +2 -3
  80. disdrodb/issue/reader.py +2 -3
  81. disdrodb/issue/writer.py +2 -5
  82. disdrodb/l0/__init__.py +2 -1
  83. disdrodb/l0/check_configs.py +36 -29
  84. disdrodb/l0/check_standards.py +1 -4
  85. disdrodb/l0/configs/LPM/l0a_encodings.yml +17 -17
  86. disdrodb/l0/configs/LPM/l0b_cf_attrs.yml +55 -55
  87. disdrodb/l0/configs/LPM/l0b_encodings.yml +17 -17
  88. disdrodb/l0/configs/LPM/raw_data_format.yml +17 -17
  89. disdrodb/l0/configs/LPM_V0/l0a_encodings.yml +2 -2
  90. disdrodb/l0/configs/LPM_V0/l0b_cf_attrs.yml +2 -2
  91. disdrodb/l0/configs/LPM_V0/l0b_encodings.yml +2 -2
  92. disdrodb/l0/configs/LPM_V0/raw_data_format.yml +2 -2
  93. disdrodb/l0/configs/ODM470/bins_diameter.yml +643 -0
  94. disdrodb/l0/configs/ODM470/bins_velocity.yml +0 -0
  95. disdrodb/l0/configs/ODM470/l0a_encodings.yml +11 -0
  96. disdrodb/l0/configs/ODM470/l0b_cf_attrs.yml +46 -0
  97. disdrodb/l0/configs/ODM470/l0b_encodings.yml +106 -0
  98. disdrodb/l0/configs/ODM470/raw_data_format.yml +111 -0
  99. disdrodb/l0/configs/PARSIVEL/l0b_cf_attrs.yml +1 -1
  100. disdrodb/l0/l0_reader.py +2 -3
  101. disdrodb/l0/l0a_processing.py +6 -8
  102. disdrodb/l0/l0b_nc_processing.py +3 -6
  103. disdrodb/l0/l0b_processing.py +2 -16
  104. disdrodb/l0/l0c_processing.py +29 -12
  105. disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +2 -1
  106. disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +18 -18
  107. disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +18 -18
  108. disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +18 -18
  109. disdrodb/l0/readers/LPM/GERMANY/DWD.py +244 -63
  110. disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +65 -23
  111. disdrodb/l0/readers/LPM/ITALY/GID_LPM_AQ.py +277 -0
  112. disdrodb/l0/readers/LPM/ITALY/GID_LPM_PI.py +19 -18
  113. disdrodb/l0/readers/LPM/ITALY/GID_LPM_T.py +23 -19
  114. disdrodb/l0/readers/LPM/ITALY/GID_LPM_W.py +19 -21
  115. disdrodb/l0/readers/LPM/KIT/CHWALA.py +19 -20
  116. disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_LPM_NC.py +1 -1
  117. disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_RWANDA_LPM_NC.py +18 -18
  118. disdrodb/l0/readers/LPM/NORWAY/HAUKELISETER_LPM.py +19 -20
  119. disdrodb/l0/readers/LPM/NORWAY/NMBU_LPM.py +19 -20
  120. disdrodb/l0/readers/LPM/SLOVENIA/ARSO.py +19 -20
  121. disdrodb/l0/readers/LPM/SLOVENIA/UL.py +19 -20
  122. disdrodb/l0/readers/LPM/SWITZERLAND/INNERERIZ_LPM.py +19 -20
  123. disdrodb/l0/readers/LPM/UK/DIVEN.py +1 -1
  124. disdrodb/l0/readers/LPM/UK/WITHWORTH_LPM.py +19 -20
  125. disdrodb/l0/readers/LPM/USA/CHARLESTON.py +19 -20
  126. disdrodb/l0/readers/LPM/USA/DEVEX.py +255 -0
  127. disdrodb/l0/readers/LPM_V0/BELGIUM/ULIEGE.py +3 -5
  128. disdrodb/l0/readers/LPM_V0/ITALY/GID_LPM_V0.py +4 -3
  129. disdrodb/l0/readers/ODM470/OCEAN/OCEANRAIN.py +124 -0
  130. disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +1 -1
  131. disdrodb/l0/readers/PARSIVEL/BASQUECOUNTRY/EUSKALMET_OTT.py +2 -1
  132. disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +2 -3
  133. disdrodb/l0/readers/PARSIVEL/EPFL/ARCTIC_2021.py +2 -1
  134. disdrodb/l0/readers/PARSIVEL/EPFL/COMMON_2011.py +2 -1
  135. disdrodb/l0/readers/PARSIVEL/EPFL/DAVOS_2009_2011.py +2 -1
  136. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_2009.py +2 -1
  137. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2008.py +2 -1
  138. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +2 -1
  139. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2011.py +2 -1
  140. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2012.py +2 -1
  141. disdrodb/l0/readers/PARSIVEL/EPFL/GENEPI_2007.py +2 -1
  142. disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007.py +2 -1
  143. disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007_2.py +2 -1
  144. disdrodb/l0/readers/PARSIVEL/EPFL/HPICONET_2010.py +2 -1
  145. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP2.py +2 -1
  146. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +2 -1
  147. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP4.py +2 -1
  148. disdrodb/l0/readers/PARSIVEL/EPFL/LOCARNO_2018.py +1 -1
  149. disdrodb/l0/readers/PARSIVEL/EPFL/LOCARNO_2019.py +1 -1
  150. disdrodb/l0/readers/PARSIVEL/EPFL/PARADISO_2014.py +2 -1
  151. disdrodb/l0/readers/PARSIVEL/EPFL/PARSIVEL_2007.py +2 -1
  152. disdrodb/l0/readers/PARSIVEL/EPFL/PLATO_2019.py +1 -1
  153. disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +2 -1
  154. disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019_WJF.py +2 -1
  155. disdrodb/l0/readers/PARSIVEL/EPFL/RIETHOLZBACH_2011.py +2 -1
  156. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +2 -1
  157. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +2 -1
  158. disdrodb/l0/readers/PARSIVEL/EPFL/UNIL_2022.py +2 -1
  159. disdrodb/l0/readers/PARSIVEL/JAPAN/JMA.py +1 -1
  160. disdrodb/l0/readers/PARSIVEL/KOREA/ICEPOP_MSC.py +159 -0
  161. disdrodb/l0/readers/PARSIVEL/NASA/LPVEX.py +1 -1
  162. disdrodb/l0/readers/PARSIVEL/NASA/MC3E.py +1 -1
  163. disdrodb/l0/readers/PARSIVEL/NCAR/CCOPE_2015.py +1 -1
  164. disdrodb/l0/readers/PARSIVEL/NCAR/OWLES_MIPS.py +1 -1
  165. disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +1 -1
  166. disdrodb/l0/readers/PARSIVEL/NCAR/PLOWS_MIPS.py +1 -1
  167. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +1 -1
  168. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +1 -3
  169. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +1 -3
  170. disdrodb/l0/readers/PARSIVEL/SLOVENIA/UL.py +2 -1
  171. disdrodb/l0/readers/PARSIVEL2/ARM/ARM_PARSIVEL2.py +2 -1
  172. disdrodb/l0/readers/PARSIVEL2/BASQUECOUNTRY/EUSKALMET_OTT2.py +2 -1
  173. disdrodb/l0/readers/PARSIVEL2/BELGIUM/ILVO.py +2 -3
  174. disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +1 -1
  175. disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +1 -1
  176. disdrodb/l0/readers/PARSIVEL2/CANADA/UQAM_NC.py +1 -1
  177. disdrodb/l0/readers/PARSIVEL2/DENMARK/DTU.py +1 -1
  178. disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_nc.py +2 -1
  179. disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_raw.py +2 -1
  180. disdrodb/l0/readers/PARSIVEL2/FINLAND/FMI_PARSIVEL2.py +1 -1
  181. disdrodb/l0/readers/PARSIVEL2/FRANCE/ENPC_PARSIVEL2.py +2 -3
  182. disdrodb/l0/readers/PARSIVEL2/FRANCE/OSUG.py +2 -2
  183. disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +1 -3
  184. disdrodb/l0/readers/PARSIVEL2/GREECE/NOA.py +4 -3
  185. disdrodb/l0/readers/PARSIVEL2/ITALY/GID_PARSIVEL2.py +1 -3
  186. disdrodb/l0/readers/PARSIVEL2/ITALY/HYDROX.py +6 -3
  187. disdrodb/l0/readers/PARSIVEL2/JAPAN/PRECIP.py +1 -1
  188. disdrodb/l0/readers/PARSIVEL2/KIT/BURKINA_FASO.py +1 -1
  189. disdrodb/l0/readers/PARSIVEL2/KIT/TEAMX.py +1 -1
  190. disdrodb/l0/readers/PARSIVEL2/KOREA/ICEPOP_MSC.py +161 -0
  191. disdrodb/l0/readers/PARSIVEL2/KOREA/ICEPOP_UCLM.py +126 -0
  192. disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +2 -1
  193. disdrodb/l0/readers/PARSIVEL2/MPI/BCO_PARSIVEL2.py +1 -1
  194. disdrodb/l0/readers/PARSIVEL2/MPI/BOWTIE.py +1 -1
  195. disdrodb/l0/readers/PARSIVEL2/NASA/APU.py +3 -1
  196. disdrodb/l0/readers/PARSIVEL2/NASA/NSSTC.py +1 -1
  197. disdrodb/l0/readers/PARSIVEL2/NCAR/FARM_PARSIVEL2.py +2 -1
  198. disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +1 -1
  199. disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_MIPS.py +1 -1
  200. disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_MIPS.py +2 -1
  201. disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_PIPS.py +2 -1
  202. disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +1 -1
  203. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +1 -1
  204. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +1 -1
  205. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P1.py +2 -3
  206. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +1 -1
  207. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +2 -1
  208. disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT_NC.py +1 -1
  209. disdrodb/l0/readers/PARSIVEL2/NORWAY/UIB.py +10 -2
  210. disdrodb/l0/readers/PARSIVEL2/PHILIPPINES/PAGASA.py +2 -3
  211. disdrodb/l0/readers/PARSIVEL2/SPAIN/CENER.py +1 -1
  212. disdrodb/l0/readers/PARSIVEL2/SPAIN/CR1000DL.py +1 -1
  213. disdrodb/l0/readers/PARSIVEL2/SPAIN/GRANADA.py +2 -3
  214. disdrodb/l0/readers/PARSIVEL2/SPAIN/LIAISE.py +1 -1
  215. disdrodb/l0/readers/PARSIVEL2/SWEDEN/SMHI.py +2 -1
  216. disdrodb/l0/readers/PARSIVEL2/USA/CSU.py +1 -1
  217. disdrodb/l0/readers/PARSIVEL2/USA/CW3E.py +2 -1
  218. disdrodb/l0/readers/PWS100/AUSTRIA/HOAL.py +2 -3
  219. disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100.py +2 -3
  220. disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100_SIRTA.py +2 -1
  221. disdrodb/l0/readers/RD80/BRAZIL/ATTO_RD80.py +1 -3
  222. disdrodb/l0/readers/RD80/BRAZIL/CHUVA_RD80.py +1 -3
  223. disdrodb/l0/readers/RD80/BRAZIL/GOAMAZON_RD80.py +1 -3
  224. disdrodb/l0/readers/RD80/NCAR/CINDY_2011_RD80.py +1 -3
  225. disdrodb/l0/readers/RD80/NCAR/RELAMPAGO_RD80.py +1 -3
  226. disdrodb/l0/readers/RD80/NOAA/PSL_RD80.py +2 -3
  227. disdrodb/l0/readers/SWS250/BELGIUM/KMI.py +2 -3
  228. disdrodb/l0/readers/template_reader_raw_netcdf_data.py +2 -3
  229. disdrodb/l0/readers/template_reader_raw_text_data.py +2 -3
  230. disdrodb/l0/standards.py +4 -5
  231. disdrodb/l0/template_tools.py +7 -11
  232. disdrodb/l1/__init__.py +2 -1
  233. disdrodb/l1/classification.py +914 -0
  234. disdrodb/l1/processing.py +36 -106
  235. disdrodb/l1/resampling.py +13 -3
  236. disdrodb/l1_env/__init__.py +1 -1
  237. disdrodb/l1_env/routines.py +7 -6
  238. disdrodb/l2/__init__.py +2 -1
  239. disdrodb/l2/empirical_dsd.py +58 -31
  240. disdrodb/l2/processing.py +327 -61
  241. disdrodb/metadata/checks.py +10 -13
  242. disdrodb/metadata/download.py +5 -4
  243. disdrodb/metadata/geolocation.py +3 -4
  244. disdrodb/metadata/info.py +3 -5
  245. disdrodb/metadata/manipulation.py +1 -3
  246. disdrodb/metadata/reader.py +1 -3
  247. disdrodb/metadata/search.py +1 -4
  248. disdrodb/metadata/standards.py +1 -3
  249. disdrodb/metadata/writer.py +1 -3
  250. disdrodb/physics/__init__.py +17 -0
  251. disdrodb/physics/atmosphere.py +273 -0
  252. disdrodb/physics/water.py +131 -0
  253. disdrodb/physics/wrappers.py +63 -0
  254. disdrodb/psd/__init__.py +1 -2
  255. disdrodb/psd/fitting.py +23 -9
  256. disdrodb/psd/models.py +2 -1
  257. disdrodb/routines/__init__.py +6 -1
  258. disdrodb/routines/l0.py +39 -25
  259. disdrodb/routines/l1.py +23 -16
  260. disdrodb/routines/l2.py +12 -9
  261. disdrodb/routines/options.py +117 -73
  262. disdrodb/routines/options_validation.py +728 -0
  263. disdrodb/routines/wrappers.py +460 -40
  264. disdrodb/scattering/__init__.py +1 -2
  265. disdrodb/scattering/axis_ratio.py +6 -6
  266. disdrodb/scattering/permittivity.py +9 -8
  267. disdrodb/scattering/routines.py +33 -15
  268. disdrodb/summary/__init__.py +1 -1
  269. disdrodb/summary/routines.py +95 -30
  270. disdrodb/utils/__init__.py +1 -1
  271. disdrodb/utils/archiving.py +18 -10
  272. disdrodb/utils/attrs.py +7 -5
  273. disdrodb/utils/cli.py +8 -10
  274. disdrodb/utils/compression.py +10 -13
  275. disdrodb/utils/coords.py +45 -0
  276. disdrodb/utils/dask.py +7 -5
  277. disdrodb/utils/dataframe.py +5 -6
  278. disdrodb/utils/decorators.py +3 -4
  279. disdrodb/utils/dict.py +1 -1
  280. disdrodb/utils/directories.py +5 -7
  281. disdrodb/utils/encoding.py +4 -5
  282. disdrodb/utils/event.py +1 -1
  283. disdrodb/utils/list.py +1 -3
  284. disdrodb/utils/logger.py +1 -3
  285. disdrodb/utils/manipulations.py +175 -4
  286. disdrodb/utils/pydantic.py +81 -0
  287. disdrodb/utils/routines.py +2 -3
  288. disdrodb/utils/subsetting.py +1 -1
  289. disdrodb/utils/time.py +6 -4
  290. disdrodb/utils/warnings.py +2 -3
  291. disdrodb/utils/writer.py +5 -3
  292. disdrodb/utils/xarray.py +31 -3
  293. disdrodb/utils/yaml.py +1 -3
  294. disdrodb/viz/__init__.py +1 -1
  295. disdrodb/viz/plots.py +193 -18
  296. {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/METADATA +5 -4
  297. disdrodb-0.4.0.dist-info/RECORD +361 -0
  298. {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/entry_points.txt +3 -0
  299. disdrodb/etc/products/L1/1MIN.yaml +0 -13
  300. disdrodb/etc/products/L1/LPM/1MIN.yaml +0 -13
  301. disdrodb/etc/products/L1/LPM_V0/1MIN.yaml +0 -13
  302. disdrodb/etc/products/L1/PARSIVEL/1MIN.yaml +0 -13
  303. disdrodb/etc/products/L1/PARSIVEL2/1MIN.yaml +0 -13
  304. disdrodb/etc/products/L1/PWS100/1MIN.yaml +0 -13
  305. disdrodb/etc/products/L1/RD80/1MIN.yaml +0 -13
  306. disdrodb/etc/products/L1/SWS250/1MIN.yaml +0 -13
  307. disdrodb/etc/products/L2M/10MIN.yaml +0 -12
  308. disdrodb/l1/beard_model.py +0 -662
  309. disdrodb/l1/filters.py +0 -205
  310. disdrodb-0.2.1.dist-info/RECORD +0 -329
  311. {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/WHEEL +0 -0
  312. {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/licenses/LICENSE +0 -0
  313. {disdrodb-0.2.1.dist-info → disdrodb-0.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,288 @@
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
+ """Theoretical models to estimate hailstones fall velocity based on particle maximum diameter in mm."""
18
+
19
+ import numpy as np
20
+ import xarray as xr
21
+
22
+ from disdrodb.constants import DIAMETER_DIMENSION
23
+ from disdrodb.l0.l0b_processing import ensure_valid_geolocation
24
+ from disdrodb.l1_env.routines import load_env_dataset
25
+ from disdrodb.physics.wrappers import retrieve_air_pressure
26
+ from disdrodb.utils.warnings import suppress_warnings
27
+
28
+
29
+ def get_fall_velocity_laurie_1960(diameter):
30
+ """Get hailstones fall velocity based on Laurie 1960 data.
31
+
32
+ The parametrizazion is reported in Table 3 of Heymsfield et al., 2018.
33
+
34
+ Parameters
35
+ ----------
36
+ diameter : array-like or float
37
+ Particle maximum diameter in millimeters [mm].
38
+
39
+
40
+ Returns
41
+ -------
42
+ fall_velocity : array-like or float
43
+ Terminal fall velocity [m s⁻¹].
44
+
45
+ References
46
+ ----------
47
+ Heymsfield, A., M. Szakáll, A. Jost, I. Giammanco, and R. Wright, 2018.
48
+ A Comprehensive Observational Study of Graupel and Hail Terminal Velocity, Mass Flux, and Kinetic Energy.
49
+ J. Atmos. Sci., 75, 3861-3885, https://doi.org/10.1175/JAS-D-18-0035.1.
50
+ """
51
+ fall_velocity = 13.95 * (0.1 * diameter) ** 0.51
52
+ return fall_velocity
53
+
54
+
55
+ def get_fall_velocity_knight_1983_low_density(diameter):
56
+ """Get low-density hailstones fall velocity based on Knight et al. 1983.
57
+
58
+ The parametrization is reported in Figure 3 of Knight et al. 1983.
59
+ It's valid for hail stone density between 0.31 and 0.61 g cm-3.
60
+
61
+ Parameters
62
+ ----------
63
+ diameter : array-like or float
64
+ Particle maximum diameter in millimeters [mm].
65
+
66
+
67
+ Returns
68
+ -------
69
+ fall_velocity : array-like or float
70
+ Terminal fall velocity [m s⁻¹].
71
+
72
+ References
73
+ ----------
74
+ Knight, N. C., and A. J. Heymsfield, 1983.
75
+ Measurement and Interpretation of Hailstone Density and Terminal Velocity.
76
+ J. Atmos. Sci., 40, 1510-1516. https://doi.org/10.1175/1520-0469(1983)040<1510:MAIOHD>2.0.CO;2.
77
+ """
78
+ fall_velocity = 8.445 * (0.1 * diameter) ** 0.553
79
+ return fall_velocity
80
+
81
+
82
+ def get_fall_velocity_knight_1983_high_density(diameter):
83
+ """Get low-density hailstones fall velocity based on Knight et al. 1983.
84
+
85
+ The parametrization is reported in Figure 6 of Knight et al. 1983.
86
+ It's valid for hail stone density around 0.82 g cm-3.
87
+
88
+ Parameters
89
+ ----------
90
+ diameter : array-like or float
91
+ Particle maximum diameter in millimeters [mm].
92
+
93
+
94
+ Returns
95
+ -------
96
+ fall_velocity : array-like or float
97
+ Terminal fall velocity [m s⁻¹].
98
+
99
+ References
100
+ ----------
101
+ Knight, N. C., and A. J. Heymsfield, 1983.
102
+ Measurement and Interpretation of Hailstone Density and Terminal Velocity.
103
+ J. Atmos. Sci., 40, 1510-1516. https://doi.org/10.1175/1520-0469(1983)040<1510:MAIOHD>2.0.CO;2.
104
+ """
105
+ fall_velocity = 10.58 * (0.1 * diameter) ** 0.267
106
+ return fall_velocity
107
+
108
+
109
+ def get_fall_velocity_heymsfield_2014(diameter):
110
+ """Get hail fall velocity from Heymsfield et al., 2014.
111
+
112
+ Use the Heymsfield et al., 2014 parameterization.
113
+
114
+ Parameters
115
+ ----------
116
+ diameter : array-like or float
117
+ Maximum Particle maximum diameter in millimeters [mm].
118
+
119
+ Returns
120
+ -------
121
+ fall_velocity : xarray.DataArray or numpy.ndarray
122
+ Terminal fall velocity [m s⁻¹].
123
+
124
+ References
125
+ ----------
126
+ Heymsfield, A. J., I. M. Giammanco, and R. Wright (2014).
127
+ Terminal velocities and kinetic energies of natural hailstones.
128
+ Geophys. Res. Lett., 41, 8666-8672, https://doi.org/10.1002/2014GL062324
129
+ """
130
+ fall_velocity = 12.28 * (0.1 * diameter) ** 0.57 # Dmax > 1.3 mm
131
+ return fall_velocity
132
+
133
+
134
+ def get_fall_velocity_heymsfield_2018(diameter):
135
+ """Get hailstones fall velocity from Heymsfield et al., 2018.
136
+
137
+ Parameters
138
+ ----------
139
+ diameter : array-like or float
140
+ Particle maximum diameter in millimeters [mm].
141
+
142
+ Returns
143
+ -------
144
+ fall_velocity : array-like or float
145
+ Terminal fall velocity [m s⁻¹].
146
+
147
+ References
148
+ ----------
149
+ Heymsfield, A., M. Szakáll, A. Jost, I. Giammanco, and R. Wright, 2018.
150
+ A Comprehensive Observational Study of Graupel and Hail Terminal Velocity, Mass Flux, and Kinetic Energy.
151
+ J. Atmos. Sci., 75, 3861-3885, https://doi.org/10.1175/JAS-D-18-0035.1.
152
+
153
+ Heymsfield, A., M. Szakáll, A. Jost, I. Giammanco, R. Wright, and J. Brimelow, 2020.
154
+ CORRIGENDUM.
155
+ J. Atmos. Sci., 77, 405-412, https://doi.org/10.1175/JAS-D-19-0185.1.
156
+ """
157
+ # Original incorrect formula from Heymsfield et al., 2018
158
+ # fall_velocity = 6.1 * (0.1 * diameter) ** 0.72 # eq 7 and 15
159
+
160
+ # Corrected formula from Heymsfield et al., 2020 (Corrigendum)
161
+ fall_velocity = 8.39 * (0.1 * diameter) ** 0.67
162
+ return fall_velocity
163
+
164
+
165
+ def get_fall_velocity_fehlmann_2020(diameter):
166
+ """Get hailstones fall velocity from Fehlmann et al., 2020."""
167
+ fall_velocity = 3.74 * diameter**0.5
168
+ return fall_velocity
169
+
170
+
171
+ ####------------------------------------------------------------------------------------
172
+ #### Wrappers
173
+
174
+
175
+ HAIL_FALL_VELOCITY_MODELS = {
176
+ "Laurie1960": get_fall_velocity_laurie_1960,
177
+ "Knight1983LD": get_fall_velocity_knight_1983_low_density,
178
+ "Knight1983HD": get_fall_velocity_knight_1983_high_density,
179
+ "Heymsfield2014": get_fall_velocity_heymsfield_2014,
180
+ "Heymsfield2018": get_fall_velocity_heymsfield_2018,
181
+ "Fehlmann2020": get_fall_velocity_fehlmann_2020,
182
+ }
183
+
184
+
185
+ def available_hail_fall_velocity_models():
186
+ """Return a list of the available hail fall velocity models."""
187
+ return list(HAIL_FALL_VELOCITY_MODELS)
188
+
189
+
190
+ def check_hail_fall_velocity_model(model):
191
+ """Check validity of the specified hail fall velocity model."""
192
+ available_models = available_hail_fall_velocity_models()
193
+ if model not in available_models:
194
+ raise ValueError(f"{model} is an invalid hail fall velocity model. Valid models: {available_models}.")
195
+ return model
196
+
197
+
198
+ def get_hail_fall_velocity_model(model):
199
+ """Return the specified hail fall velocity model.
200
+
201
+ Parameters
202
+ ----------
203
+ model : str
204
+ The model to use for calculating the rain drop fall velocity. Available models are:
205
+ 'Laurie1960', 'Knight1983LD', 'Knight1983HD', 'Heymsfield2014', 'Heymsfield2018', 'Fehlmann2020'.
206
+
207
+ Returns
208
+ -------
209
+ callable
210
+ A function which compute the hail fall velocity model
211
+ given the rain drop diameter in mm.
212
+
213
+ Notes
214
+ -----
215
+ This function serves as a wrapper to various hail fall velocity models.
216
+ It returns the appropriate model based on the `model` parameter.
217
+ """
218
+ model = check_hail_fall_velocity_model(model)
219
+ return HAIL_FALL_VELOCITY_MODELS[model]
220
+
221
+
222
+ def get_hail_fall_velocity(diameter, model, ds_env=None, minimum_diameter=4):
223
+ """Calculate the fall velocity of hails based on their diameter.
224
+
225
+ Parameters
226
+ ----------
227
+ diameter : array-like
228
+ The diameter of the hails in millimeters.
229
+ model : str
230
+ The model to use for calculating the hail fall velocity. Must be one of the following:
231
+ 'Laurie1960', 'Knight1983LD', 'Knight1983HD', 'Heymsfield2014', 'Heymsfield2018', 'Fehlmann2020'.
232
+ ds_env : xr.Dataset, optional
233
+ A dataset containing the following environmental variables:
234
+ - 'altitude' (m)
235
+ - 'latitude' (°)
236
+ - 'temperature' : Temperature in degrees Kelvin (K).
237
+ - 'relative_humidity' : Relative humidity. A value between 0 and 1.
238
+ - 'sea_level_air_pressure' : Sea level air pressure in Pascals (Pa).
239
+ - 'lapse_rate' : Lapse rate in degrees Celsius per meter (°C/m).
240
+ If not specified, sensible default values are used.
241
+
242
+ Returns
243
+ -------
244
+ fall_velocity : xr.DataArray
245
+ The calculated hail fall velocities per diameter.
246
+
247
+ """
248
+ # Check valid method
249
+ model = check_hail_fall_velocity_model(model)
250
+
251
+ # Copy diameter
252
+ if isinstance(diameter, xr.DataArray):
253
+ diameter = diameter.copy()
254
+ else:
255
+ diameter = np.atleast_1d(diameter)
256
+ diameter = xr.DataArray(diameter, dims=DIAMETER_DIMENSION, coords={DIAMETER_DIMENSION: diameter.copy()})
257
+
258
+ # Initialize ds_env if None
259
+ # --> Ensure valid altitude and geolocation
260
+ # - altitude requiredto correct for elevation (air_density)
261
+ # - latitude required for gravity
262
+ if ds_env is None:
263
+ ds_env = load_env_dataset()
264
+ for coord in ["altitude", "latitude"]:
265
+ ds_env = ensure_valid_geolocation(ds_env, coord=coord, errors="raise")
266
+
267
+ # Retrieve fall velocity
268
+ func = get_hail_fall_velocity_model(model)
269
+ with suppress_warnings(): # e.g. when diameter = 0
270
+ fall_velocity = func(diameter)
271
+
272
+ # Correct for altitude
273
+ air_pressure = retrieve_air_pressure(ds_env)
274
+ correction_factor = (101325 / air_pressure) ** 0.545
275
+ fall_velocity = fall_velocity * correction_factor
276
+
277
+ # Set to NaN for diameter outside [5, ...)
278
+ fall_velocity = fall_velocity.where(diameter > minimum_diameter)
279
+
280
+ # Ensure fall velocity is > 0 to avoid division by zero
281
+ # - Some models, at small diameter, can return negative/zero fall velocity
282
+ fall_velocity = fall_velocity.where(fall_velocity > 0)
283
+
284
+ # Add attributes
285
+ fall_velocity.name = "fall_velocity"
286
+ fall_velocity.attrs["units"] = "m/s"
287
+ fall_velocity.attrs["model"] = model
288
+ return fall_velocity.squeeze()
@@ -1,5 +1,5 @@
1
1
  # -----------------------------------------------------------------------------.
2
- # Copyright (c) 2021-2023 DISDRODB developers
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,14 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
  # -----------------------------------------------------------------------------.
17
17
  """Theoretical models to estimate the raindrop fall velocity based on drop diameter in mm."""
18
+
18
19
  import numpy as np
19
20
  import xarray as xr
20
21
 
21
22
  from disdrodb.constants import DIAMETER_DIMENSION
22
23
  from disdrodb.l0.l0b_processing import ensure_valid_geolocation
23
24
  from disdrodb.l1_env.routines import load_env_dataset
25
+ from disdrodb.physics.wrappers import retrieve_air_density
24
26
  from disdrodb.utils.warnings import suppress_warnings
25
27
 
26
28
 
@@ -138,8 +140,159 @@ def get_fall_velocity_van_dijk_2002(diameter):
138
140
  return fall_velocity
139
141
 
140
142
 
141
- def get_fall_velocity_beard_1976(diameter, ds_env):
142
- """Calculate the fall velocity of a particle using the Beard (1976) model.
143
+ ####---------------------------------------------------------------------------.
144
+ #### Beard model
145
+
146
+
147
+ def get_raindrop_reynolds_number(diameter, temperature, air_density, water_density, g):
148
+ """Compute raindrop Reynolds number.
149
+
150
+ It quantifies the relative strength of the convective inertia and linear viscous
151
+ forces acting on the drop at terminal velocity.
152
+
153
+ Estimates Reynolds number for drops with diameter between 19 um and 7 mm.
154
+ Coefficients are taken from Table 1 of Beard 1976.
155
+
156
+ Reference: Beard 1976; Pruppacher & Klett 1978
157
+ See also Table A1 in Rahman et al., 2020.
158
+
159
+ Parameters
160
+ ----------
161
+ diameter : float
162
+ Diameter of the raindrop in meters.
163
+ temperature : float
164
+ Temperature in Kelvin.
165
+ air_density : float
166
+ Density of air in kg/m^3.
167
+ water_density : float
168
+ Density of water in kg/m^3.
169
+ g : float
170
+ Gravitational acceleration in m/s^2.
171
+
172
+ Returns
173
+ -------
174
+ float
175
+ Reynolds number for the raindrop.
176
+ """
177
+ from disdrodb.physics.atmosphere import get_air_dynamic_viscosity
178
+ from disdrodb.physics.water import get_pure_water_surface_tension
179
+
180
+ # Define mask for small and large particles
181
+ small_diam_mask = diameter < 1.07e-3 # < 1mm
182
+
183
+ # Compute properties
184
+ pure_water_surface_tension = get_pure_water_surface_tension(temperature) # N/m
185
+ air_viscosity = get_air_dynamic_viscosity(temperature) # kg/(m*s) (aka Pa*s).
186
+ delta_density = water_density - air_density
187
+
188
+ # Compute Davies number for small droplets
189
+ davis_number = 4 * air_density * delta_density * g * diameter**3 / (3 * air_viscosity**2)
190
+
191
+ # Compute the slip correction (is approx 1 and can be discarded)
192
+ # l0 = 6.62*1e-8 # m
193
+ # v0 = 0.01818 # g / m / s
194
+ # p0 = 101_325_25 # Pa
195
+ # t0 = 293.15 # K
196
+ # c_sc = 1 + 2.51*l0*(air_viscosity/v0)*(air_pressure/p0)*((temperature/t0)**3)/diameter
197
+
198
+ # Compute modified Bond and physical property numbers for large droplets
199
+ bond_number = 4 * delta_density * g * diameter**2 / (3 * pure_water_surface_tension)
200
+ property_number = pure_water_surface_tension**3 * air_density**2 / (air_viscosity**4 * delta_density * g)
201
+
202
+ # Compute Reynolds_number_for small particles (diameter < 0.00107) (1 mm)
203
+ b = [-3.18657, 0.992696, -0.00153193, -0.000987059, -0.000578878, 0.0000855176, -0.00000327815]
204
+ x = np.log(davis_number)
205
+ y = b[0] + sum(b * x**i for i, b in enumerate(b[1:], start=1))
206
+ reynolds_number_small = np.exp(y) # TODO: miss C_sc = slip correction factor ?
207
+
208
+ # Compute Reynolds_number_for large particles (diameter >= 0.00107)
209
+ b = [-5.00015, 5.23778, -2.04914, 0.475294, -0.0542819, 0.00238449]
210
+ log_property_number = np.log(property_number) / 6
211
+ x = np.log(bond_number) + log_property_number
212
+ y = b[0] + sum(b * x**i for i, b in enumerate(b[1:], start=1))
213
+ reynolds_number_large = np.exp(log_property_number + y)
214
+
215
+ # Define final reynolds number
216
+ reynolds_number = xr.where(small_diam_mask, reynolds_number_small, reynolds_number_large)
217
+ return reynolds_number
218
+
219
+
220
+ def get_drag_coefficient(diameter, air_density, water_density, fall_velocity, g=9.81):
221
+ """
222
+ Computes the drag coefficient for a raindrop.
223
+
224
+ Parameters
225
+ ----------
226
+ diameter : float
227
+ Diameter of the raindrop in meters.
228
+ air_density : float
229
+ Density of air in kg/m^3.
230
+ water_density : float
231
+ Density of water in kg/m^3.
232
+ fall_velocity : float
233
+ Terminal fall velocity of the raindrop in m/s.
234
+ g : float
235
+ Gravitational acceleration in m/s^2.
236
+
237
+ Returns
238
+ -------
239
+ float
240
+ Drag coefficient of the raindrop.
241
+ """
242
+ delta_density = water_density - air_density
243
+ drag_coefficient = 4 * delta_density * g * diameter / (3 * air_density * fall_velocity**2)
244
+ return drag_coefficient
245
+
246
+
247
+ def get_raindrop_beard1976_fall_velocity(diameter, temperature, air_density, water_density, g):
248
+ """
249
+ Computes the terminal fall velocity of a raindrop in still air.
250
+
251
+ Reference: Beard 1976; Pruppacher & Klett 1978
252
+
253
+ Parameters
254
+ ----------
255
+ diameter : float
256
+ Diameter of the raindrop in millimeters.
257
+ temperature : float
258
+ Temperature in Kelvin.
259
+ air_density : float
260
+ Density of air in kg/m^3.
261
+ water_density : float
262
+ Density of water in kg/m^3.
263
+ g : float
264
+ Gravitational acceleration in m/s^2.
265
+
266
+ Returns
267
+ -------
268
+ float
269
+ Terminal fall velocity of the raindrop in m/s.
270
+ """
271
+ from disdrodb.physics.atmosphere import get_air_dynamic_viscosity
272
+
273
+ # Convert diameter to meter
274
+ diameter = diameter / 1000
275
+
276
+ # Compute air viscotiy and reynolds number
277
+ air_viscosity = get_air_dynamic_viscosity(temperature)
278
+ reynolds_number = get_raindrop_reynolds_number(
279
+ diameter=diameter,
280
+ temperature=temperature,
281
+ air_density=air_density,
282
+ water_density=water_density,
283
+ g=g,
284
+ )
285
+ # Compute fall velocity
286
+ fall_velocity = air_viscosity * reynolds_number / (air_density * diameter)
287
+ return fall_velocity
288
+
289
+
290
+ def retrieve_raindrop_beard_fall_velocity(
291
+ diameter,
292
+ ds_env,
293
+ ):
294
+ """
295
+ Computes the terminal fall velocity for liquid raindrops using the Beard (1976) model.
143
296
 
144
297
  Parameters
145
298
  ----------
@@ -150,56 +303,118 @@ def get_fall_velocity_beard_1976(diameter, ds_env):
150
303
  - 'altitude' : Altitude in meters (m).
151
304
  - 'latitude' : Latitude in degrees.
152
305
  - 'temperature' : Temperature in degrees Kelvin (K).
153
- - 'relative_humidity' : Relative humidity in percentage (%).
154
- - 'sea_level_air_pressure' : Sea level air pressure in Pascals (Pa).
155
- - 'air_pressure': Air pressure in Pascals (Pa).
156
- - 'lapse_rate' : Lapse rate in degrees Celsius per meter (°C/m).
306
+ - 'relative_humidity' : Relative humidity between 0 and 1.
307
+ - 'sea_level_air_pressure' : Standard atmospheric pressure at sea level in Pascals (Pa).
308
+ The default is 101_325 Pa.
309
+ - 'air_pressure': Air pressure in Pascals (Pa). If None, air_pressure at altitude is inferred.
310
+ - 'lapse_rate' : Atmospheric lapse rate in degrees Celsius or Kelvin per meter (°C/m).
311
+ The default is 0.0065 K/m.
312
+ - 'gas_constant_dry_air': Gas constant for dry air in J/(kg*K).
313
+ The default is 287.04 is J/(kg*K).
157
314
 
158
315
  Returns
159
316
  -------
160
317
  fall_velocity : array-like
161
- The calculated fall velocities of the raindrops.
318
+ Terminal fall velocity for liquid raindrops.
162
319
  """
163
- from disdrodb.l1.beard_model import retrieve_fall_velocity
164
-
165
- # Input diameter in mmm
166
- fall_velocity = retrieve_fall_velocity(
167
- diameter=diameter / 1000, # diameter expected in m !!!
168
- altitude=ds_env["altitude"],
169
- latitude=ds_env["latitude"],
170
- temperature=ds_env["temperature"],
171
- relative_humidity=ds_env["relative_humidity"],
172
- air_pressure=ds_env.get("air_pressure", None),
173
- sea_level_air_pressure=ds_env["sea_level_air_pressure"],
174
- lapse_rate=ds_env["lapse_rate"],
320
+ from disdrodb.physics.atmosphere import (
321
+ get_air_density,
322
+ get_air_pressure_at_height,
323
+ get_gravitational_acceleration,
324
+ get_vapor_actual_pressure,
325
+ )
326
+ from disdrodb.physics.water import get_water_density
327
+
328
+ # Retrieve relevant variables from ENV dataset
329
+ altitude = ds_env["altitude"]
330
+ latitude = ds_env["latitude"]
331
+ temperature = ds_env["temperature"]
332
+ relative_humidity = ds_env["relative_humidity"]
333
+ air_pressure = ds_env.get("air_pressure", None)
334
+ sea_level_air_pressure = ds_env.get("sea_level_air_pressure", 101_325)
335
+ gas_constant_dry_air = ds_env.get("gas_constant_dry_air", 287.04)
336
+ lapse_rate = ds_env.get("lapse_rate", 0.0065)
337
+
338
+ # Retrieve air pressure at altitude if not specified
339
+ if air_pressure is None:
340
+ air_pressure = get_air_pressure_at_height(
341
+ altitude=altitude,
342
+ latitude=latitude,
343
+ temperature=temperature,
344
+ sea_level_air_pressure=sea_level_air_pressure,
345
+ lapse_rate=lapse_rate,
346
+ gas_constant_dry_air=gas_constant_dry_air,
347
+ )
348
+
349
+ # Retrieve vapour pressure (from relative humidity)
350
+ vapor_pressure = get_vapor_actual_pressure(
351
+ relative_humidity=relative_humidity,
352
+ temperature=temperature,
175
353
  )
354
+
355
+ # Retrieve air density
356
+ air_density = get_air_density(
357
+ temperature=temperature,
358
+ air_pressure=air_pressure,
359
+ vapor_pressure=vapor_pressure,
360
+ gas_constant_dry_air=gas_constant_dry_air,
361
+ )
362
+
363
+ # Retrieve water density
364
+ water_density = get_water_density(
365
+ temperature=temperature,
366
+ air_pressure=air_pressure,
367
+ sea_level_air_pressure=sea_level_air_pressure,
368
+ )
369
+
370
+ # Retrieve accurate gravitational_acceleration
371
+ g = get_gravitational_acceleration(altitude=altitude, latitude=latitude)
372
+
373
+ # Compute fall velocity
374
+ fall_velocity = get_raindrop_beard1976_fall_velocity(
375
+ diameter=diameter,
376
+ temperature=temperature,
377
+ air_density=air_density,
378
+ water_density=water_density,
379
+ g=g,
380
+ )
381
+
382
+ # drag_coefficient = get_drag_coefficient(diameter=diameter,
383
+ # air_density=air_density,
384
+ # water_density=water_density,
385
+ # g=g.
386
+ # fall_velocity=fall_velocity)
387
+
388
+ # Clip output
176
389
  fall_velocity = fall_velocity.clip(min=0, max=None)
177
390
  return fall_velocity
178
391
 
179
392
 
180
- RAINDROP_FALL_VELOCITY_MODELS = {
393
+ #### --------------------------------------------------------------------------------------
394
+ #### WRAPPERS
395
+ RAIN_FALL_VELOCITY_MODELS = {
181
396
  "Atlas1973": get_fall_velocity_atlas_1973,
182
- "Beard1976": get_fall_velocity_beard_1976,
397
+ "Beard1976": retrieve_raindrop_beard_fall_velocity,
183
398
  "Brandes2002": get_fall_velocity_brandes_2002,
184
399
  "Uplinger1981": get_fall_velocity_uplinger_1981,
185
400
  "VanDijk2002": get_fall_velocity_van_dijk_2002,
186
401
  }
187
402
 
188
403
 
189
- def available_raindrop_fall_velocity_models():
404
+ def available_rain_fall_velocity_models():
190
405
  """Return a list of the available raindrop fall velocity models."""
191
- return list(RAINDROP_FALL_VELOCITY_MODELS)
406
+ return list(RAIN_FALL_VELOCITY_MODELS)
192
407
 
193
408
 
194
- def check_raindrop_fall_velocity_model(model):
409
+ def check_rain_fall_velocity_model(model):
195
410
  """Check validity of the specified raindrop fall velocity model."""
196
- available_models = available_raindrop_fall_velocity_models()
411
+ available_models = available_rain_fall_velocity_models()
197
412
  if model not in available_models:
198
413
  raise ValueError(f"{model} is an invalid raindrop fall velocity model. Valid models: {available_models}.")
199
414
  return model
200
415
 
201
416
 
202
- def get_raindrop_fall_velocity_model(model):
417
+ def get_rain_fall_velocity_model(model):
203
418
  """Return the specified raindrop fall velocity model.
204
419
 
205
420
  Parameters
@@ -219,11 +434,11 @@ def get_raindrop_fall_velocity_model(model):
219
434
  This function serves as a wrapper to various raindrop fall velocity models.
220
435
  It returns the appropriate model based on the `model` parameter.
221
436
  """
222
- model = check_raindrop_fall_velocity_model(model)
223
- return RAINDROP_FALL_VELOCITY_MODELS[model]
437
+ model = check_rain_fall_velocity_model(model)
438
+ return RAIN_FALL_VELOCITY_MODELS[model]
224
439
 
225
440
 
226
- def get_raindrop_fall_velocity(diameter, model, ds_env=None):
441
+ def get_rain_fall_velocity(diameter, model, ds_env=None):
227
442
  """Calculate the fall velocity of raindrops based on their diameter.
228
443
 
229
444
  Parameters
@@ -261,7 +476,7 @@ def get_raindrop_fall_velocity(diameter, model, ds_env=None):
261
476
 
262
477
  """
263
478
  # Check valid method
264
- model = check_raindrop_fall_velocity_model(model)
479
+ model = check_rain_fall_velocity_model(model)
265
480
 
266
481
  # Copy diameter
267
482
  if isinstance(diameter, xr.DataArray):
@@ -270,24 +485,31 @@ def get_raindrop_fall_velocity(diameter, model, ds_env=None):
270
485
  diameter = np.atleast_1d(diameter)
271
486
  diameter = xr.DataArray(diameter, dims=DIAMETER_DIMENSION, coords={DIAMETER_DIMENSION: diameter.copy()})
272
487
 
273
- # Initialize ds_env if None and method == "Beard1976"
274
- if model == "Beard1976":
275
- if ds_env is None:
276
- ds_env = load_env_dataset()
488
+ # Initialize ds_env
489
+ if ds_env is None:
490
+ ds_env = load_env_dataset()
277
491
 
278
- # Ensure valid altitude and geolocation
279
- # - altitude required by Beard
280
- # - latitude required for gravity
281
- for coord in ["altitude", "latitude"]:
282
- ds_env = ensure_valid_geolocation(ds_env, coord=coord, errors="raise")
492
+ # Ensure valid altitude and geolocation
493
+ # - altitude required by Beard
494
+ # - latitude required for gravity
495
+ for coord in ["altitude", "latitude"]:
496
+ ds_env = ensure_valid_geolocation(ds_env, coord=coord, errors="raise")
283
497
 
284
498
  # Retrieve fall velocity
285
- func = get_raindrop_fall_velocity_model(model)
499
+ func = get_rain_fall_velocity_model(model)
286
500
  with suppress_warnings(): # e.g. when diameter = 0 for Beard1976
287
501
  fall_velocity = func(diameter, ds_env=ds_env) if model == "Beard1976" else func(diameter)
288
502
 
503
+ # Correct for altitude
504
+ if model != "Beard1976":
505
+ air_density_height = retrieve_air_density(ds_env)
506
+ air_density_sea_surface = 1.225 # kg/m3 (International Standard Atmosphere air density at sea level)
507
+ correction_factor = (air_density_sea_surface / air_density_height) ** (diameter * 0.025 + 0.375)
508
+ fall_velocity = fall_velocity * correction_factor
509
+
289
510
  # Set to NaN for diameter outside [0, 10)
290
511
  fall_velocity = fall_velocity.where(diameter < 10).where(diameter > 0)
512
+
291
513
  # Ensure fall velocity is > 0 to avoid division by zero
292
514
  # - Some models, at small diameter, can return negative/zero fall velocity
293
515
  fall_velocity = fall_velocity.where(fall_velocity > 0)
@@ -299,7 +521,7 @@ def get_raindrop_fall_velocity(diameter, model, ds_env=None):
299
521
  return fall_velocity.squeeze()
300
522
 
301
523
 
302
- def get_raindrop_fall_velocity_from_ds(ds, ds_env=None, model="Beard1976"):
524
+ def get_rain_fall_velocity_from_ds(ds, ds_env=None, model="Beard1976", diameter="diameter_bin_center"):
303
525
  """Compute the raindrop fall velocity.
304
526
 
305
527
  Parameters
@@ -349,6 +571,5 @@ def get_raindrop_fall_velocity_from_ds(ds, ds_env=None, model="Beard1976"):
349
571
  ds_env = load_env_dataset(ds)
350
572
 
351
573
  # Compute raindrop fall velocity
352
- fall_velocity = get_raindrop_fall_velocity(diameter=ds["diameter_bin_center"], model=model, ds_env=ds_env) # mn
353
-
574
+ fall_velocity = get_rain_fall_velocity(diameter=ds[diameter], model=model, ds_env=ds_env) # mn
354
575
  return fall_velocity