meteostat 1.7.6__tar.gz → 2.0.0__tar.gz

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 (101) hide show
  1. meteostat-2.0.0/PKG-INFO +134 -0
  2. meteostat-2.0.0/README.md +116 -0
  3. meteostat-2.0.0/meteostat/__init__.py +48 -0
  4. meteostat-2.0.0/meteostat/api/daily.py +76 -0
  5. meteostat-2.0.0/meteostat/api/hourly.py +80 -0
  6. meteostat-2.0.0/meteostat/api/interpolate.py +240 -0
  7. meteostat-2.0.0/meteostat/api/inventory.py +59 -0
  8. meteostat-2.0.0/meteostat/api/merge.py +103 -0
  9. meteostat-2.0.0/meteostat/api/monthly.py +73 -0
  10. meteostat-2.0.0/meteostat/api/normals.py +144 -0
  11. meteostat-2.0.0/meteostat/api/point.py +30 -0
  12. meteostat-2.0.0/meteostat/api/stations.py +234 -0
  13. meteostat-2.0.0/meteostat/api/timeseries.py +334 -0
  14. meteostat-2.0.0/meteostat/core/cache.py +224 -0
  15. meteostat-2.0.0/meteostat/core/config.py +158 -0
  16. meteostat-2.0.0/meteostat/core/data.py +199 -0
  17. meteostat-2.0.0/meteostat/core/logger.py +9 -0
  18. meteostat-2.0.0/meteostat/core/network.py +82 -0
  19. meteostat-2.0.0/meteostat/core/parameters.py +112 -0
  20. meteostat-2.0.0/meteostat/core/providers.py +184 -0
  21. meteostat-2.0.0/meteostat/core/schema.py +170 -0
  22. meteostat-2.0.0/meteostat/core/validator.py +38 -0
  23. meteostat-2.0.0/meteostat/enumerations.py +149 -0
  24. meteostat-2.0.0/meteostat/interpolation/idw.py +120 -0
  25. meteostat-2.0.0/meteostat/interpolation/lapserate.py +91 -0
  26. meteostat-2.0.0/meteostat/interpolation/nearest.py +31 -0
  27. meteostat-2.0.0/meteostat/parameters.py +354 -0
  28. meteostat-2.0.0/meteostat/providers/dwd/climat.py +166 -0
  29. meteostat-2.0.0/meteostat/providers/dwd/daily.py +144 -0
  30. meteostat-2.0.0/meteostat/providers/dwd/hourly.py +218 -0
  31. meteostat-2.0.0/meteostat/providers/dwd/monthly.py +138 -0
  32. meteostat-2.0.0/meteostat/providers/dwd/mosmix.py +351 -0
  33. meteostat-2.0.0/meteostat/providers/dwd/poi.py +117 -0
  34. meteostat-2.0.0/meteostat/providers/dwd/shared.py +155 -0
  35. meteostat-2.0.0/meteostat/providers/eccc/daily.py +87 -0
  36. meteostat-2.0.0/meteostat/providers/eccc/hourly.py +104 -0
  37. meteostat-2.0.0/meteostat/providers/eccc/monthly.py +66 -0
  38. meteostat-2.0.0/meteostat/providers/eccc/shared.py +45 -0
  39. meteostat-2.0.0/meteostat/providers/index.py +496 -0
  40. meteostat-2.0.0/meteostat/providers/meteostat/daily.py +65 -0
  41. meteostat-2.0.0/meteostat/providers/meteostat/daily_derived.py +110 -0
  42. meteostat-2.0.0/meteostat/providers/meteostat/hourly.py +66 -0
  43. meteostat-2.0.0/meteostat/providers/meteostat/monthly.py +45 -0
  44. meteostat-2.0.0/meteostat/providers/meteostat/monthly_derived.py +106 -0
  45. meteostat-2.0.0/meteostat/providers/meteostat/shared.py +93 -0
  46. meteostat-2.0.0/meteostat/providers/metno/forecast.py +186 -0
  47. meteostat-2.0.0/meteostat/providers/noaa/ghcnd.py +228 -0
  48. meteostat-2.0.0/meteostat/providers/noaa/isd_lite.py +142 -0
  49. meteostat-2.0.0/meteostat/providers/noaa/metar.py +163 -0
  50. meteostat-2.0.0/meteostat/typing.py +113 -0
  51. meteostat-2.0.0/meteostat/utils/conversions.py +231 -0
  52. meteostat-2.0.0/meteostat/utils/data.py +194 -0
  53. meteostat-2.0.0/meteostat/utils/geo.py +28 -0
  54. meteostat-2.0.0/meteostat/utils/parsers.py +168 -0
  55. meteostat-2.0.0/meteostat/utils/types.py +113 -0
  56. meteostat-2.0.0/meteostat/utils/validators.py +31 -0
  57. meteostat-2.0.0/pyproject.toml +29 -0
  58. meteostat-1.7.6/PKG-INFO +0 -109
  59. meteostat-1.7.6/README.md +0 -89
  60. meteostat-1.7.6/meteostat/__init__.py +0 -35
  61. meteostat-1.7.6/meteostat/core/cache.py +0 -71
  62. meteostat-1.7.6/meteostat/core/loader.py +0 -103
  63. meteostat-1.7.6/meteostat/core/warn.py +0 -34
  64. meteostat-1.7.6/meteostat/enumerations/granularity.py +0 -22
  65. meteostat-1.7.6/meteostat/interface/base.py +0 -39
  66. meteostat-1.7.6/meteostat/interface/daily.py +0 -118
  67. meteostat-1.7.6/meteostat/interface/hourly.py +0 -154
  68. meteostat-1.7.6/meteostat/interface/meteodata.py +0 -210
  69. meteostat-1.7.6/meteostat/interface/monthly.py +0 -109
  70. meteostat-1.7.6/meteostat/interface/normals.py +0 -245
  71. meteostat-1.7.6/meteostat/interface/point.py +0 -143
  72. meteostat-1.7.6/meteostat/interface/stations.py +0 -252
  73. meteostat-1.7.6/meteostat/interface/timeseries.py +0 -237
  74. meteostat-1.7.6/meteostat/series/aggregate.py +0 -48
  75. meteostat-1.7.6/meteostat/series/convert.py +0 -28
  76. meteostat-1.7.6/meteostat/series/count.py +0 -17
  77. meteostat-1.7.6/meteostat/series/coverage.py +0 -20
  78. meteostat-1.7.6/meteostat/series/fetch.py +0 -28
  79. meteostat-1.7.6/meteostat/series/interpolate.py +0 -47
  80. meteostat-1.7.6/meteostat/series/normalize.py +0 -76
  81. meteostat-1.7.6/meteostat/series/stations.py +0 -22
  82. meteostat-1.7.6/meteostat/units.py +0 -149
  83. meteostat-1.7.6/meteostat/utilities/__init__.py +0 -0
  84. meteostat-1.7.6/meteostat/utilities/aggregations.py +0 -37
  85. meteostat-1.7.6/meteostat/utilities/endpoint.py +0 -33
  86. meteostat-1.7.6/meteostat/utilities/helpers.py +0 -70
  87. meteostat-1.7.6/meteostat/utilities/mutations.py +0 -89
  88. meteostat-1.7.6/meteostat/utilities/validations.py +0 -30
  89. meteostat-1.7.6/meteostat.egg-info/PKG-INFO +0 -109
  90. meteostat-1.7.6/meteostat.egg-info/SOURCES.txt +0 -42
  91. meteostat-1.7.6/meteostat.egg-info/dependency_links.txt +0 -1
  92. meteostat-1.7.6/meteostat.egg-info/requires.txt +0 -3
  93. meteostat-1.7.6/meteostat.egg-info/top_level.txt +0 -1
  94. meteostat-1.7.6/setup.cfg +0 -4
  95. meteostat-1.7.6/setup.py +0 -40
  96. {meteostat-1.7.6 → meteostat-2.0.0}/LICENSE +0 -0
  97. {meteostat-1.7.6/meteostat/core → meteostat-2.0.0/meteostat/api}/__init__.py +0 -0
  98. {meteostat-1.7.6/meteostat/enumerations → meteostat-2.0.0/meteostat/interpolation}/__init__.py +0 -0
  99. {meteostat-1.7.6/meteostat/interface → meteostat-2.0.0/meteostat/providers}/__init__.py +0 -0
  100. /meteostat-1.7.6/meteostat/interface/interpolate.py → /meteostat-2.0.0/meteostat/py.typed +0 -0
  101. {meteostat-1.7.6/meteostat/series → meteostat-2.0.0/meteostat/utils}/__init__.py +0 -0
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: meteostat
3
+ Version: 2.0.0
4
+ Summary: Access and analyze historical weather and climate data with Python.
5
+ License-File: LICENSE
6
+ Author: Meteostat
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Dist: pandas (>=2.3.3,<3.0.0)
14
+ Requires-Dist: pytz (>=2023.3.post1,<2024.0)
15
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
16
+ Description-Content-Type: text/markdown
17
+
18
+ <!-- PROJECT SHIELDS -->
19
+ <div align="center">
20
+
21
+ [![Contributors][contributors-shield]][contributors-url]
22
+ [![Forks][forks-shield]][forks-url]
23
+ [![Stargazers][stars-shield]][stars-url]
24
+ [![Issues][issues-shield]][issues-url]
25
+ [![Unlicense License][license-shield]][license-url]
26
+ [![LinkedIn][linkedin-shield]][linkedin-url]
27
+
28
+ </div>
29
+
30
+
31
+ <!-- PROJECT LOGO -->
32
+ <br />
33
+ <div align="center">
34
+ <a href="https://github.com/meteostat/meteostat">
35
+ <img src="https://media.meteostat.net/icon.svg" alt="Meteostat Logo" width="80" height="80">
36
+ </a>
37
+
38
+ <h3 align="center">Meteostat Python Package</h3>
39
+
40
+ <p align="center">
41
+ Access and analyze historical weather and climate data with Python.
42
+ <p>
43
+ <a href="https://dev.meteostat.net/python"><strong>Explore the docs »</strong></a>
44
+ </p>
45
+ <p>
46
+ <a href="https://meteostat.net">Visit Website</a>
47
+ &middot;
48
+ <a href="https://github.com/meteostat/meteostat/issues">Report Bug</a>
49
+ &middot;
50
+ <a href="https://github.com/orgs/meteostat/discussions">Request Feature</a>
51
+ </p>
52
+ </p>
53
+ </div>
54
+
55
+ ## 📚 Installation
56
+
57
+ The Meteostat Python package is available through [PyPI](https://pypi.org/project/meteostat/):
58
+
59
+ ```sh
60
+ pip install meteostat
61
+ ```
62
+
63
+ ## 🚀 Usage
64
+
65
+ Let's plot 2018 temperature data for Frankfurt, Germany:
66
+
67
+ ```python
68
+ from datetime import date
69
+ import matplotlib.pyplot as plt
70
+ import meteostat as ms
71
+
72
+ # Specify location and time range
73
+ POINT = ms.Point(50.1155, 8.6842, 113) # Try with your location
74
+ START = date(2018, 1, 1)
75
+ END = date(2018, 12, 31)
76
+
77
+ # Get nearby weather stations
78
+ stations = ms.stations.nearby(POINT, limit=4)
79
+
80
+ # Get daily data & perform interpolation
81
+ ts = ms.daily(stations, START, END)
82
+ df = ms.interpolate(ts, POINT).fetch()
83
+
84
+ # Plot line chart including average, minimum and maximum temperature
85
+ df.plot(y=[ms.Parameter.TEMP, ms.Parameter.TMIN, ms.Parameter.TMAX])
86
+ plt.show()
87
+ ```
88
+
89
+ Take a look at the expected output:
90
+
91
+ ![2018 temperature data for Frankfurt, Germany][product-screenshot]
92
+
93
+ ## 🤝 Contributing
94
+
95
+ Please read our [contributing guidelines](https://dev.meteostat.net/python/contributing) for details on how to contribute to the Meteostat Python library.
96
+
97
+ **Top contributors**
98
+
99
+ <a href="https://github.com/meteostat/meteostat/graphs/contributors">
100
+ <img src="https://contrib.rocks/image?repo=meteostat/meteostat" alt="Meteostat Contributors" />
101
+ </a>
102
+
103
+ ## 🌟 Featured In
104
+
105
+ Meteostat has been featured and used by various media outlets and organizations, including:
106
+
107
+ - [Towards Data Science](https://towardsdatascience.com/get-temperature-data-by-location-with-python-52ed872dd621/)
108
+ - [ZEIT ONLINE](https://www.zeit.de/digital/internet/2022-03/desinformation-russland-ukraine-fotos-fake-news-falschinformation-echtheit)
109
+ - [Deutsche Presse-Agentur (dpa)](https://dpa-factchecking.com/germany/230103-99-92282/)
110
+ - [heise online](https://www.heise.de/news/Open-Source-Projekt-zu-Klimadaten-Meteostat-Python-Library-1-0-erschienen-4985015.html)
111
+
112
+ Join the growing community of users and researchers relying on Meteostat for their weather data needs.
113
+
114
+ ## 📄 License
115
+
116
+ Meteostat is licensed under the [**MIT License**](https://github.com/meteostat/meteostat/blob/main/LICENSE). Data provided by Meteostat is generally licensed under the [**Creative Commons Attribution 4.0 International (CC BY 4.0)**](https://creativecommons.org/licenses/by/4.0) license. Please refer to the [documentation](https://dev.meteostat.net/license) for more information.
117
+
118
+
119
+ <!-- MARKDOWN LINKS & IMAGES -->
120
+ <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
121
+ [contributors-shield]: https://img.shields.io/github/contributors/meteostat/meteostat.svg?style=for-the-badge
122
+ [contributors-url]: https://github.com/meteostat/meteostat/graphs/contributors
123
+ [forks-shield]: https://img.shields.io/github/forks/meteostat/meteostat.svg?style=for-the-badge
124
+ [forks-url]: https://github.com/meteostat/meteostat/network/members
125
+ [stars-shield]: https://img.shields.io/github/stars/meteostat/meteostat.svg?style=for-the-badge
126
+ [stars-url]: https://github.com/meteostat/meteostat/stargazers
127
+ [issues-shield]: https://img.shields.io/github/issues/meteostat/meteostat.svg?style=for-the-badge
128
+ [issues-url]: https://github.com/meteostat/meteostat/issues
129
+ [license-shield]: https://img.shields.io/github/license/meteostat/meteostat.svg?style=for-the-badge
130
+ [license-url]: https://github.com/meteostat/meteostat/blob/main/LICENSE
131
+ [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
132
+ [linkedin-url]: https://www.linkedin.com/company/meteostat
133
+ [product-screenshot]: https://dev.meteostat.net/assets/images/example-8b6cf2a3fe2efa285bc72d7dc72c4865.png
134
+
@@ -0,0 +1,116 @@
1
+ <!-- PROJECT SHIELDS -->
2
+ <div align="center">
3
+
4
+ [![Contributors][contributors-shield]][contributors-url]
5
+ [![Forks][forks-shield]][forks-url]
6
+ [![Stargazers][stars-shield]][stars-url]
7
+ [![Issues][issues-shield]][issues-url]
8
+ [![Unlicense License][license-shield]][license-url]
9
+ [![LinkedIn][linkedin-shield]][linkedin-url]
10
+
11
+ </div>
12
+
13
+
14
+ <!-- PROJECT LOGO -->
15
+ <br />
16
+ <div align="center">
17
+ <a href="https://github.com/meteostat/meteostat">
18
+ <img src="https://media.meteostat.net/icon.svg" alt="Meteostat Logo" width="80" height="80">
19
+ </a>
20
+
21
+ <h3 align="center">Meteostat Python Package</h3>
22
+
23
+ <p align="center">
24
+ Access and analyze historical weather and climate data with Python.
25
+ <p>
26
+ <a href="https://dev.meteostat.net/python"><strong>Explore the docs »</strong></a>
27
+ </p>
28
+ <p>
29
+ <a href="https://meteostat.net">Visit Website</a>
30
+ &middot;
31
+ <a href="https://github.com/meteostat/meteostat/issues">Report Bug</a>
32
+ &middot;
33
+ <a href="https://github.com/orgs/meteostat/discussions">Request Feature</a>
34
+ </p>
35
+ </p>
36
+ </div>
37
+
38
+ ## 📚 Installation
39
+
40
+ The Meteostat Python package is available through [PyPI](https://pypi.org/project/meteostat/):
41
+
42
+ ```sh
43
+ pip install meteostat
44
+ ```
45
+
46
+ ## 🚀 Usage
47
+
48
+ Let's plot 2018 temperature data for Frankfurt, Germany:
49
+
50
+ ```python
51
+ from datetime import date
52
+ import matplotlib.pyplot as plt
53
+ import meteostat as ms
54
+
55
+ # Specify location and time range
56
+ POINT = ms.Point(50.1155, 8.6842, 113) # Try with your location
57
+ START = date(2018, 1, 1)
58
+ END = date(2018, 12, 31)
59
+
60
+ # Get nearby weather stations
61
+ stations = ms.stations.nearby(POINT, limit=4)
62
+
63
+ # Get daily data & perform interpolation
64
+ ts = ms.daily(stations, START, END)
65
+ df = ms.interpolate(ts, POINT).fetch()
66
+
67
+ # Plot line chart including average, minimum and maximum temperature
68
+ df.plot(y=[ms.Parameter.TEMP, ms.Parameter.TMIN, ms.Parameter.TMAX])
69
+ plt.show()
70
+ ```
71
+
72
+ Take a look at the expected output:
73
+
74
+ ![2018 temperature data for Frankfurt, Germany][product-screenshot]
75
+
76
+ ## 🤝 Contributing
77
+
78
+ Please read our [contributing guidelines](https://dev.meteostat.net/python/contributing) for details on how to contribute to the Meteostat Python library.
79
+
80
+ **Top contributors**
81
+
82
+ <a href="https://github.com/meteostat/meteostat/graphs/contributors">
83
+ <img src="https://contrib.rocks/image?repo=meteostat/meteostat" alt="Meteostat Contributors" />
84
+ </a>
85
+
86
+ ## 🌟 Featured In
87
+
88
+ Meteostat has been featured and used by various media outlets and organizations, including:
89
+
90
+ - [Towards Data Science](https://towardsdatascience.com/get-temperature-data-by-location-with-python-52ed872dd621/)
91
+ - [ZEIT ONLINE](https://www.zeit.de/digital/internet/2022-03/desinformation-russland-ukraine-fotos-fake-news-falschinformation-echtheit)
92
+ - [Deutsche Presse-Agentur (dpa)](https://dpa-factchecking.com/germany/230103-99-92282/)
93
+ - [heise online](https://www.heise.de/news/Open-Source-Projekt-zu-Klimadaten-Meteostat-Python-Library-1-0-erschienen-4985015.html)
94
+
95
+ Join the growing community of users and researchers relying on Meteostat for their weather data needs.
96
+
97
+ ## 📄 License
98
+
99
+ Meteostat is licensed under the [**MIT License**](https://github.com/meteostat/meteostat/blob/main/LICENSE). Data provided by Meteostat is generally licensed under the [**Creative Commons Attribution 4.0 International (CC BY 4.0)**](https://creativecommons.org/licenses/by/4.0) license. Please refer to the [documentation](https://dev.meteostat.net/license) for more information.
100
+
101
+
102
+ <!-- MARKDOWN LINKS & IMAGES -->
103
+ <!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
104
+ [contributors-shield]: https://img.shields.io/github/contributors/meteostat/meteostat.svg?style=for-the-badge
105
+ [contributors-url]: https://github.com/meteostat/meteostat/graphs/contributors
106
+ [forks-shield]: https://img.shields.io/github/forks/meteostat/meteostat.svg?style=for-the-badge
107
+ [forks-url]: https://github.com/meteostat/meteostat/network/members
108
+ [stars-shield]: https://img.shields.io/github/stars/meteostat/meteostat.svg?style=for-the-badge
109
+ [stars-url]: https://github.com/meteostat/meteostat/stargazers
110
+ [issues-shield]: https://img.shields.io/github/issues/meteostat/meteostat.svg?style=for-the-badge
111
+ [issues-url]: https://github.com/meteostat/meteostat/issues
112
+ [license-shield]: https://img.shields.io/github/license/meteostat/meteostat.svg?style=for-the-badge
113
+ [license-url]: https://github.com/meteostat/meteostat/blob/main/LICENSE
114
+ [linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
115
+ [linkedin-url]: https://www.linkedin.com/company/meteostat
116
+ [product-screenshot]: https://dev.meteostat.net/assets/images/example-8b6cf2a3fe2efa285bc72d7dc72c4865.png
@@ -0,0 +1,48 @@
1
+ """
2
+ █▀▄▀█ █▀▀ ▀█▀ █▀▀ █▀█ █▀ ▀█▀ ▄▀█ ▀█▀
3
+ █░▀░█ ██▄ ░█░ ██▄ █▄█ ▄█ ░█░ █▀█ ░█░
4
+
5
+ A Python library for accessing open weather and climate data.
6
+
7
+ Meteorological data provided by Meteostat (https://dev.meteostat.net)
8
+ under the terms of the Creative Commons Attribution 4.0 International
9
+ License.
10
+
11
+ The code is licensed under the MIT license.
12
+ """
13
+
14
+ __appname__ = "meteostat"
15
+ __version__ = "2.0.0"
16
+
17
+ from meteostat.api.daily import daily
18
+ from meteostat.api.hourly import hourly
19
+ from meteostat.api.interpolate import interpolate
20
+ from meteostat.api.merge import merge
21
+ from meteostat.api.monthly import monthly
22
+ from meteostat.api.normals import normals
23
+ from meteostat.api.point import Point
24
+ from meteostat.api.stations import stations
25
+ from meteostat.core.cache import purge
26
+ from meteostat.core.config import config
27
+ from meteostat.enumerations import Parameter, Provider, UnitSystem
28
+ from meteostat.interpolation.lapserate import lapse_rate
29
+ from meteostat.typing import Station
30
+
31
+ # Export public API
32
+ __all__ = [
33
+ "config",
34
+ "daily",
35
+ "hourly",
36
+ "interpolate",
37
+ "lapse_rate",
38
+ "merge",
39
+ "monthly",
40
+ "normals",
41
+ "Parameter",
42
+ "Point",
43
+ "Provider",
44
+ "purge",
45
+ "Station",
46
+ "stations",
47
+ "UnitSystem",
48
+ ]
@@ -0,0 +1,76 @@
1
+ """
2
+ Daily Time Series Data
3
+
4
+ Access daily time series data for one or multiple weather stations.
5
+ """
6
+
7
+ from typing import List, Optional
8
+ from datetime import datetime, date
9
+
10
+ import pandas as pd
11
+
12
+ from meteostat.core.data import data_service
13
+ from meteostat.enumerations import Parameter, Provider, Granularity
14
+ from meteostat.typing import Station, Request
15
+ from meteostat.api.point import Point
16
+ from meteostat.utils.parsers import parse_station, parse_time
17
+
18
+ DEFAULT_PARAMETERS = [
19
+ Parameter.TEMP,
20
+ Parameter.TMIN,
21
+ Parameter.TMAX,
22
+ Parameter.RHUM,
23
+ Parameter.PRCP,
24
+ Parameter.SNWD,
25
+ Parameter.WSPD,
26
+ Parameter.WPGT,
27
+ Parameter.PRES,
28
+ Parameter.TSUN,
29
+ Parameter.CLDC,
30
+ ]
31
+
32
+
33
+ def daily(
34
+ station: str | Station | Point | List[str | Station | Point] | pd.DataFrame,
35
+ start: Optional[datetime | date],
36
+ end: Optional[datetime | date],
37
+ parameters: Optional[List[Parameter]] = None,
38
+ providers: Optional[List[Provider]] = None,
39
+ ):
40
+ """
41
+ Access daily time series data.
42
+
43
+ Parameters
44
+ ----------
45
+ station : str, Station, Point, List[str | Station | Point], pd.Index, pd.Series
46
+ Weather station(s) or Point(s) to query data for. Can be a single station/point or a list.
47
+ Points are converted to virtual stations with IDs like $0001, $0002, etc.
48
+ start : datetime, date, optional
49
+ Start date for the data query. If None, the earliest available date will be used.
50
+ end : datetime, date, optional
51
+ End date for the data query. If None, the latest available date will be used.
52
+ parameters : List[Parameter], optional
53
+ List of parameters to include in the data query. Defaults to a set of common parameters.
54
+ providers : List[Provider], optional
55
+ List of data providers to use for the query. Defaults to the daily provider.
56
+
57
+ Returns
58
+ -------
59
+ TimeSeries
60
+ A TimeSeries object containing the daily data for the specified stations and parameters.
61
+ """
62
+ if parameters is None:
63
+ parameters = DEFAULT_PARAMETERS
64
+ if providers is None:
65
+ providers = [Provider.DAILY]
66
+
67
+ req = Request(
68
+ granularity=Granularity.DAILY,
69
+ providers=providers,
70
+ parameters=parameters,
71
+ station=parse_station(station),
72
+ start=parse_time(start),
73
+ end=parse_time(end, is_end=True),
74
+ )
75
+
76
+ return data_service.fetch(req)
@@ -0,0 +1,80 @@
1
+ """
2
+ Hourly Time Series Data
3
+
4
+ Access hourly time series data for one or multiple weather stations.
5
+ """
6
+
7
+ from typing import List, Optional
8
+ from datetime import datetime, date
9
+
10
+ import pandas as pd
11
+
12
+ from meteostat.core.data import data_service
13
+ from meteostat.enumerations import Parameter, Provider, Granularity
14
+ from meteostat.typing import Station, Request
15
+ from meteostat.api.point import Point
16
+ from meteostat.utils.parsers import parse_station, parse_time
17
+
18
+ DEFAULT_PARAMETERS = [
19
+ Parameter.TEMP,
20
+ Parameter.RHUM,
21
+ Parameter.PRCP,
22
+ Parameter.SNWD,
23
+ Parameter.WDIR,
24
+ Parameter.WSPD,
25
+ Parameter.WPGT,
26
+ Parameter.PRES,
27
+ Parameter.TSUN,
28
+ Parameter.CLDC,
29
+ Parameter.COCO,
30
+ ]
31
+
32
+
33
+ def hourly(
34
+ station: str | Station | Point | List[str | Station | Point] | pd.DataFrame,
35
+ start: Optional[datetime | date],
36
+ end: Optional[datetime | date],
37
+ timezone: Optional[str] = None,
38
+ parameters: Optional[List[Parameter]] = None,
39
+ providers: Optional[List[Provider]] = None,
40
+ ):
41
+ """
42
+ Access hourly time series data.
43
+
44
+ Parameters
45
+ ----------
46
+ station : str, Station, Point, List[str | Station | Point], pd.Index, pd.Series
47
+ Weather station(s) or Point(s) to query data for. Can be a single station/point or a list.
48
+ Points are converted to virtual stations with IDs like $0001, $0002, etc.
49
+ start : datetime, date, optional
50
+ Start date for the data query. If None, the earliest available date will be used.
51
+ end : datetime, date, optional
52
+ End date for the data query. If None, the latest available date will be used.
53
+ timezone : str, optional
54
+ Time zone for the data query. If None, UTC will be used.
55
+ parameters : List[Parameter], optional
56
+ List of parameters to include in the data query. Defaults to a set of common parameters.
57
+ providers : List[Provider], optional
58
+ List of data providers to use for the query. Defaults to the hourly provider.
59
+
60
+ Returns
61
+ -------
62
+ TimeSeries
63
+ A TimeSeries object containing the hourly data for the specified stations and parameters.
64
+ """
65
+ if parameters is None:
66
+ parameters = DEFAULT_PARAMETERS
67
+ if providers is None:
68
+ providers = [Provider.HOURLY]
69
+
70
+ req = Request(
71
+ granularity=Granularity.HOURLY,
72
+ providers=providers,
73
+ parameters=parameters,
74
+ station=parse_station(station),
75
+ start=parse_time(start, timezone),
76
+ end=parse_time(end, timezone, is_end=True),
77
+ timezone=timezone,
78
+ )
79
+
80
+ return data_service.fetch(req)
@@ -0,0 +1,240 @@
1
+ """
2
+ Interpolation Module
3
+
4
+ Provides spatial interpolation functions for meteorological data.
5
+ """
6
+
7
+ from typing import Optional, Union
8
+
9
+ import numpy as np
10
+ import pandas as pd
11
+
12
+ from meteostat.api.point import Point
13
+ from meteostat.api.timeseries import TimeSeries
14
+ from meteostat.typing import Station
15
+ from meteostat.interpolation.lapserate import apply_lapse_rate
16
+ from meteostat.interpolation.nearest import nearest_neighbor
17
+ from meteostat.interpolation.idw import inverse_distance_weighting
18
+ from meteostat.utils.data import aggregate_sources, reshape_by_source, stations_to_df
19
+ from meteostat.utils.geo import get_distance
20
+ from meteostat.utils.parsers import parse_station
21
+
22
+
23
+ def _create_timeseries(
24
+ ts: TimeSeries, point: Point, df: Optional[pd.DataFrame] = None
25
+ ) -> TimeSeries:
26
+ """
27
+ Create a TimeSeries object from interpolated DataFrame
28
+ """
29
+ parsed = parse_station(point)
30
+ stations_list = [parsed] if isinstance(parsed, Station) else parsed
31
+
32
+ # Convert stations to DataFrame
33
+ stations_df = stations_to_df(stations_list)
34
+
35
+ return TimeSeries(
36
+ ts.granularity,
37
+ stations_df,
38
+ df=df,
39
+ start=ts.start,
40
+ end=ts.end,
41
+ timezone=ts.timezone,
42
+ )
43
+
44
+
45
+ def _add_source_columns(
46
+ result: pd.DataFrame,
47
+ df: pd.DataFrame,
48
+ ) -> pd.DataFrame:
49
+ """
50
+ Add source columns to the result DataFrame
51
+ """
52
+ source_cols = [c for c in df.columns if c.endswith("_source")]
53
+ if source_cols:
54
+ grouped = df.groupby("time")[source_cols].agg(aggregate_sources)
55
+ if isinstance(grouped, pd.Series):
56
+ grouped = grouped.to_frame(name=source_cols[0])
57
+ grouped.index.name = "time"
58
+
59
+ # Safely align on time and add/fill source columns without causing overlaps
60
+ result_has_time_col = "time" in result.columns
61
+ if result_has_time_col:
62
+ result = result.set_index("time")
63
+
64
+ # Ensure both frames align on the same index (time)
65
+ # For each source column, add it if missing or fill NaNs if present
66
+ for col in source_cols:
67
+ if col in grouped.columns:
68
+ if col in result.columns:
69
+ # Fill missing values in result using aggregated sources
70
+ result[col] = result[col].where(result[col].notna(), grouped[col])
71
+ else:
72
+ # Add aggregated source column
73
+ result[col] = grouped[col]
74
+
75
+ if result_has_time_col:
76
+ result = result.reset_index()
77
+ return result
78
+
79
+
80
+ def interpolate(
81
+ ts: TimeSeries,
82
+ point: Point,
83
+ distance_threshold: Union[int, None] = 5000,
84
+ elevation_threshold: Union[int, None] = 50,
85
+ elevation_weight: float = 10,
86
+ power: float = 2.0,
87
+ lapse_rate: Union[float, None] = 6.5,
88
+ lapse_rate_threshold: int = 50,
89
+ ) -> TimeSeries:
90
+ """
91
+ Interpolate time series data spatially to a specific point.
92
+
93
+ Parameters
94
+ ----------
95
+ ts : TimeSeries
96
+ The time series to interpolate.
97
+ point : Point
98
+ The point to interpolate the data for.
99
+ distance_threshold : int, optional
100
+ Maximum distance (in meters) to use nearest neighbor (default: 5000).
101
+ Beyond this, IDW is used.
102
+ elevation_threshold : int, optional
103
+ Maximum elevation difference (in meters) to use nearest neighbor (default: 50).
104
+ Beyond this, IDW is used even if distance is within threshold.
105
+ elevation_weight : float, optional
106
+ Weight for elevation difference in distance calculation (default: 0.1).
107
+ The effective distance is calculated as:
108
+ sqrt(horizontal_distance^2 + (elevation_diff * elevation_weight)^2)
109
+ power : float, optional
110
+ Power parameter for IDW (default: 2.0). Higher values give more
111
+ weight to closer stations.
112
+ lapse_rate : float, optional
113
+ Apply lapse rate correction based on elevation difference (default: 6.5).
114
+ lapse_rate_threshold : int, optional
115
+ Elevation difference threshold (in meters) to apply lapse rate correction
116
+ (default: 50). If the elevation difference between the point and stations
117
+ is less than this, no correction is applied.
118
+
119
+ Returns
120
+ -------
121
+ pd.DataFrame or None
122
+ A DataFrame containing the interpolated data for the specified point,
123
+ or None if no data is available.
124
+ """
125
+ # Fetch DataFrame, filling missing values and adding location data
126
+ df = ts.fetch(fill=True, location=True, sources=True)
127
+
128
+ # If no data is returned, return None
129
+ if df is None:
130
+ return _create_timeseries(ts, point)
131
+
132
+ # Add distance column
133
+ df["distance"] = get_distance(
134
+ point.latitude, point.longitude, df["latitude"], df["longitude"]
135
+ )
136
+
137
+ # Add effective distance column if elevation is available
138
+ if point.elevation is not None and "elevation" in df.columns:
139
+ elev_diff = np.abs(df["elevation"] - point.elevation)
140
+ df["effective_distance"] = np.sqrt(
141
+ df["distance"] ** 2 + (elev_diff * elevation_weight) ** 2
142
+ )
143
+ else:
144
+ df["effective_distance"] = df["distance"]
145
+
146
+ # Add elevation difference column
147
+ if "elevation" in df.columns and point.elevation is not None:
148
+ df["elevation_diff"] = np.abs(df["elevation"] - point.elevation)
149
+ else:
150
+ df["elevation_diff"] = np.nan
151
+
152
+ # Apply lapse rate if specified and elevation is available
153
+ if (
154
+ lapse_rate
155
+ and point.elevation
156
+ and df["elevation_diff"].max() >= lapse_rate_threshold
157
+ ):
158
+ df = apply_lapse_rate(df, point.elevation, lapse_rate)
159
+
160
+ # Check if any stations are close enough for nearest neighbor
161
+ min_distance = df["distance"].min()
162
+ use_nearest = distance_threshold is None or min_distance <= distance_threshold
163
+ if use_nearest and point.elevation is not None and "elevation" in df.columns:
164
+ # Calculate minimum elevation difference
165
+ min_elev_diff = np.abs(df["elevation"] - point.elevation).min()
166
+ use_nearest = (
167
+ elevation_threshold is None or min_elev_diff <= elevation_threshold
168
+ )
169
+
170
+ # Initialize variables
171
+ df_nearest = None
172
+ df_idw = None
173
+
174
+ # Perform nearest neighbor if applicable
175
+ if use_nearest:
176
+ # Filter applicable stations based on thresholds
177
+ distance_filter = (
178
+ pd.Series([True] * len(df), index=df.index)
179
+ if distance_threshold is None
180
+ else (df["distance"] <= distance_threshold)
181
+ )
182
+ elevation_filter = (
183
+ pd.Series([True] * len(df), index=df.index)
184
+ if elevation_threshold is None
185
+ else (np.abs(df["elevation"] - point.elevation) <= elevation_threshold)
186
+ )
187
+ df_filtered = df[distance_filter & elevation_filter]
188
+ df_nearest = nearest_neighbor(df_filtered, ts, point)
189
+
190
+ # Check if we need to use IDW
191
+ if (
192
+ not use_nearest
193
+ or df_nearest is None
194
+ or len(df_nearest) == 0
195
+ or df_nearest.isna().any().any()
196
+ ):
197
+ # Perform IDW interpolation
198
+ idw_func = inverse_distance_weighting(power=power)
199
+ df_idw = idw_func(df, ts, point)
200
+
201
+ # Merge DataFrames with priority to nearest neighbor
202
+ if use_nearest and df_nearest is not None and len(df_nearest) > 0:
203
+ if df_idw is not None:
204
+ # Combine nearest and IDW results, prioritizing nearest values
205
+ result = df_nearest.combine_first(df_idw)
206
+ else:
207
+ result = df_nearest
208
+ else:
209
+ result = df_idw
210
+
211
+ # If no data is returned, return None
212
+ if result is None or result.empty:
213
+ return _create_timeseries(ts, point)
214
+
215
+ # Drop location-related columns & return
216
+ result = result.drop(
217
+ [
218
+ "latitude",
219
+ "longitude",
220
+ "elevation",
221
+ "distance",
222
+ "effective_distance",
223
+ "elevation_diff",
224
+ ],
225
+ axis=1,
226
+ )
227
+
228
+ # Add source columns: aggregate all columns that end with "_source"
229
+ result = _add_source_columns(result, df)
230
+
231
+ # Reshape by source
232
+ result = reshape_by_source(result)
233
+
234
+ # Add station index
235
+ result["station"] = "$0001"
236
+ result = result.set_index("station", append=True).reorder_levels(
237
+ ["station", "time", "source"]
238
+ )
239
+
240
+ return _create_timeseries(ts, point, result)