disdrodb 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. disdrodb/__init__.py +1 -1
  2. disdrodb/_config.py +1 -3
  3. disdrodb/_version.py +2 -2
  4. disdrodb/accessor/__init__.py +1 -1
  5. disdrodb/accessor/methods.py +18 -11
  6. disdrodb/api/checks.py +2 -4
  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 +15 -9
  11. disdrodb/api/path.py +1 -3
  12. disdrodb/cli/disdrodb_check_metadata_archive.py +2 -2
  13. disdrodb/cli/disdrodb_check_products_options.py +44 -0
  14. disdrodb/cli/disdrodb_create_summary.py +48 -22
  15. disdrodb/cli/disdrodb_create_summary_station.py +39 -18
  16. disdrodb/cli/disdrodb_data_archive_directory.py +1 -3
  17. disdrodb/cli/disdrodb_download_archive.py +45 -24
  18. disdrodb/cli/disdrodb_download_metadata_archive.py +27 -16
  19. disdrodb/cli/disdrodb_download_station.py +56 -26
  20. disdrodb/cli/disdrodb_initialize_station.py +40 -20
  21. disdrodb/cli/disdrodb_metadata_archive_directory.py +1 -3
  22. disdrodb/cli/disdrodb_open_data_archive.py +16 -11
  23. disdrodb/cli/disdrodb_open_logs_directory.py +29 -18
  24. disdrodb/cli/disdrodb_open_metadata_archive.py +25 -11
  25. disdrodb/cli/disdrodb_open_metadata_directory.py +32 -20
  26. disdrodb/cli/disdrodb_open_product_directory.py +38 -21
  27. disdrodb/cli/disdrodb_open_readers_directory.py +1 -3
  28. disdrodb/cli/disdrodb_run.py +189 -0
  29. disdrodb/cli/disdrodb_run_l0.py +55 -64
  30. disdrodb/cli/disdrodb_run_l0_station.py +47 -52
  31. disdrodb/cli/disdrodb_run_l0a.py +47 -45
  32. disdrodb/cli/disdrodb_run_l0a_station.py +38 -37
  33. disdrodb/cli/disdrodb_run_l0b.py +45 -45
  34. disdrodb/cli/disdrodb_run_l0b_station.py +37 -36
  35. disdrodb/cli/disdrodb_run_l0c.py +50 -47
  36. disdrodb/cli/disdrodb_run_l0c_station.py +41 -38
  37. disdrodb/cli/disdrodb_run_l1.py +49 -45
  38. disdrodb/cli/disdrodb_run_l1_station.py +40 -37
  39. disdrodb/cli/disdrodb_run_l2e.py +50 -45
  40. disdrodb/cli/disdrodb_run_l2e_station.py +41 -37
  41. disdrodb/cli/disdrodb_run_l2m.py +49 -45
  42. disdrodb/cli/disdrodb_run_l2m_station.py +40 -37
  43. disdrodb/cli/disdrodb_run_station.py +184 -0
  44. disdrodb/cli/disdrodb_upload_archive.py +45 -35
  45. disdrodb/cli/disdrodb_upload_station.py +39 -32
  46. disdrodb/configs.py +13 -8
  47. disdrodb/constants.py +4 -2
  48. disdrodb/data_transfer/__init__.py +1 -3
  49. disdrodb/data_transfer/download_data.py +38 -54
  50. disdrodb/data_transfer/upload_data.py +1 -3
  51. disdrodb/data_transfer/zenodo.py +1 -3
  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 +1 -14
  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 +17 -3
  74. disdrodb/etc/products/L2M/global.yaml +1 -1
  75. disdrodb/fall_velocity/__init__.py +46 -0
  76. disdrodb/fall_velocity/graupel.py +483 -0
  77. disdrodb/fall_velocity/hail.py +287 -0
  78. disdrodb/{l1/fall_velocity.py → fall_velocity/rain.py} +265 -50
  79. disdrodb/issue/__init__.py +1 -3
  80. disdrodb/issue/checks.py +3 -5
  81. disdrodb/issue/reader.py +1 -3
  82. disdrodb/issue/writer.py +1 -3
  83. disdrodb/l0/__init__.py +1 -1
  84. disdrodb/l0/check_configs.py +26 -17
  85. disdrodb/l0/check_standards.py +1 -3
  86. disdrodb/l0/configs/LPM/l0a_encodings.yml +0 -1
  87. disdrodb/l0/configs/LPM/l0b_cf_attrs.yml +0 -4
  88. disdrodb/l0/configs/LPM/l0b_encodings.yml +9 -9
  89. disdrodb/l0/configs/LPM/raw_data_format.yml +11 -11
  90. disdrodb/l0/configs/LPM_V0/bins_diameter.yml +103 -0
  91. disdrodb/l0/configs/LPM_V0/bins_velocity.yml +103 -0
  92. disdrodb/l0/configs/LPM_V0/l0a_encodings.yml +45 -0
  93. disdrodb/l0/configs/LPM_V0/l0b_cf_attrs.yml +180 -0
  94. disdrodb/l0/configs/LPM_V0/l0b_encodings.yml +410 -0
  95. disdrodb/l0/configs/LPM_V0/raw_data_format.yml +474 -0
  96. disdrodb/l0/configs/ODM470/bins_diameter.yml +643 -0
  97. disdrodb/l0/configs/ODM470/bins_velocity.yml +0 -0
  98. disdrodb/l0/configs/ODM470/l0a_encodings.yml +11 -0
  99. disdrodb/l0/configs/ODM470/l0b_cf_attrs.yml +46 -0
  100. disdrodb/l0/configs/ODM470/l0b_encodings.yml +106 -0
  101. disdrodb/l0/configs/ODM470/raw_data_format.yml +111 -0
  102. disdrodb/l0/configs/PARSIVEL/l0b_cf_attrs.yml +1 -1
  103. disdrodb/l0/configs/PARSIVEL/raw_data_format.yml +8 -8
  104. disdrodb/l0/configs/PARSIVEL2/raw_data_format.yml +9 -9
  105. disdrodb/l0/l0_reader.py +1 -3
  106. disdrodb/l0/l0a_processing.py +7 -5
  107. disdrodb/l0/l0b_nc_processing.py +2 -4
  108. disdrodb/l0/l0b_processing.py +27 -22
  109. disdrodb/l0/l0c_processing.py +37 -11
  110. disdrodb/l0/manuals/LPM_V0.pdf +0 -0
  111. disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +1 -1
  112. disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +1 -1
  113. disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +1 -1
  114. disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +1 -1
  115. disdrodb/l0/readers/LPM/GERMANY/DWD.py +190 -12
  116. disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +63 -14
  117. disdrodb/l0/readers/LPM/ITALY/GID_LPM_PI.py +279 -0
  118. disdrodb/l0/readers/LPM/ITALY/GID_LPM_T.py +279 -0
  119. disdrodb/l0/readers/LPM/ITALY/GID_LPM_W.py +3 -5
  120. disdrodb/l0/readers/LPM/KIT/CHWALA.py +1 -3
  121. disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_LPM_NC.py +1 -1
  122. disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_RWANDA_LPM_NC.py +103 -0
  123. disdrodb/l0/readers/LPM/NORWAY/HAUKELISETER_LPM.py +214 -0
  124. disdrodb/l0/readers/LPM/NORWAY/NMBU_LPM.py +206 -0
  125. disdrodb/l0/readers/LPM/SLOVENIA/ARSO.py +1 -3
  126. disdrodb/l0/readers/LPM/SLOVENIA/UL.py +1 -3
  127. disdrodb/l0/readers/LPM/SWITZERLAND/INNERERIZ_LPM.py +1 -3
  128. disdrodb/l0/readers/LPM/UK/DIVEN.py +1 -1
  129. disdrodb/l0/readers/LPM/UK/WITHWORTH_LPM.py +217 -0
  130. disdrodb/l0/readers/LPM/USA/CHARLESTON.py +227 -0
  131. disdrodb/l0/readers/{LPM → LPM_V0}/BELGIUM/ULIEGE.py +34 -52
  132. disdrodb/l0/readers/LPM_V0/ITALY/GID_LPM_V0.py +240 -0
  133. disdrodb/l0/readers/ODM470/OCEAN/OCEANRAIN.py +123 -0
  134. disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +1 -1
  135. disdrodb/l0/readers/PARSIVEL/BASQUECOUNTRY/EUSKALMET_OTT.py +1 -1
  136. disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +1 -3
  137. disdrodb/l0/readers/PARSIVEL/EPFL/ARCTIC_2021.py +1 -1
  138. disdrodb/l0/readers/PARSIVEL/EPFL/COMMON_2011.py +1 -1
  139. disdrodb/l0/readers/PARSIVEL/EPFL/DAVOS_2009_2011.py +1 -1
  140. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_2009.py +1 -1
  141. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2008.py +1 -1
  142. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +1 -1
  143. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2011.py +1 -1
  144. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2012.py +1 -1
  145. disdrodb/l0/readers/PARSIVEL/EPFL/GENEPI_2007.py +1 -1
  146. disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007.py +1 -1
  147. disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007_2.py +1 -1
  148. disdrodb/l0/readers/PARSIVEL/EPFL/HPICONET_2010.py +1 -1
  149. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP2.py +1 -1
  150. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +1 -1
  151. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP4.py +1 -1
  152. disdrodb/l0/readers/PARSIVEL/EPFL/LOCARNO_2018.py +1 -1
  153. disdrodb/l0/readers/PARSIVEL/EPFL/LOCARNO_2019.py +1 -1
  154. disdrodb/l0/readers/PARSIVEL/EPFL/PARADISO_2014.py +1 -1
  155. disdrodb/l0/readers/PARSIVEL/EPFL/PARSIVEL_2007.py +1 -1
  156. disdrodb/l0/readers/PARSIVEL/EPFL/PLATO_2019.py +1 -1
  157. disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +1 -1
  158. disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019_WJF.py +1 -1
  159. disdrodb/l0/readers/PARSIVEL/EPFL/RIETHOLZBACH_2011.py +1 -1
  160. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +1 -1
  161. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +1 -1
  162. disdrodb/l0/readers/PARSIVEL/EPFL/UNIL_2022.py +1 -1
  163. disdrodb/l0/readers/PARSIVEL/JAPAN/JMA.py +1 -1
  164. disdrodb/l0/readers/PARSIVEL/KOREA/ICEPOP_MSC.py +159 -0
  165. disdrodb/l0/readers/PARSIVEL/NASA/LPVEX.py +26 -14
  166. disdrodb/l0/readers/PARSIVEL/NASA/MC3E.py +2 -2
  167. disdrodb/l0/readers/PARSIVEL/NCAR/CCOPE_2015.py +1 -1
  168. disdrodb/l0/readers/PARSIVEL/NCAR/OWLES_MIPS.py +1 -1
  169. disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +1 -1
  170. disdrodb/l0/readers/PARSIVEL/NCAR/PLOWS_MIPS.py +1 -1
  171. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +1 -1
  172. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +1 -3
  173. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +1 -3
  174. disdrodb/l0/readers/PARSIVEL/SLOVENIA/UL.py +1 -1
  175. disdrodb/l0/readers/PARSIVEL2/ARM/ARM_PARSIVEL2.py +1 -1
  176. disdrodb/l0/readers/PARSIVEL2/BASQUECOUNTRY/EUSKALMET_OTT2.py +2 -2
  177. disdrodb/l0/readers/PARSIVEL2/BELGIUM/ILVO.py +1 -3
  178. disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +1 -1
  179. disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +1 -1
  180. disdrodb/l0/readers/PARSIVEL2/CANADA/UQAM_NC.py +1 -1
  181. disdrodb/l0/readers/PARSIVEL2/DENMARK/DTU.py +1 -1
  182. disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_nc.py +1 -1
  183. disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_raw.py +1 -1
  184. disdrodb/l0/readers/PARSIVEL2/FINLAND/FMI_PARSIVEL2.py +1 -1
  185. disdrodb/l0/readers/PARSIVEL2/FRANCE/ENPC_PARSIVEL2.py +1 -3
  186. disdrodb/l0/readers/PARSIVEL2/FRANCE/OSUG.py +1 -1
  187. disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +1 -3
  188. disdrodb/l0/readers/PARSIVEL2/GREECE/NOA.py +4 -3
  189. disdrodb/l0/readers/PARSIVEL2/ITALY/GID_PARSIVEL2.py +1 -3
  190. disdrodb/l0/readers/PARSIVEL2/ITALY/HYDROX.py +5 -3
  191. disdrodb/l0/readers/PARSIVEL2/JAPAN/PRECIP.py +155 -0
  192. disdrodb/l0/readers/PARSIVEL2/KIT/BURKINA_FASO.py +1 -1
  193. disdrodb/l0/readers/PARSIVEL2/KIT/TEAMX.py +1 -1
  194. disdrodb/l0/readers/PARSIVEL2/KOREA/ICEPOP_MSC.py +161 -0
  195. disdrodb/l0/readers/PARSIVEL2/{NASA/GCPEX.py → KOREA/ICEPOP_UCLM.py} +51 -31
  196. disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +1 -1
  197. disdrodb/l0/readers/PARSIVEL2/MPI/BCO_PARSIVEL2.py +15 -8
  198. disdrodb/l0/readers/PARSIVEL2/MPI/BOWTIE.py +9 -4
  199. disdrodb/l0/readers/PARSIVEL2/NASA/APU.py +31 -6
  200. disdrodb/l0/readers/PARSIVEL2/NASA/NSSTC.py +1 -1
  201. disdrodb/l0/readers/PARSIVEL2/NCAR/FARM_PARSIVEL2.py +1 -1
  202. disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +1 -1
  203. disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_MIPS.py +1 -1
  204. disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_MIPS.py +1 -1
  205. disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_PIPS.py +1 -1
  206. disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +2 -2
  207. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +1 -1
  208. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +1 -1
  209. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P1.py +1 -3
  210. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +1 -1
  211. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +1 -1
  212. disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT_NC.py +1 -1
  213. disdrodb/l0/readers/{PARSIVEL/NASA/PIERS.py → PARSIVEL2/NORWAY/UIB.py} +65 -31
  214. disdrodb/l0/readers/PARSIVEL2/PHILIPPINES/PAGASA.py +7 -6
  215. disdrodb/l0/readers/PARSIVEL2/SPAIN/CENER.py +1 -1
  216. disdrodb/l0/readers/PARSIVEL2/SPAIN/CR1000DL.py +1 -1
  217. disdrodb/l0/readers/PARSIVEL2/SPAIN/GRANADA.py +1 -3
  218. disdrodb/l0/readers/PARSIVEL2/SPAIN/LIAISE.py +1 -1
  219. disdrodb/l0/readers/PARSIVEL2/SWEDEN/SMHI.py +1 -1
  220. disdrodb/l0/readers/PARSIVEL2/USA/CSU.py +138 -0
  221. disdrodb/l0/readers/PARSIVEL2/USA/CW3E.py +49 -22
  222. disdrodb/l0/readers/PWS100/AUSTRIA/HOAL.py +1 -3
  223. disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100.py +1 -3
  224. disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100_SIRTA.py +1 -1
  225. disdrodb/l0/readers/{PARSIVEL/NASA/IFLOODS.py → RD80/BRAZIL/ATTO_RD80.py} +50 -36
  226. disdrodb/l0/readers/RD80/BRAZIL/CHUVA_RD80.py +1 -3
  227. disdrodb/l0/readers/RD80/BRAZIL/GOAMAZON_RD80.py +1 -3
  228. disdrodb/l0/readers/RD80/NCAR/CINDY_2011_RD80.py +1 -3
  229. disdrodb/l0/readers/RD80/NCAR/RELAMPAGO_RD80.py +1 -3
  230. disdrodb/l0/readers/RD80/NOAA/PSL_RD80.py +1 -3
  231. disdrodb/l0/readers/{SW250 → SWS250}/BELGIUM/KMI.py +2 -4
  232. disdrodb/l0/readers/template_reader_raw_netcdf_data.py +1 -3
  233. disdrodb/l0/readers/template_reader_raw_text_data.py +1 -3
  234. disdrodb/l0/standards.py +4 -5
  235. disdrodb/l0/template_tools.py +1 -3
  236. disdrodb/l1/__init__.py +1 -1
  237. disdrodb/l1/classification.py +913 -0
  238. disdrodb/l1/processing.py +36 -106
  239. disdrodb/l1/resampling.py +8 -3
  240. disdrodb/l1_env/__init__.py +1 -1
  241. disdrodb/l1_env/routines.py +6 -6
  242. disdrodb/l2/__init__.py +1 -1
  243. disdrodb/l2/empirical_dsd.py +61 -31
  244. disdrodb/l2/processing.py +327 -62
  245. disdrodb/metadata/checks.py +1 -3
  246. disdrodb/metadata/download.py +4 -4
  247. disdrodb/metadata/geolocation.py +1 -3
  248. disdrodb/metadata/info.py +1 -3
  249. disdrodb/metadata/manipulation.py +1 -3
  250. disdrodb/metadata/reader.py +1 -3
  251. disdrodb/metadata/search.py +1 -3
  252. disdrodb/metadata/standards.py +1 -3
  253. disdrodb/metadata/writer.py +1 -3
  254. disdrodb/physics/__init__.py +17 -0
  255. disdrodb/physics/atmosphere.py +272 -0
  256. disdrodb/physics/water.py +130 -0
  257. disdrodb/physics/wrappers.py +62 -0
  258. disdrodb/psd/__init__.py +1 -1
  259. disdrodb/psd/fitting.py +22 -9
  260. disdrodb/psd/models.py +1 -1
  261. disdrodb/routines/__init__.py +5 -1
  262. disdrodb/routines/l0.py +28 -18
  263. disdrodb/routines/l1.py +8 -6
  264. disdrodb/routines/l2.py +8 -4
  265. disdrodb/routines/options.py +116 -71
  266. disdrodb/routines/options_validation.py +728 -0
  267. disdrodb/routines/wrappers.py +431 -11
  268. disdrodb/scattering/__init__.py +1 -1
  269. disdrodb/scattering/axis_ratio.py +9 -6
  270. disdrodb/scattering/permittivity.py +8 -8
  271. disdrodb/scattering/routines.py +32 -14
  272. disdrodb/summary/__init__.py +1 -1
  273. disdrodb/summary/routines.py +146 -86
  274. disdrodb/utils/__init__.py +1 -1
  275. disdrodb/utils/archiving.py +16 -9
  276. disdrodb/utils/attrs.py +4 -3
  277. disdrodb/utils/cli.py +8 -10
  278. disdrodb/utils/compression.py +13 -13
  279. disdrodb/utils/dask.py +33 -14
  280. disdrodb/utils/dataframe.py +1 -3
  281. disdrodb/utils/decorators.py +1 -3
  282. disdrodb/utils/dict.py +1 -1
  283. disdrodb/utils/directories.py +3 -5
  284. disdrodb/utils/encoding.py +2 -4
  285. disdrodb/utils/event.py +1 -1
  286. disdrodb/utils/list.py +1 -3
  287. disdrodb/utils/logger.py +1 -3
  288. disdrodb/utils/manipulations.py +182 -6
  289. disdrodb/utils/pydantic.py +80 -0
  290. disdrodb/utils/routines.py +1 -3
  291. disdrodb/utils/subsetting.py +1 -1
  292. disdrodb/utils/time.py +3 -2
  293. disdrodb/utils/warnings.py +1 -3
  294. disdrodb/utils/writer.py +1 -3
  295. disdrodb/utils/xarray.py +30 -3
  296. disdrodb/utils/yaml.py +1 -3
  297. disdrodb/viz/__init__.py +1 -1
  298. disdrodb/viz/plots.py +197 -21
  299. {disdrodb-0.2.0.dist-info → disdrodb-0.3.0.dist-info}/METADATA +2 -2
  300. disdrodb-0.3.0.dist-info/RECORD +358 -0
  301. {disdrodb-0.2.0.dist-info → disdrodb-0.3.0.dist-info}/entry_points.txt +3 -0
  302. disdrodb/etc/products/L1/1MIN.yaml +0 -13
  303. disdrodb/etc/products/L1/LPM/1MIN.yaml +0 -13
  304. disdrodb/etc/products/L1/PARSIVEL/1MIN.yaml +0 -13
  305. disdrodb/etc/products/L1/PARSIVEL2/1MIN.yaml +0 -13
  306. disdrodb/etc/products/L1/PWS100/1MIN.yaml +0 -13
  307. disdrodb/etc/products/L1/RD80/1MIN.yaml +0 -13
  308. disdrodb/etc/products/L1/SWS250/1MIN.yaml +0 -13
  309. disdrodb/etc/products/L2M/10MIN.yaml +0 -12
  310. disdrodb/l1/beard_model.py +0 -618
  311. disdrodb/l1/filters.py +0 -203
  312. disdrodb-0.2.0.dist-info/RECORD +0 -312
  313. {disdrodb-0.2.0.dist-info → disdrodb-0.3.0.dist-info}/WHEEL +0 -0
  314. {disdrodb-0.2.0.dist-info → disdrodb-0.3.0.dist-info}/licenses/LICENSE +0 -0
  315. {disdrodb-0.2.0.dist-info → disdrodb-0.3.0.dist-info}/top_level.txt +0 -0
disdrodb/l1/processing.py CHANGED
@@ -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
@@ -18,35 +18,22 @@
18
18
 
19
19
  import xarray as xr
20
20
 
21
- from disdrodb.constants import DIAMETER_DIMENSION, VELOCITY_DIMENSION
22
- from disdrodb.l1.fall_velocity import get_raindrop_fall_velocity_from_ds
23
- from disdrodb.l1.filters import define_raindrop_spectrum_mask, filter_diameter_bins, filter_velocity_bins
21
+ from disdrodb.constants import DIAMETER_DIMENSION, METEOROLOGICAL_VARIABLES, VELOCITY_DIMENSION
22
+ from disdrodb.l1.classification import (
23
+ classify_raw_spectrum,
24
+ get_temperature,
25
+ map_precip_flag_to_precipitation_type,
26
+ )
24
27
  from disdrodb.l1.resampling import add_sample_interval
25
28
  from disdrodb.l1_env.routines import load_env_dataset
26
- from disdrodb.l2.empirical_dsd import ( # TODO: maybe move out of L2
27
- add_bins_metrics,
28
- get_min_max_diameter,
29
- )
29
+ from disdrodb.utils.manipulations import filter_diameter_bins
30
30
  from disdrodb.utils.time import ensure_sample_interval_in_seconds, infer_sample_interval
31
31
  from disdrodb.utils.writer import finalize_product
32
32
 
33
33
 
34
34
  def generate_l1(
35
35
  ds,
36
- # Fall velocity option
37
- fall_velocity_model="Beard1976",
38
- # Diameter-Velocity Filtering Options
39
- minimum_diameter=0,
40
- maximum_diameter=10,
41
- minimum_velocity=0,
42
- maximum_velocity=12,
43
- above_velocity_fraction=0.5,
44
- above_velocity_tolerance=None,
45
- below_velocity_fraction=0.5,
46
- below_velocity_tolerance=None,
47
- small_diameter_threshold=1, # 2
48
- small_velocity_threshold=2.5, # 3
49
- maintain_smallest_drops=True,
36
+ **kwargs, # noqa
50
37
  ):
51
38
  """Generate DISDRODB L1 Dataset from DISDRODB L0C Dataset.
52
39
 
@@ -54,31 +41,6 @@ def generate_l1(
54
41
  ----------
55
42
  ds : xarray.Dataset
56
43
  DISDRODB L0C dataset.
57
- fall_velocity_model : str, optional
58
- Method to compute fall velocity.
59
- The default method is ``"Beard1976"``.
60
- minimum_diameter : float, optional
61
- Minimum diameter for filtering. The default value is 0 mm.
62
- maximum_diameter : float, optional
63
- Maximum diameter for filtering. The default value is 10 mm.
64
- minimum_velocity : float, optional
65
- Minimum velocity for filtering. The default value is 0 m/s.
66
- maximum_velocity : float, optional
67
- Maximum velocity for filtering. The default value is 12 m/s.
68
- above_velocity_fraction : float, optional
69
- Fraction of drops above velocity threshold. The default value is 0.5.
70
- above_velocity_tolerance : float or None, optional
71
- Tolerance for above velocity filtering. The default value is ``None``.
72
- below_velocity_fraction : float, optional
73
- Fraction of drops below velocity threshold. The default value is 0.5.
74
- below_velocity_tolerance : float or None, optional
75
- Tolerance for below velocity filtering. The default value is ``None``.
76
- small_diameter_threshold : float, optional
77
- Threshold for small diameter drops. The default value is 1.
78
- small_velocity_threshold : float, optional
79
- Threshold for small velocity drops. The default value is 2.5.
80
- maintain_smallest_drops : bool, optional
81
- Whether to maintain the smallest drops. The default value is ``True``.
82
44
 
83
45
  Returns
84
46
  -------
@@ -95,7 +57,7 @@ def generate_l1(
95
57
  # - If not present, don't drop Parsivels first two bins
96
58
  sensor_name = attrs.get("sensor_name", "")
97
59
 
98
- # ---------------------------------------------------------------------------
60
+ # --------------------------------------------------------------------------
99
61
  # Retrieve sample interval
100
62
  # --> sample_interval is a coordinate of L0C products
101
63
  if "sample_interval" in ds:
@@ -104,14 +66,14 @@ def generate_l1(
104
66
  # This line is not called in the DISDRODB processing chain !
105
67
  sample_interval = infer_sample_interval(ds, verbose=False)
106
68
 
107
- # ---------------------------------------------------------------------------
69
+ # --------------------------------------------------------------------------
108
70
  # Retrieve ENV dataset or take defaults
109
71
  # - Used only for Beard fall velocity currently !
110
72
  # - It checks and includes default geolocation if missing
111
73
  # - For mobile disdrometer, infill missing geolocation with backward and forward filling
112
74
  ds_env = load_env_dataset(ds)
113
75
 
114
- # ---------------------------------------------------------------------------
76
+ # --------------------------------------------------------------------------
115
77
  # Initialize L1 dataset
116
78
  ds_l1 = xr.Dataset()
117
79
 
@@ -122,77 +84,45 @@ def generate_l1(
122
84
  ds_l1 = add_sample_interval(ds_l1, sample_interval=sample_interval)
123
85
 
124
86
  # Add optional variables to L1 dataset
125
- optional_variables = ["time_qc", "qc_resampling"]
87
+ optional_variables = ["qc_time", "qc_resampling", *METEOROLOGICAL_VARIABLES]
126
88
  for var in optional_variables:
127
89
  if var in ds:
128
90
  ds_l1[var] = ds[var]
129
91
 
130
- # -------------------------------------------------------------------------------------------
92
+ # --------------------------------------------------------------------------
131
93
  # Filter dataset by diameter and velocity bins
132
94
  if sensor_name in ["PARSIVEL", "PARSIVEL2"]:
133
95
  # - Remove first two bins because never reports data !
96
+ # - Could be removed also in L2E, but we save disk space here
134
97
  # - If not removed, can alter e.g. L2M model fitting
135
98
  ds_l1 = filter_diameter_bins(ds=ds_l1, minimum_diameter=0.2495) # it includes the 0.2495-0.3745 bin
136
99
 
137
- # - Filter diameter bins
138
- ds_l1 = filter_diameter_bins(ds=ds_l1, minimum_diameter=minimum_diameter, maximum_diameter=maximum_diameter)
139
- # - Filter velocity bins
140
- if has_velocity_dimension:
141
- ds_l1 = filter_velocity_bins(ds=ds_l1, minimum_velocity=minimum_velocity, maximum_velocity=maximum_velocity)
142
-
143
- # -------------------------------------------------------------------------------------------
144
- # Compute fall velocity
145
- ds_l1["fall_velocity"] = get_raindrop_fall_velocity_from_ds(ds=ds_l1, ds_env=ds_env, model=fall_velocity_model)
146
-
147
- # -------------------------------------------------------------------------------------------
148
- # Define filtering mask according to fall velocity
100
+ # --------------------------------------------------------------------------
101
+ # If (diameter, velocity) spectrum is available, run hydrometeor classification
149
102
  if has_velocity_dimension:
150
- mask = define_raindrop_spectrum_mask(
151
- drop_number=ds_l1["raw_drop_number"],
152
- fall_velocity=ds_l1["fall_velocity"],
153
- above_velocity_fraction=above_velocity_fraction,
154
- above_velocity_tolerance=above_velocity_tolerance,
155
- below_velocity_fraction=below_velocity_fraction,
156
- below_velocity_tolerance=below_velocity_tolerance,
157
- small_diameter_threshold=small_diameter_threshold,
158
- small_velocity_threshold=small_velocity_threshold,
159
- maintain_smallest_drops=maintain_smallest_drops,
103
+ temperature, snow_temperature_upper_limit = get_temperature(ds)
104
+ temperature = temperature.compute() if temperature is not None else None
105
+ ds_hc = classify_raw_spectrum(
106
+ ds=ds_l1,
107
+ ds_env=ds_env,
108
+ sensor_name=sensor_name,
109
+ sample_interval=sample_interval,
110
+ temperature=temperature,
111
+ rain_temperature_lower_limit=-5,
112
+ snow_temperature_upper_limit=snow_temperature_upper_limit,
160
113
  )
114
+ ds_l1.update(ds_hc)
161
115
 
162
- # -------------------------------------------------------------------------------------------
163
- # Retrieve drop number and drop_counts arrays
164
- if has_velocity_dimension:
165
- drop_number = ds_l1["raw_drop_number"].where(mask, 0) # 2D (diameter, velocity)
166
- drop_counts = drop_number.sum(dim=VELOCITY_DIMENSION) # 1D (diameter)
167
- drop_counts_raw = ds_l1["raw_drop_number"].sum(dim=VELOCITY_DIMENSION) # 1D (diameter)
116
+ # Otherwise, if no 2D spectrum, do nothing (temporary)
117
+ # --> Specialized QC for RD-80 or ODM-470 not yet implemented
168
118
  else:
169
- drop_number = ds_l1["raw_drop_number"] # 1D (diameter)
170
- drop_counts = ds_l1["raw_drop_number"] # 1D (diameter)
171
- drop_counts_raw = ds_l1["raw_drop_number"]
172
-
173
- # Add drop number and drop_counts
174
- ds_l1["drop_number"] = drop_number
175
- ds_l1["drop_counts"] = drop_counts
176
-
177
- # -------------------------------------------------------------------------------------------
178
- # Compute minimum and max drop diameter observed
179
- min_drop_diameter, max_drop_diameter = get_min_max_diameter(drop_counts)
180
-
181
- # Add drop statistics
182
- ds_l1["Dmin"] = min_drop_diameter
183
- ds_l1["Dmax"] = max_drop_diameter
184
- ds_l1["N"] = drop_counts.sum(dim=DIAMETER_DIMENSION)
185
- ds_l1["Nraw"] = drop_counts_raw.sum(dim=DIAMETER_DIMENSION)
186
- ds_l1["Nremoved"] = ds_l1["Nraw"] - ds_l1["N"]
187
-
188
- # Add bins statistics
189
- ds_l1 = add_bins_metrics(ds_l1)
190
-
191
- # -------------------------------------------------------------------------------------------
192
- # Add quality flags
193
- # TODO: snow_flags, insects_flag, ...
119
+ # If OceanRain ODM470 data, translate precip_flag to precipitation_type
120
+ if sensor_name == "ODM470" and "precip_flag" in ds:
121
+ ds_l1["precipitation_type"] = map_precip_flag_to_precipitation_type(ds["precip_flag"])
122
+ ds_l1["n_particles"] = ds_l1["raw_drop_number"].sum(dim=DIAMETER_DIMENSION)
123
+ pass
194
124
 
195
- #### ----------------------------------------------------------------------------.
125
+ #### ----------------------------------------------------------------------.
196
126
  #### Finalize dataset
197
127
  # Add global attributes
198
128
  ds_l1.attrs = attrs
disdrodb/l1/resampling.py CHANGED
@@ -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
@@ -170,6 +170,9 @@ def resample_dataset(ds, sample_interval, temporal_resolution):
170
170
  - The function updates the dataset attributes and the sample_interval coordinate.
171
171
 
172
172
  """
173
+ from disdrodb.constants import METEOROLOGICAL_VARIABLES
174
+ from disdrodb.l1.classification import TEMPERATURE_VARIABLES
175
+
173
176
  # --------------------------------------------------------------------------.
174
177
  # Ensure sample interval in seconds
175
178
  sample_interval = int(ensure_sample_interval_in_seconds(sample_interval))
@@ -244,6 +247,7 @@ def resample_dataset(ds, sample_interval, temporal_resolution):
244
247
 
245
248
  # Retrieve variables to average/sum
246
249
  # - ATTENTION: it will not resample non-dimensional time coordinates of the dataset !
250
+ # - precip_flag used for OceanRain ODM470 data
247
251
  var_to_average = ["fall_velocity"]
248
252
  var_to_cumulate = [
249
253
  "raw_drop_number",
@@ -255,8 +259,9 @@ def resample_dataset(ds, sample_interval, temporal_resolution):
255
259
  "Nremoved",
256
260
  "qc_resampling",
257
261
  ]
258
- var_to_min = ["Dmin"]
259
- var_to_max = ["Dmax", "time_qc"]
262
+ var_to_min = ["Dmin", *TEMPERATURE_VARIABLES]
263
+ met_vars = set(METEOROLOGICAL_VARIABLES) - set(TEMPERATURE_VARIABLES) # exclude air_temperature variable
264
+ var_to_max = ["Dmax", "qc_time", "precip_flag", *met_vars]
260
265
 
261
266
  # Retrieve available variables
262
267
  var_to_average = [var for var in var_to_average if var in ds]
@@ -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
@@ -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
@@ -30,15 +30,15 @@ DEFAULT_GEOLOCATION = {
30
30
 
31
31
 
32
32
  def get_default_environment_dataset():
33
- """Define defaults values for the ENV dataset."""
33
+ """Set International Standard Atmosphere values for the default ENV dataset."""
34
34
  ds_env = xr.Dataset()
35
- ds_env["sea_level_air_pressure"] = 101_325 # Pa
35
+ ds_env["sea_level_air_pressure"] = 101_325 # Pa # sea level
36
36
  ds_env["gas_constant_dry_air"] = 287.04 # J kg⁻¹ K⁻¹
37
- ds_env["lapse_rate"] = 0.0065 # K m⁻¹
37
+ ds_env["lapse_rate"] = 0.0065 # K m⁻¹ (6.5 deg/km)
38
38
  ds_env["relative_humidity"] = 0.95 # 0-1 !
39
- ds_env["temperature"] = 20 + 273.15 # K
39
+ ds_env["temperature"] = 15 + 273.15 # K
40
40
  ds_env["water_density"] = 1000 # kg m⁻³ (T == 10 --> 999.7, T == 20 --> 998.2)
41
- # get_water_density(temperature=temperature, air_pressure=air_pressure
41
+ # air density = 1.225 kg m⁻³ (if RH = 0) using retrieve_air_density(ds_env)
42
42
  return ds_env
43
43
 
44
44
 
disdrodb/l2/__init__.py CHANGED
@@ -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
@@ -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
@@ -25,6 +25,7 @@ import xarray as xr
25
25
 
26
26
  from disdrodb.api.checks import check_sensor_name
27
27
  from disdrodb.constants import DIAMETER_DIMENSION, VELOCITY_DIMENSION
28
+ from disdrodb.utils.time import ensure_sample_interval_in_seconds
28
29
  from disdrodb.utils.xarray import (
29
30
  remove_diameter_coordinates,
30
31
  remove_velocity_coordinates,
@@ -208,8 +209,26 @@ def add_bins_metrics(ds):
208
209
  return ds
209
210
 
210
211
 
211
- ####-------------------------------------------------------------------------------------------------------------------.
212
- #### DSD Spectrum, Concentration, Moments
212
+ ####------------------------------------------------------------------------------------------.
213
+ #### Sampling area and measurement interval
214
+ def get_sampling_area(sensor_name):
215
+ """Return the sampling area in m2 of the disdrometer."""
216
+ check_sensor_name(sensor_name)
217
+ area_dict = {
218
+ "PARSIVEL": 0.0054, # 54 cm2
219
+ "PARSIVEL2": 0.0054, # 54 cm2
220
+ "LPM": 0.0045, # 45 cm2
221
+ "LPM_V0": 0.0045, # 45 cm2
222
+ "ODM470": 0.00264, # 26.4 cm2
223
+ "PWS100": 0.004, # 40 cm2
224
+ "RD80": 0.005, # 50 cm2
225
+ "SWS250": 0.006504, # 65.04 cm2 (Ricardo Reinoso Rondinel, personal communication)
226
+ }
227
+ # SWS250
228
+ # - Table 29 of the manual that the sample volume is 400cm3, path length?
229
+ # - Distance between the end of the hood heaters is 291 mm.
230
+ # - Adding a factor of 1.5 for better representation of the Tx-Rx distance: L= 436 mm.
231
+ return area_dict[sensor_name]
213
232
 
214
233
 
215
234
  def get_effective_sampling_area(sensor_name, diameter):
@@ -220,29 +239,29 @@ def get_effective_sampling_area(sensor_name, diameter):
220
239
  check_sensor_name(sensor_name)
221
240
  if sensor_name in ["PARSIVEL", "PARSIVEL2"]:
222
241
  # Calculate sampling area for each diameter bin (S_i)
242
+ # - Parsivel remove margin fallers !
243
+ # - The effective sampling area decreases with increasing drop diameter
244
+ # sampling_area = 0.0054 # m2
223
245
  L = 180 / 1000 # Length of the Parsivel beam in m (180 mm)
224
246
  B = 30 / 1000 # Width of the Parsivel beam in m (30mm)
225
- sampling_area = L * (B - diameter / 2)
226
- return sampling_area
227
- if sensor_name == "LPM":
228
- # Calculate sampling area for each diameter bin (S_i)
229
- L = 228 / 1000 # Length of the Parsivel beam in m (228 mm)
230
- B = 20 / 1000 # Width of the Parsivel beam in m (20 mm)
231
- sampling_area = L * (B - diameter / 2)
247
+ sampling_area = L * (B - diameter / 2) # d_eq
232
248
  return sampling_area
249
+ return get_sampling_area(sensor_name)
250
+
251
+
252
+ def get_effective_sampling_interval(ds, sensor_name):
253
+ """Return the effective sample interval in seconds of the disdrometer."""
254
+ sample_interval = ensure_sample_interval_in_seconds(ds["sample_interval"]) # s
255
+ # Adapt sample interval for sensor duty cycle
233
256
  if sensor_name == "PWS100":
234
- sampling_area = 0.004 # m2 # TODO: L * (B - diameter / 2) ?
235
- return sampling_area
236
- if sensor_name == "RD80":
237
- sampling_area = 0.005 # m2
238
- return sampling_area
239
- if sensor_name == "SWS250": # TODO: L * (B - diameter / 2) ?
240
- # Table 29 of the manual that the sample volume is 400cm3, path length?
241
- # Distance between the end of the hood heaters is 291 mm.
242
- # Adding a factor of 1.5 for better representation of the Tx-Rx distance: L= 436 mm.
243
- sampling_area = 0.0091 # m2
244
- return sampling_area
245
- raise NotImplementedError(f"Effective sampling area for {sensor_name} must yet to be specified in the software.")
257
+ # PWS100 has a duty cycle of 9s on, 1s off
258
+ # - 9 seconds out of 10 are used for counting drops, 1 second is used to process data
259
+ sample_interval = sample_interval * (9 / 10)
260
+ return sample_interval
261
+
262
+
263
+ ####-------------------------------------------------------------------------------------------------------------------.
264
+ #### DSD Spectrum, Concentration, Moments
246
265
 
247
266
 
248
267
  def get_bin_dimensions(xr_obj):
@@ -303,15 +322,19 @@ def get_drop_number_concentration(drop_number, velocity, diameter_bin_width, sam
303
322
  # Ensure velocity is 2D (diameter, velocity)
304
323
  velocity = xr.ones_like(drop_number) * velocity
305
324
 
325
+ # Create a safe ratio: drop_number / velocity, but 0 where velocity is 0 or NaN
326
+ safe_ratio = drop_number / velocity
327
+ safe_ratio = safe_ratio.where((velocity != 0) & (~np.isnan(velocity)), 0)
328
+
306
329
  # Compute drop number concentration
307
330
  # - For disdrometer with velocity bins
308
331
  if VELOCITY_DIMENSION in drop_number.dims:
309
- drop_number_concentration = (drop_number / velocity).sum(dim=VELOCITY_DIMENSION, skipna=False) / (
332
+ drop_number_concentration = safe_ratio.sum(dim=VELOCITY_DIMENSION, skipna=False) / (
310
333
  sampling_area * diameter_bin_width * sample_interval
311
334
  )
312
335
  # - For impact disdrometers
313
336
  else:
314
- drop_number_concentration = (drop_number / velocity) / (sampling_area * diameter_bin_width * sample_interval)
337
+ drop_number_concentration = safe_ratio / (sampling_area * diameter_bin_width * sample_interval)
315
338
  return drop_number_concentration
316
339
 
317
340
 
@@ -1665,8 +1688,7 @@ def get_kinetic_energy_variables_from_drop_number(
1665
1688
  KEF = TKE / sample_interval * 3600
1666
1689
 
1667
1690
  # Compute Kinetic Energy per Rainfall Depth [J/m2/mm]
1668
- KED = KEF / R
1669
- KED = xr.where(R == 0, 0, KED) # Ensure KED is 0 when R (and thus drop number is 0)
1691
+ KED = xr.where(R == 0, 0, KEF / R) # Ensure KED is 0 when R (and thus drop number is 0)
1670
1692
 
1671
1693
  # Create dataset
1672
1694
  dict_vars = {
@@ -1731,6 +1753,10 @@ def compute_integral_parameters(
1731
1753
  - KED: Kinetic Energy per unit rainfall Depth [J·m⁻²·mm⁻¹].
1732
1754
  - KEF: Kinetic Energy Flux [J·m⁻²·h⁻¹].
1733
1755
  """
1756
+ # Ensure velocity does not contain NaN
1757
+ # --> e.g. when D > 10 mm --> Replace to 0
1758
+ velocity = velocity.fillna(0)
1759
+
1734
1760
  # Initialize dataset
1735
1761
  ds = xr.Dataset()
1736
1762
 
@@ -1760,15 +1786,15 @@ def compute_integral_parameters(
1760
1786
  moment=moment,
1761
1787
  )
1762
1788
 
1763
- # Compute Liquid Water Content (LWC) (W) [g/m3]
1764
- # ds["W"] = get_liquid_water_content(
1789
+ # Compute Liquid Water Content (LWC) [g/m3]
1790
+ # ds["LWC"] = get_liquid_water_content(
1765
1791
  # drop_number_concentration=drop_number_concentration,
1766
1792
  # diameter=diameter,
1767
1793
  # diameter_bin_width=diameter_bin_width,
1768
1794
  # water_density=water_density,
1769
1795
  # )
1770
1796
 
1771
- ds["W"] = get_liquid_water_content_from_moments(moment_3=ds["M3"], water_density=water_density)
1797
+ ds["LWC"] = get_liquid_water_content_from_moments(moment_3=ds["M3"], water_density=water_density)
1772
1798
 
1773
1799
  # Compute reflectivity in dBZ
1774
1800
  ds["Z"] = get_equivalent_reflectivity_factor(
@@ -1865,9 +1891,13 @@ def compute_spectrum_parameters(
1865
1891
  Dataset containing the following spectrum:
1866
1892
  - KE_spectrum : Kinetic Energy spectrum [J/m2/mm]
1867
1893
  - R_spectrum : Rain Rate spectrum [mm/h/mm]
1868
- - W_spectrum : Mass spectrum [g/m3/mm]
1894
+ - LWC_spectrum : Mass spectrum [g/m3/mm]
1869
1895
  - Z_spectrum : Reflectivity spectrum [dBZ of mm6/m3/mm]
1870
1896
  """
1897
+ # Ensure velocity does not contain NaN
1898
+ # --> e.g. when D > 10 mm --> Replace to 0
1899
+ velocity = velocity.fillna(0)
1900
+
1871
1901
  # Initialize dataset
1872
1902
  ds = xr.Dataset()
1873
1903
  ds["KE_spectrum"] = get_kinetic_energy_spectrum(
@@ -1878,7 +1908,7 @@ def compute_spectrum_parameters(
1878
1908
  water_density=water_density,
1879
1909
  )
1880
1910
  ds["R_spectrum"] = get_rain_rate_spectrum(drop_number_concentration, velocity=velocity, diameter=diameter)
1881
- ds["W_spectrum"] = get_liquid_water_spectrum(
1911
+ ds["LWC_spectrum"] = get_liquid_water_spectrum(
1882
1912
  drop_number_concentration,
1883
1913
  diameter=diameter,
1884
1914
  water_density=water_density,