Skip to content

remove 0.8 deprecations from pvsystem.py, modelchain.py, rework temperature model param deprecation #1033

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 19 commits into from
Aug 27, 2020
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/sphinx/source/whatsnew/v0.8.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ API Changes
:py:func:`pvlib.iotools.read_tmy3`, :py:meth:`pvlib.location.Location.from_tmy`, and
:py:class:`pvlib.pvsystem.LocalizedPVSystem` for alternatives. (:issue:`965`)
(:pull:`1008`)
* The following functions, methods, and arguments were deprecated in a previous
release and have now been removed:
* ``pvsystem.PVSystem.ashraeiam``. Use :py:meth:`~pvlib.pvsystem.PVSystem.get_iam`.
* ``pvsystem.PVSystem.physicaliam``. Use :py:meth:`~pvlib.pvsystem.PVSystem.get_iam`.
* ``pvsystem.PVSystem.sapm_aoi_loss``. Use :py:meth:`~pvlib.pvsystem.PVSystem.get_iam`.
* ``pvsystem.ashraeiam``. Use :py:func:`pvlib.iam.ashrae`.
* ``pvsystem.physicaliam``. Use :py:func:`pvlib.iam.physical`.
* ``pvsystem.sapm_aoi_loss``. Use :py:func:`pvlib.iam.sapm`.
* ``pvsystem.sapm_celltemp``. Use :py:func:`pvlib.temperature.sapm_cell`.
* ``pvsystem.pvsyst_celltemp``. Use :py:func:`pvlib.temperature.pvsyst`.
* ``times`` keyword argument of
:py:meth:`pvlib.modelchain.ModelChain.run_model`,
:py:meth:`pvlib.modelchain.ModelChain.complete_irradiance`, and
:py:meth:`pvlib.modelchain.ModelChain.prepare_inputs`.
The index of the input DataFrame is used instead.
* ``temp_model`` keyword argument of
:py:meth:`pvlib.modelchain.ModelChain`. Use ``temperature_model`` instead.

Enhancements
~~~~~~~~~~~~
Expand Down
51 changes: 3 additions & 48 deletions pvlib/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,24 +346,6 @@ def __init__(self, system, location,
self.ac_model = ac_model
self.aoi_model = aoi_model
self.spectral_model = spectral_model

# TODO: deprecated kwarg temp_model. Remove use of temp_model in v0.8
temp_model = kwargs.pop('temp_model', None)
if temp_model is not None:
if temperature_model is None:
warnings.warn('The temp_model keyword argument is deprecated.'
' Use temperature_model instead',
pvlibDeprecationWarning)
temperature_model = temp_model
elif temp_model == temperature_model:
warnings.warn('Provide only one of temperature_model or '
'temp_model (deprecated).',
pvlibDeprecationWarning)
else:
raise ValueError(
'Conflicting temperature_model {} and temp_model {}. '
'temp_model is deprecated. Specify only temperature_model.'
.format(temperature_model, temp_model))
self.temperature_model = temperature_model

self.losses_model = losses_model
Expand Down Expand Up @@ -945,7 +927,7 @@ def effective_irradiance_model(self):
fd*self.total_irrad['poa_diffuse'])
return self

def complete_irradiance(self, weather, times=None):
def complete_irradiance(self, weather):
"""
Determine the missing irradiation columns. Only two of the
following data columns (dni, ghi, dhi) are needed to calculate
Expand All @@ -962,10 +944,6 @@ def complete_irradiance(self, weather, times=None):
``'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
-------
Expand Down Expand Up @@ -994,11 +972,6 @@ def complete_irradiance(self, weather, times=None):
"""
self.weather = weather

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.solar_position = self.location.get_solarposition(
self.weather.index, method=self.solar_position_method)

Expand Down Expand Up @@ -1029,7 +1002,7 @@ def complete_irradiance(self, weather, times=None):

return self

def prepare_inputs(self, weather, times=None):
def prepare_inputs(self, weather):
"""
Prepare the solar position, irradiance, and weather inputs to
the model.
Expand All @@ -1041,10 +1014,6 @@ def prepare_inputs(self, weather, times=None):
``'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
-----
Expand All @@ -1064,11 +1033,6 @@ def prepare_inputs(self, weather, times=None):

self.weather = weather

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.times = self.weather.index
try:
kwargs = _build_kwargs(['pressure', 'temp_air'], weather)
Expand Down Expand Up @@ -1126,7 +1090,7 @@ def prepare_inputs(self, weather, times=None):
self.weather['temp_air'] = 20
return self

def run_model(self, weather, times=None):
def run_model(self, weather):
"""
Run the model.

Expand All @@ -1137,10 +1101,6 @@ def run_model(self, weather, times=None):
``'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
-------
Expand All @@ -1152,11 +1112,6 @@ def run_model(self, weather, times=None):
``dc``, ``ac``, ``losses``,
``diode_params`` (if dc_model is a single diode model)
"""
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(weather)
self.aoi_model()
self.spectral_model()
Expand Down
179 changes: 14 additions & 165 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,12 @@ class PVSystem(object):
def __init__(self,
surface_tilt=0, surface_azimuth=180,
albedo=None, surface_type=None,
module=None, module_type='glass_polymer',
module=None, module_type=None,
module_parameters=None,
temperature_model_parameters=None,
modules_per_string=1, strings_per_inverter=1,
inverter=None, inverter_parameters=None,
racking_model='open_rack', losses_parameters=None, name=None,
racking_model=None, losses_parameters=None, name=None,
**kwargs):

self.surface_tilt = surface_tilt
Expand All @@ -201,20 +201,21 @@ def __init__(self,
if temperature_model_parameters is None:
self.temperature_model_parameters = \
self._infer_temperature_model_params()
# TODO: in v0.8 check if an empty dict is returned and raise error
else:
self.temperature_model_parameters = temperature_model_parameters

# TODO: deprecated behavior if PVSystem.temperature_model_parameters
# are not specified. Remove in v0.8
if not any(self.temperature_model_parameters):
# warn user about change in default behavior in 0.9.
if all(x is None for x in
(temperature_model_parameters, module_type, racking_model)):
warnings.warn(
'Required temperature_model_parameters is not specified '
'and parameters are not inferred from racking_model and '
'module_type. Reverting to deprecated default: SAPM cell '
'temperature model parameters for a glass/glass module in '
'open racking. In the future '
'PVSystem.temperature_model_parameters will be required',
'temperature_model_parameters, racking_model, and module_type '
'are not specified. Reverting to deprecated default: SAPM '
'cell temperature model parameters for a glass/glass module '
'in open racking. In v0.9 '
'PVSystem.temperature_model_parameters will be empty dict '
'unless set by temperature_model_parameters or valid '
'combination of racking_model and module_type. Pass non-None '
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'in open racking. In v0.9 '
'PVSystem.temperature_model_parameters will be empty dict '
'unless set by temperature_model_parameters or valid '
'combination of racking_model and module_type. Pass non-None '
'in open racking. In v0.9, temperature_model_parameters or a valid '
'combination of racking_model and module_type will be required. '
' Pass non-None '

I'd prefer to be more specific how to use v0.9.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with "will be required" if the warning is emitted from PVSystem.sapm_celltemp. I don't like it if the warning is emitted from the PVSystem.__init__ because it suggests a positional argument.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PVSystem() has always been a valid, non-warned statement. There's never been a requirement that PVSystem is a complete description of a system according to some model. We can discuss changing that, but it's inconsistent to require temperature parameters and nothing else.

Agree, and point taken. I'm OK with the change proposed for ModelChain.infer_temperature_model.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed the text in the warning in the method

'value to any of these parameters to silence this warning.',
pvlibDeprecationWarning)
params = temperature._temperature_model_params(
'sapm', 'open_rack_glass_glass')
Expand Down Expand Up @@ -358,26 +359,6 @@ def get_iam(self, aoi, iam_model='physical'):
else:
raise ValueError(model + ' is not a valid IAM model')

def ashraeiam(self, aoi):
"""
Deprecated. Use ``PVSystem.get_iam`` instead.
"""
import warnings
warnings.warn('PVSystem.ashraeiam is deprecated and will be removed in'
'v0.8, use PVSystem.get_iam instead',
pvlibDeprecationWarning)
return PVSystem.get_iam(self, aoi, iam_model='ashrae')

def physicaliam(self, aoi):
"""
Deprecated. Use ``PVSystem.get_iam`` instead.
"""
import warnings
warnings.warn('PVSystem.physicaliam is deprecated and will be removed'
' in v0.8, use PVSystem.get_iam instead',
pvlibDeprecationWarning)
return PVSystem.get_iam(self, aoi, iam_model='physical')

def calcparams_desoto(self, effective_irradiance, temp_cell, **kwargs):
"""
Use the :py:func:`calcparams_desoto` function, the input
Expand Down Expand Up @@ -514,7 +495,7 @@ def sapm_celltemp(self, poa_global, temp_air, wind_speed):
def _infer_temperature_model_params(self):
# try to infer temperature model parameters from from racking_model
# and module_type
param_set = self.racking_model + '_' + self.module_type
param_set = '{}_{}'.format(self.racking_model, self.module_type)
if param_set in temperature.TEMPERATURE_MODEL_PARAMETERS['sapm']:
return temperature._temperature_model_params('sapm', param_set)
elif 'freestanding' in param_set:
Expand Down Expand Up @@ -543,16 +524,6 @@ def sapm_spectral_loss(self, airmass_absolute):
"""
return sapm_spectral_loss(airmass_absolute, self.module_parameters)

def sapm_aoi_loss(self, aoi):
"""
Deprecated. Use ``PVSystem.get_iam`` instead.
"""
import warnings
warnings.warn('PVSystem.sapm_aoi_loss is deprecated and will be'
' removed in v0.8, use PVSystem.get_iam instead',
pvlibDeprecationWarning)
return PVSystem.get_iam(self, aoi, iam_model='sapm')

def sapm_effective_irradiance(self, poa_direct, poa_diffuse,
airmass_absolute, aoi,
reference_irradiance=1000):
Expand Down Expand Up @@ -1071,27 +1042,6 @@ def calcparams_desoto(effective_irradiance, temp_cell,
Source: [4]
'''

# test for use of function pre-v0.6.0 API change
if isinstance(a_ref, dict) or \
(isinstance(a_ref, pd.Series) and ('a_ref' in a_ref.keys())):
import warnings
warnings.warn('module_parameters detected as fourth positional'
+ ' argument of calcparams_desoto. calcparams_desoto'
+ ' will require one argument for each module model'
+ ' parameter in v0.7.0 and later', DeprecationWarning)
try:
module_parameters = a_ref
a_ref = module_parameters['a_ref']
I_L_ref = module_parameters['I_L_ref']
I_o_ref = module_parameters['I_o_ref']
R_sh_ref = module_parameters['R_sh_ref']
R_s = module_parameters['R_s']
except Exception as e:
raise e('Module parameters could not be extracted from fourth'
+ ' positional argument of calcparams_desoto. Check that'
+ ' parameters are from the CEC database and/or update'
+ ' your code for the new API for calcparams_desoto')

# Boltzmann constant in eV/K
k = 8.617332478e-05

Expand Down Expand Up @@ -1624,16 +1574,6 @@ def sapm(effective_irradiance, temp_cell, module):
# reference_irradiance and expose
temp_ref = 25
irrad_ref = 1000
# TODO: remove this warning in v0.8 after deprecation period for change in
# effective irradiance units, made in v0.7
with np.errstate(invalid='ignore'): # turn off warning for NaN
ee = np.asarray(effective_irradiance)
ee_gt0 = ee[ee > 0.0]
if ee_gt0.size > 0 and np.all(ee_gt0 < 2.0):
import warnings
msg = 'effective_irradiance inputs appear to be in suns. Units ' \
'changed in v0.7 from suns to W/m2'
warnings.warn(msg, RuntimeWarning)

q = 1.60218e-19 # Elementary charge in units of coulombs
kb = 1.38066e-23 # Boltzmann's constant in units of J/K
Expand Down Expand Up @@ -1695,85 +1635,6 @@ def sapm(effective_irradiance, temp_cell, module):
return out


def _sapm_celltemp_translator(*args, **kwargs):
# TODO: remove this function after deprecation period for sapm_celltemp
new_kwargs = {}
# convert position arguments to kwargs
old_arg_list = ['poa_global', 'wind_speed', 'temp_air', 'model']
for pos in range(len(args)):
new_kwargs[old_arg_list[pos]] = args[pos]
# determine value for new kwarg 'model'
try:
param_set = new_kwargs['model']
new_kwargs.pop('model') # model is not a new kwarg
except KeyError:
# 'model' not in positional arguments, check kwargs
try:
param_set = kwargs['model']
kwargs.pop('model')
except KeyError:
# 'model' not in kwargs, use old default value
param_set = 'open_rack_glass_glass'
if type(param_set) is list:
new_kwargs.update({'a': param_set[0],
'b': param_set[1],
'deltaT': param_set[2]})
elif type(param_set) is dict:
new_kwargs.update(param_set)
else: # string
params = temperature._temperature_model_params('sapm', param_set)
new_kwargs.update(params)
new_kwargs.update(kwargs) # kwargs with unchanged names
new_kwargs['irrad_ref'] = 1000 # default for new kwarg
# convert old positional arguments to named kwargs
return temperature.sapm_cell(**new_kwargs)


sapm_celltemp = deprecated('0.7', alternative='temperature.sapm_cell',
name='sapm_celltemp', removal='0.8',
addendum='Note that the arguments and argument '
'order for temperature.sapm_cell are different '
'than for sapm_celltemp')(_sapm_celltemp_translator)


def _pvsyst_celltemp_translator(*args, **kwargs):
# TODO: remove this function after deprecation period for pvsyst_celltemp
new_kwargs = {}
# convert position arguments to kwargs
old_arg_list = ['poa_global', 'temp_air', 'wind_speed', 'eta_m',
'alpha_absorption', 'model_params']
for pos in range(len(args)):
new_kwargs[old_arg_list[pos]] = args[pos]
# determine value for new kwarg 'model'
try:
param_set = new_kwargs['model_params']
new_kwargs.pop('model_params') # model_params is not a new kwarg
except KeyError:
# 'model_params' not in positional arguments, check kwargs
try:
param_set = kwargs['model_params']
kwargs.pop('model_params')
except KeyError:
# 'model_params' not in kwargs, use old default value
param_set = 'freestanding'
if type(param_set) in (list, tuple):
new_kwargs.update({'u_c': param_set[0],
'u_v': param_set[1]})
else: # string
params = temperature._temperature_model_params('pvsyst', param_set)
new_kwargs.update(params)
new_kwargs.update(kwargs) # kwargs with unchanged names
# convert old positional arguments to named kwargs
return temperature.pvsyst_cell(**new_kwargs)


pvsyst_celltemp = deprecated(
'0.7', alternative='temperature.pvsyst_cell', name='pvsyst_celltemp',
removal='0.8', addendum='Note that the argument names for '
'temperature.pvsyst_cell are different than '
'for pvsyst_celltemp')(_pvsyst_celltemp_translator)


def sapm_spectral_loss(airmass_absolute, module):
"""
Calculates the SAPM spectral loss coefficient, F1.
Expand Down Expand Up @@ -2452,18 +2313,6 @@ def pvwatts_losses(soiling=2, shading=3, snow=0, mismatch=2, wiring=2,
return losses


ashraeiam = deprecated('0.7', alternative='iam.ashrae', name='ashraeiam',
removal='0.8')(iam.ashrae)


physicaliam = deprecated('0.7', alternative='iam.physical', name='physicaliam',
removal='0.8')(iam.physical)


sapm_aoi_loss = deprecated('0.7', alternative='iam.sapm', name='sapm_aoi_loss',
removal='0.8')(iam.sapm)


snlinverter = deprecated('0.8', alternative='inverter.sandia',
name='snlinverter', removal='0.9')(inverter.sandia)

Expand Down
Loading