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
disdrodb/utils/cli.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
@@ -105,7 +103,7 @@ def click_data_archive_dir_option(function: object):
105
103
  type=str,
106
104
  show_default=True,
107
105
  default=None,
108
- help="DISDRODB base directory",
106
+ help="DISDRODB Data Archive Directory. Format: <...>/DISDRODB",
109
107
  )(function)
110
108
  return function
111
109
 
@@ -123,7 +121,7 @@ def click_metadata_archive_dir_option(function: object):
123
121
  type=str,
124
122
  show_default=True,
125
123
  default=None,
126
- help="DISDRODB Metadata Archive Directory",
124
+ help="DISDRODB Metadata Archive Directory. Format: <...>/DISDRODB-METADATA/DISDRODB",
127
125
  )(function)
128
126
  return function
129
127
 
@@ -233,14 +231,14 @@ def click_l0_archive_options(function: object):
233
231
  type=bool,
234
232
  show_default=True,
235
233
  default=False,
236
- help="If true, remove all source L0B files once L0B concatenation is terminated.",
234
+ help="If True, remove L0B files after L0C.",
237
235
  )(function)
238
236
  function = click.option(
239
237
  "--remove_l0a",
240
238
  type=bool,
241
239
  show_default=True,
242
240
  default=False,
243
- help="If true, remove the L0A files once the L0B processing is terminated.",
241
+ help="If True, remove L0A files after L0B.",
244
242
  )(function)
245
243
  function = click.option(
246
244
  "-l0c",
@@ -248,7 +246,7 @@ def click_l0_archive_options(function: object):
248
246
  type=bool,
249
247
  show_default=True,
250
248
  default=True,
251
- help="Perform L0C processing.",
249
+ help="Run L0C processing",
252
250
  )(function)
253
251
  function = click.option(
254
252
  "-l0b",
@@ -256,7 +254,7 @@ def click_l0_archive_options(function: object):
256
254
  type=bool,
257
255
  show_default=True,
258
256
  default=True,
259
- help="Perform L0B processing.",
257
+ help="Run L0B processing",
260
258
  )(function)
261
259
  function = click.option(
262
260
  "-l0a",
@@ -264,6 +262,6 @@ def click_l0_archive_options(function: object):
264
262
  type=bool,
265
263
  show_default=True,
266
264
  default=True,
267
- help="Perform L0A processing.",
265
+ help="Run L0A processing",
268
266
  )(function)
269
267
  return function
@@ -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
@@ -25,7 +23,6 @@ import shutil
25
23
  import subprocess
26
24
  import tempfile
27
25
  import zipfile
28
- from typing import Optional
29
26
 
30
27
  from disdrodb.api.checks import check_data_archive_dir
31
28
  from disdrodb.api.path import define_station_dir
@@ -190,13 +187,13 @@ def compress_station_files(
190
187
  # Get list of files inside the station directory (in all nested directories)
191
188
  filepaths = list_files(station_dir, recursive=True)
192
189
  for filepath in filepaths:
193
- _ = _compress_file(filepath, method, skip=skip)
190
+ _ = compress_file(filepath, method, skip=skip)
194
191
 
195
192
  print(f"All files of {data_source} {campaign_name} {station_name} have been compressed.")
196
193
  print("Please now remember to update the glob_pattern of the reader ¨!")
197
194
 
198
195
 
199
- def _compress_file(filepath: str, method: str, skip: bool) -> str:
196
+ def compress_file(filepath: str, method: str, skip: bool) -> str:
200
197
  """Compress a file and delete the original.
201
198
 
202
199
  If the file is already compressed, it is not compressed again.
@@ -230,9 +227,9 @@ def _compress_file(filepath: str, method: str, skip: bool) -> str:
230
227
  archive_name = os.path.basename(filepath) + extension
231
228
  compressed_filepath = os.path.join(os.path.dirname(filepath), archive_name)
232
229
  compress_file_function = {
233
- "zip": _compress_file_zip,
234
- "gzip": _compress_file_gzip,
235
- "bzip2": _compress_file_bzip2,
230
+ "zip": compress_file_zip,
231
+ "gzip": compress_file_gzip,
232
+ "bzip2": compress_file_bzip2,
236
233
  }[method]
237
234
 
238
235
  compress_file_function(filepath, compressed_filepath)
@@ -241,7 +238,7 @@ def _compress_file(filepath: str, method: str, skip: bool) -> str:
241
238
  return compressed_filepath
242
239
 
243
240
 
244
- def _check_file_compression(filepath: str) -> Optional[str]:
241
+ def _check_file_compression(filepath: str) -> str | None:
245
242
  """Check the method used to compress a raw text file.
246
243
 
247
244
  From https://stackoverflow.com/questions/13044562/python-mechanism-to-identify-compressed-file-type-and-uncompress
@@ -271,7 +268,7 @@ def _check_file_compression(filepath: str) -> Optional[str]:
271
268
  return None
272
269
 
273
270
 
274
- def _compress_file_zip(filepath: str, compressed_filepath: str) -> None:
271
+ def compress_file_zip(filepath: str, compressed_filepath: str) -> None:
275
272
  """Compress a single file into a zip archive.
276
273
 
277
274
  Parameters
@@ -287,7 +284,7 @@ def _compress_file_zip(filepath: str, compressed_filepath: str) -> None:
287
284
  zipf.write(filepath, os.path.basename(filepath))
288
285
 
289
286
 
290
- def _compress_file_gzip(filepath: str, compressed_filepath: str) -> None:
287
+ def compress_file_gzip(filepath: str, compressed_filepath: str) -> None:
291
288
  """Compress a single file into a gzip archive.
292
289
 
293
290
  Parameters
@@ -303,7 +300,7 @@ def _compress_file_gzip(filepath: str, compressed_filepath: str) -> None:
303
300
  f_out.writelines(f_in)
304
301
 
305
302
 
306
- def _compress_file_bzip2(filepath: str, compressed_filepath: str) -> None:
303
+ def compress_file_bzip2(filepath: str, compressed_filepath: str) -> None:
307
304
  """Compress a single file into a bzip2 archive.
308
305
 
309
306
  Parameters
@@ -0,0 +1,45 @@
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 coordinates utilities."""
18
+
19
+
20
+ def add_dataset_crs_coords(xr_obj):
21
+ """Add a CF-compliant CRS (WGS84) to an xarray.Dataset."""
22
+ import xarray as xr
23
+
24
+ crs_wkt = (
25
+ 'GEOGCRS["WGS 84",'
26
+ 'DATUM["World Geodetic System 1984",'
27
+ 'ELLIPSOID["WGS 84",6378137,298.257223563, LENGTHUNIT["metre",1]]],'
28
+ 'PRIMEM["Greenwich",0, ANGLEUNIT["degree",0.0174532925199433]],'
29
+ "CS[ellipsoidal,2],"
30
+ 'AXIS["geodetic latitude",north, ANGLEUNIT["degree",0.0174532925199433]],'
31
+ 'AXIS["geodetic longitude",east, ANGLEUNIT["degree",0.0174532925199433]],'
32
+ 'UNIT["degree",0.0174532925199433]'
33
+ )
34
+ da_crs = xr.DataArray(
35
+ 0,
36
+ attrs={
37
+ "grid_mapping_name": "latitude_longitude",
38
+ "crs_wkt": crs_wkt,
39
+ "epsg_code": "EPSG:4326",
40
+ "semi_major_axis": 6378137.0,
41
+ "inverse_flattening": 298.257223563,
42
+ "longitude_of_prime_meridian": 0.0,
43
+ },
44
+ )
45
+ return xr_obj.assign_coords({"crs": da_crs})
disdrodb/utils/dask.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
@@ -17,6 +15,7 @@
17
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
16
  # -----------------------------------------------------------------------------.
19
17
  """Utilities for Dask Distributed Computations."""
18
+
20
19
  import logging
21
20
  import os
22
21
 
@@ -30,9 +29,9 @@ def check_parallel_validity(parallel):
30
29
  scheduler = dask.config.get("scheduler", None)
31
30
  if scheduler is None:
32
31
  return parallel
33
- if scheduler in ["synchronous", "threads"]:
32
+ if scheduler in ["synchronous", "threads", "single-threaded"]:
34
33
  return False
35
- if scheduler == "distributed":
34
+ if scheduler in ["distributed", "dask.distributed"]:
36
35
  from dask.distributed import default_client
37
36
 
38
37
  client = default_client()
@@ -62,6 +61,8 @@ def initialize_dask_cluster(minimum_memory=None):
62
61
  import psutil
63
62
 
64
63
  # Silence dask warnings
64
+ # dask.config.set({'distributed.worker.multiprocessing-method': 'forkserver'})
65
+ # dask.config.set({"distributed.worker.multiprocessing-method": "spawn"})
65
66
  # dask.config.set({"logging.distributed": "error"})
66
67
  # Import dask.distributed after setting the config
67
68
  from dask.distributed import Client, LocalCluster
@@ -71,6 +72,7 @@ def initialize_dask_cluster(minimum_memory=None):
71
72
  os.environ["HDF5_USE_FILE_LOCKING"] = "FALSE"
72
73
 
73
74
  # Retrieve the number of processes to run
75
+ # --> If DASK_NUM_WORKERS is not set, use all CPUs minus 2
74
76
  available_workers = os.cpu_count() - 2 # if not set, all CPUs minus 2
75
77
  num_workers = dask.config.get("num_workers", available_workers)
76
78
 
@@ -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
@@ -17,6 +15,7 @@
17
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
16
  # -----------------------------------------------------------------------------.
19
17
  """Dataframe utilities."""
18
+
20
19
  import numpy as np
21
20
  import pandas as pd
22
21
 
@@ -209,7 +208,7 @@ def compute_1d_histogram(df, column, variables=None, bins=10, labels=None, prefi
209
208
 
210
209
  # Reset index and add coordinates/labels
211
210
  df_stats = df_stats.reset_index()
212
- df_stats[f"{column}"] = pd.Categorical(df_stats[f"{column}_binned"].map(dict(zip(intervals, coords, strict=False))))
211
+ df_stats[f"{column}"] = pd.Categorical(df_stats[f"{column}_binned"].map(dict(zip(intervals, coords, strict=True))))
213
212
  df_stats = df_stats.drop(columns=f"{column}_binned")
214
213
 
215
214
  return df_stats
@@ -375,8 +374,8 @@ def compute_2d_histogram(
375
374
 
376
375
  # Reset index and set new coordinates
377
376
  df_stats = df_stats.reset_index()
378
- df_stats[f"{x}"] = pd.Categorical(df_stats[f"{x}_binned"].map(dict(zip(x_intervals, x_coords, strict=False))))
379
- df_stats[f"{y}"] = pd.Categorical(df_stats[f"{y}_binned"].map(dict(zip(y_intervals, y_coords, strict=False))))
377
+ df_stats[f"{x}"] = pd.Categorical(df_stats[f"{x}_binned"].map(dict(zip(x_intervals, x_coords, strict=True))))
378
+ df_stats[f"{y}"] = pd.Categorical(df_stats[f"{y}_binned"].map(dict(zip(y_intervals, y_coords, strict=True))))
380
379
 
381
380
  # Set new MultiIndex with coordinates
382
381
  df_stats = df_stats.set_index([f"{x}", f"{y}"])
@@ -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
@@ -17,6 +15,7 @@
17
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
16
  # -----------------------------------------------------------------------------.
19
17
  """DISDRODB decorators."""
18
+
20
19
  import functools
21
20
  import importlib
22
21
  import uuid
@@ -86,7 +85,7 @@ def single_threaded_if_parallel(function):
86
85
  if parallel:
87
86
  # Call function with single thread
88
87
  # with dask.config.set(scheduler='single-threaded'):
89
- with dask.config.set(scheduler="synchronous"):
88
+ with dask.config.set(scheduler="single-threaded"): # "synchronous"
90
89
  result = function(*args, **kwargs)
91
90
  else:
92
91
  # Else run the function as usual
disdrodb/utils/dict.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,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
@@ -17,13 +15,13 @@
17
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
16
  # -----------------------------------------------------------------------------.
19
17
  """Define utilities for Directory/File Checks/Creation/Deletion."""
18
+
20
19
  import glob
21
20
  import logging
22
21
  import os
23
22
  import pathlib
24
23
  import shutil
25
24
  import subprocess
26
- from typing import Union
27
25
 
28
26
  from disdrodb.utils.list import flatten_list
29
27
  from disdrodb.utils.logger import log_info
@@ -81,7 +79,7 @@ def check_glob_pattern(pattern: str) -> None:
81
79
  return pattern
82
80
 
83
81
 
84
- def check_glob_patterns(patterns: Union[str, list]) -> list:
82
+ def check_glob_patterns(patterns: str | list) -> list:
85
83
  """Check if glob patterns are valids."""
86
84
  if not isinstance(patterns, (str, list)):
87
85
  raise ValueError("'glob_patterns' must be a str or list of strings.")
@@ -212,7 +210,7 @@ def is_empty_directory(path, skip_hidden=True):
212
210
  return len(paths) == 0
213
211
 
214
212
 
215
- def _remove_file_or_directories(path, logger=None):
213
+ def remove_file_or_directories(path, logger=None):
216
214
  """Return the file/directory or subdirectories tree of ``path``.
217
215
 
218
216
  Use this function with caution.
@@ -259,7 +257,7 @@ def remove_if_exists(path: str, force: bool = False, logger=None) -> None:
259
257
 
260
258
  # If force=True, remove the file/directory or subdirectories and files !
261
259
  try:
262
- _remove_file_or_directories(path, logger=logger)
260
+ remove_file_or_directories(path, logger=logger)
263
261
  except Exception as e:
264
262
  msg = f"Can not delete file(s) at {path}. The error is: {e}"
265
263
  raise ValueError(msg)
@@ -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
@@ -17,6 +15,7 @@
17
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
16
  # -----------------------------------------------------------------------------.
19
17
  """DISDRODB netCDF4 encoding utilities."""
18
+
20
19
  import os
21
20
 
22
21
  import numpy as np
@@ -128,7 +127,7 @@ def rechunk_dataset(ds: xr.Dataset, encodings_dict: dict) -> xr.Dataset:
128
127
  chunks = encodings_dict[var].get("chunksizes", None) # .pop("chunksizes", None)
129
128
  if chunks is not None:
130
129
  dims = list(ds[var].dims)
131
- chunks_dict = dict(zip(dims, chunks))
130
+ chunks_dict = dict(zip(dims, chunks, strict=True))
132
131
  ds[var] = ds[var].chunk(chunks_dict)
133
132
  ds[var].encoding["chunksizes"] = chunks
134
133
  return ds
@@ -144,7 +143,7 @@ def get_time_encoding() -> dict:
144
143
  """
145
144
  encoding = {}
146
145
  encoding["dtype"] = "int64" # if float trailing sub-seconds values
147
- encoding["fillvalue"] = np.iinfo(np.int64).max
146
+ encoding["_FillValue"] = np.iinfo(np.int64).max
148
147
  encoding["units"] = EPOCH
149
148
  encoding["calendar"] = "proleptic_gregorian"
150
149
  return encoding
disdrodb/utils/event.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
disdrodb/utils/list.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
disdrodb/utils/logger.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
@@ -19,11 +17,184 @@
19
17
  """Include functions helping for DISDRODB product manipulations."""
20
18
 
21
19
  import numpy as np
20
+ import xarray as xr
22
21
 
23
- from disdrodb.constants import DIAMETER_DIMENSION
22
+ from disdrodb.constants import DIAMETER_DIMENSION, VELOCITY_DIMENSION
24
23
  from disdrodb.utils.xarray import unstack_datarray_dimension
25
24
 
26
25
 
26
+ def define_diameter_datarray(bounds):
27
+ """Define diameter DataArray."""
28
+ diameters_bin_lower = bounds[:-1]
29
+ diameters_bin_upper = bounds[1:]
30
+ diameters_bin_width = diameters_bin_upper - diameters_bin_lower
31
+ diameters_bin_center = diameters_bin_lower + diameters_bin_width / 2
32
+ da = xr.DataArray(
33
+ diameters_bin_center,
34
+ dims="diameter_bin_center",
35
+ coords={
36
+ "diameter_bin_width": ("diameter_bin_center", diameters_bin_width),
37
+ "diameter_bin_lower": ("diameter_bin_center", diameters_bin_lower),
38
+ "diameter_bin_upper": ("diameter_bin_center", diameters_bin_upper),
39
+ "diameter_bin_center": ("diameter_bin_center", diameters_bin_center),
40
+ },
41
+ )
42
+ return da
43
+
44
+
45
+ def define_velocity_datarray(bounds):
46
+ """Define velocity DataArray."""
47
+ velocitys_bin_lower = bounds[:-1]
48
+ velocitys_bin_upper = bounds[1:]
49
+ velocitys_bin_width = velocitys_bin_upper - velocitys_bin_lower
50
+ velocitys_bin_center = velocitys_bin_lower + velocitys_bin_width / 2
51
+ da = xr.DataArray(
52
+ velocitys_bin_center,
53
+ dims="velocity_bin_center",
54
+ coords={
55
+ "velocity_bin_width": ("velocity_bin_center", velocitys_bin_width),
56
+ "velocity_bin_lower": ("velocity_bin_center", velocitys_bin_lower),
57
+ "velocity_bin_upper": ("velocity_bin_center", velocitys_bin_upper),
58
+ "velocity_bin_center": ("velocity_bin_center", velocitys_bin_center),
59
+ },
60
+ )
61
+ return da
62
+
63
+
64
+ def define_diameter_array(diameter_min=0, diameter_max=10, diameter_spacing=0.05):
65
+ """
66
+ Define an array of diameters and their corresponding bin properties.
67
+
68
+ Parameters
69
+ ----------
70
+ diameter_min : float, optional
71
+ The minimum diameter value. The default value is 0 mm.
72
+ diameter_max : float, optional
73
+ The maximum diameter value. The default value is 10 mm.
74
+ diameter_spacing : float, optional
75
+ The spacing between diameter values. The default value is 0.05 mm.
76
+
77
+ Returns
78
+ -------
79
+ xr.DataArray
80
+ A DataArray containing the center of each diameter bin, with coordinates for
81
+ the bin width, lower bound, upper bound, and center.
82
+
83
+ """
84
+ diameters_bounds = np.arange(diameter_min, diameter_max + diameter_spacing / 2, step=diameter_spacing)
85
+ return define_diameter_datarray(diameters_bounds)
86
+
87
+
88
+ def define_velocity_array(velocity_min=0, velocity_max=10, velocity_spacing=0.05):
89
+ """
90
+ Define an array of velocities and their corresponding bin properties.
91
+
92
+ Parameters
93
+ ----------
94
+ velocity_min : float, optional
95
+ The minimum velocity value. The default value is 0 mm.
96
+ velocity_max : float, optional
97
+ The maximum velocity value. The default value is 10 mm.
98
+ velocity_spacing : float, optional
99
+ The spacing between velocity values. The default value is 0.05 mm.
100
+
101
+ Returns
102
+ -------
103
+ xr.DataArray
104
+ A DataArray containing the center of each velocity bin, with coordinates for
105
+ the bin width, lower bound, upper bound, and center.
106
+
107
+ """
108
+ velocitys_bounds = np.arange(velocity_min, velocity_max + velocity_spacing / 2, step=velocity_spacing)
109
+ return define_velocity_datarray(velocitys_bounds)
110
+
111
+
112
+ def filter_diameter_bins(ds, minimum_diameter=None, maximum_diameter=None):
113
+ """
114
+ Filter the dataset to include only diameter bins within specified bounds.
115
+
116
+ Parameters
117
+ ----------
118
+ ds : xarray.Dataset
119
+ The dataset containing diameter bin data.
120
+ minimum_diameter : float, optional
121
+ The minimum diameter to be included, in millimeters.
122
+ Defaults to the minimum value in `ds["diameter_bin_lower"]`.
123
+ maximum_diameter : float, optional
124
+ The maximum diameter to be included, in millimeters.
125
+ Defaults to the maximum value in `ds["diameter_bin_upper"]`.
126
+
127
+ Returns
128
+ -------
129
+ xarray.Dataset
130
+ The filtered dataset containing only the specified diameter bins.
131
+ """
132
+ # Put data into memory
133
+ ds["diameter_bin_lower"] = ds["diameter_bin_lower"].compute()
134
+ ds["diameter_bin_upper"] = ds["diameter_bin_upper"].compute()
135
+
136
+ # Initialize default arguments
137
+ if minimum_diameter is None:
138
+ minimum_diameter = ds["diameter_bin_lower"].min().item()
139
+ if maximum_diameter is None:
140
+ maximum_diameter = ds["diameter_bin_upper"].max().item()
141
+
142
+ # Select bins which overlap the specified diameters
143
+ valid_indices = np.logical_and(
144
+ ds["diameter_bin_upper"] > minimum_diameter,
145
+ ds["diameter_bin_lower"] < maximum_diameter,
146
+ )
147
+ ds = ds.isel({DIAMETER_DIMENSION: valid_indices})
148
+
149
+ if ds.sizes[DIAMETER_DIMENSION] == 0:
150
+ msg = f"Filtering using {minimum_diameter=} removes all diameter bins."
151
+ raise ValueError(msg)
152
+ return ds
153
+
154
+
155
+ def filter_velocity_bins(ds, minimum_velocity=None, maximum_velocity=None):
156
+ """
157
+ Filter the dataset to include only velocity bins within specified bounds.
158
+
159
+ Parameters
160
+ ----------
161
+ ds : xarray.Dataset
162
+ The dataset containing velocity bin data.
163
+ minimum_velocity : float, optional
164
+ The minimum velocity to include in the filter, in meters per second.
165
+ Defaults to the minimum value in `ds["velocity_bin_lower"]`.
166
+ maximum_velocity : float, optional
167
+ The maximum velocity to include in the filter, in meters per second.
168
+ Defaults to the maximum value in `ds["velocity_bin_upper"]`.
169
+
170
+ Returns
171
+ -------
172
+ xarray.Dataset
173
+ The filtered dataset containing only the specified velocity bins.
174
+ """
175
+ # Put data into memory
176
+ ds["velocity_bin_lower"] = ds["velocity_bin_lower"].compute()
177
+ ds["velocity_bin_upper"] = ds["velocity_bin_upper"].compute()
178
+
179
+ # Initialize default arguments
180
+ if minimum_velocity is None:
181
+ minimum_velocity = ds["velocity_bin_lower"].min().item()
182
+ if maximum_velocity is None:
183
+ maximum_velocity = ds["velocity_bin_upper"].max().item()
184
+
185
+ # Select bins which overlap the specified velocities
186
+ valid_indices = np.logical_and(
187
+ ds["velocity_bin_upper"] > minimum_velocity,
188
+ ds["velocity_bin_lower"] < maximum_velocity,
189
+ )
190
+
191
+ ds = ds.isel({VELOCITY_DIMENSION: valid_indices})
192
+ if ds.sizes[VELOCITY_DIMENSION] == 0:
193
+ msg = f"Filtering using {minimum_velocity=} removes all velocity bins."
194
+ raise ValueError(msg)
195
+ return ds
196
+
197
+
27
198
  def get_diameter_bin_edges(ds):
28
199
  """Retrieve diameter bin edges."""
29
200
  bin_edges = np.append(ds["diameter_bin_lower"].to_numpy(), ds["diameter_bin_upper"].to_numpy()[-1])