From f67c3b5f77ab20fbaa46f70153151654a29a3ed6 Mon Sep 17 00:00:00 2001 From: dvezinet Date: Thu, 5 Feb 2026 22:43:11 +0000 Subject: [PATCH 1/4] [#126] Attempt at fixing evaluate_spline for scipy >= 1.16.0 --- bsplines2d/_class02_bsplines_rect.py | 86 ++++++++++++++++++---------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/bsplines2d/_class02_bsplines_rect.py b/bsplines2d/_class02_bsplines_rect.py index 3b32c09..13f07b7 100644 --- a/bsplines2d/_class02_bsplines_rect.py +++ b/bsplines2d/_class02_bsplines_rect.py @@ -8,6 +8,7 @@ # Common import numpy as np +import scipy as scp import scipy.interpolate as scpinterp @@ -16,41 +17,64 @@ from . import _class02_bsplines_operators_rect -if hasattr(scpinterp._bspl, 'evaluate_spline'): - evaluate_spline = scpinterp._bspl.evaluate_spline +if hasattr(scpinterp, '_bspl'): -else: - msg = ( - "\n\n" - "bsplines2d using a new version of scipy" - " with no scpinterp._bspl.evaluate_spline()\n" - "Instead using scpinterp._bspl.evaluate_ndspline()\n" - "Prototypal and not thoroughly tested!\n" - ) - warnings.warn(msg) + if hasattr(scpinterp._bspl, 'evaluate_spline'): + evaluate_spline = scpinterp._bspl.evaluate_spline + + else: + msg = ( + "\n\n" + "bsplines2d using a new version of scipy" + " with no scpinterp._bspl.evaluate_spline()\n" + "Instead using scpinterp._bspl.evaluate_ndspline()\n" + "Prototypal and not thoroughly tested!\n" + ) + warnings.warn(msg) + + def evaluate_spline(t, c, k, xp, nu, extrapolate, out): + ndim = 1 + c1 = c.reshape(c.shape[:ndim] + (-1,)) + num_c_tr = c1.shape[-1] + strides_c1 = [stride // c.dtype.itemsize for stride in c.strides] + indices_k1d = np.unravel_index( + np.arange((k+1)**ndim), + (k+1,)*ndim, + )[0][:, None] + return scpinterp._bspl.evaluate_ndbspline( + xp[:, None], + t[None, :], + np.array([t.size], dtype=np.int32), + np.array([k], dtype=np.int32), + np.array([nu], dtype=np.int32), + extrapolate, + c.ravel(), + num_c_tr, + np.array(strides_c1, dtype=np.intp), + indices_k1d, + out, + ) + +# Should work for scipy >= 1.16.0 +elif ( + hasattr(scpinterp, '_bsplines') + and hasattr(scpinterp._bsplines, '_dierckx') + and hasattr(scpinterp._bsplines._dierckx, 'evaluate_spline') +): def evaluate_spline(t, c, k, xp, nu, extrapolate, out): - ndim = 1 - c1 = c.reshape(c.shape[:ndim] + (-1,)) - num_c_tr = c1.shape[-1] - strides_c1 = [stride // c.dtype.itemsize for stride in c.strides] - indices_k1d = np.unravel_index( - np.arange((k+1)**ndim), - (k+1,)*ndim, - )[0][:, None] - return scpinterp._bspl.evaluate_ndbspline( - xp[:, None], - t[None, :], - np.array([t.size], dtype=np.int32), - np.array([k], dtype=np.int32), - np.array([nu], dtype=np.int32), - extrapolate, - c.ravel(), - num_c_tr, - np.array(strides_c1, dtype=np.intp), - indices_k1d, - out, + out[:, 0] = scpinterp._bsplines._dierckx.evaluate_spline( + t, # 1d contiguous array of floats + c, # 2d contiguous array of floats + k, # int + nu, # int + extrapolate, # bool ) + return + +else: + msg = f"scipy {scp.__version__} has no evaluate_spline" + raise Exception(msg) # ################################################################ From 7f7086571e6bc6e00e8aee17102b63a9c2917ba3 Mon Sep 17 00:00:00 2001 From: dvezinet Date: Fri, 6 Feb 2026 16:29:29 +0000 Subject: [PATCH 2/4] [#126] fixed for scipy 1.14.0 to 1.17.0 --- bsplines2d/_class02_bsplines_rect.py | 38 +++++++++++++++------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/bsplines2d/_class02_bsplines_rect.py b/bsplines2d/_class02_bsplines_rect.py index 13f07b7..222ba5f 100644 --- a/bsplines2d/_class02_bsplines_rect.py +++ b/bsplines2d/_class02_bsplines_rect.py @@ -17,7 +17,26 @@ from . import _class02_bsplines_operators_rect -if hasattr(scpinterp, '_bspl'): +# Should work for scipy >= 1.15.0 +# see https://github.com/ToFuProject/bsplines2d/pull/147 +if ( + hasattr(scpinterp, '_bsplines') + and hasattr(scpinterp._bsplines, '_dierckx') + and hasattr(scpinterp._bsplines._dierckx, 'evaluate_spline') +): + + def evaluate_spline(t, c, k, xp, nu, extrapolate, out): + out[...] = scpinterp._bsplines._dierckx.evaluate_spline( + t, # 1d contiguous array of floats + c, # 2d contiguous array of floats + k, # int + xp, # 1d contiguous array of floats + nu, # int + extrapolate, # bool + ) + return + +elif hasattr(scpinterp, '_bspl'): if hasattr(scpinterp._bspl, 'evaluate_spline'): evaluate_spline = scpinterp._bspl.evaluate_spline @@ -55,23 +74,6 @@ def evaluate_spline(t, c, k, xp, nu, extrapolate, out): out, ) -# Should work for scipy >= 1.16.0 -elif ( - hasattr(scpinterp, '_bsplines') - and hasattr(scpinterp._bsplines, '_dierckx') - and hasattr(scpinterp._bsplines._dierckx, 'evaluate_spline') -): - - def evaluate_spline(t, c, k, xp, nu, extrapolate, out): - out[:, 0] = scpinterp._bsplines._dierckx.evaluate_spline( - t, # 1d contiguous array of floats - c, # 2d contiguous array of floats - k, # int - nu, # int - extrapolate, # bool - ) - return - else: msg = f"scipy {scp.__version__} has no evaluate_spline" raise Exception(msg) From c053efd2c0450a04779229e80afefba073396871 Mon Sep 17 00:00:00 2001 From: dvezinet Date: Fri, 6 Feb 2026 16:30:52 +0000 Subject: [PATCH 3/4] [#126] relaxed constraint on scipy --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bfafe48..adce479 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ keywords = [ # scipy 1.15.3 and 1.16.0 have no wheel for python 3.14 requires-python = ">=3.10,<3.14" dependencies = [ - "scipy<1.16.0", # until https://github.com/ToFuProject/bsplines2d/issues/126 solved + "scipy", # see https://github.com/ToFuProject/bsplines2d/pull/147 "contourpy", 'datastock>=0.0.56', ] From cb6c723c06b8a6fb36edd5f326dd081d8499f346 Mon Sep 17 00:00:00 2001 From: dvezinet Date: Fri, 6 Feb 2026 17:01:03 +0000 Subject: [PATCH 4/4] [#126] Fixed scipy 1.15.X vs 1.16.X --- bsplines2d/_class02_bsplines_rect.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/bsplines2d/_class02_bsplines_rect.py b/bsplines2d/_class02_bsplines_rect.py index 222ba5f..d13d478 100644 --- a/bsplines2d/_class02_bsplines_rect.py +++ b/bsplines2d/_class02_bsplines_rect.py @@ -25,16 +25,19 @@ and hasattr(scpinterp._bsplines._dierckx, 'evaluate_spline') ): - def evaluate_spline(t, c, k, xp, nu, extrapolate, out): - out[...] = scpinterp._bsplines._dierckx.evaluate_spline( - t, # 1d contiguous array of floats - c, # 2d contiguous array of floats - k, # int - xp, # 1d contiguous array of floats - nu, # int - extrapolate, # bool - ) - return + if scp.__version__.startswith('1.15'): + evaluate_spline = scpinterp._bsplines._dierckx.evaluate_spline + else: + def evaluate_spline(t, c, k, xp, nu, extrapolate, out): + out[...] = scpinterp._bsplines._dierckx.evaluate_spline( + t, # 1d contiguous array of floats + c, # 2d contiguous array of floats + k, # int + xp, # 1d contiguous array of floats + nu, # int + extrapolate, # bool + ) + return elif hasattr(scpinterp, '_bspl'):