disdrodb 0.0.20__py3-none-any.whl → 0.1.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 (264) hide show
  1. disdrodb/__init__.py +132 -15
  2. disdrodb/_config.py +4 -2
  3. disdrodb/_version.py +9 -4
  4. disdrodb/api/checks.py +264 -237
  5. disdrodb/api/configs.py +4 -8
  6. disdrodb/api/create_directories.py +235 -290
  7. disdrodb/api/info.py +217 -26
  8. disdrodb/api/io.py +295 -269
  9. disdrodb/api/path.py +597 -173
  10. disdrodb/api/search.py +486 -0
  11. disdrodb/{metadata/scripts → cli}/disdrodb_check_metadata_archive.py +12 -7
  12. disdrodb/{utils/pandas.py → cli/disdrodb_data_archive_directory.py} +9 -18
  13. disdrodb/cli/disdrodb_download_archive.py +86 -0
  14. disdrodb/cli/disdrodb_download_metadata_archive.py +53 -0
  15. disdrodb/cli/disdrodb_download_station.py +84 -0
  16. disdrodb/{api/scripts → cli}/disdrodb_initialize_station.py +22 -10
  17. disdrodb/cli/disdrodb_metadata_archive_directory.py +32 -0
  18. disdrodb/{data_transfer/scripts/disdrodb_download_station.py → cli/disdrodb_open_data_archive.py} +22 -22
  19. disdrodb/cli/disdrodb_open_logs_directory.py +69 -0
  20. disdrodb/{data_transfer/scripts/disdrodb_upload_station.py → cli/disdrodb_open_metadata_archive.py} +22 -24
  21. disdrodb/cli/disdrodb_open_metadata_directory.py +71 -0
  22. disdrodb/cli/disdrodb_open_product_directory.py +74 -0
  23. disdrodb/cli/disdrodb_open_readers_directory.py +32 -0
  24. disdrodb/{l0/scripts → cli}/disdrodb_run_l0.py +38 -31
  25. disdrodb/{l0/scripts → cli}/disdrodb_run_l0_station.py +32 -30
  26. disdrodb/{l0/scripts → cli}/disdrodb_run_l0a.py +30 -21
  27. disdrodb/{l0/scripts → cli}/disdrodb_run_l0a_station.py +24 -33
  28. disdrodb/{l0/scripts → cli}/disdrodb_run_l0b.py +30 -21
  29. disdrodb/{l0/scripts → cli}/disdrodb_run_l0b_station.py +25 -34
  30. disdrodb/cli/disdrodb_run_l0c.py +130 -0
  31. disdrodb/cli/disdrodb_run_l0c_station.py +129 -0
  32. disdrodb/cli/disdrodb_run_l1.py +122 -0
  33. disdrodb/cli/disdrodb_run_l1_station.py +121 -0
  34. disdrodb/cli/disdrodb_run_l2e.py +122 -0
  35. disdrodb/cli/disdrodb_run_l2e_station.py +122 -0
  36. disdrodb/cli/disdrodb_run_l2m.py +122 -0
  37. disdrodb/cli/disdrodb_run_l2m_station.py +122 -0
  38. disdrodb/cli/disdrodb_upload_archive.py +105 -0
  39. disdrodb/cli/disdrodb_upload_station.py +98 -0
  40. disdrodb/configs.py +90 -25
  41. disdrodb/data_transfer/__init__.py +22 -0
  42. disdrodb/data_transfer/download_data.py +87 -90
  43. disdrodb/data_transfer/upload_data.py +64 -37
  44. disdrodb/data_transfer/zenodo.py +15 -18
  45. disdrodb/docs.py +1 -1
  46. disdrodb/issue/__init__.py +17 -4
  47. disdrodb/issue/checks.py +10 -23
  48. disdrodb/issue/reader.py +9 -12
  49. disdrodb/issue/writer.py +14 -17
  50. disdrodb/l0/__init__.py +17 -26
  51. disdrodb/l0/check_configs.py +35 -23
  52. disdrodb/l0/check_standards.py +32 -42
  53. disdrodb/l0/configs/{Thies_LPM → LPM}/bins_diameter.yml +44 -44
  54. disdrodb/l0/configs/{Thies_LPM → LPM}/bins_velocity.yml +40 -40
  55. disdrodb/l0/configs/LPM/l0a_encodings.yml +80 -0
  56. disdrodb/l0/configs/{Thies_LPM → LPM}/l0b_cf_attrs.yml +62 -59
  57. disdrodb/l0/configs/{Thies_LPM → LPM}/l0b_encodings.yml +9 -9
  58. disdrodb/l0/configs/{Thies_LPM → LPM}/raw_data_format.yml +245 -245
  59. disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/bins_diameter.yml +66 -66
  60. disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/bins_velocity.yml +64 -64
  61. disdrodb/l0/configs/PARSIVEL/l0a_encodings.yml +32 -0
  62. disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/l0b_cf_attrs.yml +22 -20
  63. disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/l0b_encodings.yml +17 -17
  64. disdrodb/l0/configs/{OTT_Parsivel → PARSIVEL}/raw_data_format.yml +77 -77
  65. disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/bins_diameter.yml +64 -64
  66. disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/bins_velocity.yml +64 -64
  67. disdrodb/l0/configs/PARSIVEL2/l0a_encodings.yml +39 -0
  68. disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/l0b_cf_attrs.yml +24 -22
  69. disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/l0b_encodings.yml +20 -20
  70. disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/raw_data_format.yml +98 -98
  71. disdrodb/l0/configs/{RD_80 → RD80}/bins_diameter.yml +40 -40
  72. disdrodb/l0/configs/RD80/l0a_encodings.yml +16 -0
  73. disdrodb/l0/configs/{RD_80 → RD80}/l0b_cf_attrs.yml +3 -3
  74. disdrodb/l0/configs/RD80/l0b_encodings.yml +135 -0
  75. disdrodb/l0/configs/{RD_80 → RD80}/raw_data_format.yml +48 -48
  76. disdrodb/l0/l0_reader.py +216 -340
  77. disdrodb/l0/l0a_processing.py +237 -208
  78. disdrodb/l0/l0b_nc_processing.py +227 -80
  79. disdrodb/l0/l0b_processing.py +93 -173
  80. disdrodb/l0/l0c_processing.py +627 -0
  81. disdrodb/l0/readers/{ARM → LPM/ARM}/ARM_LPM.py +36 -58
  82. disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +226 -0
  83. disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +185 -0
  84. disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +183 -0
  85. disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +179 -0
  86. disdrodb/l0/readers/{UK → LPM/UK}/DIVEN.py +14 -35
  87. disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +157 -0
  88. disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +113 -0
  89. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/ARCTIC_2021.py +40 -57
  90. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/COMMON_2011.py +37 -54
  91. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/DAVOS_2009_2011.py +34 -51
  92. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_2009.py +34 -51
  93. disdrodb/l0/readers/{EPFL/PARADISO_2014.py → PARSIVEL/EPFL/EPFL_ROOF_2008.py} +38 -50
  94. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +105 -0
  95. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2011.py +34 -51
  96. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2012.py +33 -51
  97. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GENEPI_2007.py +25 -44
  98. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007.py +25 -44
  99. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007_2.py +25 -44
  100. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HPICONET_2010.py +34 -51
  101. disdrodb/l0/readers/{EPFL/EPFL_ROOF_2010.py → PARSIVEL/EPFL/HYMEX_LTE_SOP2.py} +37 -50
  102. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +111 -0
  103. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HYMEX_LTE_SOP4.py +36 -54
  104. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2018.py +34 -52
  105. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2019.py +38 -56
  106. disdrodb/l0/readers/PARSIVEL/EPFL/PARADISO_2014.py +105 -0
  107. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PARSIVEL_2007.py +27 -45
  108. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PLATO_2019.py +24 -44
  109. disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +140 -0
  110. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RACLETS_2019_WJF.py +41 -59
  111. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RIETHOLZBACH_2011.py +34 -51
  112. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +117 -0
  113. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +137 -0
  114. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/UNIL_2022.py +42 -55
  115. disdrodb/l0/readers/PARSIVEL/GPM/IFLOODS.py +104 -0
  116. disdrodb/l0/readers/{GPM → PARSIVEL/GPM}/LPVEX.py +29 -48
  117. disdrodb/l0/readers/PARSIVEL/GPM/MC3E.py +184 -0
  118. disdrodb/l0/readers/PARSIVEL/NCAR/CCOPE_2015.py +113 -0
  119. disdrodb/l0/readers/{NCAR/VORTEX_SE_2016_P1.py → PARSIVEL/NCAR/OWLES_MIPS.py} +46 -72
  120. disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +125 -0
  121. disdrodb/l0/readers/{NCAR/OWLES_MIPS.py → PARSIVEL/NCAR/PLOWS_MIPS.py} +45 -64
  122. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +114 -0
  123. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +176 -0
  124. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +183 -0
  125. disdrodb/l0/readers/{ARM/ARM_LD.py → PARSIVEL2/ARM/ARM_PARSIVEL2.py} +27 -50
  126. disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +163 -0
  127. disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +163 -0
  128. disdrodb/l0/readers/{DENMARK → PARSIVEL2/DENMARK}/EROSION_nc.py +14 -35
  129. disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +119 -0
  130. disdrodb/l0/readers/PARSIVEL2/GPM/GCPEX.py +104 -0
  131. disdrodb/l0/readers/PARSIVEL2/GPM/NSSTC.py +176 -0
  132. disdrodb/l0/readers/PARSIVEL2/ITALY/GID_PARSIVEL2.py +32 -0
  133. disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +56 -0
  134. disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +120 -0
  135. disdrodb/l0/readers/{NCAR → PARSIVEL2/NCAR}/PECAN_MIPS.py +45 -64
  136. disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +181 -0
  137. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +160 -0
  138. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +160 -0
  139. disdrodb/l0/readers/{NCAR/PLOWS_MIPS.py → PARSIVEL2/NCAR/VORTEX_SE_2016_P1.py} +49 -66
  140. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +118 -0
  141. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +152 -0
  142. disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT.py +166 -0
  143. disdrodb/l0/readers/{NCAR/RELAMPAGO_RD80.py → RD80/BRAZIL/CHUVA_RD80.py} +36 -60
  144. disdrodb/l0/readers/{BRAZIL → RD80/BRAZIL}/GOAMAZON_RD80.py +36 -55
  145. disdrodb/l0/readers/{NCAR → RD80/NCAR}/CINDY_2011_RD80.py +35 -54
  146. disdrodb/l0/readers/{BRAZIL/CHUVA_RD80.py → RD80/NCAR/RELAMPAGO_RD80.py} +40 -54
  147. disdrodb/l0/readers/template_reader_raw_netcdf_data.py +62 -0
  148. disdrodb/l0/readers/{reader_template.py → template_reader_raw_text_data.py} +20 -44
  149. disdrodb/l0/routines.py +885 -581
  150. disdrodb/l0/standards.py +72 -236
  151. disdrodb/l0/template_tools.py +104 -109
  152. disdrodb/l1/__init__.py +17 -0
  153. disdrodb/l1/beard_model.py +716 -0
  154. disdrodb/l1/encoding_attrs.py +620 -0
  155. disdrodb/l1/fall_velocity.py +260 -0
  156. disdrodb/l1/filters.py +192 -0
  157. disdrodb/l1/processing.py +200 -0
  158. disdrodb/l1/resampling.py +236 -0
  159. disdrodb/l1/routines.py +357 -0
  160. disdrodb/l1_env/__init__.py +17 -0
  161. disdrodb/l1_env/routines.py +38 -0
  162. disdrodb/l2/__init__.py +17 -0
  163. disdrodb/l2/empirical_dsd.py +1735 -0
  164. disdrodb/l2/event.py +388 -0
  165. disdrodb/l2/processing.py +519 -0
  166. disdrodb/l2/processing_options.py +213 -0
  167. disdrodb/l2/routines.py +868 -0
  168. disdrodb/metadata/__init__.py +9 -2
  169. disdrodb/metadata/checks.py +165 -118
  170. disdrodb/metadata/download.py +81 -0
  171. disdrodb/metadata/geolocation.py +146 -0
  172. disdrodb/metadata/info.py +20 -13
  173. disdrodb/metadata/manipulation.py +1 -1
  174. disdrodb/metadata/reader.py +59 -8
  175. disdrodb/metadata/search.py +77 -144
  176. disdrodb/metadata/standards.py +7 -8
  177. disdrodb/metadata/writer.py +8 -14
  178. disdrodb/psd/__init__.py +38 -0
  179. disdrodb/psd/fitting.py +2146 -0
  180. disdrodb/psd/models.py +774 -0
  181. disdrodb/routines.py +1176 -0
  182. disdrodb/scattering/__init__.py +28 -0
  183. disdrodb/scattering/axis_ratio.py +344 -0
  184. disdrodb/scattering/routines.py +456 -0
  185. disdrodb/utils/__init__.py +17 -0
  186. disdrodb/utils/attrs.py +208 -0
  187. disdrodb/utils/cli.py +269 -0
  188. disdrodb/utils/compression.py +60 -42
  189. disdrodb/utils/dask.py +62 -0
  190. disdrodb/utils/decorators.py +110 -0
  191. disdrodb/utils/directories.py +107 -46
  192. disdrodb/utils/encoding.py +127 -0
  193. disdrodb/utils/list.py +29 -0
  194. disdrodb/utils/logger.py +168 -46
  195. disdrodb/utils/time.py +657 -0
  196. disdrodb/utils/warnings.py +30 -0
  197. disdrodb/utils/writer.py +57 -0
  198. disdrodb/utils/xarray.py +138 -47
  199. disdrodb/utils/yaml.py +0 -1
  200. disdrodb/viz/__init__.py +17 -0
  201. disdrodb/viz/plots.py +17 -0
  202. disdrodb-0.1.0.dist-info/METADATA +321 -0
  203. disdrodb-0.1.0.dist-info/RECORD +216 -0
  204. {disdrodb-0.0.20.dist-info → disdrodb-0.1.0.dist-info}/WHEEL +1 -1
  205. disdrodb-0.1.0.dist-info/entry_points.txt +30 -0
  206. disdrodb/data_transfer/scripts/disdrodb_download_archive.py +0 -53
  207. disdrodb/data_transfer/scripts/disdrodb_upload_archive.py +0 -57
  208. disdrodb/l0/configs/OTT_Parsivel/l0a_encodings.yml +0 -32
  209. disdrodb/l0/configs/OTT_Parsivel2/l0a_encodings.yml +0 -39
  210. disdrodb/l0/configs/RD_80/l0a_encodings.yml +0 -16
  211. disdrodb/l0/configs/RD_80/l0b_encodings.yml +0 -135
  212. disdrodb/l0/configs/Thies_LPM/l0a_encodings.yml +0 -80
  213. disdrodb/l0/io.py +0 -257
  214. disdrodb/l0/l0_processing.py +0 -1091
  215. disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_OTT.py +0 -178
  216. disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_THIES.py +0 -247
  217. disdrodb/l0/readers/BRAZIL/CHUVA_LPM.py +0 -204
  218. disdrodb/l0/readers/BRAZIL/CHUVA_OTT.py +0 -183
  219. disdrodb/l0/readers/BRAZIL/GOAMAZON_LPM.py +0 -204
  220. disdrodb/l0/readers/BRAZIL/GOAMAZON_OTT.py +0 -183
  221. disdrodb/l0/readers/CHINA/CHONGQING.py +0 -131
  222. disdrodb/l0/readers/EPFL/EPFL_ROOF_2008.py +0 -128
  223. disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP2.py +0 -127
  224. disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP3.py +0 -129
  225. disdrodb/l0/readers/EPFL/RACLETS_2019.py +0 -158
  226. disdrodb/l0/readers/EPFL/SAMOYLOV_2017.py +0 -136
  227. disdrodb/l0/readers/EPFL/SAMOYLOV_2019.py +0 -158
  228. disdrodb/l0/readers/FRANCE/SIRTA_OTT2.py +0 -138
  229. disdrodb/l0/readers/GPM/GCPEX.py +0 -123
  230. disdrodb/l0/readers/GPM/IFLOODS.py +0 -123
  231. disdrodb/l0/readers/GPM/MC3E.py +0 -123
  232. disdrodb/l0/readers/GPM/NSSTC.py +0 -164
  233. disdrodb/l0/readers/ITALY/GID.py +0 -199
  234. disdrodb/l0/readers/MEXICO/OH_IIUNAM_nc.py +0 -92
  235. disdrodb/l0/readers/NCAR/CCOPE_2015.py +0 -133
  236. disdrodb/l0/readers/NCAR/PECAN_FP3.py +0 -137
  237. disdrodb/l0/readers/NCAR/PECAN_MOBILE.py +0 -144
  238. disdrodb/l0/readers/NCAR/RELAMPAGO_OTT.py +0 -195
  239. disdrodb/l0/readers/NCAR/SNOWIE_PJ.py +0 -172
  240. disdrodb/l0/readers/NCAR/SNOWIE_SB.py +0 -179
  241. disdrodb/l0/readers/NCAR/VORTEX2_2009.py +0 -133
  242. disdrodb/l0/readers/NCAR/VORTEX2_2010.py +0 -188
  243. disdrodb/l0/readers/NCAR/VORTEX2_2010_UF.py +0 -191
  244. disdrodb/l0/readers/NCAR/VORTEX_SE_2016_P2.py +0 -135
  245. disdrodb/l0/readers/NCAR/VORTEX_SE_2016_PIPS.py +0 -170
  246. disdrodb/l0/readers/NETHERLANDS/DELFT.py +0 -187
  247. disdrodb/l0/readers/SPAIN/SBEGUERIA.py +0 -179
  248. disdrodb/l0/scripts/disdrodb_run_l0b_concat.py +0 -93
  249. disdrodb/l0/scripts/disdrodb_run_l0b_concat_station.py +0 -85
  250. disdrodb/utils/netcdf.py +0 -452
  251. disdrodb/utils/scripts.py +0 -102
  252. disdrodb-0.0.20.dist-info/AUTHORS.md +0 -18
  253. disdrodb-0.0.20.dist-info/METADATA +0 -186
  254. disdrodb-0.0.20.dist-info/RECORD +0 -168
  255. disdrodb-0.0.20.dist-info/entry_points.txt +0 -15
  256. /disdrodb/l0/configs/{RD_80 → RD80}/bins_velocity.yml +0 -0
  257. /disdrodb/l0/manuals/{Thies_LPM.pdf → LPM.pdf} +0 -0
  258. /disdrodb/l0/manuals/{ODM_470.pdf → ODM470.pdf} +0 -0
  259. /disdrodb/l0/manuals/{OTT_Parsivel.pdf → PARSIVEL.pdf} +0 -0
  260. /disdrodb/l0/manuals/{OTT_Parsivel2.pdf → PARSIVEL2.pdf} +0 -0
  261. /disdrodb/l0/manuals/{PWS_100.pdf → PWS100.pdf} +0 -0
  262. /disdrodb/l0/manuals/{RD_80.pdf → RD80.pdf} +0 -0
  263. {disdrodb-0.0.20.dist-info → disdrodb-0.1.0.dist-info/licenses}/LICENSE +0 -0
  264. {disdrodb-0.0.20.dist-info → disdrodb-0.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,519 @@
1
+ # -----------------------------------------------------------------------------.
2
+ # Copyright (c) 2021-2023 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
+ """Implement DISDRODB L2 processing."""
18
+
19
+ import numpy as np
20
+ import xarray as xr
21
+
22
+ from disdrodb.l1.encoding_attrs import get_attrs_dict, get_encoding_dict
23
+ from disdrodb.l1.fall_velocity import get_raindrop_fall_velocity
24
+ from disdrodb.l1_env.routines import load_env_dataset
25
+ from disdrodb.l2.empirical_dsd import (
26
+ compute_integral_parameters,
27
+ compute_spectrum_parameters,
28
+ count_bins_with_drops,
29
+ get_drop_average_velocity,
30
+ get_drop_number_concentration,
31
+ get_effective_sampling_area,
32
+ get_kinetic_energy_variables_from_drop_number,
33
+ get_rain_accumulation,
34
+ get_rain_rate_from_drop_number,
35
+ )
36
+ from disdrodb.psd import create_psd, estimate_model_parameters
37
+ from disdrodb.psd.fitting import compute_gof_stats
38
+ from disdrodb.utils.attrs import set_attrs
39
+ from disdrodb.utils.decorators import check_pytmatrix_availability
40
+ from disdrodb.utils.encoding import set_encodings
41
+ from disdrodb.utils.time import ensure_sample_interval_in_seconds
42
+
43
+
44
+ def define_diameter_array(diameter_min=0, diameter_max=10, diameter_spacing=0.05):
45
+ """
46
+ Define an array of diameters and their corresponding bin properties.
47
+
48
+ Parameters
49
+ ----------
50
+ diameter_min : float, optional
51
+ The minimum diameter value. The default value is 0 mm.
52
+ diameter_max : float, optional
53
+ The maximum diameter value. The default value is 10 mm.
54
+ diameter_spacing : float, optional
55
+ The spacing between diameter values. The default value is 0.05 mm.
56
+
57
+ Returns
58
+ -------
59
+ xr.DataArray
60
+ A DataArray containing the center of each diameter bin, with coordinates for
61
+ the bin width, lower bound, upper bound, and center.
62
+
63
+ """
64
+ diameters_bounds = np.arange(diameter_min, diameter_max + diameter_spacing / 2, step=diameter_spacing)
65
+ diameters_bin_lower = diameters_bounds[:-1]
66
+ diameters_bin_upper = diameters_bounds[1:]
67
+ diameters_bin_width = diameters_bin_upper - diameters_bin_lower
68
+ diameters_bin_center = diameters_bin_lower + diameters_bin_width / 2
69
+ da = xr.DataArray(
70
+ diameters_bin_center,
71
+ dims="diameter_bin_center",
72
+ coords={
73
+ "diameter_bin_width": ("diameter_bin_center", diameters_bin_width),
74
+ "diameter_bin_lower": ("diameter_bin_center", diameters_bin_lower),
75
+ "diameter_bin_upper": ("diameter_bin_center", diameters_bin_upper),
76
+ "diameter_bin_center": ("diameter_bin_center", diameters_bin_center),
77
+ },
78
+ )
79
+ return da
80
+
81
+
82
+ def define_velocity_array(ds):
83
+ """
84
+ Create the fall velocity DataArray using various methods.
85
+
86
+ If 'velocity_bin_center' is a dimension in the dataset, returns a Dataset
87
+ with 'measured_velocity', 'average_velocity', and 'fall_velocity' as variables.
88
+ Otherwise, returns the 'fall_velocity' DataArray from the input dataset.
89
+
90
+ Parameters
91
+ ----------
92
+ ds : xarray.Dataset
93
+ The input dataset containing velocity variables.
94
+
95
+ Returns
96
+ -------
97
+ velocity: xarray.DataArray
98
+ """
99
+ drop_number = ds["drop_number"]
100
+ if "velocity_bin_center" in ds.dims:
101
+ velocity = xr.Dataset(
102
+ {
103
+ "fall_velocity": xr.ones_like(drop_number) * ds["fall_velocity"],
104
+ "measured_velocity": xr.ones_like(drop_number) * ds["velocity_bin_center"],
105
+ },
106
+ ).to_array(dim="velocity_method")
107
+ else:
108
+ velocity = ds["fall_velocity"]
109
+ return velocity
110
+
111
+
112
+ ####--------------------------------------------------------------------------
113
+ #### L2 Empirical Parameters
114
+
115
+
116
+ def generate_l2_empirical(ds, ds_env=None, compute_spectra=False):
117
+ """Generate the DISDRODB L2E dataset from the DISDRODB L1 dataset.
118
+
119
+ Parameters
120
+ ----------
121
+ ds : xarray.Dataset
122
+ DISDRODB L1 dataset.
123
+ ds_env : xarray.Dataset, optional
124
+ Environmental dataset used for fall velocity and water density estimates.
125
+ If None, a default environment dataset will be loaded.
126
+
127
+ Returns
128
+ -------
129
+ xarray.Dataset
130
+ DISRODB L2E dataset.
131
+ """
132
+ # Initialize L2E dataset
133
+ ds_l2 = xr.Dataset()
134
+
135
+ # Retrieve attributes
136
+ attrs = ds.attrs.copy()
137
+
138
+ # -------------------------------------------------------
139
+ #### Preprocessing
140
+ # Discard all timesteps without measured drops
141
+ # - This allow to speed up processing
142
+ # - Regularization can be done at the end
143
+ ds = ds.isel(time=ds["n_drops_selected"] > 0)
144
+
145
+ # Count number of diameter bins with data
146
+ if "n_bins_with_drops" not in ds:
147
+ ds["n_bins_with_drops"] = count_bins_with_drops(ds)
148
+
149
+ # Retrieve ENV dataset or take defaults
150
+ # --> Used for fall velocity and water density estimates
151
+ if ds_env is None:
152
+ ds_env = load_env_dataset(ds)
153
+
154
+ # TODO: Derive water density as function of ENV (temperature, ...)
155
+ # --> (T == 10){density_water <- 999.7}else if(T == 20){density_water <- 998.2}else{density_water <- 995.7}
156
+ water_density = 1000 # kg / m3
157
+
158
+ # Determine if the velocity dimension is available
159
+ has_velocity_dimension = "velocity_bin_center" in ds.dims
160
+
161
+ # -------------------------------------------------------
162
+ # Extract variables from L1
163
+ sensor_name = ds.attrs["sensor_name"]
164
+ diameter = ds["diameter_bin_center"] / 1000 # m
165
+ diameter_bin_width = ds["diameter_bin_width"] # mm
166
+ drop_number = ds["drop_number"]
167
+ sample_interval = ensure_sample_interval_in_seconds(ds["sample_interval"]) # s
168
+
169
+ # Compute sampling area [m2]
170
+ sampling_area = get_effective_sampling_area(sensor_name=sensor_name, diameter=diameter) # m2
171
+
172
+ # Copy relevant L1 variables to L2 product
173
+ variables = [
174
+ "drop_number", # 2D V x D
175
+ "drop_counts", # 1D D
176
+ "sample_interval",
177
+ "n_drops_selected",
178
+ "n_drops_discarded",
179
+ "Dmin",
180
+ "Dmax",
181
+ "fall_velocity",
182
+ ]
183
+
184
+ variables = [var for var in variables if var in ds]
185
+ ds_l2.update(ds[variables])
186
+
187
+ # -------------------------------------------------------------------------------------------
188
+ # Compute and add drop average velocity if an optical disdrometer (i.e OTT Parsivel or ThiesLPM)
189
+ # - We recompute it because if the input dataset is aggregated, it must be updated !
190
+ if has_velocity_dimension:
191
+ ds["drop_average_velocity"] = get_drop_average_velocity(ds["drop_number"])
192
+
193
+ # -------------------------------------------------------------------------------------------
194
+ # Define velocity array with dimension 'velocity_method'
195
+ velocity = define_velocity_array(ds)
196
+
197
+ # Compute drop number concentration (Nt) [#/m3/mm]
198
+ drop_number_concentration = get_drop_number_concentration(
199
+ drop_number=drop_number,
200
+ velocity=velocity,
201
+ diameter_bin_width=diameter_bin_width,
202
+ sample_interval=sample_interval,
203
+ sampling_area=sampling_area,
204
+ )
205
+ ds_l2["drop_number_concentration"] = drop_number_concentration
206
+
207
+ # -------------------------------------------------------
208
+ #### Compute L2 spectra
209
+ if compute_spectra:
210
+ ds_spectrum = compute_spectrum_parameters(
211
+ drop_number_concentration,
212
+ velocity=ds["fall_velocity"],
213
+ diameter=diameter,
214
+ sample_interval=sample_interval,
215
+ water_density=water_density,
216
+ )
217
+ ds_l2.update(ds_spectrum)
218
+
219
+ # ----------------------------------------------------------------------------
220
+ #### Compute L2 integral parameters from drop_number_concentration
221
+ ds_parameters = compute_integral_parameters(
222
+ drop_number_concentration=drop_number_concentration,
223
+ velocity=ds["fall_velocity"],
224
+ diameter=diameter,
225
+ diameter_bin_width=diameter_bin_width,
226
+ sample_interval=sample_interval,
227
+ water_density=water_density,
228
+ )
229
+
230
+ # -------------------------------------------------------
231
+ #### Compute R and P from drop number (without velocity assumptions)
232
+ # - Rain rate and accumulation computed with this method are not influenced by the fall velocity of drops !
233
+ ds_l2["Rm"] = get_rain_rate_from_drop_number(
234
+ drop_number=drop_number,
235
+ sampling_area=sampling_area,
236
+ diameter=diameter,
237
+ sample_interval=sample_interval,
238
+ )
239
+ # Compute rain accumulation (P) [mm]
240
+ ds_l2["Pm"] = get_rain_accumulation(rain_rate=ds_l2["Rm"], sample_interval=sample_interval)
241
+
242
+ # -------------------------------------------------------
243
+ #### Compute KE integral parameters directly from drop_number
244
+ # - The kinetic energy variables can be computed using the actual measured fall velocity by the sensor.
245
+ if has_velocity_dimension:
246
+ ds_ke = get_kinetic_energy_variables_from_drop_number(
247
+ drop_number=drop_number,
248
+ diameter=diameter,
249
+ velocity=velocity,
250
+ sampling_area=sampling_area,
251
+ sample_interval=sample_interval,
252
+ water_density=water_density,
253
+ )
254
+ # Combine integral parameters
255
+ ke_vars = list(ds_ke.data_vars)
256
+ ds_ke = ds_ke.expand_dims(dim={"source": ["drop_number"]}, axis=-1)
257
+ ds_ke_dsd = ds_parameters[ke_vars].expand_dims(dim={"source": ["drop_number_concentration"]}, axis=-1)
258
+ ds_ke = xr.concat((ds_ke_dsd, ds_ke), dim="source")
259
+ ds_parameters = ds_parameters.drop_vars(ke_vars)
260
+ for var in ke_vars:
261
+ ds_parameters[var] = ds_ke[var]
262
+
263
+ # ----------------------------------------------------------------------------
264
+ #### Finalize L2 Dataset
265
+ # Add DSD integral parameters
266
+ ds_l2.update(ds_parameters)
267
+
268
+ # ----------------------------------------------------------------------------.
269
+ #### Add encodings and attributes
270
+ # Add variables attributes
271
+ attrs_dict = get_attrs_dict()
272
+ ds_l2 = set_attrs(ds_l2, attrs_dict=attrs_dict)
273
+
274
+ # Add variables encoding
275
+ encoding_dict = get_encoding_dict()
276
+ ds_l2 = set_encodings(ds_l2, encoding_dict=encoding_dict)
277
+
278
+ # Add global attributes
279
+ ds_l2.attrs = attrs
280
+
281
+ return ds_l2
282
+
283
+
284
+ ####--------------------------------------------------------------------------
285
+ #### L2 Model Parameters
286
+
287
+
288
+ def generate_l2_model(
289
+ ds,
290
+ ds_env=None,
291
+ fall_velocity_method="Beard1976",
292
+ # PSD discretization
293
+ diameter_min=0,
294
+ diameter_max=8,
295
+ diameter_spacing=0.05,
296
+ # Fitting options
297
+ psd_model=None,
298
+ optimization=None,
299
+ optimization_kwargs=None,
300
+ # Filtering options
301
+ min_bins_with_drops=4,
302
+ remove_timesteps_with_few_bins=False,
303
+ mask_timesteps_with_few_bins=False,
304
+ # GOF metrics options
305
+ gof_metrics=True,
306
+ ):
307
+ """
308
+ Generate the DISDRODB L2M dataset from a DISDRODB L2E dataset.
309
+
310
+ This function estimates PSD model parameters and successively computes DSD integral parameters.
311
+ Optionally, radar variables at various bands are simulated using T-matrix simulations.
312
+ Goodness-of-fit metrics of the PSD can also be optionally included into the output dataset.
313
+
314
+ Parameters
315
+ ----------
316
+ ds : xarray.Dataset
317
+ DISDRODB L2E dataset.
318
+ ds_env : xarray.Dataset, optional
319
+ Environmental dataset used for fall velocity and water density estimates.
320
+ If None, a default environment dataset will be loaded.
321
+ diameter_min : float, optional
322
+ Minimum PSD diameter. The default value is 0 mm.
323
+ diameter_max : float, optional
324
+ Maximum PSD diameter. The default value is 8 mm.
325
+ diameter_spacing : float, optional
326
+ PSD diameter spacing. The default value is 0.05 mm.
327
+ psd_model : str
328
+ The PSD model to fit. See ``available_psd_models()``.
329
+ optimization : str, optional
330
+ The fitting optimization procedure. Either "GS" (Grid Search), "ML (Maximum Likelihood)
331
+ or "MOM" (Method of Moments).
332
+ optimization_kwargs : dict, optional
333
+ Dictionary with arguments to customize the fitting procedure.
334
+ gof_metrics : bool, optional
335
+ Whether to add goodness-of-fit metrics to the output dataset. The default is True.
336
+
337
+ Returns
338
+ -------
339
+ xarray.Dataset
340
+ DISDRODB L2M dataset.
341
+ """
342
+ # ----------------------------------------------------------------------------.
343
+ #### NOTES
344
+ # - Final processing: Optionally filter dataset only when PSD has fitted ?
345
+ # --> but good to have everything to compare across models
346
+
347
+ # ----------------------------------------------------------------------------.
348
+ # Retrieve attributes
349
+ attrs = ds.attrs.copy()
350
+
351
+ # -------------------------------------------------------
352
+ # Derive water density as function of ENV (temperature, ...)
353
+ # TODO --> Add into ds_env !
354
+ # --> (T == 10){density_water <- 999.7}else if(T == 20){density_water <- 998.2}else{density_water <- 995.7}
355
+ water_density = 1000 # kg / m3
356
+
357
+ ####------------------------------------------------------.
358
+ #### Preprocessing
359
+ # Count number of diameter bins with data
360
+ if "n_bins_with_drops" not in ds:
361
+ ds["n_bins_with_drops"] = count_bins_with_drops(ds)
362
+
363
+ # Identify timesteps with enough diameter bins with counted trops
364
+ valid_timesteps = ds["n_bins_with_drops"] >= min_bins_with_drops
365
+
366
+ # Drop such timesteps if asked
367
+ if remove_timesteps_with_few_bins:
368
+ mask_timesteps_with_few_bins = False
369
+ ds = ds.isel(time=valid_timesteps, drop=False)
370
+
371
+ # Retrieve ENV dataset or take defaults
372
+ # --> Used for fall velocity and water density estimates
373
+ if ds_env is None:
374
+ ds_env = load_env_dataset(ds)
375
+
376
+ ####------------------------------------------------------.
377
+ #### Define default PSD optimization arguments
378
+ if psd_model is None and optimization is None:
379
+ psd_model = "NormalizedGammaPSD"
380
+ optimization = "GS"
381
+ optimization_kwargs = {
382
+ "target": "ND",
383
+ "transformation": "identity",
384
+ "error_order": 1, # MAE
385
+ }
386
+
387
+ ####------------------------------------------------------.
388
+ #### Retrieve PSD parameters
389
+ ds_psd_params = estimate_model_parameters(
390
+ ds=ds,
391
+ psd_model=psd_model,
392
+ optimization=optimization,
393
+ optimization_kwargs=optimization_kwargs,
394
+ )
395
+
396
+ ####------------------------------------------------------.
397
+ #### Mask timesteps with few bins if asked
398
+ if mask_timesteps_with_few_bins:
399
+ ds_psd_params = ds_psd_params.where(valid_timesteps)
400
+
401
+ ####-------------------------------------------------------
402
+ #### Create PSD
403
+ psd_name = ds_psd_params.attrs["disdrodb_psd_model"]
404
+ psd = create_psd(psd_name, parameters=ds_psd_params)
405
+
406
+ ####-------------------------------------------------------
407
+ #### Compute integral parameters
408
+ # Define diameter array
409
+ diameter = define_diameter_array(
410
+ diameter_min=diameter_min,
411
+ diameter_max=diameter_max,
412
+ diameter_spacing=diameter_spacing,
413
+ )
414
+ diameter_bin_width = diameter["diameter_bin_width"]
415
+
416
+ # Retrieve time of integration
417
+ # - If dataset is opened with decode_timedelta=False, sample_interval is already in seconds !
418
+ sample_interval = ensure_sample_interval_in_seconds(ds["sample_interval"])
419
+
420
+ # Retrieve drop number concentration
421
+ drop_number_concentration = psd(diameter)
422
+
423
+ # Retrieve fall velocity for each new diameter bin
424
+ velocity = get_raindrop_fall_velocity(diameter=diameter, method=fall_velocity_method, ds_env=ds_env) # mm
425
+
426
+ # Compute integral parameters
427
+ ds_params = compute_integral_parameters(
428
+ drop_number_concentration=drop_number_concentration,
429
+ velocity=velocity,
430
+ diameter=diameter / 1000, # in meters !
431
+ diameter_bin_width=diameter_bin_width,
432
+ sample_interval=sample_interval,
433
+ water_density=water_density,
434
+ )
435
+
436
+ #### ----------------------------------------------------------------------------
437
+ #### Create L2 Dataset
438
+ # Update with PSD parameters
439
+ ds_params.update(ds_psd_params)
440
+
441
+ # Add GOF statistics if asked
442
+ if gof_metrics:
443
+ ds_gof = compute_gof_stats(drop_number_concentration=ds["drop_number_concentration"], psd=psd)
444
+ ds_params.update(ds_gof)
445
+
446
+ #### ----------------------------------------------------------------------------.
447
+ #### Add encodings and attributes
448
+ # Add variables attributes
449
+ attrs_dict = get_attrs_dict()
450
+ ds_params = set_attrs(ds_params, attrs_dict=attrs_dict)
451
+
452
+ # Add variables encoding
453
+ encoding_dict = get_encoding_dict()
454
+ ds_params = set_encodings(ds_params, encoding_dict=encoding_dict)
455
+
456
+ # Add global attributes
457
+ ds_params.attrs = attrs
458
+ ds_params.attrs["disdrodb_psd_model"] = psd_name
459
+
460
+ # Return dataset
461
+ return ds_params
462
+
463
+
464
+ ####-------------------------------------------------------------------------------------------------------------------.
465
+ #### L2 Radar Parameters
466
+
467
+
468
+ @check_pytmatrix_availability
469
+ def generate_l2_radar(ds, radar_band=None, canting_angle_std=7, diameter_max=8, axis_ratio="Thurai2007", parallel=True):
470
+ """Simulate polarimetric radar variables from empirical drop number concentration or the estimated PSD.
471
+
472
+ Parameters
473
+ ----------
474
+ ds : xarray.Dataset
475
+ Dataset containing the drop number concentration variable or the PSD parameters.
476
+ radar_band : str or list of str, optional
477
+ Radar band(s) to be used.
478
+ If ``None`` (the default), all available radar bands are used.
479
+ canting_angle_std : float or list of float, optional
480
+ Standard deviation of the canting angle. The default value is 7.
481
+ diameter_max : float or list of float, optional
482
+ Maximum diameter. The default value is 8 mm.
483
+ axis_ratio : str or list of str, optional
484
+ Method to compute the axis ratio. The default method is ``Thurai2007``.
485
+ parallel : bool, optional
486
+ Whether to compute radar variables in parallel.
487
+ The default value is ``True``.
488
+
489
+ Returns
490
+ -------
491
+ xarray.Dataset
492
+ Dataset containing the computed radar parameters.
493
+ """
494
+ # Import here to avoid pytmatrix has mandatory dependency
495
+ # - It is only needed for radar simulation
496
+ from disdrodb.scattering import get_radar_parameters
497
+
498
+ # Retrieve radar variables from L2E drop number concentration or from estimated L2M PSD model
499
+ ds_radar = get_radar_parameters(
500
+ ds=ds,
501
+ radar_band=radar_band,
502
+ canting_angle_std=canting_angle_std,
503
+ diameter_max=diameter_max,
504
+ axis_ratio=axis_ratio,
505
+ parallel=parallel,
506
+ )
507
+
508
+ #### ----------------------------------------------------------------------------.
509
+ #### Add encodings and attributes
510
+ # Add variables attributes
511
+ attrs_dict = get_attrs_dict()
512
+ ds_radar = set_attrs(ds_radar, attrs_dict=attrs_dict)
513
+
514
+ # Add variables encoding
515
+ encoding_dict = get_encoding_dict()
516
+ ds_radar = set_encodings(ds_radar, encoding_dict=encoding_dict)
517
+
518
+ # Return dataset
519
+ return ds_radar