+
    nDjF                         ^ RI t ^ RIt^ RIHtHt ^ RIHt ^ RIH	t	 ^ RI
Ht RR ltRRR	^R
R/R ltRR ltRR ltR tRR ltR# )    N)_RichResult_validate_int)get_lapack_funcs)minimize_scalar)binomc                   T pTpRpRpRpVP                   ^ ,          ^8X  di   Rp\        WV3RR7      p	VR,          p
V^RR13,          pV	! WWFWe4      w  rrV'       d,   V^ 8X  d%   \        P                  ! V
4      P	                  4       pMaRp\        WV3RR7      pV! W4RVVR	7      w  prV'       d:   V^ 8X  d3   ^\        P                  ! VR,          4      P	                  4       ,          pV^ 8  d   \        R
V)  RV 24      hWV3# )a  
Solve the equation ``a @ x = b`` for ``x``,  where ``a`` is the 
Hermitian positive-definite banded matrix defined by `ab`.

Same as scipy.linalg.solveh_banded(lower=True, check_finite=False), but:
- also returns the log of the determinant and info
- no error is raised if info > 0
- no input validation
- only real values, no complex
- only `lower = True` code path
- always overwrite_XX = False
- b only a 1-dim array

Parameters
----------
ab : (``u`` + 1, M) array_like
    Banded matrix
b : (M,) array_like
    Right-hand side

Returns
-------
x : (M,) ndarray
    The solution to the system ``a x = b``. Shape of return matches shape of `b`.
logdet : float
    Logarithm of the determinant of `ab`. Returns 0 if ``calc_logdet=False``.
info : int
F        ptsv	preferred)ilp64NpbsvT)loweroverwrite_aboverwrite_bzillegal value in zth argument of internal r   NNN)shaper   nplogsum
ValueError)abbcalc_logdeta1b1r   r   logdetmethodr
   deduxinfor   cs   &&&              Q/data/cameron/venvs/s3viz/lib/python3.14/site-packages/scipy/signal/_whittaker.py_solveh_bandedr'   	   s   : 
B	
BKLF	xx{aRDtHq#2#vJaBlPq419VVAY]]_FRD"<&13
1419$,,..Fax,dUG3KF8TUUd?    lambremlorderweightsc                 a aa \        SR^R7      o\        P                  ! S 4      o S P                  ^8w  d   RS P                   2p\        V4      hS P                  ^ ,          pVS^,           8  d   RS^,            RV R2p\        V4      hSe?   \        P                  ! S4      oSP                  S P                  8w  d   Rp\        V4      hSf7   \        P                  ! S 4      P                  4       '       g   \        R4      hM\        P                  ! S4      P                  4       '       g   \        R	4      h\        P                  ! S 4      ( ;pP                  4       '       dB   SV,          ^ 8H  P                  4       '       g   \        R
4      h\        P                  ! S 4      o RV: R2p\        V\        4      '       dJ   VR8w  d   \        V4      hVV V3R lp\        VR^
.R7      p\        P                  ! VP                  4      pV^ 8  d   \        V4      hVR8X  d&   \        P                  ! S 4      P                  4       p	M\!        S VSSR7      w  r\#        WR7      # )u  
Whittaker-Henderson (WH) smoothing/graduation of a discrete signal.

This implements WH smoothing with a difference penalty of the specified ``order``
and penalty strength ``lamb``, see [1]_, [2]_ and [3]_. WH can be seen as a
penalized B-Spline (P-Spline) of degree zero for equidistant knots at the signal
positions.

In econometrics, the WH graduation of order 2 is referred to as the
Hodrick-Prescott filter [4]_.

Parameters
----------
signal : array_like
    A one-dimensional array of length ``order + 1`` representing equidistant data
    points of a signal, e.g. a time series with constant time lag.

lamb : str or float, optional
    Smoothing or penalty parameter, default is ``"reml"`` which minimizes the
    restricted maximum likelihood (REML) criterion to find the parameter ``lamb``.
    If a number is passed, it must be non-negative and it is used directly.

order : int, default: 2
    The order of the difference penalty, must be at least 1.

weights : array_like or None, optional
    A one-dimensional array of case weights with the same length as `signal`.
    ``None`` is equivalent to an array of all ones, ``np.ones_like(signal)``.

Returns
-------
 res : _RichResult
    An object similar to an instance of `scipy.optimize.OptimizeResult` with the
    following attributes:

    x : ndarray
        The WH smoothed signal.
    lamb : float
        The penalty parameter. If the input ``lamb`` is a number, this value is
        returned. If the input was ``"reml"``, the penalty parameter that minimized
        the REML criterion is returned.

Notes
-----
For the signal :math:`y = (y_1, y_2, \ldots, y_n)` and weights
:math:`w = (w_1, w_2, \ldots, w_n)`, WH of order :math:`p` with smoothing or
penalty parameter :math:`\lambda` solves the following optimization problem for
:math:`x_i`:

.. math::

    \operatorname{argmin}_{x_i} \sum_i^n w_i (y_i - x_i)^2
    + \lambda \sum_i^{n-p} (\Delta^p x_i)^2 \,,

where :math:`\Delta^p` is the forward difference operator of order :math:`p`,
:math:`\Delta x_i = x_{i+1} - x_i` and
:math:`\Delta^2 x_i = \Delta(\Delta x_i) = x_{i+2} - 2x_{i+1} + x_i`.
For every input value :math:`y_i`, it generates a smoothed value :math:`x_i`.

One of the nice properties of WH is that it automatically performs inter- and
extrapolation of data. Interpolation means filling in values when signal data is
only available on the left and on the right. Extrapolation means filling in values
after the observed signal ends.
Set ``weights = 0`` for regions where you want to extra- or interpolate. The values
of `signal` don't matter if ``weights = 0``.
WH interpolates a polynomial of ``degree = 2 * order - 1`` and it extrapolates a
polynomial of ``degree = order - 1``. For ``order = 2``, this means cubic
interpolation and linear extrapolation.

References
----------
.. [1] Whittaker-Henderson smoothing,
       https://en.wikipedia.org/wiki/Whittaker%E2%80%93Henderson_smoothing
.. [2] Eilers, P.H.C. (2003).
       "A perfect smoother". Analytical Chem. 75, 3631-3636.
       :doi:`10.1021/AC034173T`
.. [3] Weinert, Howard L. (2007).
       "Efficient computation for Whittaker-Henderson smoothing".
       Computational Statistics and Data Analysis 52:959-74.
       :doi:`10.1016/j.csda.2006.11.038`
.. [4] Hodrick, R. J., and Prescott, E. C. (1997).
       "Postwar U.S. Business Cycles: An Empirical Investigation".
       :doi:`10.2307/2953682`

Examples
--------
We use data from https://data.giss.nasa.gov/gistemp/ for global temperature
anomalies, i.e., deviations from the corresponding 1951-1980 means (Combined
Land-Surface Air and Sea-Surface Water Temperature Anomalies, Land-Ocean Temperature
Index, L-OTI).
We use weights to indicate where to inter- and extrapolate the missing data.

>>> from pathlib import Path
>>> import numpy as np
>>> import scipy
>>> from scipy.signal import whittaker_henderson
>>> # For the most recent data, use
... # fname="https://data.giss.nasa.gov/gistemp/tabledata_v4/GLB.Ts+dSST.csv"
... # Here, we instead use a copy made in 2026.
... fname = Path(scipy.signal.__file__).parent / "tests/data/GLB.Ts+dSST.csv"
>>> data = np.genfromtxt(
...     fname=fname,
...     delimiter=",", skip_header=2, missing_values="***"
... )
>>> year = data[:, 0]
>>> temperature = data[:, 1:13].ravel()  # monthly temperature anomalies
>>> w = np.ones_like(temperature)
>>> # We might have some nan values.
... np.sum(np.isnan(temperature))
np.int64(10)
>>> w[np.isnan(temperature)] = 0
>>> res = whittaker_henderson(temperature, weights=w)
>>> temperature[:5]
array([-0.19, -0.25, -0.09, -0.16, -0.1])
>>> res.x[:5]
array([-0.18244619, -0.17823282, -0.17409373, -0.17080896, -0.16833158])

Let us plot measurements and Whittaker-Henderson smoothing.

>>> import matplotlib.pyplot as plt
>>> x = year[0] + np.arange(len(temperature)) / 12
>>> plt.plot(x, temperature, label="measurement")
>>> plt.plot(x, res.x, label="WH smooth")
>>> # Above, we set w = 0 for nan values of temperature. WH automatically
... # inter- or extrapolates for all data points with w = 0.
... plt.plot(x[w==0], res.x[w==0], color="red", label="inter-/extrapolation")
>>> plt.xlabel("year")
>>> plt.ylabel("temperature deviation [°C]")
>>> plt.title("Global Temperature Anomalies (ref. 1951-1980)")
>>> plt.legend()
>>> plt.show()

We can see that extrapolation has occurred at the right end of the signal, meaning
that NaNs existed in the data for the most recent dates, in particular months of
2026 that have not yet happened at the time of the data download in March 2026.

r+   )nameminimumz.Input array signal must be of shape (n,); got z.Input array signal must be at least of shape (z,); got .zAInput array weights must have the same shape as the signal array.z"Input array signal must be finite.z#Input array weights must be finite.zGInput array weights must be zero for all non-finite elements of signal.zGParameter lamb must be string 'reml' or a non-negative float; got lamb=r*   c                 L   < \        \        P                  ! V 4      SSSR 7      ) # ))r)   yr+   r,   )_remlr   exp)loglambr+   signalr,   s   &r&   	criterion&whittaker_henderson.<locals>.criterion   s    rvvg&wWWWr(   )bracketr	   )r)   r+   r,   )r#   r)   i)r   r   asarrayndimr   r   isfiniteallany
nan_to_num
isinstancestrr   r4   r#   copy_solve_WH_bandedr   )r6   r)   r+   r,   msgnmaskr7   optr#   _s   f$dd       r&   whittaker_hendersonrI   C   s	   T %gq9EZZF{{a>v||nMoQA519}>uqykRSQTTUVo**W%==FLL(UCS/!{{6"&&((ABB ) {{7#''))BCC[[(((D--// DMQ&++--  "7 8 8]]6*F UtgUV
WC$6>S/!	Xi#r;vvcee}axo	JJv##%TP&&r(   c                @   \        V 4      p\        P                  ! V4      p\        P                  P                  P                  W`V^,
          VR7      pV'       d8   \        W%R7      pWR,
          \        P                  ! V4      ,          V,           p	MRp	V! V4      V	3# )z5Polynomial fit equivalent to WH for lamb -> infinity.)r#   r2   degwr+   rE   r	   )lenr   arange
polynomial
Polynomialfit_logdet_difference_matrixr   )
r2   r)   r+   r,   r   rE   x_rangepoly
logdet_DtDr   s
   &&&&&     r&   _polynomial_fitrW      sy    AAiilG==##'''EAI'QD /U@
)rvvd|+j8=&  r(   c           
        V P                   ^ ,          pTpV^V,          ^,           8  d/   \        P                  ! \        P                  ! V4      V^ R7      pM;\        P                  ! \        P                  ! ^V,          ^,           4      V^ R7      pVP                  V,          p	\        P
                  ! V^,           \        ^V,          ^,           V4      34      p
\        V^,           4       F7  p\        P                  ! W4      WRV
P                   ^,          V,
          13&   K9  	  W,          p
V^V,          ^,           8  dw   \        P                  ! V
RRV^,           13,          \        P                  ! V
RWw^,           13,          V^V,          ^,           ,
          ^R7      V
RV) R13,          .^R7      p
Vfs   V\        P                  ! \        P                  4      P                  ,          ^8  d   \        WW$R7      w  r^ pMV
R;;,          R,          uu&   \        WVR7      w  rpMtV
R,          V
R,          V^,          ,           8H  P!                  4       '       d   \        WW#VR7      w  r^ pM,V
R;;,          V,          uu&   \        WV ,          VR7      w  rpV^ 8  dR   V'       d:   Vf   R	MR
pRV: 2V,           R,           p\"        P$                  ! V\&        ^R7       \        WW#VR7      w  rW3# )ae  
Solve the WH optimization problem via the normal equations.

A @ x = y
A = I + lamb * P = I + lamb * D' @ D
D = difference matrix of order=`order` 

With weights W = diag(weights):
A = W + lamb * P
A @ x = W @ y

Returns
-------
x : ndarray
    The solution.
logdet : float
    Logarithm of the determinant of matrix A. Returns 0 if ``calc_logdet=False``.
)rE   axisNr   )rY   )r)   r+   r   g      ?)r   )r)   r+   r,   r    z or due to the weightszThe linear solver in Whittaker-Henderson smoothing detected a numerical instability. This is likely due to a very large value of lamb=z. As Whittaker-Henderson approaches a polynomial of degree 'order - 1' for large lamb, this polynomial (via least squares) is returned.)
stacklevel)r+   r,   r   r   )r   r   diffeyeTzerosminrangediagonalconcatrepeatfinfofloat64epsrW   r'   r=   warningswarnUserWarning)r2   r)   r+   r,   r   	warn_userrE   pDP_rawr   ir#   r   r$   msg_weightsrD   s   &&&&&&           r&   rC   rC     s{   & 	

AA 	1Q37{GGBFF1I+GGBFF1Q37Oqq1CC!GE 
1q5#acAgq/*	+B1q5\"$++e"7rxx{Q JB1Q37{YY1dqsd7		"QA#X,QqSU!<1qbc6

 
  "((2::&***Q.'EIA DtHOH,RLOAttH47Q;..3355'EIA DtHH,R1+VOAtax  '"5MK' !SS  MM#{q9#5{
	 9r(   c           	        T pV ^8X  d   \         P                  ! V4      # Rp\        ^V^,           4       F]  pV\         P                  ! \        W,           ^,
          ^V,          ^,
          4      \        ^V,          V4      ,          4      ,          pK_  	  V\         P                  ! \        ^V,          V4      4      ,          pV# )zLogarithm of the determinant of the difference matrix.

If D is the difference matrix of order=p, then this computes `log det(D @ D.T)`
which equals the sum of the log of non-zero eigenvalues of `D.T @ D`.
r	   )r   r   ra   r   )r+   rE   rl   r   ro   s   &&   r&   rS   rS   t  s     	AzvvayF1ac]"&&quqy!A#'2U1Q3]BCC 
bffU1Q3]##FMr(   c           	        VP                   ^ ,          p\        WW#RRR7      w  rV\        W$R7      pW,
          pVf
   W,          p	MWV,          ,          p	W\        P                  ! \        P
                  ! WRR7      ^,          4      ,          ,          p	WB,
          ^\        P                  ! WV,
          ,          4      ,           ,          p
WV,
          \        P                  ! V 4      ,          V,           ,          p
W,          p
V
R,          p
V
# )ae  Calculate the restricted maximum likelihood (REML).

Parameters
----------
lamb : penalty
y : signal
x : smoothed signal
order : order of the difference penalty.
weights : case weights

Returns
-------
reml : REML criterion

References
----------
- Biessy https://arxiv.org/abs/2306.06932 (version 4)
- Wood https://doi.org/10.1111/j.1467-9868.2010.00749.x
TF)r2   r)   r+   r,   r   rk   rM   )rE   g      )r   rC   rS   r   r   r\   r   )r)   r2   r+   r,   rE   r#   r   rV   residualr2r*   s   &&&&       r&   r3   r3     s    ( 	

A 
e$RWIA +<JuH4  8+,+Q./
//BI!bffRu9%5667DY"&&,&33DNDDLDKr(   )F)   NF)ru   NFT)N)rh   numpyr   scipy._lib._utilr   r   scipy.linalg.lapackr   scipy.optimizer   scipy.specialr   r'   rI   rW   rC   rS   r3    r(   r&   <module>r|      sR      7 0 * 7tz' z'a z' z'z!bJ&<r(   