<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Forecast to Power Tutorial
This tutorial will walk through the process of going from Unidata forecast model data to AC power using the SAPM.
Table of contents
Step1:  Load Forecast data
pvlib forecast module only includes several models. To see the full list of forecast models visit the Unidata website
Step2:  Define some PV system parameters.
Step3:  Let's look at the downloaded version of the forecast data.
Step4:  This is a pandas DataFrame object. It has a lot of great properties that are beyond the scope of our tutorials.
Step5:  Plot the GHI data. Most pvlib forecast models derive this data from the weather models' cloud clover data.
Step6:  Calculate modeling intermediates
Before we can calculate power for all the forecast times, we will need to calculate
Step7:  The funny looking jump in the azimuth is just due to the coarse time sampling in the TMY file.
DNI ET
Calculate extra terrestrial radiation. This is needed for many plane of array diffuse irradiance models.
Step8:  Airmass
Calculate airmass. Lots of model options here, see the atmosphere module tutorial for more details.
Step9:  The funny appearance is due to aliasing and setting invalid numbers equal to NaN. Replot just a day or two and you'll see that the numbers are right.
POA sky diffuse
Use the Hay Davies model to calculate the plane of array diffuse sky radiation. See the irradiance module tutorial for comparisons of different models.
Step10:  POA ground diffuse
Calculate ground diffuse. We specified the albedo above. You could have also provided a string to the surface_type keyword argument.
Step11:  AOI
Calculate AOI
Step12:  Note that AOI has values greater than 90 deg. This is ok.
POA total
Calculate POA irradiance
Step13:  Cell and module temperature
Calculate pv cell and module temperature
Step14:  DC power using SAPM
Get module data from the web.
Step15:  Choose a particular module
Step16:  Run the SAPM using the parameters we calculated above.
Step17:  AC power using SAPM
Get the inverter database from the web
Step18:  Choose a particular inverter
Step19:  Plot just a few days.
Step20:  Some statistics on the AC power
<ASSISTANT_TASK:>
Python Code:
# built-in python modules
import datetime
import inspect
import os
# scientific python add-ons
import numpy as np
import pandas as pd
# plotting stuff
# first line makes the plots appear in the notebook
%matplotlib inline 
import matplotlib.pyplot as plt
import matplotlib as mpl
# seaborn makes your plots look better
try:
    import seaborn as sns
    sns.set(rc={"figure.figsize": (12, 6)})
    sns.set_color_codes()
except ImportError:
    print('We suggest you install seaborn using conda or pip and rerun this cell')
# finally, we import the pvlib library
from pvlib import solarposition,irradiance,atmosphere,pvsystem
from pvlib.forecast import GFS, NAM, NDFD, RAP, HRRR
Explanation: Forecast to Power Tutorial
This tutorial will walk through the process of going from Unidata forecast model data to AC power using the SAPM.
Table of contents:
1. Setup
2. Load Forecast data
2. Calculate modeling intermediates
2. DC power using SAPM
2. AC power using SAPM
This tutorial has been tested against the following package versions:
* Python 3.5.2
* IPython 5.0.0
* pandas 0.18.0
* matplotlib 1.5.1
* netcdf4 1.2.1
* siphon 0.4.0
It should work with other Python and Pandas versions. It requires pvlib >= 0.3.0 and IPython >= 3.0.
Authors:
* Derek Groenendyk (@moonraker), University of Arizona, November 2015
* Will Holmgren (@wholmgren), University of Arizona, November 2015, January 2016, April 2016, July 2016
Setup
These are just your standard interactive scientific python imports that you'll get very used to using.
End of explanation
# Choose a location.
# Tucson, AZ
latitude = 32.2
longitude = -110.9
tz = 'US/Mountain'
Explanation: Load Forecast data
pvlib forecast module only includes several models. To see the full list of forecast models visit the Unidata website:
http://www.unidata.ucar.edu/data/#tds
End of explanation
surface_tilt = 30
surface_azimuth = 180 # pvlib uses 0=North, 90=East, 180=South, 270=West convention
albedo = 0.2
start = pd.Timestamp(datetime.date.today(), tz=tz) # today's date
end = start + pd.Timedelta(days=7) # 7 days from today
# Define forecast model
fm = GFS()
#fm = NAM()
#fm = NDFD()
#fm = RAP()
#fm = HRRR()
# Retrieve data
forecast_data = fm.get_processed_data(latitude, longitude, start, end)
Explanation: Define some PV system parameters.
End of explanation
forecast_data.head()
Explanation: Let's look at the downloaded version of the forecast data.
End of explanation
forecast_data['temp_air'].plot()
Explanation: This is a pandas DataFrame object. It has a lot of great properties that are beyond the scope of our tutorials.
End of explanation
ghi = forecast_data['ghi']
ghi.plot()
plt.ylabel('Irradiance ($W/m^{-2}$)')
Explanation: Plot the GHI data. Most pvlib forecast models derive this data from the weather models' cloud clover data.
End of explanation
# retrieve time and location parameters
time = forecast_data.index
a_point = fm.location
solpos = a_point.get_solarposition(time)
#solpos.plot()
Explanation: Calculate modeling intermediates
Before we can calculate power for all the forecast times, we will need to calculate:
* solar position 
* extra terrestrial radiation
* airmass
* angle of incidence
* POA sky and ground diffuse radiation
* cell and module temperatures
The approach here follows that of the pvlib tmy_to_power notebook. You will find more details regarding this approach and the values being calculated in that notebook.
Solar position
Calculate the solar position for all times in the forecast data. 
The default solar position algorithm is based on Reda and Andreas (2004). Our implementation is pretty fast, but you can make it even faster if you install numba and use add  method='nrel_numba' to the function call below.
End of explanation
dni_extra = irradiance.extraradiation(fm.time)
#dni_extra.plot()
#plt.ylabel('Extra terrestrial radiation ($W/m^{-2}$)')
Explanation: The funny looking jump in the azimuth is just due to the coarse time sampling in the TMY file.
DNI ET
Calculate extra terrestrial radiation. This is needed for many plane of array diffuse irradiance models.
End of explanation
airmass = atmosphere.relativeairmass(solpos['apparent_zenith'])
#airmass.plot()
#plt.ylabel('Airmass')
Explanation: Airmass
Calculate airmass. Lots of model options here, see the atmosphere module tutorial for more details.
End of explanation
poa_sky_diffuse = irradiance.haydavies(surface_tilt, surface_azimuth,
                                             forecast_data['dhi'], forecast_data['dni'], dni_extra,
                                             solpos['apparent_zenith'], solpos['azimuth'])
#poa_sky_diffuse.plot()
#plt.ylabel('Irradiance ($W/m^{-2}$)')
Explanation: The funny appearance is due to aliasing and setting invalid numbers equal to NaN. Replot just a day or two and you'll see that the numbers are right.
POA sky diffuse
Use the Hay Davies model to calculate the plane of array diffuse sky radiation. See the irradiance module tutorial for comparisons of different models.
End of explanation
poa_ground_diffuse = irradiance.grounddiffuse(surface_tilt, ghi, albedo=albedo)
#poa_ground_diffuse.plot()
#plt.ylabel('Irradiance ($W/m^{-2}$)')
Explanation: POA ground diffuse
Calculate ground diffuse. We specified the albedo above. You could have also provided a string to the surface_type keyword argument.
End of explanation
aoi = irradiance.aoi(surface_tilt, surface_azimuth, solpos['apparent_zenith'], solpos['azimuth'])
#aoi.plot()
#plt.ylabel('Angle of incidence (deg)')
Explanation: AOI
Calculate AOI
End of explanation
poa_irrad = irradiance.globalinplane(aoi, forecast_data['dni'], poa_sky_diffuse, poa_ground_diffuse)
poa_irrad.plot()
plt.ylabel('Irradiance ($W/m^{-2}$)')
plt.title('POA Irradiance')
Explanation: Note that AOI has values greater than 90 deg. This is ok.
POA total
Calculate POA irradiance
End of explanation
temperature = forecast_data['temp_air']
wnd_spd = forecast_data['wind_speed']
pvtemps = pvsystem.sapm_celltemp(poa_irrad['poa_global'], wnd_spd, temperature)
pvtemps.plot()
plt.ylabel('Temperature (C)')
Explanation: Cell and module temperature
Calculate pv cell and module temperature
End of explanation
sandia_modules = pvsystem.retrieve_sam('SandiaMod')
Explanation: DC power using SAPM
Get module data from the web.
End of explanation
sandia_module = sandia_modules.Canadian_Solar_CS5P_220M___2009_
sandia_module
Explanation: Choose a particular module
End of explanation
effective_irradiance = pvsystem.sapm_effective_irradiance(poa_irrad.poa_direct, poa_irrad.poa_diffuse, 
                                                          airmass, aoi, sandia_module)
sapm_out = pvsystem.sapm(effective_irradiance, pvtemps['temp_cell'], sandia_module)
#print(sapm_out.head())
sapm_out[['p_mp']].plot()
plt.ylabel('DC Power (W)')
Explanation: Run the SAPM using the parameters we calculated above.
End of explanation
sapm_inverters = pvsystem.retrieve_sam('sandiainverter')
Explanation: AC power using SAPM
Get the inverter database from the web
End of explanation
sapm_inverter = sapm_inverters['ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_']
sapm_inverter
p_ac = pvsystem.snlinverter(sapm_out.v_mp, sapm_out.p_mp, sapm_inverter)
p_ac.plot()
plt.ylabel('AC Power (W)')
plt.ylim(0, None)
Explanation: Choose a particular inverter
End of explanation
p_ac[start:start+pd.Timedelta(days=2)].plot()
Explanation: Plot just a few days.
End of explanation
p_ac.describe()
p_ac.index.freq
# integrate power to find energy yield over the forecast period
p_ac.sum() * 3
Explanation: Some statistics on the AC power
End of explanation
<END_TASK>