Skip to content

Replace interp1d #2394#2741

Open
jason-rpkt wants to merge 4 commits intopvlib:mainfrom
jason-rpkt:replace_interp1d
Open

Replace interp1d #2394#2741
jason-rpkt wants to merge 4 commits intopvlib:mainfrom
jason-rpkt:replace_interp1d

Conversation

@jason-rpkt
Copy link
Copy Markdown
Contributor

  • Closes scipy.interpolate.interp1d is discouraged #2394
  • I am familiar with the contributing guidelines
  • I attest that all AI-generated material has been vetted for accuracy and is in compliance with the pvlib license
  • Tests added
  • Updates entries in docs/sphinx/source/reference for API changes.
  • Adds description and name entries in the appropriate "what's new" file in docs/sphinx/source/whatsnew for all changes. Includes link to the GitHub Issue with :issue:`num` or this Pull Request with :pull:`num`. Includes contributor name and/or GitHub username (link with :ghuser:`user`).
  • New code is fully documented. Includes numpydoc compliant docstrings, examples, and comments where necessary.
  • Pull request is nearly complete and ready for detailed review.
  • Maintainer: Appropriate GitHub Labels (including remote-data) and Milestone are assigned to the Pull Request and linked Issue.

The existing tests pass. I have added 2 in test_iam.py under test_iam_interp.

@jason-rpkt jason-rpkt marked this pull request as ready for review April 23, 2026 09:43
@cwhanse
Copy link
Copy Markdown
Member

cwhanse commented Apr 23, 2026

Reason for importing CubicSpline instead of using make_interp_spline(..., k=3)? The latter would clean up the case processing, I think.

@jason-rpkt
Copy link
Copy Markdown
Contributor Author

no particular reason. Just that I had seen CubicSpline first in https://docs.scipy.org/doc/scipy-1.17.0/tutorial/interpolate/1D.html#tutorial-interpolate-1dsection and in response.py it was hardcoded as cubic.

I have replaced CubicSpline by make_interp_spline with k=3. Now only importing make_interp_spline.

@kandersolar kandersolar added this to the v0.15.2 milestone Apr 24, 2026
Comment thread pvlib/spectrum/response.py Outdated
Comment thread pvlib/iam.py Outdated
Comment thread pvlib/iam.py Outdated
fill_value='extrapolate')
aoi_input = aoi
theta_ref = np.asarray(theta_ref)
iam_ref = np.asarray(iam_ref)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is np.asarray needed here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean to use np.asanyarray to keep consistency with np.asanyarray(aoi) below? Or to remove entirely?

np.asarray is to convert to numpy array but I can remove if you prefer.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the issue is that the docstrings states numeric for input parameters. pvlib means numeric as one of float, array or Series. Testing is all in one function test_iam_interp which inputs either list, float or array (but not Series).

My opinion: rewrite the test to remove inputting lists, which obviates np.asarray inside iam.interp. And add a test that inputs Series.

Copy link
Copy Markdown
Contributor Author

@jason-rpkt jason-rpkt May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi both, thanks for your comments. Not sure if I got this right, but I have rewritten the test to remove inputting lists. (And removed np.asarray in iam.interp )
I have also added a check for list inputs at the beginning of iam.interp
Let me know if this is OK.

--Looking at it again, it seems that keeping np.asarray might be "cleaner" than the latest version.

Comment thread pvlib/iam.py
return spline(x)

else:
raise ValueError(f"Invalid interpolation method '{method}'.")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is, technically, a breaking change, since the interp1d way also supported 'nearest', 'nearest-up', 'zero', 'slinear', 'previous', and 'next'. I doubt these got much use, if any. Any thoughts on how to handle that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I know how to update to support all of those.
Is it OK to update the error message?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since interp1d is legacy but not intended for removal, it is still available and we could fall back:

elif method in {'nearest', 'nearest-up', 'zero', 'slinear', 'previous', 'next'}:
    interpolator = interp1d(theta_ref, iam_ref, kind=method,
                               fill_value='extrapolate')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's reasonable, as long as we deprecate these weird methods too. If someone really wants these special interpolations, they can do it themselves and provide a pre-calculated input.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of those options really make any sense here. I would vote for dropping them immediately.

Comment thread pvlib/iam.py Outdated
spline = make_interp_spline(theta_ref, iam_ref, k=3)

def interpolator(x):
return spline(x)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can surely be simplified as @cwhanse mentioned in #2741 (comment)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simplified

Comment thread pvlib/iam.py
Specifies the interpolation method.
Useful options are: 'linear', 'quadratic', 'cubic'.
See scipy.interpolate.interp1d for more options.
See scipy.interpolate for more options.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line may need to be edited, depending on https://github.com/pvlib/pvlib-python/pull/2741/changes#r3137773820

Comment thread pvlib/iam.py
interpolator = make_interp_spline(theta_ref, iam_ref, k=3)

else:
raise ValueError(f"Invalid interpolation method '{method}'.")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise ValueError(f"Invalid interpolation method '{method}'.")
raise ValueError(f"Interpolation method '{method}' is not supported in pvlib-python.")

Comment thread pvlib/iam.py

from scipy.interpolate import interp1d

if isinstance(theta_ref, list):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We normally don't check the type of input. If a user inputs a non-allowed type e.g. a list, make_interp_spline will emit an error. That's OK.

Comment thread pvlib/iam.py
return spline(x)

else:
raise ValueError(f"Invalid interpolation method '{method}'.")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since interp1d is legacy but not intended for removal, it is still available and we could fall back:

elif method in {'nearest', 'nearest-up', 'zero', 'slinear', 'previous', 'next'}:
    interpolator = interp1d(theta_ref, iam_ref, kind=method,
                               fill_value='extrapolate')

Comment thread pvlib/iam.py
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}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could add a dictionary with names and k values, or something like that, to use below.

Comment thread pvlib/iam.py
return spline(x)

else:
raise ValueError(f"Invalid interpolation method '{method}'.")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of those options really make any sense here. I would vote for dropping them immediately.

fill_value='extrapolate')
"""convenience wrapper around scipy.interpolate"""
f_interp = make_interp_spline(np.flipud(df['i']), np.flipud(df['v']), k=1)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one where performance is likely important. Maybe check if np.interp is faster?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scipy.interpolate.interp1d is discouraged

4 participants