From 6cbb1aa3ba09db774a60fd03fb34d24f5d1b03ca Mon Sep 17 00:00:00 2001 From: cbcrespo Date: Tue, 11 Aug 2026 10:12:36 +0100 Subject: [PATCH 1/3] Set all IAM outputs to dict --- pvlib/iam.py | 24 ++++++++++++++---------- tests/test_iam.py | 42 ++++++++++++++++++++++-------------------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index 9ba981c5ea..32989d04d1 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -346,11 +346,11 @@ def martin_ruiz_diffuse(surface_tilt, a_r=0.16, c1=0.4244, c2=None): Returns ------- - iam_sky : numeric - The incident angle modifier for sky diffuse + iam : dict + IAM values for each type of diffuse irradiance: - iam_ground : numeric - The incident angle modifier for ground-reflected diffuse + * 'sky': radiation from the sky dome + * 'ground': radiation reflected from the ground Notes ----- @@ -419,7 +419,9 @@ def martin_ruiz_diffuse(surface_tilt, a_r=0.16, c1=0.4244, c2=None): iam_sky = pd.Series(iam_sky, index=out_index, name='iam_sky') iam_gnd = pd.Series(iam_gnd, index=out_index, name='iam_ground') - return iam_sky, iam_gnd + iam = {'sky': iam_sky, 'ground': iam_gnd} + + return iam def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): @@ -890,11 +892,11 @@ def schlick_diffuse(surface_tilt): Returns ------- - iam_sky : numeric - The incident angle modifier for sky diffuse. + iam : dict + IAM values for each type of diffuse irradiance: - iam_ground : numeric - The incident angle modifier for ground-reflected diffuse. + * 'sky': radiation from the sky dome + * 'ground': radiation reflected from the ground See Also -------- @@ -961,7 +963,9 @@ def schlick_diffuse(surface_tilt): cuk = pd.Series(cuk, surface_tilt.index) cug = pd.Series(cug, surface_tilt.index) - return cuk, cug + iam = {'sky': cuk, 'ground': cug} + + return iam def _get_model(model_name): diff --git a/tests/test_iam.py b/tests/test_iam.py index 123548cd6e..0287fd8fd2 100644 --- a/tests/test_iam.py +++ b/tests/test_iam.py @@ -134,15 +134,18 @@ def test_martin_ruiz_diffuse(): surface_tilt = 30. a_r = 0.16 - expected = (0.9549735, 0.7944426) + expected_sky = 0.9549735 + expected_ground = 0.7944426 # will fail if default values change - iam = _iam.martin_ruiz_diffuse(surface_tilt) - assert_allclose(iam, expected) + actual_iam = _iam.martin_ruiz_diffuse(surface_tilt) + assert_allclose(actual_iam['sky'], expected_sky) + assert_allclose(actual_iam['ground'], expected_ground) # will fail if parameter names change iam = _iam.martin_ruiz_diffuse(surface_tilt=surface_tilt, a_r=a_r) - assert_allclose(iam, expected) + assert_allclose(iam['sky'], expected_sky) + assert_allclose(iam['ground'], expected_ground) a_r = 0.18 surface_tilt = [0, 30, 90, 120, 180, np.nan, np.inf] @@ -153,21 +156,21 @@ def test_martin_ruiz_diffuse(): # check various inputs as list iam = _iam.martin_ruiz_diffuse(surface_tilt, a_r) - assert_allclose(iam[0], expected_sky, atol=1e-7, equal_nan=True) - assert_allclose(iam[1], expected_gnd, atol=1e-7, equal_nan=True) + assert_allclose(iam['sky'], expected_sky, atol=1e-7, equal_nan=True) + assert_allclose(iam['ground'], expected_gnd, atol=1e-7, equal_nan=True) # check various inputs as array iam = _iam.martin_ruiz_diffuse(np.array(surface_tilt), a_r) - assert_allclose(iam[0], expected_sky, atol=1e-7, equal_nan=True) - assert_allclose(iam[1], expected_gnd, atol=1e-7, equal_nan=True) + assert_allclose(iam['sky'], expected_sky, atol=1e-7, equal_nan=True) + assert_allclose(iam['ground'], expected_gnd, atol=1e-7, equal_nan=True) # check various inputs as Series surface_tilt = pd.Series(surface_tilt) expected_sky = pd.Series(expected_sky, name='iam_sky') expected_gnd = pd.Series(expected_gnd, name='iam_ground') iam = _iam.martin_ruiz_diffuse(surface_tilt, a_r) - assert_series_equal(iam[0], expected_sky) - assert_series_equal(iam[1], expected_gnd) + assert_series_equal(iam['sky'], expected_sky) + assert_series_equal(iam['ground'], expected_gnd) def test_iam_interp(): @@ -441,22 +444,21 @@ def test_schlick_diffuse(): expected_ground = np.array([0, 0.62693858, 0.93218737, 0.95238094]) # numpy arrays - actual_sky, actual_ground = _iam.schlick_diffuse(surface_tilt) - assert_allclose(expected_sky, actual_sky) - assert_allclose(expected_ground, actual_ground, rtol=1e-6) + actual_iam = _iam.schlick_diffuse(surface_tilt) + assert_allclose(expected_sky, actual_iam['sky']) + assert_allclose(expected_ground, actual_iam['ground'], rtol=1e-6) # scalars for i in range(len(surface_tilt)): - actual_sky, actual_ground = _iam.schlick_diffuse(surface_tilt[i]) - assert_allclose(expected_sky[i], actual_sky) - assert_allclose(expected_ground[i], actual_ground, rtol=1e-6) + actual_iam = _iam.schlick_diffuse(surface_tilt[i]) + assert_allclose(expected_sky[i], actual_iam['sky'], rtol=1e-6) + assert_allclose(expected_ground[i], actual_iam['ground'], rtol=1e-6) # pandas Series idx = pd.date_range('2019-01-01', freq='h', periods=len(surface_tilt)) - actual_sky, actual_ground = _iam.schlick_diffuse(pd.Series(surface_tilt, - idx)) - assert_series_equal(pd.Series(expected_sky, idx), actual_sky) - assert_series_equal(pd.Series(expected_ground, idx), actual_ground, + actual_iam = _iam.schlick_diffuse(pd.Series(surface_tilt, idx)) + assert_series_equal(pd.Series(expected_sky, idx), actual_iam['sky']) + assert_series_equal(pd.Series(expected_ground, idx), actual_iam['ground'], rtol=1e-6) From 8772a7c1c89ab6454c7da30041c3f0379d464a3c Mon Sep 17 00:00:00 2001 From: cbcrespo Date: Tue, 11 Aug 2026 10:34:58 +0100 Subject: [PATCH 2/3] Add whatsnew entry --- docs/sphinx/source/whatsnew/v0.16.0.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/sphinx/source/whatsnew/v0.16.0.rst b/docs/sphinx/source/whatsnew/v0.16.0.rst index 3ea266e6cb..78fe64be82 100644 --- a/docs/sphinx/source/whatsnew/v0.16.0.rst +++ b/docs/sphinx/source/whatsnew/v0.16.0.rst @@ -30,6 +30,10 @@ Breaking Changes * Removed the deprecated ``server`` keyword argument from :py:func:`pvlib.iotools.sodapro.get_cams`. Use ``url`` instead. (:issue:`2767`, :pull:`2766`) +* Changed the output type of :py:func:`pvlib.iam.marion_ruiz_diffuse` + and :py:func:`pvlib.iam.schlick_diffuse` from tuple to ``dict``, to be + consistent with :py:func:`pvlib.iam.marion_diffuse`. (:issue:`2837`, + :pull:`2842`) Deprecations ~~~~~~~~~~~~ From 720c8eade658826e35a4e96548660580be479ada Mon Sep 17 00:00:00 2001 From: cbcrespo Date: Tue, 11 Aug 2026 12:09:10 +0100 Subject: [PATCH 3/3] Minor change to docstrings --- pvlib/iam.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index 32989d04d1..ef9812e153 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -347,7 +347,7 @@ def martin_ruiz_diffuse(surface_tilt, a_r=0.16, c1=0.4244, c2=None): Returns ------- iam : dict - IAM values for each type of diffuse irradiance: + IAM values for each type of diffuse irradiance (assuming isotropy): * 'sky': radiation from the sky dome * 'ground': radiation reflected from the ground @@ -605,7 +605,7 @@ def marion_diffuse(model, surface_tilt, **kwargs): Returns ------- iam : dict - IAM values for each type of diffuse irradiance: + IAM values for each type of diffuse irradiance (assuming isotropy): * 'sky': radiation from the sky dome (zenith <= 90) * 'horizon': radiation from the region of the sky near the horizon @@ -893,7 +893,7 @@ def schlick_diffuse(surface_tilt): Returns ------- iam : dict - IAM values for each type of diffuse irradiance: + IAM values for each type of diffuse irradiance (assuming isotropy): * 'sky': radiation from the sky dome * 'ground': radiation reflected from the ground