Skip to content

deprecate Location, PVSystem, ModelChain kwargs, LocalizedPVSystem, LocalizedSingleAxisTracker #1053

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 9 commits into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 0 additions & 5 deletions docs/sphinx/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ corresponding procedural code.
pvsystem.PVSystem
tracking.SingleAxisTracker
modelchain.ModelChain
pvsystem.LocalizedPVSystem
tracking.LocalizedSingleAxisTracker


Solar Position
Expand Down Expand Up @@ -209,7 +207,6 @@ wrap the functions listed below. See its documentation for details.
:toctree: generated/

pvsystem.PVSystem
pvsystem.LocalizedPVSystem

Incident angle modifiers
------------------------
Expand Down Expand Up @@ -421,8 +418,6 @@ The :py:class:`~tracking.SingleAxisTracker` inherits from
tracking.SingleAxisTracker
tracking.SingleAxisTracker.singleaxis
tracking.SingleAxisTracker.get_irradiance
tracking.SingleAxisTracker.localize
tracking.LocalizedSingleAxisTracker

Functions
---------
Expand Down
1 change: 0 additions & 1 deletion docs/sphinx/source/comparison_pvlib_matlab.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ Major differences
* pvlib-python implements a handful of class designed to simplify the
PV modeling process. These include :py:class:`~pvlib.location.Location`,
:py:class:`~pvlib.pvsystem.PVSystem`,
:py:class:`~pvlib.pvsystem.LocalizedPVSystem`,
:py:class:`~pvlib.tracking.SingleAxisTracker`,
and
:py:class:`~pvlib.modelchain.ModelChain`.
Expand Down
78 changes: 0 additions & 78 deletions docs/sphinx/source/introtutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -178,81 +178,3 @@ by examining the parameters defined for the module.
plt.ylabel('Yearly energy yield (W hr)')
@suppress
plt.close();


Object oriented (LocalizedPVSystem)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The second object oriented paradigm uses a model where a
:py:class:`~pvlib.pvsystem.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 :py:class:`~pvlib.pvsystem.LocalizedPVSystem` inherits from both
:py:class:`~pvlib.pvsystem.PVSystem` and
:py:class:`~pvlib.location.Location`, while the
:py:class:`~pvlib.tracking.LocalizedSingleAxisTracker` inherits from
:py:class:`~pvlib.tracking.SingleAxisTracker` (itself a subclass of
:py:class:`~pvlib.pvsystem.PVSystem`) and
:py:class:`~pvlib.location.Location`. The
:py:class:`~pvlib.pvsystem.LocalizedPVSystem` and
:py:class:`~pvlib.tracking.LocalizedSingleAxisTracker` classes may
contain bugs due to the relative difficulty of implementing multiple
inheritance. The :py:class:`~pvlib.pvsystem.LocalizedPVSystem` and
:py:class:`~pvlib.tracking.LocalizedSingleAxisTracker` may be deprecated
in a future release. We recommend that most modeling workflows implement
:py:class:`~pvlib.location.Location`,
:py:class:`~pvlib.pvsystem.PVSystem`, and
:py:class:`~pvlib.modelchain.ModelChain`.

The following code demonstrates how to use a
:py:class:`~pvlib.pvsystem.LocalizedPVSystem` object to accomplish our
modeling goal:

.. ipython:: python

from pvlib.pvsystem import LocalizedPVSystem

energies = {}
for latitude, longitude, name, altitude, timezone in coordinates:
localized_system = LocalizedPVSystem(module_parameters=module,
inverter_parameters=inverter,
temperature_model_parameters=temperature_model_parameters,
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'])
tcell = localized_system.sapm_celltemp(total_irrad['poa_global'],
temp_air, wind_speed)
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, tcell)
ac = localized_system.snlinverter(dc['v_mp'], dc['p_mp'])
annual_energy = ac.sum()
energies[name] = annual_energy

energies = pd.Series(energies)

# based on the parameters specified above, these are in W*hrs
print(energies.round(0))

energies.plot(kind='bar', rot=0)
@savefig localized-pvsystem-energies.png width=6in
plt.ylabel('Yearly energy yield (W hr)')
@suppress
plt.close();
11 changes: 11 additions & 0 deletions docs/sphinx/source/whatsnew/v0.8.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ API Changes with Deprecations
glass/glass module in open racking and emit a warning. In v0.9, users must
provide ``temperature_model_parameters`` or a valid combination of
``module_type`` and ``racking_model``. (:issue:`1030`, :pull:`1033`)
* Deprecated arbitrary keyword arguments for
:py:class:`pvlib.location.Location`, :py:class:`pvlib.pvsystem.PVSystem`,
:py:class:`pvlib.tracking.SingleAxisTracker`, and
:py:class:`pvlib.modelchain.ModelChain`. Supplying arbitrary keyword
to these objects will result in TypeErrors in v0.9. (:issue:`1029`, :pull:`1053`)
* ``pvlib.pvsystem.LocalizedPVSystem`` and ``pvlib.pvsystem.LocalizedSingleAxisTracker``
are deprecated and will be removed in 0.9. Use
:py:class:`pvlib.location.Location`, :py:class:`pvlib.pvsystem.PVSystem`,
:py:class:`pvlib.tracking.SingleAxisTracker`, and
:py:class:`pvlib.modelchain.ModelChain` instead.
(:issue:`1029`, :pull:`1034`, :pull:`1053`)

API Changes
~~~~~~~~~~~
Expand Down
12 changes: 8 additions & 4 deletions pvlib/location.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
# Will Holmgren, University of Arizona, 2014-2016.

import datetime
import warnings

import pandas as pd
import pytz

from pvlib import solarposition, clearsky, atmosphere, irradiance
from pvlib._deprecation import pvlibDeprecationWarning


class Location:
Expand Down Expand Up @@ -48,10 +50,6 @@ class Location:
name : None or string, default None.
Sets the name attribute of the Location object.

**kwargs
Arbitrary keyword arguments.
Included for compatibility, but not used.

See also
--------
pvlib.pvsystem.PVSystem
Expand Down Expand Up @@ -82,6 +80,12 @@ def __init__(self, latitude, longitude, tz='UTC', altitude=0,

self.name = name

if kwargs:
warnings.warn(
'Arbitrary Location kwargs are deprecated and will be '
'removed in v0.9', pvlibDeprecationWarning
)

def __repr__(self):
attrs = ['name', 'latitude', 'longitude', 'altitude', 'tz']
return ('Location: \n ' + '\n '.join(
Expand Down
10 changes: 6 additions & 4 deletions pvlib/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,6 @@ class ModelChain:

name: None or str, default None
Name of ModelChain instance.

**kwargs
Arbitrary keyword arguments. Included for compatibility, but not
used.
"""

def __init__(self, system, location,
Expand Down Expand Up @@ -372,6 +368,12 @@ def __init__(self, system, location,
self.times = None
self.solar_position = None

if kwargs:
warnings.warn(
'Arbitrary ModelChain kwargs are deprecated and will be '
'removed in v0.9', pvlibDeprecationWarning
)

@classmethod
def with_pvwatts(cls, system, location,
orientation_strategy=None,
Expand Down
17 changes: 12 additions & 5 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,6 @@ class PVSystem:
:py:class:`~pvlib.modelchain.ModelChain`
objects.

See the :py:class:`LocalizedPVSystem` class for an object model that
describes an installed PV system.

The class supports basic system topologies consisting of:

* `N` total modules arranged in series
Expand Down Expand Up @@ -164,7 +161,6 @@ class PVSystem:
--------
pvlib.location.Location
pvlib.tracking.SingleAxisTracker
pvlib.pvsystem.LocalizedPVSystem
"""

def __init__(self,
Expand Down Expand Up @@ -220,6 +216,12 @@ def __init__(self,

self.name = name

if kwargs:
warnings.warn(
'Arbitrary PVSystem kwargs are deprecated and will be '
'removed in v0.9', pvlibDeprecationWarning
)

def __repr__(self):
attrs = ['name', 'surface_tilt', 'surface_azimuth', 'module',
'inverter', 'albedo', 'racking_model', 'module_type',
Expand Down Expand Up @@ -819,9 +821,12 @@ def pvwatts_ac(self, pdc):
return inverter.pvwatts(pdc, self.inverter_parameters['pdc0'],
**kwargs)

@deprecated('0.8', alternative='PVSystem, Location, and ModelChain',
name='PVSystem.localize', removal='0.9')
def localize(self, location=None, latitude=None, longitude=None,
**kwargs):
"""Creates a LocalizedPVSystem object using this object
"""
Creates a LocalizedPVSystem object using this object
and location data. Must supply either location object or
latitude, longitude, and any location kwargs

Expand All @@ -843,6 +848,8 @@ def localize(self, location=None, latitude=None, longitude=None,
return LocalizedPVSystem(pvsystem=self, location=location)


@deprecated('0.8', alternative='PVSystem, Location, and ModelChain',
name='LocalizedPVSystem', removal='0.9')
class LocalizedPVSystem(PVSystem, Location):
"""
The LocalizedPVSystem class defines a standard set of installed PV
Expand Down
10 changes: 9 additions & 1 deletion pvlib/tests/test_location.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
from pvlib.solarposition import declination_spencer71
from pvlib.solarposition import equation_of_time_spencer71
from test_solarposition import expected_solpos, golden, golden_mst
from conftest import requires_ephem, requires_tables
from pvlib._deprecation import pvlibDeprecationWarning
from conftest import requires_ephem, requires_tables, fail_on_pvlib_version


def test_location_required():
Expand Down Expand Up @@ -323,3 +324,10 @@ def test_get_sun_rise_set_transit_valueerror(golden):
tz='MST')
with pytest.raises(ValueError):
golden.get_sun_rise_set_transit(times, method='eyeball')


@fail_on_pvlib_version('0.9')
def test_deprecated_09():
match = "Arbitrary Location kwargs"
with pytest.warns(pvlibDeprecationWarning, match=match):
Location(32.2, -111, arbitrary_kwarg='value')
7 changes: 7 additions & 0 deletions pvlib/tests/test_modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,13 @@ def test_deprecated_09(sapm_dc_snl_ac_system, cec_dc_adr_ac_system,
aoi_model='no_loss', spectral_model='no_loss')


@fail_on_pvlib_version('0.9')
def test_ModelChain_kwargs_deprecated_09(sapm_dc_snl_ac_system, location):
match = "Arbitrary ModelChain kwargs"
with pytest.warns(pvlibDeprecationWarning, match=match):
ModelChain(sapm_dc_snl_ac_system, location, arbitrary_kwarg='value')


def test_basic_chain_required(sam_data, cec_inverter_parameters,
sapm_temperature_cs5p_220m):
times = pd.date_range(start='20160101 1200-0700',
Expand Down
34 changes: 23 additions & 11 deletions pvlib/tests/test_pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1064,20 +1064,24 @@ def test_PVSystem_get_irradiance():
assert_frame_equal(irradiance, expected, check_less_precise=2)


@fail_on_pvlib_version('0.9')
def test_PVSystem_localize_with_location():
system = pvsystem.PVSystem(module='blah', inverter='blarg')
location = Location(latitude=32, longitude=-111)
localized_system = system.localize(location=location)
with pytest.warns(pvlibDeprecationWarning):
localized_system = system.localize(location=location)

assert localized_system.module == 'blah'
assert localized_system.inverter == 'blarg'
assert localized_system.latitude == 32
assert localized_system.longitude == -111


@fail_on_pvlib_version('0.9')
def test_PVSystem_localize_with_latlon():
system = pvsystem.PVSystem(module='blah', inverter='blarg')
localized_system = system.localize(latitude=32, longitude=-111)
with pytest.warns(pvlibDeprecationWarning):
localized_system = system.localize(latitude=32, longitude=-111)

assert localized_system.module == 'blah'
assert localized_system.inverter == 'blarg'
Expand All @@ -1103,11 +1107,13 @@ def test_PVSystem___repr__():
assert system.__repr__() == expected


@fail_on_pvlib_version('0.9')
def test_PVSystem_localize___repr__():
system = pvsystem.PVSystem(
module='blah', inverter='blarg', name='pv ftw',
temperature_model_parameters={'a': -3.56})
localized_system = system.localize(latitude=32, longitude=-111)
with pytest.warns(pvlibDeprecationWarning):
localized_system = system.localize(latitude=32, longitude=-111)
# apparently name is not preserved when creating a system using localize
expected = """LocalizedPVSystem:
name: None
Expand All @@ -1131,23 +1137,26 @@ def test_PVSystem_localize___repr__():
# when they are attached to LocalizedPVSystem, but
# that's probably not necessary at this point.


@fail_on_pvlib_version('0.9')
def test_LocalizedPVSystem_creation():
localized_system = pvsystem.LocalizedPVSystem(latitude=32,
longitude=-111,
module='blah',
inverter='blarg')
with pytest.warns(pvlibDeprecationWarning):
localized_system = pvsystem.LocalizedPVSystem(latitude=32,
longitude=-111,
module='blah',
inverter='blarg')

assert localized_system.module == 'blah'
assert localized_system.inverter == 'blarg'
assert localized_system.latitude == 32
assert localized_system.longitude == -111


@fail_on_pvlib_version('0.9')
def test_LocalizedPVSystem___repr__():
localized_system = pvsystem.LocalizedPVSystem(
latitude=32, longitude=-111, module='blah', inverter='blarg',
name='my name', temperature_model_parameters={'a': -3.56})
with pytest.warns(pvlibDeprecationWarning):
localized_system = pvsystem.LocalizedPVSystem(
latitude=32, longitude=-111, module='blah', inverter='blarg',
name='my name', temperature_model_parameters={'a': -3.56})

expected = """LocalizedPVSystem:
name: my name
Expand Down Expand Up @@ -1311,3 +1320,6 @@ def test_deprecated_09(cec_inverter_parameters, adr_inverter_parameters):
system = pvsystem.PVSystem()
with pytest.warns(pvlibDeprecationWarning, match=match):
system.sapm_celltemp(1, 2, 3)
match = "Arbitrary PVSystem kwargs"
with pytest.warns(pvlibDeprecationWarning, match=match):
system = pvsystem.PVSystem(arbitrary_kwarg='value')
Loading