Skip to content

ModelChain 0.7 deprecations, remove times kwarg #773

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 12 commits into from
Sep 16, 2019
16 changes: 14 additions & 2 deletions docs/sphinx/source/whatsnew/v0.7.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ API Changes
old `pvsystem.sapm_celltemp` returned a `DataFrame` with both cell and module temperatures.
- Created `temperature.sapm_module` to return module temperature using the SAPM temperature model.
- Changed the order of arguments for`pvsystem.sapm_celltemp`,
`pvsystem.pvsyst_celltemp` and `PVSystem.sapm_celltemp` to be consistent
`pvsystem.pvsyst_celltemp` and `PVSystem.sapm_celltemp` to be consistent
among cell temperature model functions.
- Removed `model` as a kwarg from `temperature.sapm_cell` and
`temperature.pvsyst_cell`. These functions now require model-specific parameters.
Expand All @@ -35,7 +35,7 @@ API Changes
'open_rack_polymer_thinfilm_steel' and '22x_concentrator_tracker'
are considered obsolete and have been removed.
* Changes to `PVSystem` class
- Changed the `model` kwarg in `PVSystem.sapm_celltemp` and
- Changed the `model` kwarg in `PVSystem.sapm_celltemp` and
`PVSystem.pvsyst_celltemp` to `parameter_set`. `parameter_set` expects
a str which is a valid key for `temperature.TEMPERATURE_MODEL_PARAMETERS`
for the corresponding temperature model.
Expand Down Expand Up @@ -71,6 +71,15 @@ API Changes

* Calling :py:func:`pvlib.pvsystem.retrieve_sam` with no parameters will raise
an exception instead of displaying a dialog.
* The `times` keyword argument has been deprecated in the
:py:meth:`pvlib.modelchain.ModelChain.run_model`,
:py:meth:`pvlib.modelchain.ModelChain.prepare_inputs`, and
:py:meth:`pvlib.modelchain.ModelChain.complete_irradiance` methods.
Model times are now determined by the input `weather`. `DataFrame`.
Therefore, the `weather` DataFrame must have a `DatetimeIndex`.
The `weather` argument of the above methods is now the first, required
positional argument and the `times` argument is kept as the second keyword
argument for capability during the deprecation period.

Enhancements
~~~~~~~~~~~~
Expand Down Expand Up @@ -114,6 +123,9 @@ Removal of prior version deprecations
* Removed `atmosphere.relativeairmass`.
* Removed `solarposition.get_sun_rise_set_transit`.
* Removed `tmy` module.
* Removed `ModelChain.singlediode` method.
* Removed `ModelChain.prepare_inputs` clearsky assumption when no irradiance
data was provided.

Contributors
~~~~~~~~~~~~
Expand Down
152 changes: 64 additions & 88 deletions pvlib/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from functools import partial
import warnings
import pandas as pd

from pvlib import (atmosphere, clearsky, pvsystem, solarposition, temperature,
tools)
Expand Down Expand Up @@ -412,13 +411,6 @@ def dc_model(self, model):
self._dc_model = self.pvsyst
elif model == 'pvwatts':
self._dc_model = self.pvwatts_dc
elif model == 'singlediode':
warnings.warn('DC model keyword singlediode used for '
'ModelChain object. singlediode is '
'ambiguous, use desoto instead. singlediode '
'keyword will be removed in v0.7.0 and '
'later', pvlibDeprecationWarning)
self._dc_model = self.desoto
else:
raise ValueError(model + ' is not a valid DC power model')
else:
Expand Down Expand Up @@ -480,24 +472,6 @@ def cec(self):
def pvsyst(self):
return self._singlediode(self.system.calcparams_pvsyst)

def singlediode(self):
"""Deprecated"""
(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth) = (
self.system.calcparams_desoto(self.effective_irradiance,
self.cell_temperature))

self.desoto = (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)

self.dc = self.system.singlediode(
photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)

self.dc = self.system.scale_voltage_current_power(self.dc).fillna(0)

return self

def pvwatts_dc(self):
self.dc = self.system.pvwatts_dc(self.effective_irradiance,
self.cell_temperature)
Expand Down Expand Up @@ -746,7 +720,7 @@ def effective_irradiance_model(self):
fd*self.total_irrad['poa_diffuse'])
return self

def complete_irradiance(self, times=None, weather=None):
def complete_irradiance(self, weather, times=None):
"""
Determine the missing irradiation columns. Only two of the
following data columns (dni, ghi, dhi) are needed to calculate
Expand All @@ -758,19 +732,21 @@ def complete_irradiance(self, times=None, weather=None):
Parameters
----------
times : None or DatetimeIndex, default None
Times at which to evaluate the model. Can be None if
attribute `times` is already set.
weather : None or pandas.DataFrame, default None
Table with at least two columns containing one of the
following data sets: dni, dhi, ghi. Can be None if attribute
`weather` is already set.
weather : DataFrame
Column names must be ``'dni'``, ``'ghi'``, ``'dhi'``,
``'wind_speed'``, ``'temp_air'``. All irradiance components
are required. Air temperature of 20 C and wind speed
of 0 m/s will be added to the DataFrame if not provided.
times : None, deprecated
Deprecated argument included for API compatibility, but not
used internally. The index of the weather DataFrame is used
for times.
Returns
-------
self
Assigns attributes: times, weather
Assigns attributes: weather
Examples
--------
Expand All @@ -782,19 +758,23 @@ def complete_irradiance(self, times=None, weather=None):
>>> # my_weather containing 'dhi' and 'ghi'.
>>> mc = ModelChain(my_system, my_location) # doctest: +SKIP
>>> mc.complete_irradiance(my_datetime, my_weather) # doctest: +SKIP
>>> mc.run_model() # doctest: +SKIP
>>> mc.complete_irradiance(my_weather) # doctest: +SKIP
>>> mc.run_model(mc.weather) # doctest: +SKIP
>>> # my_weather containing 'dhi', 'ghi' and 'dni'.
>>> mc = ModelChain(my_system, my_location) # doctest: +SKIP
>>> mc.run_model(my_datetime, my_weather) # doctest: +SKIP
>>> mc.run_model(my_weather) # doctest: +SKIP
"""
if weather is not None:
self.weather = weather
self.weather = weather

if times is not None:
self.times = times
warnings.warn('times keyword argument is deprecated and will be '
'removed in 0.8. The index of the weather DataFrame '
'is used for times.', pvlibDeprecationWarning)

self.solar_position = self.location.get_solarposition(
self.times, method=self.solar_position_method)
self.weather.index, method=self.solar_position_method)

icolumns = set(self.weather.columns)
wrn_txt = ("This function is not safe at the moment.\n" +
"Results can be too high or negative.\n" +
Expand All @@ -803,7 +783,7 @@ def complete_irradiance(self, times=None, weather=None):

if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns:
clearsky = self.location.get_clearsky(
times, solar_position=self.solar_position)
self.weather.index, solar_position=self.solar_position)
self.weather.loc[:, 'dni'] = pvlib.irradiance.dni(
self.weather.loc[:, 'ghi'], self.weather.loc[:, 'dhi'],
self.solar_position.zenith,
Expand All @@ -822,62 +802,54 @@ def complete_irradiance(self, times=None, weather=None):

return self

def prepare_inputs(self, times=None, weather=None):
def prepare_inputs(self, weather, times=None):
"""
Prepare the solar position, irradiance, and weather inputs to
the model.
Parameters
----------
times : None or DatetimeIndex, default None
Times at which to evaluate the model. Can be None if
attribute `times` is already set.
weather : None or DataFrame, default None
If ``None``, the weather attribute is used. Column names
must be ``'dni'``, ``'ghi'``, ``'dhi'``, ``'wind_speed'``,
``'temp_air'``. All irradiance components are required.
Assumes air temperature is 20 C and wind speed is 0 m/s if
not provided.
weather : DataFrame
Column names must be ``'dni'``, ``'ghi'``, ``'dhi'``,
``'wind_speed'``, ``'temp_air'``. All irradiance components
are required. Air temperature of 20 C and wind speed
of 0 m/s will be added to the DataFrame if not provided.
times : None, deprecated
Deprecated argument included for API compatibility, but not
used internally. The index of the weather DataFrame is used
for times.
Notes
-----
Assigns attributes: ``times``, ``solar_position``, ``airmass``,
Assigns attributes: ``solar_position``, ``airmass``,
``total_irrad``, `aoi`
See also
--------
ModelChain.complete_irradiance
"""
if weather is not None:
self.weather = weather
if self.weather is None:
self.weather = pd.DataFrame(index=times)

if not {'ghi', 'dni', 'dhi'} <= set(weather.columns):
raise ValueError(
"Uncompleted irradiance data set. Please check your input "
"data.\nData set needs to have 'dni', 'dhi' and 'ghi'.\n"
"Detected data: {0}".format(list(weather.columns)))

self.weather = weather

if times is not None:
self.times = times
warnings.warn('times keyword argument is deprecated and will be '
'removed in 0.8. The index of the weather DataFrame '
'is used for times.', pvlibDeprecationWarning)

self.times = self.weather.index

self.solar_position = self.location.get_solarposition(
self.times, method=self.solar_position_method)
self.weather.index, method=self.solar_position_method)

self.airmass = self.location.get_airmass(
solar_position=self.solar_position, model=self.airmass_model)

if not any([x in ['ghi', 'dni', 'dhi'] for x in self.weather.columns]):
warnings.warn('Clear sky assumption for no input irradiance is '
'deprecated and will be removed in v0.7.0. Use '
'location.get_clearsky instead',
pvlibDeprecationWarning)
self.weather[['ghi', 'dni', 'dhi']] = self.location.get_clearsky(
self.solar_position.index, self.clearsky_model,
solar_position=self.solar_position,
airmass_absolute=self.airmass['airmass_absolute'])

if not {'ghi', 'dni', 'dhi'} <= set(self.weather.columns):
raise ValueError(
"Uncompleted irradiance data set. Please check your input "
"data.\nData set needs to have 'dni', 'dhi' and 'ghi'.\n"
"Detected data: {0}".format(list(self.weather.columns)))

# PVSystem.get_irradiance and SingleAxisTracker.get_irradiance
# and PVSystem.get_aoi and SingleAxisTracker.get_aoi
# have different method signatures. Use partial to handle
Expand Down Expand Up @@ -921,32 +893,36 @@ def prepare_inputs(self, times=None, weather=None):
self.weather['temp_air'] = 20
return self

def run_model(self, times=None, weather=None):
def run_model(self, weather, times=None):
"""
Run the model.
Parameters
----------
times : None or DatetimeIndex, default None
Times at which to evaluate the model. Can be None if
attribute `times` is already set.
weather : None or DataFrame, default None
If ``None``, the weather attribute is used. Column names
must be ``'dni'``, ``'ghi'``, ``'dhi'``, ``'wind_speed'``,
``'temp_air'``. All irradiance components are required.
Assumes air temperature is 20 C and wind speed is 0 m/s if
not provided.
weather : DataFrame
Column names must be ``'dni'``, ``'ghi'``, ``'dhi'``,
``'wind_speed'``, ``'temp_air'``. All irradiance components
are required. Air temperature of 20 C and wind speed
of 0 m/s will be added to the DataFrame if not provided.
times : None, deprecated
Deprecated argument included for API compatibility, but not
used internally. The index of the weather DataFrame is used
for times.
Returns
-------
self
Assigns attributes: times, solar_position, airmass, irradiance,
Assigns attributes: solar_position, airmass, irradiance,
total_irrad, effective_irradiance, weather, cell_temperature, aoi,
aoi_modifier, spectral_modifier, dc, ac, losses.
"""
if times is not None:
warnings.warn('times keyword argument is deprecated and will be '
'removed in 0.8. The index of the weather DataFrame '
'is used for times.', pvlibDeprecationWarning)

self.prepare_inputs(times, weather)
self.prepare_inputs(weather)
self.aoi_model()
self.spectral_model()
self.effective_irradiance_model()
Expand Down
Loading