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 diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 5a397229e9..b04bea0d78 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. @@ -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 @@ -1043,7 +1047,26 @@ 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: + diffuse_components = OrderedDict() + + # 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 + 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 + + else: + return sky_diffuse def disc(ghi, zenith, datetime_or_doy, pressure=101325): diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py index 83750cb6e2..85f038c936 100644 --- a/pvlib/test/test_irradiance.py +++ b/pvlib/test/test_irradiance.py @@ -158,6 +158,29 @@ 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, 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( + 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 + ) + sum_components = df_components.sum(axis=1) + + 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 def test_perez_arrays(): am = atmosphere.relativeairmass(ephem_data['apparent_zenith'])