diff --git a/docs/sphinx/source/api.rst b/docs/sphinx/source/api.rst index 07f610fa..7a9556c9 100644 --- a/docs/sphinx/source/api.rst +++ b/docs/sphinx/source/api.rst @@ -132,7 +132,6 @@ Normalization irradiance_rescale normalize_with_expected_power normalize_with_pvwatts - normalize_with_sapm pvwatts_dc_power sapm_dc_power delta_index diff --git a/docs/sphinx/source/changelog/pending.rst b/docs/sphinx/source/changelog/pending.rst index 6992650d..e9d7f27b 100644 --- a/docs/sphinx/source/changelog/pending.rst +++ b/docs/sphinx/source/changelog/pending.rst @@ -22,6 +22,11 @@ Requirements ------------ * Specified versions in ``requirements.txt`` and ``docs/notebook_requirements.txt`` have been updated (:pull:`412`) +Deprecations +------------ +* Removed :py:func:`~rdtools.normalization.sapm_dc_power` (:pull:`419`) +* Removed :py:func:`~rdtools.normalization.normalize_with_sapm` (:pull:`419`) + Contributors ------------ * Martin Springer (:ghuser:`martin-springer`) diff --git a/rdtools/__init__.py b/rdtools/__init__.py index 342427c2..c097e2be 100644 --- a/rdtools/__init__.py +++ b/rdtools/__init__.py @@ -1,4 +1,3 @@ -from rdtools.normalization import normalize_with_sapm from rdtools.normalization import normalize_with_pvwatts from rdtools.normalization import irradiance_rescale from rdtools.normalization import energy_from_power diff --git a/rdtools/normalization.py b/rdtools/normalization.py index 8629c237..2509cd33 100644 --- a/rdtools/normalization.py +++ b/rdtools/normalization.py @@ -1,7 +1,6 @@ '''Functions for normalizing, rescaling, and regularizing PV system data.''' import pandas as pd -import pvlib import numpy as np from scipy.optimize import minimize import warnings @@ -176,138 +175,6 @@ def normalize_with_pvwatts(energy, pvwatts_kws): return energy_normalized, insolation -@deprecated(since='2.0.0', removal='3.0.0', - alternative='normalize_with_expected_power') -def sapm_dc_power(pvlib_pvsystem, met_data): - ''' - Use Sandia Array Performance Model (SAPM) and PVWatts to compute the - effective DC power using measured irradiance, ambient temperature, and wind - speed. Effective irradiance and cell temperature are calculated with SAPM, - and DC power with PVWatts. - - .. warning:: - The ``pvlib_pvsystem`` argument must be a ``pvlib.pvsystem.LocalizedPVSystem`` - object, which is no longer available as of pvlib 0.9.0. To use this function - you'll need to use an older version of pvlib. - - Parameters - ---------- - pvlib_pvsystem : pvlib.pvsystem.LocalizedPVSystem - Object contains orientation, geographic coordinates, equipment - constants (including DC rated power in watts). The object must also - specify either the ``temperature_model_parameters`` attribute or both - ``racking_model`` and ``module_type`` attributes to infer the temperature model parameters. - met_data : pandas.DataFrame - Measured irradiance components, ambient temperature, and wind speed. - Expected met_data DataFrame column names: - ['DNI', 'GHI', 'DHI', 'Temperature', 'Wind Speed'] - - Note - ---- - All series are assumed to be right-labeled, meaning that the recorded - value at a given timestamp refers to the previous time interval - - Returns - ------- - power_dc : pandas.Series - DC power in watts derived using Sandia Array Performance Model and - PVWatts. - effective_poa : pandas.Series - Effective irradiance calculated with SAPM - ''' - - solar_position = pvlib_pvsystem.get_solarposition(met_data.index) - - total_irradiance = pvlib_pvsystem\ - .get_irradiance(solar_position['zenith'], - solar_position['azimuth'], - met_data['DNI'], - met_data['GHI'], - met_data['DHI']) - - aoi = pvlib_pvsystem.get_aoi(solar_position['zenith'], - solar_position['azimuth']) - - airmass = pvlib_pvsystem\ - .get_airmass(solar_position=solar_position, model='kastenyoung1989') - airmass_absolute = airmass['airmass_absolute'] - - effective_irradiance = pvlib.pvsystem\ - .sapm_effective_irradiance(poa_direct=total_irradiance['poa_direct'], - poa_diffuse=total_irradiance['poa_diffuse'], - airmass_absolute=airmass_absolute, - aoi=aoi, - module=pvlib_pvsystem.module) - - temp_cell = pvlib_pvsystem\ - .sapm_celltemp(total_irradiance['poa_global'], - met_data['Temperature'], - met_data['Wind Speed']) - - power_dc = pvlib_pvsystem\ - .pvwatts_dc(g_poa_effective=effective_irradiance, - temp_cell=temp_cell) - - return power_dc, effective_irradiance - - -@deprecated(since='2.0.0', removal='3.0.0', - alternative='normalize_with_expected_power') -def normalize_with_sapm(energy, sapm_kws): - ''' - Normalize system AC energy output given measured met_data and - meteorological data. This method relies on the Sandia Array Performance - Model (SAPM) to compute the effective DC energy using measured irradiance, - ambient temperature, and wind speed. - - Energy timeseries and met_data timeseries can be different granularities. - - .. warning:: - The ``pvlib_pvsystem`` argument must be a ``pvlib.pvsystem.LocalizedPVSystem`` - object, which is no longer available as of pvlib 0.9.0. To use this function - you'll need to use an older version of pvlib. - - Parameters - ---------- - energy : pandas.Series - Energy time series to be normalized in watt hours. - Must be a right-labeled regular time series. - sapm_kws : dict - Dictionary of parameters required for sapm_dc_power function. See - Other Parameters. - - Other Parameters - --------------- - pvlib_pvsystem : pvlib.pvsystem.LocalizedPVSystem object - Object contains orientation, geographic coordinates, equipment - constants (including DC rated power in watts). The object must also - specify either the ``temperature_model_parameters`` attribute or both - ``racking_model`` and ``module_type`` to infer the model parameters. - met_data : pandas.DataFrame - Measured met_data, ambient temperature, and wind speed. Expected - column names are ['DNI', 'GHI', 'DHI', 'Temperature', 'Wind Speed'] - - Note - ---- - All series are assumed to be right-labeled, meaning that the recorded - value at a given timestamp refers to the previous time interval - - Returns - ------- - energy_normalized : pandas.Series - Energy divided by Sandia Model DC energy. - insolation : pandas.Series - Insolation associated with each normalized point - ''' - - power_dc, irrad = sapm_dc_power(**sapm_kws) - - energy_normalized, insolation = normalize_with_expected_power(energy, power_dc, irrad, - pv_input='energy') - - return energy_normalized, insolation - - def _delta_index(series): ''' Takes a pandas series with a DatetimeIndex as input and diff --git a/rdtools/test/bootstrap_test.py b/rdtools/test/bootstrap_test.py index 12259fbe..cce236b2 100644 --- a/rdtools/test/bootstrap_test.py +++ b/rdtools/test/bootstrap_test.py @@ -20,6 +20,7 @@ def test_bootstrap_module( cods_normalized_daily, cods_normalized_daily_wo_noise, decomposition_type=decomposition_type) + else: # Rest make time serie bootstrap samples and construct of confidence intervals. # Test make bootstrap samples diff --git a/rdtools/test/irradiance_rescale_test.py b/rdtools/test/irradiance_rescale_test.py index 834d6891..300c2e71 100644 --- a/rdtools/test/irradiance_rescale_test.py +++ b/rdtools/test/irradiance_rescale_test.py @@ -18,6 +18,7 @@ def test_rescale(method, simple_irradiance): if method == "error": with pytest.raises(ValueError): irradiance_rescale(simple_irradiance, simple_irradiance * 1.05, method=method) + else: modeled = simple_irradiance measured = 1.05 * simple_irradiance diff --git a/rdtools/test/normalization_sapm_test.py b/rdtools/test/normalization_sapm_test.py deleted file mode 100644 index 12f9fb82..00000000 --- a/rdtools/test/normalization_sapm_test.py +++ /dev/null @@ -1,125 +0,0 @@ -""" Energy Normalization with SAPM Unit Tests. """ - -import unittest -import pytest - -import pandas as pd -import numpy as np -import pvlib - -from rdtools.normalization import normalize_with_sapm -from rdtools.normalization import sapm_dc_power - -from conftest import fail_on_rdtools_version, requires_pvlib_below_090 -from rdtools._deprecation import rdtoolsDeprecationWarning - - -@requires_pvlib_below_090 -class SapmNormalizationTestCase(unittest.TestCase): - ''' Unit tests for energy normalization module. ''' - - def setUp(self): - # define module constants and parameters - module = {} - module['A0'] = 0.0315 - module['A1'] = 0.05975 - module['A2'] = -0.01067 - module['A3'] = 0.0008 - module['A4'] = -2.24e-5 - module['B0'] = 1 - module['B1'] = -0.002438 - module['B2'] = 0.00031 - module['B3'] = -1.246e-5 - module['B4'] = 2.11e-7 - module['B5'] = -1.36e-9 - module['FD'] = 1 - module_parameters = { - 'pdc0': 2.1, - 'gamma_pdc': -0.0045 - } - - # define location - test_location = pvlib.location\ - .Location(latitude=37.88447702, longitude=-122.2652549) - - self.pvsystem = pvlib.pvsystem\ - .LocalizedPVSystem(location=test_location, - surface_tilt=20, - surface_azimuth=180, - module=module, - module_parameters=module_parameters, - racking_model='insulated_back', - module_type='glass_polymer', - modules_per_string=6) - - # define dummy energy data - energy_freq = 'MS' - energy_periods = 12 - energy_index = pd.date_range(start='2012-01-01', - periods=energy_periods, - freq=energy_freq) - - dummy_energy = np.repeat(a=100, repeats=energy_periods) - self.energy = pd.Series(dummy_energy, index=energy_index) - self.energy_periods = 12 - - # define dummy meteorological data - irrad_columns = ['DNI', 'GHI', 'DHI', 'Temperature', 'Wind Speed'] - irrad_freq = 'D' - irrad_index = pd.date_range(start=energy_index[0], - end=energy_index[-1] - pd.to_timedelta('1 nanosecond'), - freq=irrad_freq) - self.irrad = pd.DataFrame([[100, 45, 30, 25, 10]], - index=irrad_index, - columns=irrad_columns) - - # define an irregular pandas series - times = pd.DatetimeIndex(['2012-01-01 12:00', '2012-01-01 12:05', '2012-01-01 12:06', - '2012-01-01 12:09']) - data = [1, 2, 3, 4] - self.irregular_timeseries = pd.Series(data=data, index=times) - - def tearDown(self): - pass - - @fail_on_rdtools_version('3.0.0') - def test_sapm_dc_power(self): - ''' Test SAPM DC power. ''' - - with pytest.warns(rdtoolsDeprecationWarning): - dc_power, poa = sapm_dc_power(self.pvsystem, self.irrad) - self.assertEqual(self.irrad.index.freq, dc_power.index.freq) - self.assertEqual(len(self.irrad), len(dc_power)) - - @fail_on_rdtools_version('3.0.0') - def test_normalization_with_sapm(self): - ''' Test SAPM normalization. ''' - - sapm_kws = { - 'pvlib_pvsystem': self.pvsystem, - 'met_data': self.irrad, - } - - with pytest.warns(rdtoolsDeprecationWarning): - corr_energy, insol = normalize_with_sapm(self.energy, sapm_kws) - - # Test output is same frequency and length as energy - self.assertEqual(corr_energy.index.freq, self.energy.index.freq) - # Expected behavior is to have a nan at energy.index[0] - self.assertEqual(len(corr_energy.dropna()), len(self.energy)-1) - - # Test for valueError when energy frequency can't be inferred - with self.assertRaises(ValueError): - with pytest.warns(rdtoolsDeprecationWarning): - corr_energy, insolation = normalize_with_sapm(self.irregular_timeseries, sapm_kws) - - # TODO, test for: - # incorrect data format - # incomplete data - # missing pvsystem metadata - # missing measured irradiance data - # met_data freq > energy freq, issue/warining? - - -if __name__ == '__main__': - unittest.main()