pvlib 0.12.0__py3-none-any.whl → 0.12.1a1__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/atmosphere.py +40 -31
- pvlib/iotools/__init__.py +6 -0
- pvlib/iotools/psm4.py +819 -0
- pvlib/irradiance.py +24 -15
- pvlib/ivtools/sdm/__init__.py +20 -0
- pvlib/ivtools/sdm/_fit_desoto_pvsyst_sandia.py +585 -0
- pvlib/ivtools/sdm/cec.py +93 -0
- pvlib/ivtools/sdm/desoto.py +401 -0
- pvlib/ivtools/sdm/pvsyst.py +630 -0
- pvlib/modelchain.py +1 -1
- pvlib/pvsystem.py +109 -57
- pvlib/spectrum/irradiance.py +2 -1
- {pvlib-0.12.0.dist-info → pvlib-0.12.1a1.dist-info}/METADATA +2 -3
- {pvlib-0.12.0.dist-info → pvlib-0.12.1a1.dist-info}/RECORD +18 -13
- {pvlib-0.12.0.dist-info → pvlib-0.12.1a1.dist-info}/WHEEL +1 -1
- pvlib/ivtools/sdm.py +0 -1379
- {pvlib-0.12.0.dist-info → pvlib-0.12.1a1.dist-info}/licenses/AUTHORS.md +0 -0
- {pvlib-0.12.0.dist-info → pvlib-0.12.1a1.dist-info}/licenses/LICENSE +0 -0
- {pvlib-0.12.0.dist-info → pvlib-0.12.1a1.dist-info}/top_level.txt +0 -0
pvlib/iotools/psm4.py
ADDED
|
@@ -0,0 +1,819 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Functions for reading and retrieving data from NSRDB PSM4. See:
|
|
3
|
+
https://developer.nrel.gov/docs/solar/nsrdb/nsrdb-GOES-aggregated-v4-0-0-download/
|
|
4
|
+
https://developer.nrel.gov/docs/solar/nsrdb/nsrdb-GOES-tmy-v4-0-0-download/
|
|
5
|
+
https://developer.nrel.gov/docs/solar/nsrdb/nsrdb-GOES-conus-v4-0-0-download/
|
|
6
|
+
https://developer.nrel.gov/docs/solar/nsrdb/nsrdb-GOES-full-disc-v4-0-0-download/
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import io
|
|
10
|
+
from urllib.parse import urljoin
|
|
11
|
+
import requests
|
|
12
|
+
import pandas as pd
|
|
13
|
+
from json import JSONDecodeError
|
|
14
|
+
|
|
15
|
+
NSRDB_API_BASE = "https://developer.nrel.gov/api/nsrdb/v2/solar/"
|
|
16
|
+
PSM4_AGG_ENDPOINT = "nsrdb-GOES-aggregated-v4-0-0-download.csv"
|
|
17
|
+
PSM4_TMY_ENDPOINT = "nsrdb-GOES-tmy-v4-0-0-download.csv"
|
|
18
|
+
PSM4_CON_ENDPOINT = "nsrdb-GOES-conus-v4-0-0-download.csv"
|
|
19
|
+
PSM4_FUL_ENDPOINT = "nsrdb-GOES-full-disc-v4-0-0-download.csv"
|
|
20
|
+
PSM4_AGG_URL = urljoin(NSRDB_API_BASE, PSM4_AGG_ENDPOINT)
|
|
21
|
+
PSM4_TMY_URL = urljoin(NSRDB_API_BASE, PSM4_TMY_ENDPOINT)
|
|
22
|
+
PSM4_CON_URL = urljoin(NSRDB_API_BASE, PSM4_CON_ENDPOINT)
|
|
23
|
+
PSM4_FUL_URL = urljoin(NSRDB_API_BASE, PSM4_FUL_ENDPOINT)
|
|
24
|
+
|
|
25
|
+
PARAMETERS = (
|
|
26
|
+
'air_temperature', 'dew_point', 'dhi', 'dni', 'ghi', 'surface_albedo',
|
|
27
|
+
'surface_pressure', 'wind_direction', 'wind_speed')
|
|
28
|
+
PVLIB_PYTHON = 'pvlib python'
|
|
29
|
+
|
|
30
|
+
# Dictionary mapping PSM4 response names to pvlib names
|
|
31
|
+
VARIABLE_MAP = {
|
|
32
|
+
'GHI': 'ghi',
|
|
33
|
+
'DHI': 'dhi',
|
|
34
|
+
'DNI': 'dni',
|
|
35
|
+
'Clearsky GHI': 'ghi_clear',
|
|
36
|
+
'Clearsky DHI': 'dhi_clear',
|
|
37
|
+
'Clearsky DNI': 'dni_clear',
|
|
38
|
+
'Solar Zenith Angle': 'solar_zenith',
|
|
39
|
+
'Temperature': 'temp_air',
|
|
40
|
+
'Dew Point': 'temp_dew',
|
|
41
|
+
'Relative Humidity': 'relative_humidity',
|
|
42
|
+
'Pressure': 'pressure',
|
|
43
|
+
'Wind Speed': 'wind_speed',
|
|
44
|
+
'Wind Direction': 'wind_direction',
|
|
45
|
+
'Surface Albedo': 'albedo',
|
|
46
|
+
'Precipitable Water': 'precipitable_water',
|
|
47
|
+
'AOD': 'aod',
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# Dictionary mapping pvlib names to PSM4 request names
|
|
51
|
+
# Note, PSM4 uses different names for the same variables in the
|
|
52
|
+
# response and the request
|
|
53
|
+
REQUEST_VARIABLE_MAP = {
|
|
54
|
+
'ghi': 'ghi',
|
|
55
|
+
'dhi': 'dhi',
|
|
56
|
+
'dni': 'dni',
|
|
57
|
+
'ghi_clear': 'clearsky_ghi',
|
|
58
|
+
'dhi_clear': 'clearsky_dhi',
|
|
59
|
+
'dni_clear': 'clearsky_dni',
|
|
60
|
+
'solar_zenith': 'solar_zenith_angle',
|
|
61
|
+
'temp_air': 'air_temperature',
|
|
62
|
+
'temp_dew': 'dew_point',
|
|
63
|
+
'relative_humidity': 'relative_humidity',
|
|
64
|
+
'pressure': 'surface_pressure',
|
|
65
|
+
'wind_speed': 'wind_speed',
|
|
66
|
+
'wind_direction': 'wind_direction',
|
|
67
|
+
'albedo': 'surface_albedo',
|
|
68
|
+
'precipitable_water': 'total_precipitable_water',
|
|
69
|
+
'aod': 'aod',
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_nsrdb_psm4_aggregated(latitude, longitude, api_key, email,
|
|
74
|
+
year='2023', time_step=60,
|
|
75
|
+
parameters=PARAMETERS, leap_day=True,
|
|
76
|
+
full_name=PVLIB_PYTHON,
|
|
77
|
+
affiliation=PVLIB_PYTHON,
|
|
78
|
+
utc=False, map_variables=True, url=None,
|
|
79
|
+
timeout=30):
|
|
80
|
+
"""
|
|
81
|
+
Retrieve NSRDB PSM4 timeseries weather data from the PSM4 NSRDB GOES
|
|
82
|
+
Aggregated v4 API.
|
|
83
|
+
|
|
84
|
+
The NSRDB is described in [1]_ and the PSM4 NSRDB GOES Aggregated v4 API is
|
|
85
|
+
described in [2]_,.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
latitude : float or int
|
|
90
|
+
in decimal degrees, between -90 and 90, north is positive
|
|
91
|
+
longitude : float or int
|
|
92
|
+
in decimal degrees, between -180 and 180, east is positive
|
|
93
|
+
api_key : str
|
|
94
|
+
NREL Developer Network API key
|
|
95
|
+
email : str
|
|
96
|
+
NREL API uses this to automatically communicate messages back
|
|
97
|
+
to the user only if necessary
|
|
98
|
+
year : str, default '2023'
|
|
99
|
+
PSM4 API parameter specifing year (e.g. ``2023``) to download. The
|
|
100
|
+
allowed values update periodically, so consult the NSRDB reference
|
|
101
|
+
below for the current set of options. Called ``names`` in NSRDB API.
|
|
102
|
+
time_step : int, {60, 30}
|
|
103
|
+
time step in minutes, must be 60 or 30 for PSM4 Aggregated. Called
|
|
104
|
+
``interval`` in NSRDB API.
|
|
105
|
+
parameters : list of str, optional
|
|
106
|
+
meteorological fields to fetch. If not specified, defaults to
|
|
107
|
+
``pvlib.iotools.psm4.PARAMETERS``. See reference [2]_ for a list of
|
|
108
|
+
available fields. Alternatively, pvlib names may also be used (e.g.
|
|
109
|
+
'ghi' rather than 'GHI'); see :const:`REQUEST_VARIABLE_MAP`. To
|
|
110
|
+
retrieve all available fields, set ``parameters=[]``.
|
|
111
|
+
leap_day : bool, default : True
|
|
112
|
+
include leap day in the results
|
|
113
|
+
full_name : str, default 'pvlib python'
|
|
114
|
+
optional
|
|
115
|
+
affiliation : str, default 'pvlib python'
|
|
116
|
+
optional
|
|
117
|
+
utc: bool, default : False
|
|
118
|
+
retrieve data with timestamps converted to UTC. False returns
|
|
119
|
+
timestamps in local standard time of the selected location
|
|
120
|
+
map_variables : bool, default True
|
|
121
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
122
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
123
|
+
url : str, optional
|
|
124
|
+
Full API endpoint URL. If not specified, the PSM4 GOES Aggregated v4
|
|
125
|
+
URL is used.
|
|
126
|
+
timeout : int, default 30
|
|
127
|
+
time in seconds to wait for server response before timeout
|
|
128
|
+
|
|
129
|
+
Returns
|
|
130
|
+
-------
|
|
131
|
+
data : pandas.DataFrame
|
|
132
|
+
timeseries data from NREL PSM4
|
|
133
|
+
metadata : dict
|
|
134
|
+
metadata from NREL PSM4 about the record, see
|
|
135
|
+
:func:`pvlib.iotools.parse_nsrdb_psm4` for fields
|
|
136
|
+
|
|
137
|
+
Raises
|
|
138
|
+
------
|
|
139
|
+
requests.HTTPError
|
|
140
|
+
if the request response status is not ok, then the ``'errors'`` field
|
|
141
|
+
from the JSON response or any error message in the content will be
|
|
142
|
+
raised as an exception, for example if the `api_key` was rejected or if
|
|
143
|
+
the coordinates were not found in the NSRDB
|
|
144
|
+
|
|
145
|
+
Notes
|
|
146
|
+
-----
|
|
147
|
+
The required NREL developer key, `api_key`, is available for free by
|
|
148
|
+
registering at the `NREL Developer Network <https://developer.nrel.gov/>`_.
|
|
149
|
+
|
|
150
|
+
.. warning:: The "DEMO_KEY" `api_key` is severely rate limited and may
|
|
151
|
+
result in rejected requests.
|
|
152
|
+
|
|
153
|
+
.. warning:: PSM4 is limited to data found in the NSRDB, please consult
|
|
154
|
+
the references below for locations with available data. Additionally,
|
|
155
|
+
querying data with < 30-minute resolution uses a different API endpoint
|
|
156
|
+
with fewer available fields (see [4]_).
|
|
157
|
+
|
|
158
|
+
See Also
|
|
159
|
+
--------
|
|
160
|
+
pvlib.iotools.get_nsrdb_psm4_tmy, pvlib.iotools.get_nsrdb_psm4_conus,
|
|
161
|
+
pvlib.iotools.get_nsrdb_psm4_full_disc, pvlib.iotools.read_nsrdb_psm4,
|
|
162
|
+
pvlib.iotools.parse_nsrdb_psm4
|
|
163
|
+
|
|
164
|
+
References
|
|
165
|
+
----------
|
|
166
|
+
|
|
167
|
+
.. [1] `NREL National Solar Radiation Database (NSRDB)
|
|
168
|
+
<https://nsrdb.nrel.gov/>`_
|
|
169
|
+
.. [2] `NSRDB GOES Aggregated V4.0.0
|
|
170
|
+
<https://developer.nrel.gov/docs/solar/nsrdb/nsrdb-GOES-aggregated-v4-0-0-download/>`_
|
|
171
|
+
"""
|
|
172
|
+
# The well know text (WKT) representation of geometry notation is strict.
|
|
173
|
+
# A POINT object is a string with longitude first, then the latitude, with
|
|
174
|
+
# four decimals each, and exactly one space between them.
|
|
175
|
+
longitude = ('%9.4f' % longitude).strip()
|
|
176
|
+
latitude = ('%8.4f' % latitude).strip()
|
|
177
|
+
# TODO: make format_WKT(object_type, *args) in tools.py
|
|
178
|
+
|
|
179
|
+
# convert to string to accomodate integer years being passed in
|
|
180
|
+
year = str(year)
|
|
181
|
+
|
|
182
|
+
# convert pvlib names in parameters to PSM4 convention
|
|
183
|
+
parameters = [REQUEST_VARIABLE_MAP.get(a, a) for a in parameters]
|
|
184
|
+
|
|
185
|
+
# required query-string parameters for request to PSM4 API
|
|
186
|
+
params = {
|
|
187
|
+
'api_key': api_key,
|
|
188
|
+
'full_name': full_name,
|
|
189
|
+
'email': email,
|
|
190
|
+
'affiliation': affiliation,
|
|
191
|
+
'reason': PVLIB_PYTHON,
|
|
192
|
+
'mailing_list': 'false',
|
|
193
|
+
'wkt': 'POINT(%s %s)' % (longitude, latitude),
|
|
194
|
+
'names': year,
|
|
195
|
+
'attributes': ','.join(parameters),
|
|
196
|
+
'leap_day': str(leap_day).lower(),
|
|
197
|
+
'utc': str(utc).lower(),
|
|
198
|
+
'interval': time_step
|
|
199
|
+
}
|
|
200
|
+
# request CSV download from NREL PSM4
|
|
201
|
+
if url is None:
|
|
202
|
+
url = PSM4_AGG_URL
|
|
203
|
+
|
|
204
|
+
response = requests.get(url, params=params, timeout=timeout)
|
|
205
|
+
if not response.ok:
|
|
206
|
+
# if the API key is rejected, then the response status will be 403
|
|
207
|
+
# Forbidden, and then the error is in the content and there is no JSON
|
|
208
|
+
try:
|
|
209
|
+
errors = response.json()['errors']
|
|
210
|
+
except JSONDecodeError:
|
|
211
|
+
errors = response.content.decode('utf-8')
|
|
212
|
+
raise requests.HTTPError(errors, response=response)
|
|
213
|
+
# the CSV is in the response content as a UTF-8 bytestring
|
|
214
|
+
# to use pandas we need to create a file buffer from the response
|
|
215
|
+
fbuf = io.StringIO(response.content.decode('utf-8'))
|
|
216
|
+
return parse_nsrdb_psm4(fbuf, map_variables)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def get_nsrdb_psm4_tmy(latitude, longitude, api_key, email, year='tmy',
|
|
220
|
+
time_step=60, parameters=PARAMETERS, leap_day=False,
|
|
221
|
+
full_name=PVLIB_PYTHON, affiliation=PVLIB_PYTHON,
|
|
222
|
+
utc=False, map_variables=True, url=None, timeout=30):
|
|
223
|
+
"""
|
|
224
|
+
Retrieve NSRDB PSM4 timeseries weather data from the PSM4 NSRDB GOES
|
|
225
|
+
TMY v4 API.
|
|
226
|
+
|
|
227
|
+
The NSRDB is described in [1]_ and the PSM4 NSRDB GOES TMY v4 API is
|
|
228
|
+
described in [2]_,.
|
|
229
|
+
|
|
230
|
+
Parameters
|
|
231
|
+
----------
|
|
232
|
+
latitude : float or int
|
|
233
|
+
in decimal degrees, between -90 and 90, north is positive
|
|
234
|
+
longitude : float or int
|
|
235
|
+
in decimal degrees, between -180 and 180, east is positive
|
|
236
|
+
api_key : str
|
|
237
|
+
NREL Developer Network API key
|
|
238
|
+
email : str
|
|
239
|
+
NREL API uses this to automatically communicate messages back
|
|
240
|
+
to the user only if necessary
|
|
241
|
+
year : str, default 'tmy'
|
|
242
|
+
PSM4 API parameter specifing TMY variant to download (e.g. ``'tmy'``
|
|
243
|
+
or ``'tgy-2022'``). The allowed values update periodically, so
|
|
244
|
+
consult the NSRDB references below for the current set of options.
|
|
245
|
+
Called ``names`` in NSRDB API.
|
|
246
|
+
time_step : int, {60}
|
|
247
|
+
time step in minutes. Must be 60 for typical year requests. Called
|
|
248
|
+
``interval`` in NSRDB API.
|
|
249
|
+
parameters : list of str, optional
|
|
250
|
+
meteorological fields to fetch. If not specified, defaults to
|
|
251
|
+
``pvlib.iotools.psm4.PARAMETERS``. See reference [2]_ for a list of
|
|
252
|
+
available fields. Alternatively, pvlib names may also be used (e.g.
|
|
253
|
+
'ghi' rather than 'GHI'); see :const:`REQUEST_VARIABLE_MAP`. To
|
|
254
|
+
retrieve all available fields, set ``parameters=[]``.
|
|
255
|
+
leap_day : bool, default : False
|
|
256
|
+
Include leap day in the results. Ignored for tmy/tgy/tdy requests.
|
|
257
|
+
full_name : str, default 'pvlib python'
|
|
258
|
+
optional
|
|
259
|
+
affiliation : str, default 'pvlib python'
|
|
260
|
+
optional
|
|
261
|
+
utc: bool, default : False
|
|
262
|
+
retrieve data with timestamps converted to UTC. False returns
|
|
263
|
+
timestamps in local standard time of the selected location
|
|
264
|
+
map_variables : bool, default True
|
|
265
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
266
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
267
|
+
url : str, optional
|
|
268
|
+
Full API endpoint URL. If not specified, the PSM4 GOES TMY v4 URL is
|
|
269
|
+
used.
|
|
270
|
+
timeout : int, default 30
|
|
271
|
+
time in seconds to wait for server response before timeout
|
|
272
|
+
|
|
273
|
+
Returns
|
|
274
|
+
-------
|
|
275
|
+
data : pandas.DataFrame
|
|
276
|
+
timeseries data from NREL PSM4
|
|
277
|
+
metadata : dict
|
|
278
|
+
metadata from NREL PSM4 about the record, see
|
|
279
|
+
:func:`pvlib.iotools.parse_nsrdb_psm4` for fields
|
|
280
|
+
|
|
281
|
+
Raises
|
|
282
|
+
------
|
|
283
|
+
requests.HTTPError
|
|
284
|
+
if the request response status is not ok, then the ``'errors'`` field
|
|
285
|
+
from the JSON response or any error message in the content will be
|
|
286
|
+
raised as an exception, for example if the `api_key` was rejected or if
|
|
287
|
+
the coordinates were not found in the NSRDB
|
|
288
|
+
|
|
289
|
+
Notes
|
|
290
|
+
-----
|
|
291
|
+
The required NREL developer key, `api_key`, is available for free by
|
|
292
|
+
registering at the `NREL Developer Network <https://developer.nrel.gov/>`_.
|
|
293
|
+
|
|
294
|
+
.. warning:: The "DEMO_KEY" `api_key` is severely rate limited and may
|
|
295
|
+
result in rejected requests.
|
|
296
|
+
|
|
297
|
+
.. warning:: PSM4 is limited to data found in the NSRDB, please consult
|
|
298
|
+
the references below for locations with available data. Additionally,
|
|
299
|
+
querying data with < 30-minute resolution uses a different API endpoint
|
|
300
|
+
with fewer available fields (see [4]_).
|
|
301
|
+
|
|
302
|
+
See Also
|
|
303
|
+
--------
|
|
304
|
+
pvlib.iotools.get_nsrdb_psm4_aggregated,
|
|
305
|
+
pvlib.iotools.get_nsrdb_psm4_conus, pvlib.iotools.get_nsrdb_psm4_full_disc,
|
|
306
|
+
pvlib.iotools.read_nsrdb_psm4,pvlib.iotools.parse_nsrdb_psm4
|
|
307
|
+
|
|
308
|
+
References
|
|
309
|
+
----------
|
|
310
|
+
|
|
311
|
+
.. [1] `NREL National Solar Radiation Database (NSRDB)
|
|
312
|
+
<https://nsrdb.nrel.gov/>`_
|
|
313
|
+
.. [2] `NSRDB GOES Tmy V4.0.0
|
|
314
|
+
<https://developer.nrel.gov/docs/solar/nsrdb/nsrdb-GOES-tmy-v4-0-0-download/>`_
|
|
315
|
+
"""
|
|
316
|
+
# The well know text (WKT) representation of geometry notation is strict.
|
|
317
|
+
# A POINT object is a string with longitude first, then the latitude, with
|
|
318
|
+
# four decimals each, and exactly one space between them.
|
|
319
|
+
longitude = ('%9.4f' % longitude).strip()
|
|
320
|
+
latitude = ('%8.4f' % latitude).strip()
|
|
321
|
+
# TODO: make format_WKT(object_type, *args) in tools.py
|
|
322
|
+
|
|
323
|
+
# convert to string to accomodate integer years being passed in
|
|
324
|
+
year = str(year)
|
|
325
|
+
|
|
326
|
+
# convert pvlib names in parameters to PSM4 convention
|
|
327
|
+
parameters = [REQUEST_VARIABLE_MAP.get(a, a) for a in parameters]
|
|
328
|
+
|
|
329
|
+
# required query-string parameters for request to PSM4 API
|
|
330
|
+
params = {
|
|
331
|
+
'api_key': api_key,
|
|
332
|
+
'full_name': full_name,
|
|
333
|
+
'email': email,
|
|
334
|
+
'affiliation': affiliation,
|
|
335
|
+
'reason': PVLIB_PYTHON,
|
|
336
|
+
'mailing_list': 'false',
|
|
337
|
+
'wkt': 'POINT(%s %s)' % (longitude, latitude),
|
|
338
|
+
'names': year,
|
|
339
|
+
'attributes': ','.join(parameters),
|
|
340
|
+
'leap_day': str(leap_day).lower(),
|
|
341
|
+
'utc': str(utc).lower(),
|
|
342
|
+
'interval': time_step
|
|
343
|
+
}
|
|
344
|
+
# request CSV download from NREL PSM4
|
|
345
|
+
if url is None:
|
|
346
|
+
url = PSM4_TMY_URL
|
|
347
|
+
|
|
348
|
+
response = requests.get(url, params=params, timeout=timeout)
|
|
349
|
+
if not response.ok:
|
|
350
|
+
# if the API key is rejected, then the response status will be 403
|
|
351
|
+
# Forbidden, and then the error is in the content and there is no JSON
|
|
352
|
+
try:
|
|
353
|
+
errors = response.json()['errors']
|
|
354
|
+
except JSONDecodeError:
|
|
355
|
+
errors = response.content.decode('utf-8')
|
|
356
|
+
raise requests.HTTPError(errors, response=response)
|
|
357
|
+
# the CSV is in the response content as a UTF-8 bytestring
|
|
358
|
+
# to use pandas we need to create a file buffer from the response
|
|
359
|
+
fbuf = io.StringIO(response.content.decode('utf-8'))
|
|
360
|
+
return parse_nsrdb_psm4(fbuf, map_variables)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def get_nsrdb_psm4_conus(latitude, longitude, api_key, email, year='2023',
|
|
364
|
+
time_step=60, parameters=PARAMETERS, leap_day=True,
|
|
365
|
+
full_name=PVLIB_PYTHON, affiliation=PVLIB_PYTHON,
|
|
366
|
+
utc=False, map_variables=True, url=None, timeout=30):
|
|
367
|
+
"""
|
|
368
|
+
Retrieve NSRDB PSM4 timeseries weather data from the PSM4 NSRDB GOES CONUS
|
|
369
|
+
v4 API.
|
|
370
|
+
|
|
371
|
+
The NSRDB is described in [1]_ and the PSM4 NSRDB GOES CONUS v4 API is
|
|
372
|
+
described in [2]_,.
|
|
373
|
+
|
|
374
|
+
Parameters
|
|
375
|
+
----------
|
|
376
|
+
latitude : float or int
|
|
377
|
+
in decimal degrees, between -90 and 90, north is positive
|
|
378
|
+
longitude : float or int
|
|
379
|
+
in decimal degrees, between -180 and 180, east is positive
|
|
380
|
+
api_key : str
|
|
381
|
+
NREL Developer Network API key
|
|
382
|
+
email : str
|
|
383
|
+
NREL API uses this to automatically communicate messages back
|
|
384
|
+
to the user only if necessary
|
|
385
|
+
year : str, default '2023'
|
|
386
|
+
PSM4 API parameter specifing year (e.g. ``2023``) to download. The
|
|
387
|
+
allowed values update periodically, so consult the NSRDB reference
|
|
388
|
+
below for the current set of options. Called ``names`` in NSRDB API.
|
|
389
|
+
time_step : int, {60, 5, 15, 30}
|
|
390
|
+
time step in minutes. Called ``interval`` in NSRDB API.
|
|
391
|
+
parameters : list of str, optional
|
|
392
|
+
meteorological fields to fetch. If not specified, defaults to
|
|
393
|
+
``pvlib.iotools.psm4.PARAMETERS``. See reference [2]_ for a list of
|
|
394
|
+
available fields. Alternatively, pvlib names may also be used (e.g.
|
|
395
|
+
'ghi' rather than 'GHI'); see :const:`REQUEST_VARIABLE_MAP`. To
|
|
396
|
+
retrieve all available fields, set ``parameters=[]``.
|
|
397
|
+
leap_day : bool, default : True
|
|
398
|
+
include leap day in the results
|
|
399
|
+
full_name : str, default 'pvlib python'
|
|
400
|
+
optional
|
|
401
|
+
affiliation : str, default 'pvlib python'
|
|
402
|
+
optional
|
|
403
|
+
utc: bool, default : False
|
|
404
|
+
retrieve data with timestamps converted to UTC. False returns
|
|
405
|
+
timestamps in local standard time of the selected location
|
|
406
|
+
map_variables : bool, default True
|
|
407
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
408
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
409
|
+
url : str, optional
|
|
410
|
+
Full API endpoint URL. If not specified, the PSM4 GOES CONUS v4 URL is
|
|
411
|
+
used.
|
|
412
|
+
timeout : int, default 30
|
|
413
|
+
time in seconds to wait for server response before timeout
|
|
414
|
+
|
|
415
|
+
Returns
|
|
416
|
+
-------
|
|
417
|
+
data : pandas.DataFrame
|
|
418
|
+
timeseries data from NREL PSM4
|
|
419
|
+
metadata : dict
|
|
420
|
+
metadata from NREL PSM4 about the record, see
|
|
421
|
+
:func:`pvlib.iotools.parse_nsrdb_psm4` for fields
|
|
422
|
+
|
|
423
|
+
Raises
|
|
424
|
+
------
|
|
425
|
+
requests.HTTPError
|
|
426
|
+
if the request response status is not ok, then the ``'errors'`` field
|
|
427
|
+
from the JSON response or any error message in the content will be
|
|
428
|
+
raised as an exception, for example if the `api_key` was rejected or if
|
|
429
|
+
the coordinates were not found in the NSRDB
|
|
430
|
+
|
|
431
|
+
Notes
|
|
432
|
+
-----
|
|
433
|
+
The required NREL developer key, `api_key`, is available for free by
|
|
434
|
+
registering at the `NREL Developer Network <https://developer.nrel.gov/>`_.
|
|
435
|
+
|
|
436
|
+
.. warning:: The "DEMO_KEY" `api_key` is severely rate limited and may
|
|
437
|
+
result in rejected requests.
|
|
438
|
+
|
|
439
|
+
.. warning:: PSM4 is limited to data found in the NSRDB, please consult
|
|
440
|
+
the references below for locations with available data. Additionally,
|
|
441
|
+
querying data with < 30-minute resolution uses a different API endpoint
|
|
442
|
+
with fewer available fields (see [4]_).
|
|
443
|
+
|
|
444
|
+
See Also
|
|
445
|
+
--------
|
|
446
|
+
pvlib.iotools.get_nsrdb_psm4_aggregated,
|
|
447
|
+
pvlib.iotools.get_nsrdb_psm4_tmy, pvlib.iotools.get_nsrdb_psm4_full_disc,
|
|
448
|
+
pvlib.iotools.read_nsrdb_psm4, pvlib.iotools.parse_nsrdb_psm4
|
|
449
|
+
|
|
450
|
+
References
|
|
451
|
+
----------
|
|
452
|
+
|
|
453
|
+
.. [1] `NREL National Solar Radiation Database (NSRDB)
|
|
454
|
+
<https://nsrdb.nrel.gov/>`_
|
|
455
|
+
.. [2] `NSRDB GOES Conus V4.0.0
|
|
456
|
+
<https://developer.nrel.gov/docs/solar/nsrdb/nsrdb-GOES-conus-v4-0-0-download/>`_
|
|
457
|
+
"""
|
|
458
|
+
# The well know text (WKT) representation of geometry notation is strict.
|
|
459
|
+
# A POINT object is a string with longitude first, then the latitude, with
|
|
460
|
+
# four decimals each, and exactly one space between them.
|
|
461
|
+
longitude = ('%9.4f' % longitude).strip()
|
|
462
|
+
latitude = ('%8.4f' % latitude).strip()
|
|
463
|
+
# TODO: make format_WKT(object_type, *args) in tools.py
|
|
464
|
+
|
|
465
|
+
# convert to string to accomodate integer years being passed in
|
|
466
|
+
year = str(year)
|
|
467
|
+
|
|
468
|
+
# convert pvlib names in parameters to PSM4 convention
|
|
469
|
+
parameters = [REQUEST_VARIABLE_MAP.get(a, a) for a in parameters]
|
|
470
|
+
|
|
471
|
+
# required query-string parameters for request to PSM4 API
|
|
472
|
+
params = {
|
|
473
|
+
'api_key': api_key,
|
|
474
|
+
'full_name': full_name,
|
|
475
|
+
'email': email,
|
|
476
|
+
'affiliation': affiliation,
|
|
477
|
+
'reason': PVLIB_PYTHON,
|
|
478
|
+
'mailing_list': 'false',
|
|
479
|
+
'wkt': 'POINT(%s %s)' % (longitude, latitude),
|
|
480
|
+
'names': year,
|
|
481
|
+
'attributes': ','.join(parameters),
|
|
482
|
+
'leap_day': str(leap_day).lower(),
|
|
483
|
+
'utc': str(utc).lower(),
|
|
484
|
+
'interval': time_step
|
|
485
|
+
}
|
|
486
|
+
# request CSV download from NREL PSM4
|
|
487
|
+
if url is None:
|
|
488
|
+
url = PSM4_CON_URL
|
|
489
|
+
|
|
490
|
+
response = requests.get(url, params=params, timeout=timeout)
|
|
491
|
+
if not response.ok:
|
|
492
|
+
# if the API key is rejected, then the response status will be 403
|
|
493
|
+
# Forbidden, and then the error is in the content and there is no JSON
|
|
494
|
+
try:
|
|
495
|
+
errors = response.json()['errors']
|
|
496
|
+
except JSONDecodeError:
|
|
497
|
+
errors = response.content.decode('utf-8')
|
|
498
|
+
raise requests.HTTPError(errors, response=response)
|
|
499
|
+
# the CSV is in the response content as a UTF-8 bytestring
|
|
500
|
+
# to use pandas we need to create a file buffer from the response
|
|
501
|
+
fbuf = io.StringIO(response.content.decode('utf-8'))
|
|
502
|
+
return parse_nsrdb_psm4(fbuf, map_variables)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
def get_nsrdb_psm4_full_disc(latitude, longitude, api_key, email,
|
|
506
|
+
year='2023', time_step=60,
|
|
507
|
+
parameters=PARAMETERS, leap_day=True,
|
|
508
|
+
full_name=PVLIB_PYTHON,
|
|
509
|
+
affiliation=PVLIB_PYTHON, utc=False,
|
|
510
|
+
map_variables=True, url=None, timeout=30):
|
|
511
|
+
"""
|
|
512
|
+
Retrieve NSRDB PSM4 timeseries weather data from the PSM4 NSRDB GOES Full
|
|
513
|
+
Disc v4 API.
|
|
514
|
+
|
|
515
|
+
The NSRDB is described in [1]_ and the PSM4 NSRDB GOES Full Disc v4 API is
|
|
516
|
+
described in [2]_,.
|
|
517
|
+
|
|
518
|
+
Parameters
|
|
519
|
+
----------
|
|
520
|
+
latitude : float or int
|
|
521
|
+
in decimal degrees, between -90 and 90, north is positive
|
|
522
|
+
longitude : float or int
|
|
523
|
+
in decimal degrees, between -180 and 180, east is positive
|
|
524
|
+
api_key : str
|
|
525
|
+
NREL Developer Network API key
|
|
526
|
+
email : str
|
|
527
|
+
NREL API uses this to automatically communicate messages back
|
|
528
|
+
to the user only if necessary
|
|
529
|
+
year : str, default '2023'
|
|
530
|
+
PSM4 API parameter specifing year (e.g. ``2023``) to download. The
|
|
531
|
+
allowed values update periodically, so consult the NSRDB reference
|
|
532
|
+
below for the current set of options. Called ``names`` in NSRDB API.
|
|
533
|
+
time_step : int, {60, 10, 30}
|
|
534
|
+
time step in minutes, must be 10, 30 or 60. Called ``interval`` in
|
|
535
|
+
NSRDB API.
|
|
536
|
+
parameters : list of str, optional
|
|
537
|
+
meteorological fields to fetch. If not specified, defaults to
|
|
538
|
+
``pvlib.iotools.psm4.PARAMETERS``. See reference [2]_ for a list of
|
|
539
|
+
available fields. Alternatively, pvlib names may also be used (e.g.
|
|
540
|
+
'ghi' rather than 'GHI'); see :const:`REQUEST_VARIABLE_MAP`. To
|
|
541
|
+
retrieve all available fields, set ``parameters=[]``.
|
|
542
|
+
leap_day : bool, default : True
|
|
543
|
+
include leap day in the results
|
|
544
|
+
full_name : str, default 'pvlib python'
|
|
545
|
+
optional
|
|
546
|
+
affiliation : str, default 'pvlib python'
|
|
547
|
+
optional
|
|
548
|
+
utc: bool, default : False
|
|
549
|
+
retrieve data with timestamps converted to UTC. False returns
|
|
550
|
+
timestamps in local standard time of the selected location
|
|
551
|
+
map_variables : bool, default True
|
|
552
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
553
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
554
|
+
url : str, optional
|
|
555
|
+
Full API endpoint URL. If not specified, the PSM4 GOES Full Disc v4
|
|
556
|
+
URL is used.
|
|
557
|
+
timeout : int, default 30
|
|
558
|
+
time in seconds to wait for server response before timeout
|
|
559
|
+
|
|
560
|
+
Returns
|
|
561
|
+
-------
|
|
562
|
+
data : pandas.DataFrame
|
|
563
|
+
timeseries data from NREL PSM4
|
|
564
|
+
metadata : dict
|
|
565
|
+
metadata from NREL PSM4 about the record, see
|
|
566
|
+
:func:`pvlib.iotools.parse_nsrdb_psm4` for fields
|
|
567
|
+
|
|
568
|
+
Raises
|
|
569
|
+
------
|
|
570
|
+
requests.HTTPError
|
|
571
|
+
if the request response status is not ok, then the ``'errors'`` field
|
|
572
|
+
from the JSON response or any error message in the content will be
|
|
573
|
+
raised as an exception, for example if the `api_key` was rejected or if
|
|
574
|
+
the coordinates were not found in the NSRDB
|
|
575
|
+
|
|
576
|
+
Notes
|
|
577
|
+
-----
|
|
578
|
+
The required NREL developer key, `api_key`, is available for free by
|
|
579
|
+
registering at the `NREL Developer Network <https://developer.nrel.gov/>`_.
|
|
580
|
+
|
|
581
|
+
.. warning:: The "DEMO_KEY" `api_key` is severely rate limited and may
|
|
582
|
+
result in rejected requests.
|
|
583
|
+
|
|
584
|
+
.. warning:: PSM4 is limited to data found in the NSRDB, please consult
|
|
585
|
+
the references below for locations with available data. Additionally,
|
|
586
|
+
querying data with < 30-minute resolution uses a different API endpoint
|
|
587
|
+
with fewer available fields (see [4]_).
|
|
588
|
+
|
|
589
|
+
See Also
|
|
590
|
+
--------
|
|
591
|
+
pvlib.iotools.get_nsrdb_psm4_aggregated,
|
|
592
|
+
pvlib.iotools.get_nsrdb_psm4_tmy, pvlib.iotools.get_nsrdb_psm4_conus,
|
|
593
|
+
pvlib.iotools.read_nsrdb_psm4, pvlib.iotools.parse_nsrdb_psm4
|
|
594
|
+
|
|
595
|
+
References
|
|
596
|
+
----------
|
|
597
|
+
|
|
598
|
+
.. [1] `NREL National Solar Radiation Database (NSRDB)
|
|
599
|
+
<https://nsrdb.nrel.gov/>`_
|
|
600
|
+
.. [2] `NSRDB GOES Full Disc V4.0.0
|
|
601
|
+
<https://developer.nrel.gov/docs/solar/nsrdb/nsrdb-GOES-full-disc-v4-0-0-download/>`_
|
|
602
|
+
"""
|
|
603
|
+
# The well know text (WKT) representation of geometry notation is strict.
|
|
604
|
+
# A POINT object is a string with longitude first, then the latitude, with
|
|
605
|
+
# four decimals each, and exactly one space between them.
|
|
606
|
+
longitude = ('%9.4f' % longitude).strip()
|
|
607
|
+
latitude = ('%8.4f' % latitude).strip()
|
|
608
|
+
# TODO: make format_WKT(object_type, *args) in tools.py
|
|
609
|
+
|
|
610
|
+
# convert to string to accomodate integer years being passed in
|
|
611
|
+
year = str(year)
|
|
612
|
+
|
|
613
|
+
# convert pvlib names in parameters to PSM4 convention
|
|
614
|
+
parameters = [REQUEST_VARIABLE_MAP.get(a, a) for a in parameters]
|
|
615
|
+
|
|
616
|
+
# required query-string parameters for request to PSM4 API
|
|
617
|
+
params = {
|
|
618
|
+
'api_key': api_key,
|
|
619
|
+
'full_name': full_name,
|
|
620
|
+
'email': email,
|
|
621
|
+
'affiliation': affiliation,
|
|
622
|
+
'reason': PVLIB_PYTHON,
|
|
623
|
+
'mailing_list': 'false',
|
|
624
|
+
'wkt': 'POINT(%s %s)' % (longitude, latitude),
|
|
625
|
+
'names': year,
|
|
626
|
+
'attributes': ','.join(parameters),
|
|
627
|
+
'leap_day': str(leap_day).lower(),
|
|
628
|
+
'utc': str(utc).lower(),
|
|
629
|
+
'interval': time_step
|
|
630
|
+
}
|
|
631
|
+
# request CSV download from NREL PSM4
|
|
632
|
+
if url is None:
|
|
633
|
+
url = PSM4_FUL_URL
|
|
634
|
+
|
|
635
|
+
response = requests.get(url, params=params, timeout=timeout)
|
|
636
|
+
if not response.ok:
|
|
637
|
+
# if the API key is rejected, then the response status will be 403
|
|
638
|
+
# Forbidden, and then the error is in the content and there is no JSON
|
|
639
|
+
try:
|
|
640
|
+
errors = response.json()['errors']
|
|
641
|
+
except JSONDecodeError:
|
|
642
|
+
errors = response.content.decode('utf-8')
|
|
643
|
+
raise requests.HTTPError(errors, response=response)
|
|
644
|
+
# the CSV is in the response content as a UTF-8 bytestring
|
|
645
|
+
# to use pandas we need to create a file buffer from the response
|
|
646
|
+
fbuf = io.StringIO(response.content.decode('utf-8'))
|
|
647
|
+
return parse_nsrdb_psm4(fbuf, map_variables)
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
def parse_nsrdb_psm4(fbuf, map_variables=True):
|
|
651
|
+
"""
|
|
652
|
+
Parse an NSRDB PSM4 weather file (formatted as SAM CSV).
|
|
653
|
+
|
|
654
|
+
The NSRDB is described in [1]_ and the SAM CSV format is described in [2]_.
|
|
655
|
+
|
|
656
|
+
Parameters
|
|
657
|
+
----------
|
|
658
|
+
fbuf: file-like object
|
|
659
|
+
File-like object containing data to read.
|
|
660
|
+
map_variables: bool, default True
|
|
661
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
662
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
663
|
+
|
|
664
|
+
Returns
|
|
665
|
+
-------
|
|
666
|
+
data : pandas.DataFrame
|
|
667
|
+
timeseries data from NREL PSM4
|
|
668
|
+
metadata : dict
|
|
669
|
+
metadata from NREL PSM4 about the record, see notes for fields
|
|
670
|
+
|
|
671
|
+
Notes
|
|
672
|
+
-----
|
|
673
|
+
The return is a tuple with two items. The first item is a dataframe with
|
|
674
|
+
the PSM4 timeseries data.
|
|
675
|
+
|
|
676
|
+
The second item is a dictionary with metadata from NREL PSM4 about the
|
|
677
|
+
record containing the following fields:
|
|
678
|
+
|
|
679
|
+
* Source
|
|
680
|
+
* Location ID
|
|
681
|
+
* City
|
|
682
|
+
* State
|
|
683
|
+
* Country
|
|
684
|
+
* Latitude
|
|
685
|
+
* Longitude
|
|
686
|
+
* Time Zone
|
|
687
|
+
* Elevation
|
|
688
|
+
* Local Time Zone
|
|
689
|
+
* Clearsky DHI Units
|
|
690
|
+
* Clearsky DNI Units
|
|
691
|
+
* Clearsky GHI Units
|
|
692
|
+
* Dew Point Units
|
|
693
|
+
* DHI Units
|
|
694
|
+
* DNI Units
|
|
695
|
+
* GHI Units
|
|
696
|
+
* Solar Zenith Angle Units
|
|
697
|
+
* Temperature Units
|
|
698
|
+
* Pressure Units
|
|
699
|
+
* Relative Humidity Units
|
|
700
|
+
* Precipitable Water Units
|
|
701
|
+
* Wind Direction Units
|
|
702
|
+
* Wind Speed Units
|
|
703
|
+
* Cloud Type -15
|
|
704
|
+
* Cloud Type 0
|
|
705
|
+
* Cloud Type 1
|
|
706
|
+
* Cloud Type 2
|
|
707
|
+
* Cloud Type 3
|
|
708
|
+
* Cloud Type 4
|
|
709
|
+
* Cloud Type 5
|
|
710
|
+
* Cloud Type 6
|
|
711
|
+
* Cloud Type 7
|
|
712
|
+
* Cloud Type 8
|
|
713
|
+
* Cloud Type 9
|
|
714
|
+
* Cloud Type 10
|
|
715
|
+
* Cloud Type 11
|
|
716
|
+
* Cloud Type 12
|
|
717
|
+
* Fill Flag 0
|
|
718
|
+
* Fill Flag 1
|
|
719
|
+
* Fill Flag 2
|
|
720
|
+
* Fill Flag 3
|
|
721
|
+
* Fill Flag 4
|
|
722
|
+
* Fill Flag 5
|
|
723
|
+
* Surface Albedo Units
|
|
724
|
+
* Version
|
|
725
|
+
|
|
726
|
+
Examples
|
|
727
|
+
--------
|
|
728
|
+
>>> # Read a local PSM4 file:
|
|
729
|
+
>>> with open(filename, 'r') as f: # doctest: +SKIP
|
|
730
|
+
... df, metadata = iotools.parse_nsrdb_psm4(f) # doctest: +SKIP
|
|
731
|
+
|
|
732
|
+
See Also
|
|
733
|
+
--------
|
|
734
|
+
pvlib.iotools.read_nsrdb_psm4, pvlib.iotools.get_psm4
|
|
735
|
+
|
|
736
|
+
References
|
|
737
|
+
----------
|
|
738
|
+
.. [1] `NREL National Solar Radiation Database (NSRDB)
|
|
739
|
+
<https://nsrdb.nrel.gov/>`_
|
|
740
|
+
.. [2] `Standard Time Series Data File Format
|
|
741
|
+
<https://web.archive.org/web/20170207203107/https://sam.nrel.gov/sites/default/files/content/documents/pdf/wfcsv.pdf>`_
|
|
742
|
+
"""
|
|
743
|
+
# The first 2 lines of the response are headers with metadata
|
|
744
|
+
metadata_fields = fbuf.readline().split(',')
|
|
745
|
+
metadata_fields[-1] = metadata_fields[-1].strip() # strip trailing newline
|
|
746
|
+
metadata_values = fbuf.readline().split(',')
|
|
747
|
+
metadata_values[-1] = metadata_values[-1].strip() # strip trailing newline
|
|
748
|
+
metadata = dict(zip(metadata_fields, metadata_values))
|
|
749
|
+
# the response is all strings, so set some metadata types to numbers
|
|
750
|
+
metadata['Local Time Zone'] = int(metadata['Local Time Zone'])
|
|
751
|
+
metadata['Time Zone'] = int(metadata['Time Zone'])
|
|
752
|
+
metadata['Latitude'] = float(metadata['Latitude'])
|
|
753
|
+
metadata['Longitude'] = float(metadata['Longitude'])
|
|
754
|
+
metadata['Elevation'] = int(metadata['Elevation'])
|
|
755
|
+
# get the column names so we can set the dtypes
|
|
756
|
+
columns = fbuf.readline().split(',')
|
|
757
|
+
columns[-1] = columns[-1].strip() # strip trailing newline
|
|
758
|
+
# Since the header has so many columns, excel saves blank cols in the
|
|
759
|
+
# data below the header lines.
|
|
760
|
+
columns = [col for col in columns if col != '']
|
|
761
|
+
dtypes = dict.fromkeys(columns, float) # all floats except datevec
|
|
762
|
+
dtypes.update(Year=int, Month=int, Day=int, Hour=int, Minute=int)
|
|
763
|
+
dtypes['Cloud Type'] = int
|
|
764
|
+
dtypes['Fill Flag'] = int
|
|
765
|
+
data = pd.read_csv(
|
|
766
|
+
fbuf, header=None, names=columns, usecols=columns, dtype=dtypes,
|
|
767
|
+
delimiter=',', lineterminator='\n') # skip carriage returns \r
|
|
768
|
+
# the response 1st 5 columns are a date vector, convert to datetime
|
|
769
|
+
dtidx = pd.to_datetime(
|
|
770
|
+
data[['Year', 'Month', 'Day', 'Hour', 'Minute']])
|
|
771
|
+
# in USA all timezones are integers
|
|
772
|
+
tz = 'Etc/GMT%+d' % -metadata['Time Zone']
|
|
773
|
+
data.index = pd.DatetimeIndex(dtidx).tz_localize(tz)
|
|
774
|
+
|
|
775
|
+
if map_variables:
|
|
776
|
+
data = data.rename(columns=VARIABLE_MAP)
|
|
777
|
+
metadata['latitude'] = metadata.pop('Latitude')
|
|
778
|
+
metadata['longitude'] = metadata.pop('Longitude')
|
|
779
|
+
metadata['altitude'] = metadata.pop('Elevation')
|
|
780
|
+
|
|
781
|
+
return data, metadata
|
|
782
|
+
|
|
783
|
+
|
|
784
|
+
def read_nsrdb_psm4(filename, map_variables=True):
|
|
785
|
+
"""
|
|
786
|
+
Read an NSRDB PSM4 weather file (formatted as SAM CSV).
|
|
787
|
+
|
|
788
|
+
The NSRDB is described in [1]_ and the SAM CSV format is described in [2]_.
|
|
789
|
+
|
|
790
|
+
Parameters
|
|
791
|
+
----------
|
|
792
|
+
filename: str or path-like
|
|
793
|
+
Filename of a file containing data to read.
|
|
794
|
+
map_variables: bool, default True
|
|
795
|
+
When true, renames columns of the Dataframe to pvlib variable names
|
|
796
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
797
|
+
|
|
798
|
+
Returns
|
|
799
|
+
-------
|
|
800
|
+
data : pandas.DataFrame
|
|
801
|
+
timeseries data from NREL PSM4
|
|
802
|
+
metadata : dict
|
|
803
|
+
metadata from NREL PSM4 about the record, see
|
|
804
|
+
:func:`pvlib.iotools.parse_nsrdb_psm4` for fields
|
|
805
|
+
|
|
806
|
+
See Also
|
|
807
|
+
--------
|
|
808
|
+
pvlib.iotools.parse_nsrdb_psm4, pvlib.iotools.get_psm4
|
|
809
|
+
|
|
810
|
+
References
|
|
811
|
+
----------
|
|
812
|
+
.. [1] `NREL National Solar Radiation Database (NSRDB)
|
|
813
|
+
<https://nsrdb.nrel.gov/>`_
|
|
814
|
+
.. [2] `Standard Time Series Data File Format
|
|
815
|
+
<https://web.archive.org/web/20170207203107/https://sam.nrel.gov/sites/default/files/content/documents/pdf/wfcsv.pdf>`_
|
|
816
|
+
"""
|
|
817
|
+
with open(str(filename), 'r') as fbuf:
|
|
818
|
+
content = parse_nsrdb_psm4(fbuf, map_variables)
|
|
819
|
+
return content
|