Developer Network NREL NREL Developer Network

Python Examples

NSRDB and SAM Python API examples showing automated download of resource data and SAM simulation

NSRDB and SAM Python APIs: Automated download of resource data and SAM simulation

This example shows how to use the NSRDB API for automated data download in Section 1 and then provides an example of using these data with the SAM Software Development Kit (SDK) in Section 2. A plotting example is offered in Section 3.

In [1]:
import sys, os
import pandas as pd
import numpy as np

from IPython.display import display

1. Request Data From NSRDB using Python API

The following section shows how to download NSRDB data for a specified year and location.

Declare input variables for api request:

In [2]:
# Declare all variables as strings. Spaces must be replaced with '+', i.e., change 'John Smith' to 'John+Smith'.
# Define the lat, long of the location and the year
lat, lon, year = 33.2164, -97.1292, 2010
# You must request an NSRDB api key from the link above
api_key = '{{API_KEY}}'
# Set the attributes to extract (e.g., dhi, ghi, etc.), separated by commas.
attributes = 'ghi,dhi,dni,wind_speed,air_temperature,solar_zenith_angle'
# Choose year of data
year = '2010'
# Set leap year to true or false. True will return leap day data if present, false will not.
leap_year = 'false'
# Set time interval in minutes, i.e., '30' is half hour intervals. Valid intervals are 30 & 60.
interval = '30'
# Specify Coordinated Universal Time (UTC), 'true' will use UTC, 'false' will use the local time zone of the data.
# NOTE: In order to use the NSRDB data in SAM, you must specify UTC as 'false'. SAM requires the data to be in the
# local time zone.
utc = 'false'
# Your full name, use '+' instead of spaces.
your_name = 'John+Smith'
# Your reason for using the NSRDB.
reason_for_use = 'beta+testing'
# Your affiliation
your_affiliation = 'my+institution'
# Your email address
your_email = 'user@company.com'
# Please join our mailing list so we can keep you up-to-date on new developments.
mailing_list = 'true'

# Declare url string
url = 'https://developer.nrel.gov/api/nsrdb/v2/solar/psm3-download.csv?wkt=POINT({lon}%20{lat})&names={year}&leap_day={leap}&interval={interval}&utc={utc}&full_name={name}&email={email}&affiliation={affiliation}&mailing_list={mailing_list}&reason={reason}&api_key={api}&attributes={attr}'.format(year=year, lat=lat, lon=lon, leap=leap_year, interval=interval, utc=utc, name=your_name, email=your_email, mailing_list=mailing_list, affiliation=your_affiliation, reason=reason_for_use, api=api_key, attr=attributes)
# Return just the first 2 lines to get metadata:
info = pd.read_csv(url, nrows=1)
# See metadata for specified properties, e.g., timezone and elevation
timezone, elevation = info['Local Time Zone'], info['Elevation']
In [3]:
# View metadata
info
Out[3]:
Source Location ID City State Country Latitude Longitude Time Zone Elevation Local Time Zone ... Cloud Type 11 Cloud Type 12 Fill Flag 0 Fill Flag 1 Fill Flag 2 Fill Flag 3 Fill Flag 4 Fill Flag 5 Surface Albedo Units Version
0 NSRDB 693763 - - - 33.21 -97.14 -6 203 -6 ... Dust Smoke NaN Missing Image Low Irradiance Exceeds Clearsky Missing CLoud Properties Rayleigh Violation NaN 3.0.6

1 rows × 46 columns

In [4]:
# Return all but first 2 lines of csv to get data:
df = pd.read_csv('https://developer.nrel.gov/api/nsrdb/v2/solar/psm3-download.csv?wkt=POINT({lon}%20{lat})&names={year}&leap_day={leap}&interval={interval}&utc={utc}&full_name={name}&email={email}&affiliation={affiliation}&mailing_list={mailing_list}&reason={reason}&api_key={api}&attributes={attr}'.format(year=year, lat=lat, lon=lon, leap=leap_year, interval=interval, utc=utc, name=your_name, email=your_email, mailing_list=mailing_list, affiliation=your_affiliation, reason=reason_for_use, api=api_key, attr=attributes), skiprows=2)

# Set the time index in the pandas dataframe:
df = df.set_index(pd.date_range('1/1/{yr}'.format(yr=year), freq=interval+'Min', periods=525600/int(interval)))

# take a look
print('shape:', df.shape)
df.head()

shape: (17520, 11)
Out[4]:
Year Month Day Hour Minute GHI DHI DNI Wind Speed Temperature Solar Zenith Angle
2010-01-01 00:00:00 2010 1 1 0 0 0 0 0 2.9 -2 167.60
2010-01-01 00:30:00 2010 1 1 0 30 0 0 0 2.7 -2 169.78
2010-01-01 01:00:00 2010 1 1 1 0 0 0 0 2.5 -3 168.08
2010-01-01 01:30:00 2010 1 1 1 30 0 0 0 2.4 -3 163.67
2010-01-01 02:00:00 2010 1 1 2 0 0 0 0 2.4 -4 158.14
shape: (17520, 22)
In [5]:
# Print column names
print(df.columns.values)
['Year' 'Month' 'Day' 'Hour' 'Minute' 'GHI' 'DHI' 'DNI' 'Wind Speed'
 'Temperature' 'Solar Zenith Angle']
['Year' 'Month' 'Day' 'Hour' 'Minute' 'Clearsky DHI' 'Clearsky DNI' 'Clearsky GHI' 'Cloud Type' 'Dew Point' 'DHI' 'DNI' 'Fill Flag' 'GHI' 'Snow Depth' 'Solar Zenith Angle' 'Temperature' 'Pressure' 'Relative Humidity' 'Precipitable Water' 'Wind Direction' 'Wind Speed']

2. SAM Simulation

The following illustrates how to use the NSRDB data in a SAM simulation, using the Python Software Development Kit (SDK).

In [6]:
#import additional module for SAM simulation:
import site
# Use site.addsitedir() to set the path to the SAM SDK API. Set path to the python directory.
site.addsitedir('/Applications/sam-sdk-2015-6-30-r3/languages/python/')
import PySAM.PySSC as pssc
# Download PySAM here: https://pypi.org/project/NREL-PySAM/

ssc = pssc.PySSC()

# Resource inputs for SAM model:
# Must be byte strings
wfd = ssc.data_create()
ssc.data_set_number(wfd, b'lat', lat)
ssc.data_set_number(wfd, b'lon', lon)
ssc.data_set_number(wfd, b'tz', timezone)
ssc.data_set_number(wfd, b'elev', elevation)
ssc.data_set_array(wfd, b'year', df.index.year)
ssc.data_set_array(wfd, b'month', df.index.month)
ssc.data_set_array(wfd, b'day', df.index.day)
ssc.data_set_array(wfd, b'hour', df.index.hour)
ssc.data_set_array(wfd, b'minute', df.index.minute)
ssc.data_set_array(wfd, b'dn', df['DNI'])
ssc.data_set_array(wfd, b'df', df['DHI'])
ssc.data_set_array(wfd, b'wspd', df['Wind Speed'])
ssc.data_set_array(wfd, b'tdry', df['Temperature'])

# Create SAM compliant object  
dat = ssc.data_create()
ssc.data_set_table(dat, b'solar_resource_data', wfd)
ssc.data_free(wfd)

# Specify the system Configuration
# Set system capacity in MW
system_capacity = 4
ssc.data_set_number(dat, b'system_capacity', system_capacity)
# Set DC/AC ratio (or power ratio). See https://sam.nrel.gov/sites/default/files/content/virtual_conf_july_2013/07-sam-virtual-conference-2013-woodcock.pdf
ssc.data_set_number(dat, b'dc_ac_ratio', 1.1)
# Set tilt of system in degrees
ssc.data_set_number(dat, b'tilt', 25)
# Set azimuth angle (in degrees) from north (0 degrees)
ssc.data_set_number(dat, b'azimuth', 180)
# Set the inverter efficency
ssc.data_set_number(dat, b'inv_eff', 96)
# Set the system losses, in percent
ssc.data_set_number(dat, b'losses', 14.0757)
# Specify fixed tilt system (0=Fixed, 1=Fixed Roof, 2=1 Axis Tracker, 3=Backtracted, 4=2 Axis Tracker)
ssc.data_set_number(dat, b'array_type', 0)
# Set ground coverage ratio
ssc.data_set_number(dat, b'gcr', 0.4)
# Set constant loss adjustment
ssc.data_set_number(dat, b'adjust:constant', 0)

# execute and put generation results back into dataframe
mod = ssc.module_create(b'pvwattsv5')
ssc.module_exec(mod, dat)
df[b'generation'] = np.array(ssc.data_get_array(dat, b'gen'))

# free the memory
ssc.data_free(dat)
ssc.module_free(mod)

Check the capacity Factor

In [7]:
# Divide sum of generation by the number of periods times the system size
df[b'generation'].sum() / (525600/int(interval) * system_capacity)
Out[7]:
0.17417854667732946
In [8]:
# Total Energy:
df[b'generation'].sum()
Out[8]:
12206.432551147249

3. Plot the SAM simulation results

Define a plotting function using matplotlib

In [9]:
%matplotlib inline
from matplotlib import pyplot as plt

plt.style.use('ggplot')

def nsrdb_plot(df, i):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax2 = ax.twinx()
    df['90 Degree Zenith'] = 90
    df[['GHI', 'DNI', 'DHI', 'Solar Zenith Angle', '90 Degree Zenith']][i:i+int(interval)].plot(ax=ax, figsize=(15,8), yticks=(np.arange(0,900,100)), style={'90 Degree Zenith': '--','Solar Zenith Angle': '-o', 'DNI': '-o', 'DHI': '-o', 'GHI': '-o'}, legend=False)
    df[b'generation'][i:i+30].plot(ax=ax2, yticks=(np.arange(0,4.5,0.5)), style={'generation': 'y-o'})
    ax.grid()
    ax.set_ylabel('W/m2')
    ax2.set_ylabel('kW')
    ax.legend(loc=2, ncol=5, frameon=False)
    ax2.legend(loc=1, frameon=False)

Take a look at the results

In [10]:
nsrdb_plot(df, 5050)
Help Improve this Content