meteostat 1.7.6__py3-none-any.whl → 2.0.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 (94) hide show
  1. meteostat/__init__.py +38 -19
  2. meteostat/api/config.py +158 -0
  3. meteostat/api/daily.py +76 -0
  4. meteostat/api/hourly.py +80 -0
  5. meteostat/api/interpolate.py +378 -0
  6. meteostat/api/inventory.py +59 -0
  7. meteostat/api/merge.py +103 -0
  8. meteostat/api/monthly.py +73 -0
  9. meteostat/api/normals.py +144 -0
  10. meteostat/api/point.py +30 -0
  11. meteostat/api/stations.py +234 -0
  12. meteostat/api/timeseries.py +334 -0
  13. meteostat/core/cache.py +212 -59
  14. meteostat/core/data.py +203 -0
  15. meteostat/core/logger.py +9 -0
  16. meteostat/core/network.py +82 -0
  17. meteostat/core/parameters.py +112 -0
  18. meteostat/core/providers.py +184 -0
  19. meteostat/core/schema.py +170 -0
  20. meteostat/core/validator.py +38 -0
  21. meteostat/enumerations.py +149 -0
  22. meteostat/interpolation/idw.py +120 -0
  23. meteostat/interpolation/lapserate.py +91 -0
  24. meteostat/interpolation/nearest.py +31 -0
  25. meteostat/parameters.py +354 -0
  26. meteostat/providers/dwd/climat.py +166 -0
  27. meteostat/providers/dwd/daily.py +144 -0
  28. meteostat/providers/dwd/hourly.py +218 -0
  29. meteostat/providers/dwd/monthly.py +138 -0
  30. meteostat/providers/dwd/mosmix.py +351 -0
  31. meteostat/providers/dwd/poi.py +117 -0
  32. meteostat/providers/dwd/shared.py +155 -0
  33. meteostat/providers/eccc/daily.py +87 -0
  34. meteostat/providers/eccc/hourly.py +104 -0
  35. meteostat/providers/eccc/monthly.py +66 -0
  36. meteostat/providers/eccc/shared.py +45 -0
  37. meteostat/providers/index.py +496 -0
  38. meteostat/providers/meteostat/daily.py +65 -0
  39. meteostat/providers/meteostat/daily_derived.py +110 -0
  40. meteostat/providers/meteostat/hourly.py +66 -0
  41. meteostat/providers/meteostat/monthly.py +45 -0
  42. meteostat/providers/meteostat/monthly_derived.py +106 -0
  43. meteostat/providers/meteostat/shared.py +93 -0
  44. meteostat/providers/metno/forecast.py +186 -0
  45. meteostat/providers/noaa/ghcnd.py +228 -0
  46. meteostat/providers/noaa/isd_lite.py +142 -0
  47. meteostat/providers/noaa/metar.py +163 -0
  48. meteostat/typing.py +113 -0
  49. meteostat/utils/conversions.py +231 -0
  50. meteostat/utils/data.py +194 -0
  51. meteostat/utils/geo.py +28 -0
  52. meteostat/utils/guards.py +51 -0
  53. meteostat/utils/parsers.py +161 -0
  54. meteostat/utils/types.py +113 -0
  55. meteostat/utils/validators.py +31 -0
  56. meteostat-2.0.1.dist-info/METADATA +130 -0
  57. meteostat-2.0.1.dist-info/RECORD +64 -0
  58. {meteostat-1.7.6.dist-info → meteostat-2.0.1.dist-info}/WHEEL +1 -2
  59. meteostat/core/loader.py +0 -103
  60. meteostat/core/warn.py +0 -34
  61. meteostat/enumerations/granularity.py +0 -22
  62. meteostat/interface/base.py +0 -39
  63. meteostat/interface/daily.py +0 -118
  64. meteostat/interface/hourly.py +0 -154
  65. meteostat/interface/meteodata.py +0 -210
  66. meteostat/interface/monthly.py +0 -109
  67. meteostat/interface/normals.py +0 -245
  68. meteostat/interface/point.py +0 -143
  69. meteostat/interface/stations.py +0 -252
  70. meteostat/interface/timeseries.py +0 -237
  71. meteostat/series/aggregate.py +0 -48
  72. meteostat/series/convert.py +0 -28
  73. meteostat/series/count.py +0 -17
  74. meteostat/series/coverage.py +0 -20
  75. meteostat/series/fetch.py +0 -28
  76. meteostat/series/interpolate.py +0 -47
  77. meteostat/series/normalize.py +0 -76
  78. meteostat/series/stations.py +0 -22
  79. meteostat/units.py +0 -149
  80. meteostat/utilities/__init__.py +0 -0
  81. meteostat/utilities/aggregations.py +0 -37
  82. meteostat/utilities/endpoint.py +0 -33
  83. meteostat/utilities/helpers.py +0 -70
  84. meteostat/utilities/mutations.py +0 -89
  85. meteostat/utilities/validations.py +0 -30
  86. meteostat-1.7.6.dist-info/METADATA +0 -112
  87. meteostat-1.7.6.dist-info/RECORD +0 -39
  88. meteostat-1.7.6.dist-info/top_level.txt +0 -1
  89. /meteostat/{core → api}/__init__.py +0 -0
  90. /meteostat/{enumerations → interpolation}/__init__.py +0 -0
  91. /meteostat/{interface → providers}/__init__.py +0 -0
  92. /meteostat/{interface/interpolate.py → py.typed} +0 -0
  93. /meteostat/{series → utils}/__init__.py +0 -0
  94. {meteostat-1.7.6.dist-info → meteostat-2.0.1.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,496 @@
1
+ """
2
+ Provider Index
3
+
4
+ This module contains a list of all available data providers.
5
+ """
6
+
7
+ from datetime import date, timedelta
8
+
9
+ from meteostat.typing import License, ProviderSpec
10
+ from meteostat.enumerations import Grade, Granularity, Parameter, Provider, Priority
11
+
12
+ PROVIDER_HOURLY = ProviderSpec(
13
+ id=Provider.HOURLY,
14
+ name="Meteostat Hourly",
15
+ granularity=Granularity.HOURLY,
16
+ priority=Priority.NONE,
17
+ grade=None,
18
+ license=None,
19
+ requires=["id"],
20
+ parameters=[
21
+ Parameter.TEMP,
22
+ Parameter.RHUM,
23
+ Parameter.PRCP,
24
+ Parameter.SNWD,
25
+ Parameter.WDIR,
26
+ Parameter.WSPD,
27
+ Parameter.WPGT,
28
+ Parameter.PRES,
29
+ Parameter.TSUN,
30
+ Parameter.CLDC,
31
+ Parameter.COCO,
32
+ ],
33
+ start=date(1931, 1, 1),
34
+ module="meteostat.providers.meteostat.hourly",
35
+ )
36
+
37
+ PROVIDER_DAILY = ProviderSpec(
38
+ id=Provider.DAILY,
39
+ name="Meteostat Daily",
40
+ granularity=Granularity.DAILY,
41
+ priority=Priority.NONE,
42
+ grade=None,
43
+ license=None,
44
+ requires=["id"],
45
+ parameters=[
46
+ Parameter.TEMP,
47
+ Parameter.TMIN,
48
+ Parameter.TMAX,
49
+ Parameter.RHUM,
50
+ Parameter.PRCP,
51
+ Parameter.SNWD,
52
+ Parameter.WSPD,
53
+ Parameter.WPGT,
54
+ Parameter.PRES,
55
+ Parameter.TSUN,
56
+ Parameter.CLDC,
57
+ ],
58
+ start=date(1899, 1, 1),
59
+ module="meteostat.providers.meteostat.daily",
60
+ )
61
+
62
+ PROVIDER_DAILY_DERIVED = ProviderSpec(
63
+ id=Provider.DAILY_DERIVED,
64
+ name="Meteostat Daily Derived",
65
+ granularity=Granularity.DAILY,
66
+ priority=Priority.NONE,
67
+ grade=None,
68
+ license=None,
69
+ requires=["id"],
70
+ parameters=[
71
+ Parameter.TEMP,
72
+ Parameter.TMIN,
73
+ Parameter.TMAX,
74
+ Parameter.PRCP,
75
+ Parameter.SNOW,
76
+ Parameter.WSPD,
77
+ Parameter.WDIR,
78
+ Parameter.WPGT,
79
+ Parameter.PRES,
80
+ Parameter.TSUN,
81
+ Parameter.CLDC,
82
+ ],
83
+ start=date(1931, 1, 1),
84
+ module="meteostat.providers.meteostat.daily_derived",
85
+ )
86
+
87
+ PROVIDER_MONTHLY = ProviderSpec(
88
+ id=Provider.MONTHLY,
89
+ name="Meteostat Monthly",
90
+ granularity=Granularity.MONTHLY,
91
+ priority=Priority.NONE,
92
+ grade=None,
93
+ license=None,
94
+ requires=["id"],
95
+ parameters=[
96
+ Parameter.TEMP,
97
+ Parameter.TMIN,
98
+ Parameter.TMAX,
99
+ Parameter.PRCP,
100
+ Parameter.PRES,
101
+ Parameter.TSUN,
102
+ ],
103
+ start=date(1899, 1, 1),
104
+ module="meteostat.providers.meteostat.monthly",
105
+ )
106
+
107
+ PROVIDER_MONTHLY_DERIVED = ProviderSpec(
108
+ id=Provider.MONTHLY_DERIVED,
109
+ name="Meteostat Monthly Derived",
110
+ granularity=Granularity.MONTHLY,
111
+ priority=Priority.NONE,
112
+ grade=None,
113
+ license=None,
114
+ requires=["id"],
115
+ parameters=[
116
+ Parameter.TEMP,
117
+ Parameter.TMIN,
118
+ Parameter.TMAX,
119
+ Parameter.PRCP,
120
+ Parameter.PRES,
121
+ Parameter.TSUN,
122
+ ],
123
+ start=date(1899, 1, 1),
124
+ module="meteostat.providers.meteostat.monthly_derived",
125
+ )
126
+
127
+ PROVIDER_DWD_HOURLY = ProviderSpec(
128
+ id=Provider.DWD_HOURLY,
129
+ name="DWD Hourly",
130
+ granularity=Granularity.HOURLY,
131
+ priority=Priority.HIGHEST,
132
+ grade=Grade.RECORD,
133
+ license=License(
134
+ commercial=True,
135
+ attribution="Deutscher Wetterdienst",
136
+ name="CC BY 4.0",
137
+ url="https://creativecommons.org/licenses/by/4.0/",
138
+ ),
139
+ requires=["identifiers"],
140
+ countries=["DE"],
141
+ parameters=[
142
+ Parameter.TEMP,
143
+ Parameter.RHUM,
144
+ Parameter.PRCP,
145
+ Parameter.WDIR,
146
+ Parameter.WSPD,
147
+ Parameter.PRES,
148
+ Parameter.TSUN,
149
+ Parameter.VSBY,
150
+ Parameter.COCO,
151
+ ],
152
+ start=date(1939, 1, 1),
153
+ module="meteostat.providers.dwd.hourly",
154
+ )
155
+
156
+ PROVIDER_DWD_POI = ProviderSpec(
157
+ id=Provider.DWD_POI,
158
+ name="DWD POI",
159
+ granularity=Granularity.HOURLY,
160
+ priority=Priority.MEDIUM,
161
+ grade=Grade.OBSERVATION,
162
+ license=License(
163
+ commercial=True,
164
+ attribution="Deutscher Wetterdienst",
165
+ name="CC BY 4.0",
166
+ url="https://creativecommons.org/licenses/by/4.0/",
167
+ ),
168
+ requires=["identifiers"],
169
+ parameters=[
170
+ Parameter.CLDC,
171
+ Parameter.TEMP,
172
+ Parameter.VSBY,
173
+ Parameter.WSPD,
174
+ Parameter.WPGT,
175
+ Parameter.PRCP,
176
+ Parameter.RHUM,
177
+ Parameter.WDIR,
178
+ Parameter.PRES,
179
+ Parameter.TSUN,
180
+ Parameter.COCO,
181
+ Parameter.SNWD,
182
+ ],
183
+ start=date.today() - timedelta(days=1),
184
+ module="meteostat.providers.dwd.poi",
185
+ )
186
+
187
+ PROVIDER_DWD_MOSMIX = ProviderSpec(
188
+ id=Provider.DWD_MOSMIX,
189
+ name="DWD MOSMIX",
190
+ granularity=Granularity.HOURLY,
191
+ priority=Priority.LOWEST,
192
+ grade=Grade.FORECAST,
193
+ license=License(
194
+ commercial=True,
195
+ attribution="Deutscher Wetterdienst",
196
+ name="CC BY 4.0",
197
+ url="https://creativecommons.org/licenses/by/4.0/",
198
+ ),
199
+ requires=["identifiers"],
200
+ parameters=[
201
+ Parameter.TEMP,
202
+ Parameter.RHUM,
203
+ Parameter.PRCP,
204
+ Parameter.WDIR,
205
+ Parameter.WSPD,
206
+ Parameter.WPGT,
207
+ Parameter.PRES,
208
+ Parameter.TSUN,
209
+ Parameter.CLDC,
210
+ Parameter.COCO,
211
+ ],
212
+ start=date.today(),
213
+ module="meteostat.providers.dwd.mosmix",
214
+ )
215
+
216
+ PROVIDER_DWD_DAILY = ProviderSpec(
217
+ id=Provider.DWD_DAILY,
218
+ name="DWD Daily",
219
+ granularity=Granularity.DAILY,
220
+ priority=Priority.HIGHEST,
221
+ grade=Grade.RECORD,
222
+ license=License(
223
+ commercial=True,
224
+ attribution="Deutscher Wetterdienst",
225
+ name="CC BY 4.0",
226
+ url="https://creativecommons.org/licenses/by/4.0/",
227
+ ),
228
+ requires=["identifiers"],
229
+ countries=["DE"],
230
+ parameters=[
231
+ Parameter.TEMP,
232
+ Parameter.TMIN,
233
+ Parameter.TMAX,
234
+ Parameter.RHUM,
235
+ Parameter.PRCP,
236
+ Parameter.SNWD,
237
+ Parameter.WSPD,
238
+ Parameter.WPGT,
239
+ Parameter.PRES,
240
+ Parameter.TSUN,
241
+ Parameter.CLDC,
242
+ ],
243
+ start=date(1781, 1, 1),
244
+ module="meteostat.providers.dwd.daily",
245
+ )
246
+
247
+ PROVIDER_DWD_MONTHLY = ProviderSpec(
248
+ id=Provider.DWD_MONTHLY,
249
+ name="DWD Monthly",
250
+ granularity=Granularity.MONTHLY,
251
+ priority=Priority.HIGHEST,
252
+ grade=Grade.RECORD,
253
+ license=License(
254
+ commercial=True,
255
+ attribution="Deutscher Wetterdienst",
256
+ name="CC BY 4.0",
257
+ url="https://creativecommons.org/licenses/by/4.0/",
258
+ ),
259
+ requires=["identifiers"],
260
+ countries=["DE"],
261
+ parameters=[Parameter.TEMP, Parameter.TMIN, Parameter.TMAX, Parameter.PRCP],
262
+ start=date(1851, 1, 1),
263
+ module="meteostat.providers.dwd.monthly",
264
+ )
265
+
266
+ PROVIDER_ECCC_HOURLY = ProviderSpec(
267
+ id=Provider.ECCC_HOURLY,
268
+ name="ECCC Hourly",
269
+ granularity=Granularity.HOURLY,
270
+ priority=Priority.HIGHEST,
271
+ grade=Grade.RECORD,
272
+ license=License(
273
+ commercial=True,
274
+ attribution="Environment and Climate Change Canada",
275
+ name="Environment and Climate Change Canada Data Servers End-use Licence",
276
+ url="https://eccc-msc.github.io/open-data/licence/readme_en/",
277
+ ),
278
+ requires=["identifiers"],
279
+ countries=["CA"],
280
+ parameters=[
281
+ Parameter.TEMP,
282
+ Parameter.RHUM,
283
+ Parameter.PRCP,
284
+ Parameter.WDIR,
285
+ Parameter.WSPD,
286
+ Parameter.VSBY,
287
+ ],
288
+ start=date(1939, 1, 1),
289
+ module="meteostat.providers.eccc.hourly",
290
+ )
291
+
292
+ PROVIDER_ECCC_DAILY = ProviderSpec(
293
+ id=Provider.ECCC_DAILY,
294
+ name="ECCC Daily",
295
+ granularity=Granularity.DAILY,
296
+ priority=Priority.HIGHEST,
297
+ grade=Grade.RECORD,
298
+ license=License(
299
+ commercial=True,
300
+ attribution="Environment and Climate Change Canada",
301
+ name="Environment and Climate Change Canada Data Servers End-use Licence",
302
+ url="https://eccc-msc.github.io/open-data/licence/readme_en/",
303
+ ),
304
+ requires=["identifiers"],
305
+ countries=["CA"],
306
+ parameters=[
307
+ Parameter.TEMP,
308
+ Parameter.TMIN,
309
+ Parameter.TMAX,
310
+ Parameter.PRCP,
311
+ Parameter.SNOW,
312
+ Parameter.SNWD,
313
+ Parameter.WPGT,
314
+ ],
315
+ start=date(1939, 1, 1),
316
+ module="meteostat.providers.eccc.daily",
317
+ )
318
+
319
+ PROVIDER_ECCC_MONTHLY = ProviderSpec(
320
+ id=Provider.ECCC_MONTHLY,
321
+ name="ECCC Monthly",
322
+ granularity=Granularity.MONTHLY,
323
+ priority=Priority.HIGHEST,
324
+ grade=Grade.RECORD,
325
+ license=License(
326
+ commercial=True,
327
+ attribution="Environment and Climate Change Canada",
328
+ name="Environment and Climate Change Canada Data Servers End-use Licence",
329
+ url="https://eccc-msc.github.io/open-data/licence/readme_en/",
330
+ ),
331
+ requires=["identifiers"],
332
+ countries=["CA"],
333
+ parameters=[
334
+ Parameter.TEMP,
335
+ Parameter.TMIN,
336
+ Parameter.TMAX,
337
+ Parameter.PRCP,
338
+ Parameter.PDAY,
339
+ Parameter.SNOW,
340
+ ],
341
+ start=date(1939, 1, 1),
342
+ module="meteostat.providers.eccc.monthly",
343
+ )
344
+
345
+ PROVIDER_ISD_LITE = ProviderSpec(
346
+ id=Provider.ISD_LITE,
347
+ name="NOAA ISD Lite",
348
+ granularity=Granularity.HOURLY,
349
+ priority=Priority.HIGH,
350
+ grade=Grade.OBSERVATION,
351
+ license=License(
352
+ commercial=True,
353
+ name="CC0 1.0 Universal",
354
+ url="https://creativecommons.org/publicdomain/zero/1.0/",
355
+ ), # source: https://registry.opendata.aws/noaa-isd/
356
+ requires=["identifiers"],
357
+ parameters=[
358
+ Parameter.TEMP,
359
+ Parameter.RHUM,
360
+ Parameter.PRCP,
361
+ Parameter.WDIR,
362
+ Parameter.WSPD,
363
+ Parameter.WPGT,
364
+ Parameter.PRES,
365
+ Parameter.CLDC,
366
+ ],
367
+ start=date(1931, 1, 1),
368
+ module="meteostat.providers.noaa.isd_lite",
369
+ )
370
+
371
+ PROVIDER_GHCND = ProviderSpec(
372
+ id=Provider.GHCND,
373
+ name="NOAA GHCN-Daily",
374
+ granularity=Granularity.DAILY,
375
+ priority=Priority.HIGH,
376
+ grade=Grade.OBSERVATION,
377
+ license=License(
378
+ commercial=True,
379
+ name="CC0 1.0 Universal",
380
+ url="https://creativecommons.org/publicdomain/zero/1.0/",
381
+ ), # source: https://registry.opendata.aws/noaa-ghcn/
382
+ requires=["identifiers"],
383
+ parameters=[
384
+ Parameter.TEMP,
385
+ Parameter.TMIN,
386
+ Parameter.TMAX,
387
+ Parameter.PRCP,
388
+ Parameter.SNOW,
389
+ Parameter.WSPD,
390
+ Parameter.WDIR,
391
+ Parameter.WPGT,
392
+ Parameter.TSUN,
393
+ Parameter.CLDC,
394
+ ],
395
+ start=date(1931, 1, 1),
396
+ module="meteostat.providers.noaa.ghcnd",
397
+ )
398
+
399
+ PROVIDER_CLIMAT = ProviderSpec(
400
+ id=Provider.CLIMAT,
401
+ name="DWD CLIMAT",
402
+ granularity=Granularity.MONTHLY,
403
+ priority=Priority.HIGH,
404
+ grade=Grade.RECORD,
405
+ license=License(
406
+ commercial=True,
407
+ attribution="Deutscher Wetterdienst",
408
+ name="CC BY 4.0",
409
+ url="https://creativecommons.org/licenses/by/4.0/",
410
+ ),
411
+ requires=["identifiers"],
412
+ parameters=[
413
+ Parameter.TEMP,
414
+ Parameter.TMIN,
415
+ Parameter.TMAX,
416
+ Parameter.TXMN,
417
+ Parameter.TXMX,
418
+ Parameter.PRES,
419
+ Parameter.PRCP,
420
+ Parameter.TSUN,
421
+ ],
422
+ start=date(1875, 6, 1),
423
+ module="meteostat.providers.dwd.climat",
424
+ )
425
+
426
+ PROVIDER_METAR = ProviderSpec(
427
+ id=Provider.METAR,
428
+ name="METAR",
429
+ granularity=Granularity.HOURLY,
430
+ priority=Priority.LOW,
431
+ grade=Grade.OBSERVATION,
432
+ license=License(
433
+ commercial=True,
434
+ ),
435
+ requires=["identifiers"],
436
+ parameters=[
437
+ Parameter.TEMP,
438
+ Parameter.RHUM,
439
+ Parameter.WDIR,
440
+ Parameter.WSPD,
441
+ Parameter.PRES,
442
+ Parameter.COCO,
443
+ ],
444
+ start=date.today() - timedelta(days=1),
445
+ module="meteostat.providers.noaa.metar",
446
+ )
447
+
448
+ PROVIDER_METNO_FORECAST = ProviderSpec(
449
+ id=Provider.METNO_FORECAST,
450
+ name="MET Norway Forecast",
451
+ granularity=Granularity.HOURLY,
452
+ priority=Priority.LOWEST - 1, # MOSMIX is more specific, therefore higher prio
453
+ grade=Grade.FORECAST,
454
+ license=License(
455
+ commercial=True,
456
+ attribution="MET Norway",
457
+ name="NLOD 2.0",
458
+ url="https://data.norge.no/nlod/en/2.0",
459
+ ),
460
+ requires=["location"],
461
+ parameters=[
462
+ Parameter.TEMP,
463
+ Parameter.RHUM,
464
+ Parameter.PRCP,
465
+ Parameter.WDIR,
466
+ Parameter.WSPD,
467
+ Parameter.WPGT,
468
+ Parameter.PRES,
469
+ Parameter.CLDC,
470
+ Parameter.COCO,
471
+ ],
472
+ start=date.today(),
473
+ module="meteostat.providers.metno.forecast",
474
+ )
475
+
476
+
477
+ DEFAULT_PROVIDERS = [
478
+ PROVIDER_HOURLY,
479
+ PROVIDER_DAILY,
480
+ PROVIDER_DAILY_DERIVED,
481
+ PROVIDER_MONTHLY,
482
+ PROVIDER_MONTHLY_DERIVED,
483
+ PROVIDER_DWD_HOURLY,
484
+ PROVIDER_DWD_POI,
485
+ PROVIDER_DWD_MOSMIX,
486
+ PROVIDER_DWD_DAILY,
487
+ PROVIDER_DWD_MONTHLY,
488
+ PROVIDER_ECCC_HOURLY,
489
+ PROVIDER_ECCC_DAILY,
490
+ PROVIDER_ECCC_MONTHLY,
491
+ PROVIDER_ISD_LITE,
492
+ PROVIDER_GHCND,
493
+ PROVIDER_CLIMAT,
494
+ PROVIDER_METAR,
495
+ PROVIDER_METNO_FORECAST,
496
+ ]
@@ -0,0 +1,65 @@
1
+ """
2
+ The code is licensed under the MIT license.
3
+ """
4
+
5
+ from datetime import datetime
6
+ from typing import Optional
7
+
8
+ import pandas as pd
9
+
10
+ from meteostat.providers.meteostat.shared import filter_model_data, handle_exceptions
11
+ from meteostat.typing import ProviderRequest
12
+ from meteostat.core.cache import cache_service
13
+ from meteostat.api.config import config
14
+ from meteostat.utils.data import reshape_by_source
15
+
16
+ ENDPOINT = config.daily_endpoint
17
+
18
+
19
+ def get_ttl(_station: str, year: int) -> int:
20
+ """
21
+ Get TTL based on year
22
+
23
+ Current + previous year = one day
24
+ Else = 30 days
25
+ """
26
+ current_year = datetime.now().year
27
+ return 60 * 60 * 24 if current_year - year < 2 else 60 * 60 * 24 * 30
28
+
29
+
30
+ @cache_service.cache(get_ttl, "pickle")
31
+ @handle_exceptions
32
+ def get_df(station: str, year: int) -> Optional[pd.DataFrame]:
33
+ """
34
+ Get CSV file from Meteostat and convert to DataFrame
35
+ """
36
+ file_url = ENDPOINT.format(station=station, year=str(year))
37
+
38
+ df = pd.read_csv(file_url, sep=",", compression="gzip")
39
+
40
+ time_cols = df.columns[0:3]
41
+ df["time"] = pd.to_datetime(df[time_cols])
42
+ df = df.drop(time_cols, axis=1).set_index("time")
43
+
44
+ return reshape_by_source(df)
45
+
46
+
47
+ @filter_model_data
48
+ def fetch(req: ProviderRequest) -> Optional[pd.DataFrame]:
49
+ """
50
+ Fetch daily weather data from Meteostat's central data repository
51
+ """
52
+ if req.start is None or req.end is None:
53
+ return None
54
+
55
+ # Get a list of relevant years
56
+ years = range(req.start.year, req.end.year + 1)
57
+ # Get list of annual DataFrames
58
+ df_yearly = [get_df(req.station.id, year) for year in years]
59
+ # Concatenate into a single DataFrame
60
+ df = (
61
+ pd.concat(df_yearly)
62
+ if len(df_yearly) and not all(d is None for d in df_yearly)
63
+ else None
64
+ )
65
+ return df
@@ -0,0 +1,110 @@
1
+ from typing import Optional
2
+
3
+ import numpy as np
4
+ import pandas as pd
5
+
6
+ from meteostat.enumerations import Parameter, Provider
7
+ from meteostat.api.hourly import hourly
8
+ from meteostat.typing import ProviderRequest
9
+ from meteostat.utils.data import aggregate_sources, reshape_by_source
10
+
11
+
12
+ def daily_mean(group: pd.Series):
13
+ """
14
+ Calculate the daily mean from a series of hourly data
15
+ """
16
+ if group.isna().sum() > 3:
17
+ return np.nan
18
+ return group.interpolate(axis=0).mean()
19
+
20
+
21
+ def daily_min(group: pd.Series):
22
+ """
23
+ Calculate the daily minimum from a series of hourly data
24
+ """
25
+ if group.isna().sum() > 0:
26
+ return np.nan
27
+ return group.min()
28
+
29
+
30
+ def daily_max(group: pd.Series):
31
+ """
32
+ Calculate the daily maximum from a series of hourly data
33
+ """
34
+ if group.isna().sum() > 0:
35
+ return np.nan
36
+ return group.max()
37
+
38
+
39
+ def daily_sum(group: pd.Series):
40
+ """
41
+ Calculate the daily sum from a series of hourly data
42
+ """
43
+ if group.isna().sum() > 0:
44
+ return np.nan
45
+ return group.sum()
46
+
47
+
48
+ # Available parameters with source column and aggregation method
49
+ PARAMETER_AGGS = {
50
+ Parameter.TEMP: (Parameter.TEMP, daily_mean),
51
+ Parameter.TMIN: (Parameter.TEMP, daily_min),
52
+ Parameter.TMAX: (Parameter.TEMP, daily_max),
53
+ Parameter.RHUM: (Parameter.RHUM, daily_mean),
54
+ Parameter.DWPT: (Parameter.DWPT, daily_mean),
55
+ Parameter.PRCP: (Parameter.PRCP, daily_sum),
56
+ Parameter.SNWD: (Parameter.SNWD, daily_max),
57
+ Parameter.WSPD: (Parameter.WSPD, daily_mean),
58
+ Parameter.WPGT: (Parameter.WPGT, daily_max),
59
+ Parameter.PRES: (Parameter.PRES, daily_mean),
60
+ Parameter.TSUN: (Parameter.TSUN, daily_sum),
61
+ Parameter.CLDC: (Parameter.CLDC, daily_mean),
62
+ }
63
+
64
+
65
+ def fetch(req: ProviderRequest) -> Optional[pd.DataFrame]:
66
+ """
67
+ Fetch hourly weather data from Meteostat's central data
68
+ repository and aggregate to daily granularity
69
+ """
70
+ # Get all source columns
71
+ source_cols = list(dict.fromkeys([PARAMETER_AGGS[p][0] for p in req.parameters]))
72
+
73
+ # Get hourly DataFrame
74
+ ts_hourly = hourly(
75
+ req.station.id,
76
+ req.start,
77
+ req.end,
78
+ parameters=source_cols,
79
+ providers=[Provider.HOURLY],
80
+ timezone=req.station.timezone,
81
+ )
82
+
83
+ df_hourly = ts_hourly.fetch(fill=True, sources=True)
84
+
85
+ # If no hourly data is available, exit
86
+ if df_hourly is None:
87
+ return None
88
+
89
+ # Create daily aggregations
90
+ df = pd.DataFrame()
91
+ for parameter in req.parameters:
92
+ [hourly_param_name, agg_func] = PARAMETER_AGGS[parameter]
93
+ df[parameter] = (
94
+ df_hourly[hourly_param_name]
95
+ .groupby(pd.Grouper(level="time", freq="1D"))
96
+ .agg(agg_func)
97
+ )
98
+ df[f"{parameter}_source"] = (
99
+ df_hourly[f"{hourly_param_name}_source"]
100
+ .groupby(pd.Grouper(level="time", freq="1D"))
101
+ .agg(aggregate_sources)
102
+ )
103
+
104
+ # Adjust DataFrame and add index
105
+ df = df.round(1)
106
+ df.index = pd.to_datetime(df.index.astype("datetime64").dt.date) # type: ignore[union-attr]
107
+ df.index.name = "time"
108
+
109
+ # Return reshaped DataFrame
110
+ return reshape_by_source(df)