L i'KJddlZddlmZddlZddlmZddlmZm Z m Z m Z m Z m Z ddlmZddlmZddlmZdd lmZdd lmZdd lmZgd Zd Zd'dZdZdZGddZd'dZdZ dZ!dZ"dZ#dZ$dZ%dZ&d(dZ'dZ( d)dZ)d*ddd Z*d!Z+d"Z,d#Z-d+dd$d%Z.d&Z/y),N)prod)normalize_axis_index)get_lapack_funcs LinAlgErrorcholesky_bandedcho_solve_bandedsolve solve_banded)minimize_scalar)_dierckx) _fitpack_impl) csr_array)poch) combinations)BSplinemake_interp_splinemake_lsq_splinemake_smoothing_splinectj|tjrtjStjS)z>Return np.complex128 for complex dtypes, np.float64 otherwise.)np issubdtypecomplexfloating complex128float64dtypes a/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/scipy/interpolate/_bsplines.py _get_dtypers* }}UB../}}zzctj|}t|j}|j |d}|r.tj |j s td|S)zConvert the input into a C contiguous float array. NB: Upcasts half- and single-precision floats to double precision. F)copyz$Array must not contain infs or nans.)rascontiguousarrayrrastypeisfiniteall ValueError)x check_finitedtyps r_as_float_arrayr+s[ QA agg D E"ABKKN..0?@@ Hr c |dk(rytjtd|dzDcgc] }||||zz c}Scc}w)z Dual polynomial of the B-spline B_{j,k,t} - polynomial which is associated with B_{j,k,t}: $p_{j,k}(y) = (y - t_{j+1})(y - t_{j+2})...(y - t_{j+k})$ rr )rrrange)jktyis r _dual_polyr3*sA  Av 77E!QUO=n, ...) spline coefficients k : int B-spline degree extrapolate : bool or 'periodic', optional whether to extrapolate beyond the base interval, ``t[k] .. t[n]``, or to return nans. If True, extrapolates the first and last polynomial pieces of b-spline functions active on the base interval. If 'periodic', periodic extrapolation is used. Default is True. axis : int, optional Interpolation axis. Default is zero. Attributes ---------- t : ndarray knot vector c : ndarray spline coefficients k : int spline degree extrapolate : bool If True, extrapolates the first and last polynomial pieces of b-spline functions active on the base interval. axis : int Interpolation axis. tck : tuple A read-only equivalent of ``(self.t, self.c, self.k)`` Methods ------- __call__ basis_element derivative antiderivative integrate insert_knot construct_fast design_matrix from_power_basis Notes ----- B-spline basis elements are defined via .. math:: B_{i, 0}(x) = 1, \textrm{if $t_i \le x < t_{i+1}$, otherwise $0$,} B_{i, k}(x) = \frac{x - t_i}{t_{i+k} - t_i} B_{i, k-1}(x) + \frac{t_{i+k+1} - x}{t_{i+k+1} - t_{i+1}} B_{i+1, k-1}(x) **Implementation details** - At least ``k+1`` coefficients are required for a spline of degree `k`, so that ``n >= k+1``. Additional coefficients, ``c[j]`` with ``j > n``, are ignored. - B-spline basis elements of degree `k` form a partition of unity on the *base interval*, ``t[k] <= x <= t[n]``. Examples -------- Translating the recursive definition of B-splines into Python code, we have: >>> def B(x, k, i, t): ... if k == 0: ... return 1.0 if t[i] <= x < t[i+1] else 0.0 ... if t[i+k] == t[i]: ... c1 = 0.0 ... else: ... c1 = (x - t[i])/(t[i+k] - t[i]) * B(x, k-1, i, t) ... if t[i+k+1] == t[i+1]: ... c2 = 0.0 ... else: ... c2 = (t[i+k+1] - x)/(t[i+k+1] - t[i+1]) * B(x, k-1, i+1, t) ... return c1 + c2 >>> def bspline(x, t, c, k): ... n = len(t) - k - 1 ... assert (n >= k+1) and (len(c) >= n) ... return sum(c[i] * B(x, k, i, t) for i in range(n)) Note that this is an inefficient (if straightforward) way to evaluate B-splines --- this spline class does it in an equivalent, but much more efficient way. Here we construct a quadratic spline function on the base interval ``2 <= x <= 4`` and compare with the naive way of evaluating the spline: >>> from scipy.interpolate import BSpline >>> k = 2 >>> t = [0, 1, 2, 3, 4, 5, 6] >>> c = [-1, 2, 0, -1] >>> spl = BSpline(t, c, k) >>> spl(2.5) array(1.375) >>> bspline(2.5, t, c, k) 1.375 Note that outside of the base interval results differ. This is because `BSpline` extrapolates the first and last polynomial pieces of B-spline functions active on the base interval. >>> import matplotlib.pyplot as plt >>> import numpy as np >>> fig, ax = plt.subplots() >>> xx = np.linspace(1.5, 4.5, 50) >>> ax.plot(xx, [bspline(x, t, c ,k) for x in xx], 'r-', lw=3, label='naive') >>> ax.plot(xx, spl(xx), 'b-', lw=4, alpha=0.7, label='BSpline') >>> ax.grid(True) >>> ax.legend(loc='best') >>> plt.show() References ---------- .. [1] Tom Lyche and Knut Morken, Spline methods, http://www.uio.no/studier/emner/matnat/ifi/INF-MAT5340/v05/undervisningsmateriale/ .. [2] Carl de Boor, A practical guide to splines, Springer, 2001. cFt|tj||_t j ||_t j|t j|_ |dk(r||_ nt||_ |jjd|jz dz }t||jj}||_|dk7r&t j"|j|d|_|dkr t%d|jjdk7r t%d||jdzkrt%dd|zdzd |t j&|jdkj)r t%d t+t j,|j||dzdkr t%d t j.|jj1s t%d |jjdkr t%d |jjd|kr t%dt3|jj4}t j|j||_y)Nrperiodicrr Spline order cannot be negative.z$Knot vector must be one-dimensional.zNeed at least z knots for degree z(Knots must be in a non-decreasing order.z!Need at least two internal knots.z#Knots should not have nans or infs.z,Coefficients must be at least 1-dimensional.z0Knots, coefficients and degree are inconsistent.)super__init__operatorindexr/rasarraycr#rr0 extrapolateboolshaperndimaxismoveaxisr'diffanyr6uniquer%r&rr) selfr0rFr/rGrKndt __class__s rrBzBSpline.__init__s "A%%arzz: * $*D #K0D  FFLLOdff $q (#D$&&++6 19 [[q1DF q5?@ @ 66;;! CD D tvvz>~acAgY6HLM M GGDFFOa  $ $ &GH H ryy!A#' (1 ,@A A{{466"&&(BC C 66;;?KL L 66<<?Q OP P  %%%dffB7r cxtj|}|||c|_|_|_||_||_|S)zConstruct a spline without making checks. Accepts same parameters as the regular constructor. Input arrays `t` and `c` must of correct shape and dtype. )object__new__r0rFr/rGrK)clsr0rFr/rGrKrPs rconstruct_fastzBSpline.construct_fasts<~~c"!"Aq&  r cH|j|j|jfS)z@Equivalent to ``(self.t, self.c, self.k)`` (read-only). )r0rFr/rPs rtckz BSpline.tck svvtvvtvv%%r ct|dz }t|}tj|ddz f|z||ddzf|zf}tj|}d||<|j ||||S)atReturn a B-spline basis element ``B(x | t[0], ..., t[k+1])``. Parameters ---------- t : ndarray, shape (k+2,) internal knots extrapolate : bool or 'periodic', optional whether to extrapolate beyond the base interval, ``t[0] .. t[k+1]``, or to return nans. If 'periodic', periodic extrapolation is used. Default is True. Returns ------- basis_element : callable A callable representing a B-spline basis element for the knot vector `t`. Notes ----- The degree of the B-spline, `k`, is inferred from the length of `t` as ``len(t)-2``. The knot vector is constructed by appending and prepending ``k+1`` elements to internal knots `t`. Examples -------- Construct a cubic B-spline: >>> import numpy as np >>> from scipy.interpolate import BSpline >>> b = BSpline.basis_element([0, 1, 2, 3, 4]) >>> k = b.k >>> b.t[k:-k] array([ 0., 1., 2., 3., 4.]) >>> k 3 Construct a quadratic B-spline on ``[0, 1, 1, 2]``, and compare to its explicit form: >>> t = [0, 1, 1, 2] >>> b = BSpline.basis_element(t) >>> def f(x): ... return np.where(x < 1, x*x, (2. - x)**2) >>> import matplotlib.pyplot as plt >>> fig, ax = plt.subplots() >>> x = np.linspace(0, 2, 51) >>> ax.plot(x, b(x), 'g', lw=3) >>> ax.plot(x, f(x), 'r', lw=8, alpha=0.4) >>> ax.grid(True) >>> plt.show() r@rr ?)r6r+rr_ zeros_likerX)rWr0rGr/rFs r basis_elementzBSpline.basis_elements{r FQJ A  EE1Q46)a-QrU1WJN2 3 MM! !!!!Q;77r ct|d}t|d}|dk7r t|}|dkr td|jdk7st j |dd|ddkrtd|d t |d |zd zkrtd |d |dk(r/|j|z dz }|||||z ||||z zz}d }nF|sDt|||ks$t|||jd|z dz kDrtd |d |jd}||dzz}|t jtjjkrtj}ntj}tj|||t j ||\}} } |j#}| j$|k7r| j'|} t j(| |dzj+d|dz} | t j,|dz|z} | j#} t j,d|dz|dzz|dz|} t/|| | f|jd|jd|z dz fS)a, Returns a design matrix as a CSR format sparse array. Parameters ---------- x : array_like, shape (n,) Points to evaluate the spline at. t : array_like, shape (nt,) Sorted 1D array of knots. k : int B-spline degree. extrapolate : bool or 'periodic', optional Whether to extrapolate based on the first and last intervals or raise an error. If 'periodic', periodic extrapolation is used. Default is False. .. versionadded:: 1.10.0 Returns ------- design_matrix : `csr_array` object Sparse matrix in CSR format where each row contains all the basis elements of the input row (first row = basis elements of x[0], ..., last row = basis elements x[-1]). Examples -------- Construct a design matrix for a B-spline >>> from scipy.interpolate import make_interp_spline, BSpline >>> import numpy as np >>> x = np.linspace(0, np.pi * 2, 4) >>> y = np.sin(x) >>> k = 3 >>> bspl = make_interp_spline(x, y, k=k) >>> design_matrix = bspl.design_matrix(x, bspl.t, k) >>> design_matrix.toarray() [[1. , 0. , 0. , 0. ], [0.2962963 , 0.44444444, 0.22222222, 0.03703704], [0.03703704, 0.22222222, 0.44444444, 0.2962963 ], [0. , 0. , 0. , 1. ]] Construct a design matrix for some vector of knots >>> k = 2 >>> t = [-1, 0, 1, 2, 3, 4, 5, 6] >>> x = [1, 2, 3, 4] >>> design_matrix = BSpline.design_matrix(x, t, k).toarray() >>> design_matrix [[0.5, 0.5, 0. , 0. , 0. ], [0. , 0.5, 0.5, 0. , 0. ], [0. , 0. , 0.5, 0.5, 0. ], [0. , 0. , 0. , 0.5, 0.5]] This result is equivalent to the one created in the sparse format >>> c = np.eye(len(t) - k - 1) >>> design_matrix_gh = BSpline(t, c, k)(x) >>> np.allclose(design_matrix, design_matrix_gh, atol=1e-14) True Notes ----- .. versionadded:: 1.8.0 In each row of the design matrix all the basis elements are evaluated at the certain point (first row - x[0], ..., last row - x[-1]). `nt` is a length of the vector of knots: as far as there are `nt - k - 1` basis elements, `nt` should be not less than `2 * k + 2` to have at least `k + 1` basis element. Out of bounds `x` raises a ValueError. Tr>rr?r Nr]z2Expect t to be a 1-D sorted array_like, but got t=.r@zLength t is not enough for k=FOut of bounds w/ x = rrI)r+rHr'rJrrNr6sizeminmaxrIiinfoint32int64r data_matrix ones_likeravelrr$repeatreshapearanger) rWr(r0r/rGrQnnz int_dtypedataoffsets_indicesindptrs r design_matrixzBSpline.design_matrixRsX At $ At $ * ${+K q5?@ @ 66Q;"&&123B0 &&'S+, , q6AEAI A+=)> >4QCq9: : GGAJ1q5k "((#'' 'II$//1aa+Vgqzz| ==I %nnY/G))GQqS)11"ac:BIIac;;--/1q1uQ/QiH 7F #771:qwwqzA~12  r c2| |j}tj|}|j|j}}tj |j tj}|dk(r|jj|jz dz }|j|j||j|jz |j||j|jz zz}d}|j|jjjdk(}|rb|jjt }|jjdk(r6|j#|jjdd}n |j}|j#|jdd }t%j&|j||j|||} |r| jt(} | j#||jjddz} |j*dk7rZt-t/| j} | |||j*z| d|z| ||j*zdz} | j1| } | S) a Evaluate a spline function. Parameters ---------- x : array_like points to evaluate the spline at. nu : int, optional derivative to evaluate (default is 0). extrapolate : bool or 'periodic', optional whether to extrapolate based on the first and last intervals or return nans. If 'periodic', periodic extrapolation is used. Default is `self.extrapolate`. Returns ------- y : array_like Shape is determined by replacing the interpolation axis in the coefficient array with the shape of `x`. Nrr>r FrFrr@r])rGrrErIrJr#rnrr0rfr/_ensure_c_contiguousrFrkindviewfloatrpr evaluate_splinecomplexrKr5r- transpose) rPr(nurGx_shapex_ndimrQ is_complexccoutls r__call__zBSpline.__call__s,  **K JJqM''166  "** = * $ dff$q(Atvv!dffTVVn"4TVVDFF^9S!TTAK !!#VV\\&&#- U#Bvv{{aZZ Q3BZZ R (&&tvvr4661b+N ((7#Ckk'DFFLL$445 99>U388_%A& )*QwZ7!F499Fr)rFr"r6r0rr_rrIr splantiderr/rGrXrK)rPrrFrr[rGs rantiderivativezBSpline.antiderivativeDs2 FFKKM [3q6 ! 6a2%!''!"+"5667A&&466':B?   z )K**K"t""C[(, 3 3r c| |j}|jd}||kr||}}d}|jj|jz dz }|dk7r|st ||j|j}t ||j|}|jjdk(r9tj|||j}tj||zS|j}t|jt|z }|dkDr9tj|tj |f|j"ddzf}tj$|j||jfd\} } } |dk(rd|j|j|j|} } | | z }||z }t'||\}}|dkDrotj| | gtj(}t+j,| | j/| j"dd| |dd}|d|dz }||z}nMtj dt1|jj"ddf|jj2}| || z |zz}||z}|| krntj||gtj(}t+j,| | j/| j"dd| |dd}||d|dz z }nHtj|| gtj(}t+j,| | j/| j"dd| |dd}||d|dz z }tj| | |z| z gtj(}t+j,| | j/| j"dd| |dd}||d|dz z }nitj||gtj(}t+j,| | j/| j"dd| |d|}|d|dz }||z}|j/| j"ddS)aCompute a definite integral of the spline. Parameters ---------- a : float Lower limit of integration. b : float Upper limit of integration. extrapolate : bool or 'periodic', optional whether to extrapolate beyond the base interval, ``t[k] .. t[-k-1]``, or take the spline to be zero outside of the base interval. If 'periodic', periodic extrapolation is used. If None (default), use `self.extrapolate`. Returns ------- I : array_like Definite integral of the spline over the interval ``[a, b]``. Examples -------- Construct the linear spline ``x if x < 1 else 2 - x`` on the base interval :math:`[0, 2]`, and integrate it >>> from scipy.interpolate import BSpline >>> b = BSpline.basis_element([0, 1, 2]) >>> b.integrate(0, 1) array(0.5) If the integration limits are outside of the base interval, the result is controlled by the `extrapolate` parameter >>> b.integrate(-1, 1) array(0.0) >>> b.integrate(-1, 1, extrapolate=False) array(0.5) >>> import matplotlib.pyplot as plt >>> fig, ax = plt.subplots() >>> ax.grid(True) >>> ax.axvline(0, c='r', lw=5, alpha=0.5) # base interval >>> ax.axvline(2, c='r', lw=5, alpha=0.5) >>> xx = [-1, 1, 2] >>> ax.plot(xx, b(xx)) >>> plt.show() Nr r]r>rrF)rGr{r0rfr/rhrgrFrJrsplintr[rrEr6r_rrIrdivmodrr rrprr)rPabrGsignrQintegralrFrtacakatsteperiodinterval n_periodsleftr(rs r integratezBSpline.integratels`  **K !!# q5aqAD FFKK$&& 1 $ * $[Atvvdff~&AAtvvay!Avv{{a)//1dhh?zz(T/22 FF [3q6 ! 6a2%!''!"+"5667A"--tvvq$&&.A1E B * $VVDFF^TVVAYB"WF1uH$Xv6OIt1}JJBxrzz:..r2::bhhqk23N&(!Q7q6CF?I%88QTVV\\!"-=(>$?*.&&,,8a"f&&ADABwJJ1vRZZ8..r2::bhhqk23N&(!Q7CFSVO+JJ2wbjj9..r2::bhhqk23N&(!Q7CFSVO+JJBFRK0 C..r2::bhhqk23N&(!Q7CFSVO+ Aq64A**2rzz"((1+r/J"$aK9C1vAHD --r c ddlm}t||stdt |d|j }|j }|j jddz }|jd}|dk(r t||}n7|dk(s|dk(r t||}n |d k(r t||}ntd ||jd||zdzz } tj|| z|j j } t|dzD]} t|d z D]R} | | xxt!|dz| || | fztj"d || z zt%| ||| | |zz cc<Tt|d z || zD]X} | | xxt!|dz| || |d z fztj"d || z zt%| |||d z | |zz cc<Z|j'|| ||j(|j*S)a Construct a polynomial in the B-spline basis from a piecewise polynomial in the power basis. For now, accepts ``CubicSpline`` instances only. Parameters ---------- pp : CubicSpline A piecewise polynomial in the power basis, as created by ``CubicSpline`` bc_type : string, optional Boundary condition type as in ``CubicSpline``: one of the ``not-a-knot``, ``natural``, ``clamped``, or ``periodic``. Necessary for construction an instance of ``BSpline`` class. Default is ``not-a-knot``. Returns ------- b : `BSpline` object A new instance representing the initial polynomial in the B-spline basis. Notes ----- .. versionadded:: 1.8.0 Accepts only ``CubicSpline`` instances for now. The algorithm follows from differentiation the Marsden's identity [1]: each of coefficients of spline interpolation function in the B-spline basis is computed as follows: .. math:: c_j = \sum_{m=0}^{k} \frac{(k-m)!}{k!} c_{m,i} (-1)^{k-m} D^m p_{j,k}(x_i) :math:`c_{m, i}` - a coefficient of CubicSpline, :math:`D^m p_{j, k}(x_i)` - an m-th defivative of a dual polynomial in :math:`x_i`. ``k`` always equals 3 for now. First ``n - 2`` coefficients are computed in :math:`x_i = x_j`, e.g. .. math:: c_1 = \sum_{m=0}^{k} \frac{(k-1)!}{k!} c_{m,1} D^m p_{j,3}(x_1) Last ``nod + 2`` coefficients are computed in ``x[-2]``, ``nod`` - number of derivatives at the ends. For example, consider :math:`x = [0, 1, 2, 3, 4]`, :math:`y = [1, 1, 1, 1, 1]` and bc_type = ``natural`` The coefficients of CubicSpline in the power basis: :math:`[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 1, 1, 1, 1]]` The knot vector: :math:`t = [0, 0, 0, 0, 1, 2, 3, 4, 4, 4, 4]` In this case .. math:: c_j = \frac{0!}{k!} c_{3, i} k! = c_{3, i} = 1,~j = 0, ..., 6 References ---------- .. [1] Tom Lyche and Knut Morken, Spline Methods, 2005, Section 3.1.2 r ) CubicSplinez3Only CubicSpline objects are accepted for now. Got z instead.r not-a-knotnaturalclampedr>Unknown boundary condition: rr@r])_cubicr isinstanceNotImplementedErrortyper(rFrI _not_a_knot_augknt_periodic_knots TypeErrorrrrr-rpowerr;rXrGrK)rWppbc_typerr(coefr/rQr0nodrFmr2r.s rfrom_power_basiszBSpline.from_power_basiss(X ("k*%)66:2hZy'JK K DDtt DDJJqMA  GGAJ l "Aq!A  !W %91 A  "1%A:7)DE EggajAEAI& HHQWBDDJJ /q1u @A1q5\ <!QUQB$q!t*4((2q1u-.)!Q!a;<< <1q5!c'* @!QUQB$q!a%x.8((2q1u-.)!Q!a%!Q?@@ @  @!!!Q2>>277CCr c ||j|jks ||j|j dz kDrtd|d|dkrtd|d|jj}|jj}t |D]+}t ||||j|jdk(\}}-|j|||j|j|jS)aJInsert a new knot at `x` of multiplicity `m`. Given the knots and coefficients of a B-spline representation, create a new B-spline with a knot inserted `m` times at point `x`. Parameters ---------- x : float The position of the new knot m : int, optional The number of times to insert the given knot (its multiplicity). Default is 1. Returns ------- spl : `BSpline` object A new `BSpline` object with the new knot inserted. Notes ----- Based on algorithms from [1]_ and [2]_. In case of a periodic spline (``self.extrapolate == "periodic"``) there must be either at least k interior knots t(j) satisfying ``t(k+1)>> import numpy as np >>> from scipy.interpolate import BSpline, make_interp_spline >>> x = np.linspace(0, 10, 5) >>> y = np.sin(x) >>> spl = make_interp_spline(x, y, k=3) >>> spl.t array([ 0., 0., 0., 0., 5., 10., 10., 10., 10.]) Insert a single knot >>> spl_1 = spl.insert_knot(3) >>> spl_1.t array([ 0., 0., 0., 0., 3., 5., 10., 10., 10., 10.]) Insert a multiple knot >>> spl_2 = spl.insert_knot(8, m=3) >>> spl_2.t array([ 0., 0., 0., 0., 5., 8., 8., 8., 10., 10., 10., 10.]) r zCannot insert a knot at rcrz`m` must be positive, got m = r>) r0r/r'r"rFr-_insertrGrXrK)rPr(rttrrvs r insert_knotzBSpline.insert_knotYsJ tvvdff~ TVVTVVGAI%6!67s!<= = 6>!qAB B VV[[] VV[[]q PAQB0@0@J0NOFB P""2r46643C3CTYYOOr )Tr)TFrN)r N)r)__name__ __module__ __qualname____doc__rB classmethodrXpropertyr[raryrr{rrrrr __classcell__)rSs@rrrEsIV,8\  && =8=8~D D LBH #38&3P@.DhDhDTOPr rctj||t||d}|dkrtd|d|||||zdzk(r|dz}|r1|dzd|zkr&|dz|jdd|zz k\r tdt j |d|dz|||dzdf}|jddzf|jddz}t j||j }||dd f||dzdd f<t|||z d D]<} ||| z || |zdz|| z z } | || d fzd | z || dz d fzz|| d f<>|d||z dzd f|d||z dzd f<|r|jd} | |z dz } | d|zz dz } || ||z }|| |z k\r!|| |z | |z |d||| | |zd f|d|d f<|d|zdz kr*||dz|dz|z|z|| |z d|d|d f|| | |zd f<||fS) zInsert a single knot at `xval`.FrzCannot insert the knot at rcr r@zNot enough internal knots.Nr.r]r^) r find_intervalr~r'rIrr_rrr-)xvalr0rFr/r>rrnewshaperr2facrQnkn2kTs rrrs$%%aE$KEBH!|5dV1=>> {a1 q())A  qLAaC hlaggaj1Q36F&F9: : q(1*~tQxz{^3 4B Q 17712;.H (!'' *BXY^,Bxz{C 8XaZ ,<be|1Q3q5 BqE 121c6]b3h!A#s( %;;1c6 < !(Q,q.#!56B1 Q HHQK UQY!A#gk rFRUN rAv Qr]Q&BrFSq[#-.Brr3wK qs1u !A#ac!e}q(BqstH#%bqb#g;Bs37{C r6Mr ctj|}|dzdk(r|dzdz}|j}n|dz}|dd|ddzdz }||| }tj|df|dzz||df|dzzf}|S)a^Given data x, construct the knot vector w/ not-a-knot BC. cf de Boor, XIII(12). For even k, it's a bit ad hoc: Greville sites + omit 2nd and 2nd-to-last data points, a la not-a-knot. This seems to match what Dierckx does, too: https://github.com/scipy/scipy/blob/maintenance/1.11.x/scipy/interpolate/fitpack/fpcurf.f#L63-L80 r@r Nr]r)rrEr"r_)r(r/k2r0s rrrs 1 A1uz!e\ FFH !V qrUQsV^q  "bS A qtgqsmQ2!A#./A Hr cJtj|df|z||df|zfS)zBConstruct a knot vector appropriate for the order-k interpolation.rr])rr_)r(r/s rrr s, 55!A$A"xz) **r ct|trL|dk(rdtj|fg}|S|dk(rdtj|fg}|St d||S)Nrr rr@zUnknown boundary condition : )rstrrrr')deriv target_shapes r_convert_string_aliasesrsr% I ,/01E L i ,/01E LAb"Xq!$A Ab1f A Hr ctj|}t|}|dzdk(r)tj|}|ddxxx|dddz zccctj|}tj|d|zz}|||| t d|D]B}|||z |||dz z dz z |||z dz <|| |zdz |||dz zz|| |z<D|S)z+ returns vector of nodes on circle r@rr r]N)rr"r6rMrr-)r(r/xcrQdxr0r2s rrr~s B BA1uz WWR[ 1b RWq[ B QUAAa!H 1a[4Qx"qAE{^a%7"88!a%!) qb1fqjMBqAE{O31"q& 4 Hr c ttj|||f\}}}|j}tj||zdz ||zdz f}t |dz D]o}t j|||d||dz}||d|dzfxx|z cc<t j|||d||zdz |dzdd}||| dfxx|zcc<qt |D]X}||}|||k(r|} ntj||dz } t j|||| }||||zdz | |z | dzf<Ztjdg|dz z|f} t|| } | S)a0 Returns a solution of a system for B-spline interpolation with periodic boundary conditions. First ``k - 1`` rows of matrix are conditions of periodicity (continuity of ``k - 1`` derivatives at the boundary points). Last ``n`` rows are interpolation conditions. RHS is ``k - 1`` zeros and ``n`` ordinates in this case. Parameters ---------- x : 1-D array, shape (n,) Values of x - coordinate of a given set of points. y : 1-D array, shape (n,) Values of y - coordinate of a given set of points. t : 1-D array, shape(n+2*k,) Vector of knots. k : int The maximum degree of spline Returns ------- c : 1-D array, shape (n+k-1,) B-spline coefficients Notes ----- ``t`` is supposed to be taken on circle. r rNr]) maprrErfrr-r evaluate_all_bspl searchsortedr_r ) r(r1r0r/rQmatrr2bbrrrrFs r_make_interp_per_full_matrrs<"**q!Qi(GAq! A 88QUQYA * +D1q5\  ' '1adAq1u = Q!a%ZB  ' '1aeQUQYA Fs K QV  1X ,t 1Q4<D??1d+a/D ' '1dD 9)+QUQYQtAv %& , qcQUmQA dAA Hr c tj||t||d}t|jdD]Q} || } tj ||||| } t|dzD] } ||z | z} | | |||z|z| z| z | f<"Sy)a" Fill in the entries of the colocation matrix corresponding to known derivatives at `xval`. The colocation matrix is in the banded storage, as prepared by _coloc. No error checking. Parameters ---------- t : ndarray, shape (nt + k + 1,) knots k : integer B-spline order xval : float The value at which to evaluate the derivatives at. ab : ndarray, shape(2*kl + ku + 1, nt), Fortran order B-spline colocation matrix. This argument is modified *in-place*. kl : integer Number of lower diagonals of ab. ku : integer Number of upper diagonals of ab. deriv_ords : 1D ndarray Orders of derivatives known at xval offset : integer, optional Skip this many rows of the matrix ab. Frr N)r rr~r-rIr)r0r/rabklku deriv_ordsoffsetrrowrwrkrclmns r_handle_lhs_derivativesrs:  ! !!Qd Q >DZ%%a()= _((AtT2>qs =A!8arr@Frorderr])r/)rIrrprrr-rr#rrXr6rrr`r _colocrdiagr concatenate)r(r1r0r/rKrQextradimy_newrFr2ntkulrrrrrs r_make_periodic_splinersP  AAGGABK H IIa "E !a%!)X&'A Avx GA0E!Q$KAFAadG G  AEAI} t$j'|| |Sx}}t j<d#|z|zdz|ftj@d$%}tCjD|||jF| | dkDrtI||d|||| |dkDrtI||d||||||z &tK|jdd}t jL||f|j"}| dkDr| jOd||d| |jOd||| ||z |dkDr|jOd||||z d|rtQtjR||f\}}tUd'||f\}|||||d(d()\}}} }|dkDr tWd*|dkrtd+| d,t j| jO|f|jddz} t$j'|| |S#t$r} td|| d} ~ wwxYw)-a?Create an interpolating B-spline with specified degree and boundary conditions. Parameters ---------- x : array_like, shape (n,) Abscissas. y : array_like, shape (n, ...) Ordinates. k : int, optional B-spline degree. Default is cubic, ``k = 3``. t : array_like, shape (nt + k + 1,), optional. Knots. The number of knots needs to agree with the number of data points and the number of derivatives at the edges. Specifically, ``nt - n`` must equal ``len(deriv_l) + len(deriv_r)``. bc_type : 2-tuple or None Boundary conditions. Default is None, which means choosing the boundary conditions automatically. Otherwise, it must be a length-two tuple where the first element (``deriv_l``) sets the boundary conditions at ``x[0]`` and the second element (``deriv_r``) sets the boundary conditions at ``x[-1]``. Each of these must be an iterable of pairs ``(order, value)`` which gives the values of derivatives of specified orders at the given edge of the interpolation interval. Alternatively, the following string aliases are recognized: * ``"clamped"``: The first derivatives at the ends are zero. This is equivalent to ``bc_type=([(1, 0.0)], [(1, 0.0)])``. * ``"natural"``: The second derivatives at ends are zero. This is equivalent to ``bc_type=([(2, 0.0)], [(2, 0.0)])``. * ``"not-a-knot"`` (default): The first and second segments are the same polynomial. This is equivalent to having ``bc_type=None``. * ``"periodic"``: The values and the first ``k-1`` derivatives at the ends are equivalent. axis : int, optional Interpolation axis. Default is 0. check_finite : bool, optional Whether to check that the input arrays contain only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Default is True. Returns ------- b : `BSpline` object A `BSpline` object of the degree ``k`` and with knots ``t``. See Also -------- BSpline : base class representing the B-spline objects CubicSpline : a cubic spline in the polynomial basis make_lsq_spline : a similar factory function for spline fitting UnivariateSpline : a wrapper over FITPACK spline fitting routines splrep : a wrapper over FITPACK spline fitting routines Examples -------- Use cubic interpolation on Chebyshev nodes: >>> import numpy as np >>> import matplotlib.pyplot as plt >>> def cheb_nodes(N): ... jj = 2.*np.arange(N) + 1 ... x = np.cos(np.pi * jj / 2 / N)[::-1] ... return x >>> x = cheb_nodes(20) >>> y = np.sqrt(1 - x**2) >>> from scipy.interpolate import BSpline, make_interp_spline >>> b = make_interp_spline(x, y) >>> np.allclose(b(x), y) True Note that the default is a cubic spline with a not-a-knot boundary condition >>> b.k 3 Here we use a 'natural' spline, with zero 2nd derivatives at edges: >>> l, r = [(2, 0.0)], [(2, 0.0)] >>> b_n = make_interp_spline(x, y, bc_type=(l, r)) # or, bc_type="natural" >>> np.allclose(b_n(x), y) True >>> x0, x1 = x[0], x[-1] >>> np.allclose([b_n(x0, 2), b_n(x1, 2)], [0, 0]) True Interpolation of parametric curves is also supported. As an example, we compute a discretization of a snail curve in polar coordinates >>> phi = np.linspace(0, 2.*np.pi, 40) >>> r = 0.3 + np.cos(phi) >>> x, y = r*np.cos(phi), r*np.sin(phi) # convert to Cartesian coordinates Build an interpolating curve, parameterizing it by the angle >>> spl = make_interp_spline(phi, np.c_[x, y]) Evaluate the interpolant on a finer grid (note that we transpose the result to unpack it into a pair of x- and y-arrays) >>> phi_new = np.linspace(0, 2.*np.pi, 100) >>> x_new, y_new = spl(phi_new).T Plot the result >>> plt.plot(x, y, 'o') >>> plt.plot(x_new, y_new, '-') >>> plt.show() Build a B-spline curve with 2 dimensional y >>> x = np.linspace(0, 2*np.pi, 10) >>> y = np.array([np.sin(x), np.cos(x)]) Periodic condition is satisfied because y coordinates of points on the ends are equivalent >>> ax = plt.axes(projection='3d') >>> xx = np.linspace(0, 2*np.pi, 100) >>> bspl = make_interp_spline(x, y, k=5, bc_type='periodic', axis=1) >>> ax.plot3D(xx, *bspl(xx)) >>> ax.scatter3D(x, *y, color='red') >>> plt.show() Nrr>NNrrr]gV瞯<)atolzAFirst and last points does not match while periodic case expected Shapes of x  and y  are incompatibler zExpect x to not have duplicates1Expect x to be a 1D strictly increasing sequence.c3$K|]}|du ywr).0rvs r z%make_interp_spline..s<q}K|]}d|cxkxrkncywrrrr2r/s rrz%make_interp_spline..71qqA{{{1zBad boundary conditions at c3>K|]}d|cxkxrkncywrrrs rrz%make_interp_spline..:rr zAThe number of derivatives at boundaries does not match: expected z, got +r@rr)r)gbsvT) overwrite_ab overwrite_bzColocation matrix is singular.zillegal value in z-th argument of internal gbsv),rrrr'rrErrJr+rLallcloserfrIrNr_r#rrrrXrCrDrrrrrrrr&rr~rr rrrremptyrprasarray_chkfiniterr)r(r1r/r0rrKr)deriv_lderiv_rrrF deriv_l_ords deriv_l_valsnleft deriv_r_ords deriv_r_valsnrightrQr rrrr rhsr#lupivinfos ` rrrYsJ'\1W 5J% GS !"G N& GW 1 A aff -D<(A<(A AtQA*R[[1qu5%I23 3vv<yy@QRSS vvaeq"vo:;;vv{bffQqrUQsV^,LMM Av %%aAD%99 Av!)GOOP P EE!A$1R5. ! JJqM  *QWW*= >%%aAD%99qA*!#-. .  y ?w*$#Aq)1%1 A<(A1u122vv{bffQqrUQsV^,BCCvv Q4x'=affqj1n=MQOPP !qt 2A201566*$Q1a66&gqwwqr{;G!4W!=L,   q !E%gqwwqr{;G!4W!=L,    "F 1L1 16qtfA>?? 1L1 16qugQ?@@ A !aB Av,,.qD6waxIJ J vv{ HHbUQWWQR[( 6%%aAD%99 KB 1R4"9q="%RZZs CB OOAq!RTT5) qy1adBB E z1aeRR')&y 2AGGABK H ((B> 1C qy"**2x8FU YYr84Cb6k z(00X>BKLb**RI6C YS 2EDBB)-4ABQ ax:;; ,dUG3PQRR QYYuqwwqr{':;jA||||S)aCreate a smoothing B-spline satisfying the Least SQuares (LSQ) criterion. The result is a linear combination .. math:: S(x) = \sum_j c_j B_j(x; t) of the B-spline basis elements, :math:`B_j(x; t)`, which minimizes .. math:: \sum_{j} \left( w_j \times (S(x_j) - y_j) \right)^2 Parameters ---------- x : array_like, shape (m,) Abscissas. y : array_like, shape (m, ...) Ordinates. t : array_like, shape (n + k + 1,). Knots. Knots and data points must satisfy Schoenberg-Whitney conditions. k : int, optional B-spline degree. Default is cubic, ``k = 3``. w : array_like, shape (m,), optional Weights for spline fitting. Must be positive. If ``None``, then weights are all equal. Default is ``None``. axis : int, optional Interpolation axis. Default is zero. check_finite : bool, optional Whether to check that the input arrays contain only finite numbers. Disabling may give a performance gain, but may result in problems (crashes, non-termination) if the inputs do contain infinities or NaNs. Default is True. method : str, optional Method for solving the linear LSQ problem. Allowed values are "norm-eq" (Explicitly construct and solve the normal system of equations), and "qr" (Use the QR factorization of the design matrix). Default is "qr". Returns ------- b : `BSpline` object A `BSpline` object of the degree ``k`` with knots ``t``. See Also -------- BSpline : base class representing the B-spline objects make_interp_spline : a similar factory function for interpolating splines LSQUnivariateSpline : a FITPACK-based spline fitting routine splrep : a FITPACK-based fitting routine Notes ----- The number of data points must be larger than the spline degree ``k``. Knots ``t`` must satisfy the Schoenberg-Whitney conditions, i.e., there must be a subset of data points ``x[j]`` such that ``t[j] < x[j] < t[j+k+1]``, for ``j=0, 1,...,n-k-2``. Examples -------- Generate some noisy data: >>> import numpy as np >>> import matplotlib.pyplot as plt >>> rng = np.random.default_rng() >>> x = np.linspace(-3, 3, 50) >>> y = np.exp(-x**2) + 0.1 * rng.standard_normal(50) Now fit a smoothing cubic spline with a pre-defined internal knots. Here we make the knot vector (k+1)-regular by adding boundary knots: >>> from scipy.interpolate import make_lsq_spline, BSpline >>> t = [-1, 0, 1] >>> k = 3 >>> t = np.r_[(x[0],)*(k+1), ... t, ... (x[-1],)*(k+1)] >>> spl = make_lsq_spline(x, y, t, k) For comparison, we also construct an interpolating spline for the same set of data: >>> from scipy.interpolate import make_interp_spline >>> spl_i = make_interp_spline(x, y) Plot both: >>> xs = np.linspace(-3, 3, 100) >>> plt.plot(x, y, 'ro', ms=5) >>> plt.plot(xs, spl(xs), 'g-', lw=3, label='LSQ spline') >>> plt.plot(xs, spl_i(xs), 'b-', lw=3, alpha=0.7, label='interp spline') >>> plt.legend(loc='best') >>> plt.show() **NaN handling**: If the input arrays contain ``nan`` values, the result is not useful since the underlying spline fitting routines cannot deal with ``nan``. A workaround is to use zero weights for not-a-number data points: >>> y[8] = np.nan >>> w = np.isnan(y) >>> y[w] = 0. >>> tck = make_lsq_spline(x, y, t, w=~w) Notice the need to replace a ``nan`` by a numerical value (precise value does not matter as long as the corresponding weight is zero.) NrC)rr zExpect x to be a 1-D sequence.zNeed more x points.rr]z1Expect t to be a 1D strictly increasing sequence.rrrrdrcz and w znorm-eqrr5z,Expect x to be a 1D non-decreasing sequence.rFr@Trrr)r$lowerr))r%r)zUnknown method =r)!r+rrmrCrDrrJrLrrr"r'rIrNrfrr|r}r~rprrrr _norm_eq_lsqrrrr _lsq_solve_qrr#rrX)r(r1r0r/wrKr)r6rQ was_complexyyr r9rr1 cho_decomprrFrvs rrrns` <(A<(A<(A} A| , LLOqA aff -D AtQA 77   FFF vv{9::wwqzAaC.//1u122vv{bffQqrUQsV^a/0LMMvv<yy@QRSS1uQqTa!QB%i0101566vv<yy@QRSS rvvaeafn&9:LMM ~#aeafnq01GHH  QA77<<3&K Bqvv{ ZZ A &BHHQRL!H B !B77<<3&K Bqvv{ ZZ A &BHHQRL!H B !B  XXqsAhbjj <hh8}BJJ7aA  ddC ) ((7#Ckk1$,-%Rd%2>@ IIaL j%0#++a2DRV*6 88? 8J 42q!Q/1a wA,F:Q/00 1$$%A QA  ! !!Q ! 55r c|jdk(sJ||dddfz}tj||||\}}}tj||||tj|||} ||| fS)zSolve for the LSQ spline coeffs given x, y and knots. `y` is always 2D: for 1D data, the shape is ``(m, 1)``. `w` is always 1D: one weight value per `x` value. r@N)rJr rl qr_reducefpback) r(r1r0r/r<y_wrrncrFs rr;r;Css 66Q;; a4j.C((Aq!4MAvr q&"c*2s#A c19r c ` d}d fd}|jd}||||}||||}|jdk(rFt|d|fd|||||f} | jr | jSt d| j |jd k(rtj|jd} t|jdD]R} t|d|fd|||||d d | ff} | jr| j| | <.compute_banded_symmetric_XT_W_Y{s6ggaj A! q -A 1q56 Naaj (N AwQw 1QUV9 ,  - GGAJhh1vq DA3qsA;' D#&qQx#dqsdAEk2B'B#CQBqD!a%K  D D r c fd}t|}tddD]"}|| |dz dfxx|dd| dzfzcc<$d|ddzz }|dxx|dzcc<|jdtjdf }tdz ddD]0}tt d |z dz ddD]}||||||2d gz|d <|S) a! Inverse 3 central bands of matrix :math:`A=U^T D^{-1} U` assuming that ``U`` is a unit upper triangular banded matrix using an algorithm proposed in [1]. Parameters ---------- A : array, shape (4, n) Matrix to inverse, stored in LAPACK banded storage. Returns ------- B : array, shape (4, n) 3 unique bands of the symmetric matrix that is an inverse to ``A``. The first row is filled with zeros. Notes ----- The algorithm is based on the cholesky decomposition and, therefore, in case matrix ``A`` is close to not positive defined, the function raises LinalgError. Both matrices ``A`` and ``B`` are stored in LAPACK banded storage. References ---------- .. [1] M. F. Hutchinson and F. R. de Hoog, "Smoothing noisy data with spline functions," Numerische Mathematik, vol. 47, no. 1, pp. 99-106, 1985. :doi:`10.1007/BF01389878` c~td |z dz }d}|dk(rDtd|dzD]"}||| dz ||zf|| dz ||zfzz}$|||z }||d|f<ytd|dzD]?}t||z }|t||z} ||| dz ||zf|| dz | |zfzz}A||| dz ||zf<y)Nrr rr])rgr-abs) r2r.rDBrngrng_sumr/r indrQs rfind_b_inv_elemzN_compute_optimal_gcv_parameter..compute_b_inv..find_b_inv_elemsaQ#CGAvq#'*CAq!aQ/!QBFAEM2BBBGC1Q4""a%q#'*KAq1u:Dc!Qi-Cq!aQ/!TEAIsTz4I2JJJGK$+1"q&!a%- r r@rIr Nr]r^rHrerrQr)rr-rIrrrg)rrXrr2rSrTr.rQs @r compute_b_invz5_compute_optimal_gcv_parameter..compute_b_invsD +" A q! (A qb!A#$hK1R1"Q$Y< 'K ( !B%!O "2 GGAJ HHAq6 "q1ub"% /A3q!a%!),b"5 /1aA. / /tax!r c 8|jd}td|||zz|}tj|}||z} t |D]H} t t d| |z dzt d| dzD]} || xx| | | dz| z fz cc<Jtjj||zdz|z } |||zz} | }||z}|ddxxxdzcccdtt||z z dz}| |z }|S#t$r td wxYw) a Computes the generalized cross-validation criteria [1]. Parameters ---------- lam : float, (:math:`\lambda \geq 0`) Regularization parameter. X : array, shape (5, n) Matrix is stored in LAPACK banded storage. XtWX : array, shape (4, n) Product :math:`X^T W X` stored in LAPACK banded storage. wE : array, shape (5, n) Matrix :math:`W^{-1} E` stored in LAPACK banded storage. XtE : array, shape (4, n) Product :math:`X^T E` stored in LAPACK banded storage. Returns ------- res : float Value of the GCV criteria with the regularization parameter :math:`\lambda`. Notes ----- Criteria is computed from the formula (1.3.2) [3]: .. math: GCV(\lambda) = \dfrac{1}{n} \sum\limits_{k = 1}^{n} \dfrac{ \left( y_k - f_{\lambda}(x_k) \right)^2}{\left( 1 - \Tr{A}/n\right)^2}$. The criteria is discussed in section 1.3 [3]. The numerator is computed using (2.2.4) [3] and the denominator is computed using an algorithm from [2] (see in the ``compute_b_inv`` function). References ---------- .. [1] G. Wahba, "Estimating the smoothing parameter" in Spline models for observational data, Philadelphia, Pennsylvania: Society for Industrial and Applied Mathematics, 1990, pp. 45-65. :doi:`10.1137/1.9781611970128` .. [2] M. F. Hutchinson and F. R. de Hoog, "Smoothing noisy data with spline functions," Numerische Mathematik, vol. 47, no. 1, pp. 99-106, 1985. :doi:`10.1007/BF01389878` .. [3] E. Zemlyanoy, "Generalized cross-validation smoothing splines", BSc thesis, 2022. Might be available (in Russian) `here `_ r r@r@rrrIr@Nr]z#Seems like the problem is ill-posed) rIr rrr-rhrglinalgnormrJrr')lamrKXtWXwEXtEr1rQrFr9tmpr2r.numerlhsb_bandedtrdenomrYs r_gcvz,_compute_optimal_gcv_parameter.._gcvsEj GGAJ S2Xq 1hhqk1fq ,A3q!a%!),c!QUm< ,A#aQl++ , , sSy)1,q0S3Y D$S)HDB sGqLGSW))A-E em  DBC C Ds 8DDr rBounded)boundsr6argsz,Unable to find minimum of the GCV function: r@Nz5Internal error. Please report it to scipy developers.) rIrJr successr(r'messagerr'r- RuntimeError) rKr`r1r<rNrhrQr_ragcv_estr2estrYs @r_compute_optimal_gcv_parameterrqXs_F'RAFN`  A *1a 3D )!Q 3Cvv{! !Q D"c18M  ??99 &&-oo%689 9 1((1771:&qwwqz" AA!aVIQb#qQRTUQUw"@AA ARSSr c|jd}tj|}t|D]0}d}t|D]}||k7s |||||z z}d|z ||<2|S)a Returns the coefficients of the divided difference. Parameters ---------- x : array, shape (n,) Array which is used for the computation of divided difference. Returns ------- res : array_like, shape (n,) Coefficients of the divided difference. Notes ----- Vector ``x`` should have unique elements, otherwise an error division by zero might be raised. No checks are performed. rr^)rIrrr-)r(rQr9r2rr/s r_coeff_of_divided_diffrsUs|,  A ((1+C 1X q $AAvqtad{# $bA  Jr rc 6 tj|t}tj|t}t|dd|ddz dkr t d|j dk7s|j d|j |k7r%t d|j d|j |tjt|}n.tj|}t|dkr t d tj|dgd z||dgd zf}|j d}|d kr t d t||j }tj||d}|j dd}|d k7r|j|df}tj||d }tjd|f} t!dd D]0} || | d z d dftj"|d z | | ddf<2|d| d<|d|dzd|dzz |dz|d|dzf| dddf<|d|dz |dz|df| d ddf<|d|d|dz |dzf| dddf<|d|dzd|dz|dz |dz |dzf| dddf<|d| d<tjd|f} t%|dd |dd z | dddf<t%|dd |dd z | dddf<t!d|dz D];} || dz|| dz z t%|| dz | d zz|| dz | d zz | dd| f<=t%|dd |ddz | dddf<t%|dd|ddz | dddf<| dz} |t'| | ||}n|dkr t dtj |dk(rt)d| || zz|} ntj |dk(rftj*||j df} t!|j dD]&} t)d| || | zz|dd| f| dd| f<(n t-d| j| j dg|} | ddd f| ddd f}}| dddd f| dddd f}}tj||d|d zd|d zz z|z||d|d z z|z| ddd f||d|d!z z|z|d|dz|d"z |d!z z|zf}tj/||d |#S)$a Create a smoothing B-spline satisfying the Generalized Cross Validation (GCV) criterion. Compute the (coefficients of) smoothing cubic spline function using ``lam`` to control the tradeoff between the amount of smoothness of the curve and its proximity to the data. In case ``lam`` is None, using the GCV criteria [1] to find it. A smoothing spline is found as a solution to the regularized weighted linear regression problem: .. math:: \sum\limits_{i=1}^n w_i\lvert y_i - f(x_i) \rvert^2 + \lambda\int\limits_{x_1}^{x_n} (f^{(2)}(u))^2 d u where :math:`f` is a spline function, :math:`w` is a vector of weights and :math:`\lambda` is a regularization parameter. If ``lam`` is None, we use the GCV criteria to find an optimal regularization parameter, otherwise we solve the regularized weighted linear regression problem with given parameter. The parameter controls the tradeoff in the following way: the larger the parameter becomes, the smoother the function gets. Parameters ---------- x : array_like, shape (n,) Abscissas. `n` must be at least 5. y : array_like, shape (n, ...) Ordinates. `n` must be at least 5. w : array_like, shape (n,), optional Vector of weights. Default is ``np.ones_like(x)``. lam : float, (:math:`\lambda \geq 0`), optional Regularization parameter. If ``lam`` is None, then it is found from the GCV criteria. Default is None. axis : int, optional The data axis. Default is zero. The assumption is that ``y.shape[axis] == n``, and all other axes of ``y`` are batching axes. Returns ------- func : `BSpline` object An object representing a spline in the B-spline basis as a solution of the problem of smoothing splines using the GCV criteria [1] in case ``lam`` is None, otherwise using the given parameter ``lam``. Notes ----- This algorithm is a clean room reimplementation of the algorithm introduced by Woltring in FORTRAN [2]. The original version cannot be used in SciPy source code because of the license issues. The details of the reimplementation are discussed here (available only in Russian) [4]. If the vector of weights ``w`` is None, we assume that all the points are equal in terms of weights, and vector of weights is vector of ones. Note that in weighted residual sum of squares, weights are not squared: :math:`\sum\limits_{i=1}^n w_i\lvert y_i - f(x_i) \rvert^2` while in ``splrep`` the sum is built from the squared weights. In cases when the initial problem is ill-posed (for example, the product :math:`X^T W X` where :math:`X` is a design matrix is not a positive defined matrix) a ValueError is raised. References ---------- .. [1] G. Wahba, "Estimating the smoothing parameter" in Spline models for observational data, Philadelphia, Pennsylvania: Society for Industrial and Applied Mathematics, 1990, pp. 45-65. :doi:`10.1137/1.9781611970128` .. [2] H. J. Woltring, A Fortran package for generalized, cross-validatory spline smoothing and differentiation, Advances in Engineering Software, vol. 8, no. 2, pp. 104-113, 1986. :doi:`10.1016/0141-1195(86)90098-7` .. [3] T. Hastie, J. Friedman, and R. Tisbshirani, "Smoothing Splines" in The elements of Statistical Learning: Data Mining, Inference, and prediction, New York: Springer, 2017, pp. 241-249. :doi:`10.1007/978-0-387-84858-7` .. [4] E. Zemlyanoy, "Generalized cross-validation smoothing splines", BSc thesis, 2022. ``_ (in Russian) Examples -------- Generate some noisy data >>> import numpy as np >>> np.random.seed(1234) >>> n = 200 >>> def func(x): ... return x**3 + x**2 * np.sin(4 * x) >>> x = np.sort(np.random.random_sample(n) * 4 - 2) >>> y = func(x) + np.random.normal(scale=1.5, size=n) Make a smoothing spline function >>> from scipy.interpolate import make_smoothing_spline >>> spl = make_smoothing_spline(x, y) Plot both >>> import matplotlib.pyplot as plt >>> grid = np.linspace(x[0], x[-1], 400) >>> plt.plot(x, y, '.') >>> plt.plot(grid, spl(grid), label='Spline') >>> plt.plot(grid, func(grid), label='Original function') >>> plt.legend(loc='best') >>> plt.show() rr Nr]rz"``x`` should be an ascending arrayz!``x`` should be 1D and x.shape = z == y.shape = zInvalid vector of weightsrrHz)``x`` and ``y`` length must be at least 5rrIr@rG)rr)r r )r r@r[)ruru)rGrG)rGru)r]r])rrGrQz/Regularization parameter should be non-negativez5Internal error, please report it to SciPy developers..ir)rr#r~rNr'rJrIonesr6r_rrLrprryrr- diag_indicesrsrqr r'rnrX)r(r1r<r^rKr0rQy_shape1X_bsplrKr2r`r.rFc0c1cm0cm1c_s rrrvsh Qe,A Qe,A 1QR51Sb6>Q =>>vv{aggajAGGDM1=177,o177,OPPy GGCFO   # qAv;89 9 qtfqj!aeWq[()A  AAvDEE aff -D AtQAwwqr{H2~ IIq"g  " "1a +F !QA 1a[FQAXq"u_-booa!e.DE!QU( FTlAdG1!q1Q4x'6$<7t vd|+-Aa!eH1!t ,fTl;Aa!eH!B%!B%-6&>!ABAafI&.0ae)ae#ae+vf~=?AafIf~AeH 1a& B&q!u-"15Bqr1uI&q!u-"15Bqr1uI 1a!e_!acFQqsVO'=a!AaCj'IIqsAaC[!1a4!*!BC&11AbcF:BssBwK(2301RS69BssBwK!GB {,QAq9 rJKK wws|q S2Xq 1   HHa1& 'syy|$ EA"61s1v{?AadGDAadG ERSS 1771:))*AqsCx[!AaCH+BBr32b8S=!1C rQqTAaD[1qt8+,r1QqTAaD[!B&B}aeaem$s*a!B%i!B%'!B%/036 7 8B  ! !!R ! 66r c .tj|}tj|}|jdk7s|jdk7rtd|d||jd}|jd}||z dz }|dz|cxkr|ksntd|d|d|d|d |dz|d|d zkDj rtd |d||d ||dz d kj rtd |d||dz||z ||||z dz kj rtd|d|d||ks|d |||z dz kDrtd|d|dd|d|d}|d||dzk\s|d |||z d z kr t||jd}|dz}||z dz }|d kry t d|dzD]O} || } |dz }||} tj|| kD} | |dz k\r t||| | k\sFt|y )z Check consistency of the data vector `x` and the knot vector `t`. Return None if inputs are consistent, raises a ValueError otherwise. r z,Expect `x` and `t` be 1D sequences. Got x = z and t = rz Need k+1 <= n-k-1 <= m. Got m = z, n = z and k = rcNr@z'First k knots must be ordered; got t = r]z&Last k knots must be ordered; got t = z)Internal knots must be distinct. Got t = zOut of bounds: x = z2Schoenberg-Whitney condition is violated with t = z and x =r)rrErJr'rIrNr-argmax) r(r0r/rrQnk1mesgrnk3r.tjtlr2s rfpcheckrS s. 1 A 1 Avv{affkHA6qfUVV  A  A a%!)C ES A <vWvZ1&PQRSS $1Q3!Aac(!CqfAFGG #$!CE"+""$BaV1EFF !A#ac a!A#a%j %%'EaHII !qt 21Q3q5)/1& aV1=>>AA6qe1 MD !!A#AbEQqs1uX-  A !A a%!)C Qw 1c!e_# qT Q qT IIa"f  !8T" " Q42:T" "# r r)r)rNNrT)rNrTr)0rCmathrnumpyrscipy._lib._utilr scipy.linalgrrrrr r scipy.optimizer r r scipy.sparser scipy.specialr itertoolsr__all__rr+r3r;rrrrrrrrrrrrrr;rqrsrrrr rrs1//+"" $  >  c Pc PLCT ,+  %S l (< ~(=VZNz>?$(R6jN6tN6j*zTzBV7!V7zR r