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/routines/l1.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
@@ -42,6 +40,8 @@ from disdrodb.configs import (
42
40
  get_folder_partitioning,
43
41
  get_metadata_archive_dir,
44
42
  )
43
+ from disdrodb.constants import METEOROLOGICAL_VARIABLES
44
+ from disdrodb.l1.classification import TEMPERATURE_VARIABLES
45
45
  from disdrodb.l1.processing import generate_l1
46
46
  from disdrodb.l1.resampling import resample_dataset
47
47
  from disdrodb.metadata.reader import read_station_metadata
@@ -145,11 +145,14 @@ def _generate_l1(
145
145
  ):
146
146
  """Define L1 product processing."""
147
147
  # Open the L0C netCDF files
148
+ # - precip_flag used for OceanRain ODM470 data only
149
+ # - Missing variables in dataset are simply not selected
150
+ variables = ["raw_drop_number", "qc_time", "precip_flag", *TEMPERATURE_VARIABLES, *METEOROLOGICAL_VARIABLES]
148
151
  ds = open_netcdf_files(
149
152
  filepaths,
150
153
  start_time=start_time,
151
154
  end_time=end_time,
152
- variables=["raw_drop_number", "time_qc"],
155
+ variables=variables,
153
156
  parallel=False,
154
157
  compute=True,
155
158
  )
@@ -313,7 +316,7 @@ def run_l1_station(
313
316
  return
314
317
 
315
318
  # -------------------------------------------------------------------------.
316
- # Read station metadata and retrieve sensor name
319
+ # Read station metadata and sensor name
317
320
  metadata = read_station_metadata(
318
321
  metadata_archive_dir=metadata_archive_dir,
319
322
  data_source=data_source,
@@ -347,7 +350,6 @@ def run_l1_station(
347
350
 
348
351
  # Retrieve product options
349
352
  product_options = l1_processing_options.get_product_options(temporal_resolution)
350
- product_options = product_options.get("product_options")
351
353
 
352
354
  # ------------------------------------------------------------------.
353
355
  # Create product directory
disdrodb/routines/l2.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
@@ -297,6 +297,7 @@ def run_l2e_station(
297
297
  campaign_name=campaign_name,
298
298
  station_name=station_name,
299
299
  )
300
+ sensor_name = metadata["sensor_name"]
300
301
  sample_interval = metadata["measurement_interval"]
301
302
  if isinstance(sample_interval, list):
302
303
  sample_interval = min(sample_interval)
@@ -305,7 +306,7 @@ def run_l2e_station(
305
306
  # Generate products for each temporal resolution
306
307
  # temporal_resolution = "1MIN"
307
308
  # temporal_resolution = "10MIN"
308
- temporal_resolutions = get_product_temporal_resolutions(product)
309
+ temporal_resolutions = get_product_temporal_resolutions(product=product, sensor_name=sensor_name)
309
310
  for temporal_resolution in temporal_resolutions:
310
311
 
311
312
  # ------------------------------------------------------------------.
@@ -339,6 +340,7 @@ def run_l2e_station(
339
340
  l2e_processing_options = L2ProcessingOptions(
340
341
  product=product,
341
342
  temporal_resolution=temporal_resolution,
343
+ sensor_name=sensor_name,
342
344
  filepaths=filepaths,
343
345
  parallel=parallel,
344
346
  )
@@ -692,6 +694,7 @@ def run_l2m_station(
692
694
  campaign_name=campaign_name,
693
695
  station_name=station_name,
694
696
  )
697
+ sensor_name = metadata["sensor_name"]
695
698
  sample_interval = metadata["measurement_interval"]
696
699
  if isinstance(sample_interval, list):
697
700
  sample_interval = min(sample_interval)
@@ -700,7 +703,7 @@ def run_l2m_station(
700
703
  # Loop
701
704
  # temporal_resolution = "1MIN"
702
705
  # temporal_resolution = "10MIN"
703
- temporal_resolutions = get_product_temporal_resolutions(product)
706
+ temporal_resolutions = get_product_temporal_resolutions(product=product, sensor_name=sensor_name)
704
707
  for temporal_resolution in temporal_resolutions:
705
708
 
706
709
  # ------------------------------------------------------------------.
@@ -734,6 +737,7 @@ def run_l2m_station(
734
737
  l2m_processing_options = L2ProcessingOptions(
735
738
  product=product,
736
739
  temporal_resolution=temporal_resolution,
740
+ sensor_name=sensor_name,
737
741
  filepaths=filepaths,
738
742
  parallel=parallel,
739
743
  )
@@ -766,7 +770,7 @@ def run_l2m_station(
766
770
  # -----------------------------------------------------------------.
767
771
  # Retrieve product-model options
768
772
  product_options = copy.deepcopy(global_product_options)
769
- model_options = get_model_options(product="L2M", model_name=model_name)
773
+ model_options = get_model_options(model_name=model_name)
770
774
  product_options["product_options"].update(model_options)
771
775
 
772
776
  psd_model = model_options["psd_model"]
@@ -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
@@ -17,9 +17,10 @@
17
17
  """Implements ProcessingOption class for DISDRODB routines."""
18
18
  import json
19
19
  import os
20
+ from pathlib import Path
20
21
 
21
22
  import disdrodb
22
- from disdrodb.api.checks import check_product, check_sensor_name, check_temporal_resolution
23
+ from disdrodb.api.checks import check_product, check_temporal_resolution
23
24
  from disdrodb.api.info import group_filepaths
24
25
  from disdrodb.configs import get_products_configs_dir
25
26
  from disdrodb.utils.archiving import define_temporal_partitions, group_files_by_temporal_partitions
@@ -28,20 +29,68 @@ from disdrodb.utils.routines import is_possible_product
28
29
  from disdrodb.utils.time import ensure_timedelta_seconds, get_sampling_information
29
30
  from disdrodb.utils.yaml import read_yaml
30
31
 
31
- # TODO: Test ensure recursive update for product_options key, do not replace just "product_options" dict !
32
- # get_product_options(product="L2E", temporal_resolution="10MIN")
33
- # get_product_options(product="L2M", temporal_resolution="10MIN")
34
- # get_product_options(product="L1")
35
- # get_product_options(product="L1", temporal_resolution="1MIN")
36
- # get_product_options(product="L1", temporal_resolution="1MIN", sensor_name="PARSIVEL")
37
32
 
38
- # TODO: test return list
39
- # get_product_temporal_resolutions(product="L1")
40
- # get_product_temporal_resolutions(product="L2E")
41
- # get_product_temporal_resolutions(product="L2M")
42
-
43
-
44
- def get_product_options(product, temporal_resolution=None, sensor_name=None):
33
+ def get_product_options_directory(products_configs_dir, product, sensor_name=None):
34
+ """Retrieve path to the product options directory."""
35
+ products_configs_dir = str(products_configs_dir) # convert pathlib to str
36
+ if sensor_name is None:
37
+ return os.path.join(products_configs_dir, product)
38
+ return os.path.join(products_configs_dir, product, sensor_name)
39
+
40
+
41
+ def get_l2m_model_settings_directory(products_configs_dir):
42
+ """Retrieve path to the product options directory."""
43
+ return os.path.join(products_configs_dir, "L2M", "MODELS")
44
+
45
+
46
+ def get_l2m_model_settings_files(products_configs_dir):
47
+ """Retrieve path to the product options directory."""
48
+ models_dir = Path(get_l2m_model_settings_directory(products_configs_dir))
49
+ models_files = list(models_dir.glob("*.yaml")) + list(models_dir.glob("*.yml"))
50
+ return models_files
51
+
52
+
53
+ def get_product_global_options_path(products_configs_dir, product, sensor_name=None):
54
+ """Retrieve path to the product global options."""
55
+ product_options_dir = get_product_options_directory(
56
+ products_configs_dir=products_configs_dir,
57
+ product=product,
58
+ sensor_name=sensor_name,
59
+ )
60
+ product_global_options_path = os.path.join(product_options_dir, "global.yaml")
61
+ if os.path.exists(product_global_options_path):
62
+ return product_global_options_path
63
+
64
+ product_options_dir = get_product_options_directory(
65
+ products_configs_dir=products_configs_dir,
66
+ product=product,
67
+ sensor_name=None,
68
+ )
69
+ global_options_path = os.path.join(product_options_dir, "global.yaml") # this must exists
70
+ return global_options_path
71
+
72
+
73
+ def get_product_custom_options_path(products_configs_dir, product, temporal_resolution, sensor_name=None):
74
+ """Retrieve path to the product temporal resolution custom options."""
75
+ product_options_dir = get_product_options_directory(
76
+ products_configs_dir=products_configs_dir,
77
+ product=product,
78
+ sensor_name=sensor_name,
79
+ )
80
+ product_global_options_path = os.path.join(product_options_dir, f"{temporal_resolution}.yaml")
81
+ if os.path.exists(product_global_options_path):
82
+ return product_global_options_path
83
+
84
+ product_options_dir = get_product_options_directory(
85
+ products_configs_dir=products_configs_dir,
86
+ product=product,
87
+ sensor_name=None,
88
+ )
89
+ custom_options_path = os.path.join(product_options_dir, f"{temporal_resolution}.yaml") # this might not exists
90
+ return custom_options_path
91
+
92
+
93
+ def get_product_options(product, temporal_resolution=None, sensor_name=None, products_configs_dir=None):
45
94
  """Return DISDRODB product options.
46
95
 
47
96
  If temporal resolution is not provided, it returns the global product option.
@@ -49,16 +98,20 @@ def get_product_options(product, temporal_resolution=None, sensor_name=None):
49
98
  If product="L1" and sensor_name is specified, it customize product options also by sensor.
50
99
  """
51
100
  # Retrieve products configuration directory
52
- products_configs_dir = get_products_configs_dir()
53
-
54
- # Validate DISDRODB products configuration
55
- validate_product_configuration(products_configs_dir)
101
+ products_configs_dir = get_products_configs_dir(products_configs_dir=products_configs_dir)
56
102
 
57
103
  # Check product
58
104
  check_product(product)
59
105
 
106
+ # Get product global options path
107
+ global_options_path = get_product_global_options_path(
108
+ products_configs_dir=products_configs_dir,
109
+ product=product,
110
+ sensor_name=sensor_name,
111
+ )
112
+
60
113
  # Retrieve global product options (when no temporal resolution !)
61
- global_options = read_yaml(os.path.join(products_configs_dir, product, "global.yaml"))
114
+ global_options = read_yaml(global_options_path)
62
115
  if temporal_resolution is None:
63
116
  global_options = check_availability_radar_simulations(global_options)
64
117
  return global_options
@@ -70,43 +123,44 @@ def get_product_options(product, temporal_resolution=None, sensor_name=None):
70
123
  global_options.pop("temporal_resolutions", None)
71
124
 
72
125
  # Read custom options for specific temporal resolution
73
- custom_options_path = os.path.join(products_configs_dir, product, f"{temporal_resolution}.yaml")
126
+ custom_options_path = get_product_custom_options_path(
127
+ products_configs_dir=products_configs_dir,
128
+ product=product,
129
+ sensor_name=sensor_name,
130
+ temporal_resolution=temporal_resolution,
131
+ )
74
132
  if not os.path.exists(custom_options_path):
75
133
  return global_options
76
134
  custom_options = read_yaml(custom_options_path)
77
135
 
78
- # Define product options
136
+ # Update global options with the custom options specified
79
137
  options = global_options.copy()
80
- if "product_options" in custom_options:
81
- options["product_options"].update(custom_options.pop("product_options"))
138
+ keys_options = ["archive_options", "product_options", "radar_options"]
139
+ for key in keys_options:
140
+ if key in custom_options:
141
+ options[key].update(custom_options.pop(key)) # Update with only one
142
+
143
+ # Update remaining flat keys
82
144
  options.update(custom_options)
83
145
 
84
146
  # Check availability of radar simulations
85
147
  options = check_availability_radar_simulations(options)
86
148
 
87
- # Customize product options by sensor if L1 product
88
- if product == "L1" and sensor_name is not None:
89
- check_sensor_name(sensor_name)
90
- custom_options_path = os.path.join(products_configs_dir, product, sensor_name, f"{temporal_resolution}.yaml")
91
- if not os.path.exists(custom_options_path):
92
- return options
93
- custom_options = read_yaml(custom_options_path)
94
- if "product_options" in custom_options:
95
- options["product_options"].update(custom_options.pop("product_options"))
96
149
  return options
97
150
 
98
151
 
99
- def get_product_temporal_resolutions(product):
152
+ def get_product_temporal_resolutions(product, sensor_name=None):
100
153
  """Return DISDRODB products temporal resolutions."""
101
154
  # Check only L2E and L2M
102
- return get_product_options(product)["temporal_resolutions"]
155
+ return get_product_options(product, sensor_name=sensor_name)["temporal_resolutions"]
103
156
 
104
157
 
105
- def get_model_options(product, model_name):
158
+ def get_model_options(model_name, products_configs_dir=None):
106
159
  """Return DISDRODB L2M product model options."""
107
160
  # Retrieve products configuration directory
108
- products_configs_dir = get_products_configs_dir()
109
- model_options_path = os.path.join(products_configs_dir, product, "MODELS", f"{model_name}.yaml")
161
+ products_configs_dir = get_products_configs_dir(products_configs_dir=products_configs_dir)
162
+ models_settings_dir = get_l2m_model_settings_directory(products_configs_dir)
163
+ model_options_path = os.path.join(models_settings_dir, f"{model_name}.yaml")
110
164
  model_options = read_yaml(model_options_path)
111
165
  return model_options
112
166
 
@@ -118,19 +172,6 @@ def check_availability_radar_simulations(options):
118
172
  return options
119
173
 
120
174
 
121
- def validate_product_configuration(products_configs_dir):
122
- """Validate the DISDRODB products configuration files."""
123
- # TODO: Implement validation of DISDRODB products configuration files with pydantic
124
- # TODO: Raise warning if L1 temporal resolutions does not includes all temporal resolutions of L2 products.
125
- # TODO: Raise warning if L2E temporal resolutions does not includes all temporal resolutions of L2M products.
126
- # if stategy_event, check neighbor_time_interval >= sample_interval !
127
- # if temporal_resolution_to_seconds(neighbor_time_interval) < temporal_resolution_to_seconds(sample_interval):
128
- # msg = "'neighbor_time_interval' must be at least equal to the dataset sample interval ({sample_interval})"
129
- # raise ValueError(msg)
130
-
131
- pass
132
-
133
-
134
175
  def _define_blocks_offsets(sample_interval, temporal_resolution):
135
176
  """Define blocks offset for resampling logic."""
136
177
  # Retrieve accumulation_interval and rolling option
@@ -150,6 +191,19 @@ def _define_blocks_offsets(sample_interval, temporal_resolution):
150
191
  return block_starts_offset, block_ends_offset
151
192
 
152
193
 
194
+ class L0CProcessingOptions:
195
+ """Define L0C product processing options."""
196
+
197
+ def __init__(self, sensor_name):
198
+ """Define DISDRODB L0C product processing options."""
199
+ product = "L0C"
200
+ options = get_product_options(product=product, sensor_name=sensor_name)["archive_options"]
201
+
202
+ self.product = product
203
+ self.folder_partitioning = options["folder_partitioning"]
204
+ self.product_frequency = options["strategy_options"]["freq"]
205
+
206
+
153
207
  class L1ProcessingOptions:
154
208
  """Define L1 product processing options."""
155
209
 
@@ -160,7 +214,7 @@ class L1ProcessingOptions:
160
214
  # ---------------------------------------------------------------------.
161
215
  # Define temporal resolutions for which to retrieve processing options
162
216
  if temporal_resolutions is None:
163
- temporal_resolutions = get_product_temporal_resolutions(product)
217
+ temporal_resolutions = get_product_temporal_resolutions(product, sensor_name=sensor_name)
164
218
  elif isinstance(temporal_resolutions, str):
165
219
  temporal_resolutions = [temporal_resolutions]
166
220
  _ = [check_temporal_resolution(temporal_resolution) for temporal_resolution in temporal_resolutions]
@@ -200,12 +254,9 @@ class L1ProcessingOptions:
200
254
  archive_options = product_options.pop("archive_options")
201
255
 
202
256
  dict_product_options[temporal_resolution] = product_options
203
- # -------------------------------------------------------------------------.
257
+
204
258
  # Define folder partitioning
205
- if "folder_partitioning" not in archive_options:
206
- dict_folder_partitioning[temporal_resolution] = disdrodb.config.get("folder_partitioning")
207
- else:
208
- dict_folder_partitioning[temporal_resolution] = archive_options.pop("folder_partitioning")
259
+ dict_folder_partitioning[temporal_resolution] = archive_options.pop("folder_partitioning")
209
260
 
210
261
  # -------------------------------------------------------------------------.
211
262
  # Define list of temporal partitions
@@ -282,40 +333,34 @@ class L1ProcessingOptions:
282
333
  self.dict_folder_partitioning = dict_folder_partitioning
283
334
 
284
335
  def group_files_by_temporal_partitions(self, temporal_resolution):
285
- """Return files partitions dictionary for a specific L2E product."""
336
+ """Return files partitions dictionary for a specific L1 product."""
286
337
  return self.dict_files_partitions[temporal_resolution]
287
338
 
288
- def get_product_options(self, temporal_resolution):
289
- """Return product options dictionary for a specific L2E product."""
290
- return self.dict_product_options[temporal_resolution]
339
+ def get_product_options(self, temporal_resolution): # noqa
340
+ """Return product options dictionary for a specific L1 product."""
341
+ return {} # self.dict_product_options[temporal_resolution]
291
342
 
292
343
  def get_folder_partitioning(self, temporal_resolution):
293
- """Return the folder partitioning for a specific L2E product."""
294
- # to be used for logs and files !
344
+ """Return the folder partitioning for a specific L1 product."""
295
345
  return self.dict_folder_partitioning[temporal_resolution]
296
346
 
297
347
 
298
348
  class L2ProcessingOptions:
299
349
  """Define L2 products processing options."""
300
350
 
301
- def __init__(self, product, filepaths, parallel, temporal_resolution):
351
+ def __init__(self, product, filepaths, parallel, temporal_resolution, sensor_name):
302
352
  """Define DISDRODB L2 products processing options."""
303
- import disdrodb
304
-
305
353
  # Check temporal resolution
306
354
  check_temporal_resolution(temporal_resolution)
307
355
 
308
356
  # Get product options
309
- product_options = get_product_options(product, temporal_resolution=temporal_resolution)
357
+ product_options = get_product_options(product, temporal_resolution=temporal_resolution, sensor_name=sensor_name)
310
358
 
311
359
  # Extract processing options
312
360
  archive_options = product_options.pop("archive_options")
313
361
 
314
362
  # Define folder partitioning
315
- if "folder_partitioning" not in archive_options:
316
- folder_partitioning = disdrodb.config.get("folder_partitioning")
317
- else:
318
- folder_partitioning = archive_options.pop("folder_partitioning")
363
+ folder_partitioning = archive_options.pop("folder_partitioning")
319
364
 
320
365
  # Define files temporal partitions
321
366
  # - [{start_time: np.datetime64, end_time: np.datetime64}, ....]