From c0b3c05db24d7adcdd169ce099a8783f518100ba Mon Sep 17 00:00:00 2001 From: Marc Anoma Date: Tue, 1 Nov 2016 14:42:54 -0700 Subject: [PATCH 1/7] Saving diffuse components into dict to be returned * dictionary returned depending on optional boolean input argument for backward compatibility --- pvlib/irradiance.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 5a397229e9..8ae52fd144 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -886,7 +886,7 @@ def king(surface_tilt, dhi, ghi, solar_zenith): def perez(surface_tilt, surface_azimuth, dhi, dni, dni_extra, solar_zenith, solar_azimuth, airmass, - model='allsitescomposite1990'): + model='allsitescomposite1990', return_components=False): ''' Determine diffuse irradiance from the sky on a tilted surface using one of the Perez models. @@ -1043,7 +1043,20 @@ def perez(surface_tilt, surface_azimuth, dhi, dni, dni_extra, else: sky_diffuse = np.where(np.isnan(airmass), 0, sky_diffuse) - return sky_diffuse + if return_components: + component_keys = ('isotropic', 'circumsolar', 'horizon') + diffuse_components = dict.fromkeys(component_keys, np.zeros(np.shape(sky_diffuse))) + + # Calculate the different components for positive values + mask_positive_values = np.where(sky_diffuse != 0) + diffuse_components['isotropic'][mask_positive_values] = (dhi * term1)[mask_positive_values] + diffuse_components['circumsolar'][mask_positive_values] = (dhi * term2)[mask_positive_values] + diffuse_components['horizon'][mask_positive_values] = (dhi * term3)[mask_positive_values] + + return sky_diffuse, diffuse_components + + else: + return sky_diffuse def disc(ghi, zenith, datetime_or_doy, pressure=101325): From a02930d7b4f287bd6ad8f69171e55c4626a05ad6 Mon Sep 17 00:00:00 2001 From: Marc Anoma Date: Tue, 1 Nov 2016 15:18:11 -0700 Subject: [PATCH 2/7] Wrote test for diffuse components * all tests are passing --- pvlib/irradiance.py | 15 +++++++++------ pvlib/test/test_irradiance.py | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 8ae52fd144..6ed74a4680 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -1045,13 +1045,16 @@ def perez(surface_tilt, surface_azimuth, dhi, dni, dni_extra, if return_components: component_keys = ('isotropic', 'circumsolar', 'horizon') - diffuse_components = dict.fromkeys(component_keys, np.zeros(np.shape(sky_diffuse))) + diffuse_components = dict.fromkeys(component_keys) - # Calculate the different components for positive values - mask_positive_values = np.where(sky_diffuse != 0) - diffuse_components['isotropic'][mask_positive_values] = (dhi * term1)[mask_positive_values] - diffuse_components['circumsolar'][mask_positive_values] = (dhi * term2)[mask_positive_values] - diffuse_components['horizon'][mask_positive_values] = (dhi * term3)[mask_positive_values] + # Calculate the different components + diffuse_components['isotropic'] = dhi * term1 + diffuse_components['circumsolar'] = dhi * term2 + diffuse_components['horizon'] = dhi * term3 + + # Set values of components to 0 when sky_diffuse is 0 + for k in diffuse_components.keys(): + diffuse_components[k][sky_diffuse == 0] = 0 return sky_diffuse, diffuse_components diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index 83750cb6e2..6f4f78936e 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -158,6 +158,20 @@ def test_perez(): assert_series_equal(out, expected, check_less_precise=2) +def test_perez_components(): + am = atmosphere.relativeairmass(ephem_data['apparent_zenith']) + dni = irrad_data['dni'].copy() + dni.iloc[2] = np.nan + out, components = irradiance.perez(40, 180, irrad_data['dhi'], dni, + dni_et, ephem_data['apparent_zenith'], + ephem_data['azimuth'], am, return_components=True) + expected = pd.Series(np.array( + [ 0. , 31.46046871, np.nan, 45.45539877]), + index=times) + sum_components = pd.Series(np.sum(components.values(), axis=0), index=times) + assert_series_equal(out, expected, check_less_precise=2) + assert_series_equal(sum_components, expected, check_less_precise=2) + @needs_numpy_1_10 def test_perez_arrays(): am = atmosphere.relativeairmass(ephem_data['apparent_zenith']) From ea3ea1df8764ff91f721453de8fbebbeb52a0fe3 Mon Sep 17 00:00:00 2001 From: Marc Anoma Date: Thu, 17 Nov 2016 11:40:15 -0800 Subject: [PATCH 3/7] Updated docstring and fixed test for Python3 --- pvlib/irradiance.py | 4 ++++ pvlib/test/test_irradiance.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 6ed74a4680..ed2ff73fa1 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -953,6 +953,10 @@ def perez(surface_tilt, surface_azimuth, dhi, dni, dni_extra, * 'capecanaveral1988' * 'albany1988' + return_components: bool (optional, default=False) + Flag used to decide whether to return the calculated diffuse components + or not. + Returns -------- sky_diffuse : numeric diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index 6f4f78936e..8b7448324e 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -168,7 +168,7 @@ def test_perez_components(): expected = pd.Series(np.array( [ 0. , 31.46046871, np.nan, 45.45539877]), index=times) - sum_components = pd.Series(np.sum(components.values(), axis=0), index=times) + sum_components = pd.Series(np.sum(list(components.values()), axis=0), index=times) assert_series_equal(out, expected, check_less_precise=2) assert_series_equal(sum_components, expected, check_less_precise=2) From 33a01416d953acbb59c8879e7266431801bd2acc Mon Sep 17 00:00:00 2001 From: Marc Anoma Date: Fri, 18 Nov 2016 09:48:11 -0800 Subject: [PATCH 4/7] Now testing each calculated component * and not just the sum of them --- pvlib/test/test_irradiance.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index 8b7448324e..3ab3ccef4a 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -168,8 +168,18 @@ def test_perez_components(): expected = pd.Series(np.array( [ 0. , 31.46046871, np.nan, 45.45539877]), index=times) + expected_components = pd.DataFrame( + { + 'circumsolar': np.array([ 0. , 0. , np.nan, 4.47966439]), + 'isotropic': np.array([ 0. , 26.84138589, np.nan, 31.72696071]), + 'horizon': np.array([ 0. , 4.62212181, np.nan, 9.25316454]) + }, + index=times + ) + df_components = pd.DataFrame(components) sum_components = pd.Series(np.sum(list(components.values()), axis=0), index=times) assert_series_equal(out, expected, check_less_precise=2) + assert_frame_equal(df_components, expected_components) assert_series_equal(sum_components, expected, check_less_precise=2) @needs_numpy_1_10 From fc5d6b10276850857d474d9223da9dab098515bf Mon Sep 17 00:00:00 2001 From: Marc Anoma Date: Fri, 18 Nov 2016 09:55:45 -0800 Subject: [PATCH 5/7] Updated whatsnew file with changes --- docs/sphinx/source/whatsnew/v0.4.2.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sphinx/source/whatsnew/v0.4.2.txt b/docs/sphinx/source/whatsnew/v0.4.2.txt index 4f46308b01..e57ddde90f 100644 --- a/docs/sphinx/source/whatsnew/v0.4.2.txt +++ b/docs/sphinx/source/whatsnew/v0.4.2.txt @@ -46,6 +46,7 @@ Enhancements separate pages for each function, class, or method. (:issue:`258`) * Improved Linke turbidity factor time interpolation with Python `calendar` month days and leap years (:issue:`265`) +* Added option to return diffuse components from Perez transposition model. Other @@ -61,3 +62,4 @@ Code Contributors * Will Holmgren * Volker Beutner * Mark Mikofski +* Marc Anoma From fb0c60a126618528d6f27648b811cd6d5171e840 Mon Sep 17 00:00:00 2001 From: Marc Anoma Date: Fri, 18 Nov 2016 15:10:27 -0800 Subject: [PATCH 6/7] Cleaning changes * Defining components as ordered dict * Treating case where inputs can be scalar --- pvlib/irradiance.py | 11 +++++++---- pvlib/test/test_irradiance.py | 6 ++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index ed2ff73fa1..b04bea0d78 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -1048,8 +1048,7 @@ def perez(surface_tilt, surface_azimuth, dhi, dni, dni_extra, sky_diffuse = np.where(np.isnan(airmass), 0, sky_diffuse) if return_components: - component_keys = ('isotropic', 'circumsolar', 'horizon') - diffuse_components = dict.fromkeys(component_keys) + diffuse_components = OrderedDict() # Calculate the different components diffuse_components['isotropic'] = dhi * term1 @@ -1057,8 +1056,12 @@ def perez(surface_tilt, surface_azimuth, dhi, dni, dni_extra, diffuse_components['horizon'] = dhi * term3 # Set values of components to 0 when sky_diffuse is 0 - for k in diffuse_components.keys(): - diffuse_components[k][sky_diffuse == 0] = 0 + mask = sky_diffuse == 0 + if isinstance(sky_diffuse, pd.Series): + diffuse_components = pd.DataFrame(diffuse_components) + diffuse_components.ix[mask] = 0 + else: + diffuse_components = {k: np.where(mask, 0, v) for k, v in diffuse_components.items()} return sky_diffuse, diffuse_components diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index 3ab3ccef4a..c58e45c0b6 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -177,9 +177,11 @@ def test_perez_components(): index=times ) df_components = pd.DataFrame(components) - sum_components = pd.Series(np.sum(list(components.values()), axis=0), index=times) + sum_components = df_components.sum(axis=1) + + columns = df_components.columns assert_series_equal(out, expected, check_less_precise=2) - assert_frame_equal(df_components, expected_components) + assert_frame_equal(df_components[columns], expected_components[columns]) assert_series_equal(sum_components, expected, check_less_precise=2) @needs_numpy_1_10 From 29da7850550ffe7d1f12ae10955b6f92096547d4 Mon Sep 17 00:00:00 2001 From: Marc Anoma Date: Mon, 21 Nov 2016 13:27:59 -0800 Subject: [PATCH 7/7] Check that component col order is correct in test --- pvlib/test/test_irradiance.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index c58e45c0b6..85f038c936 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -162,26 +162,23 @@ def test_perez_components(): am = atmosphere.relativeairmass(ephem_data['apparent_zenith']) dni = irrad_data['dni'].copy() dni.iloc[2] = np.nan - out, components = irradiance.perez(40, 180, irrad_data['dhi'], dni, + out, df_components = irradiance.perez(40, 180, irrad_data['dhi'], dni, dni_et, ephem_data['apparent_zenith'], ephem_data['azimuth'], am, return_components=True) expected = pd.Series(np.array( [ 0. , 31.46046871, np.nan, 45.45539877]), index=times) expected_components = pd.DataFrame( - { - 'circumsolar': np.array([ 0. , 0. , np.nan, 4.47966439]), - 'isotropic': np.array([ 0. , 26.84138589, np.nan, 31.72696071]), - 'horizon': np.array([ 0. , 4.62212181, np.nan, 9.25316454]) - }, + np.array([[ 0. , 26.84138589, np.nan, 31.72696071], + [ 0. , 0. , np.nan, 4.47966439], + [ 0. , 4.62212181, np.nan, 9.25316454]]).T, + columns=['isotropic', 'circumsolar', 'horizon'], index=times ) - df_components = pd.DataFrame(components) sum_components = df_components.sum(axis=1) - columns = df_components.columns assert_series_equal(out, expected, check_less_precise=2) - assert_frame_equal(df_components[columns], expected_components[columns]) + assert_frame_equal(df_components, expected_components) assert_series_equal(sum_components, expected, check_less_precise=2) @needs_numpy_1_10