diff --git a/docs/examples/plot_greensboro_kimber_soiling.py b/docs/examples/plot_greensboro_kimber_soiling.py index aa000b6c22..db9a97dd43 100644 --- a/docs/examples/plot_greensboro_kimber_soiling.py +++ b/docs/examples/plot_greensboro_kimber_soiling.py @@ -7,7 +7,7 @@ # %% # This example shows basic usage of pvlib's Kimber Soiling model [1]_ with -# :py:meth:`pvlib.losses.soiling_kimber`. +# :py:func:`pvlib.soiling.kimber`. # # References # ---------- @@ -33,7 +33,7 @@ import pathlib from matplotlib import pyplot as plt from pvlib.iotools import read_tmy3 -from pvlib.losses import soiling_kimber +from pvlib.soiling import kimber import pvlib # get full path to the data directory @@ -45,7 +45,7 @@ greensboro_rain = greensboro.Lprecipdepth # calculate soiling with no wash dates and cleaning threshold of 25-mm of rain THRESHOLD = 25.0 -soiling_no_wash = soiling_kimber(greensboro_rain, cleaning_threshold=THRESHOLD) +soiling_no_wash = kimber(greensboro_rain, cleaning_threshold=THRESHOLD) soiling_no_wash.name = 'soiling' # daily rain totals daily_rain = greensboro_rain.iloc[:-1].resample('D').sum() diff --git a/docs/sphinx/source/api.rst b/docs/sphinx/source/api.rst index 13b8c6f8c9..e7187629ae 100644 --- a/docs/sphinx/source/api.rst +++ b/docs/sphinx/source/api.rst @@ -310,10 +310,8 @@ Functions for fitting diode models Other ----- - .. autosummary:: :toctree: generated/ - pvsystem.retrieve_sam pvsystem.systemdef pvsystem.scale_voltage_current_power @@ -332,8 +330,8 @@ Effects on PV System Output .. autosummary:: :toctree: generated/ - losses.soiling_hsu - losses.soiling_kimber + soiling.hsu + soiling.kimber diff --git a/docs/sphinx/source/whatsnew/v0.7.2.rst b/docs/sphinx/source/whatsnew/v0.7.2.rst index 41bec86778..cc0b21ed45 100644 --- a/docs/sphinx/source/whatsnew/v0.7.2.rst +++ b/docs/sphinx/source/whatsnew/v0.7.2.rst @@ -10,6 +10,11 @@ API Changes * :py:func:`pvlib.iotools.read_tmy3` when coerced to a single year now returns indices that are monotonically increasing. Therefore, the last index will be January 1, 00:00 of the *next* year. (:pull:`910`) +* Renamed ``pvlib.losses`` to :py:mod:`pvlib.soiling`. Additional loss + models will go into code modules named for the loss or effect type. + (:issue:`935`, :issue:`891`) +* Renamed ``pvlib.losses.soiling_hsu`` to :py:func:`pvlib.soiling.hsu` + (:issue:`935`) Enhancements ~~~~~~~~~~~~ @@ -19,7 +24,8 @@ Enhancements * Add :py:func:`~pvlib.pvsystem.PVSystem.faiman` and added ``temperature_model='faiman'`` option to :py:class:`~pvlib.modelchain.ModelChain` (:pull:`897`) (:issue:`836`). -* Add Kimber soiling model :py:func:`pvlib.losses.soiling_kimber`. (:pull:`860`) +* Add Kimber soiling model :py:func:`pvlib.soiling.kimber`. (:pull:`860`, + :issue`935`) * Add :func:`~pvlib.iotools.read_pvgis_tmy` for files downloaded using the PVGIS tool. (:issue:`880`) * Add new module :py:mod:`pvlib.snow` to contain models related to snow coverage and effects on a PV system. (:pull:`764`) diff --git a/pvlib/__init__.py b/pvlib/__init__.py index df2b3c5c74..c2d645d169 100644 --- a/pvlib/__init__.py +++ b/pvlib/__init__.py @@ -14,5 +14,5 @@ from pvlib import modelchain # noqa: F401 from pvlib import singlediode # noqa: F401 from pvlib import bifacial # noqa: F401 -from pvlib import losses # noqa: F401 +from pvlib import soiling # noqa: F401 from pvlib import snow # noqa: F401 diff --git a/pvlib/losses.py b/pvlib/soiling.py similarity index 93% rename from pvlib/losses.py rename to pvlib/soiling.py index 7093afc938..1b7aadc73d 100644 --- a/pvlib/losses.py +++ b/pvlib/soiling.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- """ -This module contains functions for losses of various types: soiling, mismatch, -snow cover, etc. +This module contains functions for soiling models """ import datetime @@ -10,8 +9,8 @@ from pvlib.tools import cosd -def soiling_hsu(rainfall, cleaning_threshold, tilt, pm2_5, pm10, - depo_veloc=None, rain_accum_period=pd.Timedelta('1h')): +def hsu(rainfall, cleaning_threshold, tilt, pm2_5, pm10, + depo_veloc=None, rain_accum_period=pd.Timedelta('1h')): """ Calculates soiling ratio given particulate and rain data using the model from Humboldt State University (HSU). @@ -66,7 +65,7 @@ def soiling_hsu(rainfall, cleaning_threshold, tilt, pm2_5, pm10, try: from scipy.special import erf except ImportError: - raise ImportError("The soiling_hsu function requires scipy.") + raise ImportError("The pvlib.soiling.hsu function requires scipy.") # never use mutable input arguments if depo_veloc is None: @@ -96,9 +95,9 @@ def soiling_hsu(rainfall, cleaning_threshold, tilt, pm2_5, pm10, return soiling_ratio -def soiling_kimber(rainfall, cleaning_threshold=6, soiling_loss_rate=0.0015, - grace_period=14, max_soiling=0.3, manual_wash_dates=None, - initial_soiling=0, rain_accum_period=24): +def kimber(rainfall, cleaning_threshold=6, soiling_loss_rate=0.0015, + grace_period=14, max_soiling=0.3, manual_wash_dates=None, + initial_soiling=0, rain_accum_period=24): """ Calculates fraction of energy lost due to soiling given rainfall data and daily loss rate using the Kimber model. diff --git a/pvlib/tests/test_losses.py b/pvlib/tests/test_soiling.py similarity index 73% rename from pvlib/tests/test_losses.py rename to pvlib/tests/test_soiling.py index 170efa88c3..b80dd13547 100644 --- a/pvlib/tests/test_losses.py +++ b/pvlib/tests/test_soiling.py @@ -5,7 +5,7 @@ import numpy as np import pandas as pd from pandas.util.testing import assert_series_equal -from pvlib.losses import soiling_hsu, soiling_kimber +from pvlib.soiling import hsu, kimber from pvlib.iotools import read_tmy3 from conftest import ( requires_scipy, needs_pandas_0_22, DATA_DIR) @@ -75,7 +75,7 @@ def rainfall_input(): @requires_scipy @needs_pandas_0_22 -def test_soiling_hsu_no_cleaning(rainfall_input, expected_output): +def test_hsu_no_cleaning(rainfall_input, expected_output): """Test Soiling HSU function""" rainfall = rainfall_input @@ -85,15 +85,15 @@ def test_soiling_hsu_no_cleaning(rainfall_input, expected_output): tilt = 0. expected_no_cleaning = expected_output - result = soiling_hsu(rainfall=rainfall, cleaning_threshold=10., tilt=tilt, - pm2_5=pm2_5, pm10=pm10, depo_veloc=depo_veloc, - rain_accum_period=pd.Timedelta('1h')) + result = hsu(rainfall=rainfall, cleaning_threshold=10., tilt=tilt, + pm2_5=pm2_5, pm10=pm10, depo_veloc=depo_veloc, + rain_accum_period=pd.Timedelta('1h')) assert_series_equal(result, expected_no_cleaning) @requires_scipy @needs_pandas_0_22 -def test_soiling_hsu(rainfall_input, expected_output_2): +def test_hsu(rainfall_input, expected_output_2): """Test Soiling HSU function with cleanings""" rainfall = rainfall_input @@ -104,21 +104,21 @@ def test_soiling_hsu(rainfall_input, expected_output_2): expected = expected_output_2 # three cleaning events at 4:00-6:00, 8:00-11:00, and 17:00-20:00 - result = soiling_hsu(rainfall=rainfall, cleaning_threshold=0.5, tilt=tilt, - pm2_5=pm2_5, pm10=pm10, depo_veloc=depo_veloc, - rain_accum_period=pd.Timedelta('3h')) + result = hsu(rainfall=rainfall, cleaning_threshold=0.5, tilt=tilt, + pm2_5=pm2_5, pm10=pm10, depo_veloc=depo_veloc, + rain_accum_period=pd.Timedelta('3h')) assert_series_equal(result, expected) @requires_scipy @needs_pandas_0_22 -def test_soiling_hsu_defaults(rainfall_input, expected_output_1): +def test_hsu_defaults(rainfall_input, expected_output_1): """ Test Soiling HSU function with default deposition velocity and default rain accumulation period. """ - result = soiling_hsu( + result = hsu( rainfall=rainfall_input, cleaning_threshold=0.5, tilt=0.0, pm2_5=1.0, pm10=2.0) assert np.allclose(result.values, expected_output_1) @@ -132,50 +132,45 @@ def greensboro_rain(): @pytest.fixture -def expected_kimber_soiling_nowash(): +def expected_kimber_nowash(): return pd.read_csv( DATA_DIR / 'greensboro_kimber_soil_nowash.dat', parse_dates=True, index_col='timestamp') @needs_pandas_0_22 -def test_kimber_soiling_nowash(greensboro_rain, - expected_kimber_soiling_nowash): +def test_kimber_nowash(greensboro_rain, expected_kimber_nowash): """Test Kimber soiling model with no manual washes""" # Greensboro typical expected annual rainfall is 8345mm assert greensboro_rain.sum() == 8345 # calculate soiling with no wash dates - soiling_nowash = soiling_kimber(greensboro_rain) + nowash = kimber(greensboro_rain) # test no washes - assert np.allclose( - soiling_nowash.values, - expected_kimber_soiling_nowash['soiling'].values) + assert np.allclose(nowash.values, expected_kimber_nowash['soiling'].values) @pytest.fixture -def expected_kimber_soiling_manwash(): +def expected_kimber_manwash(): return pd.read_csv( DATA_DIR / 'greensboro_kimber_soil_manwash.dat', parse_dates=True, index_col='timestamp') @needs_pandas_0_22 -def test_kimber_soiling_manwash(greensboro_rain, - expected_kimber_soiling_manwash): +def test_kimber_manwash(greensboro_rain, expected_kimber_manwash): """Test Kimber soiling model with a manual wash""" # a manual wash date manwash = [datetime.date(1990, 2, 15), ] # calculate soiling with manual wash - soiling_manwash = soiling_kimber( - greensboro_rain, manual_wash_dates=manwash) + manwash = kimber(greensboro_rain, manual_wash_dates=manwash) # test manual wash assert np.allclose( - soiling_manwash.values, - expected_kimber_soiling_manwash['soiling'].values) + manwash.values, + expected_kimber_manwash['soiling'].values) @pytest.fixture -def expected_kimber_soiling_norain(): +def expected_kimber_norain(): # expected soiling reaches maximum soiling_loss_rate = 0.0015 max_loss_rate = 0.3 @@ -186,19 +181,18 @@ def expected_kimber_soiling_norain(): @needs_pandas_0_22 -def test_kimber_soiling_norain(greensboro_rain, - expected_kimber_soiling_norain): +def test_kimber_norain(greensboro_rain, expected_kimber_norain): """Test Kimber soiling model with no rain""" # a year with no rain norain = pd.Series(0, index=greensboro_rain.index) # calculate soiling with no rain - soiling_norain = soiling_kimber(norain) + norain = kimber(norain) # test no rain, soiling reaches maximum - assert np.allclose(soiling_norain.values, expected_kimber_soiling_norain) + assert np.allclose(norain.values, expected_kimber_norain) @pytest.fixture -def expected_kimber_soiling_initial_soil(): +def expected_kimber_initial_soil(): # expected soiling reaches maximum soiling_loss_rate = 0.0015 max_loss_rate = 0.3 @@ -209,13 +203,11 @@ def expected_kimber_soiling_initial_soil(): @needs_pandas_0_22 -def test_kimber_soiling_initial_soil(greensboro_rain, - expected_kimber_soiling_initial_soil): +def test_kimber_initial_soil(greensboro_rain, expected_kimber_initial_soil): """Test Kimber soiling model with initial soiling""" # a year with no rain norain = pd.Series(0, index=greensboro_rain.index) # calculate soiling with no rain - soiling_norain = soiling_kimber(norain, initial_soiling=0.1) + norain = kimber(norain, initial_soiling=0.1) # test no rain, soiling reaches maximum - assert np.allclose( - soiling_norain.values, expected_kimber_soiling_initial_soil) + assert np.allclose(norain.values, expected_kimber_initial_soil)