From 83f09901a11b3c7d5f7076eb121c853540146912 Mon Sep 17 00:00:00 2001 From: Perry Date: Mon, 3 Oct 2022 16:52:55 -0600 Subject: [PATCH 01/33] added new irradiance function for component sum --- pvlib/irradiance.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 03ddd13f5a..451a927e70 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2915,3 +2915,46 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, (zenith < zenith_threshold_for_zero_dni) & (dni > max_dni)] = max_dni return dni + + +def component_sum_irradiance(self, weather, solar_zenith): + """ + + Parameters + ---------- + weather : TYPE + DESCRIPTION. + solar_zenith : TYPE + DESCRIPTION. + + Returns + ------- + None. + + """ + icolumns = set(weather.columns) + wrn_txt = ("This function is not safe at the moment.\n" + + "Results can be too high or negative.\n" + + "Help to improve this function on github:\n" + + "https://github.com/pvlib/pvlib-python \n") + + if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns: + clearsky = self.location.get_clearsky( + weather.index, solar_position=self.results.solar_position) + weather.loc[:, 'dni'] = pvlib.irradiance.dni( + weather.loc[:, 'ghi'], + weather.loc[:, 'dhi'], + solar_zenith, + clearsky_dni=clearsky['dni'], + clearsky_tolerance=1.1) + elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: + warnings.warn(wrn_txt, UserWarning) + weather.loc[:, 'ghi'] = ( + weather.dhi + weather.dni * + tools.cosd(solar_zenith) + ) + elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: + warnings.warn(wrn_txt, UserWarning) + weather.loc[:, 'dhi'] = ( + weather.ghi - weather.dni * + tools.cosd(solar_zenith)) From 59809302f070485e740e49816339e300100ccf9b Mon Sep 17 00:00:00 2001 From: Perry Date: Mon, 3 Oct 2022 17:15:29 -0600 Subject: [PATCH 02/33] added to docstrings --- pvlib/irradiance.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 451a927e70..b33cff9b79 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -10,6 +10,7 @@ import numpy as np import pandas as pd +import warnings from pvlib import atmosphere, solarposition, tools @@ -2917,14 +2918,19 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, return dni -def component_sum_irradiance(self, weather, solar_zenith): +def component_sum_irradiance(self, weather, + zenith, + clearsky_dni=None): """ Parameters ---------- - weather : TYPE - DESCRIPTION. - solar_zenith : TYPE + weather : DataFrame, or tuple or list of DataFrame + Column names must include ``'dni'``, ``'ghi'``, ``'dhi'``. + zenith : Series + True (not refraction-corrected) zenith angles in decimal + degrees. Angles must be >=0 and <=180. + clearsky_dni : Series, default None DESCRIPTION. Returns @@ -2939,22 +2945,21 @@ def component_sum_irradiance(self, weather, solar_zenith): "https://github.com/pvlib/pvlib-python \n") if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns: - clearsky = self.location.get_clearsky( - weather.index, solar_position=self.results.solar_position) - weather.loc[:, 'dni'] = pvlib.irradiance.dni( + weather.loc[:, 'dni'] = dni( weather.loc[:, 'ghi'], weather.loc[:, 'dhi'], - solar_zenith, - clearsky_dni=clearsky['dni'], + zenith, + clearsky_dni=clearsky_dni, clearsky_tolerance=1.1) elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: warnings.warn(wrn_txt, UserWarning) weather.loc[:, 'ghi'] = ( weather.dhi + weather.dni * - tools.cosd(solar_zenith) + tools.cosd(zenith) ) elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: warnings.warn(wrn_txt, UserWarning) weather.loc[:, 'dhi'] = ( weather.ghi - weather.dni * - tools.cosd(solar_zenith)) + tools.cosd(zenith)) + return weather \ No newline at end of file From 1b2e5edc0793041c0dfd6a88263e4b53fe0652b6 Mon Sep 17 00:00:00 2001 From: Perry Date: Mon, 3 Oct 2022 17:16:42 -0600 Subject: [PATCH 03/33] updated docstrings --- pvlib/irradiance.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index b33cff9b79..e61d7a0c55 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2926,7 +2926,8 @@ def component_sum_irradiance(self, weather, Parameters ---------- weather : DataFrame, or tuple or list of DataFrame - Column names must include ``'dni'``, ``'ghi'``, ``'dhi'``. + Column names must include at least 2 of the 3 columns: + ``'dni'``, ``'ghi'``, ``'dhi'``. zenith : Series True (not refraction-corrected) zenith angles in decimal degrees. Angles must be >=0 and <=180. @@ -2935,7 +2936,7 @@ def component_sum_irradiance(self, weather, Returns ------- - None. + weather: """ icolumns = set(weather.columns) @@ -2943,7 +2944,6 @@ def component_sum_irradiance(self, weather, "Results can be too high or negative.\n" + "Help to improve this function on github:\n" + "https://github.com/pvlib/pvlib-python \n") - if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns: weather.loc[:, 'dni'] = dni( weather.loc[:, 'ghi'], @@ -2962,4 +2962,4 @@ def component_sum_irradiance(self, weather, weather.loc[:, 'dhi'] = ( weather.ghi - weather.dni * tools.cosd(zenith)) - return weather \ No newline at end of file + return weather From 08a18cf50005cf00d1faa6fa3e26247545bb1404 Mon Sep 17 00:00:00 2001 From: Perry Date: Tue, 4 Oct 2022 16:10:36 -0600 Subject: [PATCH 04/33] updated methods with new component_sum_irradiance() function --- pvlib/irradiance.py | 82 +++++++++++++++++++++++++++------------------ pvlib/modelchain.py | 43 ++++++++++++++---------- 2 files changed, 75 insertions(+), 50 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index e61d7a0c55..621a57225b 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2918,48 +2918,64 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, return dni -def component_sum_irradiance(self, weather, - zenith, +def component_sum_irradiance(zenith, + ghi=None, + dhi=None, + dni=None, clearsky_dni=None): """ + Use the component sum equations to calculate the missing series, using + the other available time series. One of the three parameters (ghi, dhi, + dni) is passed as None, and the other associated series passed are used to + calculate the missing series value. Parameters ---------- - weather : DataFrame, or tuple or list of DataFrame - Column names must include at least 2 of the 3 columns: - ``'dni'``, ``'ghi'``, ``'dhi'``. zenith : Series True (not refraction-corrected) zenith angles in decimal - degrees. Angles must be >=0 and <=180. + degrees, with datetime index. Angles must be >=0 and <=180. Must have + the same datetime index as ghi, dhi, and dni series, when available. + ghi : Series, default None + Pandas series of dni data, with datetime index. Must have the same + datetime index as dni, dhi, and zenith series, when available. + dhi : Series, default None + Pandas series of dni data, with datetime index. Must have the same + datetime index as ghi, dni, and zenith series, when available. + dni : Series, default None + Pandas series of dni data, with datetime index. Must have the same + datetime index as ghi, dhi, and zenith series, when available. clearsky_dni : Series, default None - DESCRIPTION. + Pandas series of clearsky dni data, calculated via the + get_clearsky function. Must have the same datetime index as ghi, dhi, + dni, and zenith series, when available. Returns ------- - weather: - + ghi : Series + Pandas series of GHI values with datetime index, which can either be + the original passed series or the component-sum calculated series + (if ghi passed as None) + dhi : Series + Pandas series of DHI values with datetime index, which can either be + the original passed series or the component-sum calculated series + (if dhi passed as None) + dni: Series + Pandas series of DNI values with datetime index, which can either be + the original passed series or the component-sum calculated series + (if dni passed as None) """ - icolumns = set(weather.columns) - wrn_txt = ("This function is not safe at the moment.\n" + - "Results can be too high or negative.\n" + - "Help to improve this function on github:\n" + - "https://github.com/pvlib/pvlib-python \n") - if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns: - weather.loc[:, 'dni'] = dni( - weather.loc[:, 'ghi'], - weather.loc[:, 'dhi'], - zenith, - clearsky_dni=clearsky_dni, - clearsky_tolerance=1.1) - elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: - warnings.warn(wrn_txt, UserWarning) - weather.loc[:, 'ghi'] = ( - weather.dhi + weather.dni * - tools.cosd(zenith) - ) - elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: - warnings.warn(wrn_txt, UserWarning) - weather.loc[:, 'dhi'] = ( - weather.ghi - weather.dni * - tools.cosd(zenith)) - return weather + if ghi and dhi and not dni: + dni = dni(ghi, dhi, zenith, + clearsky_dni=clearsky_dni, + clearsky_tolerance=1.1) + return + elif dni and dhi and not ghi: + ghi = (dhi + dni * tools.cosd(zenith)) + elif dni and ghi and not dhi: + dhi = (ghi - dni * tools.cosd(zenith)) + else: + wrn_txt = ("No component sum calculated. Please recheck \n" + "passed ghi, dni, and dhi parameters to check \n" + "exactly one field out of the three is set to None.") + warnings.warn(wrn_txt) + return ghi, dhi, dni diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 8211981433..a2328fe2ef 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1289,13 +1289,13 @@ def complete_irradiance(self, weather): self._assign_times() self.results.solar_position = self.location.get_solarposition( self.results.times, method=self.solar_position_method) - + # Calculate the irradiance using the component sum equations, + # if needed if isinstance(weather, tuple): for w in self.results.weather: self._complete_irradiance(w) else: self._complete_irradiance(self.results.weather) - return self def _complete_irradiance(self, weather): @@ -1304,26 +1304,35 @@ def _complete_irradiance(self, weather): "Results can be too high or negative.\n" + "Help to improve this function on github:\n" + "https://github.com/pvlib/pvlib-python \n") - + warnings.warn(wrn_txt, UserWarning) if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns: clearsky = self.location.get_clearsky( weather.index, solar_position=self.results.solar_position) - weather.loc[:, 'dni'] = pvlib.irradiance.dni( - weather.loc[:, 'ghi'], weather.loc[:, 'dhi'], - self.results.solar_position.zenith, - clearsky_dni=clearsky['dni'], - clearsky_tolerance=1.1) + ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( + zenith=self.results.solar_position.zenith, + ghi=weather.ghi, + dhi=weather.dhi, + dni=None, + clearsky_dni=clearsky) elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: - warnings.warn(wrn_txt, UserWarning) - weather.loc[:, 'ghi'] = ( - weather.dhi + weather.dni * - tools.cosd(self.results.solar_position.zenith) - ) + ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( + zenith=self.results.solar_position.zenith, + ghi=None, + dhi=weather.dhi, + dni=weather.dni, + clearsky_dni=clearsky) elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: - warnings.warn(wrn_txt, UserWarning) - weather.loc[:, 'dhi'] = ( - weather.ghi - weather.dni * - tools.cosd(self.results.solar_position.zenith)) + ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( + zenith=self.results.solar_position.zenith, + ghi=weather.ghi, + dhi=None, + dni=weather.dni, + clearsky_dni=clearsky) + # Set the ghi, dni, and dhi columns based on + # pvlib.irradiance.component_sum_irradiance outputs + weather.loc[:, 'dhi'] = dhi + weather.loc[:, 'dni'] = dni + weather.loc[:, 'ghi'] = ghi def _prep_inputs_solar_pos(self, weather): """ From 21599f69fea3ba8264f67578828a8f8512e4fec8 Mon Sep 17 00:00:00 2001 From: Perry Date: Tue, 4 Oct 2022 17:02:23 -0600 Subject: [PATCH 05/33] added associated unit test for the new component sum function --- pvlib/irradiance.py | 7 +++--- pvlib/tests/test_irradiance.py | 44 +++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 621a57225b..01c210a670 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2964,14 +2964,13 @@ def component_sum_irradiance(zenith, the original passed series or the component-sum calculated series (if dni passed as None) """ - if ghi and dhi and not dni: + if (ghi, dhi) is not None and dni is None: dni = dni(ghi, dhi, zenith, clearsky_dni=clearsky_dni, clearsky_tolerance=1.1) - return - elif dni and dhi and not ghi: + elif (dhi,dni) is not None and ghi is None: ghi = (dhi + dni * tools.cosd(zenith)) - elif dni and ghi and not dhi: + elif (dni, ghi) is not None and dhi is None: dhi = (ghi - dni * tools.cosd(zenith)) else: wrn_txt = ("No component sum calculated. Please recheck \n" diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 8dc4877d0d..4e7ebbf77c 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -8,7 +8,7 @@ import pytest from numpy.testing import assert_almost_equal, assert_allclose - +from pvlib.location import Location from pvlib import irradiance from .conftest import ( @@ -30,6 +30,10 @@ def times(): return pd.date_range(start='20140624', freq='6H', periods=4, tz='US/Arizona') +@pytest.fixture +def location(): + return Location(32.2, -111, altitude=700) + @pytest.fixture def irrad_data(times): @@ -1082,3 +1086,41 @@ def test_clearness_index_zenith_independent(airmass_kt): airmass) expected = pd.Series([np.nan, 0.553744437562], index=times) assert_series_equal(out, expected) + + +def test_component_sum_irradiance(location): + # Generate dataframe to test on + times = pd.date_range('2010-07-05 7:00:00-0700', periods=2, freq='H') + i = pd.DataFrame({'dni': [49.756966, 62.153947], + 'ghi': [372.103976116, 497.087579068], + 'dhi': [356.543700, 465.44400]}, index=times) + # Get zenith values associated with the location + solar_position = location.get_solarposition(times, + method='nrel_numpy') + # Get the clearsky data associated with the location + clearsky = location.get_clearsky(times, solar_position=solar_position) + # Test scenario where DNI is generated via component sum equation + irradiance.component_sum_irradiance(solar_position.zenith, + ghi=i.ghi, + dhi=i.dhi, + dni=None, + clearsky_dni=clearsky) + # Test scenario where GHI is generated via component sum equation + irradiance.component_sum_irradiance(solar_position.zenith, + ghi=i.ghi, + dhi=i.dhi, + dni=None, + clearsky_dni=clearsky) + # Test scenario where DHI is generated via component sum equation + irradiance.component_sum_irradiance(solar_position.zenith, + ghi=i.ghi, + dhi=i.dhi, + dni=None, + clearsky_dni=clearsky) + # Test scenario where all parameters are passed (throw warning) + irradiance.component_sum_irradiance(solar_position.zenith, + ghi=i.ghi, + dhi=i.dhi, + dni=i.dni, + clearsky_dni=clearsky) + From fbf0ee9a07e9711534bcf8ccc3dfa56edc30b84d Mon Sep 17 00:00:00 2001 From: Perry Date: Wed, 5 Oct 2022 10:35:31 -0600 Subject: [PATCH 06/33] added units tests for the component_sum_irradiance() function --- pvlib/irradiance.py | 30 +++++++-------- pvlib/modelchain.py | 6 +-- pvlib/tests/test_irradiance.py | 67 +++++++++++++++++++++++----------- 3 files changed, 63 insertions(+), 40 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 01c210a670..f48b31dccd 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2919,9 +2919,9 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, def component_sum_irradiance(zenith, - ghi=None, - dhi=None, - dni=None, + ghi_series=None, + dhi_series=None, + dni_series=None, clearsky_dni=None): """ Use the component sum equations to calculate the missing series, using @@ -2935,13 +2935,13 @@ def component_sum_irradiance(zenith, True (not refraction-corrected) zenith angles in decimal degrees, with datetime index. Angles must be >=0 and <=180. Must have the same datetime index as ghi, dhi, and dni series, when available. - ghi : Series, default None + ghi_series : Series, default None Pandas series of dni data, with datetime index. Must have the same datetime index as dni, dhi, and zenith series, when available. - dhi : Series, default None + dhi_series : Series, default None Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dni, and zenith series, when available. - dni : Series, default None + dni_series : Series, default None Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dhi, and zenith series, when available. clearsky_dni : Series, default None @@ -2964,17 +2964,17 @@ def component_sum_irradiance(zenith, the original passed series or the component-sum calculated series (if dni passed as None) """ - if (ghi, dhi) is not None and dni is None: - dni = dni(ghi, dhi, zenith, - clearsky_dni=clearsky_dni, - clearsky_tolerance=1.1) - elif (dhi,dni) is not None and ghi is None: - ghi = (dhi + dni * tools.cosd(zenith)) - elif (dni, ghi) is not None and dhi is None: - dhi = (ghi - dni * tools.cosd(zenith)) + if (ghi_series, dhi_series) is not None and dni_series is None: + dni_series = dni(ghi_series, dhi_series, zenith, + clearsky_dni=clearsky_dni, + clearsky_tolerance=1.1) + elif (dhi_series, dni_series) is not None and ghi_series is None: + ghi_series = (dhi_series + dni_series * tools.cosd(zenith)) + elif (dni_series, ghi_series) is not None and dhi_series is None: + dhi_series = (ghi_series - dni_series * tools.cosd(zenith)) else: wrn_txt = ("No component sum calculated. Please recheck \n" "passed ghi, dni, and dhi parameters to check \n" "exactly one field out of the three is set to None.") warnings.warn(wrn_txt) - return ghi, dhi, dni + return ghi_series, dhi_series, dni_series diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index a2328fe2ef..8219c465ce 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1313,21 +1313,21 @@ def _complete_irradiance(self, weather): ghi=weather.ghi, dhi=weather.dhi, dni=None, - clearsky_dni=clearsky) + clearsky_dni=clearsky.dni) elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, ghi=None, dhi=weather.dhi, dni=weather.dni, - clearsky_dni=clearsky) + clearsky_dni=clearsky.dni) elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, ghi=weather.ghi, dhi=None, dni=weather.dni, - clearsky_dni=clearsky) + clearsky_dni=clearsky.dni) # Set the ghi, dni, and dhi columns based on # pvlib.irradiance.component_sum_irradiance outputs weather.loc[:, 'dhi'] = dhi diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 4e7ebbf77c..b0e13417c3 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -7,7 +7,7 @@ import pandas as pd import pytest -from numpy.testing import assert_almost_equal, assert_allclose +from numpy.testing import assert_almost_equal, assert_allclose, assert_warns from pvlib.location import Location from pvlib import irradiance @@ -1100,27 +1100,50 @@ def test_component_sum_irradiance(location): # Get the clearsky data associated with the location clearsky = location.get_clearsky(times, solar_position=solar_position) # Test scenario where DNI is generated via component sum equation - irradiance.component_sum_irradiance(solar_position.zenith, - ghi=i.ghi, - dhi=i.dhi, - dni=None, - clearsky_dni=clearsky) + ghi_series, dhi_series, dni_series = irradiance.component_sum_irradiance( + solar_position.zenith, + ghi_series=i.ghi, + dhi_series=i.dhi, + dni_series=None, + clearsky_dni=clearsky.dni) + dni_series.name = 'dni' + # Assert that the ghi, dhi, and dni series match the original dataframe + # values + assert_series_equal(ghi_series, i.ghi) + assert_series_equal(dhi_series, i.dhi) + assert_series_equal(dni_series, i.dni) # Test scenario where GHI is generated via component sum equation - irradiance.component_sum_irradiance(solar_position.zenith, - ghi=i.ghi, - dhi=i.dhi, - dni=None, - clearsky_dni=clearsky) + ghi_series, dhi_series, dni_series = irradiance.component_sum_irradiance( + solar_position.zenith, + ghi_series=i.ghi, + dhi_series=i.dhi, + dni_series=None, + clearsky_dni=clearsky.dni) # Test scenario where DHI is generated via component sum equation - irradiance.component_sum_irradiance(solar_position.zenith, - ghi=i.ghi, - dhi=i.dhi, - dni=None, - clearsky_dni=clearsky) + ghi_series, dhi_series, dni_series = irradiance.component_sum_irradiance( + solar_position.zenith, + ghi_series=i.ghi, + dhi_series=i.dhi, + dni_series=None, + clearsky_dni=clearsky.dni) + dni_series.name = 'dni' + # Assert that the ghi, dhi, and dni series match the original dataframe + # values + assert_series_equal(ghi_series, i.ghi) + assert_series_equal(dhi_series, i.dhi) + assert_series_equal(dni_series, i.dni) # Test scenario where all parameters are passed (throw warning) - irradiance.component_sum_irradiance(solar_position.zenith, - ghi=i.ghi, - dhi=i.dhi, - dni=i.dni, - clearsky_dni=clearsky) - + ghi_series, dhi_series, dni_series = \ + assert_warns(UserWarning, + irradiance.component_sum_irradiance, + solar_position.zenith, + ghi_series=i.ghi, + dhi_series=i.dhi, + dni_series=i.dni, + clearsky_dni=clearsky.dni) + dni_series.name = 'dni' + # Assert that the ghi, dhi, and dni series match the original dataframe + # values + assert_series_equal(ghi_series, i.ghi) + assert_series_equal(dhi_series, i.dhi) + assert_series_equal(dni_series, i.dni) From 34344e9fcebc22a7cca93f730dd79f83ab09c60e Mon Sep 17 00:00:00 2001 From: Perry Date: Wed, 5 Oct 2022 10:47:00 -0600 Subject: [PATCH 07/33] added whatsnew file for v0.9.4 --- docs/sphinx/source/reference/irradiance.rst | 1 + docs/sphinx/source/whatsnew/v0.9.4.rst | 37 +++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 docs/sphinx/source/whatsnew/v0.9.4.rst diff --git a/docs/sphinx/source/reference/irradiance.rst b/docs/sphinx/source/reference/irradiance.rst index e0a5777533..a348092b1b 100644 --- a/docs/sphinx/source/reference/irradiance.rst +++ b/docs/sphinx/source/reference/irradiance.rst @@ -28,6 +28,7 @@ Decomposing and combining irradiance irradiance.poa_components irradiance.get_ground_diffuse irradiance.dni + irradiance.component_sum_irradiance Transposition models -------------------- diff --git a/docs/sphinx/source/whatsnew/v0.9.4.rst b/docs/sphinx/source/whatsnew/v0.9.4.rst new file mode 100644 index 0000000000..70fe4a28e9 --- /dev/null +++ b/docs/sphinx/source/whatsnew/v0.9.4.rst @@ -0,0 +1,37 @@ +.. _whatsnew_0930: + +v0.9.3 (TBD) +------------------------ + +Deprecations +~~~~~~~~~~~~ + +Enhancements +~~~~~~~~~~~~ +* Added the component sum irradiance function to calculate the component sum value for GHI, DHI, and DNI values + :py:func:`~pvlib.irradiance.component_sum_irradiance` + (:issue:`1565`, :pull:`1567`) + +Bug fixes +~~~~~~~~~ + + +Testing +~~~~~~~ + + +Documentation +~~~~~~~~~~~~~ + + +Benchmarking +~~~~~~~~~~~~~ + + +Requirements +~~~~~~~~~~~~ + + +Contributors +~~~~~~~~~~~~ +* Kirsten Perry (:ghuser:`kperrynrel`) From 533d63bf6d2c117c62e692e711a4798f494ea773 Mon Sep 17 00:00:00 2001 From: Perry Date: Wed, 5 Oct 2022 13:39:22 -0600 Subject: [PATCH 08/33] fixed modelchain error to stop unit test erroring --- pvlib/modelchain.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 8219c465ce..d92a92e397 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1314,6 +1314,7 @@ def _complete_irradiance(self, weather): dhi=weather.dhi, dni=None, clearsky_dni=clearsky.dni) + weather.loc[:, 'dni'] = dni elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, @@ -1321,6 +1322,7 @@ def _complete_irradiance(self, weather): dhi=weather.dhi, dni=weather.dni, clearsky_dni=clearsky.dni) + weather.loc[:, 'ghi'] = ghi elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, @@ -1328,11 +1330,7 @@ def _complete_irradiance(self, weather): dhi=None, dni=weather.dni, clearsky_dni=clearsky.dni) - # Set the ghi, dni, and dhi columns based on - # pvlib.irradiance.component_sum_irradiance outputs - weather.loc[:, 'dhi'] = dhi - weather.loc[:, 'dni'] = dni - weather.loc[:, 'ghi'] = ghi + weather.loc[:, 'dhi'] = dhi def _prep_inputs_solar_pos(self, weather): """ From 1a554e8a2443c372eae1f2c97f81d1959539202d Mon Sep 17 00:00:00 2001 From: Perry Date: Wed, 5 Oct 2022 14:11:59 -0600 Subject: [PATCH 09/33] removed clearsky_dni arg for cases where it's not used --- pvlib/irradiance.py | 2 +- pvlib/modelchain.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index f48b31dccd..36ccfff831 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2976,5 +2976,5 @@ def component_sum_irradiance(zenith, wrn_txt = ("No component sum calculated. Please recheck \n" "passed ghi, dni, and dhi parameters to check \n" "exactly one field out of the three is set to None.") - warnings.warn(wrn_txt) + warnings.warn(wrn_txt, UserWarning) return ghi_series, dhi_series, dni_series diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index d92a92e397..f69e09933a 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1320,16 +1320,14 @@ def _complete_irradiance(self, weather): zenith=self.results.solar_position.zenith, ghi=None, dhi=weather.dhi, - dni=weather.dni, - clearsky_dni=clearsky.dni) + dni=weather.dni) weather.loc[:, 'ghi'] = ghi elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, ghi=weather.ghi, dhi=None, - dni=weather.dni, - clearsky_dni=clearsky.dni) + dni=weather.dni) weather.loc[:, 'dhi'] = dhi def _prep_inputs_solar_pos(self, weather): From 73e9b55305b019f7676e8c781b9703357f353442 Mon Sep 17 00:00:00 2001 From: Perry Date: Wed, 5 Oct 2022 14:28:16 -0600 Subject: [PATCH 10/33] updated naming conventions for component_sum_irradiance function in modelchains --- pvlib/modelchain.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index f69e09933a..e0a1548b5f 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1310,24 +1310,24 @@ def _complete_irradiance(self, weather): weather.index, solar_position=self.results.solar_position) ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, - ghi=weather.ghi, - dhi=weather.dhi, - dni=None, + ghi_series=weather.ghi, + dhi_series=weather.dhi, + dni_series=None, clearsky_dni=clearsky.dni) weather.loc[:, 'dni'] = dni elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, - ghi=None, - dhi=weather.dhi, - dni=weather.dni) + ghi_series=None, + dhi_series=weather.dhi, + dni_series=weather.dni) weather.loc[:, 'ghi'] = ghi elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, - ghi=weather.ghi, - dhi=None, - dni=weather.dni) + ghi_series=weather.ghi, + dhi_series=None, + dni_series=weather.dni) weather.loc[:, 'dhi'] = dhi def _prep_inputs_solar_pos(self, weather): From 789540f50cf09051d1cdb2ba6a1f9cf516f8ecc3 Mon Sep 17 00:00:00 2001 From: Perry Date: Wed, 5 Oct 2022 14:59:29 -0600 Subject: [PATCH 11/33] updated the routines to remove pep8 errors, added to clearsky_dni docstring --- pvlib/irradiance.py | 5 +++-- pvlib/modelchain.py | 26 +++++++++++++------------- pvlib/tests/test_irradiance.py | 1 + 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 36ccfff831..7a66b79964 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2944,10 +2944,11 @@ def component_sum_irradiance(zenith, dni_series : Series, default None Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dhi, and zenith series, when available. - clearsky_dni : Series, default None + clearsky_dni : Series, (optional, default None) Pandas series of clearsky dni data, calculated via the get_clearsky function. Must have the same datetime index as ghi, dhi, - dni, and zenith series, when available. + dni, and zenith series, when available. This is an optional field that + is only used when calculating the DNI component sum series. Returns ------- diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index e0a1548b5f..e6556ca185 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1309,25 +1309,25 @@ def _complete_irradiance(self, weather): clearsky = self.location.get_clearsky( weather.index, solar_position=self.results.solar_position) ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( - zenith=self.results.solar_position.zenith, - ghi_series=weather.ghi, - dhi_series=weather.dhi, - dni_series=None, - clearsky_dni=clearsky.dni) + zenith=self.results.solar_position.zenith, + ghi_series=weather.ghi, + dhi_series=weather.dhi, + dni_series=None, + clearsky_dni=clearsky.dni) weather.loc[:, 'dni'] = dni elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( - zenith=self.results.solar_position.zenith, - ghi_series=None, - dhi_series=weather.dhi, - dni_series=weather.dni) + zenith=self.results.solar_position.zenith, + ghi_series=None, + dhi_series=weather.dhi, + dni_series=weather.dni) weather.loc[:, 'ghi'] = ghi elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( - zenith=self.results.solar_position.zenith, - ghi_series=weather.ghi, - dhi_series=None, - dni_series=weather.dni) + zenith=self.results.solar_position.zenith, + ghi_series=weather.ghi, + dhi_series=None, + dni_series=weather.dni) weather.loc[:, 'dhi'] = dhi def _prep_inputs_solar_pos(self, weather): diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index b0e13417c3..594778eb0b 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -30,6 +30,7 @@ def times(): return pd.date_range(start='20140624', freq='6H', periods=4, tz='US/Arizona') + @pytest.fixture def location(): return Location(32.2, -111, altitude=700) From 06cb5845ab967ffbff3f0d06161cbfaffb3d32ee Mon Sep 17 00:00:00 2001 From: Perry Date: Thu, 6 Oct 2022 13:58:40 -0600 Subject: [PATCH 12/33] updated the routine to return dataframe after calculating component sum + other suggestions --- pvlib/irradiance.py | 50 ++++++++++++-------------- pvlib/modelchain.py | 30 ++++++++-------- pvlib/tests/test_irradiance.py | 65 +++++++++++++++++----------------- 3 files changed, 71 insertions(+), 74 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 7a66b79964..5458e4f7e2 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -13,6 +13,7 @@ import warnings from pvlib import atmosphere, solarposition, tools +import pvlib # see References section of get_ground_diffuse function @@ -2919,9 +2920,9 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, def component_sum_irradiance(zenith, - ghi_series=None, - dhi_series=None, - dni_series=None, + ghi=None, + dhi=None, + dni=None, clearsky_dni=None): """ Use the component sum equations to calculate the missing series, using @@ -2935,13 +2936,13 @@ def component_sum_irradiance(zenith, True (not refraction-corrected) zenith angles in decimal degrees, with datetime index. Angles must be >=0 and <=180. Must have the same datetime index as ghi, dhi, and dni series, when available. - ghi_series : Series, default None + ghi : Series, default None Pandas series of dni data, with datetime index. Must have the same datetime index as dni, dhi, and zenith series, when available. - dhi_series : Series, default None + dhi : Series, default None Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dni, and zenith series, when available. - dni_series : Series, default None + dni : Series, default None Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dhi, and zenith series, when available. clearsky_dni : Series, (optional, default None) @@ -2952,30 +2953,25 @@ def component_sum_irradiance(zenith, Returns ------- - ghi : Series - Pandas series of GHI values with datetime index, which can either be - the original passed series or the component-sum calculated series - (if ghi passed as None) - dhi : Series - Pandas series of DHI values with datetime index, which can either be - the original passed series or the component-sum calculated series - (if dhi passed as None) - dni: Series - Pandas series of DNI values with datetime index, which can either be - the original passed series or the component-sum calculated series - (if dni passed as None) + component_sum_df : Dataframe + Pandas series of 'ghi', 'dhi', and 'dni' columns with datetime index """ - if (ghi_series, dhi_series) is not None and dni_series is None: - dni_series = dni(ghi_series, dhi_series, zenith, - clearsky_dni=clearsky_dni, - clearsky_tolerance=1.1) - elif (dhi_series, dni_series) is not None and ghi_series is None: - ghi_series = (dhi_series + dni_series * tools.cosd(zenith)) - elif (dni_series, ghi_series) is not None and dhi_series is None: - dhi_series = (ghi_series - dni_series * tools.cosd(zenith)) + if (ghi, dhi) is not None and dni is None: + dni = pvlib.irradiance.dni(ghi, dhi, zenith, + clearsky_dni=clearsky_dni, + clearsky_tolerance=1.1) + elif (dhi, dni) is not None and ghi is None: + ghi = (dhi + dni * tools.cosd(zenith)) + elif (dni, ghi) is not None and dhi is None: + dhi = (ghi - dni * tools.cosd(zenith)) else: wrn_txt = ("No component sum calculated. Please recheck \n" "passed ghi, dni, and dhi parameters to check \n" "exactly one field out of the three is set to None.") warnings.warn(wrn_txt, UserWarning) - return ghi_series, dhi_series, dni_series + # Merge the outputs into a master dataframe containing 'ghi', 'dhi', + # and 'dni' columns + component_sum_df = pd.concat({'ghi': ghi, + 'dhi': dhi, + 'dni': dni}, axis=1) + return component_sum_df diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index e6556ca185..0a04481765 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1308,27 +1308,27 @@ def _complete_irradiance(self, weather): if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns: clearsky = self.location.get_clearsky( weather.index, solar_position=self.results.solar_position) - ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( + component_sum_df = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, - ghi_series=weather.ghi, - dhi_series=weather.dhi, - dni_series=None, + ghi=weather.ghi, + dhi=weather.dhi, + dni=None, clearsky_dni=clearsky.dni) - weather.loc[:, 'dni'] = dni + weather.loc[:, 'dni'] = component_sum_df.dni elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: - ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( + component_sum_df = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, - ghi_series=None, - dhi_series=weather.dhi, - dni_series=weather.dni) - weather.loc[:, 'ghi'] = ghi + ghi=None, + dhi=weather.dhi, + dni=weather.dni) + weather.loc[:, 'ghi'] = component_sum_df.ghi elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: - ghi, dhi, dni = pvlib.irradiance.component_sum_irradiance( + component_sum_df = pvlib.irradiance.component_sum_irradiance( zenith=self.results.solar_position.zenith, - ghi_series=weather.ghi, - dhi_series=None, - dni_series=weather.dni) - weather.loc[:, 'dhi'] = dhi + ghi=weather.ghi, + dhi=None, + dni=weather.dni) + weather.loc[:, 'dhi'] = component_sum_df.dhi def _prep_inputs_solar_pos(self, weather): """ diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 594778eb0b..59a83d8e07 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -1101,50 +1101,51 @@ def test_component_sum_irradiance(location): # Get the clearsky data associated with the location clearsky = location.get_clearsky(times, solar_position=solar_position) # Test scenario where DNI is generated via component sum equation - ghi_series, dhi_series, dni_series = irradiance.component_sum_irradiance( + component_sum_df = irradiance.component_sum_irradiance( solar_position.zenith, - ghi_series=i.ghi, - dhi_series=i.dhi, - dni_series=None, + ghi=i.ghi, + dhi=i.dhi, + dni=None, clearsky_dni=clearsky.dni) - dni_series.name = 'dni' # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_series_equal(ghi_series, i.ghi) - assert_series_equal(dhi_series, i.dhi) - assert_series_equal(dni_series, i.dni) + assert_series_equal(component_sum_df.ghi, i.ghi) + assert_series_equal(component_sum_df.dhi, i.dhi) + assert_series_equal(component_sum_df.dni, i.dni) # Test scenario where GHI is generated via component sum equation - ghi_series, dhi_series, dni_series = irradiance.component_sum_irradiance( + component_sum_df = irradiance.component_sum_irradiance( solar_position.zenith, - ghi_series=i.ghi, - dhi_series=i.dhi, - dni_series=None, + ghi=i.ghi, + dhi=i.dhi, + dni=None, clearsky_dni=clearsky.dni) + # Assert that the ghi, dhi, and dni series match the original dataframe + # values + assert_series_equal(component_sum_df.ghi, i.ghi) + assert_series_equal(component_sum_df.dhi, i.dhi) + assert_series_equal(component_sum_df.dni, i.dni) # Test scenario where DHI is generated via component sum equation - ghi_series, dhi_series, dni_series = irradiance.component_sum_irradiance( + component_sum_df = irradiance.component_sum_irradiance( solar_position.zenith, - ghi_series=i.ghi, - dhi_series=i.dhi, - dni_series=None, + ghi=i.ghi, + dhi=i.dhi, + dni=None, clearsky_dni=clearsky.dni) - dni_series.name = 'dni' # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_series_equal(ghi_series, i.ghi) - assert_series_equal(dhi_series, i.dhi) - assert_series_equal(dni_series, i.dni) + assert_series_equal(component_sum_df.ghi, i.ghi) + assert_series_equal(component_sum_df.dhi, i.dhi) + assert_series_equal(component_sum_df.dni, i.dni) # Test scenario where all parameters are passed (throw warning) - ghi_series, dhi_series, dni_series = \ - assert_warns(UserWarning, - irradiance.component_sum_irradiance, - solar_position.zenith, - ghi_series=i.ghi, - dhi_series=i.dhi, - dni_series=i.dni, - clearsky_dni=clearsky.dni) - dni_series.name = 'dni' + component_sum_df = assert_warns(UserWarning, + irradiance.component_sum_irradiance, + solar_position.zenith, + ghi=i.ghi, + dhi=i.dhi, + dni=i.dni, + clearsky_dni=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_series_equal(ghi_series, i.ghi) - assert_series_equal(dhi_series, i.dhi) - assert_series_equal(dni_series, i.dni) + assert_series_equal(component_sum_df.ghi, i.ghi) + assert_series_equal(component_sum_df.dhi, i.dhi) + assert_series_equal(component_sum_df.dni, i.dni) From b0ae6f4a670b79b314ea11b8a377e9c540471f49 Mon Sep 17 00:00:00 2001 From: Perry Date: Mon, 10 Oct 2022 10:46:17 -0600 Subject: [PATCH 13/33] updated the PR based on @kanderso-nrel review --- pvlib/irradiance.py | 36 +++++++++++++++++----------------- pvlib/modelchain.py | 8 ++++---- pvlib/tests/test_irradiance.py | 26 +++++++++++++++--------- pvlib/tests/test_modelchain.py | 4 ++-- 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 5458e4f7e2..f3a47a983b 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2919,11 +2919,11 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, return dni -def component_sum_irradiance(zenith, +def component_sum_irradiance(solar_zenith, ghi=None, dhi=None, dni=None, - clearsky_dni=None): + dni_clear=None): """ Use the component sum equations to calculate the missing series, using the other available time series. One of the three parameters (ghi, dhi, @@ -2932,20 +2932,20 @@ def component_sum_irradiance(zenith, Parameters ---------- - zenith : Series - True (not refraction-corrected) zenith angles in decimal + solar_zenith : Series + Refraction-corrected zenith angles in decimal degrees, with datetime index. Angles must be >=0 and <=180. Must have the same datetime index as ghi, dhi, and dni series, when available. - ghi : Series, default None + ghi : Series, (optional, default None) Pandas series of dni data, with datetime index. Must have the same datetime index as dni, dhi, and zenith series, when available. - dhi : Series, default None + dhi : Series, (optional, default None) Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dni, and zenith series, when available. - dni : Series, default None + dni : Series, (optional, default None) Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dhi, and zenith series, when available. - clearsky_dni : Series, (optional, default None) + dni_clear : Series, (optional, default None) Pandas series of clearsky dni data, calculated via the get_clearsky function. Must have the same datetime index as ghi, dhi, dni, and zenith series, when available. This is an optional field that @@ -2956,14 +2956,14 @@ def component_sum_irradiance(zenith, component_sum_df : Dataframe Pandas series of 'ghi', 'dhi', and 'dni' columns with datetime index """ - if (ghi, dhi) is not None and dni is None: - dni = pvlib.irradiance.dni(ghi, dhi, zenith, - clearsky_dni=clearsky_dni, + if ghi is not None and dhi is not None and dni is None: + dni = pvlib.irradiance.dni(ghi, dhi, solar_zenith, + clearsky_dni=dni_clear, clearsky_tolerance=1.1) - elif (dhi, dni) is not None and ghi is None: - ghi = (dhi + dni * tools.cosd(zenith)) - elif (dni, ghi) is not None and dhi is None: - dhi = (ghi - dni * tools.cosd(zenith)) + elif dni is not None and dhi is not None and ghi is None: + ghi = (dhi + dni * tools.cosd(solar_zenith)) + elif dni is not None and ghi is not None and dhi is None: + dhi = (ghi - dni * tools.cosd(solar_zenith)) else: wrn_txt = ("No component sum calculated. Please recheck \n" "passed ghi, dni, and dhi parameters to check \n" @@ -2971,7 +2971,7 @@ def component_sum_irradiance(zenith, warnings.warn(wrn_txt, UserWarning) # Merge the outputs into a master dataframe containing 'ghi', 'dhi', # and 'dni' columns - component_sum_df = pd.concat({'ghi': ghi, - 'dhi': dhi, - 'dni': dni}, axis=1) + component_sum_df = pd.DataFrame({'ghi': ghi, + 'dhi': dhi, + 'dni': dni}) return component_sum_df diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 0a04481765..25a7a80eb6 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1309,22 +1309,22 @@ def _complete_irradiance(self, weather): clearsky = self.location.get_clearsky( weather.index, solar_position=self.results.solar_position) component_sum_df = pvlib.irradiance.component_sum_irradiance( - zenith=self.results.solar_position.zenith, + solar_zenith=self.results.solar_position.apparent_zenith, ghi=weather.ghi, dhi=weather.dhi, dni=None, - clearsky_dni=clearsky.dni) + dni_clear=clearsky.dni) weather.loc[:, 'dni'] = component_sum_df.dni elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: component_sum_df = pvlib.irradiance.component_sum_irradiance( - zenith=self.results.solar_position.zenith, + solar_zenith=self.results.solar_position.apparent_zenith, ghi=None, dhi=weather.dhi, dni=weather.dni) weather.loc[:, 'ghi'] = component_sum_df.ghi elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: component_sum_df = pvlib.irradiance.component_sum_irradiance( - zenith=self.results.solar_position.zenith, + solar_zenith=self.results.solar_position.apparent_zenith, ghi=weather.ghi, dhi=None, dni=weather.dni) diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 59a83d8e07..7dbb727f39 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -1092,7 +1092,7 @@ def test_clearness_index_zenith_independent(airmass_kt): def test_component_sum_irradiance(location): # Generate dataframe to test on times = pd.date_range('2010-07-05 7:00:00-0700', periods=2, freq='H') - i = pd.DataFrame({'dni': [49.756966, 62.153947], + i = pd.DataFrame({'dni': [49.63565561689957, 62.10624908037814], 'ghi': [372.103976116, 497.087579068], 'dhi': [356.543700, 465.44400]}, index=times) # Get zenith values associated with the location @@ -1102,11 +1102,11 @@ def test_component_sum_irradiance(location): clearsky = location.get_clearsky(times, solar_position=solar_position) # Test scenario where DNI is generated via component sum equation component_sum_df = irradiance.component_sum_irradiance( - solar_position.zenith, + solar_position.apparent_zenith, ghi=i.ghi, dhi=i.dhi, dni=None, - clearsky_dni=clearsky.dni) + dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values assert_series_equal(component_sum_df.ghi, i.ghi) @@ -1114,11 +1114,11 @@ def test_component_sum_irradiance(location): assert_series_equal(component_sum_df.dni, i.dni) # Test scenario where GHI is generated via component sum equation component_sum_df = irradiance.component_sum_irradiance( - solar_position.zenith, + solar_position.apparent_zenith, ghi=i.ghi, dhi=i.dhi, dni=None, - clearsky_dni=clearsky.dni) + dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values assert_series_equal(component_sum_df.ghi, i.ghi) @@ -1126,11 +1126,11 @@ def test_component_sum_irradiance(location): assert_series_equal(component_sum_df.dni, i.dni) # Test scenario where DHI is generated via component sum equation component_sum_df = irradiance.component_sum_irradiance( - solar_position.zenith, + solar_position.apparent_zenith, ghi=i.ghi, dhi=i.dhi, dni=None, - clearsky_dni=clearsky.dni) + dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values assert_series_equal(component_sum_df.ghi, i.ghi) @@ -1139,13 +1139,21 @@ def test_component_sum_irradiance(location): # Test scenario where all parameters are passed (throw warning) component_sum_df = assert_warns(UserWarning, irradiance.component_sum_irradiance, - solar_position.zenith, + solar_position.apparent_zenith, ghi=i.ghi, dhi=i.dhi, dni=i.dni, - clearsky_dni=clearsky.dni) + dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values assert_series_equal(component_sum_df.ghi, i.ghi) assert_series_equal(component_sum_df.dhi, i.dhi) assert_series_equal(component_sum_df.dni, i.dni) + # Test scenario where only one parameter is passed (throw warning) + component_sum_df = assert_warns(UserWarning, + irradiance.component_sum_irradiance, + solar_position.apparent_zenith, + ghi=None, + dhi=None, + dni=i.dni, + dni_clear=clearsky.dni) diff --git a/pvlib/tests/test_modelchain.py b/pvlib/tests/test_modelchain.py index 62b71f2042..3d8b055d25 100644 --- a/pvlib/tests/test_modelchain.py +++ b/pvlib/tests/test_modelchain.py @@ -1886,7 +1886,7 @@ def test_complete_irradiance(sapm_dc_snl_ac_system, location): """Check calculations""" mc = ModelChain(sapm_dc_snl_ac_system, location) times = pd.date_range('2010-07-05 7:00:00-0700', periods=2, freq='H') - i = pd.DataFrame({'dni': [49.756966, 62.153947], + i = pd.DataFrame({'dni': [49.63565561689957, 62.10624908037814], 'ghi': [372.103976116, 497.087579068], 'dhi': [356.543700, 465.44400]}, index=times) @@ -1904,7 +1904,7 @@ def test_complete_irradiance(sapm_dc_snl_ac_system, location): mc.complete_irradiance(i[['dhi', 'ghi']]) assert_series_equal(mc.results.weather['dni'], - pd.Series([49.756966, 62.153947], + pd.Series([49.63565561689957, 62.10624908037814], index=times, name='dni')) From e776928d4d086d5e3b3f535e9fe3d2a62efd21d7 Mon Sep 17 00:00:00 2001 From: Perry Date: Fri, 14 Oct 2022 13:30:40 -0600 Subject: [PATCH 14/33] made updates based on kanderso-nrel's suggestions --- pvlib/irradiance.py | 4 +-- pvlib/tests/test_irradiance.py | 50 +++++++++++++++------------------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index f3a47a983b..5de46cd31f 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2965,10 +2965,10 @@ def component_sum_irradiance(solar_zenith, elif dni is not None and ghi is not None and dhi is None: dhi = (ghi - dni * tools.cosd(solar_zenith)) else: - wrn_txt = ("No component sum calculated. Please recheck \n" + err_txt = ("No component sum calculated. Please recheck \n" "passed ghi, dni, and dhi parameters to check \n" "exactly one field out of the three is set to None.") - warnings.warn(wrn_txt, UserWarning) + raise ValueError(err_txt) # Merge the outputs into a master dataframe containing 'ghi', 'dhi', # and 'dni' columns component_sum_df = pd.DataFrame({'ghi': ghi, diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 7dbb727f39..439da1591f 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -8,7 +8,6 @@ import pytest from numpy.testing import assert_almost_equal, assert_allclose, assert_warns -from pvlib.location import Location from pvlib import irradiance from .conftest import ( @@ -31,11 +30,6 @@ def times(): tz='US/Arizona') -@pytest.fixture -def location(): - return Location(32.2, -111, altitude=700) - - @pytest.fixture def irrad_data(times): return pd.DataFrame(np.array( @@ -1089,17 +1083,25 @@ def test_clearness_index_zenith_independent(airmass_kt): assert_series_equal(out, expected) -def test_component_sum_irradiance(location): +def test_component_sum_irradiance(): # Generate dataframe to test on times = pd.date_range('2010-07-05 7:00:00-0700', periods=2, freq='H') i = pd.DataFrame({'dni': [49.63565561689957, 62.10624908037814], 'ghi': [372.103976116, 497.087579068], 'dhi': [356.543700, 465.44400]}, index=times) - # Get zenith values associated with the location - solar_position = location.get_solarposition(times, - method='nrel_numpy') - # Get the clearsky data associated with the location - clearsky = location.get_clearsky(times, solar_position=solar_position) + # Define the solar position and clearsky dataframes + solar_position = pd.DataFrame({'apparent_zenith': [71.7303262449161, + 59.369], + 'zenith': [71.7764, 59.395]}, + index=pd.DatetimeIndex([ + '2010-07-05 07:00:00-0700', + '2010-07-05 08:00:00-0700'])) + clearsky = pd.DataFrame({'ghi': [246.3508023804681, 469.461381740857], + 'dni': [625.5254880160008, 778.7766443075865], + 'dhi': [50.25488725346631, 72.66909939636372]}, + index=pd.DatetimeIndex([ + '2010-07-05 07:00:00-0700', + '2010-07-05 08:00:00-0700'])) # Test scenario where DNI is generated via component sum equation component_sum_df = irradiance.component_sum_irradiance( solar_position.apparent_zenith, @@ -1109,33 +1111,27 @@ def test_component_sum_irradiance(location): dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_series_equal(component_sum_df.ghi, i.ghi) - assert_series_equal(component_sum_df.dhi, i.dhi) - assert_series_equal(component_sum_df.dni, i.dni) + assert_frame_equal(component_sum_df, i) # Test scenario where GHI is generated via component sum equation component_sum_df = irradiance.component_sum_irradiance( solar_position.apparent_zenith, - ghi=i.ghi, + ghi=None, dhi=i.dhi, - dni=None, + dni=i.dni, dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_series_equal(component_sum_df.ghi, i.ghi) - assert_series_equal(component_sum_df.dhi, i.dhi) - assert_series_equal(component_sum_df.dni, i.dni) + assert_frame_equal(component_sum_df, i) # Test scenario where DHI is generated via component sum equation component_sum_df = irradiance.component_sum_irradiance( solar_position.apparent_zenith, ghi=i.ghi, - dhi=i.dhi, - dni=None, + dhi=None, + dni=i.dni, dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_series_equal(component_sum_df.ghi, i.ghi) - assert_series_equal(component_sum_df.dhi, i.dhi) - assert_series_equal(component_sum_df.dni, i.dni) + assert_frame_equal(component_sum_df, i) # Test scenario where all parameters are passed (throw warning) component_sum_df = assert_warns(UserWarning, irradiance.component_sum_irradiance, @@ -1146,9 +1142,7 @@ def test_component_sum_irradiance(location): dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_series_equal(component_sum_df.ghi, i.ghi) - assert_series_equal(component_sum_df.dhi, i.dhi) - assert_series_equal(component_sum_df.dni, i.dni) + assert_frame_equal(component_sum_df, i) # Test scenario where only one parameter is passed (throw warning) component_sum_df = assert_warns(UserWarning, irradiance.component_sum_irradiance, From 74c954de1eea85af8b36fb96889da68533c0b792 Mon Sep 17 00:00:00 2001 From: Perry Date: Fri, 14 Oct 2022 13:38:26 -0600 Subject: [PATCH 15/33] updated all the unit tests to pass --- pvlib/tests/test_irradiance.py | 51 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 439da1591f..7814fa3054 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -7,7 +7,10 @@ import pandas as pd import pytest -from numpy.testing import assert_almost_equal, assert_allclose, assert_warns +from numpy.testing import (assert_almost_equal, + assert_allclose, + assert_warns, + assert_raises) from pvlib import irradiance from .conftest import ( @@ -1086,9 +1089,10 @@ def test_clearness_index_zenith_independent(airmass_kt): def test_component_sum_irradiance(): # Generate dataframe to test on times = pd.date_range('2010-07-05 7:00:00-0700', periods=2, freq='H') - i = pd.DataFrame({'dni': [49.63565561689957, 62.10624908037814], - 'ghi': [372.103976116, 497.087579068], - 'dhi': [356.543700, 465.44400]}, index=times) + i = pd.DataFrame({'ghi': [372.103976116, 497.087579068], + 'dhi': [356.543700, 465.44400], + 'dni': [49.63565561689957, 62.10624908037814]}, + index=times) # Define the solar position and clearsky dataframes solar_position = pd.DataFrame({'apparent_zenith': [71.7303262449161, 59.369], @@ -1096,8 +1100,8 @@ def test_component_sum_irradiance(): index=pd.DatetimeIndex([ '2010-07-05 07:00:00-0700', '2010-07-05 08:00:00-0700'])) - clearsky = pd.DataFrame({'ghi': [246.3508023804681, 469.461381740857], - 'dni': [625.5254880160008, 778.7766443075865], + clearsky = pd.DataFrame({'dni': [625.5254880160008, 778.7766443075865], + 'ghi': [246.3508023804681, 469.461381740857], 'dhi': [50.25488725346631, 72.66909939636372]}, index=pd.DatetimeIndex([ '2010-07-05 07:00:00-0700', @@ -1132,22 +1136,19 @@ def test_component_sum_irradiance(): # Assert that the ghi, dhi, and dni series match the original dataframe # values assert_frame_equal(component_sum_df, i) - # Test scenario where all parameters are passed (throw warning) - component_sum_df = assert_warns(UserWarning, - irradiance.component_sum_irradiance, - solar_position.apparent_zenith, - ghi=i.ghi, - dhi=i.dhi, - dni=i.dni, - dni_clear=clearsky.dni) - # Assert that the ghi, dhi, and dni series match the original dataframe - # values - assert_frame_equal(component_sum_df, i) - # Test scenario where only one parameter is passed (throw warning) - component_sum_df = assert_warns(UserWarning, - irradiance.component_sum_irradiance, - solar_position.apparent_zenith, - ghi=None, - dhi=None, - dni=i.dni, - dni_clear=clearsky.dni) + # Test scenario where all parameters are passed (throw error) + component_sum_df = assert_raises(ValueError, + irradiance.component_sum_irradiance, + solar_position.apparent_zenith, + ghi=i.ghi, + dhi=i.dhi, + dni=i.dni, + dni_clear=clearsky.dni) + # Test scenario where only one parameter is passed (throw error) + component_sum_df = assert_raises(ValueError, + irradiance.component_sum_irradiance, + solar_position.apparent_zenith, + ghi=None, + dhi=None, + dni=i.dni, + dni_clear=clearsky.dni) From bebf34985de7063b3448001decf4569aa19d4e4a Mon Sep 17 00:00:00 2001 From: Kirsten Perry <70228568+kperrynrel@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:39:12 -0600 Subject: [PATCH 16/33] Update pvlib/irradiance.py Co-authored-by: Kevin Anderson --- pvlib/irradiance.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 5de46cd31f..40ec11f9bd 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2930,6 +2930,13 @@ def component_sum_irradiance(solar_zenith, dni) is passed as None, and the other associated series passed are used to calculate the missing series value. + The "component sum" or "closure" equation relates the three + primary irradiance components as follows: + + .. math:: + + GHI = DHI + DNI \cos(\theta_z) + Parameters ---------- solar_zenith : Series From f35b8e07183782538878083d82b93cf33188ddac Mon Sep 17 00:00:00 2001 From: Kirsten Perry <70228568+kperrynrel@users.noreply.github.com> Date: Mon, 17 Oct 2022 10:33:12 -0600 Subject: [PATCH 17/33] Update pvlib/irradiance.py Co-authored-by: Kevin Anderson --- pvlib/irradiance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 40ec11f9bd..521d8bdf33 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2924,7 +2924,7 @@ def component_sum_irradiance(solar_zenith, dhi=None, dni=None, dni_clear=None): - """ + r""" Use the component sum equations to calculate the missing series, using the other available time series. One of the three parameters (ghi, dhi, dni) is passed as None, and the other associated series passed are used to From 98e531ced39fb0fa9148ae9523def42e17b525cc Mon Sep 17 00:00:00 2001 From: Perry Date: Mon, 17 Oct 2022 12:42:20 -0600 Subject: [PATCH 18/33] moved warning out of dni generation call (just ghi and dhi) --- pvlib/modelchain.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 25a7a80eb6..07fbd9c490 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1304,7 +1304,6 @@ def _complete_irradiance(self, weather): "Results can be too high or negative.\n" + "Help to improve this function on github:\n" + "https://github.com/pvlib/pvlib-python \n") - warnings.warn(wrn_txt, UserWarning) if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns: clearsky = self.location.get_clearsky( weather.index, solar_position=self.results.solar_position) @@ -1316,6 +1315,7 @@ def _complete_irradiance(self, weather): dni_clear=clearsky.dni) weather.loc[:, 'dni'] = component_sum_df.dni elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: + warnings.warn(wrn_txt, UserWarning) component_sum_df = pvlib.irradiance.component_sum_irradiance( solar_zenith=self.results.solar_position.apparent_zenith, ghi=None, @@ -1323,6 +1323,7 @@ def _complete_irradiance(self, weather): dni=weather.dni) weather.loc[:, 'ghi'] = component_sum_df.ghi elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: + warnings.warn(wrn_txt, UserWarning) component_sum_df = pvlib.irradiance.component_sum_irradiance( solar_zenith=self.results.solar_position.apparent_zenith, ghi=weather.ghi, From ed6e106758b7b347913ad9c288d2cf4899583262 Mon Sep 17 00:00:00 2001 From: Perry Date: Mon, 17 Oct 2022 14:57:10 -0600 Subject: [PATCH 19/33] fix sticklerci formatting errors --- pvlib/irradiance.py | 1 - pvlib/tests/test_irradiance.py | 151 ++++++++++++++++----------------- 2 files changed, 75 insertions(+), 77 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 521d8bdf33..a9cabca754 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -10,7 +10,6 @@ import numpy as np import pandas as pd -import warnings from pvlib import atmosphere, solarposition, tools import pvlib diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 7814fa3054..54cab1cd2f 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -9,7 +9,6 @@ import pytest from numpy.testing import (assert_almost_equal, assert_allclose, - assert_warns, assert_raises) from pvlib import irradiance @@ -36,23 +35,23 @@ def times(): @pytest.fixture def irrad_data(times): return pd.DataFrame(np.array( - [[ 0. , 0. , 0. ], - [ 79.73860422, 316.1949056 , 40.46149818], + [[0., 0., 0.], + [79.73860422, 316.1949056, 40.46149818], [1042.48031487, 939.95469881, 118.45831879], - [ 257.20751138, 646.22886049, 62.03376265]]), + [257.20751138, 646.22886049, 62.03376265]]), columns=['ghi', 'dni', 'dhi'], index=times) @pytest.fixture def ephem_data(times): return pd.DataFrame(np.array( - [[124.0390863 , 124.0390863 , -34.0390863 , -34.0390863 , + [[124.0390863, 124.0390863, -34.0390863, -34.0390863, 352.69550699, -2.36677158], - [ 82.85457044, 82.97705621, 7.14542956, 7.02294379, - 66.71410338, -2.42072165], - [ 10.56413562, 10.56725766, 79.43586438, 79.43274234, + [82.85457044, 82.97705621, 7.14542956, 7.02294379, + 66.71410338, -2.42072165], + [10.56413562, 10.56725766, 79.43586438, 79.43274234, 144.76567754, -2.47457321], - [ 72.41687122, 72.46903556, 17.58312878, 17.53096444, + [72.41687122, 72.46903556, 17.58312878, 17.53096444, 287.04104128, -2.52831909]]), columns=['apparent_zenith', 'zenith', 'apparent_elevation', 'elevation', 'azimuth', 'equation_of_time'], @@ -230,7 +229,7 @@ def test_perez(irrad_data, ephem_data, dni_et, relative_airmass): dni_et, ephem_data['apparent_zenith'], ephem_data['azimuth'], relative_airmass) expected = pd.Series(np.array( - [ 0. , 31.46046871, np.nan, 45.45539877]), + [0., 31.46046871, np.nan, 45.45539877]), index=irrad_data.index) assert_series_equal(out, expected, check_less_precise=2) @@ -243,10 +242,10 @@ def test_perez_components(irrad_data, ephem_data, dni_et, relative_airmass): ephem_data['azimuth'], relative_airmass, return_components=True) expected = pd.DataFrame(np.array( - [[ 0. , 31.46046871, np.nan, 45.45539877], - [ 0. , 26.84138589, np.nan, 31.72696071], - [ 0. , 0. , np.nan, 4.47966439], - [ 0. , 4.62212181, np.nan, 9.25316454]]).T, + [[0., 31.46046871, np.nan, 45.45539877], + [0., 26.84138589, np.nan, 31.72696071], + [0., 0., np.nan, 4.47966439], + [0., 4.62212181, np.nan, 9.25316454]]).T, columns=['sky_diffuse', 'isotropic', 'circumsolar', 'horizon'], index=irrad_data.index ) @@ -269,12 +268,12 @@ def test_perez_negative_horizon(): # dni_e is slightly rounded from irradiance.get_extra_radiation # airmass from atmosphere.get_relative_airmas inputs = pd.DataFrame(np.array( - [[ 158, 19, 1, 0, 0], - [ 249, 165, 136, 93, 50], - [ 57.746951, 57.564205, 60.813841, 66.989435, 75.353368], - [ 171.003315, 187.346924, 202.974357, 216.725599, 228.317233], + [[158, 19, 1, 0, 0], + [249, 165, 136, 93, 50], + [57.746951, 57.564205, 60.813841, 66.989435, 75.353368], + [171.003315, 187.346924, 202.974357, 216.725599, 228.317233], [1414, 1414, 1414, 1414, 1414], - [ 1.869315, 1.859981, 2.044429, 2.544943, 3.900136]]).T, + [1.869315, 1.859981, 2.044429, 2.544943, 3.900136]]).T, columns=['dni', 'dhi', 'solar_zenith', 'solar_azimuth', 'dni_extra', 'airmass'], index=times @@ -292,7 +291,7 @@ def test_perez_negative_horizon(): [[281.410185, 152.20879, 123.867898, 82.836412, 43.517015], [166.785419, 142.24475, 119.173875, 83.525150, 45.725931], [113.548755, 16.09757, 9.956174, 3.142467, 0], - [ 1.076010, -6.13353, -5.262151, -3.831230, -2.208923]]).T, + [1.076010, -6.13353, -5.262151, -3.831230, -2.208923]]).T, columns=['sky_diffuse', 'isotropic', 'circumsolar', 'horizon'], index=times ) @@ -313,7 +312,7 @@ def test_perez_arrays(irrad_data, ephem_data, dni_et, relative_airmass): ephem_data['azimuth'].values, relative_airmass.values) expected = np.array( - [ 0. , 31.46046871, np.nan, 45.45539877]) + [0., 31.46046871, np.nan, 45.45539877]) assert_allclose(out, expected, atol=1e-2) assert isinstance(out, np.ndarray) @@ -471,14 +470,14 @@ def test_poa_components(irrad_data, ephem_data, dni_et, relative_airmass): out = irradiance.poa_components( aoi, irrad_data['dni'], diff_perez, gr_sand) expected = pd.DataFrame(np.array( - [[ 0. , -0. , 0. , 0. , - 0. ], - [ 35.19456561, 0. , 35.19456561, 31.4635077 , + [[0., -0., 0., 0., + 0.], + [35.19456561, 0., 35.19456561, 31.4635077, 3.73105791], [956.18253696, 798.31939281, 157.86314414, 109.08433162, - 48.77881252], - [ 90.99624896, 33.50143401, 57.49481495, 45.45978964, - 12.03502531]]), + 48.77881252], + [90.99624896, 33.50143401, 57.49481495, 45.45978964, + 12.03502531]]), columns=['poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse', 'poa_ground_diffuse'], index=irrad_data.index) @@ -683,9 +682,9 @@ def test_gti_dirint(): expected_col_order = ['ghi', 'dni', 'dhi'] expected = pd.DataFrame(array( - [[ 21.05796198, 0. , 21.05796198], - [ 291.40037163, 63.41290679, 246.56067523], - [ 931.04078010, 695.94965324, 277.06172442]]), + [[21.05796198, 0., 21.05796198], + [291.40037163, 63.41290679, 246.56067523], + [931.04078010, 695.94965324, 277.06172442]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -707,9 +706,9 @@ def test_gti_dirint(): pressure=pressure) expected = pd.DataFrame(array( - [[ 21.05796198, 0. , 21.05796198], - [ 293.21310935, 63.27500913, 248.47092131], - [ 932.46756378, 648.05001357, 323.49974813]]), + [[21.05796198, 0., 21.05796198], + [293.21310935, 63.27500913, 248.47092131], + [932.46756378, 648.05001357, 323.49974813]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -721,9 +720,9 @@ def test_gti_dirint(): albedo=albedo) expected = pd.DataFrame(array( - [[ 21.3592591, 0. , 21.3592591 ], - [ 294.4985420, 66.25848451, 247.64671830], - [ 941.7943404, 727.50552952, 258.16276278]]), + [[21.3592591, 0., 21.3592591], + [294.4985420, 66.25848451, 247.64671830], + [941.7943404, 727.50552952, 258.16276278]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -743,9 +742,9 @@ def test_gti_dirint(): temp_dew=temp_dew) expected = pd.DataFrame(array( - [[ 21.05796198, 0., 21.05796198], - [ 295.06070190, 38.20346345, 268.0467738], - [ 931.79627208, 689.81549269, 283.5817439]]), + [[21.05796198, 0., 21.05796198], + [295.06070190, 38.20346345, 268.0467738], + [931.79627208, 689.81549269, 283.5817439]]), columns=expected_col_order, index=times) assert_frame_equal(output, expected) @@ -952,7 +951,7 @@ def airmass_kt(): def test_kt_kt_prime_factor(airmass_kt): out = irradiance._kt_kt_prime_factor(airmass_kt) - expected = np.array([ 0.999971, 0.723088, 0.548811, 0.471068]) + expected = np.array([0.999971, 0.723088, 0.548811, 0.471068]) assert_allclose(out, expected, atol=1e-5) @@ -963,11 +962,11 @@ def test_clearsky_index(): with np.errstate(invalid='ignore', divide='ignore'): out = irradiance.clearsky_index(ghi_measured, ghi_modeled) expected = np.array( - [[1. , 0. , 0. , 0. , 0. , np.nan], - [0. , 0. , 0. , 0. , 0. , np.nan], - [0. , 0. , 1. , 2. , 2. , np.nan], - [0. , 0. , 0.002 , 1. , 2. , np.nan], - [0. , 0. , 0.001 , 0.5 , 1. , np.nan], + [[1., 0., 0., 0., 0., np.nan], + [0., 0., 0., 0., 0., np.nan], + [0., 0., 1., 2., 2., np.nan], + [0., 0., 0.002, 1., 2., np.nan], + [0., 0., 0.001, 0.5, 1., np.nan], [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan]]) assert_allclose(out, expected, atol=0.001) # specify max_clearsky_index @@ -975,11 +974,11 @@ def test_clearsky_index(): out = irradiance.clearsky_index(ghi_measured, ghi_modeled, max_clearsky_index=1.5) expected = np.array( - [[1. , 0. , 0. , 0. , 0. , np.nan], - [0. , 0. , 0. , 0. , 0. , np.nan], - [0. , 0. , 1. , 1.5 , 1.5 , np.nan], - [0. , 0. , 0.002 , 1. , 1.5 , np.nan], - [0. , 0. , 0.001 , 0.5 , 1. , np.nan], + [[1., 0., 0., 0., 0., np.nan], + [0., 0., 0., 0., 0., np.nan], + [0., 0., 1., 1.5, 1.5, np.nan], + [0., 0., 0.002, 1., 1.5, np.nan], + [0., 0., 0.001, 0.5, 1., np.nan], [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan]]) assert_allclose(out, expected, atol=0.001) # scalars @@ -1003,29 +1002,29 @@ def test_clearness_index(): out = irradiance.clearness_index(ghi, solar_zenith, 1370) # np.set_printoptions(precision=3, floatmode='maxprec', suppress=True) expected = np.array( - [[0. , 0. , 0.011, 2. ], - [0. , 0. , 0.011, 2. ], - [0. , 0. , 0.011, 2. ], - [0. , 0. , 0.001, 0.73 ]]) + [[0., 0., 0.011, 2.], + [0., 0., 0.011, 2.], + [0., 0., 0.011, 2.], + [0., 0., 0.001, 0.73]]) assert_allclose(out, expected, atol=0.001) # specify min_cos_zenith with np.errstate(invalid='ignore', divide='ignore'): out = irradiance.clearness_index(ghi, solar_zenith, 1400, min_cos_zenith=0) expected = np.array( - [[0. , nan, 2. , 2. ], - [0. , 0. , 2. , 2. ], - [0. , 0. , 2. , 2. ], - [0. , 0. , 0.001, 0.714]]) + [[0., nan, 2., 2.], + [0., 0., 2., 2.], + [0., 0., 2., 2.], + [0., 0., 0.001, 0.714]]) assert_allclose(out, expected, atol=0.001) # specify max_clearness_index out = irradiance.clearness_index(ghi, solar_zenith, 1370, max_clearness_index=0.82) expected = np.array( - [[ 0. , 0. , 0.011, 0.82 ], - [ 0. , 0. , 0.011, 0.82 ], - [ 0. , 0. , 0.011, 0.82 ], - [ 0. , 0. , 0.001, 0.73 ]]) + [[0., 0., 0.011, 0.82], + [0., 0., 0.011, 0.82], + [0., 0., 0.011, 0.82], + [0., 0., 0.001, 0.73]]) assert_allclose(out, expected, atol=0.001) # specify min_cos_zenith and max_clearness_index with np.errstate(invalid='ignore', divide='ignore'): @@ -1033,10 +1032,10 @@ def test_clearness_index(): min_cos_zenith=0, max_clearness_index=0.82) expected = np.array( - [[ 0. , nan, 0.82 , 0.82 ], - [ 0. , 0. , 0.82 , 0.82 ], - [ 0. , 0. , 0.82 , 0.82 ], - [ 0. , 0. , 0.001, 0.714]]) + [[0., nan, 0.82, 0.82], + [0., 0., 0.82, 0.82], + [0., 0., 0.82, 0.82], + [0., 0., 0.001, 0.714]]) assert_allclose(out, expected, atol=0.001) # scalars out = irradiance.clearness_index(1000, 10, 1400) @@ -1058,19 +1057,19 @@ def test_clearness_index_zenith_independent(airmass_kt): out = irradiance.clearness_index_zenith_independent(clearness_index, airmass_kt) expected = np.array( - [[0. , 0. , 0.1 , 1. ], - [0. , 0. , 0.138, 1.383], - [0. , 0. , 0.182, 1.822], - [0. , 0. , 0.212, 2. ]]) + [[0., 0., 0.1, 1.], + [0., 0., 0.138, 1.383], + [0., 0., 0.182, 1.822], + [0., 0., 0.212, 2.]]) assert_allclose(out, expected, atol=0.001) # test max_clearness_index out = irradiance.clearness_index_zenith_independent( clearness_index, airmass_kt, max_clearness_index=0.82) expected = np.array( - [[ 0. , 0. , 0.1 , 0.82 ], - [ 0. , 0. , 0.138, 0.82 ], - [ 0. , 0. , 0.182, 0.82 ], - [ 0. , 0. , 0.212, 0.82 ]]) + [[0., 0., 0.1, 0.82], + [0., 0., 0.138, 0.82], + [0., 0., 0.182, 0.82], + [0., 0., 0.212, 0.82]]) assert_allclose(out, expected, atol=0.001) # scalars out = irradiance.clearness_index_zenith_independent(.4, 2) @@ -1104,8 +1103,8 @@ def test_component_sum_irradiance(): 'ghi': [246.3508023804681, 469.461381740857], 'dhi': [50.25488725346631, 72.66909939636372]}, index=pd.DatetimeIndex([ - '2010-07-05 07:00:00-0700', - '2010-07-05 08:00:00-0700'])) + '2010-07-05 07:00:00-0700', + '2010-07-05 08:00:00-0700'])) # Test scenario where DNI is generated via component sum equation component_sum_df = irradiance.component_sum_irradiance( solar_position.apparent_zenith, From 9cfde3b9d2a394c8513f1a1554f6488d1de0219a Mon Sep 17 00:00:00 2001 From: Kirsten Perry <70228568+kperrynrel@users.noreply.github.com> Date: Tue, 25 Oct 2022 16:16:10 -0600 Subject: [PATCH 20/33] Update pvlib/irradiance.py Co-authored-by: Kevin Anderson --- pvlib/irradiance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index a9cabca754..6447e6b5b2 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2942,7 +2942,7 @@ def component_sum_irradiance(solar_zenith, Refraction-corrected zenith angles in decimal degrees, with datetime index. Angles must be >=0 and <=180. Must have the same datetime index as ghi, dhi, and dni series, when available. - ghi : Series, (optional, default None) + ghi : Series, optional Pandas series of dni data, with datetime index. Must have the same datetime index as dni, dhi, and zenith series, when available. dhi : Series, (optional, default None) From 7cc348541ac3a2c54f73bd3182c3b149f856eca3 Mon Sep 17 00:00:00 2001 From: Perry Date: Tue, 25 Oct 2022 16:27:47 -0600 Subject: [PATCH 21/33] updates to name-changed to 'complete_irradiance' --- docs/sphinx/source/reference/irradiance.rst | 2 +- docs/sphinx/source/whatsnew/v0.9.4.rst | 2 +- pvlib/irradiance.py | 14 ++++++------- pvlib/modelchain.py | 12 +++++------ pvlib/tests/test_irradiance.py | 22 ++++++++++----------- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/sphinx/source/reference/irradiance.rst b/docs/sphinx/source/reference/irradiance.rst index a348092b1b..ad3da96eab 100644 --- a/docs/sphinx/source/reference/irradiance.rst +++ b/docs/sphinx/source/reference/irradiance.rst @@ -28,7 +28,7 @@ Decomposing and combining irradiance irradiance.poa_components irradiance.get_ground_diffuse irradiance.dni - irradiance.component_sum_irradiance + irradiance.complete_irradiance Transposition models -------------------- diff --git a/docs/sphinx/source/whatsnew/v0.9.4.rst b/docs/sphinx/source/whatsnew/v0.9.4.rst index de8317729b..bf96908140 100644 --- a/docs/sphinx/source/whatsnew/v0.9.4.rst +++ b/docs/sphinx/source/whatsnew/v0.9.4.rst @@ -11,7 +11,7 @@ Enhancements ~~~~~~~~~~~~ * Multiple code style issues fixed that were reported by LGTM analysis. (:issue:`1275`, :pull:`1559`) * Added the component sum irradiance function to calculate the component sum value for GHI, DHI, and DNI values - :py:func:`~pvlib.irradiance.component_sum_irradiance` + :py:func:`~pvlib.irradiance.complete_irradiance` (:issue:`1565`, :pull:`1567`) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 6447e6b5b2..93b66f137b 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2918,11 +2918,11 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1, return dni -def component_sum_irradiance(solar_zenith, - ghi=None, - dhi=None, - dni=None, - dni_clear=None): +def complete_irradiance(solar_zenith, + ghi=None, + dhi=None, + dni=None, + dni_clear=None): r""" Use the component sum equations to calculate the missing series, using the other available time series. One of the three parameters (ghi, dhi, @@ -2971,8 +2971,8 @@ def component_sum_irradiance(solar_zenith, elif dni is not None and ghi is not None and dhi is None: dhi = (ghi - dni * tools.cosd(solar_zenith)) else: - err_txt = ("No component sum calculated. Please recheck \n" - "passed ghi, dni, and dhi parameters to check \n" + err_txt = ("No component sum calculated. Please recheck " + "passed ghi, dni, and dhi parameters to check " "exactly one field out of the three is set to None.") raise ValueError(err_txt) # Merge the outputs into a master dataframe containing 'ghi', 'dhi', diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 07fbd9c490..14dc29230a 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1307,29 +1307,29 @@ def _complete_irradiance(self, weather): if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns: clearsky = self.location.get_clearsky( weather.index, solar_position=self.results.solar_position) - component_sum_df = pvlib.irradiance.component_sum_irradiance( + complete_irrad_df = pvlib.irradiance.complete_irradiance( solar_zenith=self.results.solar_position.apparent_zenith, ghi=weather.ghi, dhi=weather.dhi, dni=None, dni_clear=clearsky.dni) - weather.loc[:, 'dni'] = component_sum_df.dni + weather.loc[:, 'dni'] = complete_irrad_df.dni elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: warnings.warn(wrn_txt, UserWarning) - component_sum_df = pvlib.irradiance.component_sum_irradiance( + complete_irrad_df = pvlib.irradiance.complete_irradiance( solar_zenith=self.results.solar_position.apparent_zenith, ghi=None, dhi=weather.dhi, dni=weather.dni) - weather.loc[:, 'ghi'] = component_sum_df.ghi + weather.loc[:, 'ghi'] = complete_irrad_df.ghi elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: warnings.warn(wrn_txt, UserWarning) - component_sum_df = pvlib.irradiance.component_sum_irradiance( + complete_irrad_df = pvlib.irradiance.complete_irradiance( solar_zenith=self.results.solar_position.apparent_zenith, ghi=weather.ghi, dhi=None, dni=weather.dni) - weather.loc[:, 'dhi'] = component_sum_df.dhi + weather.loc[:, 'dhi'] = complete_irrad_df.dhi def _prep_inputs_solar_pos(self, weather): """ diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 54cab1cd2f..a7b67311bf 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -1085,7 +1085,7 @@ def test_clearness_index_zenith_independent(airmass_kt): assert_series_equal(out, expected) -def test_component_sum_irradiance(): +def test_complete_irradiance(): # Generate dataframe to test on times = pd.date_range('2010-07-05 7:00:00-0700', periods=2, freq='H') i = pd.DataFrame({'ghi': [372.103976116, 497.087579068], @@ -1106,7 +1106,7 @@ def test_component_sum_irradiance(): '2010-07-05 07:00:00-0700', '2010-07-05 08:00:00-0700'])) # Test scenario where DNI is generated via component sum equation - component_sum_df = irradiance.component_sum_irradiance( + complete_df = irradiance.complete_irradiance( solar_position.apparent_zenith, ghi=i.ghi, dhi=i.dhi, @@ -1114,9 +1114,9 @@ def test_component_sum_irradiance(): dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_frame_equal(component_sum_df, i) + assert_frame_equal(complete_df, i) # Test scenario where GHI is generated via component sum equation - component_sum_df = irradiance.component_sum_irradiance( + complete_df = irradiance.complete_irradiance( solar_position.apparent_zenith, ghi=None, dhi=i.dhi, @@ -1124,9 +1124,9 @@ def test_component_sum_irradiance(): dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_frame_equal(component_sum_df, i) + assert_frame_equal(complete_df, i) # Test scenario where DHI is generated via component sum equation - component_sum_df = irradiance.component_sum_irradiance( + complete_df = irradiance.complete_irradiance( solar_position.apparent_zenith, ghi=i.ghi, dhi=None, @@ -1134,18 +1134,18 @@ def test_component_sum_irradiance(): dni_clear=clearsky.dni) # Assert that the ghi, dhi, and dni series match the original dataframe # values - assert_frame_equal(component_sum_df, i) + assert_frame_equal(complete_df, i) # Test scenario where all parameters are passed (throw error) - component_sum_df = assert_raises(ValueError, - irradiance.component_sum_irradiance, + complete_df = assert_raises(ValueError, + irradiance.complete_irradiance, solar_position.apparent_zenith, ghi=i.ghi, dhi=i.dhi, dni=i.dni, dni_clear=clearsky.dni) # Test scenario where only one parameter is passed (throw error) - component_sum_df = assert_raises(ValueError, - irradiance.component_sum_irradiance, + complete_df = assert_raises(ValueError, + irradiance.complete_irradiance, solar_position.apparent_zenith, ghi=None, dhi=None, From aff38d45d7a1310fff501e50163659d4c3e4e92e Mon Sep 17 00:00:00 2001 From: Perry Date: Tue, 25 Oct 2022 17:07:47 -0600 Subject: [PATCH 22/33] fixed over-indentation error --- pvlib/tests/test_irradiance.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index a7b67311bf..1ea619118a 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -1137,17 +1137,17 @@ def test_complete_irradiance(): assert_frame_equal(complete_df, i) # Test scenario where all parameters are passed (throw error) complete_df = assert_raises(ValueError, - irradiance.complete_irradiance, - solar_position.apparent_zenith, - ghi=i.ghi, - dhi=i.dhi, - dni=i.dni, - dni_clear=clearsky.dni) + irradiance.complete_irradiance, + solar_position.apparent_zenith, + ghi=i.ghi, + dhi=i.dhi, + dni=i.dni, + dni_clear=clearsky.dni) # Test scenario where only one parameter is passed (throw error) complete_df = assert_raises(ValueError, - irradiance.complete_irradiance, - solar_position.apparent_zenith, - ghi=None, - dhi=None, - dni=i.dni, - dni_clear=clearsky.dni) + irradiance.complete_irradiance, + solar_position.apparent_zenith, + ghi=None, + dhi=None, + dni=i.dni, + dni_clear=clearsky.dni) From e595465e6f678866a3bde3fa070f9b14d2a5347f Mon Sep 17 00:00:00 2001 From: Perry Date: Wed, 26 Oct 2022 11:34:01 -0600 Subject: [PATCH 23/33] removed default none from function params --- pvlib/irradiance.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 93b66f137b..036af91b42 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2945,13 +2945,13 @@ def complete_irradiance(solar_zenith, ghi : Series, optional Pandas series of dni data, with datetime index. Must have the same datetime index as dni, dhi, and zenith series, when available. - dhi : Series, (optional, default None) + dhi : Series, optional Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dni, and zenith series, when available. - dni : Series, (optional, default None) + dni : Series, optional Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dhi, and zenith series, when available. - dni_clear : Series, (optional, default None) + dni_clear : Series, optional Pandas series of clearsky dni data, calculated via the get_clearsky function. Must have the same datetime index as ghi, dhi, dni, and zenith series, when available. This is an optional field that From 4fac56f4a7adce117ac6b514988d53c8a02b9610 Mon Sep 17 00:00:00 2001 From: Kirsten Perry <70228568+kperrynrel@users.noreply.github.com> Date: Fri, 28 Oct 2022 10:56:25 -0600 Subject: [PATCH 24/33] Update docs/sphinx/source/whatsnew/v0.9.4.rst Co-authored-by: Cliff Hansen --- docs/sphinx/source/whatsnew/v0.9.4.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/source/whatsnew/v0.9.4.rst b/docs/sphinx/source/whatsnew/v0.9.4.rst index aae10af99a..1348221bd4 100644 --- a/docs/sphinx/source/whatsnew/v0.9.4.rst +++ b/docs/sphinx/source/whatsnew/v0.9.4.rst @@ -10,7 +10,7 @@ Deprecations Enhancements ~~~~~~~~~~~~ * Multiple code style issues fixed that were reported by LGTM analysis. (:issue:`1275`, :pull:`1559`) -* Added the component sum irradiance function to calculate the component sum value for GHI, DHI, and DNI values +* Added a function to calculate one of GHI, DHI, and DNI from values of the other two. :py:func:`~pvlib.irradiance.complete_irradiance` (:issue:`1565`, :pull:`1567`) From b9ec98737b173dd8cf709514a49e21c030b74041 Mon Sep 17 00:00:00 2001 From: "Perry, Kirsten" Date: Fri, 28 Oct 2022 12:46:43 -0600 Subject: [PATCH 25/33] made updates based on @cwhanse's recommendations --- pvlib/irradiance.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 036af91b42..a666289cfa 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2939,9 +2939,9 @@ def complete_irradiance(solar_zenith, Parameters ---------- solar_zenith : Series - Refraction-corrected zenith angles in decimal - degrees, with datetime index. Angles must be >=0 and <=180. Must have - the same datetime index as ghi, dhi, and dni series, when available. + Zenith angles in decimal degrees, with datetime index. + Angles must be >=0 and <=180. Must have the same datetime index + as ghi, dhi, and dni series, when available. ghi : Series, optional Pandas series of dni data, with datetime index. Must have the same datetime index as dni, dhi, and zenith series, when available. @@ -2971,9 +2971,8 @@ def complete_irradiance(solar_zenith, elif dni is not None and ghi is not None and dhi is None: dhi = (ghi - dni * tools.cosd(solar_zenith)) else: - err_txt = ("No component sum calculated. Please recheck " - "passed ghi, dni, and dhi parameters to check " - "exactly one field out of the three is set to None.") + err_txt = ("No component sum calculated. Please check that " + "exactly one of ghi, dhi and dni parameters is set to None") raise ValueError(err_txt) # Merge the outputs into a master dataframe containing 'ghi', 'dhi', # and 'dni' columns From 7ce6fa61fe607e61dceb81282d8a0b97e800b5d1 Mon Sep 17 00:00:00 2001 From: Kirsten Perry <70228568+kperrynrel@users.noreply.github.com> Date: Mon, 31 Oct 2022 09:23:16 -0600 Subject: [PATCH 26/33] Update pvlib/irradiance.py Co-authored-by: Will Holmgren --- pvlib/irradiance.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index a666289cfa..b34109f46a 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2971,9 +2971,10 @@ def complete_irradiance(solar_zenith, elif dni is not None and ghi is not None and dhi is None: dhi = (ghi - dni * tools.cosd(solar_zenith)) else: - err_txt = ("No component sum calculated. Please check that " - "exactly one of ghi, dhi and dni parameters is set to None") - raise ValueError(err_txt) + raise ValueError( + "Please check that exactly one of ghi, dhi and dni parameters " + "is set to None" + ) # Merge the outputs into a master dataframe containing 'ghi', 'dhi', # and 'dni' columns component_sum_df = pd.DataFrame({'ghi': ghi, From 881779eb91a7c0f19c34c8de65c9d4f3186e5509 Mon Sep 17 00:00:00 2001 From: Kirsten Perry <70228568+kperrynrel@users.noreply.github.com> Date: Mon, 31 Oct 2022 09:23:52 -0600 Subject: [PATCH 27/33] Update pvlib/irradiance.py Co-authored-by: Will Holmgren --- pvlib/irradiance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index b34109f46a..3f2f298302 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -12,7 +12,7 @@ import pandas as pd from pvlib import atmosphere, solarposition, tools -import pvlib +import pvlib # used to avoid dni name collision in complete_irradiance # see References section of get_ground_diffuse function From a0d6b18725e10d13337808c222715c7f8b22daee Mon Sep 17 00:00:00 2001 From: "Perry, Kirsten" Date: Mon, 31 Oct 2022 12:31:37 -0600 Subject: [PATCH 28/33] changed to pytest error raise based on @wholmgren's recommendation --- pvlib/tests/test_irradiance.py | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index e56efd4eee..1a1971ae44 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -8,8 +8,7 @@ import pytest from numpy.testing import (assert_almost_equal, - assert_allclose, - assert_raises) + assert_allclose) from pvlib import irradiance from .conftest import ( @@ -1136,18 +1135,16 @@ def test_complete_irradiance(): # values assert_frame_equal(complete_df, i) # Test scenario where all parameters are passed (throw error) - complete_df = assert_raises(ValueError, - irradiance.complete_irradiance, - solar_position.apparent_zenith, - ghi=i.ghi, - dhi=i.dhi, - dni=i.dni, - dni_clear=clearsky.dni) + with pytest.raises(ValueError): + irradiance.complete_irradiance(solar_position.apparent_zenith, + ghi=i.ghi, + dhi=i.dhi, + dni=i.dni, + dni_clear=clearsky.dni) # Test scenario where only one parameter is passed (throw error) - complete_df = assert_raises(ValueError, - irradiance.complete_irradiance, - solar_position.apparent_zenith, - ghi=None, - dhi=None, - dni=i.dni, - dni_clear=clearsky.dni) + with pytest.raises(ValueError): + irradiance.complete_irradiance(solar_position.apparent_zenith, + ghi=None, + dhi=None, + dni=i.dni, + dni_clear=clearsky.dni) \ No newline at end of file From 99205b4daa88910c3c3e3d0ee592799ac3605404 Mon Sep 17 00:00:00 2001 From: "Perry, Kirsten" Date: Mon, 31 Oct 2022 12:36:06 -0600 Subject: [PATCH 29/33] Made updates to code based on @wholmgren's recommendations --- pvlib/irradiance.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index a666289cfa..1c64262406 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -2952,10 +2952,9 @@ def complete_irradiance(solar_zenith, Pandas series of dni data, with datetime index. Must have the same datetime index as ghi, dhi, and zenith series, when available. dni_clear : Series, optional - Pandas series of clearsky dni data, calculated via the - get_clearsky function. Must have the same datetime index as ghi, dhi, - dni, and zenith series, when available. This is an optional field that - is only used when calculating the DNI component sum series. + Pandas series of clearsky dni data. Must have the same datetime index + as ghi, dhi, dni, and zenith series, when available. See + :py:func:`dni` for details. Returns ------- From 01736b910817c193c3075d4929c2fffcec1d0f6d Mon Sep 17 00:00:00 2001 From: "Perry, Kirsten" Date: Mon, 31 Oct 2022 12:41:19 -0600 Subject: [PATCH 30/33] fix pep8 error 2 --- pvlib/tests/test_irradiance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 1a1971ae44..e4a36da589 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -1147,4 +1147,4 @@ def test_complete_irradiance(): ghi=None, dhi=None, dni=i.dni, - dni_clear=clearsky.dni) \ No newline at end of file + dni_clear=clearsky.dni) From 3958012aab2c98b1a9ead9f835573dd6726d436d Mon Sep 17 00:00:00 2001 From: "Perry, Kirsten" Date: Mon, 31 Oct 2022 14:56:38 -0600 Subject: [PATCH 31/33] updated modelchains to use zenith instead of apparent zenith --- pvlib/modelchain.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 14dc29230a..ccf2e614f3 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1308,7 +1308,7 @@ def _complete_irradiance(self, weather): clearsky = self.location.get_clearsky( weather.index, solar_position=self.results.solar_position) complete_irrad_df = pvlib.irradiance.complete_irradiance( - solar_zenith=self.results.solar_position.apparent_zenith, + solar_zenith=self.results.solar_position.zenith, ghi=weather.ghi, dhi=weather.dhi, dni=None, @@ -1317,7 +1317,7 @@ def _complete_irradiance(self, weather): elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: warnings.warn(wrn_txt, UserWarning) complete_irrad_df = pvlib.irradiance.complete_irradiance( - solar_zenith=self.results.solar_position.apparent_zenith, + solar_zenith=self.results.solar_position.zenith, ghi=None, dhi=weather.dhi, dni=weather.dni) @@ -1325,7 +1325,7 @@ def _complete_irradiance(self, weather): elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: warnings.warn(wrn_txt, UserWarning) complete_irrad_df = pvlib.irradiance.complete_irradiance( - solar_zenith=self.results.solar_position.apparent_zenith, + solar_zenith=self.results.solar_position.zenith, ghi=weather.ghi, dhi=None, dni=weather.dni) From 725d859fd651372eadf3aeba4aec4535953633fe Mon Sep 17 00:00:00 2001 From: "Perry, Kirsten" Date: Mon, 31 Oct 2022 16:29:28 -0600 Subject: [PATCH 32/33] check that unit tests run --- pvlib/tests/test_irradiance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index b663b3a7af..ae3a7ec88a 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -1130,7 +1130,7 @@ def test_complete_irradiance(): 'dhi': [356.543700, 465.44400], 'dni': [49.63565561689957, 62.10624908037814]}, index=times) - # Define the solar position and clearsky dataframes + # Define the solar position and clearsky dataframe solar_position = pd.DataFrame({'apparent_zenith': [71.7303262449161, 59.369], 'zenith': [71.7764, 59.395]}, From 65fde50b9dc54847de738deea594fedd2a0df6d4 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Tue, 1 Nov 2022 09:01:56 -0400 Subject: [PATCH 33/33] undo ModelChain.complete_irradiance test changes --- pvlib/tests/test_modelchain.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pvlib/tests/test_modelchain.py b/pvlib/tests/test_modelchain.py index 3d8b055d25..62b71f2042 100644 --- a/pvlib/tests/test_modelchain.py +++ b/pvlib/tests/test_modelchain.py @@ -1886,7 +1886,7 @@ def test_complete_irradiance(sapm_dc_snl_ac_system, location): """Check calculations""" mc = ModelChain(sapm_dc_snl_ac_system, location) times = pd.date_range('2010-07-05 7:00:00-0700', periods=2, freq='H') - i = pd.DataFrame({'dni': [49.63565561689957, 62.10624908037814], + i = pd.DataFrame({'dni': [49.756966, 62.153947], 'ghi': [372.103976116, 497.087579068], 'dhi': [356.543700, 465.44400]}, index=times) @@ -1904,7 +1904,7 @@ def test_complete_irradiance(sapm_dc_snl_ac_system, location): mc.complete_irradiance(i[['dhi', 'ghi']]) assert_series_equal(mc.results.weather['dni'], - pd.Series([49.63565561689957, 62.10624908037814], + pd.Series([49.756966, 62.153947], index=times, name='dni'))