Package Overview¶
Introduction¶
The core mission of pvlib-python is to provide open, reliable, interoperable, and benchmark implementations of PV system models.
There are at least as many opinions about how to model PV systems as there are modelers of PV systems, so pvlib-python provides several modeling paradigms.
Modeling paradigms¶
The backbone of pvlib-python is well-tested procedural code that implements PV system models. pvlib-python also provides a collection of classes for users that prefer object-oriented programming. These classes can help users keep track of data in a more organized way, provide some “smart” functions with more flexible inputs, and simplify the modeling process for common situations. The classes do not add any algorithms beyond what’s available in the procedural code, and most of the object methods are simple wrappers around the corresponding procedural code.
Let’s use each of these pvlib modeling paradigms to calculate the yearly energy yield for a given hardware configuration at a handful of sites listed below.
In [1]: import pandas as pd
In [2]: import matplotlib.pyplot as plt
# seaborn makes the plots look nicer
In [3]: import seaborn as sns
In [4]: sns.set_color_codes()
In [5]: naive_times = pd.DatetimeIndex(start='2015', end='2016', freq='1h')
# very approximate
# latitude, longitude, name, altitude, timezone
In [6]: coordinates = [(30, -110, 'Tucson', 700, 'Etc/GMT+7'),
...: (35, -105, 'Albuquerque', 1500, 'Etc/GMT+7'),
...: (40, -120, 'San Francisco', 10, 'Etc/GMT+8'),
...: (50, 10, 'Berlin', 34, 'Etc/GMT-1')]
...:
In [7]: import pvlib
# get the module and inverter specifications from SAM
In [8]: sandia_modules = pvlib.pvsystem.retrieve_sam('SandiaMod')
In [9]: sapm_inverters = pvlib.pvsystem.retrieve_sam('cecinverter')
In [10]: module = sandia_modules['Canadian_Solar_CS5P_220M___2009_']
In [11]: inverter = sapm_inverters['ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_']
# specify constant ambient air temp and wind for simplicity
In [12]: temp_air = 20
In [13]: wind_speed = 0
Procedural¶
The straightforward procedural code can be used for all modeling steps in pvlib-python.
The following code demonstrates how to use the procedural code to accomplish our system modeling goal:
In [14]: system = {'module': module, 'inverter': inverter,
....: 'surface_azimuth': 180}
....:
In [15]: energies = {}
In [16]: for latitude, longitude, name, altitude, timezone in coordinates:
....: times = naive_times.tz_localize(timezone)
....: system['surface_tilt'] = latitude
....: solpos = pvlib.solarposition.get_solarposition(times, latitude, longitude)
....: dni_extra = pvlib.irradiance.extraradiation(times)
....: dni_extra = pd.Series(dni_extra, index=times)
....: airmass = pvlib.atmosphere.relativeairmass(solpos['apparent_zenith'])
....: pressure = pvlib.atmosphere.alt2pres(altitude)
....: am_abs = pvlib.atmosphere.absoluteairmass(airmass, pressure)
....: tl = pvlib.clearsky.lookup_linke_turbidity(times, latitude, longitude)
....: cs = pvlib.clearsky.ineichen(solpos['apparent_zenith'], am_abs, tl,
....: dni_extra=dni_extra, altitude=altitude)
....: aoi = pvlib.irradiance.aoi(system['surface_tilt'], system['surface_azimuth'],
....: solpos['apparent_zenith'], solpos['azimuth'])
....: total_irrad = pvlib.irradiance.total_irrad(system['surface_tilt'],
....: system['surface_azimuth'],
....: solpos['apparent_zenith'],
....: solpos['azimuth'],
....: cs['dni'], cs['ghi'], cs['dhi'],
....: dni_extra=dni_extra,
....: model='haydavies')
....: temps = pvlib.pvsystem.sapm_celltemp(total_irrad['poa_global'],
....: wind_speed, temp_air)
....: effective_irradiance = pvlib.pvsystem.sapm_effective_irradiance(
....: total_irrad['poa_direct'], total_irrad['poa_diffuse'],
....: am_abs, aoi, module)
....: dc = pvlib.pvsystem.sapm(effective_irradiance, temps['temp_cell'], module)
....: ac = pvlib.pvsystem.snlinverter(dc['v_mp'], dc['p_mp'], inverter)
....: annual_energy = ac.sum()
....: energies[name] = annual_energy
....:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-16-da00fd02098b> in <module>()
2 times = naive_times.tz_localize(timezone)
3 system['surface_tilt'] = latitude
----> 4 solpos = pvlib.solarposition.get_solarposition(times, latitude, longitude)
5 dni_extra = pvlib.irradiance.extraradiation(times)
6 dni_extra = pd.Series(dni_extra, index=times)
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/solarposition.py in get_solarposition(time, latitude, longitude, altitude, pressure, method, temperature, **kwargs)
98 ephem_df = spa_python(time, latitude, longitude, altitude,
99 pressure, temperature,
--> 100 how='numpy', **kwargs)
101 elif method == 'pyephem':
102 ephem_df = pyephem(time, latitude, longitude, pressure, temperature,
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/solarposition.py in spa_python(time, latitude, longitude, altitude, pressure, temperature, delta_t, atmos_refract, how, numthreads, **kwargs)
324 app_zenith, zenith, app_elevation, elevation, azimuth, eot = spa.solar_position(
325 unixtime, lat, lon, elev, pressure, temperature, delta_t,
--> 326 atmos_refract, numthreads)
327
328 result = pd.DataFrame({'apparent_zenith': app_zenith, 'zenith': zenith,
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in solar_position(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
1149 result = do_calc(unixtime, lat, lon, elev, pressure,
1150 temp, delta_t, atmos_refract, numthreads,
-> 1151 sst, esd)
1152
1153 if not isinstance(result, np.ndarray):
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in solar_position_numpy(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
1058 return v, alpha, delta
1059 m = sun_mean_longitude(jme)
-> 1060 eot = equation_of_time(m, alpha, delta_psi, epsilon)
1061 H = local_hour_angle(v, lon, alpha)
1062 xi = equatorial_horizontal_parallax(R)
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in equation_of_time(sun_mean_longitude, geocentric_sun_right_ascension, longitude_nutation, true_ecliptic_obliquity)
892 less = E < -20
893 other = (E <= 20) & (E >= -20)
--> 894 E = greater * (E - 1440) + less * (E + 1440) + other * E
895 return E
896
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/indexes/base.pyc in _evaluate_numeric_binop(self, other)
3458
3459 from pandas.tseries.offsets import DateOffset
-> 3460 other = self._validate_for_numeric_binop(other, op, opstr)
3461
3462 # handle time-based others
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/indexes/base.pyc in _validate_for_numeric_binop(self, other, op, opstr)
3435 other = _values_from_object(other)
3436 if other.dtype.kind not in ['f', 'i']:
-> 3437 raise TypeError("cannot evaluate a numeric op "
3438 "with a non-numeric dtype")
3439 elif isinstance(other, (DateOffset, np.timedelta64,
TypeError: cannot evaluate a numeric op with a non-numeric dtype
In [17]: energies = pd.Series(energies)
# based on the parameters specified above, these are in W*hrs
In [18]: print(energies.round(0))
Series([], dtype: float64)
In [19]: energies.plot(kind='bar', rot=0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-19-2f97a4fe1d4b> in <module>()
----> 1 energies.plot(kind='bar', rot=0)
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in __call__(self, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
3597 colormap=colormap, table=table, yerr=yerr,
3598 xerr=xerr, label=label, secondary_y=secondary_y,
-> 3599 **kwds)
3600 __call__.__doc__ = plot_series.__doc__
3601
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in plot_series(data, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
2671 yerr=yerr, xerr=xerr,
2672 label=label, secondary_y=secondary_y,
-> 2673 **kwds)
2674
2675
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in _plot(data, x, y, subplots, ax, kind, **kwds)
2467 plot_obj = klass(data, subplots=subplots, ax=ax, kind=kind, **kwds)
2468
-> 2469 plot_obj.generate()
2470 plot_obj.draw()
2471 return plot_obj.result
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in generate(self)
1039 def generate(self):
1040 self._args_adjust()
-> 1041 self._compute_plot_data()
1042 self._setup_subplots()
1043 self._make_plot()
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in _compute_plot_data(self)
1148 if is_empty:
1149 raise TypeError('Empty {0!r}: no numeric data to '
-> 1150 'plot'.format(numeric_data.__class__.__name__))
1151
1152 self.data = numeric_data
TypeError: Empty 'DataFrame': no numeric data to plot
In [20]: plt.ylabel('Yearly energy yield (W hr)')
Out[20]: <matplotlib.text.Text at 0x7feee2ebc210>
pvlib-python provides a basic_chain()
function that implements much of the code above. Use this function with
a full understanding of what it is doing internally!
In [21]: from pvlib.modelchain import basic_chain
In [22]: energies = {}
In [23]: for latitude, longitude, name, altitude, timezone in coordinates:
....: dc, ac = basic_chain(naive_times.tz_localize(timezone),
....: latitude, longitude,
....: module, inverter,
....: altitude=altitude,
....: orientation_strategy='south_at_latitude_tilt')
....: annual_energy = ac.sum()
....: energies[name] = annual_energy
....:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-23-bb5c37b8c90f> in <module>()
4 module, inverter,
5 altitude=altitude,
----> 6 orientation_strategy='south_at_latitude_tilt')
7 annual_energy = ac.sum()
8 energies[name] = annual_energy
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/modelchain.py in basic_chain(times, latitude, longitude, module_parameters, inverter_parameters, irradiance, weather, surface_tilt, surface_azimuth, orientation_strategy, transposition_model, solar_position_method, airmass_model, altitude, pressure, **kwargs)
129 altitude=altitude,
130 pressure=pressure,
--> 131 **kwargs)
132
133 # possible error with using apparent zenith with some models
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/solarposition.py in get_solarposition(time, latitude, longitude, altitude, pressure, method, temperature, **kwargs)
98 ephem_df = spa_python(time, latitude, longitude, altitude,
99 pressure, temperature,
--> 100 how='numpy', **kwargs)
101 elif method == 'pyephem':
102 ephem_df = pyephem(time, latitude, longitude, pressure, temperature,
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/solarposition.py in spa_python(time, latitude, longitude, altitude, pressure, temperature, delta_t, atmos_refract, how, numthreads, **kwargs)
324 app_zenith, zenith, app_elevation, elevation, azimuth, eot = spa.solar_position(
325 unixtime, lat, lon, elev, pressure, temperature, delta_t,
--> 326 atmos_refract, numthreads)
327
328 result = pd.DataFrame({'apparent_zenith': app_zenith, 'zenith': zenith,
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in solar_position(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
1149 result = do_calc(unixtime, lat, lon, elev, pressure,
1150 temp, delta_t, atmos_refract, numthreads,
-> 1151 sst, esd)
1152
1153 if not isinstance(result, np.ndarray):
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in solar_position_numpy(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
1058 return v, alpha, delta
1059 m = sun_mean_longitude(jme)
-> 1060 eot = equation_of_time(m, alpha, delta_psi, epsilon)
1061 H = local_hour_angle(v, lon, alpha)
1062 xi = equatorial_horizontal_parallax(R)
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in equation_of_time(sun_mean_longitude, geocentric_sun_right_ascension, longitude_nutation, true_ecliptic_obliquity)
892 less = E < -20
893 other = (E <= 20) & (E >= -20)
--> 894 E = greater * (E - 1440) + less * (E + 1440) + other * E
895 return E
896
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/indexes/base.pyc in _evaluate_numeric_binop(self, other)
3458
3459 from pandas.tseries.offsets import DateOffset
-> 3460 other = self._validate_for_numeric_binop(other, op, opstr)
3461
3462 # handle time-based others
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/indexes/base.pyc in _validate_for_numeric_binop(self, other, op, opstr)
3435 other = _values_from_object(other)
3436 if other.dtype.kind not in ['f', 'i']:
-> 3437 raise TypeError("cannot evaluate a numeric op "
3438 "with a non-numeric dtype")
3439 elif isinstance(other, (DateOffset, np.timedelta64,
TypeError: cannot evaluate a numeric op with a non-numeric dtype
In [24]: energies = pd.Series(energies)
# based on the parameters specified above, these are in W*hrs
In [25]: print(energies.round(0))
Series([], dtype: float64)
In [26]: energies.plot(kind='bar', rot=0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-26-2f97a4fe1d4b> in <module>()
----> 1 energies.plot(kind='bar', rot=0)
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in __call__(self, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
3597 colormap=colormap, table=table, yerr=yerr,
3598 xerr=xerr, label=label, secondary_y=secondary_y,
-> 3599 **kwds)
3600 __call__.__doc__ = plot_series.__doc__
3601
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in plot_series(data, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
2671 yerr=yerr, xerr=xerr,
2672 label=label, secondary_y=secondary_y,
-> 2673 **kwds)
2674
2675
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in _plot(data, x, y, subplots, ax, kind, **kwds)
2467 plot_obj = klass(data, subplots=subplots, ax=ax, kind=kind, **kwds)
2468
-> 2469 plot_obj.generate()
2470 plot_obj.draw()
2471 return plot_obj.result
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in generate(self)
1039 def generate(self):
1040 self._args_adjust()
-> 1041 self._compute_plot_data()
1042 self._setup_subplots()
1043 self._make_plot()
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in _compute_plot_data(self)
1148 if is_empty:
1149 raise TypeError('Empty {0!r}: no numeric data to '
-> 1150 'plot'.format(numeric_data.__class__.__name__))
1151
1152 self.data = numeric_data
TypeError: Empty 'DataFrame': no numeric data to plot
In [27]: plt.ylabel('Yearly energy yield (W hr)')
Out[27]: <matplotlib.text.Text at 0x7feee2d580d0>
Object oriented (Location, PVSystem, ModelChain)¶
The first object oriented paradigm uses a model where a
PVSystem object represents an assembled
collection of modules, inverters, etc., a
Location object represents a particular
place on the planet, and a ModelChain
object describes the modeling chain used to calculate PV output at that
Location. This can be a useful paradigm if you prefer to think about the
PV system and its location as separate concepts or if you develop your
own ModelChain subclasses. It can also be helpful if you make extensive
use of Location-specific methods for other calculations.
The following code demonstrates how to use
Location,
PVSystem, and
ModelChain
objects to accomplish our system modeling goal:
In [28]: from pvlib.pvsystem import PVSystem
In [29]: from pvlib.location import Location
In [30]: from pvlib.modelchain import ModelChain
In [31]: system = PVSystem(module_parameters=module,
....: inverter_parameters=inverter)
....:
In [32]: energies = {}
In [33]: for latitude, longitude, name, altitude, timezone in coordinates:
....: location = Location(latitude, longitude, name=name, altitude=altitude,
....: tz=timezone)
....: mc = ModelChain(system, location,
....: orientation_strategy='south_at_latitude_tilt')
....: mc.run_model(naive_times.tz_localize(timezone))
....: annual_energy = mc.ac.sum()
....: energies[name] = annual_energy
....:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-33-ea2c6c6ff63f> in <module>()
4 mc = ModelChain(system, location,
5 orientation_strategy='south_at_latitude_tilt')
----> 6 mc.run_model(naive_times.tz_localize(timezone))
7 annual_energy = mc.ac.sum()
8 energies[name] = annual_energy
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/modelchain.py in run_model(self, times, irradiance, weather)
710 """
711
--> 712 self.prepare_inputs(times, irradiance, weather)
713 self.aoi_model()
714 self.spectral_model()
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/modelchain.py in prepare_inputs(self, times, irradiance, weather)
630 self.times = times
631
--> 632 self.solar_position = self.location.get_solarposition(self.times)
633
634 self.airmass = self.location.get_airmass(
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/location.py in get_solarposition(self, times, pressure, temperature, **kwargs)
165 pressure=pressure,
166 temperature=temperature,
--> 167 **kwargs)
168
169
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/solarposition.py in get_solarposition(time, latitude, longitude, altitude, pressure, method, temperature, **kwargs)
98 ephem_df = spa_python(time, latitude, longitude, altitude,
99 pressure, temperature,
--> 100 how='numpy', **kwargs)
101 elif method == 'pyephem':
102 ephem_df = pyephem(time, latitude, longitude, pressure, temperature,
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/solarposition.py in spa_python(time, latitude, longitude, altitude, pressure, temperature, delta_t, atmos_refract, how, numthreads, **kwargs)
324 app_zenith, zenith, app_elevation, elevation, azimuth, eot = spa.solar_position(
325 unixtime, lat, lon, elev, pressure, temperature, delta_t,
--> 326 atmos_refract, numthreads)
327
328 result = pd.DataFrame({'apparent_zenith': app_zenith, 'zenith': zenith,
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in solar_position(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
1149 result = do_calc(unixtime, lat, lon, elev, pressure,
1150 temp, delta_t, atmos_refract, numthreads,
-> 1151 sst, esd)
1152
1153 if not isinstance(result, np.ndarray):
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in solar_position_numpy(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
1058 return v, alpha, delta
1059 m = sun_mean_longitude(jme)
-> 1060 eot = equation_of_time(m, alpha, delta_psi, epsilon)
1061 H = local_hour_angle(v, lon, alpha)
1062 xi = equatorial_horizontal_parallax(R)
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in equation_of_time(sun_mean_longitude, geocentric_sun_right_ascension, longitude_nutation, true_ecliptic_obliquity)
892 less = E < -20
893 other = (E <= 20) & (E >= -20)
--> 894 E = greater * (E - 1440) + less * (E + 1440) + other * E
895 return E
896
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/indexes/base.pyc in _evaluate_numeric_binop(self, other)
3458
3459 from pandas.tseries.offsets import DateOffset
-> 3460 other = self._validate_for_numeric_binop(other, op, opstr)
3461
3462 # handle time-based others
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/indexes/base.pyc in _validate_for_numeric_binop(self, other, op, opstr)
3435 other = _values_from_object(other)
3436 if other.dtype.kind not in ['f', 'i']:
-> 3437 raise TypeError("cannot evaluate a numeric op "
3438 "with a non-numeric dtype")
3439 elif isinstance(other, (DateOffset, np.timedelta64,
TypeError: cannot evaluate a numeric op with a non-numeric dtype
In [34]: energies = pd.Series(energies)
# based on the parameters specified above, these are in W*hrs
In [35]: print(energies.round(0))
Series([], dtype: float64)
In [36]: energies.plot(kind='bar', rot=0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-36-2f97a4fe1d4b> in <module>()
----> 1 energies.plot(kind='bar', rot=0)
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in __call__(self, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
3597 colormap=colormap, table=table, yerr=yerr,
3598 xerr=xerr, label=label, secondary_y=secondary_y,
-> 3599 **kwds)
3600 __call__.__doc__ = plot_series.__doc__
3601
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in plot_series(data, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
2671 yerr=yerr, xerr=xerr,
2672 label=label, secondary_y=secondary_y,
-> 2673 **kwds)
2674
2675
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in _plot(data, x, y, subplots, ax, kind, **kwds)
2467 plot_obj = klass(data, subplots=subplots, ax=ax, kind=kind, **kwds)
2468
-> 2469 plot_obj.generate()
2470 plot_obj.draw()
2471 return plot_obj.result
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in generate(self)
1039 def generate(self):
1040 self._args_adjust()
-> 1041 self._compute_plot_data()
1042 self._setup_subplots()
1043 self._make_plot()
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in _compute_plot_data(self)
1148 if is_empty:
1149 raise TypeError('Empty {0!r}: no numeric data to '
-> 1150 'plot'.format(numeric_data.__class__.__name__))
1151
1152 self.data = numeric_data
TypeError: Empty 'DataFrame': no numeric data to plot
In [37]: plt.ylabel('Yearly energy yield (W hr)')
Out[37]: <matplotlib.text.Text at 0x7feee2ad0650>
See Will Holmgren’s ModelChain gist for more discussion about new features in ModelChain.
Object oriented (LocalizedPVSystem)¶
The second object oriented paradigm uses a model where a
LocalizedPVSystem represents a
PV system at a particular place on the planet. This can be a useful
paradigm if you’re thinking about a power plant that already exists.
The following code demonstrates how to use a
LocalizedPVSystem
object to accomplish our modeling goal:
In [38]: from pvlib.pvsystem import LocalizedPVSystem
In [39]: energies = {}
In [40]: for latitude, longitude, name, altitude, timezone in coordinates:
....: localized_system = LocalizedPVSystem(module_parameters=module,
....: inverter_parameters=inverter,
....: surface_tilt=latitude,
....: surface_azimuth=180,
....: latitude=latitude,
....: longitude=longitude,
....: name=name,
....: altitude=altitude,
....: tz=timezone)
....: times = naive_times.tz_localize(timezone)
....: clearsky = localized_system.get_clearsky(times)
....: solar_position = localized_system.get_solarposition(times)
....: total_irrad = localized_system.get_irradiance(solar_position['apparent_zenith'],
....: solar_position['azimuth'],
....: clearsky['dni'],
....: clearsky['ghi'],
....: clearsky['dhi'])
....: temps = localized_system.sapm_celltemp(total_irrad['poa_global'],
....: wind_speed, temp_air)
....: aoi = localized_system.get_aoi(solar_position['apparent_zenith'],
....: solar_position['azimuth'])
....: airmass = localized_system.get_airmass(solar_position=solar_position)
....: effective_irradiance = localized_system.sapm_effective_irradiance(
....: total_irrad['poa_direct'], total_irrad['poa_diffuse'],
....: airmass['airmass_absolute'], aoi)
....: dc = localized_system.sapm(effective_irradiance, temps['temp_cell'])
....: ac = localized_system.snlinverter(dc['v_mp'], dc['p_mp'])
....: annual_energy = ac.sum()
....: energies[name] = annual_energy
....:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-40-782e66a18e4f> in <module>()
10 tz=timezone)
11 times = naive_times.tz_localize(timezone)
---> 12 clearsky = localized_system.get_clearsky(times)
13 solar_position = localized_system.get_solarposition(times)
14 total_irrad = localized_system.get_irradiance(solar_position['apparent_zenith'],
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/location.py in get_clearsky(self, times, model, solar_position, dni_extra, **kwargs)
204 if solar_position is None:
205 solar_position = self.get_solarposition(times, pressure=pressure,
--> 206 **kwargs)
207
208 apparent_zenith = solar_position['apparent_zenith']
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/location.py in get_solarposition(self, times, pressure, temperature, **kwargs)
165 pressure=pressure,
166 temperature=temperature,
--> 167 **kwargs)
168
169
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/solarposition.py in get_solarposition(time, latitude, longitude, altitude, pressure, method, temperature, **kwargs)
98 ephem_df = spa_python(time, latitude, longitude, altitude,
99 pressure, temperature,
--> 100 how='numpy', **kwargs)
101 elif method == 'pyephem':
102 ephem_df = pyephem(time, latitude, longitude, pressure, temperature,
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/solarposition.py in spa_python(time, latitude, longitude, altitude, pressure, temperature, delta_t, atmos_refract, how, numthreads, **kwargs)
324 app_zenith, zenith, app_elevation, elevation, azimuth, eot = spa.solar_position(
325 unixtime, lat, lon, elev, pressure, temperature, delta_t,
--> 326 atmos_refract, numthreads)
327
328 result = pd.DataFrame({'apparent_zenith': app_zenith, 'zenith': zenith,
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in solar_position(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
1149 result = do_calc(unixtime, lat, lon, elev, pressure,
1150 temp, delta_t, atmos_refract, numthreads,
-> 1151 sst, esd)
1152
1153 if not isinstance(result, np.ndarray):
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in solar_position_numpy(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
1058 return v, alpha, delta
1059 m = sun_mean_longitude(jme)
-> 1060 eot = equation_of_time(m, alpha, delta_psi, epsilon)
1061 H = local_hour_angle(v, lon, alpha)
1062 xi = equatorial_horizontal_parallax(R)
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/checkouts/pvsystem_tutport/pvlib/spa.py in equation_of_time(sun_mean_longitude, geocentric_sun_right_ascension, longitude_nutation, true_ecliptic_obliquity)
892 less = E < -20
893 other = (E <= 20) & (E >= -20)
--> 894 E = greater * (E - 1440) + less * (E + 1440) + other * E
895 return E
896
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/indexes/base.pyc in _evaluate_numeric_binop(self, other)
3458
3459 from pandas.tseries.offsets import DateOffset
-> 3460 other = self._validate_for_numeric_binop(other, op, opstr)
3461
3462 # handle time-based others
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/indexes/base.pyc in _validate_for_numeric_binop(self, other, op, opstr)
3435 other = _values_from_object(other)
3436 if other.dtype.kind not in ['f', 'i']:
-> 3437 raise TypeError("cannot evaluate a numeric op "
3438 "with a non-numeric dtype")
3439 elif isinstance(other, (DateOffset, np.timedelta64,
TypeError: cannot evaluate a numeric op with a non-numeric dtype
In [41]: energies = pd.Series(energies)
# based on the parameters specified above, these are in W*hrs
In [42]: print(energies.round(0))
Series([], dtype: float64)
In [43]: energies.plot(kind='bar', rot=0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-43-2f97a4fe1d4b> in <module>()
----> 1 energies.plot(kind='bar', rot=0)
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in __call__(self, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
3597 colormap=colormap, table=table, yerr=yerr,
3598 xerr=xerr, label=label, secondary_y=secondary_y,
-> 3599 **kwds)
3600 __call__.__doc__ = plot_series.__doc__
3601
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in plot_series(data, kind, ax, figsize, use_index, title, grid, legend, style, logx, logy, loglog, xticks, yticks, xlim, ylim, rot, fontsize, colormap, table, yerr, xerr, label, secondary_y, **kwds)
2671 yerr=yerr, xerr=xerr,
2672 label=label, secondary_y=secondary_y,
-> 2673 **kwds)
2674
2675
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in _plot(data, x, y, subplots, ax, kind, **kwds)
2467 plot_obj = klass(data, subplots=subplots, ax=ax, kind=kind, **kwds)
2468
-> 2469 plot_obj.generate()
2470 plot_obj.draw()
2471 return plot_obj.result
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in generate(self)
1039 def generate(self):
1040 self._args_adjust()
-> 1041 self._compute_plot_data()
1042 self._setup_subplots()
1043 self._make_plot()
/home/docs/checkouts/readthedocs.org/user_builds/pvlib-python-dacoex/conda/pvsystem_tutport/lib/python2.7/site-packages/pandas/tools/plotting.pyc in _compute_plot_data(self)
1148 if is_empty:
1149 raise TypeError('Empty {0!r}: no numeric data to '
-> 1150 'plot'.format(numeric_data.__class__.__name__))
1151
1152 self.data = numeric_data
TypeError: Empty 'DataFrame': no numeric data to plot
In [44]: plt.ylabel('Yearly energy yield (W hr)')
Out[44]: <matplotlib.text.Text at 0x7fef07dcd190>
User extensions¶
There are many other ways to organize PV modeling code. We encourage you to build on these paradigms and to share your experiences with the pvlib community via issues and pull requests.
Getting support¶
The best way to get support is to make an issue on our GitHub issues page .
How do I contribute?¶
We’re so glad you asked! Please see our wiki for information and instructions on how to contribute. We really appreciate it!
Credits¶
The pvlib-python community thanks Sandia National Lab for developing PVLIB Matlab and for supporting Rob Andrews of Calama Consulting to port the library to Python. Will Holmgren thanks the DOE EERE Postdoctoral Fellowship program for support. The pvlib-python maintainers thank all of pvlib’s contributors of issues and especially pull requests. The pvlib-python community thanks all of the maintainers and contributors to the PyData stack.