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
@@ -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
  """Metadata tools to verify/complete geolocation information."""
18
+
20
19
  import time
21
20
 
22
21
  import numpy as np
@@ -126,7 +125,7 @@ def infer_altitudes(lats, lons, dem="aster30m"):
126
125
  block_lons = lons[i : i + max_locations]
127
126
 
128
127
  # Create the list_coords string in the format "lat1,lon1|lat2,lon2|..."
129
- list_coords = "|".join([f"{lat},{lon}" for lat, lon in zip(block_lats, block_lons)])
128
+ list_coords = "|".join([f"{lat},{lon}" for lat, lon in zip(block_lats, block_lons, strict=True)])
130
129
 
131
130
  # Define API URL
132
131
  url = f"https://api.opentopodata.org/v1/{dem}?locations={list_coords}&interpolation=nearest"
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
@@ -17,8 +15,8 @@
17
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
16
  # -----------------------------------------------------------------------------.
19
17
  """Test Metadata Info Extraction."""
18
+
20
19
  import os
21
- from typing import Optional
22
20
 
23
21
  from disdrodb.api.info import (
24
22
  infer_campaign_name_from_path,
@@ -29,7 +27,7 @@ from disdrodb.metadata.reader import read_station_metadata
29
27
  from disdrodb.metadata.search import get_list_metadata
30
28
 
31
29
 
32
- def get_archive_metadata_key_value(key: str, return_tuple: bool = True, metadata_archive_dir: Optional[str] = None):
30
+ def get_archive_metadata_key_value(key: str, return_tuple: bool = True, metadata_archive_dir: str | None = None):
33
31
  """Return the values of a metadata key for all the archive.
34
32
 
35
33
  Parameters
@@ -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
@@ -18,7 +16,6 @@
18
16
  # -----------------------------------------------------------------------------.
19
17
  """Routines to manipulate the DISDRODB Metadata Archive."""
20
18
 
21
-
22
19
  from disdrodb.api.path import define_metadata_filepath
23
20
  from disdrodb.api.search import available_stations
24
21
 
@@ -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."""
@@ -0,0 +1,273 @@
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 atmospheric physics module."""
18
+
19
+ import numpy as np
20
+ import xarray as xr
21
+
22
+
23
+ def get_gravitational_acceleration(latitude, altitude=0):
24
+ """
25
+ Computes gravitational acceleration at a given altitude and latitude.
26
+
27
+ Parameters
28
+ ----------
29
+ altitude : float
30
+ Altitude in meters. The default is 0 m (sea level).
31
+ latitude : float
32
+ Latitude in degrees.
33
+
34
+ Returns
35
+ -------
36
+ float
37
+ Gravitational acceleration in m/s^2.
38
+ """
39
+ g0 = 9.806229 - 0.025889372 * np.cos(2 * np.deg2rad(latitude))
40
+ return g0 - 2.879513 * altitude / 1e6
41
+
42
+
43
+ def get_air_pressure_at_height(
44
+ altitude,
45
+ latitude,
46
+ temperature,
47
+ sea_level_air_pressure=101_325,
48
+ lapse_rate=0.0065,
49
+ gas_constant_dry_air=287.04,
50
+ ):
51
+ """
52
+ Computes the air pressure at a given height in a standard atmosphere.
53
+
54
+ According to the hypsometric formula of Brutsaert 1982; Ulaby et al. 1981
55
+
56
+ Parameters
57
+ ----------
58
+ altitude : float
59
+ Altitude in meters.
60
+ latitude : float
61
+ Latitude in degrees.
62
+ temperature : float
63
+ Temperature at altitude in Kelvin.
64
+ sea_level_air_pressure : float, optional
65
+ Standard atmospheric pressure at sea level in Pascals. The default is 101_325 Pascals.
66
+ lapse_rate : float, optional
67
+ Standard atmospheric lapse rate in K/m. The default is 0.0065 K/m.
68
+ gas_constant_dry_air : float, optional
69
+ Gas constant for dry air in J/(kg*K). The default is 287.04 J/(kg*K).
70
+
71
+ Returns
72
+ -------
73
+ float
74
+ Air pressure in Pascals.
75
+ """
76
+ g = get_gravitational_acceleration(altitude=altitude, latitude=latitude)
77
+ return sea_level_air_pressure * np.exp(
78
+ -g / (lapse_rate * gas_constant_dry_air) * np.log(1 + lapse_rate * altitude / temperature),
79
+ )
80
+
81
+
82
+ def get_air_temperature_at_height(altitude, sea_level_temperature, lapse_rate=0.0065):
83
+ """
84
+ Computes the air temperature at a given height in a standard atmosphere.
85
+
86
+ Reference: Brutsaert 1982; Ulaby et al. 1981
87
+
88
+ Parameters
89
+ ----------
90
+ altitude : float
91
+ Altitude in meters.
92
+ sea_level_temperature : float
93
+ Standard temperature at sea level in Kelvin.
94
+ lapse_rate : float, optional
95
+ Standard atmospheric lapse rate in K/m. The default is 0.0065 K/m.
96
+
97
+ Returns
98
+ -------
99
+ float
100
+ Air temperature in Kelvin.
101
+ """
102
+ return sea_level_temperature - lapse_rate * altitude
103
+
104
+
105
+ def get_air_dynamic_viscosity(temperature):
106
+ """
107
+ Computes the dynamic viscosity of dry air.
108
+
109
+ Reference: Beard 1977; Pruppacher & Klett 1978
110
+
111
+ Parameters
112
+ ----------
113
+ temperature : float
114
+ Temperature in Kelvin.
115
+
116
+ Returns
117
+ -------
118
+ float
119
+ Dynamic viscosity of dry air in kg/(m*s) (aka Pa*s).
120
+ """
121
+ # Convert to Celsius
122
+ temperature = temperature - 273.15
123
+
124
+ # Define mask
125
+ above_freezing_mask = temperature > 0
126
+
127
+ # Compute viscosity above freezing temperature
128
+ viscosity_above_0 = (1.721 + 0.00487 * temperature) / 1e5
129
+
130
+ # Compute viscosity below freezing temperature
131
+ viscosity_below_0 = (1.718 + 0.0049 * temperature - 1.2 * temperature**2 / 1e5) / 1e5
132
+
133
+ # Define final viscosity
134
+ viscosity = xr.where(above_freezing_mask, viscosity_above_0, viscosity_below_0)
135
+ return viscosity
136
+
137
+
138
+ def get_air_density(temperature, air_pressure, vapor_pressure, gas_constant_dry_air=287.04):
139
+ """
140
+ Computes the air density according to the equation of state for moist air.
141
+
142
+ Reference: Brutsaert 1982
143
+
144
+ Parameters
145
+ ----------
146
+ temperature : float
147
+ Temperature in Kelvin.
148
+ air_pressure : float
149
+ Air pressure in Pascals.
150
+ vapor_pressure : float
151
+ Vapor pressure in Pascals.
152
+ gas_constant_dry_air : float, optional
153
+ Gas constant for dry air in J/(kg*K). The default is 287.04 J/(kg*K).
154
+
155
+ Returns
156
+ -------
157
+ float
158
+ Air density in kg/m^3.
159
+ """
160
+ # # Define constant for water vapor in J/(kg·K)
161
+ # gas_constant_water_vapor=461.5
162
+
163
+ # # Partial pressure of dry air (Pa)
164
+ # pressure_dry_air = air_pressure - vapor_pressure
165
+
166
+ # # Density of dry air (kg/m^3)
167
+ # density_dry_air = pressure_dry_air / (gas_constant_dry_air * temperature)
168
+
169
+ # # Density of water vapor (kg/m^3)
170
+ # density_water_vapor = vapor_pressure / (gas_constant_water_vapor * temperature)
171
+
172
+ # # Total air density (kg/m^3)
173
+ # air_density = density_dry_air + density_water_vapor
174
+
175
+ return air_pressure * (1 - 0.378 * vapor_pressure / air_pressure) / (gas_constant_dry_air * temperature)
176
+
177
+
178
+ def get_vapor_actual_pressure_at_height(
179
+ altitude,
180
+ sea_level_temperature,
181
+ sea_level_relative_humidity,
182
+ sea_level_air_pressure=101_325,
183
+ lapse_rate=0.0065,
184
+ ):
185
+ """
186
+ Computes the vapor pressure using Yamamoto's exponential relationship.
187
+
188
+ Reference: Brutsaert 1982
189
+
190
+ Parameters
191
+ ----------
192
+ altitude : float
193
+ Altitude in meters.
194
+ sea_level_temperature : float
195
+ Standard temperature at sea level in Kelvin.
196
+ sea_level_relative_humidity : float
197
+ Relative humidity at sea level. A value between 0 and 1.
198
+ sea_level_air_pressure : float, optional
199
+ Standard atmospheric pressure at sea level in Pascals. The default is 101_325 Pascals.
200
+ lapse_rate : float, optional
201
+ Standard atmospheric lapse rate in K/m. The default is 0.0065 K/m.
202
+
203
+ Returns
204
+ -------
205
+ float
206
+ Vapor pressure in Pascals.
207
+ """
208
+ temperature_at_altitude = get_air_temperature_at_height(
209
+ altitude=altitude,
210
+ sea_level_temperature=sea_level_temperature,
211
+ lapse_rate=lapse_rate,
212
+ )
213
+ esat = get_vapor_saturation_pressure(sea_level_temperature)
214
+ actual_vapor = sea_level_relative_humidity / (1 / esat - (1 - sea_level_relative_humidity) / sea_level_air_pressure)
215
+ return actual_vapor * np.exp(-(5.8e3 * lapse_rate / (temperature_at_altitude**2) + 5.5e-5) * altitude)
216
+
217
+
218
+ def get_vapor_saturation_pressure(temperature):
219
+ """
220
+ Computes the saturation vapor pressure over water as a function of temperature.
221
+
222
+ Use formulation and coefficients of Wexler (1976, 1977).
223
+ References: Brutsaert 1982; Pruppacher & Klett 1978; Flatau & al. 1992
224
+
225
+ Parameters
226
+ ----------
227
+ temperature : float
228
+ Temperature in Kelvin.
229
+
230
+ Returns
231
+ -------
232
+ float
233
+ Saturation vapor pressure in Pascal.
234
+ """
235
+ # Polynomial coefficients
236
+ g = [
237
+ -0.29912729e4,
238
+ -0.60170128e4,
239
+ 0.1887643854e2,
240
+ -0.28354721e-1,
241
+ 0.17838301e-4,
242
+ -0.84150417e-9,
243
+ 0.44412543e-12,
244
+ 0.2858487e1,
245
+ ]
246
+ # Perform polynomial accumulation using Horner rule
247
+ esat = g[6]
248
+ for i in [5, 4, 3, 2]:
249
+ esat = esat * temperature + g[i]
250
+ esat = esat + g[7] * np.log(temperature)
251
+ for i in [1, 0]:
252
+ esat = esat * temperature + g[i]
253
+ return np.exp(esat / (temperature**2))
254
+
255
+
256
+ def get_vapor_actual_pressure(relative_humidity, temperature):
257
+ """
258
+ Computes the actual vapor pressure over water.
259
+
260
+ Parameters
261
+ ----------
262
+ relative_humidity : float
263
+ Relative humidity. A value between 0 and 1.
264
+ temperature : float
265
+ Temperature in Kelvin.
266
+
267
+ Returns
268
+ -------
269
+ float
270
+ Actual vapor pressure in Pascal.
271
+ """
272
+ esat = get_vapor_saturation_pressure(temperature)
273
+ return relative_humidity * esat
@@ -0,0 +1,131 @@
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 water physics module."""
18
+
19
+ import numpy as np
20
+ import xarray as xr
21
+
22
+
23
+ def get_pure_water_density(temperature):
24
+ """
25
+ Computes the density of pure water at standard pressure.
26
+
27
+ For temperatures above freezing uses Kell formulation.
28
+ For temperatures below freezing use Dorsch & Boyd formulation.
29
+
30
+ References: Pruppacher & Klett 1978; Weast & Astle 1980
31
+
32
+ Parameters
33
+ ----------
34
+ temperature : float
35
+ Temperature in Kelvin.
36
+
37
+ Returns
38
+ -------
39
+ float
40
+ Density of pure water in kg/m^3.
41
+ """
42
+ # Convert to Celsius
43
+ temperature = temperature - 273.15
44
+
45
+ # Define mask
46
+ above_freezing_mask = temperature > 0
47
+
48
+ # Compute density above freezing temperature
49
+ c = [9.9983952e2, 1.6945176e1, -7.9870401e-3, -4.6170461e-5, 1.0556302e-7, -2.8054253e-10, 1.6879850e-2]
50
+ density = c[0] + sum(c * temperature**i for i, c in enumerate(c[1:6], start=1))
51
+ density_above_0 = density / (1 + c[6] * temperature)
52
+
53
+ # Compute density below freezing temperature
54
+ c = [999.84, 0.086, -0.0108]
55
+ density_below_0 = c[0] + sum(c * temperature**i for i, c in enumerate(c[1:], start=1))
56
+
57
+ # Define final density
58
+ density = xr.where(above_freezing_mask, density_above_0, density_below_0)
59
+ return density
60
+
61
+
62
+ def get_pure_water_compressibility(temperature):
63
+ """
64
+ Computes the isothermal compressibility of pure ordinary water.
65
+
66
+ Reference: Kell, Weast & Astle 1980
67
+
68
+ Parameters
69
+ ----------
70
+ temperature : float
71
+ Temperature in Kelvin.
72
+
73
+ Returns
74
+ -------
75
+ float
76
+ Compressibility of water in Pascals.
77
+ """
78
+ # Convert to Celsius
79
+ temperature = temperature - 273.15
80
+
81
+ # Compute compressibility
82
+ c = [5.088496e1, 6.163813e-1, 1.459187e-3, 2.008438e-5, -5.857727e-8, 4.10411e-10, 1.967348e-2]
83
+ compressibility = c[0] + sum(c * temperature**i for i, c in enumerate(c[1:6], start=1))
84
+ compressibility = compressibility / (1 + c[6] * temperature) * 1e-11
85
+ return compressibility
86
+
87
+
88
+ def get_pure_water_surface_tension(temperature):
89
+ """
90
+ Computes the surface tension of pure ordinary water against air.
91
+
92
+ Reference: Pruppacher & Klett 1978
93
+
94
+ Parameters
95
+ ----------
96
+ temperature : float
97
+ Temperature in Kelvin.
98
+
99
+ Returns
100
+ -------
101
+ float
102
+ Surface tension in N/m.
103
+ """
104
+ sigma = 0.0761 - 0.000155 * (temperature - 273.15)
105
+ return sigma
106
+
107
+
108
+ def get_water_density(temperature, air_pressure, sea_level_air_pressure=101_325):
109
+ """
110
+ Computes the density of water according to Weast & Astle 1980.
111
+
112
+ Parameters
113
+ ----------
114
+ temperature : float
115
+ Temperature in Kelvin.
116
+ air_pressure : float
117
+ Air pressure in Pascals.
118
+ sea_level_air_pressure : float
119
+ Standard atmospheric pressure at sea level in Pascals.
120
+ The default is 101_325 Pascal.
121
+ freezing_temperature : float, optional
122
+ Freezing temperature of water in Kelvin. The default is 273.15 K.
123
+
124
+ Returns
125
+ -------
126
+ float
127
+ Water density in kg/m^3.
128
+ """
129
+ delta_pressure = sea_level_air_pressure - air_pressure
130
+ water_compressibility = get_pure_water_compressibility(temperature)
131
+ return get_pure_water_density(temperature) * np.exp(-1 * water_compressibility * delta_pressure)
@@ -0,0 +1,63 @@
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 wrapper functions."""
18
+
19
+ from disdrodb.physics.atmosphere import (
20
+ get_air_density,
21
+ get_air_dynamic_viscosity,
22
+ get_air_pressure_at_height,
23
+ get_vapor_actual_pressure,
24
+ )
25
+
26
+
27
+ ####---------------------------------------------------------------------------.
28
+ #### Wrappers
29
+ def retrieve_air_pressure(ds_env):
30
+ """Retrieve air pressure."""
31
+ if "air_pressure" in ds_env:
32
+ return ds_env["air_pressure"]
33
+ air_pressure = get_air_pressure_at_height(
34
+ altitude=ds_env["altitude"],
35
+ latitude=ds_env["latitude"],
36
+ temperature=ds_env["temperature"],
37
+ sea_level_air_pressure=ds_env["sea_level_air_pressure"],
38
+ lapse_rate=ds_env["lapse_rate"],
39
+ )
40
+ return air_pressure
41
+
42
+
43
+ def retrieve_air_dynamic_viscosity(ds_env):
44
+ """Retrieve air dynamic viscosity."""
45
+ air_viscosity = get_air_dynamic_viscosity(ds_env["temperature"])
46
+ return air_viscosity
47
+
48
+
49
+ def retrieve_air_density(ds_env):
50
+ """Retrieve air density."""
51
+ temperature = ds_env["temperature"]
52
+ relative_humidity = ds_env["relative_humidity"]
53
+ air_pressure = retrieve_air_pressure(ds_env)
54
+ vapor_pressure = get_vapor_actual_pressure(
55
+ relative_humidity=relative_humidity,
56
+ temperature=temperature,
57
+ )
58
+ air_density = get_air_density(
59
+ temperature=temperature,
60
+ air_pressure=air_pressure,
61
+ vapor_pressure=vapor_pressure,
62
+ )
63
+ return air_density
disdrodb/psd/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # -----------------------------------------------------------------------------.
2
- # Copyright (c) 2021-2023 DISDRODB developers
2
+ # Copyright (c) 2021-2026 DISDRODB developers
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -16,7 +16,6 @@
16
16
  # -----------------------------------------------------------------------------.
17
17
  """Implement PSD model and fitting routines."""
18
18
 
19
-
20
19
  from disdrodb.psd.fitting import estimate_model_parameters
21
20
  from disdrodb.psd.models import (
22
21
  ExponentialPSD,
disdrodb/psd/fitting.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,6 +15,7 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
  # -----------------------------------------------------------------------------.
17
17
  """Routines for PSD fitting."""
18
+
18
19
  import numpy as np
19
20
  import scipy.stats as ss
20
21
  import xarray as xr
@@ -23,7 +24,7 @@ from scipy.optimize import minimize
23
24
  from scipy.special import gamma, gammaln # Regularized lower incomplete gamma function
24
25
 
25
26
  from disdrodb.constants import DIAMETER_DIMENSION
26
- from disdrodb.l1.fall_velocity import get_raindrop_fall_velocity_from_ds
27
+ from disdrodb.fall_velocity import get_rain_fall_velocity_from_ds
27
28
  from disdrodb.l2.empirical_dsd import (
28
29
  get_median_volume_drop_diameter,
29
30
  get_moment,
@@ -1056,14 +1057,26 @@ def _compute_z(ND, D, dD):
1056
1057
  return Z
1057
1058
 
1058
1059
 
1059
- def _compute_target_variable_error(target, ND_obs, ND_preds, D, dD, V):
1060
+ def _compute_target_variable_error(target, ND_obs, ND_preds, D, dD, V, relative=False, eps=1e-12):
1061
+ # Compute observed and predicted target variables
1060
1062
  if target == "Z":
1061
- errors = np.abs(_compute_z(ND_obs, D, dD) - _compute_z(ND_preds, D, dD))
1063
+ obs = _compute_z(ND_obs, D, dD)
1064
+ pred = _compute_z(ND_preds, D, dD)
1062
1065
  elif target == "R":
1063
- errors = np.abs(_compute_rain_rate(ND_obs, D, dD, V) - _compute_rain_rate(ND_preds, D, dD, V))
1064
- else: # if target == "LWC":
1065
- errors = np.abs(_compute_lwc(ND_obs, D, dD) - _compute_lwc(ND_preds, D, dD))
1066
- return errors
1066
+ obs = _compute_rain_rate(ND_obs, D, dD, V)
1067
+ pred = _compute_rain_rate(ND_preds, D, dD, V)
1068
+ else: # "LWC"
1069
+ obs = _compute_lwc(ND_obs, D, dD)
1070
+ pred = _compute_lwc(ND_preds, D, dD)
1071
+
1072
+ # Absolute error
1073
+ abs_error = np.abs(obs - pred)
1074
+
1075
+ # Return relative error if requested
1076
+ if relative:
1077
+ return abs_error / (np.abs(obs) + eps)
1078
+
1079
+ return abs_error
1067
1080
 
1068
1081
 
1069
1082
  def _compute_cost_function(ND_obs, ND_preds, D, dD, V, target, transformation, error_order):
@@ -1992,6 +2005,7 @@ ATTRS_PARAMS_DICT = {
1992
2005
  },
1993
2006
  }
1994
2007
 
2008
+ PSD_MODELS = list(ATTRS_PARAMS_DICT)
1995
2009
 
1996
2010
  MOM_METHODS_DICT = {
1997
2011
  "GammaPSD": {
@@ -2356,7 +2370,7 @@ def get_gs_parameters(ds, psd_model, target="ND", transformation="log", error_or
2356
2370
 
2357
2371
  # Check fall velocity is available if target R
2358
2372
  if "fall_velocity" not in ds:
2359
- ds["fall_velocity"] = get_raindrop_fall_velocity_from_ds(ds)
2373
+ ds["fall_velocity"] = get_rain_fall_velocity_from_ds(ds)
2360
2374
 
2361
2375
  # Retrieve estimation function
2362
2376
  func = OPTIMIZATION_ROUTINES_DICT["GS"][psd_model]