disdrodb 0.0.21__py3-none-any.whl → 0.1.1__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 (279) 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 +306 -270
  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 +46 -51
  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 +84 -65
  57. disdrodb/l0/configs/{Thies_LPM → LPM}/l0b_encodings.yml +50 -9
  58. disdrodb/l0/configs/{Thies_LPM → LPM}/raw_data_format.yml +285 -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 +23 -21
  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 +28 -26
  69. disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/l0b_encodings.yml +20 -20
  70. disdrodb/l0/configs/{OTT_Parsivel2 → PARSIVEL2}/raw_data_format.yml +107 -107
  71. disdrodb/l0/configs/PWS100/bins_diameter.yml +173 -0
  72. disdrodb/l0/configs/PWS100/bins_velocity.yml +173 -0
  73. disdrodb/l0/configs/PWS100/l0a_encodings.yml +19 -0
  74. disdrodb/l0/configs/PWS100/l0b_cf_attrs.yml +76 -0
  75. disdrodb/l0/configs/PWS100/l0b_encodings.yml +176 -0
  76. disdrodb/l0/configs/PWS100/raw_data_format.yml +182 -0
  77. disdrodb/l0/configs/{RD_80 → RD80}/bins_diameter.yml +40 -40
  78. disdrodb/l0/configs/RD80/l0a_encodings.yml +16 -0
  79. disdrodb/l0/configs/{RD_80 → RD80}/l0b_cf_attrs.yml +3 -3
  80. disdrodb/l0/configs/RD80/l0b_encodings.yml +135 -0
  81. disdrodb/l0/configs/{RD_80 → RD80}/raw_data_format.yml +46 -50
  82. disdrodb/l0/l0_reader.py +216 -340
  83. disdrodb/l0/l0a_processing.py +237 -208
  84. disdrodb/l0/l0b_nc_processing.py +227 -80
  85. disdrodb/l0/l0b_processing.py +96 -174
  86. disdrodb/l0/l0c_processing.py +627 -0
  87. disdrodb/l0/readers/{ARM → LPM/ARM}/ARM_LPM.py +36 -58
  88. disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +236 -0
  89. disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +185 -0
  90. disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +185 -0
  91. disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +195 -0
  92. disdrodb/l0/readers/LPM/ITALY/GID_LPM_W.py +210 -0
  93. disdrodb/l0/readers/{BRAZIL/GOAMAZON_LPM.py → LPM/KIT/CHWALA.py} +97 -76
  94. disdrodb/l0/readers/LPM/SLOVENIA/ARSO.py +197 -0
  95. disdrodb/l0/readers/LPM/SLOVENIA/CRNI_VRH.py +197 -0
  96. disdrodb/l0/readers/{UK → LPM/UK}/DIVEN.py +14 -35
  97. disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +157 -0
  98. disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +113 -0
  99. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/ARCTIC_2021.py +40 -57
  100. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/COMMON_2011.py +37 -54
  101. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/DAVOS_2009_2011.py +34 -51
  102. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_2009.py +34 -51
  103. disdrodb/l0/readers/{EPFL/PARADISO_2014.py → PARSIVEL/EPFL/EPFL_ROOF_2008.py} +38 -50
  104. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +105 -0
  105. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2011.py +34 -51
  106. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/EPFL_ROOF_2012.py +33 -51
  107. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GENEPI_2007.py +25 -44
  108. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007.py +25 -44
  109. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/GRAND_ST_BERNARD_2007_2.py +25 -44
  110. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HPICONET_2010.py +34 -51
  111. disdrodb/l0/readers/{EPFL/EPFL_ROOF_2010.py → PARSIVEL/EPFL/HYMEX_LTE_SOP2.py} +37 -50
  112. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +111 -0
  113. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/HYMEX_LTE_SOP4.py +36 -54
  114. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2018.py +34 -52
  115. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/LOCARNO_2019.py +38 -56
  116. disdrodb/l0/readers/PARSIVEL/EPFL/PARADISO_2014.py +105 -0
  117. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PARSIVEL_2007.py +27 -45
  118. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/PLATO_2019.py +24 -44
  119. disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +140 -0
  120. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RACLETS_2019_WJF.py +41 -59
  121. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/RIETHOLZBACH_2011.py +34 -51
  122. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +117 -0
  123. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +137 -0
  124. disdrodb/l0/readers/{EPFL → PARSIVEL/EPFL}/UNIL_2022.py +42 -55
  125. disdrodb/l0/readers/PARSIVEL/GPM/IFLOODS.py +104 -0
  126. disdrodb/l0/readers/{GPM → PARSIVEL/GPM}/LPVEX.py +29 -48
  127. disdrodb/l0/readers/PARSIVEL/GPM/MC3E.py +184 -0
  128. disdrodb/l0/readers/PARSIVEL/KIT/BURKINA_FASO.py +133 -0
  129. disdrodb/l0/readers/PARSIVEL/NCAR/CCOPE_2015.py +113 -0
  130. disdrodb/l0/readers/{NCAR/VORTEX_SE_2016_P1.py → PARSIVEL/NCAR/OWLES_MIPS.py} +46 -72
  131. disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +125 -0
  132. disdrodb/l0/readers/{NCAR/OWLES_MIPS.py → PARSIVEL/NCAR/PLOWS_MIPS.py} +45 -64
  133. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +114 -0
  134. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +176 -0
  135. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +183 -0
  136. disdrodb/l0/readers/PARSIVEL/SLOVENIA/UL_FGG.py +121 -0
  137. disdrodb/l0/readers/{ARM/ARM_LD.py → PARSIVEL2/ARM/ARM_PARSIVEL2.py} +27 -50
  138. disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +163 -0
  139. disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +163 -0
  140. disdrodb/l0/readers/{DENMARK → PARSIVEL2/DENMARK}/EROSION_nc.py +14 -35
  141. disdrodb/l0/readers/PARSIVEL2/FRANCE/ENPC_PARSIVEL2.py +189 -0
  142. disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +119 -0
  143. disdrodb/l0/readers/PARSIVEL2/GPM/GCPEX.py +104 -0
  144. disdrodb/l0/readers/PARSIVEL2/GPM/NSSTC.py +176 -0
  145. disdrodb/l0/readers/PARSIVEL2/ITALY/GID_PARSIVEL2.py +32 -0
  146. disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +56 -0
  147. disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +120 -0
  148. disdrodb/l0/readers/{NCAR → PARSIVEL2/NCAR}/PECAN_MIPS.py +45 -64
  149. disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +181 -0
  150. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +160 -0
  151. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +160 -0
  152. disdrodb/l0/readers/{NCAR/PLOWS_MIPS.py → PARSIVEL2/NCAR/VORTEX_SE_2016_P1.py} +49 -66
  153. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +118 -0
  154. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +152 -0
  155. disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT.py +166 -0
  156. disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100.py +150 -0
  157. disdrodb/l0/readers/{NCAR/RELAMPAGO_RD80.py → RD80/BRAZIL/CHUVA_RD80.py} +36 -60
  158. disdrodb/l0/readers/{BRAZIL → RD80/BRAZIL}/GOAMAZON_RD80.py +36 -55
  159. disdrodb/l0/readers/{NCAR → RD80/NCAR}/CINDY_2011_RD80.py +35 -54
  160. disdrodb/l0/readers/{BRAZIL/CHUVA_RD80.py → RD80/NCAR/RELAMPAGO_RD80.py} +40 -54
  161. disdrodb/l0/readers/RD80/NOAA/PSL_RD80.py +274 -0
  162. disdrodb/l0/readers/template_reader_raw_netcdf_data.py +62 -0
  163. disdrodb/l0/readers/{reader_template.py → template_reader_raw_text_data.py} +20 -44
  164. disdrodb/l0/routines.py +885 -581
  165. disdrodb/l0/standards.py +77 -238
  166. disdrodb/l0/template_tools.py +105 -110
  167. disdrodb/l1/__init__.py +17 -0
  168. disdrodb/l1/beard_model.py +716 -0
  169. disdrodb/l1/encoding_attrs.py +635 -0
  170. disdrodb/l1/fall_velocity.py +260 -0
  171. disdrodb/l1/filters.py +192 -0
  172. disdrodb/l1/processing.py +202 -0
  173. disdrodb/l1/resampling.py +236 -0
  174. disdrodb/l1/routines.py +358 -0
  175. disdrodb/l1_env/__init__.py +17 -0
  176. disdrodb/l1_env/routines.py +38 -0
  177. disdrodb/l2/__init__.py +17 -0
  178. disdrodb/l2/empirical_dsd.py +1833 -0
  179. disdrodb/l2/event.py +388 -0
  180. disdrodb/l2/processing.py +528 -0
  181. disdrodb/l2/processing_options.py +213 -0
  182. disdrodb/l2/routines.py +868 -0
  183. disdrodb/metadata/__init__.py +9 -2
  184. disdrodb/metadata/checks.py +180 -124
  185. disdrodb/metadata/download.py +81 -0
  186. disdrodb/metadata/geolocation.py +146 -0
  187. disdrodb/metadata/info.py +20 -13
  188. disdrodb/metadata/manipulation.py +3 -3
  189. disdrodb/metadata/reader.py +59 -8
  190. disdrodb/metadata/search.py +77 -144
  191. disdrodb/metadata/standards.py +83 -80
  192. disdrodb/metadata/writer.py +10 -16
  193. disdrodb/psd/__init__.py +38 -0
  194. disdrodb/psd/fitting.py +2146 -0
  195. disdrodb/psd/models.py +774 -0
  196. disdrodb/routines.py +1412 -0
  197. disdrodb/scattering/__init__.py +28 -0
  198. disdrodb/scattering/axis_ratio.py +344 -0
  199. disdrodb/scattering/routines.py +456 -0
  200. disdrodb/utils/__init__.py +17 -0
  201. disdrodb/utils/attrs.py +208 -0
  202. disdrodb/utils/cli.py +269 -0
  203. disdrodb/utils/compression.py +60 -42
  204. disdrodb/utils/dask.py +62 -0
  205. disdrodb/utils/dataframe.py +342 -0
  206. disdrodb/utils/decorators.py +110 -0
  207. disdrodb/utils/directories.py +107 -46
  208. disdrodb/utils/encoding.py +127 -0
  209. disdrodb/utils/list.py +29 -0
  210. disdrodb/utils/logger.py +168 -46
  211. disdrodb/utils/time.py +657 -0
  212. disdrodb/utils/warnings.py +30 -0
  213. disdrodb/utils/writer.py +57 -0
  214. disdrodb/utils/xarray.py +138 -47
  215. disdrodb/utils/yaml.py +0 -1
  216. disdrodb/viz/__init__.py +17 -0
  217. disdrodb/viz/plots.py +17 -0
  218. disdrodb-0.1.1.dist-info/METADATA +294 -0
  219. disdrodb-0.1.1.dist-info/RECORD +232 -0
  220. {disdrodb-0.0.21.dist-info → disdrodb-0.1.1.dist-info}/WHEEL +1 -1
  221. disdrodb-0.1.1.dist-info/entry_points.txt +30 -0
  222. disdrodb/data_transfer/scripts/disdrodb_download_archive.py +0 -53
  223. disdrodb/data_transfer/scripts/disdrodb_upload_archive.py +0 -57
  224. disdrodb/l0/configs/OTT_Parsivel/l0a_encodings.yml +0 -32
  225. disdrodb/l0/configs/OTT_Parsivel2/l0a_encodings.yml +0 -39
  226. disdrodb/l0/configs/RD_80/l0a_encodings.yml +0 -16
  227. disdrodb/l0/configs/RD_80/l0b_encodings.yml +0 -135
  228. disdrodb/l0/configs/Thies_LPM/l0a_encodings.yml +0 -80
  229. disdrodb/l0/io.py +0 -257
  230. disdrodb/l0/l0_processing.py +0 -1091
  231. disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_OTT.py +0 -178
  232. disdrodb/l0/readers/AUSTRALIA/MELBOURNE_2007_THIES.py +0 -247
  233. disdrodb/l0/readers/BRAZIL/CHUVA_LPM.py +0 -204
  234. disdrodb/l0/readers/BRAZIL/CHUVA_OTT.py +0 -183
  235. disdrodb/l0/readers/BRAZIL/GOAMAZON_OTT.py +0 -183
  236. disdrodb/l0/readers/CHINA/CHONGQING.py +0 -131
  237. disdrodb/l0/readers/EPFL/EPFL_ROOF_2008.py +0 -128
  238. disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP2.py +0 -127
  239. disdrodb/l0/readers/EPFL/HYMEX_LTE_SOP3.py +0 -129
  240. disdrodb/l0/readers/EPFL/RACLETS_2019.py +0 -158
  241. disdrodb/l0/readers/EPFL/SAMOYLOV_2017.py +0 -136
  242. disdrodb/l0/readers/EPFL/SAMOYLOV_2019.py +0 -158
  243. disdrodb/l0/readers/FRANCE/SIRTA_OTT2.py +0 -138
  244. disdrodb/l0/readers/GPM/GCPEX.py +0 -123
  245. disdrodb/l0/readers/GPM/IFLOODS.py +0 -123
  246. disdrodb/l0/readers/GPM/MC3E.py +0 -123
  247. disdrodb/l0/readers/GPM/NSSTC.py +0 -164
  248. disdrodb/l0/readers/ITALY/GID.py +0 -199
  249. disdrodb/l0/readers/MEXICO/OH_IIUNAM_nc.py +0 -92
  250. disdrodb/l0/readers/NCAR/CCOPE_2015.py +0 -133
  251. disdrodb/l0/readers/NCAR/PECAN_FP3.py +0 -137
  252. disdrodb/l0/readers/NCAR/PECAN_MOBILE.py +0 -144
  253. disdrodb/l0/readers/NCAR/RELAMPAGO_OTT.py +0 -195
  254. disdrodb/l0/readers/NCAR/SNOWIE_PJ.py +0 -172
  255. disdrodb/l0/readers/NCAR/SNOWIE_SB.py +0 -179
  256. disdrodb/l0/readers/NCAR/VORTEX2_2009.py +0 -133
  257. disdrodb/l0/readers/NCAR/VORTEX2_2010.py +0 -188
  258. disdrodb/l0/readers/NCAR/VORTEX2_2010_UF.py +0 -191
  259. disdrodb/l0/readers/NCAR/VORTEX_SE_2016_P2.py +0 -135
  260. disdrodb/l0/readers/NCAR/VORTEX_SE_2016_PIPS.py +0 -170
  261. disdrodb/l0/readers/NETHERLANDS/DELFT.py +0 -187
  262. disdrodb/l0/readers/SPAIN/SBEGUERIA.py +0 -179
  263. disdrodb/l0/scripts/disdrodb_run_l0b_concat.py +0 -93
  264. disdrodb/l0/scripts/disdrodb_run_l0b_concat_station.py +0 -85
  265. disdrodb/utils/netcdf.py +0 -452
  266. disdrodb/utils/scripts.py +0 -102
  267. disdrodb-0.0.21.dist-info/AUTHORS.md +0 -18
  268. disdrodb-0.0.21.dist-info/METADATA +0 -186
  269. disdrodb-0.0.21.dist-info/RECORD +0 -168
  270. disdrodb-0.0.21.dist-info/entry_points.txt +0 -15
  271. /disdrodb/l0/configs/{RD_80 → RD80}/bins_velocity.yml +0 -0
  272. /disdrodb/l0/manuals/{Thies_LPM.pdf → LPM.pdf} +0 -0
  273. /disdrodb/l0/manuals/{ODM_470.pdf → ODM470.pdf} +0 -0
  274. /disdrodb/l0/manuals/{OTT_Parsivel.pdf → PARSIVEL.pdf} +0 -0
  275. /disdrodb/l0/manuals/{OTT_Parsivel2.pdf → PARSIVEL2.pdf} +0 -0
  276. /disdrodb/l0/manuals/{PWS_100.pdf → PWS100.pdf} +0 -0
  277. /disdrodb/l0/manuals/{RD_80.pdf → RD80.pdf} +0 -0
  278. {disdrodb-0.0.21.dist-info → disdrodb-0.1.1.dist-info/licenses}/LICENSE +0 -0
  279. {disdrodb-0.0.21.dist-info → disdrodb-0.1.1.dist-info}/top_level.txt +0 -0
disdrodb/api/path.py CHANGED
@@ -17,189 +17,184 @@
17
17
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
18
  # -----------------------------------------------------------------------------.
19
19
  """Define paths within the DISDRODB infrastructure."""
20
-
21
20
  import os
22
21
 
23
- import pandas as pd
24
- import xarray as xr
25
-
26
- from disdrodb.api.info import infer_campaign_name_from_path
27
- from disdrodb.configs import get_base_dir
22
+ from disdrodb.configs import get_data_archive_dir, get_metadata_archive_dir
28
23
  from disdrodb.utils.directories import check_directory_exists
24
+ from disdrodb.utils.time import (
25
+ ensure_sample_interval_in_seconds,
26
+ get_file_start_end_time,
27
+ seconds_to_acronym,
28
+ )
29
29
 
30
30
  ####--------------------------------------------------------------------------.
31
- #### Paths from BASE_DIR
31
+ #### DISDRODB Metadata and Data Archive directories and file paths
32
32
 
33
33
 
34
- def get_disdrodb_path(
35
- base_dir,
34
+ def define_disdrodb_path(
35
+ archive_dir,
36
36
  product,
37
37
  data_source="",
38
38
  campaign_name="",
39
39
  check_exists=True,
40
40
  ):
41
- """Return the directory in the DISDRODB infrastructure.
41
+ """Return the directory path in the DISDRODB Metadata and Data Archive.
42
+
43
+ If ``product="METADATA"``, it returns the path in the DISDRODB Metadata Archive.
44
+ Otherwise, it returns the path in the DISDRODB Data Archive.
45
+
46
+ If ``data_source`` and ``campaign_name`` are not specified it return the product directory.
42
47
 
43
- If data_source and campaign_name are not specified it return the product directory.
44
- If data_source is specified, it returns the data_source directory.
45
- If campaign_source is specified, it returns the campaign_name directory.
48
+ If ``data_source`` is specified, it returns the ``data_source`` directory.
49
+
50
+ If ``campaign_source`` is specified, it returns the ``campaign_name`` directory.
46
51
 
47
52
  Parameters
48
53
  ----------
49
- base_dir : str
50
- The disdrodb base directory
54
+ archive_dir : str
55
+ The DISDRODB archive directory
51
56
  product : str
52
- The DISDRODB product. It can be "RAW", "L0A", or "L0B".
57
+ The DISDRODB product. See ``disdrodb.available_products()``.
58
+ If "METADATA" is specified, it returns the path in the DISDRODB Metadata Archive.
53
59
  data_source : str, optional
54
- The data source. Must be specified if campaign_name is specified.
60
+ The data source. Must be specified if ``campaign_name`` is specified.
55
61
  campaign_name : str, optional
56
- The campaign_name.
62
+ The campaign name.
57
63
  check_exists : bool, optional
58
- Whether to check if the directory exists. By default True.
64
+ Whether to check if the directory exists. The default value is ``True``.
59
65
 
60
66
  Returns
61
67
  -------
62
68
  dir_path : str
63
69
  Directory path
64
70
  """
65
- from disdrodb.api.checks import check_base_dir
71
+ from disdrodb import ARCHIVE_VERSION
66
72
 
67
- # Check base_dir validity
68
- base_dir = check_base_dir(base_dir)
69
- if len(campaign_name) > 0:
70
- if len(data_source) == 0:
71
- raise ValueError("If campaign_name is specified, data_source must be specified.")
73
+ if len(campaign_name) > 0 and len(data_source) == 0:
74
+ raise ValueError("If campaign_name is specified, data_source must be specified.")
72
75
 
73
76
  # Get directory
74
- if product.upper() == "RAW":
75
- dir_path = os.path.join(base_dir, "Raw", data_source, campaign_name)
77
+ if product.upper() == "METADATA":
78
+ dir_path = os.path.join(archive_dir, "METADATA", data_source, campaign_name)
79
+ elif product.upper() == "RAW":
80
+ dir_path = os.path.join(archive_dir, "RAW", data_source, campaign_name)
76
81
  else:
77
- dir_path = os.path.join(base_dir, "Processed", data_source, campaign_name)
82
+ dir_path = os.path.join(archive_dir, ARCHIVE_VERSION, data_source, campaign_name)
78
83
  if check_exists:
79
84
  check_directory_exists(dir_path)
80
85
  return dir_path
81
86
 
82
87
 
83
- def define_campaign_dir(
88
+ def define_data_source_dir(
89
+ archive_dir,
84
90
  product,
85
91
  data_source,
86
- campaign_name,
87
- base_dir=None,
88
92
  check_exists=False,
89
93
  ):
90
- """Return the campaign directory in the DISDRODB infrastructure.
94
+ """Return the data source directory in the DISDRODB infrastructure.
95
+
96
+ If ``product="METADATA"``, it returns the path in the DISDRODB Metadata Archive.
97
+ Otherwise, it returns the path in the DISDRODB Data Archive.
91
98
 
92
99
  Parameters
93
100
  ----------
94
101
  product : str
95
- The DISDRODB product. It can be "RAW", "L0A", or "L0B".
102
+ The DISDRODB product. See ``disdrodb.available_products()``.
103
+ If "METADATA" is specified, it returns the path in the DISDRODB Metadata Archive.
96
104
  data_source : str
97
- The data source. Must be specified if campaign_name is specified.
98
- campaign_name : str
99
- The campaign_name.
100
- base_dir : str, optional
105
+ The data source.
106
+ archive_dir : str, optional
101
107
  The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
102
108
  If not specified, the path specified in the DISDRODB active configuration will be used.
103
109
  check_exists : bool, optional
104
- Whether to check if the directory exists. By default False.
110
+ Whether to check if the directory exists. The default value is ``False``.
105
111
 
106
112
  Returns
107
113
  -------
108
114
  station_dir : str
109
115
  Station data directory path
110
116
  """
111
- base_dir = get_base_dir(base_dir)
112
- campaign_dir = get_disdrodb_path(
113
- base_dir=base_dir,
117
+ data_source_dir = define_disdrodb_path(
118
+ archive_dir=archive_dir,
114
119
  product=product,
115
120
  data_source=data_source,
116
- campaign_name=campaign_name,
117
121
  check_exists=check_exists,
118
122
  )
119
- return str(campaign_dir)
123
+ return str(data_source_dir)
120
124
 
121
125
 
122
- def define_station_dir(
126
+ def define_campaign_dir(
127
+ archive_dir,
123
128
  product,
124
129
  data_source,
125
130
  campaign_name,
126
- station_name,
127
- base_dir=None,
128
131
  check_exists=False,
129
132
  ):
130
- """Return the station data directory in the DISDRODB infrastructure.
133
+ """Return the campaign directory in the DISDRODB infrastructure.
134
+
135
+ If ``product="METADATA"``, it returns the path in the DISDRODB Metadata Archive.
136
+ Otherwise, it returns the path in the DISDRODB Data Archive.
131
137
 
132
138
  Parameters
133
139
  ----------
134
140
  product : str
135
- The DISDRODB product. It can be "RAW", "L0A", or "L0B".
141
+ The DISDRODB product. See ``disdrodb.available_products()``.
142
+ If "METADATA" is specified, it returns the path in the DISDRODB Metadata Archive.
136
143
  data_source : str
137
- The data source.
144
+ The data source. Must be specified if ``campaign_name`` is specified.
138
145
  campaign_name : str
139
146
  The campaign name.
140
- station_name : str
141
- The station name.
142
- base_dir : str, optional
147
+ archive_dir : str, optional
143
148
  The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
144
149
  If not specified, the path specified in the DISDRODB active configuration will be used.
145
150
  check_exists : bool, optional
146
- Whether to check if the directory exists. By default False.
151
+ Whether to check if the directory exists. The default value is ``False``.
147
152
 
148
153
  Returns
149
154
  -------
150
155
  station_dir : str
151
156
  Station data directory path
152
157
  """
153
- base_dir = get_base_dir(base_dir)
154
- campaign_dir = get_disdrodb_path(
155
- base_dir=base_dir,
158
+ campaign_dir = define_disdrodb_path(
159
+ archive_dir=archive_dir,
156
160
  product=product,
157
161
  data_source=data_source,
158
162
  campaign_name=campaign_name,
159
163
  check_exists=check_exists,
160
164
  )
161
- if product.upper() == "RAW":
162
- station_dir = os.path.join(campaign_dir, "data", station_name)
163
- else:
164
- station_dir = os.path.join(campaign_dir, product, station_name)
165
- if check_exists:
166
- check_directory_exists(station_dir)
167
- return str(station_dir)
165
+ return str(campaign_dir)
168
166
 
169
167
 
170
168
  def define_metadata_dir(
171
- product,
172
169
  data_source,
173
170
  campaign_name,
174
- base_dir=None,
171
+ metadata_archive_dir=None,
175
172
  check_exists=False,
176
173
  ):
177
174
  """Return the metadata directory in the DISDRODB infrastructure.
178
175
 
179
176
  Parameters
180
177
  ----------
181
- product : str
182
- The DISDRODB product. It can be "RAW", "L0A", or "L0B".
183
178
  data_source : str
184
179
  The data source.
185
180
  campaign_name : str
186
181
  The campaign name.
187
- base_dir : str, optional
182
+ data_archive_dir : str, optional
188
183
  The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
189
184
  If not specified, the path specified in the DISDRODB active configuration will be used.
190
185
  check_exists : bool, optional
191
- Whether to check if the directory exists. By default False.
186
+ Whether to check if the directory exists. The default value is ``False``.
192
187
 
193
188
  Returns
194
189
  -------
195
- metadata_dir : str
190
+ metadata_archive_dir : str
196
191
  Station data directory path
197
192
  """
198
- base_dir = get_base_dir(base_dir)
193
+ metadata_archive_dir = get_metadata_archive_dir(metadata_archive_dir)
199
194
  campaign_dir = define_campaign_dir(
200
- base_dir=base_dir,
201
- product=product,
195
+ archive_dir=metadata_archive_dir,
202
196
  data_source=data_source,
197
+ product="METADATA",
203
198
  campaign_name=campaign_name,
204
199
  check_exists=check_exists,
205
200
  )
@@ -212,7 +207,7 @@ def define_metadata_dir(
212
207
  def define_issue_dir(
213
208
  data_source,
214
209
  campaign_name,
215
- base_dir=None,
210
+ metadata_archive_dir=None,
216
211
  check_exists=False,
217
212
  ):
218
213
  """Return the issue directory in the DISDRODB infrastructure.
@@ -223,21 +218,21 @@ def define_issue_dir(
223
218
  The data source.
224
219
  campaign_name : str
225
220
  The campaign name.
226
- base_dir : str, optional
221
+ data_archive_dir : str, optional
227
222
  The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
228
223
  If not specified, the path specified in the DISDRODB active configuration will be used.
229
224
  check_exists : bool, optional
230
- Whether to check if the directory exists. By default False.
225
+ Whether to check if the directory exists. The default value is ``False``.
231
226
 
232
227
  Returns
233
228
  -------
234
229
  issue_dir : str
235
230
  Station data directory path
236
231
  """
237
- base_dir = get_base_dir(base_dir)
232
+ metadata_archive_dir = get_metadata_archive_dir(metadata_archive_dir)
238
233
  campaign_dir = define_campaign_dir(
239
- base_dir=base_dir,
240
- product="RAW",
234
+ archive_dir=metadata_archive_dir,
235
+ product="METADATA",
241
236
  data_source=data_source,
242
237
  campaign_name=campaign_name,
243
238
  check_exists=check_exists,
@@ -249,47 +244,46 @@ def define_issue_dir(
249
244
 
250
245
 
251
246
  def define_metadata_filepath(
252
- product,
253
247
  data_source,
254
248
  campaign_name,
255
249
  station_name,
256
- base_dir=None,
250
+ metadata_archive_dir=None,
257
251
  check_exists=False,
258
252
  ):
259
253
  """Return the station metadata filepath in the DISDRODB infrastructure.
260
254
 
261
255
  Parameters
262
256
  ----------
263
- product : str
264
- The DISDRODB product. It can be "RAW", "L0A", or "L0B".
265
257
  data_source : str
266
258
  The data source.
267
259
  campaign_name : str
268
260
  The campaign name.
269
261
  station_name : str
270
262
  The station name.
271
- base_dir : str, optional
263
+ data_archive_dir : str, optional
272
264
  The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
273
265
  If not specified, the path specified in the DISDRODB active configuration will be used.
274
266
  check_exists : bool, optional
275
- Whether to check if the directory exists. By default False.
267
+ Whether to check if the directory exists. The default value is ``False``.
276
268
 
277
269
  Returns
278
270
  -------
279
- metadata_dir : str
271
+ metadata_archive_dir : str
280
272
  Station data directory path
281
273
  """
282
- base_dir = get_base_dir(base_dir)
274
+ metadata_dir = get_metadata_archive_dir(metadata_archive_dir)
283
275
  metadata_dir = define_metadata_dir(
284
- base_dir=base_dir,
285
- product=product,
276
+ metadata_archive_dir=metadata_archive_dir,
286
277
  data_source=data_source,
287
278
  campaign_name=campaign_name,
288
279
  check_exists=False,
289
280
  )
290
281
  metadata_filepath = os.path.join(metadata_dir, f"{station_name}.yml")
291
282
  if check_exists and not os.path.exists(metadata_filepath):
292
- raise ValueError(f"The metadata file for {station_name} at {metadata_filepath} does not exists.")
283
+ raise ValueError(
284
+ f"The station {data_source} {campaign_name} {station_name} does not exist. "
285
+ f"No metadata file is available at {metadata_filepath}.",
286
+ )
293
287
 
294
288
  return str(metadata_filepath)
295
289
 
@@ -298,7 +292,7 @@ def define_issue_filepath(
298
292
  data_source,
299
293
  campaign_name,
300
294
  station_name,
301
- base_dir=None,
295
+ metadata_archive_dir=None,
302
296
  check_exists=False,
303
297
  ):
304
298
  """Return the station issue filepath in the DISDRODB infrastructure.
@@ -311,20 +305,20 @@ def define_issue_filepath(
311
305
  The campaign name.
312
306
  station_name : str
313
307
  The station name.
314
- base_dir : str, optional
308
+ data_archive_dir : str, optional
315
309
  The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
316
310
  If not specified, the path specified in the DISDRODB active configuration will be used.
317
311
  check_exists : bool, optional
318
- Whether to check if the directory exists. By default False.
312
+ Whether to check if the directory exists. The default value is ``False``.
319
313
 
320
314
  Returns
321
315
  -------
322
316
  issue_dir : str
323
317
  Station data directory path
324
318
  """
325
- base_dir = get_base_dir(base_dir)
319
+ metadata_archive_dir = get_metadata_archive_dir(metadata_archive_dir)
326
320
  issue_dir = define_issue_dir(
327
- base_dir=base_dir,
321
+ metadata_archive_dir=metadata_archive_dir,
328
322
  data_source=data_source,
329
323
  campaign_name=campaign_name,
330
324
  check_exists=False,
@@ -332,10 +326,13 @@ def define_issue_filepath(
332
326
  issue_filepath = os.path.join(issue_dir, f"{station_name}.yml")
333
327
  if check_exists and not os.path.exists(issue_filepath):
334
328
  raise ValueError(f"The issue file for {station_name} at {issue_filepath} does not exists.")
335
-
336
329
  return str(issue_filepath)
337
330
 
338
331
 
332
+ ####--------------------------------------------------------------------------.
333
+ #### DISDRODB software configuration directory
334
+
335
+
339
336
  def define_config_dir(product):
340
337
  """Define the config directory path of a given DISDRODB product."""
341
338
  from disdrodb import __root_path__
@@ -352,153 +349,580 @@ def define_config_dir(product):
352
349
  #### Directory/Filepaths L0A and L0B products
353
350
 
354
351
 
355
- def define_l0a_station_dir(processed_dir: str, station_name: str) -> str:
356
- """Define L0A directory.
352
+ def define_file_folder_path(obj, data_dir, folder_partitioning):
353
+ """
354
+ Define the folder path where saving a file based on the dataset's starting time.
357
355
 
358
356
  Parameters
359
357
  ----------
360
- processed_dir : str
361
- Path of the processed directory
362
- station_name : str
363
- Name of the station
358
+ ds : xarray.Dataset or pandas.DataFrame
359
+ The object containing time information.
360
+ data_dir : str
361
+ Directory within the DISDRODB Data Archive where DISDRODB product files are to be saved.
362
+ folder_partitioning : str or None
363
+ Define the subdirectory structure where saving files.
364
+ Allowed values are:
365
+ - None: Files are saved directly in data_dir.
366
+ - "year": Files are saved under a subdirectory for the year.
367
+ - "year/month": Files are saved under subdirectories for year and month.
368
+ - "year/month/day": Files are saved under subdirectories for year, month and day
369
+ - "year/month_name": Files are stored under subdirectories by year and month name
370
+ - "year/quarter": Files are saved under subdirectories for year and quarter.
364
371
 
365
372
  Returns
366
373
  -------
367
374
  str
368
- L0A directory path.
375
+ A complete directory path where the file should be saved.
369
376
  """
370
- station_dir = os.path.join(processed_dir, "L0A", station_name)
371
- return station_dir
377
+ from disdrodb.api.checks import check_folder_partitioning
378
+
379
+ # Validate the folder partition parameter.
380
+ check_folder_partitioning(folder_partitioning)
381
+
382
+ # Retrieve the starting time from the dataset.
383
+ starting_time, _ = get_file_start_end_time(obj)
384
+
385
+ # Build the folder path based on the chosen partition scheme.
386
+ if folder_partitioning == "":
387
+ return data_dir
388
+ if folder_partitioning == "year":
389
+ year = str(starting_time.year)
390
+ return os.path.join(data_dir, year)
391
+ if folder_partitioning == "year/month":
392
+ year = str(starting_time.year)
393
+ month = str(starting_time.month).zfill(2)
394
+ return os.path.join(data_dir, year, month)
395
+ if folder_partitioning == "year/month/day":
396
+ year = str(starting_time.year)
397
+ month = str(starting_time.month).zfill(2)
398
+ day = str(starting_time.day).zfill(2)
399
+ return os.path.join(data_dir, year, month, day)
400
+ if folder_partitioning == "year/month_name":
401
+ year = str(starting_time.year)
402
+ month = str(starting_time.month_name())
403
+ return os.path.join(data_dir, year, month)
404
+ if folder_partitioning == "year/quarter":
405
+ year = str(starting_time.year)
406
+ # Calculate quarter: months 1-3 => Q1, 4-6 => Q2, etc.
407
+ quarter = (starting_time.month - 1) // 3 + 1
408
+ quarter_dir = f"Q{quarter}"
409
+ return os.path.join(data_dir, year, quarter_dir)
410
+ raise NotImplementedError(f"Unrecognized '{folder_partitioning}' folder partitioning scheme.")
411
+
412
+
413
+ def define_product_dir_tree(
414
+ product,
415
+ **product_kwargs,
416
+ ):
417
+ """Return the product directory tree.
372
418
 
419
+ Parameters
420
+ ----------
421
+ product : str
422
+ The DISDRODB product. See ``disdrodb.available_products()``.
423
+ sample_interval : int, optional
424
+ The sampling interval in seconds of the product.
425
+ It must be specified only for product L2E and L2M !
426
+ rolling : bool, optional
427
+ Whether the dataset has been resampled by aggregating or rolling.
428
+ It must be specified only for product L2E and L2M !
429
+ model_name : str
430
+ The custom model name of the fitted statistical distribution.
431
+ It must be specified only for product L2M !
373
432
 
374
- def define_l0b_station_dir(processed_dir: str, station_name: str) -> str:
375
- """Define L0B directory.
433
+ Returns
434
+ -------
435
+ data_dir : str
436
+ Station data directory path
437
+ """
438
+ from disdrodb.api.checks import check_product, check_product_kwargs, check_rolling, check_sample_interval
439
+
440
+ product = check_product(product)
441
+ product_kwargs = check_product_kwargs(product, product_kwargs)
442
+ if product.upper() == "RAW":
443
+ return ""
444
+ if product.upper() in ["L0A", "L0B", "L0C", "L1"]:
445
+ return ""
446
+ if product == "L2E":
447
+ rolling = product_kwargs.get("rolling")
448
+ sample_interval = product_kwargs.get("sample_interval")
449
+ check_rolling(rolling)
450
+ check_sample_interval(sample_interval)
451
+ sample_interval_acronym = define_accumulation_acronym(seconds=sample_interval, rolling=rolling)
452
+ return os.path.join(sample_interval_acronym)
453
+ if product == "L2M":
454
+ rolling = product_kwargs.get("rolling")
455
+ sample_interval = product_kwargs.get("sample_interval")
456
+ model_name = product_kwargs.get("model_name")
457
+ check_rolling(rolling)
458
+ check_sample_interval(sample_interval)
459
+ sample_interval_acronym = define_accumulation_acronym(seconds=sample_interval, rolling=rolling)
460
+ return os.path.join(model_name, sample_interval_acronym)
461
+ raise ValueError(f"The product {product} is not defined.")
462
+
463
+
464
+ def define_logs_dir(
465
+ product,
466
+ data_source,
467
+ campaign_name,
468
+ station_name,
469
+ data_archive_dir=None,
470
+ check_exists=False,
471
+ **product_kwargs,
472
+ ):
473
+ """Return the station log directory in the DISDRODB infrastructure.
376
474
 
377
475
  Parameters
378
476
  ----------
379
- processed_dir : str
380
- Path of the processed directory
381
- station_name : int
382
- Name of the station
477
+ product : str
478
+ The DISDRODB product. See ``disdrodb.available_products()``.
479
+ data_source : str
480
+ The data source.
481
+ campaign_name : str
482
+ The campaign name.
483
+ station_name : str
484
+ The station name.
485
+ data_archive_dir : str, optional
486
+ The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
487
+ If not specified, the path specified in the DISDRODB active configuration will be used.
488
+ check_exists : bool, optional
489
+ Whether to check if the directory exists. The default value is ``False``.
490
+
491
+ Returns
492
+ -------
493
+ station_dir : str
494
+ Station data directory path
495
+ """
496
+ campaign_dir = define_campaign_dir(
497
+ archive_dir=data_archive_dir,
498
+ product=product,
499
+ data_source=data_source,
500
+ campaign_name=campaign_name,
501
+ check_exists=check_exists,
502
+ )
503
+ product_dir_tree = define_product_dir_tree(
504
+ product=product,
505
+ **product_kwargs,
506
+ )
507
+ logs_dir = os.path.join(campaign_dir, "logs", "files", product, product_dir_tree, station_name)
508
+ if check_exists:
509
+ check_directory_exists(logs_dir)
510
+ return str(logs_dir)
511
+
512
+
513
+ def define_station_dir(
514
+ product,
515
+ data_source,
516
+ campaign_name,
517
+ station_name,
518
+ data_archive_dir=None,
519
+ check_exists=False,
520
+ ):
521
+ """Return the station product directory in the DISDRODB infrastructure.
522
+
523
+ Parameters
524
+ ----------
525
+ product : str
526
+ The DISDRODB product. See ``disdrodb.available_products()``.
527
+ data_source : str
528
+ The data source.
529
+ campaign_name : str
530
+ The campaign name.
531
+ station_name : str
532
+ The station name.
533
+ data_archive_dir : str, optional
534
+ The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
535
+ If not specified, the path specified in the DISDRODB active configuration will be used.
536
+ check_exists : bool, optional
537
+ Whether to check if the directory exists. The default value is ``False``.
538
+
539
+ Returns
540
+ -------
541
+ station_dir : str
542
+ Station data directory path
543
+ """
544
+ data_archive_dir = get_data_archive_dir(data_archive_dir)
545
+ campaign_dir = define_disdrodb_path(
546
+ archive_dir=data_archive_dir,
547
+ product=product,
548
+ data_source=data_source,
549
+ campaign_name=campaign_name,
550
+ check_exists=check_exists,
551
+ )
552
+ if product.upper() == "RAW":
553
+ station_dir = os.path.join(campaign_dir, "data", station_name)
554
+ else:
555
+ station_dir = os.path.join(campaign_dir, product, station_name)
556
+ if check_exists:
557
+ check_directory_exists(station_dir)
558
+ return str(station_dir)
559
+
560
+
561
+ def define_data_dir(
562
+ product,
563
+ data_source,
564
+ campaign_name,
565
+ station_name,
566
+ data_archive_dir=None,
567
+ check_exists=False,
568
+ **product_kwargs,
569
+ ):
570
+ """Return the station product data directory in the DISDRODB infrastructure.
571
+
572
+ Parameters
573
+ ----------
574
+ product : str
575
+ The DISDRODB product. See ``disdrodb.available_products()``.
576
+ data_source : str
577
+ The data source.
578
+ campaign_name : str
579
+ The campaign name.
580
+ station_name : str
581
+ The station name.
582
+ data_archive_dir : str, optional
583
+ The base directory of DISDRODB, expected in the format ``<...>/DISDRODB``.
584
+ If not specified, the path specified in the DISDRODB active configuration will be used.
585
+ check_exists : bool, optional
586
+ Whether to check if the directory exists. The default value is ``False``.
587
+ sample_interval : int, optional
588
+ The sampling interval in seconds of the product.
589
+ It must be specified only for product L2E and L2M !
590
+ rolling : bool, optional
591
+ Whether the dataset has been resampled by aggregating or rolling.
592
+ It must be specified only for product L2E and L2M !
593
+ model_name : str
594
+ The name of the fitted statistical distribution for the DSD.
595
+ It must be specified only for product L2M !
596
+
597
+ Returns
598
+ -------
599
+ data_dir : str
600
+ Station data directory path
601
+ """
602
+ from disdrodb.api.checks import check_product, check_product_kwargs
603
+
604
+ product = check_product(product)
605
+ product_kwargs = check_product_kwargs(product, product_kwargs)
606
+ # Define station directory
607
+ station_dir = define_station_dir(
608
+ data_archive_dir=data_archive_dir,
609
+ product=product,
610
+ data_source=data_source,
611
+ campaign_name=campaign_name,
612
+ station_name=station_name,
613
+ check_exists=check_exists,
614
+ ) # <product>/<station_name>
615
+ # Define product directory directory (i.e. for L2E and L2M)
616
+ product_dir_tree = define_product_dir_tree(
617
+ product,
618
+ **product_kwargs,
619
+ )
620
+ # Define data directory
621
+ data_dir = os.path.join(station_dir, product_dir_tree)
622
+ # Check if directory exists
623
+ if check_exists:
624
+ check_directory_exists(data_dir)
625
+ return str(data_dir)
626
+
627
+
628
+ ####--------------------------------------------------------------------------.
629
+ #### Filenames for DISDRODB products
630
+
631
+
632
+ def define_accumulation_acronym(seconds, rolling):
633
+ """Define the accumulation acronnym.
634
+
635
+ Prefix the accumulation interval acronym with ROLL if rolling=True.
636
+ """
637
+ accumulation_acronym = seconds_to_acronym(seconds)
638
+ if rolling:
639
+ accumulation_acronym = f"ROLL{accumulation_acronym}"
640
+ return accumulation_acronym
641
+
642
+
643
+ ####--------------------------------------------------------------------------.
644
+ #### Filenames for DISDRODB products
645
+
646
+
647
+ def define_filename(
648
+ product: str,
649
+ campaign_name: str,
650
+ station_name: str,
651
+ # Filename options
652
+ obj=None,
653
+ add_version=True,
654
+ add_time_period=True,
655
+ add_extension=True,
656
+ # Prefix
657
+ prefix="",
658
+ suffix="",
659
+ # Product options
660
+ **product_kwargs,
661
+ ) -> str:
662
+ """Define DISDRODB products filename.
663
+
664
+ Parameters
665
+ ----------
666
+ obj : xarray.Dataset or pandas.DataFrame
667
+ xarray Dataset or pandas DataFrame.
668
+ Required if add_time_period = True.
669
+ campaign_name : str
670
+ Name of the campaign.
671
+ station_name : str
672
+ Name of the station.
673
+ sample_interval : int, optional
674
+ The sampling interval in seconds of the product.
675
+ It must be specified only for product L2E and L2M !
676
+ rolling : bool, optional
677
+ Whether the dataset has been resampled by aggregating or rolling.
678
+ It must be specified only for product L2E and L2M !
679
+ model_name : str
680
+ The model name of the fitted statistical distribution for the DSD.
681
+ It must be specified only for product L2M !
383
682
 
384
683
  Returns
385
684
  -------
386
685
  str
387
- Path of the L0B directory
686
+ L0B file name.
388
687
  """
389
- station_dir = os.path.join(processed_dir, "L0B", station_name)
390
- return station_dir
688
+ from disdrodb import ARCHIVE_VERSION
689
+ from disdrodb.api.checks import check_product, check_product_kwargs
690
+
691
+ product = check_product(product)
692
+ product_kwargs = check_product_kwargs(product, product_kwargs)
693
+
694
+ # -----------------------------------------.
695
+ # TODO: Define sample_interval_acronym
696
+ # - ADD sample_interval_acronym also to L0A and L0B
697
+ # - Add sample_interval_acronym also to L0C and L1
698
+
699
+ # -----------------------------------------.
700
+ # Define product acronym
701
+ product_acronym = f"{product}"
702
+ if product in ["L2E", "L2M"]:
703
+ rolling = product_kwargs.get("rolling")
704
+ sample_interval = product_kwargs.get("sample_interval")
705
+ sample_interval_acronym = define_accumulation_acronym(seconds=sample_interval, rolling=rolling)
706
+ product_acronym = f"L2E.{sample_interval_acronym}"
707
+ if product in ["L2M"]:
708
+ model_name = product_kwargs.get("model_name")
709
+ product_acronym = f"L2M_{model_name}.{sample_interval_acronym}"
710
+
711
+ # -----------------------------------------.
712
+ # Define base filename
713
+ filename = f"{product_acronym}.{campaign_name}.{station_name}"
714
+
715
+ # -----------------------------------------.
716
+ # Add prefix
717
+ if prefix != "":
718
+ filename = f"{prefix}.{filename}"
719
+
720
+ # -----------------------------------------.
721
+ # Add time period information
722
+ if add_time_period:
723
+ starting_time, ending_time = get_file_start_end_time(obj)
724
+ starting_time = starting_time.strftime("%Y%m%d%H%M%S")
725
+ ending_time = ending_time.strftime("%Y%m%d%H%M%S")
726
+ filename = f"{filename}.s{starting_time}.e{ending_time}"
727
+
728
+ # -----------------------------------------.
729
+ # Add product version
730
+ if add_version:
731
+ filename = f"{filename}.{ARCHIVE_VERSION}"
732
+
733
+ # -----------------------------------------.
734
+ # Add product extension
735
+ if add_extension:
736
+ filename = f"{filename}.parquet" if product == "L0A" else f"{filename}.nc"
737
+
738
+ # -----------------------------------------.
739
+ # Add suffix
740
+ if suffix != "":
741
+ filename = f"{filename}.{suffix}"
742
+ return filename
391
743
 
392
744
 
393
- def define_l0a_filename(df, processed_dir, station_name: str) -> str:
745
+ def define_l0a_filename(df, campaign_name: str, station_name: str) -> str:
394
746
  """Define L0A file name.
395
747
 
396
748
  Parameters
397
749
  ----------
398
- df : pd.DataFrame
399
- L0A DataFrame
400
- processed_dir : str
401
- Path of the processed directory
750
+ df : pandas.DataFrame
751
+ L0A DataFrame.
752
+ campaign_name : str
753
+ Name of the campaign.
402
754
  station_name : str
403
- Name of the station
755
+ Name of the station.
404
756
 
405
757
  Returns
406
758
  -------
407
759
  str
408
760
  L0A file name.
409
761
  """
410
- from disdrodb.l0.standards import PRODUCT_VERSION
411
- from disdrodb.utils.pandas import get_dataframe_start_end_time
412
-
413
- starting_time, ending_time = get_dataframe_start_end_time(df)
414
- starting_time = pd.to_datetime(starting_time).strftime("%Y%m%d%H%M%S")
415
- ending_time = pd.to_datetime(ending_time).strftime("%Y%m%d%H%M%S")
416
- campaign_name = infer_campaign_name_from_path(processed_dir).replace(".", "-")
417
- version = PRODUCT_VERSION
762
+ from disdrodb import ARCHIVE_VERSION
763
+
764
+ starting_time, ending_time = get_file_start_end_time(df)
765
+ starting_time = starting_time.strftime("%Y%m%d%H%M%S")
766
+ ending_time = ending_time.strftime("%Y%m%d%H%M%S")
767
+ version = ARCHIVE_VERSION
418
768
  filename = f"L0A.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.parquet"
419
769
  return filename
420
770
 
421
771
 
422
- def define_l0b_filename(ds, processed_dir, station_name: str) -> str:
772
+ def define_l0b_filename(ds, campaign_name: str, station_name: str) -> str:
423
773
  """Define L0B file name.
424
774
 
425
775
  Parameters
426
776
  ----------
427
- ds : xr.Dataset
428
- L0B xarray Dataset
429
- processed_dir : str
430
- Path of the processed directory
777
+ ds : xarray.Dataset
778
+ L0B xarray Dataset.
779
+ campaign_name : str
780
+ Name of the campaign.
431
781
  station_name : str
432
- Name of the station
782
+ Name of the station.
433
783
 
434
784
  Returns
435
785
  -------
436
786
  str
437
787
  L0B file name.
438
788
  """
439
- from disdrodb.l0.standards import PRODUCT_VERSION
440
- from disdrodb.utils.xarray import get_dataset_start_end_time
441
-
442
- starting_time, ending_time = get_dataset_start_end_time(ds)
443
- starting_time = pd.to_datetime(starting_time).strftime("%Y%m%d%H%M%S")
444
- ending_time = pd.to_datetime(ending_time).strftime("%Y%m%d%H%M%S")
445
- campaign_name = infer_campaign_name_from_path(processed_dir).replace(".", "-")
446
- version = PRODUCT_VERSION
789
+ from disdrodb import ARCHIVE_VERSION
790
+
791
+ starting_time, ending_time = get_file_start_end_time(ds)
792
+ starting_time = starting_time.strftime("%Y%m%d%H%M%S")
793
+ ending_time = ending_time.strftime("%Y%m%d%H%M%S")
794
+ version = ARCHIVE_VERSION
447
795
  filename = f"L0B.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
448
796
  return filename
449
797
 
450
798
 
451
- def define_l0a_filepath(df: pd.DataFrame, processed_dir: str, station_name: str) -> str:
452
- """Define L0A file path.
799
+ def define_l0c_filename(ds, campaign_name: str, station_name: str) -> str:
800
+ """Define L0C file name.
453
801
 
454
802
  Parameters
455
803
  ----------
456
- df : pd.DataFrame
457
- L0A DataFrame.
458
- processed_dir : str
459
- Path of the processed directory.
804
+ ds : xarray.Dataset
805
+ L0B xarray Dataset.
806
+ campaign_name : str
807
+ Name of the campaign.
460
808
  station_name : str
461
809
  Name of the station.
462
810
 
463
811
  Returns
464
812
  -------
465
813
  str
466
- L0A file path.
814
+ L0B file name.
467
815
  """
468
- filename = define_l0a_filename(df=df, processed_dir=processed_dir, station_name=station_name)
469
- station_dir = define_l0a_station_dir(processed_dir=processed_dir, station_name=station_name)
470
- filepath = os.path.join(station_dir, filename)
471
- return filepath
816
+ from disdrodb import ARCHIVE_VERSION
817
+
818
+ # TODO: add sample_interval as argument
819
+ sample_interval = int(ensure_sample_interval_in_seconds(ds["sample_interval"]).data.item())
820
+ sample_interval_acronym = define_accumulation_acronym(sample_interval, rolling=False)
821
+ starting_time, ending_time = get_file_start_end_time(ds)
822
+ starting_time = starting_time.strftime("%Y%m%d%H%M%S")
823
+ ending_time = ending_time.strftime("%Y%m%d%H%M%S")
824
+ version = ARCHIVE_VERSION
825
+ filename = (
826
+ f"L0C.{sample_interval_acronym}.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
827
+ )
828
+ return filename
472
829
 
473
830
 
474
- def define_l0b_filepath(ds: xr.Dataset, processed_dir: str, station_name: str, l0b_concat=False) -> str:
475
- """Define L0B file path.
831
+ def define_l1_filename(ds, campaign_name, station_name: str) -> str:
832
+ """Define L1 file name.
476
833
 
477
834
  Parameters
478
835
  ----------
479
- ds : xr.Dataset
480
- L0B xarray Dataset.
481
- processed_dir : str
482
- Path of the processed directory.
836
+ ds : xarray.Dataset
837
+ L1 xarray Dataset.
838
+ campaign_name : str
839
+ Name of the campaign.
483
840
  station_name : str
484
- ID of the station
485
- l0b_concat : bool
486
- If False, the file is specified inside the station directory.
487
- If True, the file is specified outside the station directory.
841
+ Name of the station.
488
842
 
489
843
  Returns
490
844
  -------
491
845
  str
492
- L0B file path.
846
+ L1 file name.
493
847
  """
494
- station_dir = define_l0b_station_dir(processed_dir, station_name)
495
- filename = define_l0b_filename(ds, processed_dir, station_name)
496
- if l0b_concat:
497
- product_dir = os.path.dirname(station_dir)
498
- filepath = os.path.join(product_dir, filename)
499
- else:
500
- filepath = os.path.join(station_dir, filename)
501
- return filepath
848
+ from disdrodb import ARCHIVE_VERSION
849
+
850
+ # TODO: add sample_interval as argument
851
+ sample_interval = int(ensure_sample_interval_in_seconds(ds["sample_interval"]).data.item())
852
+ sample_interval_acronym = define_accumulation_acronym(sample_interval, rolling=False)
853
+ starting_time, ending_time = get_file_start_end_time(ds)
854
+ starting_time = starting_time.strftime("%Y%m%d%H%M%S")
855
+ ending_time = ending_time.strftime("%Y%m%d%H%M%S")
856
+ version = ARCHIVE_VERSION
857
+ filename = (
858
+ f"L1.{sample_interval_acronym}.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
859
+ )
860
+ return filename
502
861
 
503
862
 
504
- ####--------------------------------------------------------------------------.
863
+ def define_l2e_filename(ds, campaign_name: str, station_name: str, sample_interval: int, rolling: bool) -> str:
864
+ """Define L2E file name.
865
+
866
+ Parameters
867
+ ----------
868
+ ds : xarray.Dataset
869
+ L1 xarray Dataset
870
+ campaign_name : str
871
+ Name of the campaign.
872
+ station_name : str
873
+ Name of the station
874
+
875
+ Returns
876
+ -------
877
+ str
878
+ L0B file name.
879
+ """
880
+ from disdrodb import ARCHIVE_VERSION
881
+
882
+ sample_interval_acronym = define_accumulation_acronym(seconds=sample_interval, rolling=rolling)
883
+ starting_time, ending_time = get_file_start_end_time(ds)
884
+ starting_time = starting_time.strftime("%Y%m%d%H%M%S")
885
+ ending_time = ending_time.strftime("%Y%m%d%H%M%S")
886
+ version = ARCHIVE_VERSION
887
+ filename = (
888
+ f"L2E.{sample_interval_acronym}.{campaign_name}.{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
889
+ )
890
+ return filename
891
+
892
+
893
+ def define_l2m_filename(
894
+ ds,
895
+ campaign_name: str,
896
+ station_name: str,
897
+ sample_interval: int,
898
+ rolling: bool,
899
+ model_name: str,
900
+ ) -> str:
901
+ """Define L2M file name.
902
+
903
+ Parameters
904
+ ----------
905
+ ds : xarray.Dataset
906
+ L1 xarray Dataset
907
+ campaign_name : str
908
+ Name of the campaign.
909
+ station_name : str
910
+ Name of the station
911
+
912
+ Returns
913
+ -------
914
+ str
915
+ L0B file name.
916
+ """
917
+ from disdrodb import ARCHIVE_VERSION
918
+
919
+ sample_interval_acronym = define_accumulation_acronym(seconds=sample_interval, rolling=rolling)
920
+ starting_time, ending_time = get_file_start_end_time(ds)
921
+ starting_time = starting_time.strftime("%Y%m%d%H%M%S")
922
+ ending_time = ending_time.strftime("%Y%m%d%H%M%S")
923
+ version = ARCHIVE_VERSION
924
+ filename = (
925
+ f"L2M_{model_name}.{sample_interval_acronym}.{campaign_name}."
926
+ + f"{station_name}.s{starting_time}.e{ending_time}.{version}.nc"
927
+ )
928
+ return filename