disdrodb 0.0.21__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.21.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.21.dist-info/AUTHORS.md +0 -18
  253. disdrodb-0.0.21.dist-info/METADATA +0 -186
  254. disdrodb-0.0.21.dist-info/RECORD +0 -168
  255. disdrodb-0.0.21.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.21.dist-info → disdrodb-0.1.0.dist-info/licenses}/LICENSE +0 -0
  264. {disdrodb-0.0.21.dist-info → disdrodb-0.1.0.dist-info}/top_level.txt +0 -0
@@ -32,23 +32,25 @@ from disdrodb.l0.check_standards import (
32
32
  from disdrodb.l0.standards import (
33
33
  # get_valid_coordinates_names,
34
34
  get_bin_coords_dict,
35
- get_coords_attrs_dict,
36
35
  get_data_range_dict,
37
36
  get_dims_size_dict,
38
37
  get_l0b_cf_attrs_dict,
39
38
  get_l0b_encodings_dict,
40
39
  get_raw_array_dims_order,
41
40
  get_raw_array_nvalues,
42
- get_time_encoding,
41
+ )
42
+ from disdrodb.utils.attrs import (
43
+ set_coordinate_attributes,
43
44
  set_disdrodb_attrs,
44
45
  )
45
46
  from disdrodb.utils.directories import create_directory, remove_if_exists
47
+ from disdrodb.utils.encoding import set_encodings
46
48
  from disdrodb.utils.logger import (
47
49
  # log_warning,
48
50
  # log_debug,
49
- log_error,
50
51
  log_info,
51
52
  )
53
+ from disdrodb.utils.time import ensure_sorted_by_time
52
54
 
53
55
  logger = logging.getLogger(__name__)
54
56
 
@@ -78,10 +80,7 @@ def infer_split_str(string: str) -> str:
78
80
  idx_delimiter = np.argmax(counts)
79
81
  # If don't find the delimiter, set to None
80
82
  # --> The array will not be split, and then raise an error later on
81
- if counts[idx_delimiter] == 0:
82
- split_str = None
83
- else:
84
- split_str = valid_delims[idx_delimiter]
83
+ split_str = None if counts[idx_delimiter] == 0 else valid_delims[idx_delimiter]
85
84
  else:
86
85
  split_str = None # ''.split(None) output []
87
86
  return split_str
@@ -114,7 +113,6 @@ def _format_string_array(string: str, n_values: int) -> np.array:
114
113
  np.array
115
114
  array of float
116
115
  """
117
-
118
116
  split_str = infer_split_str(string)
119
117
  values = np.array(string.strip(split_str).split(split_str))
120
118
 
@@ -160,16 +158,17 @@ def _reshape_raw_spectrum(
160
158
  dims_order : list
161
159
  The order of dimension in the raw spectrum.
162
160
 
163
- Examples:
164
- - OTT Parsivel spectrum [v1d1 ... v1d32, v2d1, ..., v2d32]
161
+ Examples
162
+ --------
163
+ - OTT PARSIVEL spectrum [v1d1 ... v1d32, v2d1, ..., v2d32]
165
164
  --> dims_order = ["diameter_bin_center", "velocity_bin_center"]
166
165
  - Thies LPM spectrum [v1d1 ... v20d1, v1d2, ..., v20d2]
167
166
  --> dims_order = ["velocity_bin_center", "diameter_bin_center"]
168
167
  dims_size_dict : dict
169
168
  Dictionary with the number of bins for each dimension.
170
- For OTT_Parsivel:
169
+ For PARSIVEL and PARSIVEL2:
171
170
  {"diameter_bin_center": 32, "velocity_bin_center": 32}
172
- For This_LPM
171
+ For LPM
173
172
  {"diameter_bin_center": 22, "velocity_bin_center": 20}
174
173
  n_timesteps : int
175
174
  Number of timesteps.
@@ -185,14 +184,13 @@ def _reshape_raw_spectrum(
185
184
  Impossible to reshape the raw_spectrum matrix
186
185
  """
187
186
  # Define output dimensions
188
- dims = ["time"] + dims_order
187
+ dims = ["time", *dims_order]
189
188
  # Retrieve reshaping dimensions as function of dimension order
190
189
  reshape_dims = [n_timesteps] + [dims_size_dict[dim] for dim in dims_order]
191
190
  try:
192
191
  arr = arr.reshape(reshape_dims)
193
192
  except Exception as e:
194
193
  msg = f"Impossible to reshape the raw_spectrum matrix. The error is: \n {e}"
195
- log_error(logger=logger, msg=msg, verbose=False)
196
194
  raise ValueError(msg)
197
195
  return arr, dims
198
196
 
@@ -200,13 +198,14 @@ def _reshape_raw_spectrum(
200
198
  def retrieve_l0b_arrays(
201
199
  df: pd.DataFrame,
202
200
  sensor_name: str,
201
+ logger=None,
203
202
  verbose: bool = False,
204
203
  ) -> dict:
205
204
  """Retrieves the L0B data matrix.
206
205
 
207
206
  Parameters
208
207
  ----------
209
- df : pd.DataFrame
208
+ df : pandas.DataFrame
210
209
  Input dataframe
211
210
  sensor_name : str
212
211
  Name of the sensor
@@ -217,12 +216,11 @@ def retrieve_l0b_arrays(
217
216
  Dictionary with data arrays.
218
217
 
219
218
  """
220
-
221
- msg = " - Retrieval of L0B data arrays started."
219
+ msg = "Retrieval of L0B data arrays started."
222
220
  log_info(logger=logger, msg=msg, verbose=verbose)
223
221
  # ----------------------------------------------------------.
224
222
  # Check L0 raw field availability
225
- _check_raw_fields_available(df=df, sensor_name=sensor_name)
223
+ _check_raw_fields_available(df=df, sensor_name=sensor_name, logger=logger, verbose=verbose)
226
224
 
227
225
  # Retrieve the number of values expected for each array
228
226
  n_values_dict = get_raw_array_nvalues(sensor_name=sensor_name)
@@ -258,8 +256,8 @@ def retrieve_l0b_arrays(
258
256
 
259
257
  # For key='raw_drop_number', if 2D spectrum, reshape to 2D matrix
260
258
  # Example:
261
- # - This applies i.e for OTT_Parsivel* and Thies_LPM
262
- # - This does not apply to RD_80
259
+ # - This applies i.e for PARSIVEL* and LPM
260
+ # - This does not apply to RD80
263
261
  if key == "raw_drop_number" and len(dims_order) == 2:
264
262
  arr, dims = _reshape_raw_spectrum(
265
263
  arr=arr,
@@ -269,14 +267,14 @@ def retrieve_l0b_arrays(
269
267
  )
270
268
  else:
271
269
  # Otherwise just define the dimensions of the array
272
- dims = ["time"] + dims_order
270
+ dims = ["time", *dims_order]
273
271
 
274
272
  # Define dictionary to pass to xr.Dataset
275
273
  dict_data[key] = (dims, arr)
276
274
 
277
275
  # -------------------------------------------------------------------------.
278
276
  # Log
279
- msg = " - Retrieval of L0B data arrays ended."
277
+ msg = "Retrieval of L0B data arrays ended."
280
278
  log_info(logger=logger, msg=msg, verbose=verbose)
281
279
  # Return
282
280
  return dict_data
@@ -287,16 +285,16 @@ def retrieve_l0b_arrays(
287
285
 
288
286
 
289
287
  def _convert_object_variables_to_string(ds: xr.Dataset) -> xr.Dataset:
290
- """Convert variables with object dtype to string.
288
+ """Convert variables with ``object`` dtype to ``string``.
291
289
 
292
290
  Parameters
293
291
  ----------
294
- ds : xr.Dataset
292
+ ds : xarray.Dataset
295
293
  Input dataset.
296
294
 
297
295
  Returns
298
296
  -------
299
- xr.Dataset
297
+ xarray.Dataset
300
298
  Output dataset.
301
299
  """
302
300
  for var in ds.data_vars:
@@ -306,11 +304,11 @@ def _convert_object_variables_to_string(ds: xr.Dataset) -> xr.Dataset:
306
304
 
307
305
 
308
306
  def _set_variable_attributes(ds: xr.Dataset, sensor_name: str) -> xr.Dataset:
309
- """Set attributes to each xr.Dataset variable.
307
+ """Set attributes to each ``xr.Dataset`` variable.
310
308
 
311
309
  Parameters
312
310
  ----------
313
- ds : xr.Dataset
311
+ ds : xarray.Dataset
314
312
  Input dataset.
315
313
  sensor_name : str
316
314
  Name of the sensor.
@@ -333,35 +331,20 @@ def _set_variable_attributes(ds: xr.Dataset, sensor_name: str) -> xr.Dataset:
333
331
  return ds
334
332
 
335
333
 
336
- def _set_attrs_dict(ds, attrs_dict):
337
- for var in attrs_dict.keys():
338
- if var in ds:
339
- ds[var].attrs.update(attrs_dict[var])
340
- return ds
341
-
342
-
343
- def _set_coordinate_attributes(ds):
344
- # Get attributes dictionary
345
- attrs_dict = get_coords_attrs_dict(ds)
346
- # Set attributes
347
- ds = _set_attrs_dict(ds, attrs_dict)
348
- return ds
349
-
350
-
351
334
  def _set_dataset_attrs(ds, sensor_name):
352
335
  """Set variable and coordinates attributes."""
353
336
  # - Add netCDF variable attributes
354
337
  # --> Attributes: long_name, units, descriptions, valid_min, valid_max
355
338
  ds = _set_variable_attributes(ds=ds, sensor_name=sensor_name)
356
339
  # - Add netCDF coordinate attributes
357
- ds = _set_coordinate_attributes(ds=ds)
340
+ ds = set_coordinate_attributes(ds=ds)
358
341
  # - Set DISDRODB global attributes
359
342
  ds = set_disdrodb_attrs(ds=ds, product="L0B")
360
343
  return ds
361
344
 
362
345
 
363
346
  def add_dataset_crs_coords(ds):
364
- "Add the CRS coordinate to the xr.Dataset"
347
+ """Add the CRS coordinate to the xr.Dataset."""
365
348
  # TODO: define CF-compliant CRS !
366
349
  # - CF compliant
367
350
  # - wkt
@@ -377,75 +360,54 @@ def add_dataset_crs_coords(ds):
377
360
  #### L0B Raw DataFrame Preprocessing
378
361
 
379
362
 
380
- def _define_dataset_variables(df, sensor_name, verbose):
363
+ def _define_dataset_variables(df, sensor_name, logger=None, verbose=False):
381
364
  """Define DISDRODB L0B netCDF variables."""
382
365
  # Preprocess raw_spectrum, diameter and velocity arrays if available
383
366
  raw_fields = ["raw_drop_concentration", "raw_drop_average_velocity", "raw_drop_number"]
384
367
  if np.any(np.isin(raw_fields, df.columns)):
385
368
  # Retrieve dictionary of raw data matrices for xarray Dataset
386
- data_vars = retrieve_l0b_arrays(df, sensor_name, verbose=verbose)
369
+ data_vars = retrieve_l0b_arrays(df, sensor_name=sensor_name, logger=logger, verbose=verbose)
387
370
  else:
388
371
  raise ValueError("No raw fields available.")
389
372
 
390
373
  # Define other disdrometer 'auxiliary' variables varying over time dimension
374
+ # - Includes time
375
+ # - Includes longitude and latitude for moving sensors
391
376
  valid_core_fields = [
392
377
  "raw_drop_concentration",
393
378
  "raw_drop_average_velocity",
394
379
  "raw_drop_number",
395
- "time",
396
- # longitude and latitude too for moving sensors
397
380
  ]
398
381
  aux_columns = df.columns[np.isin(df.columns, valid_core_fields, invert=True)]
399
- aux_data_vars = {column: (["time"], df[column].values) for column in aux_columns}
382
+ aux_data_vars = {column: (["time"], df[column].to_numpy()) for column in aux_columns}
400
383
  data_vars.update(aux_data_vars)
401
-
402
- # Add key "time"
403
- # - Is dropped in _define_coordinates !
404
- data_vars["time"] = df["time"].values
405
-
406
384
  return data_vars
407
385
 
408
386
 
409
- def _define_coordinates(data_vars, attrs, sensor_name):
410
- """Define DISDRODB L0B netCDF coordinates."""
411
- # Note: attrs and data_vars are modified in place !
412
-
413
- # - Diameter and velocity
414
- coords = get_bin_coords_dict(sensor_name=sensor_name)
415
-
416
- # - Geolocation + Time
417
- geolocation_vars = ["time", "latitude", "longitude", "altitude"]
418
- for var in geolocation_vars:
419
- if var in data_vars:
420
- coords[var] = data_vars[var]
421
- _ = data_vars.pop(var)
422
- _ = attrs.pop(var, None)
423
- else:
424
- coords[var] = attrs[var]
425
- _ = attrs.pop(var)
426
- return coords
427
-
428
-
429
387
  def create_l0b_from_l0a(
430
388
  df: pd.DataFrame,
431
- attrs: dict,
389
+ metadata: dict,
390
+ logger=None,
432
391
  verbose: bool = False,
433
392
  ) -> xr.Dataset:
434
393
  """Transform the L0A dataframe to the L0B xr.Dataset.
435
394
 
436
395
  Parameters
437
396
  ----------
438
- df : pd.DataFrame
397
+ df : pandas.DataFrame
439
398
  DISDRODB L0A dataframe.
440
- attrs : dict
441
- Station metadata.
399
+ The raw drop number spectrum is reshaped to a 2D(+time) array.
400
+ The raw drop concentration and velocity are reshaped to 1D(+time) arrays.
401
+ metadata : dict
402
+ DISDRODB station metadata.
403
+ To use this function outside the DISDRODB routines, the dictionary must
404
+ contain the fields: ``sensor_name``, ``latitude``, ``longitude``, ``altitude``, ``platform_type``.
442
405
  verbose : bool, optional
443
- Whether to verbose the processing.
444
- The default is False.
406
+ Whether to verbose the processing. The default value is ``False``.
445
407
 
446
408
  Returns
447
409
  -------
448
- xr.Dataset
410
+ xarray.Dataset
449
411
  DISDRODB L0B dataset.
450
412
 
451
413
  Raises
@@ -454,27 +416,15 @@ def create_l0b_from_l0a(
454
416
  Error if the DISDRODB L0B xarray dataset can not be created.
455
417
  """
456
418
  # Retrieve sensor name
457
- attrs = attrs.copy()
419
+ attrs = metadata.copy()
458
420
  sensor_name = attrs["sensor_name"]
459
- # -----------------------------------------------------------.
460
- # Define Dataset variables and coordinates
461
- data_vars = _define_dataset_variables(df, sensor_name=sensor_name, verbose=verbose)
462
421
 
463
- # -----------------------------------------------------------.
464
- # Define coordinates for xarray Dataset
465
- # - attrs and data_vars are modified in place !
466
- coords = _define_coordinates(data_vars, attrs=attrs, sensor_name=sensor_name)
422
+ # Define Dataset variables and coordinates
423
+ data_vars = _define_dataset_variables(df, sensor_name=sensor_name, logger=logger, verbose=verbose)
467
424
 
468
- # -----------------------------------------------------------
469
425
  # Create xarray Dataset
470
- ds = xr.Dataset(
471
- data_vars=data_vars,
472
- coords=coords,
473
- attrs=attrs,
474
- )
475
- ds = finalize_dataset(ds, sensor_name=sensor_name)
476
-
477
- # -----------------------------------------------------------
426
+ ds = xr.Dataset(data_vars=data_vars)
427
+ ds = finalize_dataset(ds, sensor_name=sensor_name, attrs=attrs)
478
428
  return ds
479
429
 
480
430
 
@@ -482,8 +432,43 @@ def create_l0b_from_l0a(
482
432
  #### L0B netCDF4 Writer
483
433
 
484
434
 
485
- def finalize_dataset(ds, sensor_name):
435
+ def set_geolocation_coordinates(ds, attrs):
436
+ """Add geolocation coordinates to dataset."""
437
+ # Assumption
438
+ # - If coordinate is present in L0A, overrides the one specified in the attributes
439
+ # - If a station is fixed, discard the coordinates in the DISDRODB reader !
440
+
441
+ # Assign geolocation coordinates to dataset
442
+ coords = ["latitude", "longitude", "altitude"]
443
+ for coord in coords:
444
+ # If coordinate not present, add it from dictionary
445
+ if coord not in ds:
446
+ ds = ds.assign_coords({coord: attrs.pop(coord, np.nan)})
447
+ # Else if set coordinates the variable in the dataset (present in the raw data)
448
+ else:
449
+ ds = ds.set_coords(coord)
450
+ _ = attrs.pop(coord, None)
451
+
452
+ # Set -9999 flag value to np.nan
453
+ for coord in coords:
454
+ ds[coord] = xr.where(ds[coord] == -9999, np.nan, ds[coord])
455
+
456
+ # Set attributes without geolocation coordinates
457
+ ds.attrs = attrs
458
+ return ds
459
+
460
+
461
+ def finalize_dataset(ds, sensor_name, attrs):
486
462
  """Finalize DISDRODB L0B Dataset."""
463
+ # Ensure sorted by time
464
+ ds = ensure_sorted_by_time(ds)
465
+
466
+ # Set diameter and velocity bin coordinates
467
+ ds = ds.assign_coords(get_bin_coords_dict(sensor_name=sensor_name))
468
+
469
+ # Set geolocation coordinates and attributes
470
+ ds = set_geolocation_coordinates(ds, attrs=attrs)
471
+
487
472
  # Add dataset CRS coordinate
488
473
  ds = add_dataset_crs_coords(ds)
489
474
 
@@ -501,88 +486,23 @@ def finalize_dataset(ds, sensor_name):
501
486
  return ds
502
487
 
503
488
 
504
- def sanitize_encodings_dict(encoding_dict: dict, ds: xr.Dataset) -> dict:
505
- """Ensure chunk size to be smaller than the array shape.
489
+ def set_l0b_encodings(ds: xr.Dataset, sensor_name: str):
490
+ """Apply the L0B encodings to the xarray Dataset.
506
491
 
507
492
  Parameters
508
493
  ----------
509
- encoding_dict : dict
510
- Dictionary containing the encoding to write DISDRODB L0B netCDFs.
511
- ds : xr.Dataset
512
- Input dataset.
513
-
514
- Returns
515
- -------
516
- dict
517
- Encoding dictionary.
518
- """
519
- for var in ds.data_vars:
520
- shape = ds[var].shape
521
- chunks = encoding_dict[var]["chunksizes"]
522
- if chunks is not None:
523
- chunks = [shape[i] if chunks[i] > shape[i] else chunks[i] for i in range(len(chunks))]
524
- encoding_dict[var]["chunksizes"] = chunks
525
- return encoding_dict
526
-
527
-
528
- def rechunk_dataset(ds: xr.Dataset, encoding_dict: dict) -> xr.Dataset:
529
- """Coerce the dataset arrays to have the chunk size specified in the encoding dictionary.
530
-
531
- Parameters
532
- ----------
533
- ds : xr.Dataset
534
- Input xarray dataset
535
- encoding_dict : dict
536
- Dictionary containing the encoding to write the xarray dataset as a netCDF.
537
-
538
- Returns
539
- -------
540
- xr.Dataset
541
- Output xarray dataset
542
- """
543
-
544
- for var in ds.data_vars:
545
- chunks = encoding_dict[var].pop("chunksizes")
546
- dims = list(ds[var].dims)
547
- chunks_dict = dict(zip(dims, chunks))
548
- if chunks is not None:
549
- ds[var] = ds[var].chunk(chunks_dict)
550
- return ds
551
-
552
-
553
- def set_encodings(ds: xr.Dataset, sensor_name: str) -> xr.Dataset:
554
- """Apply the encodings to the xarray Dataset.
555
-
556
- Parameters
557
- ----------
558
- ds : xr.Dataset
494
+ ds : xarray.Dataset
559
495
  Input xarray dataset.
560
496
  sensor_name : str
561
497
  Name of the sensor.
562
498
 
563
499
  Returns
564
500
  -------
565
- xr.Dataset
501
+ xarray.Dataset
566
502
  Output xarray dataset.
567
503
  """
568
- # Get encoding dictionary
569
504
  encoding_dict = get_l0b_encodings_dict(sensor_name)
570
- encoding_dict = {k: encoding_dict[k] for k in ds.data_vars}
571
-
572
- # Ensure chunksize smaller than the array shape
573
- encoding_dict = sanitize_encodings_dict(encoding_dict, ds)
574
-
575
- # Rechunk variables for fast writing !
576
- # - This pop the chunksize argument from the encoding dict !
577
- ds = rechunk_dataset(ds, encoding_dict)
578
-
579
- # Set time encoding
580
- ds["time"].encoding.update(get_time_encoding())
581
-
582
- # Set the variable encodings
583
- for var in ds.data_vars:
584
- ds[var].encoding.update(encoding_dict[var])
585
-
505
+ ds = set_encodings(ds=ds, encoding_dict=encoding_dict)
586
506
  return ds
587
507
 
588
508
 
@@ -591,7 +511,7 @@ def write_l0b(ds: xr.Dataset, filepath: str, force=False) -> None:
591
511
 
592
512
  Parameters
593
513
  ----------
594
- ds : xr.Dataset
514
+ ds : xarray.Dataset
595
515
  Input xarray dataset.
596
516
  filepath : str
597
517
  Output file path.
@@ -599,8 +519,8 @@ def write_l0b(ds: xr.Dataset, filepath: str, force=False) -> None:
599
519
  Name of the sensor.
600
520
  force : bool, optional
601
521
  Whether to overwrite existing data.
602
- If True, overwrite existing data into destination directories.
603
- If False, raise an error if there are already data into destination directories. This is the default.
522
+ If ``True``, overwrite existing data into destination directories.
523
+ If ``False``, raise an error if there are already data into destination directories. This is the default.
604
524
  """
605
525
  # Create station directory if does not exist
606
526
  create_directory(os.path.dirname(filepath))
@@ -614,7 +534,7 @@ def write_l0b(ds: xr.Dataset, filepath: str, force=False) -> None:
614
534
  sensor_name = ds.attrs.get("sensor_name")
615
535
 
616
536
  # Set encodings
617
- ds = set_encodings(ds=ds, sensor_name=sensor_name)
537
+ ds = set_l0b_encodings(ds=ds, sensor_name=sensor_name)
618
538
 
619
539
  # Write netcdf
620
540
  ds.to_netcdf(filepath, engine="netcdf4")