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

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