pvlib 0.13.0a1__py3-none-any.whl → 0.13.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.
- pvlib/bifacial/pvfactors.py +1 -1
- pvlib/clearsky.py +21 -12
- pvlib/inverter.py +11 -7
- pvlib/iotools/__init__.py +6 -0
- pvlib/iotools/meteonorm.py +623 -0
- pvlib/iotools/nasa_power.py +153 -0
- pvlib/iotools/psm3.py +1 -1
- pvlib/iotools/pvgis.py +1 -1
- pvlib/iotools/sodapro.py +1 -1
- pvlib/iotools/tmy.py +4 -2
- pvlib/irradiance.py +311 -299
- pvlib/ivtools/sdm/_fit_desoto_pvsyst_sandia.py +1 -1
- pvlib/ivtools/sdm/cec.py +1 -1
- pvlib/ivtools/sdm/desoto.py +6 -6
- pvlib/ivtools/sdm/pvsyst.py +7 -7
- pvlib/modelchain.py +19 -10
- pvlib/pvarray.py +61 -17
- pvlib/singlediode.py +16 -10
- pvlib/solarposition.py +11 -10
- pvlib/spectrum/mismatch.py +7 -19
- pvlib/temperature.py +58 -10
- pvlib/tools.py +2 -2
- pvlib/tracking.py +11 -6
- {pvlib-0.13.0a1.dist-info → pvlib-0.13.1.dist-info}/METADATA +5 -5
- {pvlib-0.13.0a1.dist-info → pvlib-0.13.1.dist-info}/RECORD +29 -27
- {pvlib-0.13.0a1.dist-info → pvlib-0.13.1.dist-info}/WHEEL +0 -0
- {pvlib-0.13.0a1.dist-info → pvlib-0.13.1.dist-info}/licenses/AUTHORS.md +0 -0
- {pvlib-0.13.0a1.dist-info → pvlib-0.13.1.dist-info}/licenses/LICENSE +0 -0
- {pvlib-0.13.0a1.dist-info → pvlib-0.13.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
"""Functions for retrieving data from Meteonorm."""
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import requests
|
|
5
|
+
from urllib.parse import urljoin
|
|
6
|
+
from pandas._libs.tslibs.parsing import DateParseError
|
|
7
|
+
|
|
8
|
+
URL = "https://api.meteonorm.com/v1/"
|
|
9
|
+
|
|
10
|
+
VARIABLE_MAP = {
|
|
11
|
+
"global_horizontal_irradiance": "ghi",
|
|
12
|
+
"diffuse_horizontal_irradiance": "dhi",
|
|
13
|
+
"direct_normal_irradiance": "dni",
|
|
14
|
+
"direct_horizontal_irradiance": "bhi",
|
|
15
|
+
"global_clear_sky_irradiance": "ghi_clear",
|
|
16
|
+
"diffuse_clear_sky_irradiance": "dhi_clear",
|
|
17
|
+
"direct_normal_clear_sky_irradiance": "dni_clear",
|
|
18
|
+
"direct_horizontal_clear_sky_irradiance": "bhi_clear",
|
|
19
|
+
"diffuse_tilted_irradiance": "poa_diffuse",
|
|
20
|
+
"direct_tilted_irradiance": "poa_direct",
|
|
21
|
+
"global_tilted_irradiance": "poa",
|
|
22
|
+
"temperature": "temp_air",
|
|
23
|
+
"dew_point_temperature": "temp_dew",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
TIME_STEP_MAP = {
|
|
27
|
+
"1h": "1_hour",
|
|
28
|
+
"h": "1_hour",
|
|
29
|
+
"15min": "15_minutes",
|
|
30
|
+
"1min": "1_minute",
|
|
31
|
+
"min": "1_minute",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_meteonorm_forecast_basic(
|
|
36
|
+
latitude, longitude, start, end,
|
|
37
|
+
api_key, parameters="all", *,
|
|
38
|
+
surface_tilt=0, surface_azimuth=180,
|
|
39
|
+
horizon="auto", interval_index=False,
|
|
40
|
+
map_variables=True, url=URL):
|
|
41
|
+
"""
|
|
42
|
+
Retrieve basic forecast data from Meteonorm.
|
|
43
|
+
|
|
44
|
+
The basic forecast data only supports hourly time step.
|
|
45
|
+
|
|
46
|
+
The Meteonorm data options are described in [1]_ and the API is described
|
|
47
|
+
in [2]_. A detailed list of API options can be found in [3]_.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
latitude : float
|
|
53
|
+
In decimal degrees, north is positive (ISO 19115).
|
|
54
|
+
longitude: float
|
|
55
|
+
In decimal degrees, east is positive (ISO 19115).
|
|
56
|
+
start : datetime like or str
|
|
57
|
+
First timestamp of the requested period. If a timezone is not
|
|
58
|
+
specified, UTC is assumed. Relative date/time strings are
|
|
59
|
+
also allowed, e.g., 'now' or '+3hours'.
|
|
60
|
+
end : datetime like or str
|
|
61
|
+
Last timestamp of the requested period. If a timezone is not
|
|
62
|
+
specified, UTC is assumed. Relative date/time strings are
|
|
63
|
+
also allowed, e.g., 'now' or '+3hours'.
|
|
64
|
+
api_key : str
|
|
65
|
+
Meteonorm API key.
|
|
66
|
+
parameters : list or 'all', default : 'all'
|
|
67
|
+
List of parameters to request or `'all'` to get all parameters.
|
|
68
|
+
surface_tilt : float, default : 0
|
|
69
|
+
Tilt angle from horizontal plane.
|
|
70
|
+
surface_azimuth : float, default : 180
|
|
71
|
+
Orientation (azimuth angle) of the (fixed) plane. Clockwise from north
|
|
72
|
+
(north=0, east=90, south=180, west=270).
|
|
73
|
+
horizon : str or list, default : 'auto'
|
|
74
|
+
Specification of the horizon line. Can be either 'flat', 'auto', or
|
|
75
|
+
a list of 360 integer horizon elevation angles.
|
|
76
|
+
interval_index : bool, default : False
|
|
77
|
+
Index is pd.DatetimeIndex when False, and pd.IntervalIndex when True.
|
|
78
|
+
This is an experimental feature which may be removed without warning.
|
|
79
|
+
map_variables : bool, default : True
|
|
80
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
81
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
82
|
+
url : str, optional
|
|
83
|
+
Base URL of the Meteonorm API. The default is
|
|
84
|
+
:const:`pvlib.iotools.meteonorm.URL`.
|
|
85
|
+
|
|
86
|
+
Raises
|
|
87
|
+
------
|
|
88
|
+
requests.HTTPError
|
|
89
|
+
Raises an error when an incorrect request is made.
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
data : pd.DataFrame
|
|
94
|
+
Time series data. The index corresponds to the middle of the
|
|
95
|
+
interval unless ``interval_index`` is set to True.
|
|
96
|
+
meta : dict
|
|
97
|
+
Metadata.
|
|
98
|
+
|
|
99
|
+
See Also
|
|
100
|
+
--------
|
|
101
|
+
pvlib.iotools.get_meteonorm_forecast_precision,
|
|
102
|
+
pvlib.iotools.get_meteonorm_observation_realtime,
|
|
103
|
+
pvlib.iotools.get_meteonorm_observation_training,
|
|
104
|
+
pvlib.iotools.get_meteonorm_tmy
|
|
105
|
+
|
|
106
|
+
References
|
|
107
|
+
----------
|
|
108
|
+
.. [1] `Meteonorm
|
|
109
|
+
<https://meteonorm.com/>`_
|
|
110
|
+
.. [2] `Meteonorm API
|
|
111
|
+
<https://docs.meteonorm.com/docs/getting-started>`_
|
|
112
|
+
.. [3] `Meteonorm API reference
|
|
113
|
+
<https://docs.meteonorm.com/api>`_
|
|
114
|
+
"""
|
|
115
|
+
endpoint = "forecast/basic"
|
|
116
|
+
time_step = None
|
|
117
|
+
|
|
118
|
+
data, meta = _get_meteonorm(
|
|
119
|
+
latitude, longitude, start, end,
|
|
120
|
+
api_key, parameters, surface_tilt, surface_azimuth,
|
|
121
|
+
time_step, horizon, interval_index, map_variables,
|
|
122
|
+
url, endpoint)
|
|
123
|
+
return data, meta
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def get_meteonorm_forecast_precision(
|
|
127
|
+
latitude, longitude, start, end,
|
|
128
|
+
api_key, parameters="all", *,
|
|
129
|
+
surface_tilt=0, surface_azimuth=180,
|
|
130
|
+
time_step="15min", horizon="auto", interval_index=False,
|
|
131
|
+
map_variables=True, url=URL):
|
|
132
|
+
"""
|
|
133
|
+
Retrieve precision forecast data from Meteonorm.
|
|
134
|
+
|
|
135
|
+
The Meteonorm data options are described in [1]_ and the API is described
|
|
136
|
+
in [2]_. A detailed list of API options can be found in [3]_.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
latitude : float
|
|
141
|
+
In decimal degrees, north is positive (ISO 19115).
|
|
142
|
+
longitude: float
|
|
143
|
+
In decimal degrees, east is positive (ISO 19115).
|
|
144
|
+
start : datetime like or str
|
|
145
|
+
First timestamp of the requested period. If a timezone is not
|
|
146
|
+
specified, UTC is assumed. Relative date/time strings are
|
|
147
|
+
also allowed, e.g., 'now' or '+3hours'.
|
|
148
|
+
end : datetime like or str
|
|
149
|
+
Last timestamp of the requested period. If a timezone is not
|
|
150
|
+
specified, UTC is assumed. Relative date/time strings are
|
|
151
|
+
also allowed, e.g., 'now' or '+3hours'.
|
|
152
|
+
api_key : str
|
|
153
|
+
Meteonorm API key.
|
|
154
|
+
parameters : list or 'all', default : 'all'
|
|
155
|
+
List of parameters to request or `'all'` to get all parameters.
|
|
156
|
+
surface_tilt : float, default : 0
|
|
157
|
+
Tilt angle from horizontal plane.
|
|
158
|
+
surface_azimuth : float, default : 180
|
|
159
|
+
Orientation (azimuth angle) of the (fixed) plane. Clockwise from north
|
|
160
|
+
(north=0, east=90, south=180, west=270).
|
|
161
|
+
time_step : {'1min', '15min', '1h'}, default : '15min'
|
|
162
|
+
Frequency of the time series.
|
|
163
|
+
horizon : str or list, default : 'auto'
|
|
164
|
+
Specification of the horizon line. Can be either 'flat', 'auto', or
|
|
165
|
+
a list of 360 integer horizon elevation angles.
|
|
166
|
+
interval_index : bool, default : False
|
|
167
|
+
Index is pd.DatetimeIndex when False, and pd.IntervalIndex when True.
|
|
168
|
+
This is an experimental feature which may be removed without warning.
|
|
169
|
+
map_variables : bool, default : True
|
|
170
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
171
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
172
|
+
url : str, optional
|
|
173
|
+
Base URL of the Meteonorm API. The default is
|
|
174
|
+
:const:`pvlib.iotools.meteonorm.URL`.
|
|
175
|
+
|
|
176
|
+
Raises
|
|
177
|
+
------
|
|
178
|
+
requests.HTTPError
|
|
179
|
+
Raises an error when an incorrect request is made.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
data : pd.DataFrame
|
|
184
|
+
Time series data. The index corresponds to the middle of the
|
|
185
|
+
interval unless ``interval_index`` is set to True.
|
|
186
|
+
meta : dict
|
|
187
|
+
Metadata.
|
|
188
|
+
|
|
189
|
+
See Also
|
|
190
|
+
--------
|
|
191
|
+
pvlib.iotools.get_meteonorm_forecast_basic,
|
|
192
|
+
pvlib.iotools.get_meteonorm_observation_realtime,
|
|
193
|
+
pvlib.iotools.get_meteonorm_observation_training,
|
|
194
|
+
pvlib.iotools.get_meteonorm_tmy
|
|
195
|
+
|
|
196
|
+
References
|
|
197
|
+
----------
|
|
198
|
+
.. [1] `Meteonorm
|
|
199
|
+
<https://meteonorm.com/>`_
|
|
200
|
+
.. [2] `Meteonorm API
|
|
201
|
+
<https://docs.meteonorm.com/docs/getting-started>`_
|
|
202
|
+
.. [3] `Meteonorm API reference
|
|
203
|
+
<https://docs.meteonorm.com/api>`_
|
|
204
|
+
"""
|
|
205
|
+
endpoint = "forecast/precision"
|
|
206
|
+
|
|
207
|
+
data, meta = _get_meteonorm(
|
|
208
|
+
latitude, longitude, start, end,
|
|
209
|
+
api_key, parameters, surface_tilt, surface_azimuth,
|
|
210
|
+
time_step, horizon, interval_index, map_variables,
|
|
211
|
+
url, endpoint)
|
|
212
|
+
return data, meta
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def get_meteonorm_observation_realtime(
|
|
216
|
+
latitude, longitude, start, end,
|
|
217
|
+
api_key, parameters="all", *,
|
|
218
|
+
surface_tilt=0, surface_azimuth=180,
|
|
219
|
+
time_step="15min", horizon="auto", interval_index=False,
|
|
220
|
+
map_variables=True, url=URL):
|
|
221
|
+
"""
|
|
222
|
+
Retrieve near real-time observational data from Meteonorm.
|
|
223
|
+
|
|
224
|
+
The Meteonorm data options are described in [1]_ and the API is described
|
|
225
|
+
in [2]_. A detailed list of API options can be found in [3]_.
|
|
226
|
+
|
|
227
|
+
Near-real time is supports data access for the past 7-days.
|
|
228
|
+
|
|
229
|
+
Parameters
|
|
230
|
+
----------
|
|
231
|
+
latitude : float
|
|
232
|
+
In decimal degrees, north is positive (ISO 19115).
|
|
233
|
+
longitude: float
|
|
234
|
+
In decimal degrees, east is positive (ISO 19115).
|
|
235
|
+
start : datetime like
|
|
236
|
+
First timestamp of the requested period. If a timezone is not
|
|
237
|
+
specified, UTC is assumed.
|
|
238
|
+
end : datetime like
|
|
239
|
+
Last timestamp of the requested period. If a timezone is not
|
|
240
|
+
specified, UTC is assumed.
|
|
241
|
+
api_key : str
|
|
242
|
+
Meteonorm API key.
|
|
243
|
+
parameters : list or 'all', default : 'all'
|
|
244
|
+
List of parameters to request or `'all'` to get all parameters.
|
|
245
|
+
surface_tilt : float, default : 0
|
|
246
|
+
Tilt angle from horizontal plane.
|
|
247
|
+
surface_azimuth : float, default : 180
|
|
248
|
+
Orientation (azimuth angle) of the (fixed) plane. Clockwise from north
|
|
249
|
+
(north=0, east=90, south=180, west=270).
|
|
250
|
+
time_step : {'1min', '15min', '1h'}, default : '15min'
|
|
251
|
+
Frequency of the time series.
|
|
252
|
+
horizon : str or list, default : 'auto'
|
|
253
|
+
Specification of the horizon line. Can be either 'flat', 'auto', or
|
|
254
|
+
a list of 360 integer horizon elevation angles.
|
|
255
|
+
interval_index : bool, default : False
|
|
256
|
+
Index is pd.DatetimeIndex when False, and pd.IntervalIndex when True.
|
|
257
|
+
This is an experimental feature which may be removed without warning.
|
|
258
|
+
map_variables : bool, default : True
|
|
259
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
260
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
261
|
+
url : str, optional
|
|
262
|
+
Base URL of the Meteonorm API. The default is
|
|
263
|
+
:const:`pvlib.iotools.meteonorm.URL`.
|
|
264
|
+
|
|
265
|
+
Raises
|
|
266
|
+
------
|
|
267
|
+
requests.HTTPError
|
|
268
|
+
Raises an error when an incorrect request is made.
|
|
269
|
+
|
|
270
|
+
Returns
|
|
271
|
+
-------
|
|
272
|
+
data : pd.DataFrame
|
|
273
|
+
Time series data. The index corresponds to the middle of the
|
|
274
|
+
interval unless ``interval_index`` is set to True.
|
|
275
|
+
meta : dict
|
|
276
|
+
Metadata.
|
|
277
|
+
|
|
278
|
+
See Also
|
|
279
|
+
--------
|
|
280
|
+
pvlib.iotools.get_meteonorm_forecast_basic,
|
|
281
|
+
pvlib.iotools.get_meteonorm_forecast_precision,
|
|
282
|
+
pvlib.iotools.get_meteonorm_observation_training,
|
|
283
|
+
pvlib.iotools.get_meteonorm_tmy
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
References
|
|
287
|
+
----------
|
|
288
|
+
.. [1] `Meteonorm
|
|
289
|
+
<https://meteonorm.com/>`_
|
|
290
|
+
.. [2] `Meteonorm API
|
|
291
|
+
<https://docs.meteonorm.com/docs/getting-started>`_
|
|
292
|
+
.. [3] `Meteonorm API reference
|
|
293
|
+
<https://docs.meteonorm.com/api>`_
|
|
294
|
+
"""
|
|
295
|
+
endpoint = "observation/realtime"
|
|
296
|
+
|
|
297
|
+
data, meta = _get_meteonorm(
|
|
298
|
+
latitude, longitude, start, end,
|
|
299
|
+
api_key, parameters, surface_tilt, surface_azimuth,
|
|
300
|
+
time_step, horizon, interval_index, map_variables,
|
|
301
|
+
url, endpoint)
|
|
302
|
+
return data, meta
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def get_meteonorm_observation_training(
|
|
306
|
+
latitude, longitude, start, end,
|
|
307
|
+
api_key, parameters="all", *,
|
|
308
|
+
surface_tilt=0, surface_azimuth=180,
|
|
309
|
+
time_step="15min", horizon="auto", interval_index=False,
|
|
310
|
+
map_variables=True, url=URL):
|
|
311
|
+
"""
|
|
312
|
+
Retrieve historical observational data from Meteonorm.
|
|
313
|
+
|
|
314
|
+
The Meteonorm data options are described in [1]_ and the API is described
|
|
315
|
+
in [2]_. A detailed list of API options can be found in [3]_.
|
|
316
|
+
|
|
317
|
+
Parameters
|
|
318
|
+
----------
|
|
319
|
+
latitude : float
|
|
320
|
+
In decimal degrees, north is positive (ISO 19115).
|
|
321
|
+
longitude: float
|
|
322
|
+
In decimal degrees, east is positive (ISO 19115).
|
|
323
|
+
start : datetime like
|
|
324
|
+
First timestamp of the requested period. If a timezone is not
|
|
325
|
+
specified, UTC is assumed.
|
|
326
|
+
end : datetime like
|
|
327
|
+
Last timestamp of the requested period. If a timezone is not
|
|
328
|
+
specified, UTC is assumed.
|
|
329
|
+
api_key : str
|
|
330
|
+
Meteonorm API key.
|
|
331
|
+
parameters : list or 'all', default : 'all'
|
|
332
|
+
List of parameters to request or `'all'` to get all parameters.
|
|
333
|
+
surface_tilt : float, default : 0
|
|
334
|
+
Tilt angle from horizontal plane.
|
|
335
|
+
surface_azimuth : float, default : 180
|
|
336
|
+
Orientation (azimuth angle) of the (fixed) plane. Clockwise from north
|
|
337
|
+
(north=0, east=90, south=180, west=270).
|
|
338
|
+
time_step : {'1min', '15min', '1h'}, default : '15min'
|
|
339
|
+
Frequency of the time series.
|
|
340
|
+
horizon : str or list, default : 'auto'
|
|
341
|
+
Specification of the horizon line. Can be either 'flat', 'auto', or
|
|
342
|
+
a list of 360 integer horizon elevation angles.
|
|
343
|
+
interval_index : bool, default : False
|
|
344
|
+
Index is pd.DatetimeIndex when False, and pd.IntervalIndex when True.
|
|
345
|
+
This is an experimental feature which may be removed without warning.
|
|
346
|
+
map_variables : bool, default : True
|
|
347
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
348
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
349
|
+
url : str, optional
|
|
350
|
+
Base URL of the Meteonorm API. The default is
|
|
351
|
+
:const:`pvlib.iotools.meteonorm.URL`.
|
|
352
|
+
|
|
353
|
+
Raises
|
|
354
|
+
------
|
|
355
|
+
requests.HTTPError
|
|
356
|
+
Raises an error when an incorrect request is made.
|
|
357
|
+
|
|
358
|
+
Returns
|
|
359
|
+
-------
|
|
360
|
+
data : pd.DataFrame
|
|
361
|
+
Time series data. The index corresponds to the middle of the
|
|
362
|
+
interval unless ``interval_index`` is set to True.
|
|
363
|
+
meta : dict
|
|
364
|
+
Metadata.
|
|
365
|
+
|
|
366
|
+
Examples
|
|
367
|
+
--------
|
|
368
|
+
>>> # Retrieve historical time series data
|
|
369
|
+
>>> df, meta = pvlib.iotools.get_meteonorm_observation_training( # doctest: +SKIP
|
|
370
|
+
... latitude=50, longitude=10, # doctest: +SKIP
|
|
371
|
+
... start='2023-01-01', end='2025-01-01', # doctest: +SKIP
|
|
372
|
+
... api_key='redacted') # doctest: +SKIP
|
|
373
|
+
|
|
374
|
+
See Also
|
|
375
|
+
--------
|
|
376
|
+
pvlib.iotools.get_meteonorm_forecast_basic,
|
|
377
|
+
pvlib.iotools.get_meteonorm_forecast_precision,
|
|
378
|
+
pvlib.iotools.get_meteonorm_observation_realtime,
|
|
379
|
+
pvlib.iotools.get_meteonorm_tmy
|
|
380
|
+
|
|
381
|
+
References
|
|
382
|
+
----------
|
|
383
|
+
.. [1] `Meteonorm
|
|
384
|
+
<https://meteonorm.com/>`_
|
|
385
|
+
.. [2] `Meteonorm API
|
|
386
|
+
<https://docs.meteonorm.com/docs/getting-started>`_
|
|
387
|
+
.. [3] `Meteonorm API reference
|
|
388
|
+
<https://docs.meteonorm.com/api>`_
|
|
389
|
+
""" # noqa: E501
|
|
390
|
+
endpoint = "observation/training"
|
|
391
|
+
|
|
392
|
+
data, meta = _get_meteonorm(
|
|
393
|
+
latitude, longitude, start, end,
|
|
394
|
+
api_key, parameters, surface_tilt, surface_azimuth,
|
|
395
|
+
time_step, horizon, interval_index, map_variables,
|
|
396
|
+
url, endpoint)
|
|
397
|
+
return data, meta
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def get_meteonorm_tmy(
|
|
401
|
+
latitude, longitude, api_key, parameters="all", *,
|
|
402
|
+
surface_tilt=0, surface_azimuth=180,
|
|
403
|
+
time_step="1h", horizon="auto", terrain_situation="open",
|
|
404
|
+
albedo=None, turbidity="auto", random_seed=None,
|
|
405
|
+
clear_sky_radiation_model="esra", data_version="latest",
|
|
406
|
+
future_scenario=None, future_year=None, interval_index=False,
|
|
407
|
+
map_variables=True, url=URL):
|
|
408
|
+
"""
|
|
409
|
+
Retrieve TMY irradiance and weather data from Meteonorm.
|
|
410
|
+
|
|
411
|
+
The Meteonorm data options are described in [1]_ and the API is described
|
|
412
|
+
in [2]_. A detailed list of API options can be found in [3]_.
|
|
413
|
+
|
|
414
|
+
Parameters
|
|
415
|
+
----------
|
|
416
|
+
latitude : float
|
|
417
|
+
In decimal degrees, north is positive (ISO 19115).
|
|
418
|
+
longitude : float
|
|
419
|
+
In decimal degrees, east is positive (ISO 19115).
|
|
420
|
+
api_key : str
|
|
421
|
+
Meteonorm API key.
|
|
422
|
+
parameters : list or 'all', default : 'all'
|
|
423
|
+
List of parameters to request or `'all'` to get all parameters.
|
|
424
|
+
surface_tilt : float, default : 0
|
|
425
|
+
Tilt angle from horizontal plane.
|
|
426
|
+
surface_azimuth : float, default : 180
|
|
427
|
+
Orientation (azimuth angle) of the (fixed) plane. Clockwise from north
|
|
428
|
+
(north=0, east=90, south=180, west=270).
|
|
429
|
+
time_step : {'1min', '1h'}, default : '1h'
|
|
430
|
+
Frequency of the time series.
|
|
431
|
+
horizon : str, optional
|
|
432
|
+
Specification of the horizon line. Can be either 'flat' or 'auto', or
|
|
433
|
+
specified as a list of 360 integer horizon elevation angles.
|
|
434
|
+
'auto'.
|
|
435
|
+
terrain_situation : str, default : 'open'
|
|
436
|
+
Local terrain situation. Must be one of: ['open', 'depression',
|
|
437
|
+
'cold_air_lake', 'sea_lake', 'city', 'slope_south',
|
|
438
|
+
'slope_west_east'].
|
|
439
|
+
albedo : float, optional
|
|
440
|
+
Constant ground albedo. If no value is specified a baseline albedo of
|
|
441
|
+
0.2 is used and albedo changes due to snow fall are modeled. If a value
|
|
442
|
+
is specified, then snow fall is not modeled.
|
|
443
|
+
turbidity : list or 'auto', optional
|
|
444
|
+
List of 12 monthly mean atmospheric Linke turbidity values. The default
|
|
445
|
+
is 'auto'.
|
|
446
|
+
random_seed : int, optional
|
|
447
|
+
Random seed to be used for stochastic processes. Two identical requests
|
|
448
|
+
with the same random seed will yield identical results.
|
|
449
|
+
clear_sky_radiation_model : str, default : 'esra'
|
|
450
|
+
Which clearsky model to use. Must be either `'esra'` or `'solis'`.
|
|
451
|
+
data_version : str, default : 'latest'
|
|
452
|
+
Version of Meteonorm climatological data to be used.
|
|
453
|
+
future_scenario : str, optional
|
|
454
|
+
Future climate scenario.
|
|
455
|
+
future_year : int, optional
|
|
456
|
+
Central year for a 20-year reference period in the future.
|
|
457
|
+
interval_index : bool, default : False
|
|
458
|
+
Index is pd.DatetimeIndex when False, and pd.IntervalIndex when True.
|
|
459
|
+
This is an experimental feature which may be removed without warning.
|
|
460
|
+
map_variables : bool, default : True
|
|
461
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
462
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
463
|
+
url : str, optional.
|
|
464
|
+
Base URL of the Meteonorm API. `'climate/tmy'` is
|
|
465
|
+
appended to the URL. The default is:
|
|
466
|
+
:const:`pvlib.iotools.meteonorm.URL`.
|
|
467
|
+
|
|
468
|
+
Raises
|
|
469
|
+
------
|
|
470
|
+
requests.HTTPError
|
|
471
|
+
Raises an error when an incorrect request is made.
|
|
472
|
+
|
|
473
|
+
Returns
|
|
474
|
+
-------
|
|
475
|
+
data : pd.DataFrame
|
|
476
|
+
Time series data. The index corresponds to the middle of the
|
|
477
|
+
interval unless ``interval_index`` is set to True.
|
|
478
|
+
meta : dict
|
|
479
|
+
Metadata.
|
|
480
|
+
|
|
481
|
+
See Also
|
|
482
|
+
--------
|
|
483
|
+
pvlib.iotools.get_meteonorm_forecast_basic,
|
|
484
|
+
pvlib.iotools.get_meteonorm_forecast_precision,
|
|
485
|
+
pvlib.iotools.get_meteonorm_observation_realtime,
|
|
486
|
+
pvlib.iotools.get_meteonorm_observation_training
|
|
487
|
+
|
|
488
|
+
References
|
|
489
|
+
----------
|
|
490
|
+
.. [1] `Meteonorm
|
|
491
|
+
<https://meteonorm.com/>`_
|
|
492
|
+
.. [2] `Meteonorm API
|
|
493
|
+
<https://docs.meteonorm.com/docs/getting-started>`_
|
|
494
|
+
.. [3] `Meteonorm API reference
|
|
495
|
+
<https://docs.meteonorm.com/api>`_
|
|
496
|
+
"""
|
|
497
|
+
additional_params = {
|
|
498
|
+
"situation": terrain_situation,
|
|
499
|
+
"turbidity": turbidity,
|
|
500
|
+
"clear_sky_radiation_model": clear_sky_radiation_model,
|
|
501
|
+
"data_version": data_version,
|
|
502
|
+
"random_seed": random_seed,
|
|
503
|
+
"future_scenario": future_scenario,
|
|
504
|
+
"future_year": future_year,
|
|
505
|
+
"response_format": "json",
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if not isinstance(turbidity, str):
|
|
509
|
+
additional_params["turbidity"] = ",".join(map(str, turbidity))
|
|
510
|
+
|
|
511
|
+
endpoint = "climate/tmy"
|
|
512
|
+
|
|
513
|
+
start, end = None, None
|
|
514
|
+
|
|
515
|
+
data, meta = _get_meteonorm(
|
|
516
|
+
latitude, longitude, start, end,
|
|
517
|
+
api_key, parameters,
|
|
518
|
+
surface_tilt, surface_azimuth,
|
|
519
|
+
time_step, horizon,
|
|
520
|
+
interval_index, map_variables,
|
|
521
|
+
url, endpoint, **additional_params)
|
|
522
|
+
return data, meta
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def _get_meteonorm(
|
|
526
|
+
latitude, longitude, start, end,
|
|
527
|
+
api_key, parameters,
|
|
528
|
+
surface_tilt, surface_azimuth,
|
|
529
|
+
time_step, horizon,
|
|
530
|
+
interval_index, map_variables,
|
|
531
|
+
url, endpoint, **kwargs):
|
|
532
|
+
|
|
533
|
+
# Check for None type in case of TMY request
|
|
534
|
+
# Check for DateParseError in case of relative times, e.g., '+3hours'
|
|
535
|
+
# TODO: remove ValueError when our minimum pandas version is high enough
|
|
536
|
+
# to make it unnecessary (2.0?)
|
|
537
|
+
if (start is not None) & (start != 'now'):
|
|
538
|
+
try:
|
|
539
|
+
start = pd.Timestamp(start)
|
|
540
|
+
start = start.tz_localize("UTC") if start.tzinfo is None else start
|
|
541
|
+
start = start.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
542
|
+
except (ValueError, DateParseError):
|
|
543
|
+
pass
|
|
544
|
+
if (end is not None) & (end != 'now'):
|
|
545
|
+
try:
|
|
546
|
+
end = pd.Timestamp(end)
|
|
547
|
+
end = end.tz_localize("UTC") if end.tzinfo is None else end
|
|
548
|
+
end = end.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
549
|
+
except (ValueError, DateParseError):
|
|
550
|
+
pass
|
|
551
|
+
|
|
552
|
+
params = {
|
|
553
|
+
"lat": latitude,
|
|
554
|
+
"lon": longitude,
|
|
555
|
+
'start': start,
|
|
556
|
+
'end': end,
|
|
557
|
+
"parameters": parameters,
|
|
558
|
+
"surface_tilt": surface_tilt,
|
|
559
|
+
"surface_azimuth": surface_azimuth,
|
|
560
|
+
"horizon": horizon,
|
|
561
|
+
'frequency': TIME_STEP_MAP.get(time_step, time_step),
|
|
562
|
+
"response_format": "json",
|
|
563
|
+
**kwargs
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
# Allow specifying single parameters as string
|
|
567
|
+
if isinstance(parameters, str):
|
|
568
|
+
parameters = [parameters]
|
|
569
|
+
|
|
570
|
+
# allow the use of pvlib parameter names
|
|
571
|
+
parameter_dict = {v: k for k, v in VARIABLE_MAP.items()}
|
|
572
|
+
parameters = [parameter_dict.get(p, p) for p in parameters]
|
|
573
|
+
# convert list to string with values separated by commas
|
|
574
|
+
params["parameters"] = ",".join(parameters)
|
|
575
|
+
|
|
576
|
+
if not isinstance(horizon, str):
|
|
577
|
+
params["horizon"] = ",".join(map(str, horizon))
|
|
578
|
+
|
|
579
|
+
headers = {"Authorization": f"Bearer {api_key}"}
|
|
580
|
+
|
|
581
|
+
response = requests.get(
|
|
582
|
+
urljoin(url, endpoint), headers=headers, params=params
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
if not response.ok:
|
|
586
|
+
# response.raise_for_status() does not give a useful error message
|
|
587
|
+
raise requests.HTTPError(
|
|
588
|
+
"Meteonorm API returned an error: "
|
|
589
|
+
+ response.json()["error"]["message"]
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
data, meta = _parse_meteonorm(response, interval_index, map_variables)
|
|
593
|
+
|
|
594
|
+
return data, meta
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def _parse_meteonorm(response, interval_index, map_variables):
|
|
598
|
+
data_json = response.json()["values"]
|
|
599
|
+
# identify empty columns
|
|
600
|
+
empty_columns = [k for k, v in data_json.items() if v is None]
|
|
601
|
+
# remove empty columns
|
|
602
|
+
_ = [data_json.pop(k) for k in empty_columns]
|
|
603
|
+
|
|
604
|
+
data = pd.DataFrame(data_json)
|
|
605
|
+
|
|
606
|
+
# xxx: experimental feature - see parameter description
|
|
607
|
+
data.index = pd.IntervalIndex.from_arrays(
|
|
608
|
+
left=pd.to_datetime(response.json()["start_times"]),
|
|
609
|
+
right=pd.to_datetime(response.json()["end_times"]),
|
|
610
|
+
closed="left",
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
if not interval_index:
|
|
614
|
+
data.index = data.index.mid
|
|
615
|
+
|
|
616
|
+
meta = response.json()["meta"]
|
|
617
|
+
|
|
618
|
+
if map_variables:
|
|
619
|
+
data = data.rename(columns=VARIABLE_MAP)
|
|
620
|
+
meta["latitude"] = meta.pop("lat")
|
|
621
|
+
meta["longitude"] = meta.pop("lon")
|
|
622
|
+
|
|
623
|
+
return data, meta
|