-
Notifications
You must be signed in to change notification settings - Fork 1.1k
ENH: Create psm3.py #694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
ENH: Create psm3.py #694
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
e0859f7
Create psm3.py
mikofski 6535a04
fix well known text for geometric POINT
mikofski f7003ac
TST: add test for getting psm3
mikofski 15f93d3
update docs, closes #592
mikofski 4c8c073
stickler, default interval
mikofski 2b9cff5
add psm3 to api
mikofski c52d5b7
use astype, fix typos, change param names to match API
mikofski 2809897
use pandas, better variable names, comments, set all dtypes
mikofski 6cf57a4
stickler fixes
mikofski 05cf879
api_key as param
mikofski 13c196a
TST: decorate test_get_psm3 with needs_pandas_0_22
mikofski 02c143f
api_key and email are required according to NREL
mikofski 64d7cb9
Merge branch 'patch-1' of github.com:mikofski/pvlib-python into psm3
mikofski f9df42d
stickler: remove unused JSON import
mikofski b6f79cf
remove non-ASCII quotation marks around DEMO_KEY in warning
mikofski 8884c7f
remove "required" for api_key param in get_psm3
wholmgren 1935215
rewording for "email" param in get_psm3
wholmgren 24c1f3b
clarify WKT formating and errors
mikofski 4059db5
Merge branch 'patch-1' of github.com:mikofski/pvlib-python into psm3
mikofski f12c36b
DOC: defaults in argtype for get_psm3
mikofski File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
""" | ||
Get PSM3 TMY | ||
see https://developer.nrel.gov/docs/solar/nsrdb/psm3_data_download/ | ||
""" | ||
|
||
import io | ||
import csv | ||
import datetime | ||
import requests | ||
import pandas as pd | ||
import pytz | ||
|
||
URL = "http://developer.nrel.gov/api/solar/nsrdb_psm3_download.csv" | ||
|
||
# 'relative_humidity', 'total_precipitable_water' are note available | ||
ATTRIBUTES = [ | ||
'air_temperature', 'dew_point', 'dhi', 'dni', 'ghi', 'surface_albedo', | ||
'surface_pressure', 'wind_direction', 'wind_speed'] | ||
|
||
|
||
def get_psm3(latitude, longitude, tmy='tmy', interval=60): | ||
""" | ||
Get PSM3 data | ||
|
||
Parameters | ||
---------- | ||
latitude : float or int | ||
in decimal degrees, between -90 and 90, north is positive | ||
longitude : float or int | ||
in decimal degrees, between -180 and 180, east is positive | ||
tmy : str | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
PSM3 parameter "name", see notes below for options, default ``'tmy'`` | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
interval : integer | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
interval size in minutes, can be only either 30 or 60, default 60 | ||
|
||
Returns | ||
------- | ||
headers : dict | ||
meta data from NREL PSM-3 about the record, see notes for fields | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
data : pandas.DataFrame | ||
timeseries data from NREL PSM3 | ||
|
||
Raises | ||
------ | ||
requests.HTTPError | ||
|
||
Notes | ||
----- | ||
The ``tmy`` parameter 'names' must be a single value from the following | ||
list: | ||
|
||
['1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', | ||
'2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013', | ||
'2014', '2015', '2016', '2017', 'tmy', 'tmy-2016', 'tmy-2017', | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'tdy-2017', 'tgy-2017'] | ||
|
||
The return is a tuple with two items. The first item is a header with meta | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
data from NREL PSM3 about the record containing the following fields: | ||
|
||
* Source | ||
* Location ID | ||
* City | ||
* State | ||
* Country | ||
* Latitude | ||
* Longitude | ||
* Time Zone | ||
* Elevation | ||
* Local Time Zone | ||
* Dew Point Units | ||
* DHI Units | ||
* DNI Units | ||
* GHI Units | ||
* Temperature Units | ||
* Pressure Units | ||
* Wind Direction Units | ||
* Wind Speed | ||
* Surface Albedo Units | ||
* Version | ||
|
||
See Also | ||
-------- | ||
pvlib.iotools.read_tmy2, pvlib.iotools.read_tmy3 | ||
|
||
References | ||
---------- | ||
[1] `NREL Developer Network - Physical Solar Model (PSM) v3 | ||
<https://developer.nrel.gov/docs/solar/nsrdb/psm3_data_download/>`_ | ||
[2] `NREL National Solar Radiation Database (NSRDB) | ||
<https://nsrdb.nrel.gov/>`_ | ||
""" | ||
longitude = ('%9.4f' % longitude).strip() | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
latitude = ('%8.4f' % latitude).strip() | ||
params = { | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'api_key': 'DEMO_KEY', | ||
'full_name': 'Sample User', | ||
'email': 'sample@email.com', | ||
'affiliation': 'Test Organization', | ||
'reason': 'Example', | ||
'mailing_list': 'true', | ||
'wkt': 'POINT(%s %s)' % (longitude, latitude), | ||
'names': tmy, | ||
'attributes': ','.join(ATTRIBUTES), | ||
'leap_day': 'false', | ||
'utc': 'false', | ||
'interval': interval | ||
} | ||
|
||
s = requests.get(URL, params=params) | ||
if s.ok: | ||
f = io.StringIO(s.content.decode('utf-8')) | ||
x = csv.reader(f, delimiter=',', lineterminator='\n') | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
y = list(x) | ||
z = dict(zip(y[0], y[1])) | ||
# in USA all timezones are integers | ||
z['Local Time Zone'] = int(z['Local Time Zone']) | ||
z['Time Zone'] = int(z['Time Zone']) | ||
z['Latitude'] = float(z['Latitude']) | ||
z['Longitude'] = float(z['Longitude']) | ||
z['Elevation'] = int(z['Elevation']) | ||
tz = pytz.timezone('Etc/GMT%+d' % -z['Time Zone']) | ||
w = pd.DataFrame(y[3:], columns=y[2], dtype=float) | ||
w.Year = w.Year.apply(lambda yr: int(yr)) | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
w.Month = w.Month.apply(lambda mt: int(mt)) | ||
w.Day = w.Day.apply(lambda dy: int(dy)) | ||
w.Hour = w.Hour.apply(lambda hr: int(hr)) | ||
w.Minute = w.Minute.apply(lambda mn: int(mn)) | ||
w.index = w.apply( | ||
lambda dt: tz.localize(datetime.datetime( | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
int(dt.Year), int(dt.Month), int(dt.Day), | ||
int(dt.Hour), int(dt.Minute))), axis=1) | ||
return z, w | ||
raise requests.HTTPError(s.json()['errors']) | ||
mikofski marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
""" | ||
test iotools for PSM3 | ||
""" | ||
|
||
import os | ||
from pvlib.iotools import psm3 | ||
import numpy as np | ||
import pandas as pd | ||
import pytest | ||
from requests import HTTPError | ||
|
||
BASEDIR = os.path.abspath(os.path.dirname(__file__)) | ||
PROJDIR = os.path.dirname(BASEDIR) | ||
DATADIR = os.path.join(PROJDIR, 'data') | ||
TEST_DATA = os.path.join(DATADIR, 'test_psm3.csv') | ||
LATITUDE, LONGITUDE = 40.5137, -108.5449 | ||
HEADER_FIELDS = [ | ||
'Source', 'Location ID', 'City', 'State', 'Country', 'Latitude', | ||
'Longitude', 'Time Zone', 'Elevation', 'Local Time Zone', | ||
'Dew Point Units', 'DHI Units', 'DNI Units', 'GHI Units', | ||
'Temperature Units', 'Pressure Units', 'Wind Direction Units', | ||
'Wind Speed', 'Surface Albedo Units', 'Version'] | ||
|
||
|
||
def test_psm3(): | ||
"""test get_psm3""" | ||
header, data = psm3.get_psm3(LATITUDE, LONGITUDE) | ||
expected = pd.read_csv(TEST_DATA) | ||
# check datevec columns | ||
assert np.allclose(data.Year, expected.Year) | ||
assert np.allclose(data.Month, expected.Month) | ||
assert np.allclose(data.Day, expected.Day) | ||
assert np.allclose(data.Hour, expected.Hour) | ||
assert np.allclose(data.Minute, expected.Minute) | ||
# check data columns | ||
assert np.allclose(data.GHI, expected.GHI) | ||
assert np.allclose(data.DNI, expected.DNI) | ||
assert np.allclose(data.DHI, expected.DHI) | ||
assert np.allclose(data.Temperature, expected.Temperature) | ||
assert np.allclose(data.Pressure, expected.Pressure) | ||
assert np.allclose(data['Dew Point'], expected['Dew Point']) | ||
assert np.allclose(data['Surface Albedo'], expected['Surface Albedo']) | ||
assert np.allclose(data['Wind Speed'], expected['Wind Speed']) | ||
assert np.allclose(data['Wind Direction'], expected['Wind Direction']) | ||
# check header | ||
for hf in HEADER_FIELDS: | ||
assert hf in header | ||
# check error | ||
with pytest.raises(HTTPError): | ||
psm3.get_psm3(LATITUDE, LONGITUDE, 'bad') |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.