
    (phK                         S r SSKrSSKrSSKrSSKJrJr  SSKJrJ	r	J
r
  / SQrS rSS jr " S S	5      r " S
 S\5      rSSS.S jjrSSSSS.S jjrg)a  
Chirp z-transform.

We provide two interfaces to the chirp z-transform: an object interface
which precalculates part of the transform and can be applied efficiently
to many different data sets, and a functional interface which is applied
only to the given data set.

Transforms
----------

CZT : callable (x, axis=-1) -> array
   Define a chirp z-transform that can be applied to different signals.
ZoomFFT : callable (x, axis=-1) -> array
   Define a Fourier transform on a range of frequencies.

Functions
---------

czt : array
   Compute the chirp z-transform for a signal.
zoom_fft : array
   Compute the Fourier transform on a range of frequencies.
    N)piarange)fftifftnext_fast_len)cztzoom_fftCZTZoomFFT
czt_pointsc                     U S:  d  [        U [        R                  5      (       d  [        SU  S35      eUc  U nU$ US:  d  [        U[        R                  5      (       d  [        SU S35      eU$ )N   z#Invalid number of CZT data points (z1) specified. n must be positive and integer type.z%Invalid number of CZT output points (z1) specified. m must be positive and integer type.)
isinstancenumbersIntegral
ValueError)nms     D/var/www/html/venv/lib/python3.13/site-packages/scipy/signal/_czt.py_validate_sizesr   %   s    1uJq'"2"233 $$%3 '@@ A 	A 	y H 
QjG$4$455 $$%3 '@@ A 	A H    c                     [        SU 5      n [        U 5      nSU-  nUc&  U[        R                  " S[        -  U-  U -  5      -  $ SU-  nX!U* -  -  $ )a(  
Return the points at which the chirp z-transform is computed.

Parameters
----------
m : int
    The number of points desired.
w : complex, optional
    The ratio between points in each step.
    Defaults to equally spaced points around the entire unit circle.
a : complex, optional
    The starting point in the complex plane.  Default is 1+0j.

Returns
-------
out : ndarray
    The points in the Z plane at which `CZT` samples the z-transform,
    when called with arguments `m`, `w`, and `a`, as complex numbers.

See Also
--------
CZT : Class that creates a callable chirp z-transform function.
czt : Convenience function for quickly calculating CZT.

Examples
--------
Plot the points of a 16-point FFT:

>>> import numpy as np
>>> from scipy.signal import czt_points
>>> points = czt_points(16)
>>> import matplotlib.pyplot as plt
>>> plt.plot(points.real, points.imag, 'o')
>>> plt.gca().add_patch(plt.Circle((0,0), radius=1, fill=False, alpha=.3))
>>> plt.axis('equal')
>>> plt.show()

and a 91-point logarithmic spiral that crosses the unit circle:

>>> m, w, a = 91, 0.995*np.exp(-1j*np.pi*.05), 0.8*np.exp(1j*np.pi/6)
>>> points = czt_points(m, w, a)
>>> plt.plot(points.real, points.imag, 'o')
>>> plt.gca().add_patch(plt.Circle((0,0), radius=1, fill=False, alpha=.3))
>>> plt.axis('equal')
>>> plt.show()
r         ?               @)r   r   npexpr   )r   waks       r   r   r   5   sa    ^ 	1Aq	AaAy266"r'A+/*** !Gqb5yr   c                   6    \ rS rSrSrS
S jrSS.S jrS rS	rg)r
   s   a  
Create a callable chirp z-transform function.

Transform to compute the frequency response around a spiral.
Objects of this class are callables which can compute the
chirp z-transform on their inputs.  This object precalculates the constant
chirps used in the given transform.

Parameters
----------
n : int
    The size of the signal.
m : int, optional
    The number of output points desired.  Default is `n`.
w : complex, optional
    The ratio between points in each step.  This must be precise or the
    accumulated error will degrade the tail of the output sequence.
    Defaults to equally spaced points around the entire unit circle.
a : complex, optional
    The starting point in the complex plane.  Default is 1+0j.

Returns
-------
f : CZT
    Callable object ``f(x, axis=-1)`` for computing the chirp z-transform
    on `x`.

See Also
--------
czt : Convenience function for quickly calculating CZT.
ZoomFFT : Class that creates a callable partial FFT function.

Notes
-----
The defaults are chosen such that ``f(x)`` is equivalent to
``fft.fft(x)`` and, if ``m > len(x)``, that ``f(x, m)`` is equivalent to
``fft.fft(x, m)``.

If `w` does not lie on the unit circle, then the transform will be
around a spiral with exponentially-increasing radius.  Regardless,
angle will increase linearly.

For transforms that do lie on the unit circle, accuracy is better when
using `ZoomFFT`, since any numerical error in `w` is
accumulated for long data lengths, drifting away from the unit circle.

The chirp z-transform can be faster than an equivalent FFT with
zero padding.  Try it with your own array sizes to see.

However, the chirp z-transform is considerably less precise than the
equivalent zero-padded FFT.

As this CZT is implemented using the Bluestein algorithm, it can compute
large prime-length Fourier transforms in O(N log N) time, rather than the
O(N**2) time required by the direct DFT calculation.  (`scipy.fft` also
uses Bluestein's algorithm'.)

(The name "chirp z-transform" comes from the use of a chirp in the
Bluestein algorithm.  It does not decompose signals into chirps, like
other transforms with "chirp" in the name.)

References
----------
.. [1] Leo I. Bluestein, "A linear filtering approach to the computation
       of the discrete Fourier transform," Northeast Electronics Research
       and Engineering Meeting Record 10, 218-219 (1968).
.. [2] Rabiner, Schafer, and Rader, "The chirp z-transform algorithm and
       its application," Bell Syst. Tech. J. 48, 1249-1292 (1969).

Examples
--------
Compute multiple prime-length FFTs:

>>> from scipy.signal import CZT
>>> import numpy as np
>>> a = np.random.rand(7)
>>> b = np.random.rand(7)
>>> c = np.random.rand(7)
>>> czt_7 = CZT(n=7)
>>> A = czt_7(a)
>>> B = czt_7(b)
>>> C = czt_7(c)

Display the points at which the FFT is calculated:

>>> czt_7.points()
array([ 1.00000000+0.j        ,  0.62348980+0.78183148j,
       -0.22252093+0.97492791j, -0.90096887+0.43388374j,
       -0.90096887-0.43388374j, -0.22252093-0.97492791j,
        0.62348980-0.78183148j])
>>> import matplotlib.pyplot as plt
>>> plt.plot(czt_7.points().real, czt_7.points().imag, 'o')
>>> plt.gca().add_patch(plt.Circle((0,0), radius=1, fill=False, alpha=.3))
>>> plt.axis('equal')
>>> plt.show()
Nc           	      |   [        X5      n[        [        X!5      [        R                  " [        X!5      S-  * 5      S9nUcN  [
        R                  " S[        -  U-  5      n[        R                  " S[        -  US-  SU-  -  -  * U-  5      nO
X5S-  S-  -  nSU-  nX4sU l        U l	        X!sU l
        U l        [        X-   S-
  5      nXES U * -  US U -  U l        Xpl        [        S[        R                   " XaS-
  SS	2   US U 45      -  U5      U l        US U U l        ['        US-
  X-   S-
  5      U l        g )
N   dtype                            ?g       @r   r   r   )r   r   maxr   min_scalar_typecmathr   r   r   r   r   r   r   _Awk2_nfftr   hstack_Fwk2_wk2slice_yidx)selfr   r   r   r   r   wk2nffts           r   __init__CZT.__init__   s4   A!3q9B$6$6A	1}$EF9		#b&(#A&&27q!t!n56:;C d2g,C!GQUQY'2AYRa(

299cA#a(mS!W%=>>E
G	1Q3A&
r   r(   axisc                   [         R                  " U5      nUR                  U   U R                  :w  a(  [	        SU R                   SUR                  U    35      e[         R
                  " UR                  5      nSU/X2S/'   UR                  " U6 n[        U R                  [        XR                  -  U R                  5      -  5      nUSU R                  4   U R                  -  nUR                  " U6 $ )aY  
Calculate the chirp z-transform of a signal.

Parameters
----------
x : array
    The signal to transform.
axis : int, optional
    Axis over which to compute the FFT. If not given, the last axis is
    used.

Returns
-------
out : ndarray
    An array of the same dimensions as `x`, but with the length of the
    transformed axis set to `m`.
zCZT defined for length z, not r(   .)r   asarrayshaper   r   r   ndim	transposer   r/   r   r,   r-   r2   r0   )r3   xr9   trnspys        r   __call__CZT.__call__   s    $ JJqM774=DFF"6tvvhf !0 1 1 		!&&!JRjKKc!JJ,

;;<c4::o*{{E""r   c                 X    [        U R                  U R                  U R                  5      $ )z?
Return the points at which the chirp z-transform is computed.
)r   r   r   r   )r3   s    r   points
CZT.points  s     $&&$&&$&&11r   )	r,   r/   r-   r0   r2   r   r   r   r   NN      ?        )	__name__
__module____qualname____firstlineno____doc__r6   rB   rE   __static_attributes__ r   r   r
   r
   s   s    _B'2 #% #<2r   r
   c                   ,    \ rS rSrSrS	SSS.S jjrSrg)
r   i  a#  
Create a callable zoom FFT transform function.

This is a specialization of the chirp z-transform (`CZT`) for a set of
equally-spaced frequencies around the unit circle, used to calculate a
section of the FFT more efficiently than calculating the entire FFT and
truncating.

Parameters
----------
n : int
    The size of the signal.
fn : array_like
    A length-2 sequence [`f1`, `f2`] giving the frequency range, or a
    scalar, for which the range [0, `fn`] is assumed.
m : int, optional
    The number of points to evaluate.  Default is `n`.
fs : float, optional
    The sampling frequency.  If ``fs=10`` represented 10 kHz, for example,
    then `f1` and `f2` would also be given in kHz.
    The default sampling frequency is 2, so `f1` and `f2` should be
    in the range [0, 1] to keep the transform below the Nyquist
    frequency.
endpoint : bool, optional
    If True, `f2` is the last sample. Otherwise, it is not included.
    Default is False.

Returns
-------
f : ZoomFFT
    Callable object ``f(x, axis=-1)`` for computing the zoom FFT on `x`.

See Also
--------
zoom_fft : Convenience function for calculating a zoom FFT.

Notes
-----
The defaults are chosen such that ``f(x, 2)`` is equivalent to
``fft.fft(x)`` and, if ``m > len(x)``, that ``f(x, 2, m)`` is equivalent to
``fft.fft(x, m)``.

Sampling frequency is 1/dt, the time step between samples in the
signal `x`.  The unit circle corresponds to frequencies from 0 up
to the sampling frequency.  The default sampling frequency of 2
means that `f1`, `f2` values up to the Nyquist frequency are in the
range [0, 1). For `f1`, `f2` values expressed in radians, a sampling
frequency of 2*pi should be used.

Remember that a zoom FFT can only interpolate the points of the existing
FFT.  It cannot help to resolve two separate nearby frequencies.
Frequency resolution can only be increased by increasing acquisition
time.

These functions are implemented using Bluestein's algorithm (as is
`scipy.fft`). [2]_

References
----------
.. [1] Steve Alan Shilling, "A study of the chirp z-transform and its
       applications", pg 29 (1970)
       https://krex.k-state.edu/dspace/bitstream/handle/2097/7844/LD2668R41972S43.pdf
.. [2] Leo I. Bluestein, "A linear filtering approach to the computation
       of the discrete Fourier transform," Northeast Electronics Research
       and Engineering Meeting Record 10, 218-219 (1968).

Examples
--------
To plot the transform results use something like the following:

>>> import numpy as np
>>> from scipy.signal import ZoomFFT
>>> t = np.linspace(0, 1, 1021)
>>> x = np.cos(2*np.pi*15*t) + np.sin(2*np.pi*17*t)
>>> f1, f2 = 5, 27
>>> transform = ZoomFFT(len(x), [f1, f2], len(x), fs=1021)
>>> X = transform(x)
>>> f = np.linspace(f1, f2, len(x))
>>> import matplotlib.pyplot as plt
>>> plt.plot(f, 20*np.log10(np.abs(X)))
>>> plt.show()
Nr#   F)fsendpointc          	         [        X5      n[        [        X15      [        R                  " [        X15      S-  * 5      S9n[        R
                  " U5      S:X  a  Uu  pxO)[        R
                  " U5      S:X  a  SUpO[        S5      eXxUsU l        U l        U l	        U(       a  X-
  U-  XCS-
  -  -  n	OX-
  U-  n	[        R                  " S[        -  U-  U-  5      n
[        R                  " S[        -  U	-  US-  -  * U-  5      n[        R                  " S[        -  U-  U	-  5      U l        Xl        X1sU l        U l        [        R                  " S[        -  U-  U-  US U -  5      nXS U -  U l        [%        X-   S-
  5      nXl        [)        S[        R*                  " XS-
  S	S
2   US U 45      -  U5      U l        US U U l        [1        US-
  X-   S-
  5      U l        g )Nr#   r$   r   g        z(fn must be a scalar or 2-length sequencer   r'   r&   r   r(   )r   r   r)   r   r*   sizer   f1f2rQ   r+   r   r   r   r   r   r   r,   r   r-   r   r.   r/   r0   r1   r2   )r3   r   fnr   rQ   rR   r   rU   rV   scaler   r4   akr5   s                 r   r6   ZoomFFT.__init__g  s   A!3q9B$6$6A	1}$EF772;!FBWWR[A"GHH$&B!$'g]rU|4EWNEIIb2gl2o&ffrBwA-.233r6!8e+,VVC"HrM"$q!u,-bq'\
QUQY'
299cA#a(mS!W%=>>E
G	1Q3A&
r   )r,   r/   r-   r0   r2   r   rU   rV   rQ   r   r   r   N)rI   rJ   rK   rL   rM   r6   rN   rO   r   r   r   r     s    Qf 'A  '  'r   r   r(   r8   c                j    [         R                  " U 5      n [        U R                  U   XUS9nU" XS9$ )a  
Compute the frequency response around a spiral in the Z plane.

Parameters
----------
x : array
    The signal to transform.
m : int, optional
    The number of output points desired.  Default is the length of the
    input data.
w : complex, optional
    The ratio between points in each step.  This must be precise or the
    accumulated error will degrade the tail of the output sequence.
    Defaults to equally spaced points around the entire unit circle.
a : complex, optional
    The starting point in the complex plane.  Default is 1+0j.
axis : int, optional
    Axis over which to compute the FFT. If not given, the last axis is
    used.

Returns
-------
out : ndarray
    An array of the same dimensions as `x`, but with the length of the
    transformed axis set to `m`.

See Also
--------
CZT : Class that creates a callable chirp z-transform function.
zoom_fft : Convenience function for partial FFT calculations.

Notes
-----
The defaults are chosen such that ``signal.czt(x)`` is equivalent to
``fft.fft(x)`` and, if ``m > len(x)``, that ``signal.czt(x, m)`` is
equivalent to ``fft.fft(x, m)``.

If the transform needs to be repeated, use `CZT` to construct a
specialized transform function which can be reused without
recomputing constants.

An example application is in system identification, repeatedly evaluating
small slices of the z-transform of a system, around where a pole is
expected to exist, to refine the estimate of the pole's true location. [1]_

References
----------
.. [1] Steve Alan Shilling, "A study of the chirp z-transform and its
       applications", pg 20 (1970)
       https://krex.k-state.edu/dspace/bitstream/handle/2097/7844/LD2668R41972S43.pdf

Examples
--------
Generate a sinusoid:

>>> import numpy as np
>>> f1, f2, fs = 8, 10, 200  # Hz
>>> t = np.linspace(0, 1, fs, endpoint=False)
>>> x = np.sin(2*np.pi*t*f2)
>>> import matplotlib.pyplot as plt
>>> plt.plot(t, x)
>>> plt.axis([0, 1, -1.1, 1.1])
>>> plt.show()

Its discrete Fourier transform has all of its energy in a single frequency
bin:

>>> from scipy.fft import rfft, rfftfreq
>>> from scipy.signal import czt, czt_points
>>> plt.plot(rfftfreq(fs, 1/fs), abs(rfft(x)))
>>> plt.margins(0, 0.1)
>>> plt.show()

However, if the sinusoid is logarithmically-decaying:

>>> x = np.exp(-t*f1) * np.sin(2*np.pi*t*f2)
>>> plt.plot(t, x)
>>> plt.axis([0, 1, -1.1, 1.1])
>>> plt.show()

the DFT will have spectral leakage:

>>> plt.plot(rfftfreq(fs, 1/fs), abs(rfft(x)))
>>> plt.margins(0, 0.1)
>>> plt.show()

While the DFT always samples the z-transform around the unit circle, the
chirp z-transform allows us to sample the Z-transform along any
logarithmic spiral, such as a circle with radius smaller than unity:

>>> M = fs // 2  # Just positive frequencies, like rfft
>>> a = np.exp(-f1/fs)  # Starting point of the circle, radius < 1
>>> w = np.exp(-1j*np.pi/M)  # "Step size" of circle
>>> points = czt_points(M + 1, w, a)  # M + 1 to include Nyquist
>>> plt.plot(points.real, points.imag, '.')
>>> plt.gca().add_patch(plt.Circle((0,0), radius=1, fill=False, alpha=.3))
>>> plt.axis('equal'); plt.axis([-1.05, 1.05, -0.05, 1.05])
>>> plt.show()

With the correct radius, this transforms the decaying sinusoid (and others
with the same decay rate) without spectral leakage:

>>> z_vals = czt(x, M + 1, w, a)  # Include Nyquist for comparison to rfft
>>> freqs = np.angle(points)*fs/(2*np.pi)  # angle = omega, radius = sigma
>>> plt.plot(freqs, abs(z_vals))
>>> plt.margins(0, 0.1)
>>> plt.show()
)r   r   r   r8   )r   r;   r
   r<   )r?   r   r   r   r9   	transforms         r   r   r     s3    Z 	

1AAGGDMQq1IQ""r   r#   F)rQ   rR   r9   c                j    [         R                  " U 5      n [        U R                  U   XX4S9nU" XS9$ )a  
Compute the DFT of `x` only for frequencies in range `fn`.

Parameters
----------
x : array
    The signal to transform.
fn : array_like
    A length-2 sequence [`f1`, `f2`] giving the frequency range, or a
    scalar, for which the range [0, `fn`] is assumed.
m : int, optional
    The number of points to evaluate.  The default is the length of `x`.
fs : float, optional
    The sampling frequency.  If ``fs=10`` represented 10 kHz, for example,
    then `f1` and `f2` would also be given in kHz.
    The default sampling frequency is 2, so `f1` and `f2` should be
    in the range [0, 1] to keep the transform below the Nyquist
    frequency.
endpoint : bool, optional
    If True, `f2` is the last sample. Otherwise, it is not included.
    Default is False.
axis : int, optional
    Axis over which to compute the FFT. If not given, the last axis is
    used.

Returns
-------
out : ndarray
    The transformed signal.  The Fourier transform will be calculated
    at the points f1, f1+df, f1+2df, ..., f2, where df=(f2-f1)/m.

See Also
--------
ZoomFFT : Class that creates a callable partial FFT function.

Notes
-----
The defaults are chosen such that ``signal.zoom_fft(x, 2)`` is equivalent
to ``fft.fft(x)`` and, if ``m > len(x)``, that ``signal.zoom_fft(x, 2, m)``
is equivalent to ``fft.fft(x, m)``.

To graph the magnitude of the resulting transform, use::

    plot(linspace(f1, f2, m, endpoint=False), abs(zoom_fft(x, [f1, f2], m)))

If the transform needs to be repeated, use `ZoomFFT` to construct
a specialized transform function which can be reused without
recomputing constants.

Examples
--------
To plot the transform results use something like the following:

>>> import numpy as np
>>> from scipy.signal import zoom_fft
>>> t = np.linspace(0, 1, 1021)
>>> x = np.cos(2*np.pi*15*t) + np.sin(2*np.pi*17*t)
>>> f1, f2 = 5, 27
>>> X = zoom_fft(x, [f1, f2], len(x), fs=1021)
>>> f = np.linspace(f1, f2, len(x))
>>> import matplotlib.pyplot as plt
>>> plt.plot(f, 20*np.log10(np.abs(X)))
>>> plt.show()
)r   rQ   rR   r8   )r   r;   r   r<   )r?   rW   r   rQ   rR   r9   r]   s          r   r	   r	     s3    B 	

1Ar2IIQ""r   )NrH   rG   r[   )rM   r+   r   numpyr   r   r   	scipy.fftr   r   r   __all__r   r   r
   r   r   r	   rO   r   r   <module>rb      sk   2     . .
= ;|]2 ]2@t'c t'no#2 o#dC#!e" C#r   