disdrodb 0.2.1__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (302) hide show
  1. disdrodb/__init__.py +1 -1
  2. disdrodb/_config.py +1 -3
  3. disdrodb/_version.py +2 -2
  4. disdrodb/accessor/__init__.py +1 -1
  5. disdrodb/accessor/methods.py +9 -9
  6. disdrodb/api/checks.py +1 -3
  7. disdrodb/api/configs.py +1 -3
  8. disdrodb/api/create_directories.py +4 -6
  9. disdrodb/api/info.py +1 -3
  10. disdrodb/api/io.py +9 -8
  11. disdrodb/api/path.py +1 -3
  12. disdrodb/cli/disdrodb_check_metadata_archive.py +2 -2
  13. disdrodb/cli/disdrodb_check_products_options.py +44 -0
  14. disdrodb/cli/disdrodb_create_summary.py +48 -22
  15. disdrodb/cli/disdrodb_create_summary_station.py +39 -18
  16. disdrodb/cli/disdrodb_data_archive_directory.py +1 -3
  17. disdrodb/cli/disdrodb_download_archive.py +45 -24
  18. disdrodb/cli/disdrodb_download_metadata_archive.py +27 -16
  19. disdrodb/cli/disdrodb_download_station.py +56 -26
  20. disdrodb/cli/disdrodb_initialize_station.py +40 -20
  21. disdrodb/cli/disdrodb_metadata_archive_directory.py +1 -3
  22. disdrodb/cli/disdrodb_open_data_archive.py +16 -11
  23. disdrodb/cli/disdrodb_open_logs_directory.py +29 -18
  24. disdrodb/cli/disdrodb_open_metadata_archive.py +25 -11
  25. disdrodb/cli/disdrodb_open_metadata_directory.py +32 -20
  26. disdrodb/cli/disdrodb_open_product_directory.py +38 -21
  27. disdrodb/cli/disdrodb_open_readers_directory.py +1 -3
  28. disdrodb/cli/disdrodb_run.py +189 -0
  29. disdrodb/cli/disdrodb_run_l0.py +55 -64
  30. disdrodb/cli/disdrodb_run_l0_station.py +47 -52
  31. disdrodb/cli/disdrodb_run_l0a.py +47 -45
  32. disdrodb/cli/disdrodb_run_l0a_station.py +38 -37
  33. disdrodb/cli/disdrodb_run_l0b.py +45 -45
  34. disdrodb/cli/disdrodb_run_l0b_station.py +37 -36
  35. disdrodb/cli/disdrodb_run_l0c.py +50 -47
  36. disdrodb/cli/disdrodb_run_l0c_station.py +41 -38
  37. disdrodb/cli/disdrodb_run_l1.py +49 -45
  38. disdrodb/cli/disdrodb_run_l1_station.py +40 -37
  39. disdrodb/cli/disdrodb_run_l2e.py +50 -45
  40. disdrodb/cli/disdrodb_run_l2e_station.py +41 -37
  41. disdrodb/cli/disdrodb_run_l2m.py +49 -45
  42. disdrodb/cli/disdrodb_run_l2m_station.py +40 -37
  43. disdrodb/cli/disdrodb_run_station.py +184 -0
  44. disdrodb/cli/disdrodb_upload_archive.py +45 -35
  45. disdrodb/cli/disdrodb_upload_station.py +39 -32
  46. disdrodb/configs.py +13 -8
  47. disdrodb/constants.py +4 -2
  48. disdrodb/data_transfer/__init__.py +1 -3
  49. disdrodb/data_transfer/download_data.py +38 -54
  50. disdrodb/data_transfer/upload_data.py +1 -3
  51. disdrodb/data_transfer/zenodo.py +1 -3
  52. disdrodb/docs.py +1 -3
  53. disdrodb/etc/configs/attributes.yaml +52 -2
  54. disdrodb/etc/configs/encodings.yaml +45 -1
  55. disdrodb/etc/products/L0C/ODM470/global.yaml +5 -0
  56. disdrodb/etc/products/L0C/global.yaml +5 -0
  57. disdrodb/etc/products/L1/ODM470/global.yaml +6 -0
  58. disdrodb/etc/products/L1/global.yaml +0 -13
  59. disdrodb/etc/products/L2E/LPM/1MIN.yaml +1 -0
  60. disdrodb/etc/products/L2E/LPM/global.yaml +36 -0
  61. disdrodb/etc/products/L2E/LPM_V0/1MIN.yaml +1 -0
  62. disdrodb/etc/products/L2E/LPM_V0/global.yaml +36 -0
  63. disdrodb/etc/products/L2E/ODM470/1MIN.yaml +1 -0
  64. disdrodb/etc/products/L2E/ODM470/global.yaml +36 -0
  65. disdrodb/etc/products/L2E/PARSIVEL/1MIN.yaml +1 -0
  66. disdrodb/etc/products/L2E/PARSIVEL/global.yaml +36 -0
  67. disdrodb/etc/products/L2E/PARSIVEL2/1MIN.yaml +1 -0
  68. disdrodb/etc/products/L2E/PARSIVEL2/global.yaml +36 -0
  69. disdrodb/etc/products/L2E/PWS100/1MIN.yaml +1 -0
  70. disdrodb/etc/products/L2E/PWS100/global.yaml +36 -0
  71. disdrodb/etc/products/L2E/RD80/1MIN.yaml +19 -0
  72. disdrodb/etc/products/L2E/SWS250/1MIN.yaml +19 -0
  73. disdrodb/etc/products/L2E/global.yaml +16 -2
  74. disdrodb/fall_velocity/__init__.py +46 -0
  75. disdrodb/fall_velocity/graupel.py +483 -0
  76. disdrodb/fall_velocity/hail.py +287 -0
  77. disdrodb/{l1/fall_velocity.py → fall_velocity/rain.py} +264 -44
  78. disdrodb/issue/__init__.py +1 -3
  79. disdrodb/issue/checks.py +1 -3
  80. disdrodb/issue/reader.py +1 -3
  81. disdrodb/issue/writer.py +1 -3
  82. disdrodb/l0/__init__.py +1 -1
  83. disdrodb/l0/check_configs.py +25 -16
  84. disdrodb/l0/check_standards.py +1 -3
  85. disdrodb/l0/configs/ODM470/bins_diameter.yml +643 -0
  86. disdrodb/l0/configs/ODM470/bins_velocity.yml +0 -0
  87. disdrodb/l0/configs/ODM470/l0a_encodings.yml +11 -0
  88. disdrodb/l0/configs/ODM470/l0b_cf_attrs.yml +46 -0
  89. disdrodb/l0/configs/ODM470/l0b_encodings.yml +106 -0
  90. disdrodb/l0/configs/ODM470/raw_data_format.yml +111 -0
  91. disdrodb/l0/configs/PARSIVEL/l0b_cf_attrs.yml +1 -1
  92. disdrodb/l0/l0_reader.py +1 -3
  93. disdrodb/l0/l0a_processing.py +1 -3
  94. disdrodb/l0/l0b_nc_processing.py +2 -4
  95. disdrodb/l0/l0b_processing.py +1 -3
  96. disdrodb/l0/l0c_processing.py +27 -11
  97. disdrodb/l0/readers/LPM/ARM/ARM_LPM.py +1 -1
  98. disdrodb/l0/readers/LPM/AUSTRALIA/MELBOURNE_2007_LPM.py +1 -1
  99. disdrodb/l0/readers/LPM/BRAZIL/CHUVA_LPM.py +1 -1
  100. disdrodb/l0/readers/LPM/BRAZIL/GOAMAZON_LPM.py +1 -1
  101. disdrodb/l0/readers/LPM/GERMANY/DWD.py +190 -12
  102. disdrodb/l0/readers/LPM/ITALY/GID_LPM.py +47 -6
  103. disdrodb/l0/readers/LPM/ITALY/GID_LPM_PI.py +1 -1
  104. disdrodb/l0/readers/LPM/ITALY/GID_LPM_T.py +5 -2
  105. disdrodb/l0/readers/LPM/ITALY/GID_LPM_W.py +1 -3
  106. disdrodb/l0/readers/LPM/KIT/CHWALA.py +1 -3
  107. disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_LPM_NC.py +1 -1
  108. disdrodb/l0/readers/LPM/NETHERLANDS/DELFT_RWANDA_LPM_NC.py +1 -1
  109. disdrodb/l0/readers/LPM/NORWAY/HAUKELISETER_LPM.py +1 -3
  110. disdrodb/l0/readers/LPM/NORWAY/NMBU_LPM.py +1 -3
  111. disdrodb/l0/readers/LPM/SLOVENIA/ARSO.py +1 -3
  112. disdrodb/l0/readers/LPM/SLOVENIA/UL.py +1 -3
  113. disdrodb/l0/readers/LPM/SWITZERLAND/INNERERIZ_LPM.py +1 -3
  114. disdrodb/l0/readers/LPM/UK/DIVEN.py +1 -1
  115. disdrodb/l0/readers/LPM/UK/WITHWORTH_LPM.py +1 -3
  116. disdrodb/l0/readers/LPM/USA/CHARLESTON.py +1 -3
  117. disdrodb/l0/readers/LPM_V0/BELGIUM/ULIEGE.py +1 -3
  118. disdrodb/l0/readers/LPM_V0/ITALY/GID_LPM_V0.py +1 -1
  119. disdrodb/l0/readers/ODM470/OCEAN/OCEANRAIN.py +123 -0
  120. disdrodb/l0/readers/PARSIVEL/AUSTRALIA/MELBOURNE_2007_PARSIVEL.py +1 -1
  121. disdrodb/l0/readers/PARSIVEL/BASQUECOUNTRY/EUSKALMET_OTT.py +1 -1
  122. disdrodb/l0/readers/PARSIVEL/CHINA/CHONGQING.py +1 -3
  123. disdrodb/l0/readers/PARSIVEL/EPFL/ARCTIC_2021.py +1 -1
  124. disdrodb/l0/readers/PARSIVEL/EPFL/COMMON_2011.py +1 -1
  125. disdrodb/l0/readers/PARSIVEL/EPFL/DAVOS_2009_2011.py +1 -1
  126. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_2009.py +1 -1
  127. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2008.py +1 -1
  128. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2010.py +1 -1
  129. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2011.py +1 -1
  130. disdrodb/l0/readers/PARSIVEL/EPFL/EPFL_ROOF_2012.py +1 -1
  131. disdrodb/l0/readers/PARSIVEL/EPFL/GENEPI_2007.py +1 -1
  132. disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007.py +1 -1
  133. disdrodb/l0/readers/PARSIVEL/EPFL/GRAND_ST_BERNARD_2007_2.py +1 -1
  134. disdrodb/l0/readers/PARSIVEL/EPFL/HPICONET_2010.py +1 -1
  135. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP2.py +1 -1
  136. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP3.py +1 -1
  137. disdrodb/l0/readers/PARSIVEL/EPFL/HYMEX_LTE_SOP4.py +1 -1
  138. disdrodb/l0/readers/PARSIVEL/EPFL/LOCARNO_2018.py +1 -1
  139. disdrodb/l0/readers/PARSIVEL/EPFL/LOCARNO_2019.py +1 -1
  140. disdrodb/l0/readers/PARSIVEL/EPFL/PARADISO_2014.py +1 -1
  141. disdrodb/l0/readers/PARSIVEL/EPFL/PARSIVEL_2007.py +1 -1
  142. disdrodb/l0/readers/PARSIVEL/EPFL/PLATO_2019.py +1 -1
  143. disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019.py +1 -1
  144. disdrodb/l0/readers/PARSIVEL/EPFL/RACLETS_2019_WJF.py +1 -1
  145. disdrodb/l0/readers/PARSIVEL/EPFL/RIETHOLZBACH_2011.py +1 -1
  146. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2017.py +1 -1
  147. disdrodb/l0/readers/PARSIVEL/EPFL/SAMOYLOV_2019.py +1 -1
  148. disdrodb/l0/readers/PARSIVEL/EPFL/UNIL_2022.py +1 -1
  149. disdrodb/l0/readers/PARSIVEL/JAPAN/JMA.py +1 -1
  150. disdrodb/l0/readers/PARSIVEL/KOREA/ICEPOP_MSC.py +159 -0
  151. disdrodb/l0/readers/PARSIVEL/NASA/LPVEX.py +1 -1
  152. disdrodb/l0/readers/PARSIVEL/NASA/MC3E.py +1 -1
  153. disdrodb/l0/readers/PARSIVEL/NCAR/CCOPE_2015.py +1 -1
  154. disdrodb/l0/readers/PARSIVEL/NCAR/OWLES_MIPS.py +1 -1
  155. disdrodb/l0/readers/PARSIVEL/NCAR/PECAN_MOBILE.py +1 -1
  156. disdrodb/l0/readers/PARSIVEL/NCAR/PLOWS_MIPS.py +1 -1
  157. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2009.py +1 -1
  158. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010.py +1 -3
  159. disdrodb/l0/readers/PARSIVEL/NCAR/VORTEX2_2010_UF.py +1 -3
  160. disdrodb/l0/readers/PARSIVEL/SLOVENIA/UL.py +1 -1
  161. disdrodb/l0/readers/PARSIVEL2/ARM/ARM_PARSIVEL2.py +1 -1
  162. disdrodb/l0/readers/PARSIVEL2/BASQUECOUNTRY/EUSKALMET_OTT2.py +1 -1
  163. disdrodb/l0/readers/PARSIVEL2/BELGIUM/ILVO.py +1 -3
  164. disdrodb/l0/readers/PARSIVEL2/BRAZIL/CHUVA_PARSIVEL2.py +1 -1
  165. disdrodb/l0/readers/PARSIVEL2/BRAZIL/GOAMAZON_PARSIVEL2.py +1 -1
  166. disdrodb/l0/readers/PARSIVEL2/CANADA/UQAM_NC.py +1 -1
  167. disdrodb/l0/readers/PARSIVEL2/DENMARK/DTU.py +1 -1
  168. disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_nc.py +1 -1
  169. disdrodb/l0/readers/PARSIVEL2/DENMARK/EROSION_raw.py +1 -1
  170. disdrodb/l0/readers/PARSIVEL2/FINLAND/FMI_PARSIVEL2.py +1 -1
  171. disdrodb/l0/readers/PARSIVEL2/FRANCE/ENPC_PARSIVEL2.py +1 -3
  172. disdrodb/l0/readers/PARSIVEL2/FRANCE/OSUG.py +1 -1
  173. disdrodb/l0/readers/PARSIVEL2/FRANCE/SIRTA_PARSIVEL2.py +1 -3
  174. disdrodb/l0/readers/PARSIVEL2/GREECE/NOA.py +4 -3
  175. disdrodb/l0/readers/PARSIVEL2/ITALY/GID_PARSIVEL2.py +1 -3
  176. disdrodb/l0/readers/PARSIVEL2/ITALY/HYDROX.py +5 -3
  177. disdrodb/l0/readers/PARSIVEL2/JAPAN/PRECIP.py +1 -1
  178. disdrodb/l0/readers/PARSIVEL2/KIT/BURKINA_FASO.py +1 -1
  179. disdrodb/l0/readers/PARSIVEL2/KIT/TEAMX.py +1 -1
  180. disdrodb/l0/readers/PARSIVEL2/KOREA/ICEPOP_MSC.py +161 -0
  181. disdrodb/l0/readers/PARSIVEL2/KOREA/ICEPOP_UCLM.py +126 -0
  182. disdrodb/l0/readers/PARSIVEL2/MEXICO/OH_IIUNAM_nc.py +1 -1
  183. disdrodb/l0/readers/PARSIVEL2/MPI/BCO_PARSIVEL2.py +1 -1
  184. disdrodb/l0/readers/PARSIVEL2/MPI/BOWTIE.py +1 -1
  185. disdrodb/l0/readers/PARSIVEL2/NASA/APU.py +3 -1
  186. disdrodb/l0/readers/PARSIVEL2/NASA/NSSTC.py +1 -1
  187. disdrodb/l0/readers/PARSIVEL2/NCAR/FARM_PARSIVEL2.py +1 -1
  188. disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_FP3.py +1 -1
  189. disdrodb/l0/readers/PARSIVEL2/NCAR/PECAN_MIPS.py +1 -1
  190. disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_MIPS.py +1 -1
  191. disdrodb/l0/readers/PARSIVEL2/NCAR/PERILS_PIPS.py +1 -1
  192. disdrodb/l0/readers/PARSIVEL2/NCAR/RELAMPAGO_PARSIVEL2.py +1 -1
  193. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_PJ.py +1 -1
  194. disdrodb/l0/readers/PARSIVEL2/NCAR/SNOWIE_SB.py +1 -1
  195. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P1.py +1 -3
  196. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_P2.py +1 -1
  197. disdrodb/l0/readers/PARSIVEL2/NCAR/VORTEX_SE_2016_PIPS.py +1 -1
  198. disdrodb/l0/readers/PARSIVEL2/NETHERLANDS/DELFT_NC.py +1 -1
  199. disdrodb/l0/readers/PARSIVEL2/NORWAY/UIB.py +10 -2
  200. disdrodb/l0/readers/PARSIVEL2/PHILIPPINES/PAGASA.py +1 -3
  201. disdrodb/l0/readers/PARSIVEL2/SPAIN/CENER.py +1 -1
  202. disdrodb/l0/readers/PARSIVEL2/SPAIN/CR1000DL.py +1 -1
  203. disdrodb/l0/readers/PARSIVEL2/SPAIN/GRANADA.py +1 -3
  204. disdrodb/l0/readers/PARSIVEL2/SPAIN/LIAISE.py +1 -1
  205. disdrodb/l0/readers/PARSIVEL2/SWEDEN/SMHI.py +1 -1
  206. disdrodb/l0/readers/PARSIVEL2/USA/CSU.py +1 -1
  207. disdrodb/l0/readers/PARSIVEL2/USA/CW3E.py +1 -1
  208. disdrodb/l0/readers/PWS100/AUSTRIA/HOAL.py +1 -3
  209. disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100.py +1 -3
  210. disdrodb/l0/readers/PWS100/FRANCE/ENPC_PWS100_SIRTA.py +1 -1
  211. disdrodb/l0/readers/RD80/BRAZIL/ATTO_RD80.py +1 -3
  212. disdrodb/l0/readers/RD80/BRAZIL/CHUVA_RD80.py +1 -3
  213. disdrodb/l0/readers/RD80/BRAZIL/GOAMAZON_RD80.py +1 -3
  214. disdrodb/l0/readers/RD80/NCAR/CINDY_2011_RD80.py +1 -3
  215. disdrodb/l0/readers/RD80/NCAR/RELAMPAGO_RD80.py +1 -3
  216. disdrodb/l0/readers/RD80/NOAA/PSL_RD80.py +1 -3
  217. disdrodb/l0/readers/SWS250/BELGIUM/KMI.py +1 -3
  218. disdrodb/l0/readers/template_reader_raw_netcdf_data.py +1 -3
  219. disdrodb/l0/readers/template_reader_raw_text_data.py +1 -3
  220. disdrodb/l0/standards.py +4 -5
  221. disdrodb/l0/template_tools.py +1 -3
  222. disdrodb/l1/__init__.py +1 -1
  223. disdrodb/l1/classification.py +913 -0
  224. disdrodb/l1/processing.py +36 -106
  225. disdrodb/l1/resampling.py +8 -3
  226. disdrodb/l1_env/__init__.py +1 -1
  227. disdrodb/l1_env/routines.py +6 -6
  228. disdrodb/l2/__init__.py +1 -1
  229. disdrodb/l2/empirical_dsd.py +57 -31
  230. disdrodb/l2/processing.py +327 -62
  231. disdrodb/metadata/checks.py +1 -3
  232. disdrodb/metadata/download.py +4 -4
  233. disdrodb/metadata/geolocation.py +1 -3
  234. disdrodb/metadata/info.py +1 -3
  235. disdrodb/metadata/manipulation.py +1 -3
  236. disdrodb/metadata/reader.py +1 -3
  237. disdrodb/metadata/search.py +1 -3
  238. disdrodb/metadata/standards.py +1 -3
  239. disdrodb/metadata/writer.py +1 -3
  240. disdrodb/physics/__init__.py +17 -0
  241. disdrodb/physics/atmosphere.py +272 -0
  242. disdrodb/physics/water.py +130 -0
  243. disdrodb/physics/wrappers.py +62 -0
  244. disdrodb/psd/__init__.py +1 -1
  245. disdrodb/psd/fitting.py +22 -9
  246. disdrodb/psd/models.py +1 -1
  247. disdrodb/routines/__init__.py +5 -1
  248. disdrodb/routines/l0.py +26 -16
  249. disdrodb/routines/l1.py +8 -6
  250. disdrodb/routines/l2.py +8 -4
  251. disdrodb/routines/options.py +116 -73
  252. disdrodb/routines/options_validation.py +728 -0
  253. disdrodb/routines/wrappers.py +431 -11
  254. disdrodb/scattering/__init__.py +1 -1
  255. disdrodb/scattering/axis_ratio.py +6 -6
  256. disdrodb/scattering/permittivity.py +8 -8
  257. disdrodb/scattering/routines.py +31 -13
  258. disdrodb/summary/__init__.py +1 -1
  259. disdrodb/summary/routines.py +83 -25
  260. disdrodb/utils/__init__.py +1 -1
  261. disdrodb/utils/archiving.py +16 -9
  262. disdrodb/utils/attrs.py +4 -3
  263. disdrodb/utils/cli.py +8 -10
  264. disdrodb/utils/compression.py +9 -11
  265. disdrodb/utils/dask.py +2 -3
  266. disdrodb/utils/dataframe.py +1 -3
  267. disdrodb/utils/decorators.py +1 -3
  268. disdrodb/utils/dict.py +1 -1
  269. disdrodb/utils/directories.py +3 -5
  270. disdrodb/utils/encoding.py +2 -4
  271. disdrodb/utils/event.py +1 -1
  272. disdrodb/utils/list.py +1 -3
  273. disdrodb/utils/logger.py +1 -3
  274. disdrodb/utils/manipulations.py +175 -5
  275. disdrodb/utils/pydantic.py +80 -0
  276. disdrodb/utils/routines.py +1 -3
  277. disdrodb/utils/subsetting.py +1 -1
  278. disdrodb/utils/time.py +3 -2
  279. disdrodb/utils/warnings.py +1 -3
  280. disdrodb/utils/writer.py +1 -3
  281. disdrodb/utils/xarray.py +30 -3
  282. disdrodb/utils/yaml.py +1 -3
  283. disdrodb/viz/__init__.py +1 -1
  284. disdrodb/viz/plots.py +192 -18
  285. {disdrodb-0.2.1.dist-info → disdrodb-0.3.0.dist-info}/METADATA +2 -2
  286. disdrodb-0.3.0.dist-info/RECORD +358 -0
  287. {disdrodb-0.2.1.dist-info → disdrodb-0.3.0.dist-info}/entry_points.txt +3 -0
  288. disdrodb/etc/products/L1/1MIN.yaml +0 -13
  289. disdrodb/etc/products/L1/LPM/1MIN.yaml +0 -13
  290. disdrodb/etc/products/L1/LPM_V0/1MIN.yaml +0 -13
  291. disdrodb/etc/products/L1/PARSIVEL/1MIN.yaml +0 -13
  292. disdrodb/etc/products/L1/PARSIVEL2/1MIN.yaml +0 -13
  293. disdrodb/etc/products/L1/PWS100/1MIN.yaml +0 -13
  294. disdrodb/etc/products/L1/RD80/1MIN.yaml +0 -13
  295. disdrodb/etc/products/L1/SWS250/1MIN.yaml +0 -13
  296. disdrodb/etc/products/L2M/10MIN.yaml +0 -12
  297. disdrodb/l1/beard_model.py +0 -662
  298. disdrodb/l1/filters.py +0 -205
  299. disdrodb-0.2.1.dist-info/RECORD +0 -329
  300. {disdrodb-0.2.1.dist-info → disdrodb-0.3.0.dist-info}/WHEEL +0 -0
  301. {disdrodb-0.2.1.dist-info → disdrodb-0.3.0.dist-info}/licenses/LICENSE +0 -0
  302. {disdrodb-0.2.1.dist-info → disdrodb-0.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,106 @@
1
+ precipitation_rate:
2
+ dtype: float32
3
+ zlib: true
4
+ complevel: 3
5
+ shuffle: true
6
+ fletcher32: false
7
+ contiguous: false
8
+ chunksizes: 43200
9
+ precip_flag:
10
+ dtype: int8
11
+ zlib: true
12
+ complevel: 3
13
+ shuffle: true
14
+ fletcher32: false
15
+ contiguous: false
16
+ chunksizes: 43200
17
+ _FillValue: 127
18
+ reference_voltage:
19
+ dtype: float32
20
+ zlib: true
21
+ complevel: 3
22
+ shuffle: true
23
+ fletcher32: false
24
+ contiguous: false
25
+ chunksizes: 43200
26
+ weather_code_synop_4677:
27
+ dtype: uint8
28
+ zlib: true
29
+ complevel: 3
30
+ shuffle: true
31
+ fletcher32: false
32
+ contiguous: false
33
+ chunksizes: 5000
34
+ _FillValue: 255
35
+ relative_wind_speed:
36
+ dtype: uint16
37
+ scale_factor: 0.1
38
+ add_offset: -99.9
39
+ zlib: true
40
+ complevel: 3
41
+ shuffle: true
42
+ fletcher32: false
43
+ contiguous: false
44
+ _FillValue: 65535
45
+ chunksizes: 43200
46
+ relative_wind_direction:
47
+ dtype: uint16
48
+ zlib: true
49
+ complevel: 3
50
+ shuffle: true
51
+ fletcher32: false
52
+ contiguous: false
53
+ _FillValue: 65535
54
+ chunksizes: 43200
55
+ raw_drop_number:
56
+ dtype: uint16
57
+ zlib: true
58
+ complevel: 3
59
+ shuffle: true
60
+ fletcher32: false
61
+ contiguous: false
62
+ _FillValue: 65535
63
+ chunksizes:
64
+ - 43200
65
+ - 128
66
+ air_temperature:
67
+ dtype: uint16
68
+ scale_factor: 0.1
69
+ add_offset: -99.9
70
+ zlib: true
71
+ complevel: 3
72
+ shuffle: true
73
+ fletcher32: false
74
+ contiguous: false
75
+ _FillValue: 65535
76
+ chunksizes: 43200
77
+ relative_humidity:
78
+ dtype: uint16
79
+ scale_factor: 0.01
80
+ zlib: true
81
+ complevel: 3
82
+ shuffle: true
83
+ fletcher32: false
84
+ contiguous: false
85
+ _FillValue: 65535
86
+ chunksizes: 43200
87
+ wind_speed:
88
+ dtype: uint16
89
+ scale_factor: 0.1
90
+ add_offset: -99.9
91
+ zlib: true
92
+ complevel: 3
93
+ shuffle: true
94
+ fletcher32: false
95
+ contiguous: false
96
+ _FillValue: 65535
97
+ chunksizes: 43200
98
+ wind_direction:
99
+ dtype: uint16
100
+ zlib: true
101
+ complevel: 3
102
+ shuffle: true
103
+ fletcher32: false
104
+ contiguous: false
105
+ _FillValue: 65535
106
+ chunksizes: 43200
@@ -0,0 +1,111 @@
1
+ precipitation_rate:
2
+ n_digits: 6
3
+ n_characters: 7
4
+ n_decimals: 3
5
+ n_naturals: 3
6
+ data_range:
7
+ - 0.0
8
+ - 999.999
9
+ nan_flags: null
10
+ field_number: "1"
11
+ reference_voltage:
12
+ n_digits: 6
13
+ n_characters: 7
14
+ n_decimals: 3
15
+ n_naturals: 3
16
+ data_range:
17
+ - 0.0
18
+ - 5.5
19
+ nan_flags: null
20
+ field_number: "2"
21
+ relative_wind_speed:
22
+ n_digits: 6
23
+ n_characters: 7
24
+ n_decimals: 3
25
+ n_naturals: 3
26
+ data_range:
27
+ - 0.0
28
+ - 100
29
+ nan_flags: null
30
+ field_number: "3"
31
+ relative_wind_direction:
32
+ n_digits: 6
33
+ n_characters: 7
34
+ n_decimals: 3
35
+ n_naturals: 3
36
+ data_range:
37
+ - 0.0
38
+ - 360
39
+ nan_flags: null
40
+ field_number: "4"
41
+ precip_flag:
42
+ n_digits: 1
43
+ n_characters: 1
44
+ n_decimals: 0
45
+ n_naturals: 0
46
+ data_range:
47
+ - -1
48
+ - 5
49
+ nan_flags: null
50
+ field_number: "5"
51
+ weather_code_synop_4677:
52
+ n_digits: 2
53
+ n_characters: 2
54
+ n_decimals: 0
55
+ n_naturals: 2
56
+ data_range:
57
+ - 0
58
+ - 90
59
+ nan_flags: null
60
+ field_number: "6"
61
+ raw_drop_number:
62
+ n_digits: 1317
63
+ n_characters: 1756
64
+ n_decimals: 1317
65
+ n_naturals: 0
66
+ data_range: null
67
+ nan_flags: null
68
+ dimension_order:
69
+ - diameter_bin_center
70
+ n_values: 128
71
+ field_number: "81"
72
+ air_temperature:
73
+ n_digits: 4
74
+ n_characters: 5
75
+ n_decimals: 1
76
+ n_naturals: 2
77
+ data_range:
78
+ - -40
79
+ - 70
80
+ nan_flags: 99999
81
+ field_number: "521"
82
+ relative_humidity:
83
+ n_digits: 5
84
+ n_characters: 5
85
+ n_decimals: 0
86
+ n_naturals: 5
87
+ data_range:
88
+ - 0
89
+ - 99999
90
+ nan_flags: 99999
91
+ field_number: "522"
92
+ wind_speed:
93
+ n_digits: 3
94
+ n_characters: 4
95
+ n_decimals: 1
96
+ n_naturals: 2
97
+ data_range:
98
+ - 0
99
+ - 60
100
+ nan_flags: null
101
+ field_number: "523"
102
+ wind_direction:
103
+ n_digits: 3
104
+ n_characters: 3
105
+ n_decimals: 0
106
+ n_naturals: 3
107
+ data_range:
108
+ - 0
109
+ - 360
110
+ nan_flags: 999
111
+ field_number: "524"
@@ -121,7 +121,7 @@ reflectivity_16bit:
121
121
  raw_drop_concentration:
122
122
  description: Particle number concentrations per diameter class
123
123
  long_name: Raw drop concentration
124
- units: 1/(m3*mm)
124
+ units: log10 1/(m3*mm)
125
125
  raw_drop_average_velocity:
126
126
  description: Average particle velocities for each diameter class
127
127
  long_name: Raw drop average velocity
disdrodb/l0/l0_reader.py CHANGED
@@ -1,7 +1,5 @@
1
- #!/usr/bin/env python3
2
-
3
1
  # -----------------------------------------------------------------------------.
4
- # Copyright (c) 2021-2023 DISDRODB developers
2
+ # Copyright (c) 2021-2026 DISDRODB developers
5
3
  #
6
4
  # This program is free software: you can redistribute it and/or modify
7
5
  # it under the terms of the GNU General Public License as published by
@@ -1,7 +1,5 @@
1
- #!/usr/bin/env python3
2
-
3
1
  # -----------------------------------------------------------------------------.
4
- # Copyright (c) 2021-2023 DISDRODB developers
2
+ # Copyright (c) 2021-2026 DISDRODB developers
5
3
  #
6
4
  # This program is free software: you can redistribute it and/or modify
7
5
  # it under the terms of the GNU General Public License as published by
@@ -1,7 +1,5 @@
1
- #!/usr/bin/env python3
2
-
3
1
  # -----------------------------------------------------------------------------.
4
- # Copyright (c) 2021-2023 DISDRODB developers
2
+ # Copyright (c) 2021-2026 DISDRODB developers
5
3
  #
6
4
  # This program is free software: you can redistribute it and/or modify
7
5
  # it under the terms of the GNU General Public License as published by
@@ -50,7 +48,7 @@ def _check_dict_names_validity(dict_names, sensor_name):
50
48
  keys = np.array(list(dict_names.keys()))
51
49
  values = np.array(list(dict_names.values()))
52
50
  # Get invalid keys
53
- invalid_keys = keys[np.isin(values, valid_names, invert=True)]
51
+ invalid_keys = keys[np.isin(values, valid_names, invert=True)].tolist()
54
52
  if len(invalid_keys) > 0:
55
53
  # Report invalid keys and raise error
56
54
  invalid_dict = {k: dict_names[k] for k in invalid_keys}
@@ -1,7 +1,5 @@
1
- #!/usr/bin/env python3
2
-
3
1
  # -----------------------------------------------------------------------------.
4
- # Copyright (c) 2021-2023 DISDRODB developers
2
+ # Copyright (c) 2021-2026 DISDRODB developers
5
3
  #
6
4
  # This program is free software: you can redistribute it and/or modify
7
5
  # it under the terms of the GNU General Public License as published by
@@ -1,7 +1,5 @@
1
- #!/usr/bin/env python3
2
-
3
1
  # -----------------------------------------------------------------------------.
4
- # Copyright (c) 2021-2023 DISDRODB developers
2
+ # Copyright (c) 2021-2026 DISDRODB developers
5
3
  #
6
4
  # This program is free software: you can redistribute it and/or modify
7
5
  # it under the terms of the GNU General Public License as published by
@@ -340,6 +338,20 @@ def get_problematic_timestep_indices(timesteps, sample_interval):
340
338
  return idx_previous_missing, idx_next_missing, idx_isolated_missing
341
339
 
342
340
 
341
+ def nearest_expected_times(times, expected_times):
342
+ """Return index of nearest expected time."""
343
+ # both must be sorted ascending
344
+ idx = np.searchsorted(expected_times, times)
345
+ idx = np.clip(idx, 1, len(expected_times) - 1)
346
+
347
+ # Compare distance to the previous vs next expected time
348
+ prev = expected_times[idx - 1]
349
+ next_ = expected_times[idx]
350
+ choose_next = (times - prev) > (next_ - times)
351
+ nearest = np.where(choose_next, next_, prev)
352
+ return nearest
353
+
354
+
343
355
  def regularize_timesteps(ds, sample_interval, robust=False, add_quality_flag=True, logger=None, verbose=True):
344
356
  """Ensure timesteps match with the sample_interval.
345
357
 
@@ -364,13 +376,16 @@ def regularize_timesteps(ds, sample_interval, robust=False, add_quality_flag=Tru
364
376
  times = times.to_numpy(dtype="M8[s]")
365
377
  expected_times = expected_times.to_numpy(dtype="M8[s]")
366
378
 
379
+ # Vectorized mapping of observed times → nearest expected times
380
+ adjusted_times = nearest_expected_times(times, expected_times)
381
+
367
382
  # Map original times to the nearest expected times
368
- # Calculate the difference between original times and expected times
369
- time_deltas = np.abs(times - expected_times[:, None]).astype(int)
383
+ # # Calculate the difference between original times and expected times
384
+ # time_deltas = np.abs(times - expected_times[:, None]).astype(int)
370
385
 
371
- # Find the index of the closest expected time for each original time
372
- nearest_indices = np.argmin(time_deltas, axis=0)
373
- adjusted_times = expected_times[nearest_indices]
386
+ # # Find the index of the closest expected time for each original time
387
+ # nearest_indices = np.argmin(time_deltas, axis=0)
388
+ # adjusted_times = expected_times[nearest_indices]
374
389
 
375
390
  # Check for duplicates in adjusted times
376
391
  unique_times, counts = np.unique(adjusted_times, return_counts=True)
@@ -466,10 +481,10 @@ def regularize_timesteps(ds, sample_interval, robust=False, add_quality_flag=Tru
466
481
  # qc_flag[-1] = 0
467
482
 
468
483
  # Add time quality flag variable
469
- ds["time_qc"] = xr.DataArray(qc_flag, dims="time")
484
+ ds["qc_time"] = xr.DataArray(qc_flag, dims="time")
470
485
 
471
- # Add CF attributes for time_qc
472
- ds["time_qc"].attrs = {
486
+ # Add CF attributes for qc_time
487
+ ds["qc_time"].attrs = {
473
488
  "long_name": "time quality flag",
474
489
  "standard_name": "status_flag",
475
490
  "units": "1",
@@ -587,6 +602,7 @@ def _finalize_l0c_dataset(ds, sample_interval, sensor_name, verbose=True, logger
587
602
  ds = add_sample_interval(ds, sample_interval=sample_interval)
588
603
 
589
604
  # Regularize timesteps (for trailing seconds)
605
+ # --> This remove time encoding
590
606
  ds = regularize_timesteps(
591
607
  ds,
592
608
  sample_interval=sample_interval,
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  # -----------------------------------------------------------------------------.
3
- # Copyright (c) 2021-2023 DISDRODB developers
3
+ # Copyright (c) 2021-2026 DISDRODB developers
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  # -----------------------------------------------------------------------------.
3
- # Copyright (c) 2021-2023 DISDRODB developers
3
+ # Copyright (c) 2021-2026 DISDRODB developers
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  # -----------------------------------------------------------------------------.
3
- # Copyright (c) 2021-2023 DISDRODB developers
3
+ # Copyright (c) 2021-2026 DISDRODB developers
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  # -----------------------------------------------------------------------------.
3
- # Copyright (c) 2021-2023 DISDRODB developers
3
+ # Copyright (c) 2021-2026 DISDRODB developers
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -1,7 +1,5 @@
1
- #!/usr/bin/env python3
2
-
3
1
  # -----------------------------------------------------------------------------.
4
- # Copyright (c) 2021-2023 DISDRODB developers
2
+ # Copyright (c) 2021-2026 DISDRODB developers
5
3
  #
6
4
  # This program is free software: you can redistribute it and/or modify
7
5
  # it under the terms of the GNU General Public License as published by
@@ -17,13 +15,16 @@
17
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
16
  # -----------------------------------------------------------------------------.
19
17
  """DISDRODB reader for DWD stations."""
18
+ import glob
20
19
  import os
20
+ from pathlib import Path
21
21
 
22
22
  import numpy as np
23
23
  import pandas as pd
24
24
 
25
25
  from disdrodb.l0.l0_reader import is_documented_by, reader_generic_docstring
26
26
  from disdrodb.l0.l0a_processing import read_raw_text_file
27
+ from disdrodb.utils.logger import log_error, log_warning
27
28
 
28
29
  # Assign column names
29
30
  COLUMNS = [
@@ -104,14 +105,90 @@ COLUMNS = [
104
105
  "raw_drop_number",
105
106
  ]
106
107
 
108
+ ####------------------------------------------------------------------------.
109
+ #### SYNOP utilities
110
+
111
+
112
+ def _reindex_to_custom_frequency(df, freq="1min"):
113
+ # Interpolate to 1 min
114
+ t_start = df.index.min()
115
+ t_end = df.index.max()
116
+ timesteps = pd.date_range(
117
+ start=t_start,
118
+ end=t_end,
119
+ freq=freq,
120
+ )
121
+ return df.reindex(timesteps)
122
+
123
+
124
+ def interpolate_wind_direction(wind_direction, limit=None):
125
+ """Interpolate NaN values in a 1-min wind direction series.
126
+
127
+ Use circular (vector) interpolation.
128
+
129
+ Parameters
130
+ ----------
131
+ wind_direction : pandas.Series
132
+ Wind direction in degrees with DateTimeIndex.
133
+ limit : int or None
134
+ Max number of consecutive NaNs to fill.
135
+
136
+ Returns
137
+ -------
138
+ pandas.Series
139
+ Wind direction with NaNs interpolated.
140
+ """
141
+ wind_direction = wind_direction.copy()
142
+ wind_direction.index = pd.to_datetime(wind_direction.index)
143
+
144
+ # Convert to radians
145
+ theta = np.deg2rad(wind_direction)
146
+
147
+ # Vector components
148
+ u = np.cos(theta)
149
+ v = np.sin(theta)
150
+
151
+ df_vec = pd.DataFrame({"u": u, "v": v}, index=wind_direction.index)
152
+
153
+ # Interpolate ONLY NaNs
154
+ df_vec_i = df_vec.interpolate(
155
+ method="time",
156
+ limit=limit,
157
+ )
158
+
159
+ # Back to degrees
160
+ dir_i = np.rad2deg(np.arctan2(df_vec_i["v"], df_vec_i["u"]))
161
+ dir_i = (dir_i + 360) % 360
162
+
163
+ dir_i = (dir_i / 10).round() * 10
164
+ return pd.Series(dir_i, index=wind_direction.index, name=wind_direction.name)
107
165
 
108
- def read_synop_file(filepath, logger):
166
+
167
+ def retrieve_synop_filepaths(df, filepath):
168
+ """Retrieve SYNOP files relevant for a LPM file."""
169
+ # Retrieve relevant info to list required synop files
170
+ filename = os.path.basename(filepath)
171
+ station_id = filename.split("_")[1]
172
+ date = df["time"].dt.date.iloc[0]
173
+ synop_base_dir = Path(filepath).parents[3] / "SYNOP"
174
+ synop_filepaths = []
175
+ for d in [date, date + pd.Timedelta(days=1)]:
176
+ y = d.strftime("%Y")
177
+ m = d.strftime("%m")
178
+ ymd = d.strftime("%Y%m%d")
179
+ fname_pattern = f"synop10min_{station_id}_{ymd}*1.0days.dat"
180
+ glob_pattern = os.path.join(synop_base_dir, y, m, fname_pattern)
181
+ synop_filepaths.append(*glob.glob(glob_pattern))
182
+ return synop_filepaths
183
+
184
+
185
+ def read_synop_file(filepath, logger=None):
109
186
  """Read SYNOP 10 min file."""
110
187
  ##------------------------------------------------------------------------.
111
188
  #### Define column names
112
189
  column_names = [
113
190
  "time",
114
- "temperature_2m",
191
+ "air_temperature",
115
192
  "relative_humidity",
116
193
  "precipitation_accumulated_10min",
117
194
  "total_cloud_cover",
@@ -169,6 +246,99 @@ def read_synop_file(filepath, logger):
169
246
  return df
170
247
 
171
248
 
249
+ def _add_nan_synop_variables(df, logger, msg):
250
+ """Guarantee SYNOP columns on LPM df output."""
251
+ # Define SYNOP vars to be always present
252
+ synop_vars = [
253
+ "air_temperature",
254
+ "relative_humidity",
255
+ "wind_speed",
256
+ "wind_direction",
257
+ ]
258
+ # Add SYNOP vars columns
259
+ log_warning(logger=logger, msg=msg)
260
+ for v in synop_vars:
261
+ df[v] = np.nan
262
+ return df
263
+
264
+
265
+ def add_synop_information(df, filepath, logger):
266
+ """Add SYNOP (10-min) meteorological data to an LPM (1-min) dataframe.
267
+
268
+ LPM files contains timesteps: 00:00-23.59
269
+ SYNOP files contains timesteps: 00:00-23.50
270
+
271
+ To interpolate SYNOP data between 00:00-23.59 we need also next-day SYNOP file
272
+
273
+ Always returns a dataframe with SYNOP columns present.
274
+ """
275
+ # Drop duplicate timesteps from input LPM dataframe
276
+ df = df.drop_duplicates(subset="time", keep="first").sort_values("time")
277
+
278
+ # Retrieve date
279
+ date = df["time"].iloc[0].date()
280
+
281
+ # --------------------------------------------------------------------
282
+ # Retrieve required SYNOP files
283
+ synop_filepaths = retrieve_synop_filepaths(df=df, filepath=filepath)
284
+
285
+ # If no SYNOP files available
286
+ if not synop_filepaths:
287
+ msg = f"No SYNOP files available for {date}"
288
+ return _add_nan_synop_variables(df, logger=logger, msg=msg)
289
+
290
+ # Read relevant SYNOP files
291
+ synop_dfs = []
292
+ for f in synop_filepaths:
293
+ try:
294
+ synop_dfs.append(read_synop_file(f))
295
+ except Exception as e:
296
+ log_error(logger=logger, msg=f"Failed to read SYNOP file {f}. Error: {e!s}")
297
+
298
+ if not synop_dfs:
299
+ msg = f"No valid SYNOP data could be read for {date}"
300
+ return _add_nan_synop_variables(df, logger=logger, msg=msg)
301
+
302
+ # Concatenate SYNOP files into unique dataframe
303
+ df_synop_10min = pd.concat(synop_dfs, ignore_index=True)
304
+
305
+ # --------------------------------------------------------------------
306
+ # Subset SYNOP file
307
+ tmin = df["time"].min() - pd.Timedelta(minutes=10)
308
+ tmax = df["time"].max() + pd.Timedelta(minutes=10)
309
+ df_synop_10min = df_synop_10min[(df_synop_10min["time"] >= tmin) & (df_synop_10min["time"] <= tmax)]
310
+ if df_synop_10min.empty:
311
+ msg = f"No SYNOP data available for {date}"
312
+ return _add_nan_synop_variables(df, logger=logger, msg=msg)
313
+
314
+ # Drop time duplicates if present
315
+ df_synop_10min = df_synop_10min.drop_duplicates(subset="time", keep="first")
316
+ df_synop_10min = df_synop_10min.drop(columns=["total_cloud_cover", "precipitation_accumulated_10min"])
317
+ # Reindex SYNOP 10 min file to 1 min
318
+ df_synop_10min = df_synop_10min.set_index("time") # set time column as index
319
+ df_synop_10min = df_synop_10min.astype(float) # cast column to float
320
+ df_synop_1min = _reindex_to_custom_frequency(df_synop_10min, freq="1min")
321
+ # Interpolate variables
322
+ df_synop_1min["wind_direction"] = interpolate_wind_direction(df_synop_1min["wind_direction"], limit=9)
323
+ variables = ["air_temperature", "relative_humidity", "wind_speed"]
324
+ df_synop_1min[variables] = df_synop_1min[variables].interpolate(method="time", limit=9)
325
+ df_synop_1min = df_synop_1min.reset_index().rename(columns={"index": "time"})
326
+ # Merge data
327
+ df_synop_1min = df_synop_1min.drop_duplicates(subset="time", keep="first").sort_values("time")
328
+ df_merged = pd.merge_asof(
329
+ df,
330
+ df_synop_1min,
331
+ on="time",
332
+ direction="nearest", # or "backward" / "forward"
333
+ tolerance=pd.Timedelta("0min"),
334
+ )
335
+ return df_merged
336
+
337
+
338
+ ####-------------------------------------------------------------------------.
339
+ #### LPM parsers
340
+
341
+
172
342
  def parse_format_v1(df):
173
343
  """Parse DWD format v1."""
174
344
  raise NotImplementedError
@@ -433,7 +603,7 @@ def reader(
433
603
  ):
434
604
  """Reader."""
435
605
  ##------------------------------------------------------------------------.
436
- #### - Define raw data headers
606
+ #### Define raw data headers
437
607
  column_names = ["TO_PARSE"]
438
608
 
439
609
  ##------------------------------------------------------------------------.
@@ -481,11 +651,19 @@ def reader(
481
651
  )
482
652
  ##------------------------------------------------------------------------.
483
653
  #### Adapt the dataframe to adhere to DISDRODB L0 standards
654
+ # Read LPM raw data
484
655
  filename = os.path.basename(filepath)
485
656
  if filename.startswith("3_"):
486
- return parse_format_v3(df)
487
- if filename.startswith("2_"):
488
- return parse_format_v2(df)
489
- if filename.startswith("1_"):
490
- return parse_format_v1(df)
491
- raise ValueError(f"Not implemented parser for DWD {filepath} data format.")
657
+ df = parse_format_v3(df)
658
+ elif filename.startswith("2_"):
659
+ df = parse_format_v2(df)
660
+ elif filename.startswith("1_"):
661
+ df = parse_format_v1(df)
662
+ else:
663
+ raise ValueError(f"Not implemented parser for DWD {filepath} data format.")
664
+
665
+ # Add SYNOP data if available
666
+ df = add_synop_information(df=df, filepath=filepath, logger=logger)
667
+
668
+ # Return dataframe
669
+ return df