From 71f79348eafa1b5f2c797713089482335f061c24 Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Thu, 23 Apr 2026 17:26:51 +0800 Subject: [PATCH 01/14] Replace interp1d #2394 --- .../plot_partial_module_shading_simple.py | 8 ++--- pvlib/iam.py | 31 ++++++++++++++++--- pvlib/spectrum/response.py | 20 ++++++------ tests/test_iam.py | 26 ++++++++++++++++ 4 files changed, 66 insertions(+), 19 deletions(-) diff --git a/docs/examples/shading/plot_partial_module_shading_simple.py b/docs/examples/shading/plot_partial_module_shading_simple.py index ce031eff10..c298c68033 100644 --- a/docs/examples/shading/plot_partial_module_shading_simple.py +++ b/docs/examples/shading/plot_partial_module_shading_simple.py @@ -38,7 +38,7 @@ from pvlib import pvsystem, singlediode import pandas as pd import numpy as np -from scipy.interpolate import interp1d +from scipy.interpolate import make_interp_spline import matplotlib.pyplot as plt from scipy.constants import e as qe, k as kB @@ -178,9 +178,9 @@ def plot_curves(dfs, labels, title): def interpolate(df, i): - """convenience wrapper around scipy.interpolate.interp1d""" - f_interp = interp1d(np.flipud(df['i']), np.flipud(df['v']), kind='linear', - fill_value='extrapolate') + """convenience wrapper around scipy.interpolate""" + f_interp = make_interp_spline(np.flipud(df['i']), np.flipud(df['v']), k=1) + return f_interp(i) diff --git a/pvlib/iam.py b/pvlib/iam.py index 161de84589..bd8483c591 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -440,7 +440,7 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): method : str, default 'linear' Specifies the interpolation method. Useful options are: 'linear', 'quadratic', 'cubic'. - See scipy.interpolate.interp1d for more options. + See scipy.interpolate for more options. normalize : boolean, default True When true, the interpolated values are divided by the interpolated @@ -470,7 +470,7 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): ''' # Contributed by Anton Driesse (@adriesse), PV Performance Labs. July, 2019 - from scipy.interpolate import interp1d + from scipy.interpolate import CubicSpline, make_interp_spline # Scipy doesn't give the clearest feedback, so check number of points here. MIN_REF_VALS = {'linear': 2, 'quadratic': 3, 'cubic': 4, 1: 2, 2: 3, 3: 4} @@ -483,10 +483,31 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): raise ValueError("Negative value(s) found in 'iam_ref'. " "This is not physically possible.") - interpolator = interp1d(theta_ref, iam_ref, kind=method, - fill_value='extrapolate') - aoi_input = aoi + theta_ref = np.asarray(theta_ref) + iam_ref = np.asarray(iam_ref) + + if method == "linear": + spline = make_interp_spline(theta_ref, iam_ref, k=1) + + def interpolator(x): + return spline(x) + + elif method == "quadratic": + spline = make_interp_spline(theta_ref, iam_ref, k=2) + + def interpolator(x): + return spline(x) + elif method == "cubic": + spline = CubicSpline(theta_ref, iam_ref, extrapolate=True) + + def interpolator(x): + return spline(x) + + else: + raise ValueError(f"Invalid interpolation method '{method}'.") + + aoi_input = aoi aoi = np.asanyarray(aoi) aoi = np.abs(aoi) iam = interpolator(aoi) diff --git a/pvlib/spectrum/response.py b/pvlib/spectrum/response.py index 4da92bb32a..9d45eb3cf1 100644 --- a/pvlib/spectrum/response.py +++ b/pvlib/spectrum/response.py @@ -6,7 +6,7 @@ import numpy as np import pandas as pd import scipy.constants -from scipy.interpolate import interp1d +from scipy.interpolate import CubicSpline _PLANCK_BY_LIGHT_SPEED_OVER_ELEMENTAL_CHARGE_BY_BILLION = ( @@ -66,16 +66,16 @@ def get_example_spectral_response(wavelength=None): if wavelength is None: resolution = 5.0 wavelength = np.arange(280, 1200 + resolution, resolution) + x = SR_DATA[0] + y = SR_DATA[1] + spline = CubicSpline( + x, y, + extrapolate=False + ) + values = spline(wavelength) + values[(wavelength < x[0]) | (wavelength > x[-1])] = 0.0 - interpolator = interp1d(SR_DATA[0], SR_DATA[1], - kind='cubic', - bounds_error=False, - fill_value=0.0, - copy=False, - assume_sorted=True) - - sr = pd.Series(data=interpolator(wavelength), index=wavelength) - + sr = pd.Series(data=values, index=wavelength) sr.index.name = 'wavelength' sr.name = 'spectral_response' diff --git a/tests/test_iam.py b/tests/test_iam.py index f5ca231bd4..42c65ae5e6 100644 --- a/tests/test_iam.py +++ b/tests/test_iam.py @@ -213,6 +213,32 @@ def test_iam_interp(): with pytest.raises(ValueError): _iam.interp(0.0, [0, 90], [1, -1]) + # check linear after updating interp1d + theta_ref = np.array([0, 60, 90]) + iam_ref = np.array([1.0, 0.8, 0.0]) + + aoi = np.array([0, 30, 60]) + iam = _iam.interp( + aoi, theta_ref, iam_ref, + method="linear", normalize=False) + expected = np.array([1.0, 0.9, 0.8]) + np.testing.assert_allclose(iam, expected) + + # check quadratic + theta_ref = np.array([0, 30, 60, 90]) + iam_ref = 1.0 - 1e-4 * theta_ref**2 + aoi = np.array([15, 45, 75]) + iam = _iam.interp( + aoi, + theta_ref, + iam_ref, + method="quadratic", + normalize=False + ) + + expected = 1.0 - 1e-4 * aoi**2 + np.testing.assert_allclose(iam, expected, rtol=1e-12) + @pytest.mark.parametrize('aoi,expected', [ (45, 0.9975036250000002), From cc6e5099893d40712586475abcee80c2408fc8fd Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Fri, 24 Apr 2026 10:24:29 +0800 Subject: [PATCH 02/14] Replace CubicSpline by make_interp_spline k=3 --- pvlib/iam.py | 4 ++-- pvlib/spectrum/response.py | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index bd8483c591..031ede6f1e 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -470,7 +470,7 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): ''' # Contributed by Anton Driesse (@adriesse), PV Performance Labs. July, 2019 - from scipy.interpolate import CubicSpline, make_interp_spline + from scipy.interpolate import make_interp_spline # Scipy doesn't give the clearest feedback, so check number of points here. MIN_REF_VALS = {'linear': 2, 'quadratic': 3, 'cubic': 4, 1: 2, 2: 3, 3: 4} @@ -499,7 +499,7 @@ def interpolator(x): return spline(x) elif method == "cubic": - spline = CubicSpline(theta_ref, iam_ref, extrapolate=True) + spline = make_interp_spline(theta_ref, iam_ref, k=3) def interpolator(x): return spline(x) diff --git a/pvlib/spectrum/response.py b/pvlib/spectrum/response.py index 9d45eb3cf1..673917be83 100644 --- a/pvlib/spectrum/response.py +++ b/pvlib/spectrum/response.py @@ -6,7 +6,7 @@ import numpy as np import pandas as pd import scipy.constants -from scipy.interpolate import CubicSpline +from scipy.interpolate import make_interp_spline _PLANCK_BY_LIGHT_SPEED_OVER_ELEMENTAL_CHARGE_BY_BILLION = ( @@ -68,10 +68,9 @@ def get_example_spectral_response(wavelength=None): wavelength = np.arange(280, 1200 + resolution, resolution) x = SR_DATA[0] y = SR_DATA[1] - spline = CubicSpline( - x, y, - extrapolate=False - ) + spline = make_interp_spline( + x, y, k=3) + values = spline(wavelength) values[(wavelength < x[0]) | (wavelength > x[-1])] = 0.0 From 0dccc708a11d1e9340120fb21d3c6d343cd94c60 Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Mon, 27 Apr 2026 11:16:15 +0800 Subject: [PATCH 03/14] clean up/ simplify/move import to top --- pvlib/iam.py | 19 ++++--------------- pvlib/spectrum/response.py | 3 +-- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index 031ede6f1e..820e15a67b 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -13,6 +13,7 @@ import functools from scipy.optimize import minimize from pvlib.tools import cosd, sind, acosd +from scipy.interpolate import make_interp_spline # a dict of required parameter names for each IAM model # keys are the function names for the IAM models @@ -469,9 +470,6 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): pvlib.iam.sapm ''' # Contributed by Anton Driesse (@adriesse), PV Performance Labs. July, 2019 - - from scipy.interpolate import make_interp_spline - # Scipy doesn't give the clearest feedback, so check number of points here. MIN_REF_VALS = {'linear': 2, 'quadratic': 3, 'cubic': 4, 1: 2, 2: 3, 3: 4} @@ -487,22 +485,13 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): iam_ref = np.asarray(iam_ref) if method == "linear": - spline = make_interp_spline(theta_ref, iam_ref, k=1) - - def interpolator(x): - return spline(x) + interpolator = make_interp_spline(theta_ref, iam_ref, k=1) elif method == "quadratic": - spline = make_interp_spline(theta_ref, iam_ref, k=2) - - def interpolator(x): - return spline(x) + interpolator = make_interp_spline(theta_ref, iam_ref, k=2) elif method == "cubic": - spline = make_interp_spline(theta_ref, iam_ref, k=3) - - def interpolator(x): - return spline(x) + interpolator = make_interp_spline(theta_ref, iam_ref, k=3) else: raise ValueError(f"Invalid interpolation method '{method}'.") diff --git a/pvlib/spectrum/response.py b/pvlib/spectrum/response.py index 673917be83..906c156ed2 100644 --- a/pvlib/spectrum/response.py +++ b/pvlib/spectrum/response.py @@ -68,8 +68,7 @@ def get_example_spectral_response(wavelength=None): wavelength = np.arange(280, 1200 + resolution, resolution) x = SR_DATA[0] y = SR_DATA[1] - spline = make_interp_spline( - x, y, k=3) + spline = make_interp_spline(x, y, k=3) values = spline(wavelength) values[(wavelength < x[0]) | (wavelength > x[-1])] = 0.0 From 894efc60555c5c0fe9f5c1a7f589b5555a204009 Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Tue, 5 May 2026 13:57:56 +0800 Subject: [PATCH 04/14] remove list input --- pvlib/iam.py | 7 ++++--- tests/test_iam.py | 20 ++++++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index 820e15a67b..ff82d6f7ae 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -470,6 +470,10 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): pvlib.iam.sapm ''' # Contributed by Anton Driesse (@adriesse), PV Performance Labs. July, 2019 + if isinstance(theta_ref, list): + raise TypeError("theta_ref cannot be a list") + if isinstance(iam_ref, list): + raise TypeError("iam_ref cannot be a list") # Scipy doesn't give the clearest feedback, so check number of points here. MIN_REF_VALS = {'linear': 2, 'quadratic': 3, 'cubic': 4, 1: 2, 2: 3, 3: 4} @@ -481,9 +485,6 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): raise ValueError("Negative value(s) found in 'iam_ref'. " "This is not physically possible.") - theta_ref = np.asarray(theta_ref) - iam_ref = np.asarray(iam_ref) - if method == "linear": interpolator = make_interp_spline(theta_ref, iam_ref, k=1) diff --git a/tests/test_iam.py b/tests/test_iam.py index 42c65ae5e6..84295d1c21 100644 --- a/tests/test_iam.py +++ b/tests/test_iam.py @@ -171,8 +171,8 @@ def test_martin_ruiz_diffuse(): def test_iam_interp(): - aoi_meas = [0.0, 45.0, 65.0, 75.0] - iam_meas = [1.0, 0.9, 0.8, 0.6] + aoi_meas = np.array([0.0, 45.0, 65.0, 75.0]) + iam_meas = np.array([1.0, 0.9, 0.8, 0.6]) # simple default linear method aoi = 55.0 @@ -200,18 +200,18 @@ def test_iam_interp(): assert_series_equal(iam, expected) # check beyond reference values - aoi = [-45, 0, 45, 85, 90, 95, 100, 105, 110] - expected = [0.9, 1.0, 0.9, 0.4, 0.3, 0.2, 0.1, 0.0, 0.0] + aoi = np.array([-45, 0, 45, 85, 90, 95, 100, 105, 110]) + expected = np.array([0.9, 1.0, 0.9, 0.4, 0.3, 0.2, 0.1, 0.0, 0.0]) iam = _iam.interp(aoi, aoi_meas, iam_meas) assert_allclose(iam, expected) # check exception clause with pytest.raises(ValueError): - _iam.interp(0.0, [0], [1]) + _iam.interp(0.0, np.array([0]), np.array([1])) # check exception clause with pytest.raises(ValueError): - _iam.interp(0.0, [0, 90], [1, -1]) + _iam.interp(0.0, np.array([0, 90]), np.array([1, -1])) # check linear after updating interp1d theta_ref = np.array([0, 60, 90]) @@ -239,6 +239,14 @@ def test_iam_interp(): expected = 1.0 - 1e-4 * aoi**2 np.testing.assert_allclose(iam, expected, rtol=1e-12) + # check exception clause - list input for theta_ref + with pytest.raises(TypeError): + _iam.interp(0.0, [0, 60, 90], np.array([1.0, 0.8, 0.0])) + + # check exception clause - list input for iam_ref + with pytest.raises(TypeError): + _iam.interp(0.0, np.array([0, 60, 90]), [1.0, 0.8, 0.0]) + @pytest.mark.parametrize('aoi,expected', [ (45, 0.9975036250000002), From feda4f0290793d06e5195aacce5d0d33c5759c3a Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Wed, 17 Jun 2026 18:50:26 +0800 Subject: [PATCH 05/14] Remove ifinstance check/Use np.interp --- .../examples/shading/plot_partial_module_shading_simple.py | 7 ++----- pvlib/iam.py | 6 +----- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/docs/examples/shading/plot_partial_module_shading_simple.py b/docs/examples/shading/plot_partial_module_shading_simple.py index c298c68033..f81bae5194 100644 --- a/docs/examples/shading/plot_partial_module_shading_simple.py +++ b/docs/examples/shading/plot_partial_module_shading_simple.py @@ -178,11 +178,8 @@ def plot_curves(dfs, labels, title): def interpolate(df, i): - """convenience wrapper around scipy.interpolate""" - f_interp = make_interp_spline(np.flipud(df['i']), np.flipud(df['v']), k=1) - - return f_interp(i) - + """convenience wrapper around numpy.interp""" + return np.interp(i,np.flipud(df['i']), np.flipud(df['v'])) def combine_series(dfs): """ diff --git a/pvlib/iam.py b/pvlib/iam.py index ff82d6f7ae..5c5b6794f7 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -470,10 +470,6 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): pvlib.iam.sapm ''' # Contributed by Anton Driesse (@adriesse), PV Performance Labs. July, 2019 - if isinstance(theta_ref, list): - raise TypeError("theta_ref cannot be a list") - if isinstance(iam_ref, list): - raise TypeError("iam_ref cannot be a list") # Scipy doesn't give the clearest feedback, so check number of points here. MIN_REF_VALS = {'linear': 2, 'quadratic': 3, 'cubic': 4, 1: 2, 2: 3, 3: 4} @@ -495,7 +491,7 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): interpolator = make_interp_spline(theta_ref, iam_ref, k=3) else: - raise ValueError(f"Invalid interpolation method '{method}'.") + raise ValueError(f"Interpolation method '{method}' is not supported in pvlib-python.") aoi_input = aoi aoi = np.asanyarray(aoi) From bf2c97c9797e9010a14adce6d63ac0d04fda6789 Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Wed, 17 Jun 2026 18:59:02 +0800 Subject: [PATCH 06/14] linting --- docs/examples/shading/plot_partial_module_shading_simple.py | 4 ++-- pvlib/iam.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/examples/shading/plot_partial_module_shading_simple.py b/docs/examples/shading/plot_partial_module_shading_simple.py index f81bae5194..40680f24b2 100644 --- a/docs/examples/shading/plot_partial_module_shading_simple.py +++ b/docs/examples/shading/plot_partial_module_shading_simple.py @@ -38,7 +38,6 @@ from pvlib import pvsystem, singlediode import pandas as pd import numpy as np -from scipy.interpolate import make_interp_spline import matplotlib.pyplot as plt from scipy.constants import e as qe, k as kB @@ -179,7 +178,8 @@ def plot_curves(dfs, labels, title): def interpolate(df, i): """convenience wrapper around numpy.interp""" - return np.interp(i,np.flipud(df['i']), np.flipud(df['v'])) + return np.interp(i, np.flipud(df['i']), np.flipud(df['v'])) + def combine_series(dfs): """ diff --git a/pvlib/iam.py b/pvlib/iam.py index 5c5b6794f7..428c1780d8 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -491,7 +491,9 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): interpolator = make_interp_spline(theta_ref, iam_ref, k=3) else: - raise ValueError(f"Interpolation method '{method}' is not supported in pvlib-python.") + raise ValueError( + f"Interpolation method '{method}' is not supported" + " in pvlib-python.") aoi_input = aoi aoi = np.asanyarray(aoi) From 43cd880b2b4df025b82fcaa8d58ed3c231da4284 Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Fri, 17 Jul 2026 12:05:59 +0800 Subject: [PATCH 07/14] Remove test to check for lists --- tests/test_iam.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/test_iam.py b/tests/test_iam.py index 84295d1c21..17f3e6f304 100644 --- a/tests/test_iam.py +++ b/tests/test_iam.py @@ -239,14 +239,6 @@ def test_iam_interp(): expected = 1.0 - 1e-4 * aoi**2 np.testing.assert_allclose(iam, expected, rtol=1e-12) - # check exception clause - list input for theta_ref - with pytest.raises(TypeError): - _iam.interp(0.0, [0, 60, 90], np.array([1.0, 0.8, 0.0])) - - # check exception clause - list input for iam_ref - with pytest.raises(TypeError): - _iam.interp(0.0, np.array([0, 60, 90]), [1.0, 0.8, 0.0]) - @pytest.mark.parametrize('aoi,expected', [ (45, 0.9975036250000002), From d142a597e1e936a88e7b6007e85ed7afbfd54a39 Mon Sep 17 00:00:00 2001 From: jason-rpkt <156782515+jason-rpkt@users.noreply.github.com> Date: Thu, 23 Jul 2026 15:03:17 +0800 Subject: [PATCH 08/14] Update pvlib/iam.py Co-authored-by: Cliff Hansen --- pvlib/iam.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index 428c1780d8..eb571c40b7 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -481,14 +481,9 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): raise ValueError("Negative value(s) found in 'iam_ref'. " "This is not physically possible.") - if method == "linear": - interpolator = make_interp_spline(theta_ref, iam_ref, k=1) - - elif method == "quadratic": - interpolator = make_interp_spline(theta_ref, iam_ref, k=2) - - elif method == "cubic": - interpolator = make_interp_spline(theta_ref, iam_ref, k=3) + kvals = {'linear': 1, 'quadratic': 2, 'cubic': 3} + if method in kvals: + interpolator = make_interp_spline(theta_ref, iam_ref, k=kvals[method]) else: raise ValueError( From 6debdcae605c371599883becca830225e3b4d0c7 Mon Sep 17 00:00:00 2001 From: jason-rpkt <156782515+jason-rpkt@users.noreply.github.com> Date: Thu, 30 Jul 2026 12:01:37 +0800 Subject: [PATCH 09/14] Update pvlib/iam.py with warn_deprecated Co-authored-by: Cliff Hansen --- pvlib/iam.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pvlib/iam.py b/pvlib/iam.py index eb571c40b7..fdeb7d4aba 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -485,6 +485,12 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): if method in kvals: interpolator = make_interp_spline(theta_ref, iam_ref, k=kvals[method]) + elif method in {'nearest', 'nearest-up', 'zero', 'slinear', 'previous', 'next'}: + msg = ( + f"Interpolation method {method} is deprecated in pvlib" + ) + warn_deprecated(since="0.15.3", removal="0.16.0", addendum=msg) + interpolator = interp1d(theta_ref, iam_ref, kind=method, fill_value='extrapolate') else: raise ValueError( f"Interpolation method '{method}' is not supported" From 7e30aa9e059dc7c3f7ba1918f903d4893dbd414c Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Thu, 30 Jul 2026 16:00:28 +0800 Subject: [PATCH 10/14] add imports for interp1d and warn_deprecate --- pvlib/iam.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index fdeb7d4aba..4933fc670a 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -13,7 +13,8 @@ import functools from scipy.optimize import minimize from pvlib.tools import cosd, sind, acosd -from scipy.interpolate import make_interp_spline +from pvlib._deprecation import warn_deprecated +from scipy.interpolate import make_interp_spline, interp1d # a dict of required parameter names for each IAM model # keys are the function names for the IAM models @@ -483,7 +484,8 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): kvals = {'linear': 1, 'quadratic': 2, 'cubic': 3} if method in kvals: - interpolator = make_interp_spline(theta_ref, iam_ref, k=kvals[method]) + interpolator = make_interp_spline( + theta_ref, iam_ref, k=kvals[method]) elif method in {'nearest', 'nearest-up', 'zero', 'slinear', 'previous', 'next'}: msg = ( From c1d24f6a1f57fb302408737c2fd02ea3e7b38e65 Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Thu, 30 Jul 2026 18:21:52 +0800 Subject: [PATCH 11/14] Add tests for invalid/deprecated interp methods --- pvlib/iam.py | 6 ++++-- tests/test_iam.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index 4933fc670a..6e8d7eb06d 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -487,12 +487,14 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): interpolator = make_interp_spline( theta_ref, iam_ref, k=kvals[method]) - elif method in {'nearest', 'nearest-up', 'zero', 'slinear', 'previous', 'next'}: + elif method in {'nearest', 'nearest-up', 'zero', + 'slinear', 'previous', 'next'}: msg = ( f"Interpolation method {method} is deprecated in pvlib" ) warn_deprecated(since="0.15.3", removal="0.16.0", addendum=msg) - interpolator = interp1d(theta_ref, iam_ref, kind=method, fill_value='extrapolate') + interpolator = interp1d(theta_ref, iam_ref, kind=method, + fill_value='extrapolate') else: raise ValueError( f"Interpolation method '{method}' is not supported" diff --git a/tests/test_iam.py b/tests/test_iam.py index 17f3e6f304..e349bb66ef 100644 --- a/tests/test_iam.py +++ b/tests/test_iam.py @@ -12,6 +12,7 @@ from numpy.testing import assert_allclose from pvlib import iam as _iam +from pvlib._deprecation import pvlibDeprecationWarning def test_ashrae(): @@ -240,6 +241,41 @@ def test_iam_interp(): np.testing.assert_allclose(iam, expected, rtol=1e-12) +@pytest.mark.parametrize( + "method", + ["nearest", "nearest-up", "zero", "slinear", "previous", "next"] +) +def test_iam_interp_deprecated_methods(method): + theta_ref = np.array([0, 60, 90]) + iam_ref = np.array([1.0, 0.8, 0.0]) + + with pytest.warns( + pvlibDeprecationWarning, + match=f"Interpolation method {method} is deprecated in pvlib" + ): + _iam.interp( + 30, + theta_ref, + iam_ref, + method=method + ) + + +def test_iam_interp_invalid_method(): + theta_ref = np.array([0, 60, 90]) + iam_ref = np.array([1.0, 0.8, 0.0]) + + with pytest.raises( + ValueError, + match="is not supported" + ): + _iam.interp( + 30, + theta_ref, + iam_ref, + method="unsupported" + ) + @pytest.mark.parametrize('aoi,expected', [ (45, 0.9975036250000002), (np.array([[-30, 30, 100, np.nan]]), From f2a168232ae401998a259e7c70bf56a5d521e79e Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Thu, 30 Jul 2026 18:28:20 +0800 Subject: [PATCH 12/14] Linting --- pvlib/iam.py | 4 ++-- tests/test_iam.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index 6e8d7eb06d..6c0f706689 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -487,13 +487,13 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): interpolator = make_interp_spline( theta_ref, iam_ref, k=kvals[method]) - elif method in {'nearest', 'nearest-up', 'zero', + elif method in {'nearest', 'nearest-up', 'zero', 'slinear', 'previous', 'next'}: msg = ( f"Interpolation method {method} is deprecated in pvlib" ) warn_deprecated(since="0.15.3", removal="0.16.0", addendum=msg) - interpolator = interp1d(theta_ref, iam_ref, kind=method, + interpolator = interp1d(theta_ref, iam_ref, kind=method, fill_value='extrapolate') else: raise ValueError( diff --git a/tests/test_iam.py b/tests/test_iam.py index e349bb66ef..123548cd6e 100644 --- a/tests/test_iam.py +++ b/tests/test_iam.py @@ -276,6 +276,7 @@ def test_iam_interp_invalid_method(): method="unsupported" ) + @pytest.mark.parametrize('aoi,expected', [ (45, 0.9975036250000002), (np.array([[-30, 30, 100, np.nan]]), From 2c0880af837222210d2a2a1c0aa5e7fefed0e322 Mon Sep 17 00:00:00 2001 From: jason-rpkt <156782515+jason-rpkt@users.noreply.github.com> Date: Fri, 31 Jul 2026 10:34:02 +0800 Subject: [PATCH 13/14] Update pvlib/iam.py Co-authored-by: Cliff Hansen --- pvlib/iam.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pvlib/iam.py b/pvlib/iam.py index 6c0f706689..a540dca0ca 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -442,7 +442,6 @@ def interp(aoi, theta_ref, iam_ref, method='linear', normalize=True): method : str, default 'linear' Specifies the interpolation method. Useful options are: 'linear', 'quadratic', 'cubic'. - See scipy.interpolate for more options. normalize : boolean, default True When true, the interpolated values are divided by the interpolated From 413a20651fb97a64f6a64adbc279e9eb6c3f8975 Mon Sep 17 00:00:00 2001 From: Jason Lun Leung Date: Fri, 31 Jul 2026 10:57:32 +0800 Subject: [PATCH 14/14] Add whatsnew for Deprecate scipy.interpolate --- docs/sphinx/source/whatsnew/v0.15.3.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/sphinx/source/whatsnew/v0.15.3.rst b/docs/sphinx/source/whatsnew/v0.15.3.rst index 23d89b06e5..d368b1cd8c 100644 --- a/docs/sphinx/source/whatsnew/v0.15.3.rst +++ b/docs/sphinx/source/whatsnew/v0.15.3.rst @@ -10,7 +10,7 @@ Breaking Changes Deprecations ~~~~~~~~~~~~ - +* Deprecate scipy.interpolate.interp1d. (:issue:`2394`, :pull:`2741`) Bug fixes ~~~~~~~~~ @@ -53,3 +53,4 @@ Contributors * Mathias Aschwanden (:ghuser:`maschwanden`) * Yonry Zhu (:ghuser:`yonryzhu`) * Darshan Gowda (:ghuser:`dgowdaan-cmyk`) +* Jason Lun Leung (:ghuser:`jason-rpkt`) \ No newline at end of file