meteostat 1.7.5__py3-none-any.whl → 2.0.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.
- meteostat/__init__.py +32 -19
- meteostat/api/daily.py +76 -0
- meteostat/api/hourly.py +80 -0
- meteostat/api/interpolate.py +240 -0
- meteostat/api/inventory.py +59 -0
- meteostat/api/merge.py +103 -0
- meteostat/api/monthly.py +73 -0
- meteostat/api/normals.py +144 -0
- meteostat/api/point.py +30 -0
- meteostat/api/stations.py +234 -0
- meteostat/api/timeseries.py +334 -0
- meteostat/core/cache.py +212 -59
- meteostat/core/config.py +158 -0
- meteostat/core/data.py +199 -0
- meteostat/core/logger.py +9 -0
- meteostat/core/network.py +82 -0
- meteostat/core/parameters.py +112 -0
- meteostat/core/providers.py +184 -0
- meteostat/core/schema.py +170 -0
- meteostat/core/validator.py +38 -0
- meteostat/enumerations.py +149 -0
- meteostat/interpolation/idw.py +120 -0
- meteostat/interpolation/lapserate.py +91 -0
- meteostat/interpolation/nearest.py +31 -0
- meteostat/parameters.py +354 -0
- meteostat/providers/dwd/climat.py +166 -0
- meteostat/providers/dwd/daily.py +144 -0
- meteostat/providers/dwd/hourly.py +218 -0
- meteostat/providers/dwd/monthly.py +138 -0
- meteostat/providers/dwd/mosmix.py +351 -0
- meteostat/providers/dwd/poi.py +117 -0
- meteostat/providers/dwd/shared.py +155 -0
- meteostat/providers/eccc/daily.py +87 -0
- meteostat/providers/eccc/hourly.py +104 -0
- meteostat/providers/eccc/monthly.py +66 -0
- meteostat/providers/eccc/shared.py +45 -0
- meteostat/providers/index.py +496 -0
- meteostat/providers/meteostat/daily.py +65 -0
- meteostat/providers/meteostat/daily_derived.py +110 -0
- meteostat/providers/meteostat/hourly.py +66 -0
- meteostat/providers/meteostat/monthly.py +45 -0
- meteostat/providers/meteostat/monthly_derived.py +106 -0
- meteostat/providers/meteostat/shared.py +93 -0
- meteostat/providers/metno/forecast.py +186 -0
- meteostat/providers/noaa/ghcnd.py +228 -0
- meteostat/providers/noaa/isd_lite.py +142 -0
- meteostat/providers/noaa/metar.py +163 -0
- meteostat/typing.py +113 -0
- meteostat/utils/conversions.py +231 -0
- meteostat/utils/data.py +194 -0
- meteostat/utils/geo.py +28 -0
- meteostat/utils/parsers.py +168 -0
- meteostat/utils/types.py +113 -0
- meteostat/utils/validators.py +31 -0
- meteostat-2.0.0.dist-info/METADATA +134 -0
- meteostat-2.0.0.dist-info/RECORD +63 -0
- {meteostat-1.7.5.dist-info → meteostat-2.0.0.dist-info}/WHEEL +1 -2
- meteostat/core/loader.py +0 -103
- meteostat/core/warn.py +0 -34
- meteostat/enumerations/granularity.py +0 -22
- meteostat/interface/base.py +0 -39
- meteostat/interface/daily.py +0 -118
- meteostat/interface/hourly.py +0 -154
- meteostat/interface/meteodata.py +0 -210
- meteostat/interface/monthly.py +0 -109
- meteostat/interface/normals.py +0 -245
- meteostat/interface/point.py +0 -143
- meteostat/interface/stations.py +0 -252
- meteostat/interface/timeseries.py +0 -237
- meteostat/series/aggregate.py +0 -48
- meteostat/series/convert.py +0 -28
- meteostat/series/count.py +0 -17
- meteostat/series/coverage.py +0 -20
- meteostat/series/fetch.py +0 -28
- meteostat/series/interpolate.py +0 -47
- meteostat/series/normalize.py +0 -76
- meteostat/series/stations.py +0 -22
- meteostat/units.py +0 -149
- meteostat/utilities/__init__.py +0 -0
- meteostat/utilities/aggregations.py +0 -37
- meteostat/utilities/endpoint.py +0 -33
- meteostat/utilities/helpers.py +0 -70
- meteostat/utilities/mutations.py +0 -85
- meteostat/utilities/validations.py +0 -30
- meteostat-1.7.5.dist-info/METADATA +0 -112
- meteostat-1.7.5.dist-info/RECORD +0 -39
- meteostat-1.7.5.dist-info/top_level.txt +0 -1
- /meteostat/{core → api}/__init__.py +0 -0
- /meteostat/{enumerations → interpolation}/__init__.py +0 -0
- /meteostat/{interface → providers}/__init__.py +0 -0
- /meteostat/{interface/interpolate.py → py.typed} +0 -0
- /meteostat/{series → utils}/__init__.py +0 -0
- {meteostat-1.7.5.dist-info → meteostat-2.0.0.dist-info/licenses}/LICENSE +0 -0
meteostat/interface/hourly.py
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Hourly Class
|
|
3
|
-
|
|
4
|
-
Meteorological data provided by Meteostat (https://dev.meteostat.net)
|
|
5
|
-
under the terms of the Creative Commons Attribution-NonCommercial
|
|
6
|
-
4.0 International Public License.
|
|
7
|
-
|
|
8
|
-
The code is licensed under the MIT license.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
from math import floor
|
|
12
|
-
from datetime import datetime, timedelta
|
|
13
|
-
from typing import Optional, Union
|
|
14
|
-
import pytz
|
|
15
|
-
import pandas as pd
|
|
16
|
-
from meteostat.enumerations.granularity import Granularity
|
|
17
|
-
from meteostat.utilities.aggregations import degree_mean
|
|
18
|
-
from meteostat.interface.timeseries import TimeSeries
|
|
19
|
-
from meteostat.interface.point import Point
|
|
20
|
-
from meteostat.utilities.mutations import calculate_dwpt
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class Hourly(TimeSeries):
|
|
24
|
-
"""
|
|
25
|
-
Retrieve hourly weather observations for one or multiple weather stations or
|
|
26
|
-
a single geographical point
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
# The cache subdirectory
|
|
30
|
-
cache_subdir = "hourly"
|
|
31
|
-
|
|
32
|
-
# Granularity
|
|
33
|
-
granularity = Granularity.HOURLY
|
|
34
|
-
|
|
35
|
-
# Download data as annual chunks
|
|
36
|
-
# This cannot be changed and is only kept for backward compatibility
|
|
37
|
-
chunked = True
|
|
38
|
-
|
|
39
|
-
# The time zone
|
|
40
|
-
_timezone: Optional[str] = None
|
|
41
|
-
|
|
42
|
-
# Default frequency
|
|
43
|
-
_freq = "1h"
|
|
44
|
-
|
|
45
|
-
# Source mappings
|
|
46
|
-
_source_mappings = {
|
|
47
|
-
"metar": "D",
|
|
48
|
-
"model": "E",
|
|
49
|
-
"isd_lite": "B",
|
|
50
|
-
"synop": "C",
|
|
51
|
-
"dwd_poi": "C",
|
|
52
|
-
"dwd_hourly": "A",
|
|
53
|
-
"dwd_mosmix": "E",
|
|
54
|
-
"metno_forecast": "E",
|
|
55
|
-
"eccc_hourly": "A",
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
# Flag which represents model data
|
|
59
|
-
_model_flag = "E"
|
|
60
|
-
|
|
61
|
-
# Raw data columns
|
|
62
|
-
_columns = [
|
|
63
|
-
"year",
|
|
64
|
-
"month",
|
|
65
|
-
"day",
|
|
66
|
-
"hour",
|
|
67
|
-
"temp",
|
|
68
|
-
{"dwpt": calculate_dwpt},
|
|
69
|
-
"rhum",
|
|
70
|
-
"prcp",
|
|
71
|
-
{"snow": "snwd"},
|
|
72
|
-
"wdir",
|
|
73
|
-
"wspd",
|
|
74
|
-
"wpgt",
|
|
75
|
-
"pres",
|
|
76
|
-
"tsun",
|
|
77
|
-
"coco",
|
|
78
|
-
]
|
|
79
|
-
|
|
80
|
-
# Index of first meteorological column
|
|
81
|
-
_first_met_col = 4
|
|
82
|
-
|
|
83
|
-
# Columns for date parsing
|
|
84
|
-
_parse_dates = ["year", "month", "day", "hour"]
|
|
85
|
-
|
|
86
|
-
# Default aggregation functions
|
|
87
|
-
aggregations = {
|
|
88
|
-
"temp": "mean",
|
|
89
|
-
"dwpt": "mean",
|
|
90
|
-
"rhum": "mean",
|
|
91
|
-
"prcp": "sum",
|
|
92
|
-
"snow": "max",
|
|
93
|
-
"wdir": degree_mean,
|
|
94
|
-
"wspd": "mean",
|
|
95
|
-
"wpgt": "max",
|
|
96
|
-
"pres": "mean",
|
|
97
|
-
"tsun": "sum",
|
|
98
|
-
"coco": "max",
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
def _set_time(
|
|
102
|
-
self,
|
|
103
|
-
start: Optional[datetime] = None,
|
|
104
|
-
end: Optional[datetime] = None,
|
|
105
|
-
timezone: Optional[str] = None,
|
|
106
|
-
) -> None:
|
|
107
|
-
"""
|
|
108
|
-
Set & adapt the period's time zone
|
|
109
|
-
"""
|
|
110
|
-
if timezone:
|
|
111
|
-
# Save timezone
|
|
112
|
-
self._timezone = timezone
|
|
113
|
-
|
|
114
|
-
if start and end:
|
|
115
|
-
# Initialize time zone
|
|
116
|
-
timezone = pytz.timezone(self._timezone)
|
|
117
|
-
|
|
118
|
-
# Set start date
|
|
119
|
-
start = timezone.localize(start, is_dst=None).astimezone(pytz.utc)
|
|
120
|
-
|
|
121
|
-
# Set end date
|
|
122
|
-
end = timezone.localize(end, is_dst=None).astimezone(pytz.utc)
|
|
123
|
-
|
|
124
|
-
if self.chunked:
|
|
125
|
-
self._annual_steps = [
|
|
126
|
-
start.year + i for i in range(end.year - start.year + 1)
|
|
127
|
-
]
|
|
128
|
-
|
|
129
|
-
self._start = start
|
|
130
|
-
self._end = end
|
|
131
|
-
|
|
132
|
-
def __init__(
|
|
133
|
-
self,
|
|
134
|
-
loc: Union[pd.DataFrame, Point, list, str], # Station(s) or geo point
|
|
135
|
-
start=datetime(1890, 1, 1, 0, 0, 0),
|
|
136
|
-
end=datetime.combine(
|
|
137
|
-
datetime.today().date() + timedelta(days=10), datetime.max.time()
|
|
138
|
-
),
|
|
139
|
-
timezone: Optional[str] = None,
|
|
140
|
-
model=True, # Include model data?
|
|
141
|
-
flags=False, # Load source flags?
|
|
142
|
-
) -> None:
|
|
143
|
-
# Set time zone and adapt period
|
|
144
|
-
self._set_time(start, end, timezone)
|
|
145
|
-
|
|
146
|
-
# Initialize time series
|
|
147
|
-
self._init_time_series(loc, start, end, model, flags)
|
|
148
|
-
|
|
149
|
-
def expected_rows(self) -> int:
|
|
150
|
-
"""
|
|
151
|
-
Return the number of rows expected for the defined date range
|
|
152
|
-
"""
|
|
153
|
-
|
|
154
|
-
return floor((self._end - self._start).total_seconds() / 3600) + 1
|
meteostat/interface/meteodata.py
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Meteorological Data Class
|
|
3
|
-
|
|
4
|
-
A parent class for both time series and
|
|
5
|
-
climate normals data
|
|
6
|
-
|
|
7
|
-
Meteorological data provided by Meteostat (https://dev.meteostat.net)
|
|
8
|
-
under the terms of the Creative Commons Attribution-NonCommercial
|
|
9
|
-
4.0 International Public License.
|
|
10
|
-
|
|
11
|
-
The code is licensed under the MIT license.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
from collections.abc import Callable
|
|
15
|
-
from typing import Dict, List, Union
|
|
16
|
-
import pandas as pd
|
|
17
|
-
from meteostat.enumerations.granularity import Granularity
|
|
18
|
-
from meteostat.core.loader import processing_handler
|
|
19
|
-
from meteostat.utilities.mutations import adjust_temp
|
|
20
|
-
from meteostat.utilities.aggregations import weighted_average
|
|
21
|
-
from meteostat.interface.base import Base
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class MeteoData(Base):
|
|
25
|
-
"""
|
|
26
|
-
A parent class for both time series and
|
|
27
|
-
climate normals data
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
# The list of weather Stations
|
|
31
|
-
_stations: Union[pd.Index, None] = None
|
|
32
|
-
|
|
33
|
-
# The data frame
|
|
34
|
-
_data: pd.DataFrame = pd.DataFrame()
|
|
35
|
-
|
|
36
|
-
@property
|
|
37
|
-
def _raw_columns(self) -> List[str]:
|
|
38
|
-
"""
|
|
39
|
-
Get the list of raw data columns, excluding any dicts with callable values
|
|
40
|
-
"""
|
|
41
|
-
return [
|
|
42
|
-
list(col.values())[0] if isinstance(col, dict) else col
|
|
43
|
-
for col in self._columns
|
|
44
|
-
if not (
|
|
45
|
-
isinstance(col, dict)
|
|
46
|
-
and (
|
|
47
|
-
isinstance(list(col.values())[0], Callable)
|
|
48
|
-
or list(col.values())[0] is None
|
|
49
|
-
)
|
|
50
|
-
)
|
|
51
|
-
]
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def _processed_columns(self) -> List[str]:
|
|
55
|
-
"""
|
|
56
|
-
Get the list of processed data columns, excluding any dicts with callable values
|
|
57
|
-
"""
|
|
58
|
-
return [
|
|
59
|
-
list(col.keys())[0] if isinstance(col, dict) else col
|
|
60
|
-
for col in self._columns[self._first_met_col :]
|
|
61
|
-
]
|
|
62
|
-
|
|
63
|
-
@property
|
|
64
|
-
def _renamed_columns(self) -> Dict[str, str]:
|
|
65
|
-
"""
|
|
66
|
-
Get the dict of renamed data columns, including `_source` suffixes
|
|
67
|
-
"""
|
|
68
|
-
return {
|
|
69
|
-
new_key: new_val
|
|
70
|
-
for d in self._columns
|
|
71
|
-
if isinstance(d, dict)
|
|
72
|
-
for k, v in d.items()
|
|
73
|
-
if not isinstance(v, Callable)
|
|
74
|
-
for new_key, new_val in ((v, k), (f"{v}_source", f"{k}_source"))
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
@property
|
|
78
|
-
def _virtual_columns(self) -> Dict[str, str]:
|
|
79
|
-
"""
|
|
80
|
-
Get the dict of virtual data columns
|
|
81
|
-
"""
|
|
82
|
-
return {
|
|
83
|
-
k: v
|
|
84
|
-
for d in self._columns
|
|
85
|
-
if isinstance(d, dict)
|
|
86
|
-
for k, v in d.items()
|
|
87
|
-
if isinstance(v, Callable)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
def _get_datasets(self) -> list:
|
|
91
|
-
"""
|
|
92
|
-
Get list of datasets
|
|
93
|
-
"""
|
|
94
|
-
|
|
95
|
-
if self.granularity in (Granularity.HOURLY, Granularity.DAILY):
|
|
96
|
-
datasets = [
|
|
97
|
-
(str(station), year)
|
|
98
|
-
for station in self._stations
|
|
99
|
-
for year in self._annual_steps
|
|
100
|
-
]
|
|
101
|
-
else:
|
|
102
|
-
datasets = [(str(station),) for station in self._stations]
|
|
103
|
-
|
|
104
|
-
return datasets
|
|
105
|
-
|
|
106
|
-
def _get_data(self) -> None:
|
|
107
|
-
"""
|
|
108
|
-
Get all required data dumps
|
|
109
|
-
"""
|
|
110
|
-
|
|
111
|
-
if len(self._stations) > 0:
|
|
112
|
-
# Get list of datasets
|
|
113
|
-
datasets = self._get_datasets()
|
|
114
|
-
|
|
115
|
-
# Data Processings
|
|
116
|
-
return processing_handler(
|
|
117
|
-
datasets, self._load_data, self.processes, self.threads
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
# Empty DataFrame
|
|
121
|
-
return pd.DataFrame(columns=self._processed_columns)
|
|
122
|
-
|
|
123
|
-
# pylint: disable=too-many-branches
|
|
124
|
-
def _resolve_point(
|
|
125
|
-
self, method: str, stations: pd.DataFrame, alt: int, adapt_temp: bool
|
|
126
|
-
) -> None:
|
|
127
|
-
"""
|
|
128
|
-
Project weather station data onto a single point
|
|
129
|
-
"""
|
|
130
|
-
|
|
131
|
-
if self._stations.size == 0 or self._data.size == 0:
|
|
132
|
-
return
|
|
133
|
-
|
|
134
|
-
if method == "nearest":
|
|
135
|
-
if adapt_temp:
|
|
136
|
-
# Join elevation of involved weather stations
|
|
137
|
-
data = self._data.join(stations["elevation"], on="station")
|
|
138
|
-
|
|
139
|
-
# Adapt temperature-like data based on altitude
|
|
140
|
-
data = adjust_temp(data, alt)
|
|
141
|
-
|
|
142
|
-
# Drop elevation & round
|
|
143
|
-
data = data.drop("elevation", axis=1).round(1)
|
|
144
|
-
|
|
145
|
-
else:
|
|
146
|
-
data = self._data
|
|
147
|
-
|
|
148
|
-
if self.granularity == Granularity.NORMALS:
|
|
149
|
-
self._data = data.groupby(level=["start", "end", "month"]).agg("first")
|
|
150
|
-
|
|
151
|
-
else:
|
|
152
|
-
self._data = data.groupby(
|
|
153
|
-
pd.Grouper(level="time", freq=self._freq)
|
|
154
|
-
).agg("first")
|
|
155
|
-
|
|
156
|
-
else:
|
|
157
|
-
# Join score and elevation of involved weather stations
|
|
158
|
-
data = self._data.join(stations[["score", "elevation"]], on="station")
|
|
159
|
-
|
|
160
|
-
# Adapt temperature-like data based on altitude
|
|
161
|
-
if adapt_temp:
|
|
162
|
-
data = adjust_temp(data, alt)
|
|
163
|
-
|
|
164
|
-
# Exclude non-mean data & perform aggregation
|
|
165
|
-
if not self.granularity == Granularity.NORMALS:
|
|
166
|
-
excluded = data["wdir"]
|
|
167
|
-
excluded = excluded.groupby(
|
|
168
|
-
pd.Grouper(level="time", freq=self._freq)
|
|
169
|
-
).agg("first")
|
|
170
|
-
|
|
171
|
-
# Aggregate mean data
|
|
172
|
-
if self.granularity == Granularity.NORMALS:
|
|
173
|
-
data = data.groupby(level=["start", "end", "month"]).apply(
|
|
174
|
-
weighted_average
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
# Remove obsolete index column
|
|
178
|
-
try:
|
|
179
|
-
data = data.reset_index(level=3, drop=True)
|
|
180
|
-
except IndexError:
|
|
181
|
-
pass
|
|
182
|
-
|
|
183
|
-
else:
|
|
184
|
-
data = data.groupby(pd.Grouper(level="time", freq=self._freq)).apply(
|
|
185
|
-
weighted_average
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
# Drop RangeIndex
|
|
189
|
-
data.index = data.index.droplevel(1)
|
|
190
|
-
|
|
191
|
-
# Merge excluded fields
|
|
192
|
-
data["wdir"] = excluded
|
|
193
|
-
|
|
194
|
-
# Drop score and elevation
|
|
195
|
-
self._data = data.drop(["score", "elevation"], axis=1).round(1)
|
|
196
|
-
|
|
197
|
-
# Set placeholder station ID
|
|
198
|
-
self._data["station"] = "XXXXX"
|
|
199
|
-
|
|
200
|
-
# Set index
|
|
201
|
-
if self.granularity == Granularity.NORMALS:
|
|
202
|
-
self._data = self._data.set_index("station", append=True)
|
|
203
|
-
self._data = self._data.reorder_levels(["station", "start", "end", "month"])
|
|
204
|
-
else:
|
|
205
|
-
self._data = self._data.set_index(
|
|
206
|
-
["station", self._data.index.get_level_values("time")]
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
# Set station index
|
|
210
|
-
self._stations = pd.Index(["XXXXX"])
|
meteostat/interface/monthly.py
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Monthly Class
|
|
3
|
-
|
|
4
|
-
Meteorological data provided by Meteostat (https://dev.meteostat.net)
|
|
5
|
-
under the terms of the Creative Commons Attribution-NonCommercial
|
|
6
|
-
4.0 International Public License.
|
|
7
|
-
|
|
8
|
-
The code is licensed under the MIT license.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
from datetime import datetime
|
|
12
|
-
from typing import Union
|
|
13
|
-
import pandas as pd
|
|
14
|
-
from meteostat.enumerations.granularity import Granularity
|
|
15
|
-
from meteostat.interface.timeseries import TimeSeries
|
|
16
|
-
from meteostat.interface.point import Point
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class Monthly(TimeSeries):
|
|
20
|
-
"""
|
|
21
|
-
Retrieve monthly weather data for one or multiple weather stations or
|
|
22
|
-
a single geographical point
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
# The cache subdirectory
|
|
26
|
-
cache_subdir = "monthly"
|
|
27
|
-
|
|
28
|
-
# Granularity
|
|
29
|
-
granularity = Granularity.MONTHLY
|
|
30
|
-
|
|
31
|
-
# Default frequency
|
|
32
|
-
_freq = "1MS"
|
|
33
|
-
|
|
34
|
-
# Source mappings
|
|
35
|
-
_source_mappings = {
|
|
36
|
-
"dwd_monthly": "A",
|
|
37
|
-
"eccc_monthly": "A",
|
|
38
|
-
"dwd_daily": "C",
|
|
39
|
-
"eccc_daily": "C",
|
|
40
|
-
"ghcnd": "D",
|
|
41
|
-
"dwd_hourly": "E",
|
|
42
|
-
"eccc_hourly": "E",
|
|
43
|
-
"isd_lite": "F",
|
|
44
|
-
"synop": "G",
|
|
45
|
-
"dwd_poi": "G",
|
|
46
|
-
"metar": "H",
|
|
47
|
-
"model": "I",
|
|
48
|
-
"dwd_mosmix": "I",
|
|
49
|
-
"metno_forecast": "I",
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
# Flag which represents model data
|
|
53
|
-
_model_flag = "I"
|
|
54
|
-
|
|
55
|
-
# Columns
|
|
56
|
-
_columns = [
|
|
57
|
-
"year",
|
|
58
|
-
"month",
|
|
59
|
-
{"tavg": "temp"},
|
|
60
|
-
"tmin",
|
|
61
|
-
"tmax",
|
|
62
|
-
"prcp",
|
|
63
|
-
"wspd",
|
|
64
|
-
"pres",
|
|
65
|
-
"tsun",
|
|
66
|
-
]
|
|
67
|
-
|
|
68
|
-
# Index of first meteorological column
|
|
69
|
-
_first_met_col = 2
|
|
70
|
-
|
|
71
|
-
# Columns for date parsing
|
|
72
|
-
_parse_dates = ["year", "month"]
|
|
73
|
-
|
|
74
|
-
# Default aggregation functions
|
|
75
|
-
aggregations = {
|
|
76
|
-
"tavg": "mean",
|
|
77
|
-
"tmin": "mean",
|
|
78
|
-
"tmax": "mean",
|
|
79
|
-
"prcp": "sum",
|
|
80
|
-
"wspd": "mean",
|
|
81
|
-
"pres": "mean",
|
|
82
|
-
"tsun": "sum",
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
def __init__(
|
|
86
|
-
self,
|
|
87
|
-
loc: Union[pd.DataFrame, Point, list, str], # Station(s) or geo point
|
|
88
|
-
start: datetime = None,
|
|
89
|
-
end: datetime = None,
|
|
90
|
-
model: bool = True, # Include model data?
|
|
91
|
-
flags: bool = False, # Load source flags?
|
|
92
|
-
) -> None:
|
|
93
|
-
# Set start date
|
|
94
|
-
if start is not None:
|
|
95
|
-
start = start.replace(day=1)
|
|
96
|
-
|
|
97
|
-
# Initialize time series
|
|
98
|
-
self._init_time_series(loc, start, end, model, flags)
|
|
99
|
-
|
|
100
|
-
def expected_rows(self) -> int:
|
|
101
|
-
"""
|
|
102
|
-
Return the number of rows expected for the defined date range
|
|
103
|
-
"""
|
|
104
|
-
|
|
105
|
-
return (
|
|
106
|
-
(self._end.year - self._start.year) * 12
|
|
107
|
-
+ self._end.month
|
|
108
|
-
- self._start.month
|
|
109
|
-
) + 1
|