
    sg                       d Z ddlmZ ddlmZ ddlmZmZmZ ddl	m
Z
mZmZ ddlZddlmZ ddlmZ ddlmZ d	gZed
   Zed   ZddZ G d d	      Zy)z=Implementation of an FFT-based Short-time Fourier Transform.     )annotations)	Generator)cache	lru_cachepartial)Callableget_argsLiteralN)detrend
get_windowShortTimeFFTzerosedgeevenodd)twosidedcenteredonesided
onesided2Xc                   |t        |       kD  rt        d|dt        |        dz         t        | j                  j                  t
        j                        rt        dd| j                  dz         | j                  dz  | j                  dz  z   }|j                         }t        |t        |       |      D ]&  }||dxxx |d|  z  ccc |d| xxx ||d z  ccc ( t        j                  | j                        j                  t        |      z  }t        j                  ||k\        st        d      | |z  S )	a  Calculate canonical dual window for 1d window `win` and a time step
    of `hop` samples.

    A ``ValueError`` is raised, if the inversion fails.

    This is a separate function not a method, since it is also used in the
    class method ``ShortTimeFFT.from_dual()``.
    zhop=z! is larger than window length of z => STFT not invertible!z/Parameter 'win' cannot be of integer type, but z
win.dtype=   Nz,Short-time Fourier Transform not invertible!)len
ValueError
issubclassdtypetypenpintegerrealimagcopyrangefinfo
resolutionmaxall)winhopw2DDk_relative_resolutions         O/var/www/html/venv/lib/python3.12/site-packages/scipy/signal/_short_time_fft.py_calc_dual_canonical_windowr0   +   s5    SX~DC6!B3s8*M34 5 	5#)).."**-J&CII<'?@A B 	B 
1sxx{	"B	BCS3' 
232ds8
4RCBrsG
 ((399-883r7B66"++,GHH8O    c                     e Zd ZU dZded<   dZded<   ded<   d	ed
<   dZded<   ded<   dZded<   ded<   dZded<   dZ	ded<   dZ
ded<   dddddd	 	 	 	 	 	 	 	 	 dVdZeddddd	 	 	 	 	 	 	 dWd       Zedddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dXd       ZedYd        ZedZd!       Zed[d"       Zej&                  d\d#       Zed[d$       Zej&                  d\d%       Zed]d&       Zej&                  d^d'       ZedZd(       Zej&                  d_d)       Zed`d*       Zdad+Zedbd,       Zej&                  dcd-       Z	 	 	 	 ddd.Z	 	 dedd/d0d1	 	 	 	 	 	 	 	 	 dfd2Z	 dedd/d0d1	 	 	 	 	 	 	 	 	 	 	 	 	 dgd3Z	 	 dedddd/d0d4	 	 	 	 	 	 	 	 	 	 	 	 	 dhd5ZedYd6       Zedid7       Zdjd8d0d9	 	 	 	 	 dkd:Z ed[d;       Z!ed[d<       Z"edZd=       Z#edZd>       Z$e%dld?       Z&edZd@       Z'edZdA       Z( e)dBC      dmdD       Z*dndEZ+dndFZ,dndGZ-edldH       Z. e)dBC      dmdI       Z/ed[dJ       Z0	 	 de	 	 	 dodKZ1 e)dLC      	 	 dp	 	 	 dqdM       Z2drdsdNZ3ed[dO       Z4edZdP       Z5edidQ       Z6edYdR       Z7dtdSZ8dudTZ9	 	 dv	 	 	 dwdUZ:y)xr   a  Provide a parametrized discrete Short-time Fourier transform (stft)
    and its inverse (istft).

    .. currentmodule:: scipy.signal.ShortTimeFFT

    The `~ShortTimeFFT.stft` calculates sequential FFTs by sliding a
    window (`win`) over an input signal by `hop` increments. It can be used to
    quantify the change of the spectrum over time.

    The `~ShortTimeFFT.stft` is represented by a complex-valued matrix S[q,p]
    where the p-th column represents an FFT with the window centered at the
    time t[p] = p * `delta_t` = p * `hop` * `T` where `T` is  the sampling
    interval of the input signal. The q-th row represents the values at the
    frequency f[q] = q * `delta_f` with `delta_f` = 1 / (`mfft` * `T`) being
    the bin width of the FFT.

    The inverse STFT `~ShortTimeFFT.istft` is calculated by reversing the steps
    of the STFT: Take the IFFT of the p-th slice of S[q,p] and multiply the
    result with the so-called dual window (see `dual_win`). Shift the result by
    p * `delta_t` and add the result to previous shifted results to reconstruct
    the signal. If only the dual window is known and the STFT is invertible,
    `from_dual` can be used to instantiate this class.

    Due to the convention of time t = 0 being at the first sample of the input
    signal, the STFT values typically have negative time slots. Hence,
    negative indexes like `p_min` or `k_min` do not indicate counting
    backwards from an array's end like in standard Python indexing but being
    left of t = 0.

    More detailed information can be found in the :ref:`tutorial_stft` section
    of the :ref:`user_guide`.

    Note that all parameters of the initializer, except `scale_to` (which uses
    `scaling`) have identical named attributes.

    Parameters
    ----------
    win : np.ndarray
        The window must be a real- or complex-valued 1d array.
    hop : int
        The increment in samples, by which the window is shifted in each step.
    fs : float
        Sampling frequency of input signal and window. Its relation to the
        sampling interval `T` is ``T = 1 / fs``.
    fft_mode : 'twosided', 'centered', 'onesided', 'onesided2X'
        Mode of FFT to be used (default 'onesided').
        See property `fft_mode` for details.
    mfft: int | None
        Length of the FFT used, if a zero padded FFT is desired.
        If ``None`` (default), the length of the window `win` is used.
    dual_win : np.ndarray | None
        The dual window of `win`. If set to ``None``, it is calculated if
        needed.
    scale_to : 'magnitude', 'psd' | None
        If not ``None`` (default) the window function is scaled, so each STFT
        column represents  either a 'magnitude' or a power spectral density
        ('psd') spectrum. This parameter sets the property `scaling` to the
        same value. See method `scale_to` for details.
    phase_shift : int | None
        If set, add a linear phase `phase_shift` / `mfft` * `f` to each
        frequency `f`. The default value 0 ensures that there is no phase shift
        on the zeroth slice (in which t=0 is centered). See property
        `phase_shift` for more details.

    Examples
    --------
    The following example shows the magnitude of the STFT of a sine with
    varying frequency :math:`f_i(t)` (marked by a red dashed line in the plot):

    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from scipy.signal import ShortTimeFFT
    >>> from scipy.signal.windows import gaussian
    ...
    >>> T_x, N = 1 / 20, 1000  # 20 Hz sampling rate for 50 s signal
    >>> t_x = np.arange(N) * T_x  # time indexes for signal
    >>> f_i = 1 * np.arctan((t_x - t_x[N // 2]) / 2) + 5  # varying frequency
    >>> x = np.sin(2*np.pi*np.cumsum(f_i)*T_x) # the signal

    The utilized Gaussian window is 50 samples or 2.5 s long. The parameter
    ``mfft=200`` in `ShortTimeFFT` causes the spectrum to be oversampled
    by a factor of 4:

    >>> g_std = 8  # standard deviation for Gaussian window in samples
    >>> w = gaussian(50, std=g_std, sym=True)  # symmetric Gaussian window
    >>> SFT = ShortTimeFFT(w, hop=10, fs=1/T_x, mfft=200, scale_to='magnitude')
    >>> Sx = SFT.stft(x)  # perform the STFT

    In the plot, the time extent of the signal `x` is marked by vertical dashed
    lines. Note that the SFT produces values outside the time range of `x`. The
    shaded areas on the left and the right indicate border effects caused
    by  the window slices in that area not fully being inside time range of
    `x`:

    >>> fig1, ax1 = plt.subplots(figsize=(6., 4.))  # enlarge plot a bit
    >>> t_lo, t_hi = SFT.extent(N)[:2]  # time range of plot
    >>> ax1.set_title(rf"STFT ({SFT.m_num*SFT.T:g}$\,s$ Gaussian window, " +
    ...               rf"$\sigma_t={g_std*SFT.T}\,$s)")
    >>> ax1.set(xlabel=f"Time $t$ in seconds ({SFT.p_num(N)} slices, " +
    ...                rf"$\Delta t = {SFT.delta_t:g}\,$s)",
    ...         ylabel=f"Freq. $f$ in Hz ({SFT.f_pts} bins, " +
    ...                rf"$\Delta f = {SFT.delta_f:g}\,$Hz)",
    ...         xlim=(t_lo, t_hi))
    ...
    >>> im1 = ax1.imshow(abs(Sx), origin='lower', aspect='auto',
    ...                  extent=SFT.extent(N), cmap='viridis')
    >>> ax1.plot(t_x, f_i, 'r--', alpha=.5, label='$f_i(t)$')
    >>> fig1.colorbar(im1, label="Magnitude $|S_x(t, f)|$")
    ...
    >>> # Shade areas where window slices stick out to the side:
    >>> for t0_, t1_ in [(t_lo, SFT.lower_border_end[0] * SFT.T),
    ...                  (SFT.upper_border_begin(N)[0] * SFT.T, t_hi)]:
    ...     ax1.axvspan(t0_, t1_, color='w', linewidth=0, alpha=.2)
    >>> for t_ in [0, N * SFT.T]:  # mark signal borders with vertical line:
    ...     ax1.axvline(t_, color='y', linestyle='--', alpha=0.5)
    >>> ax1.legend()
    >>> fig1.tight_layout()
    >>> plt.show()

    Reconstructing the signal with the `~ShortTimeFFT.istft` is
    straightforward, but note that the length of `x1` should be specified,
    since the SFT length increases in `hop` steps:

    >>> SFT.invertible  # check if invertible
    True
    >>> x1 = SFT.istft(Sx, k1=N)
    >>> np.allclose(x, x1)
    True

    It is possible to calculate the SFT of signal parts:

    >>> p_q = SFT.nearest_k_p(N // 2)
    >>> Sx0 = SFT.stft(x[:p_q])
    >>> Sx1 = SFT.stft(x[p_q:])

    When assembling sequential STFT parts together, the overlap needs to be
    considered:

    >>> p0_ub = SFT.upper_border_begin(p_q)[1] - SFT.p_min
    >>> p1_le = SFT.lower_border_end[1] - SFT.p_min
    >>> Sx01 = np.hstack((Sx0[:, :p0_ub],
    ...                   Sx0[:, p0_ub:] + Sx1[:, :p1_le],
    ...                   Sx1[:, p1_le:]))
    >>> np.allclose(Sx01, Sx)  # Compare with SFT of complete signal
    True

    It is also possible to calculate the `itsft` for signal parts:

    >>> y_p = SFT.istft(Sx, N//3, N//2)
    >>> np.allclose(y_p, x[N//3:N//2])
    True

    
np.ndarray_winNnp.ndarray | None	_dual_winint_hopfloat_fsr   FFT_MODE_TYPE	_fft_mode_mfft"Literal['magnitude', 'psd'] | None_scaling
int | None_phase_shiftzfloat | None_fac_mag_fac_psdztuple[int, int] | None_lower_border_endr   )fft_modemfftdual_winscale_tophase_shiftc                  |j                   dk(  r|j                  dkD  st        d|j                  d      t	        t        j                  |            st        d      |dk\  rt        |t              st        d|d      |||c| _	        | _
        | _        |t        |      n|| _        |h|j                  |j                  k7  r&t        d|j                  d	|j                  d      t	        t        j                  |            st        d
      || _        || j                  |       ||c| _        | _        y )N   r   z(Parameter win must be 1d, but win.shape=!z'Parameter win must have finite entries!zParameter hop=z is not an integer >= 1!zdual_win.shape=z must equal win.shape=z*Parameter dual_win must be a finite array!)ndimsizer   shaper(   r   isfinite
isinstancer7   r4   r8   fsr   rF   r6   rH   rE   rI   )	selfr)   r*   rR   rE   rF   rG   rH   rI   s	            r/   __init__zShortTimeFFT.__init__   s    A#((Q,Hcii\KLL2;;s#$FGGqZS1#/GHII(+S"%	49dg $CH$	~~* OHNN#44KA!NOOr{{8,- !MNN!MM(#*2K't'r1   )rE   rF   rH   rI   c          
     :    t        ||      } | ||||||||      S )a  Instantiate a `ShortTimeFFT` by only providing a dual window.

        If an STFT is invertible, it is possible to calculate the window `win`
        from a given dual window `dual_win`. All other parameters have the
        same meaning as in the initializer of `ShortTimeFFT`.

        As explained in the :ref:`tutorial_stft` section of the
        :ref:`user_guide`, an invertible STFT can be interpreted as series
        expansion of time-shifted and frequency modulated dual windows. E.g.,
        the series coefficient S[q,p] belongs to the term, which shifted
        `dual_win` by p * `delta_t` and multiplied it by
        exp( 2 * j * pi * t * q * `delta_f`).


        Examples
        --------
        The following example discusses decomposing a signal into time- and
        frequency-shifted Gaussians. A Gaussian with standard deviation of
        one made up of 51 samples will be used:

        >>> import numpy as np
        >>> import matplotlib.pyplot as plt
        >>> from scipy.signal import ShortTimeFFT
        >>> from scipy.signal.windows import gaussian
        ...
        >>> T, N = 0.1, 51
        >>> d_win = gaussian(N, std=1/T, sym=True)  # symmetric Gaussian window
        >>> t = T * (np.arange(N) - N//2)
        ...
        >>> fg1, ax1 = plt.subplots()
        >>> ax1.set_title(r"Dual Window: Gaussian with $\sigma_t=1$")
        >>> ax1.set(xlabel=f"Time $t$ in seconds ({N} samples, $T={T}$ s)",
        ...        xlim=(t[0], t[-1]), ylim=(0, 1.1*max(d_win)))
        >>> ax1.plot(t, d_win, 'C0-')

        The following plot with the overlap of 41, 11 and 2 samples show how
        the `hop` interval affects the shape of the window `win`:

        >>> fig2, axx = plt.subplots(3, 1, sharex='all')
        ...
        >>> axx[0].set_title(r"Windows for hop$\in\{10, 40, 49\}$")
        >>> for c_, h_ in enumerate([10, 40, 49]):
        ...     SFT = ShortTimeFFT.from_dual(d_win, h_, 1/T)
        ...     axx[c_].plot(t + h_ * T, SFT.win, 'k--', alpha=.3, label=None)
        ...     axx[c_].plot(t - h_ * T, SFT.win, 'k:', alpha=.3, label=None)
        ...     axx[c_].plot(t, SFT.win, f'C{c_+1}',
        ...                     label=r"$\Delta t=%0.1f\,$s" % SFT.delta_t)
        ...     axx[c_].set_ylim(0, 1.1*max(SFT.win))
        ...     axx[c_].legend(loc='center')
        >>> axx[-1].set(xlabel=f"Time $t$ in seconds ({N} samples, $T={T}$ s)",
        ...             xlim=(t[0], t[-1]))
        >>> plt.show()

        Beside the window `win` centered at t = 0 the previous (t = -`delta_t`)
        and following window (t = `delta_t`) are depicted. It can be seen that
        for small `hop` intervals, the window is compact and smooth, having a
        good time-frequency concentration in the STFT. For the large `hop`
        interval of 4.9 s, the window has small values around t = 0, which are
        not covered by the overlap of the adjacent windows, which could lead to
        numeric inaccuracies. Furthermore, the peaky shape at the beginning and
        the end of the window points to a higher bandwidth, resulting in a
        poorer time-frequency resolution of the STFT.
        Hence, the choice of the `hop` interval will be a compromise between
        a time-frequency resolution and memory requirements demanded by small
        `hop` sizes.

        See Also
        --------
        from_window: Create instance by wrapping `get_window`.
        ShortTimeFFT: Create instance using standard initializer.
        )r)   r*   rR   rE   rF   rG   rH   rI   )r0   )	clsrG   r*   rR   rE   rF   rH   rI   r)   s	            r/   	from_dualzShortTimeFFT.from_dual  s0    Z *(C8sXD$x*, 	,r1   F)symmetric_winrE   rF   rH   rI   c          	     D    t        |||       }
 | |
||z
  |||||	      S )a  Instantiate `ShortTimeFFT` by using `get_window`.

        The method `get_window` is used to create a window of length
        `nperseg`. The parameter names `noverlap`, and `nperseg` are used here,
        since they more inline with other classical STFT libraries.

        Parameters
        ----------
        win_param: Union[str, tuple, float],
            Parameters passed to `get_window`. For windows with no parameters,
            it may be a string (e.g., ``'hann'``), for parametrized windows a
            tuple, (e.g., ``('gaussian', 2.)``) or a single float specifying
            the shape parameter of a kaiser window (i.e. ``4.``  and
            ``('kaiser', 4.)`` are equal. See `get_window` for more details.
        fs : float
            Sampling frequency of input signal. Its relation to the
            sampling interval `T` is ``T = 1 / fs``.
        nperseg: int
            Window length in samples, which corresponds to the `m_num`.
        noverlap: int
            Window overlap in samples. It relates to the `hop` increment by
            ``hop = npsereg - noverlap``.
        symmetric_win: bool
            If ``True`` then a symmetric window is generated, else a periodic
            window is generated (default). Though symmetric windows seem for
            most applications to be more sensible, the default of a periodic
            windows was chosen to correspond to the default of `get_window`.
        fft_mode : 'twosided', 'centered', 'onesided', 'onesided2X'
            Mode of FFT to be used (default 'onesided').
            See property `fft_mode` for details.
        mfft: int | None
            Length of the FFT used, if a zero padded FFT is desired.
            If ``None`` (default), the length of the window `win` is used.
        scale_to : 'magnitude', 'psd' | None
            If not ``None`` (default) the window function is scaled, so each
            STFT column represents  either a 'magnitude' or a power spectral
            density ('psd') spectrum. This parameter sets the property
            `scaling` to the same value. See method `scale_to` for details.
        phase_shift : int | None
            If set, add a linear phase `phase_shift` / `mfft` * `f` to each
            frequency `f`. The default value 0 ensures that there is no phase
            shift on the zeroth slice (in which t=0 is centered). See property
            `phase_shift` for more details.

        Examples
        --------
        The following instances ``SFT0`` and ``SFT1`` are equivalent:

        >>> from scipy.signal import ShortTimeFFT, get_window
        >>> nperseg = 9  # window length
        >>> w = get_window(('gaussian', 2.), nperseg)
        >>> fs = 128  # sampling frequency
        >>> hop = 3  # increment of STFT time slice
        >>> SFT0 = ShortTimeFFT(w, hop, fs=fs)
        >>> SFT1 = ShortTimeFFT.from_window(('gaussian', 2.), fs, nperseg,
        ...                                 noverlap=nperseg-hop)

        See Also
        --------
        scipy.signal.get_window: Return a window of a given length and type.
        from_dual: Create instance using dual window.
        ShortTimeFFT: Create instance using standard initializer.
        )fftbins)r*   rR   rE   rF   rH   rI   r   )rV   	win_paramrR   npersegnoverlaprX   rE   rF   rH   rI   r)   s              r/   from_windowzShortTimeFFT.from_windowg  s9    N G5FG3GH,hx[J 	Jr1   c                    | j                   S )a8  Window function as real- or complex-valued 1d array.

        This attribute is read only, since `dual_win` depends on it.

        See Also
        --------
        dual_win: Canonical dual window.
        m_num: Number of samples in window `win`.
        m_num_mid: Center index of window `win`.
        mfft: Length of input for the FFT used - may be larger than `m_num`.
        hop: ime increment in signal samples for sliding window.
        win: Window function as real- or complex-valued 1d array.
        ShortTimeFFT: Class this property belongs to.
        )r4   rS   s    r/   r)   zShortTimeFFT.win        yyr1   c                    | j                   S )aB  Time increment in signal samples for sliding window.

        This attribute is read only, since `dual_win` depends on it.

        See Also
        --------
        delta_t: Time increment of STFT (``hop*T``)
        m_num: Number of samples in window `win`.
        m_num_mid: Center index of window `win`.
        mfft: Length of input for the FFT used - may be larger than `m_num`.
        T: Sampling interval of input signal and of the window.
        win: Window function as real- or complex-valued 1d array.
        ShortTimeFFT: Class this property belongs to.
        )r8   r`   s    r/   r*   zShortTimeFFT.hop  ra   r1   c                     d| j                   z  S )a  Sampling interval of input signal and of the window.

        A ``ValueError`` is raised if it is set to a non-positive value.

        See Also
        --------
        delta_t: Time increment of STFT (``hop*T``)
        hop: Time increment in signal samples for sliding window.
        fs: Sampling frequency (being ``1/T``)
        t: Times of STFT for an input signal with `n` samples.
        ShortTimeFFT: Class this property belongs to.
        rK   r:   r`   s    r/   TzShortTimeFFT.T  s     488|r1   c                @    |dkD  st        d| d      d|z  | _        y)zSampling interval of input signal and of the window.

        A ``ValueError`` is raised if it is set to a non-positive value.
        r   zSampling interval T= must be positive!rK   Nr   r:   rS   vs     r/   re   zShortTimeFFT.T  s,     A3A36HIJJq5r1   c                    | j                   S )a  Sampling frequency of input signal and of the window.

        The sampling frequency is the inverse of the sampling interval `T`.
        A ``ValueError`` is raised if it is set to a non-positive value.

        See Also
        --------
        delta_t: Time increment of STFT (``hop*T``)
        hop: Time increment in signal samples for sliding window.
        T: Sampling interval of input signal and of the window (``1/fs``).
        ShortTimeFFT: Class this property belongs to.
        rd   r`   s    r/   rR   zShortTimeFFT.fs  s     xxr1   c                :    |dkD  st        d| d      || _        y)zSampling frequency of input signal and of the window.

        The sampling frequency is the inverse of the sampling interval `T`.
        A ``ValueError`` is raised if it is set to a non-positive value.
        r   zSampling frequency fs=rg   Nrh   ri   s     r/   rR   zShortTimeFFT.fs   s(     A5aS8JKLLr1   c                    | j                   S )a  Mode of utilized FFT ('twosided', 'centered', 'onesided' or
        'onesided2X').

        It can have the following values:

        'twosided':
            Two-sided FFT, where values for the negative frequencies are in
            upper half of the array. Corresponds to :func:`~scipy.fft.fft()`.
        'centered':
            Two-sided FFT with the values being ordered along monotonically
            increasing frequencies. Corresponds to applying
            :func:`~scipy.fft.fftshift()` to :func:`~scipy.fft.fft()`.
        'onesided':
            Calculates only values for non-negative frequency values.
            Corresponds to :func:`~scipy.fft.rfft()`.
        'onesided2X':
            Like `onesided`, but the non-zero frequencies are doubled if
            `scaling` is set to 'magnitude' or multiplied by ``sqrt(2)`` if
            set to 'psd'. If `scaling` is ``None``, setting `fft_mode` to
            `onesided2X` is not allowed.
            If the FFT length `mfft` is even, the last FFT value is not paired,
            and thus it is not scaled.

        Note that `onesided` and `onesided2X` do not work for complex-valued signals or
        complex-valued windows. Furthermore, the frequency values can be obtained by
        reading the `f` property, and the number of samples by accessing the `f_pts`
        property.

        See Also
        --------
        delta_f: Width of the frequency bins of the STFT.
        f: Frequencies values of the STFT.
        f_pts: Width of the frequency bins of the STFT.
        onesided_fft: True if a one-sided FFT is used.
        scaling: Normalization applied to the window function
        ShortTimeFFT: Class this property belongs to.
        )r<   r`   s    r/   rE   zShortTimeFFT.fft_mode  s    N ~~r1   c                   |t        t              x}vrt        d| d| d      |dv r1t        j                  | j
                        rt        d| ddz         |dk(  r| j                  t        d
| d      || _        y	)zSet mode of FFT.

        Allowed values are 'twosided', 'centered', 'onesided', 'onesided2X'.
        See the property `fft_mode` for more details.
        z
fft_mode='z	' not in rL      r   r   z#One-sided spectra, i.e., fft_mode='z', z+are not allowed for complex-valued windows!r   NzFor scaling is None, fft_mode='z9' is invalid!Do scale_to('psd') or scale_to('magnitude')!)r	   r;   r   r   iscomplexobjr)   scalingr<   )rS   tfft_mode_typess      r/   rE   zShortTimeFFT.fft_mode4  s     x'>>^?z!In5EQGHH**rtxx/HB1#SIJK L L !5>qc BL L M Mr1   c                    | j                   S )a  Length of input for the FFT used - may be larger than window
        length `m_num`.

        If not set, `mfft` defaults to the window length `m_num`.

        See Also
        --------
        f_pts: Number of points along the frequency axis.
        f: Frequencies values of the STFT.
        m_num: Number of samples in window `win`.
        ShortTimeFFT: Class this property belongs to.
        )r=   r`   s    r/   rF   zShortTimeFFT.mfftG  s     zzr1   c                p    || j                   k\  s t        d| dd| j                    dz         || _        y)zeSetter for the length of FFT utilized.

        See the property `mfft` for further details.
        zAttribute mfft=z needs to be at least the zwindow length m_num=rL   N)m_numr   r=   )rS   n_s     r/   rF   zShortTimeFFT.mfftW  sH     djj rd2LM3DJJ<qAB C C
r1   c                    | j                   S )a  Normalization applied to the window function
        ('magnitude', 'psd' or ``None``).

        If not ``None``, the FFTs can be either interpreted as a magnitude or
        a power spectral density spectrum.

        The window function can be scaled by calling the `scale_to` method,
        or it is set by the initializer parameter ``scale_to``.

        See Also
        --------
        fac_magnitude: Scaling factor for to a magnitude spectrum.
        fac_psd: Scaling factor for to  a power spectral density spectrum.
        fft_mode: Mode of utilized FFT
        scale_to: Scale window to obtain 'magnitude' or 'psd' scaling.
        ShortTimeFFT: Class this property belongs to.
        )r?   r`   s    r/   rq   zShortTimeFFT.scalingb  s    & }}r1   c                &   |ddhx}vrt        d|d| d      | j                  |k(  ry|dk(  r| j                  n| j                  }| j                  |z  | _        | j
                  | j
                  |z  | _        d\  | _        | _        || _        y)av  Scale window to obtain 'magnitude' or 'psd' scaling for the STFT.

        The window of a 'magnitude' spectrum has an integral of one, i.e., unit
        area for non-negative windows. This ensures that absolute the values of
        spectrum does not change if the length of the window changes (given
        the input signal is stationary).

        To represent the power spectral density ('psd') for varying length
        windows the area of the absolute square of the window needs to be
        unity.

        The `scaling` property shows the current scaling. The properties
        `fac_magnitude` and `fac_psd` show the scaling factors required to
        scale the STFT values to a magnitude or a psd spectrum.

        This method is called, if the initializer parameter `scale_to` is set.

        See Also
        --------
        fac_magnitude: Scaling factor for to  a magnitude spectrum.
        fac_psd: Scaling factor for to  a power spectral density spectrum.
        fft_mode: Mode of utilized FFT
        scaling: Normalization applied to the window function.
        ShortTimeFFT: Class this method belongs to.
        	magnitudepsdzscaling= not in rL   NNN)r   r?   fac_psdfac_magnituder4   r6   rB   rC   )rS   rq   scaling_valuess_facs       r/   rH   zShortTimeFFT.scale_tow  s    4 k5-AA>Bz.1ACDD==G# '5 0d6H6HII%	>>%!^^e3DN'1$t}r1   c                    | j                   S )a  If set, add linear phase `phase_shift` / `mfft` * `f` to each FFT
        slice of frequency `f`.

        Shifting (more precisely `rolling`) an `mfft`-point FFT input by
        `phase_shift` samples results in a multiplication of the output by
        ``np.exp(2j*np.pi*q*phase_shift/mfft)`` at the frequency q * `delta_f`.

        The default value 0 ensures that there is no phase shift on the
        zeroth slice (in which t=0 is centered).
        No phase shift (``phase_shift is None``) is equivalent to
        ``phase_shift = -mfft//2``. In this case slices are not shifted
        before calculating the FFT.

        The absolute value of `phase_shift` is limited to be less than `mfft`.

        See Also
        --------
        delta_f: Width of the frequency bins of the STFT.
        f: Frequencies values of the STFT.
        mfft: Length of input for the FFT used
        ShortTimeFFT: Class this property belongs to.
        )rA   r`   s    r/   rI   zShortTimeFFT.phase_shift  s    0    r1   c                    ||| _         yt        |t              st        d| ddz         | j                   |cxk  r| j                  k  s!n t        dd| j                   d| dz         || _         y)	zThe absolute value of the phase shift needs to be less than mfft
        samples.

        See the `phase_shift` getter method for more details.
        Nzphase_shift=z has the unit samples. Hence z(it needs to be an int or it may be None!z)-mfft < phase_shift < mfft does not hold z	for mfft=z, phase_shift=rL   )rA   rQ   r7   r   rF   ri   s     r/   rI   zShortTimeFFT.phase_shift  s     9 !D!S!|A3.KLGH I I
Q**H(>!AFG H Hr1   c              #    K   |t        t              x}vrt        d|d| d      t        dd      t        d      t        d	d
      t        d	d      d}|j                  d   ||z
  | j
                  z  }	}|| j
                  z  | j                  z
  |z   }
|
|	z   | j                  z   }t        |
d      t        ||      }}dg|j                  dz
  z  t        |
d       t        ||z
  d      fgz   }t        j                  |d||f   |fi ||   }t        d|	| j
                        D ]  }|d||| j                  z   f     yw)zGenerate signal slices along last axis of `x`.

        This method is only used by `stft_detrend`. The parameters are
        described in `~ShortTimeFFT.stft`.
        zParameter padding=r|   rL   constantr   r   )modeconstant_valuesr   )r   reflectr   )r   reflect_typer   r   r   rK   .N)r	   PAD_TYPEr   dictrO   r*   	m_num_midrv   r'   minrM   r   padr$   )rS   xk_offp0p1paddingpadding_typespad_kwsnn1k0k1i0i1	pad_widthx1r-   s                    r/   	_x_sliceszShortTimeFFT._x_slices  sV     HX,>>=?2'8M?!LMMz6Bf%if=YU;	$ b2g12$((]T^^+e3"Wtzz!RSQZBHq)s2qzk3rAvq>-J,KK	VVAc2b5jM9A0@A2txx( 	.BS"R$**_,,--	.s   E	Er   r   k_offsetr   axisc          	     2    | j                  |d|||||      S )a{	  Perform the short-time Fourier transform.

        A two-dimensional matrix with ``p1-p0`` columns is calculated.
        The `f_pts` rows represent value at the frequencies `f`. The q-th
        column of the windowed FFT with the window `win` is centered at t[q].
        The columns represent the values at the frequencies `f`.

        Parameters
        ----------
        x
            The input signal as real or complex valued array. For complex values, the
            property `fft_mode` must be set to 'twosided' or 'centered'.
        p0
            The first element of the range of slices to calculate. If ``None``
            then it is set to :attr:`p_min`, which is the smallest possible
            slice.
        p1
            The end of the array. If ``None`` then `p_max(n)` is used.
        k_offset
            Index of first sample (t = 0) in `x`.
        padding
            Kind of values which are added, when the sliding window sticks out
            on either the lower or upper end of the input `x`. Zeros are added
            if the default 'zeros' is set. For 'edge' either the first or the
            last value of `x` is used. 'even' pads by reflecting the
            signal on the first or last sample and 'odd' additionally
            multiplies it with -1.
        axis
            The axis of `x` over which to compute the STFT.
            If not given, the last axis is used.

        Returns
        -------
        S
            A complex array is returned with the dimension always being larger
            by one than of `x`. The last axis always represent the time slices
            of the STFT. `axis` defines the frequency axis (default second to
            last). E.g., for a one-dimensional `x`, a complex 2d array is
            returned, with axis 0 representing frequency and axis 1 the time
            slices.

        See Also
        --------
        delta_f: Width of the frequency bins of the STFT.
        delta_t: Time increment of STFT
        f: Frequencies values of the STFT.
        invertible: Check if STFT is invertible.
        :meth:`~ShortTimeFFT.istft`: Inverse short-time Fourier transform.
        p_range: Determine and validate slice index range.
        stft_detrend: STFT with detrended segments.
        t: Times of STFT for an input signal with `n` samples.
        :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
        Nr   )stft_detrend)rS   r   r   r   r   r   r   s          r/   stftzShortTimeFFT.stft  s,    r   D"b8)0t ! = 	=r1   c          	        | j                   r.t        j                  |      rt        d| j                  d      t        |t              rt        t        |      }n|t        |      st        d|ddz         |j                  |   }|| j                  | j                  z
  x}	k\  s@|j                  dk(  rd	t        |      nd
|d|j                   }
t        |
 d|	 d      |j                  dkD  rt        j                  ||d      }| j!                  |||      \  }}| j"                  ||z
  f}|j                  dkD  r|j                  dd |z   n|}t        j$                  |t&              }t)        | j+                  |||||            D ]C  \  }}| ||      }| j-                  || j.                  j1                         z        |ddd|f<   E |j                  dkD  r%t        j                  |d|dk\  r|      S |dz
        S |S )a  Short-time Fourier transform with a trend being subtracted from each
        segment beforehand.

        If `detr` is set to 'constant', the mean is subtracted, if set to
        "linear", the linear trend is removed. This is achieved by calling
        :func:`scipy.signal.detrend`. If `detr` is a function, `detr` is
        applied to each segment.
        All other parameters have the same meaning as in `~ShortTimeFFT.stft`.

        Note that due to the detrending, the original signal cannot be
        reconstructed by the `~ShortTimeFFT.istft`.

        See Also
        --------
        invertible: Check if STFT is invertible.
        :meth:`~ShortTimeFFT.istft`: Inverse short-time Fourier transform.
        :meth:`~ShortTimeFFT.stft`: Short-time Fourier transform
                                   (without detrending).
        :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
        z1Complex-valued `x` not allowed for self.fft_mode=z7'! Set property `fft_mode` to 'twosided' or 'centered'.)r   NzParameter detr=z is not a str, function or zNone!rK   zlen(x)=zof axis=z of z must be >= ceil(m_num/2) = rL   r   r   .r   )onesided_fftr   rp   r   rE   rQ   strr   r   callablerO   rv   r   rM   r   moveaxisp_rangef_ptsr   complex	enumerater   	_fft_funcr)   conj)rS   r   detrr   r   r   r   r   r   m2pe_str
S_shape_1dS_shapeSp_x_s                   r/   r   zShortTimeFFT.stft_detrend!  s   4 !3Q4==BR ST T U UdC 7.D,(4./$0KL$% & &GGDMTZZ66c7$%FFaKws1viLy4'aggY5OEw&B3%qIJJ66A:AtR(AaR(Bjj"r'*
/0vvz!''#2,+zHHWG,q(BG LM 	AFB"X NN2+?@Ac1bjM	A 66A:;;q"daidDDT!VDDr1   )r   r   r   r   r   c          	         | j                  |||||||      }	|||u r|	j                  dz  |	j                  dz  z   S | j                  |||||||      }
|	|
j                         z  S )a   Calculate spectrogram or cross-spectrogram.

        The spectrogram is the absolute square of the STFT, i.e, it is
        ``abs(S[q,p])**2`` for given ``S[q,p]``  and thus is always
        non-negative.
        For two STFTs ``Sx[q,p], Sy[q,p]``, the cross-spectrogram is defined
        as ``Sx[q,p] * np.conj(Sx[q,p])`` and is complex-valued.
        This is a convenience function for calling `~ShortTimeFFT.stft` /
        `stft_detrend`, hence all parameters are discussed there. If `y` is not
        ``None`` it needs to have the same shape as `x`.

        Examples
        --------
        The following example shows the spectrogram of a square wave with
        varying frequency :math:`f_i(t)` (marked by a green dashed line in the
        plot) sampled with 20 Hz:

        >>> import matplotlib.pyplot as plt
        >>> import numpy as np
        >>> from scipy.signal import square, ShortTimeFFT
        >>> from scipy.signal.windows import gaussian
        ...
        >>> T_x, N = 1 / 20, 1000  # 20 Hz sampling rate for 50 s signal
        >>> t_x = np.arange(N) * T_x  # time indexes for signal
        >>> f_i = 5e-3*(t_x - t_x[N // 3])**2 + 1  # varying frequency
        >>> x = square(2*np.pi*np.cumsum(f_i)*T_x)  # the signal

        The utitlized Gaussian window is 50 samples or 2.5 s long. The
        parameter ``mfft=800`` (oversampling factor 16) and the `hop` interval
        of 2 in `ShortTimeFFT` was chosen to produce a sufficient number of
        points:

        >>> g_std = 12  # standard deviation for Gaussian window in samples
        >>> win = gaussian(50, std=g_std, sym=True)  # symmetric Gaussian wind.
        >>> SFT = ShortTimeFFT(win, hop=2, fs=1/T_x, mfft=800, scale_to='psd')
        >>> Sx2 = SFT.spectrogram(x)  # calculate absolute square of STFT

        The plot's colormap is logarithmically scaled as the power spectral
        density is in dB. The time extent of the signal `x` is marked by
        vertical dashed lines and the shaded areas mark the presence of border
        effects:

        >>> fig1, ax1 = plt.subplots(figsize=(6., 4.))  # enlarge plot a bit
        >>> t_lo, t_hi = SFT.extent(N)[:2]  # time range of plot
        >>> ax1.set_title(rf"Spectrogram ({SFT.m_num*SFT.T:g}$\,s$ Gaussian " +
        ...               rf"window, $\sigma_t={g_std*SFT.T:g}\,$s)")
        >>> ax1.set(xlabel=f"Time $t$ in seconds ({SFT.p_num(N)} slices, " +
        ...                rf"$\Delta t = {SFT.delta_t:g}\,$s)",
        ...         ylabel=f"Freq. $f$ in Hz ({SFT.f_pts} bins, " +
        ...                rf"$\Delta f = {SFT.delta_f:g}\,$Hz)",
        ...         xlim=(t_lo, t_hi))
        >>> Sx_dB = 10 * np.log10(np.fmax(Sx2, 1e-4))  # limit range to -40 dB
        >>> im1 = ax1.imshow(Sx_dB, origin='lower', aspect='auto',
        ...                  extent=SFT.extent(N), cmap='magma')
        >>> ax1.plot(t_x, f_i, 'g--', alpha=.5, label='$f_i(t)$')
        >>> fig1.colorbar(im1, label='Power Spectral Density ' +
        ...                          r"$20\,\log_{10}|S_x(t, f)|$ in dB")
        ...
        >>> # Shade areas where window slices stick out to the side:
        >>> for t0_, t1_ in [(t_lo, SFT.lower_border_end[0] * SFT.T),
        ...                  (SFT.upper_border_begin(N)[0] * SFT.T, t_hi)]:
        ...     ax1.axvspan(t0_, t1_, color='w', linewidth=0, alpha=.3)
        >>> for t_ in [0, N * SFT.T]:  # mark signal borders with vertical line
        ...     ax1.axvline(t_, color='c', linestyle='--', alpha=0.5)
        >>> ax1.legend()
        >>> fig1.tight_layout()
        >>> plt.show()

        The logarithmic scaling reveals the odd harmonics of the square wave,
        which are reflected at the Nyquist frequency of 10 Hz. This aliasing
        is also the main source of the noise artifacts in the plot.


        See Also
        --------
        :meth:`~ShortTimeFFT.stft`: Perform the short-time Fourier transform.
        stft_detrend: STFT with a trend subtracted from each segment.
        :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
        r   r   )r   r!   r"   r   )rS   r   yr   r   r   r   r   r   SxSys              r/   spectrogramzShortTimeFFT.spectrogramW  s    l q$B'.T  ;9Q77A:
**q$B'.T  ;BGGI~r1   c                |    | j                   %t        | j                  | j                        | _         | j                   S )a  Canonical dual window.

        A STFT can be interpreted as the input signal being expressed as a
        weighted sum of modulated and time-shifted dual windows. Note that for
        a given window there exist many dual windows. The canonical window is
        the one with the minimal energy (i.e., :math:`L_2` norm).

        `dual_win` has same length as `win`, namely `m_num` samples.

        If the dual window cannot be calculated a ``ValueError`` is raised.
        This attribute is read only and calculated lazily.

        See Also
        --------
        dual_win: Canonical dual window.
        m_num: Number of samples in window `win`.
        win: Window function as real- or complex-valued 1d array.
        ShortTimeFFT: Class this property belongs to.
        )r6   r0   r)   r*   r`   s    r/   rG   zShortTimeFFT.dual_win  s.    * >>!8488LDN~~r1   c                R    	 t        | j                        dkD  S # t        $ r Y yw xY w)a  Check if STFT is invertible.

        This is achieved by trying to calculate the canonical dual window.

        See Also
        --------
        :meth:`~ShortTimeFFT.istft`: Inverse short-time Fourier transform.
        m_num: Number of samples in window `win` and `dual_win`.
        dual_win: Canonical dual window.
        win: Window for STFT.
        ShortTimeFFT: Class this property belongs to.
        r   F)r   rG   r   r`   s    r/   
invertiblezShortTimeFFT.invertible  s-    	t}}%)) 		s    	&&r   )f_axist_axisc          	     t   ||k(  rt        d|d|d      |j                  |   | j                  k7  r:t        d|j                  |   dd| j                  d|j                  dz         | j                  | j                  z
  }|j                  |   | j                  |      x}k\  s/t        d	|j                  |   d
| d|j                  dz         ||j                  dz
  k7  s||j                  dz
  k7  rE|dk  r|j                  |z   n|}|dk  r|j                  |z   n|}t        j                  |||fd      }|j                  d   | j                  z   }|dz
  | j                  z  | j                  z   | j                  z
  }	||	n|}| j                  |cxk  r|cxk  r|	k  s(n t        d| j                  d|d|dd|	dz         ||z
  x}
|k\  st        d|d|d|
 dd| dz         |dk\  r|| j                  z  | j                  z   n|| j                  z  }t        | j                  |      |      }| j                  |      | j                  |d      }}||z
  | j                  z   | j                  z
  }t        j                  |j                  dd |fz   | j                   rt"        nt$               }t'        ||      D ]  }| j)                  |d!dd|| j                  z
  f         | j*                  z  }|| j                  z  | j                  z
  }t        || j                  z   ||z         }d||z
  }}||k  r
|||z
  z  }|}|d!||z
  ||z
  fxx   |d!||f   z  cc<    |d!d||z
  f   }|j                  dkD  r(t        j                  |d||j                  k  r|n|      }|S )"a  Inverse short-time Fourier transform.

        It returns an array of dimension ``S.ndim - 1``  which is real
        if `onesided_fft` is set, else complex. If the STFT is not
        `invertible`, or the parameters are out of bounds  a ``ValueError`` is
        raised.

        Parameters
        ----------
        S
            A complex valued array where `f_axis` denotes the frequency
            values and the `t-axis` dimension the temporal values of the
            STFT values.
        k0, k1
            The start and the end index of the reconstructed signal. The
            default (``k0 = 0``, ``k1 = None``) assumes that the maximum length
            signal should be reconstructed.
        f_axis, t_axis
            The axes in `S` denoting the frequency and the time dimension.

        Notes
        -----
        It is required that `S` has `f_pts` entries along the `f_axis`. For
        the `t_axis` it is assumed that the first entry corresponds to
        `p_min` * `delta_t` (being <= 0). The length of `t_axis` needs to be
        compatible with `k1`. I.e., ``S.shape[t_axis] >= self.p_max(k1)`` must
        hold, if `k1` is not ``None``. Else `k1` is set to `k_max` with::

            q_max = S.shape[t_range] + self.p_min
            k_max = (q_max - 1) * self.hop + self.m_num - self.m_num_mid

        The :ref:`tutorial_stft` section of the :ref:`user_guide` discussed the
        slicing behavior by means of an example.

        See Also
        --------
        invertible: Check if STFT is invertible.
        :meth:`~ShortTimeFFT.stft`: Perform Short-time Fourier transform.
        :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
        zf_axis=z may not be equal to t_axis=rL   zS.shape[f_axis]=z must be equal to zself.f_pts=z
 (S.shape=z)!zS.shape[t_axis]=z needs to have at least z slices (S.shape=rK   r   r   )r   r   r   Nz(self.k_min=z	) <= (k0=z) < (k1=z) <= z(k_max=z) is false!z(k1=z) - (k0=z) = z has to be at z!least the half the window length F)leftr   r   .)r   rO   r   rv   r   p_numrM   r   r   p_minr*   k_minr   p_maxnearest_k_pr   r   r9   r   r$   
_ifft_funcrG   )rS   r   r   r   r   r   n_minq_numq_maxk_maxnum_ptsq0q1k_q0k_q1n_ptsr   q_xsr   r   j0j1s                          r/   istftzShortTimeFFT.istft  s   V Vy(EfYaHII776?djj( 011CD +

}Kqwwj;< = =

4>>)TZZ->$>E? 011IJ %w&8z<= > >QVVaZ6QVVaZ#7(.
QVVf_F(.
QVVf_FA/:Adjj(dhh&3dnnDjUb

b.2..}ZB5	bU%H'45 6 67"u,uY2%tG9NK@qIJ K K .01WbDHHntzz)DHHn 	B'%%b)4+;+;BU+;+Kdtdjj(4>>9HHQWWSb\UH,$($5$557DB- 	2B32

?#:!;<t}}LBdhh/BR$**_eBh/BRBBwb2gc2b5B;2c2b5j>1	2 c6BrE6kN66A:ArVaff_6&IAr1   c                    | j                   dk(  ry| j                  &dt        t        | j                              z  | _        | j                  S )a1  Factor to multiply the STFT values by to scale each frequency slice
        to a magnitude spectrum.

        It is 1 if attribute ``scaling == 'magnitude'``.
        The window can be scaled to a magnitude spectrum by using the method
        `scale_to`.

        See Also
        --------
        fac_psd: Scaling factor for to a power spectral density spectrum.
        scale_to: Scale window to obtain 'magnitude' or 'psd' scaling.
        scaling: Normalization applied to the window function.
        ShortTimeFFT: Class this property belongs to.
        rz   rK   )rq   rB   abssumr)   r`   s    r/   r   zShortTimeFFT.fac_magnitude;  s@      <<;&== CM 22DM}}r1   c                   | j                   dk(  ry| j                  ddt        j                  t	        | j
                  j                  dz  | j
                  j                  dz  z         | j                  z        z  | _        | j                  S )a(  Factor to multiply the STFT values by to scale each frequency slice
        to a power spectral density (PSD).

        It is 1 if attribute ``scaling == 'psd'``.
        The window can be scaled to a psd spectrum by using the method
        `scale_to`.

        See Also
        --------
        fac_magnitude: Scaling factor for to a magnitude spectrum.
        scale_to: Scale window to obtain 'magnitude' or 'psd' scaling.
        scaling: Normalization applied to the window function.
        ShortTimeFFT: Class this property belongs to.
        r{   rK   r   )	rq   rC   r   sqrtr   r)   r!   r"   re   r`   s    r/   r~   zShortTimeFFT.fac_psdQ  sp      <<5 == DHHMM1$TXX]]A%556?!A ADM}}r1   c                ,    t        | j                        S )a  Number of samples in window `win`.

        Note that the FFT can be oversampled by zero-padding. This is achieved
        by setting the `mfft` property.

        See Also
        --------
        m_num_mid: Center index of window `win`.
        mfft: Length of input for the FFT used - may be larger than `m_num`.
        hop: Time increment in signal samples for sliding window.
        win: Window function as real- or complex-valued 1d array.
        ShortTimeFFT: Class this property belongs to.
        )r   r)   r`   s    r/   rv   zShortTimeFFT.m_numh  s     488}r1   c                     | j                   dz  S )a  Center index of window `win`.

        For odd `m_num`, ``(m_num - 1) / 2`` is returned and
        for even `m_num` (per definition) ``m_num / 2`` is returned.

        See Also
        --------
        m_num: Number of samples in window `win`.
        mfft: Length of input for the FFT used - may be larger than `m_num`.
        hop: ime increment in signal samples for sliding window.
        win: Window function as real- or complex-valued 1d array.
        ShortTimeFFT: Class this property belongs to.
        r   )rv   r`   s    r/   r   zShortTimeFFT.m_num_midy  s     zzQr1   c                |   | j                   j                  dz  | j                   j                  dz  z   }| j                   }t	        t        ||| j                  z
  dz
  | j                               D ]>  \  }}|| j                  z
  }|| j                  z   dk  st        ||d dk(        s9|| fc S  t        d      )zSmallest signal index and slice index due to padding.

         Since, per convention, for time t=0, n,q is zero, the returned values
         are negative or zero.
         r   rK   r   N/This is code line should not have been reached!)
r)   r!   r"   r   r   r$   rv   r*   r(   RuntimeError)rS   r+   n0r   rw   n_nexts         r/   _pre_paddingzShortTimeFFT._pre_padding  s     XX]]Aq 00nn_b"TZZ-/DHH9 EF 	FB$((]F

"a'3r&'{a/?+@B3w	 LMMr1   c                (    | j                         d   S )a  The smallest possible signal index of the STFT.

        `k_min` is the index of the left-most non-zero value of the lowest
        slice `p_min`. Since the zeroth slice is centered over the zeroth
        sample of the input signal, `k_min` is never positive.
        A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
        section of the :ref:`user_guide`.

        See Also
        --------
        k_max: First sample index after signal end not touched by a time slice.
        lower_border_end: Where pre-padding effects end.
        p_min: The smallest possible slice index.
        p_max: Index of first non-overlapping upper time slice.
        p_num: Number of time slices, i.e., `p_max` - `p_min`.
        p_range: Determine and validate slice index range.
        upper_border_begin: Where post-padding effects start.
        ShortTimeFFT: Class this property belongs to.
        r   r   r`   s    r/   r   zShortTimeFFT.k_min  s    *   "1%%r1   c                (    | j                         d   S )a  The smallest possible slice index.

        `p_min` is the index of the left-most slice, where the window still
        sticks into the signal, i.e., has non-zero part for t >= 0.
        `k_min` is the smallest index where the window function of the slice
        `p_min` is non-zero.

        Since, per convention the zeroth slice is centered at t=0,
        `p_min` <= 0 always holds.
        A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
        section of the :ref:`user_guide`.

        See Also
        --------
        k_min: The smallest possible signal index.
        k_max: First sample index after signal end not touched by a time slice.
        p_max: Index of first non-overlapping upper time slice.
        p_num: Number of time slices, i.e., `p_max` - `p_min`.
        p_range: Determine and validate slice index range.
        ShortTimeFFT: Class this property belongs to.
        rK   r   r`   s    r/   r   zShortTimeFFT.p_min  s    .   "1%%r1      )maxsizec                   | j                   j                  dz  | j                   j                  dz  z   }|| j                  z  }|| j                  z  | j                  z
  }t        t        ||| j                  z   | j                        |      D ]C  \  }}|| j                  z   }||k\  st        |d||z
   dk(        s/|| j                  z   |dz   fc S  t        d      )z4Largest signal index and slice index due to padding.r   )startNr   rK   r   )
r)   r!   r"   r*   r   r   r$   rv   r(   r   )rS   r   r+   r   r   r   r-   r   s           r/   _post_paddingzShortTimeFFT._post_padding  s     XX]]Aq 00$((]$((]T^^+b!DJJ, AL 	/FB$((]F{c"Yah-1"45DJJQ..	/ LMMr1   c                *    | j                  |      d   S )a  First sample index after signal end not touched by a time slice.

        `k_max` - 1 is the largest sample index of the slice `p_max` for a
        given input signal of `n` samples.
        A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
        section of the :ref:`user_guide`.

        See Also
        --------
        k_min: The smallest possible signal index.
        p_min: The smallest possible slice index.
        p_max: Index of first non-overlapping upper time slice.
        p_num: Number of time slices, i.e., `p_max` - `p_min`.
        p_range: Determine and validate slice index range.
        ShortTimeFFT: Class this method belongs to.
        r   r   rS   r   s     r/   r   zShortTimeFFT.k_max  s    " !!!$Q''r1   c                *    | j                  |      d   S )a  Index of first non-overlapping upper time slice for `n` sample
        input.

        Note that center point t[p_max] = (p_max(n)-1) * `delta_t` is typically
        larger than last time index t[n-1] == (`n`-1) * `T`. The upper border
        of samples indexes covered by the window slices is given by `k_max`.
        Furthermore, `p_max` does not denote the number of slices `p_num` since
        `p_min` is typically less than zero.
        A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
        section of the :ref:`user_guide`.

        See Also
        --------
        k_min: The smallest possible signal index.
        k_max: First sample index after signal end not touched by a time slice.
        p_min: The smallest possible slice index.
        p_num: Number of time slices, i.e., `p_max` - `p_min`.
        p_range: Determine and validate slice index range.
        ShortTimeFFT: Class this method belongs to.
        rK   r   r   s     r/   r   zShortTimeFFT.p_max  s    * !!!$Q''r1   c                >    | j                  |      | j                  z
  S )a  Number of time slices for an input signal with `n` samples.

        It is given by `p_num` = `p_max` - `p_min` with `p_min` typically
        being negative.
        A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
        section of the :ref:`user_guide`.

        See Also
        --------
        k_min: The smallest possible signal index.
        k_max: First sample index after signal end not touched by a time slice.
        lower_border_end: Where pre-padding effects end.
        p_min: The smallest possible slice index.
        p_max: Index of first non-overlapping upper time slice.
        p_range: Determine and validate slice index range.
        upper_border_begin: Where post-padding effects start.
        ShortTimeFFT: Class this method belongs to.
        )r   r   r   s     r/   r   zShortTimeFFT.p_num  s    & zz!}tzz))r1   c                   | j                   | j                   S t        j                  | j                  j                  dz  | j                  j
                  dz  z         d   }| j                   |z   }t        t        || j                  dz   | j                              D ]>  \  }}|| j                  z   dk\  s|| j                  z   |dz   f| _         | j                   c S  dt        | j                  d      f| _         | j                   S )ao  First signal index and first slice index unaffected by pre-padding.

        Describes the point where the window does not stick out to the left
        of the signal domain.
        A detailed example is provided in the :ref:`tutorial_stft_sliding_win`
        section of the :ref:`user_guide`.

        See Also
        --------
        k_min: The smallest possible signal index.
        k_max: First sample index after signal end not touched by a time slice.
        lower_border_end: Where pre-padding effects end.
        p_min: The smallest possible slice index.
        p_max: Index of first non-overlapping upper time slice.
        p_num: Number of time slices, i.e., `p_max` - `p_min`.
        p_range: Determine and validate slice index range.
        upper_border_begin: Where post-padding effects start.
        ShortTimeFFT: Class this property belongs to.
        r   r   rK   )rD   r   flatnonzeror)   r!   r"   r   r   r$   r*   rv   r'   r   )rS   m0r   r   r-   s        r/   lower_border_endzShortTimeFFT.lower_border_end  s    , !!-))) ^^DHHMM1,txx}}a/??@C nn_r!b$((Q, AB 	.FBDHH}!*,tzz/26)B&---	. #$SQ%7!8%%%r1   c                   | j                   j                  dz  | j                   j                  dz  z   }|| j                  z  dz   }t	        || j
                  z
  | j                  z  dz
  d      }t        ||d      D ]j  }|| j                  z  | j
                  | j                  z
  z   }||k  st        |||z
  d dk(        sF|dz   | j                  z  | j                  z
  |dz   fc S  y)a'  First signal index and first slice index affected by post-padding.

        Describes the point where the window does begin stick out to the right
        of the signal domain.
        A detailed example is given :ref:`tutorial_stft_sliding_win` section
        of the :ref:`user_guide`.

        See Also
        --------
        k_min: The smallest possible signal index.
        k_max: First sample index after signal end not touched by a time slice.
        lower_border_end: Where pre-padding effects end.
        p_min: The smallest possible slice index.
        p_max: Index of first non-overlapping upper time slice.
        p_num: Number of time slices, i.e., `p_max` - `p_min`.
        p_range: Determine and validate slice index range.
        ShortTimeFFT: Class this method belongs to.
        r   rK   r   Nr   r   )	r)   r!   r"   r*   r'   rv   r$   r   r(   )rS   r   r+   q2r   r   r-   s          r/   upper_border_beginzShortTimeFFT.upper_border_begin?  s    ( XX]]Aq 00$((]Q!DJJ,488+a/4B# 	DBdhh$**t~~"=>BAvR"Y!^,Q$((*T^^;R!VCC	D r1   c                4    | j                   | j                  z  S )a  Time increment of STFT.

        The time increment `delta_t` = `T` * `hop` represents the sample
        increment `hop` converted to time based on the sampling interval `T`.

        See Also
        --------
        delta_f: Width of the frequency bins of the STFT.
        hop: Hop size in signal samples for sliding window.
        t: Times of STFT for an input signal with `n` samples.
        T: Sampling interval of input signal and window `win`.
        ShortTimeFFT: Class this property belongs to
        )re   r*   r`   s    r/   delta_tzShortTimeFFT.delta_t]  s     vv  r1   c                    | j                  |      }|| j                  n|}||n|}| j                  |cxk  r|cxk  r|k  s/n t        d|d|dd| j                  d|dz   d|dz         ||fS )	a  Determine and validate slice index range.

        Parameters
        ----------
        n : int
            Number of samples of input signal, assuming t[0] = 0.
        p0 : int | None
            First slice index. If 0 then the first slice is centered at t = 0.
            If ``None`` then `p_min` is used. Note that p0 may be < 0 if
            slices are left of t = 0.
        p1 : int | None
            End of interval (last value is p1-1).
            If ``None`` then `p_max(n)` is used.


        Returns
        -------
        p0_ : int
            The fist slice index
        p1_ : int
            End of interval (last value is p1-1).

        Notes
        -----
        A ``ValueError`` is raised if ``p_min <= p0 < p1 <= p_max(n)`` does not
        hold.

        See Also
        --------
        k_min: The smallest possible signal index.
        k_max: First sample index after signal end not touched by a time slice.
        lower_border_end: Where pre-padding effects end.
        p_min: The smallest possible slice index.
        p_max: Index of first non-overlapping upper time slice.
        p_num: Number of time slices, i.e., `p_max` - `p_min`.
        upper_border_begin: Where post-padding effects start.
        ShortTimeFFT: Class this property belongs to.
        zInvalid Parameter p0=z, p1=z, i.e., zself.p_min=z <= p0 < p1 <= p_max= z"does not hold for signal length n=rL   )r   r   r   )rS   r   r   r   r   p0_p1_s          r/   r   zShortTimeFFT.p_rangen  s    P 

1JdjjBzer

c0C0505"fXF +

},BE81EFBt1EF G G Cxr1   rK   c                    | j                  |||      \  }}t        j                  ||      | j                  z  || j                  z  z   S )a?  Times of STFT for an input signal with `n` samples.

        Returns a 1d array with times of the `~ShortTimeFFT.stft` values with
        the same  parametrization. Note that the slices are
        ``delta_t = hop * T`` time units apart.

         Parameters
        ----------
        n
            Number of sample of the input signal.
        p0
            The first element of the range of slices to calculate. If ``None``
            then it is set to :attr:`p_min`, which is the smallest possible
            slice.
        p1
            The end of the array. If ``None`` then `p_max(n)` is used.
        k_offset
            Index of first sample (t = 0) in `x`.


        See Also
        --------
        delta_t: Time increment of STFT (``hop*T``)
        hop: Time increment in signal samples for sliding window.
        nearest_k_p: Nearest sample index k_p for which t[k_p] == t[p] holds.
        T: Sampling interval of input signal and of the window (``1/fs``).
        fs: Sampling frequency (being ``1/T``)
        ShortTimeFFT: Class this method belongs to.
        )r   r   aranger   re   )rS   r   r   r   r   s        r/   rr   zShortTimeFFT.t  sC    @ aR(ByyR 4<</(TVV2CCCr1   c                    t        || j                        \  }}|dk(  r|S |r|| j                  z  S |dz   | j                  z  S )af  Return nearest sample index k_p for which t[k_p] == t[p] holds.

        The nearest next smaller time sample p (where t[p] is the center
        position of the window of the p-th slice) is p_k = k // `hop`.
        If `hop` is a divisor of `k` than `k` is returned.
        If `left` is set than p_k * `hop` is returned else (p_k+1) * `hop`.

        This method can be used to slice an input signal into chunks for
        calculating the STFT and iSTFT incrementally.

        See Also
        --------
        delta_t: Time increment of STFT (``hop*T``)
        hop: Time increment in signal samples for sliding window.
        T: Sampling interval of input signal and of the window (``1/fs``).
        fs: Sampling frequency (being ``1/T``)
        t: Times of STFT for an input signal with `n` samples.
        ShortTimeFFT: Class this method belongs to.
        r   rK   )divmodr*   )rS   kr   p_q	remainders        r/   r   zShortTimeFFT.nearest_k_p  sF    (  488,Y>H!%sTXX~?C!Gtxx+??r1   c                :    d| j                   | j                  z  z  S )a  Width of the frequency bins of the STFT.

        Return the frequency interval `delta_f` = 1 / (`mfft` * `T`).

        See Also
        --------
        delta_t: Time increment of STFT.
        f_pts: Number of points along the frequency axis.
        f: Frequencies values of the STFT.
        mfft: Length of the input for FFT used.
        T: Sampling interval.
        t: Times of STFT for an input signal with `n` samples.
        ShortTimeFFT: Class this property belongs to.
        rK   )rF   re   r`   s    r/   delta_fzShortTimeFFT.delta_f  s      DII&''r1   c                V    | j                   r| j                  dz  dz   S | j                  S )a!  Number of points along the frequency axis.

        See Also
        --------
        delta_f: Width of the frequency bins of the STFT.
        f: Frequencies values of the STFT.
        mfft: Length of the input for FFT used.
        ShortTimeFFT: Class this property belongs to.
        r   rK   )r   rF   r`   s    r/   r   zShortTimeFFT.f_pts  s(     &*%6%6tyyA~!EDIIEr1   c                    | j                   dv S )a<  Return True if a one-sided FFT is used.

        Returns ``True`` if `fft_mode` is either 'onesided' or 'onesided2X'.

        See Also
        --------
        fft_mode: Utilized FFT ('twosided', 'centered', 'onesided' or
                 'onesided2X')
        ShortTimeFFT: Class this property belongs to.
        ro   )rE   r`   s    r/   r   zShortTimeFFT.onesided_fft  s     }} :::r1   c                   | j                   dv r*t        j                  | j                  | j                        S | j                   dk(  r*t        j
                  | j                  | j                        S | j                   dk(  r=t        j                  t        j
                  | j                  | j                              S t        t              }t        d| j                   d| d      )av  Frequencies values of the STFT.

        A 1d array of length `f_pts` with `delta_f` spaced entries is returned.

        See Also
        --------
        delta_f: Width of the frequency bins of the STFT.
        f_pts: Number of points along the frequency axis.
        mfft: Length of the input for FFT used.
        ShortTimeFFT: Class this property belongs to.
        ro   r   r   self.fft_mode=r|   rL   )
rE   fft_librfftfreqrF   re   fftfreqfftshiftr	   r;   r   )rS   	fft_modess     r/   fzShortTimeFFT.f  s     ==66##DIItvv66]]j(??499dff55]]j(##GOODIItvv$FGG]+	ndmm-Xi[BCCr1   c                F   | j                   |j                  d   | j                  k  rjt        |j                        }| j                  |j                  d   z
  |d<   t	        j
                  |t	        j                  ||j                        f      }| j                   | j                  z   | j                  z  }t	        j                  || d      }| j                  dk(  r"t        j                  || j                  d      S | j                  dk(  r7t        j                  t        j                  || j                  d      d      S | j                  d	k(  r"t        j                  || j                  d      S | j                  d
k(  rot        j                  || j                  d      }| j                   dk(  rt	        j"                  d      nd}|dd| j                  dz  dk(  rdndfxx   |z  cc<   |S t%        t&              }t)        d| j                  d| d      )zFFT based on the `fft_mode`, `mfft`, `scaling` and `phase_shift`
        attributes.

        For multidimensional arrays the transformation is carried out on the
        last axis.
        Nr   r   r   r   r   r   r   axesr   r   r{   r   .rK   r   r  r|   rL   )rI   rO   rF   listr   hstackr   r   r   rv   rollrE   r  fftr  rfftrq   r   r	   r;   r   )rS   r   z_shapep_sXfacr  s          r/   r   zShortTimeFFT._fft_func  s    'wwr{TYY&qww-"ii!''"+5IIq"((7!''"BCD##dnn4

BCC4b)A==J&;;qDIIB77==J&##GKK4992$FRPP==J&<<TYYR88==L(Q$))"5A $ 5"''!*1Cc1DIIMQ.bD889S@9H]+	ndmm-Xi[BCCr1   c                   | j                   dk(  r$t        j                  || j                  d      }n3| j                   dk(  r8t        j                  t        j                  |d      | j                  d      }n| j                   dk(  r#t        j
                  || j                  d      }n| j                   dk(  r|j                         }| j                  dk(  rt        j                  d	      nd	}| j                  d	z  d
k(  rdnd}|dd|fxx   |z  cc<   t        j
                  || j                  d      }n+d| j                   dt        t               d}t        |      | j                  |d| j                   S | j                  | j                  z   | j                  z  }t        j                   ||d      d| j                   S )a  Inverse to `_fft_func`.

        Returned is an array of length `m_num`. If the FFT is `onesided`
        then a float array is returned else a complex array is returned.
        For multidimensional arrays the transformation is carried out on the
        last axis.
        r   r   r  r   r  r   r   r{   r   r   N.rK   r  r|   rL   r  )rE   r  ifftrF   	ifftshiftirfftr#   rq   r   r   r	   r;   r   rI   rv   r   r  )rS   r#  r   Xcr$  r   	error_strr"  s           r/   r   zShortTimeFFT._ifft_func?  sm    ==J&Q$))"5A]]j(W..qr:diibQA]]j(a49926A]]l*B $ 5"''!*1C yy1})tBsAbDyMS MbDIIB7A)4==*(8M3J2K1MIy))#[djj>!$..0DJJ>wwq#B'44r1   c                   |dvrt        d|d      | j                  rd| j                  }}no| j                  dk(  rD| j                   dz  }| j                  dz  dk(  r| j                  dz  dz
  n| j                  dz  }nt        d| j                   d	d
z         | j
                  | j                  |      }}|rI| j                  |dz
  z  | j                  |dz
  z  }	}| j                  |dz
  z  | j                  |dz
  z  }}
n<| j                  |z  | j                  |z  }	}| j                  |z  | j                  |z  }}
|dk(  r||	|
|fS |
|||	fS )a(  Return minimum and maximum values time-frequency values.

        A tuple with four floats  ``(t0, t1, f0, f1)`` for 'tf' and
        ``(f0, f1, t0, t1)`` for 'ft' is returned describing the corners
        of the time-frequency domain of the `~ShortTimeFFT.stft`.
        That tuple can be passed to `matplotlib.pyplot.imshow` as a parameter
        with the same name.

        Parameters
        ----------
        n : int
            Number of samples in input signal.
        axes_seq : {'tf', 'ft'}
            Return time extent first and then frequency extent or vice-versa.
        center_bins: bool
            If set (default ``False``), the values of the time slots and
            frequency bins are moved from the side the middle. This is useful,
            when plotting the `~ShortTimeFFT.stft` values as step functions,
            i.e., with no interpolation.

        See Also
        --------
        :func:`matplotlib.pyplot.imshow`: Display data as an image.
        :class:`scipy.signal.ShortTimeFFT`: Class this method belongs to.
        )tfftzParameter axes_seq=z not in ['tf', 'ft']!r   r   r   rK   zAttribute fft_mode=z	 must be z)in ['centered', 'onesided', 'onesided2X']g      ?r,  )	r   r   r   rE   rF   r   r   r   r  )rS   r   axes_seqcenter_binsr   r   r   r   t0t1f0f1s               r/   extentzShortTimeFFT.extent^  s`   6 <'3(4IJKK

B]]j())qB'+yy1}'9a!#tyyA~B24==/KHI J J TZZ]B\\R#X.S0IB\\R#X.S0IB\\B&r(9B\\B&r(9B#+t#3BBI"b"b9IIr1   )r)   r3   r*   r7   rR   r9   rE   r;   rF   r@   rG   r5   rH   r>   rI   r@   )rG   r3   r*   r7   rR   r9   rE   r;   rF   r@   rH   r>   rI   r@   )r[   zstr | tuple | floatrR   r9   r\   r7   r]   r7   rX   boolrE   r;   rF   r@   rH   r>   rI   r@   )returnr3   )r6  r7   )r6  r9   )rj   r9   )r6  r;   )rr   r;   )rw   r7   )r6  r>   )rq   zLiteral['magnitude', 'psd'])r6  r@   )rj   r@   )r   r3   r   r7   r   r7   r   r7   r   r   r6  z!Generator[np.ndarray, None, None]r}   )r   r3   r   r@   r   r@   r   r7   r   r   r   r7   r6  r3   )r   r3   r   ICallable[[np.ndarray], np.ndarray] | Literal['linear', 'constant'] | Noner   r@   r   r@   r   r7   r   r   r   r7   r6  r3   )r   r3   r   r5   r   r7  r   r@   r   r@   r   r7   r   r   r   r7   r6  r3   )r6  r5  )r   N)r   r3   r   r7   r   r@   r   r7   r   r7   r6  r3   )r6  tuple[int, int])r   r7   r6  r8  )r   r7   r6  r7   )r   r7   r   r@   r   r@   r6  r8  )NNr   )
r   r7   r   r@   r   r@   r   r7   r6  r3   )T)r  r7   r   r5  r6  r7   )r   r3   r6  r3   )r#  r3   r6  r3   )r,  F)r   r7   r.  zLiteral['tf', 'ft']r/  r5  r6  z!tuple[float, float, float, float]);__name__
__module____qualname____doc____annotations__r6   r<   r?   rB   rC   rD   rT   classmethodrW   r^   propertyr)   r*   re   setterrR   rE   rF   rq   rH   rI   r   r   r   r   rG   r   r   r   r~   rv   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rr   r   r  r   r   r  r   r   r4   r1   r/   r   r   N   s   Xt #'I '
I 
J)I})J37H07 "Hl!!Hl!04-4 ,6$(/3@D+,@(@!@ -@ >	@
 )@8 ,6%)AE,-	O,)O,"O, ?O,  *	O, O,b  +0.8'+CG./HJHJ(+HJ7:HJ#'HJ ,HJ %	HJ
 AHJ ",HJ HJT  "  "   XX    YY  & &P __ $   
[[   ($ L ! !2  ".#.(I.8 48":=78!(b:=:=14:=:=03:= :=| >B4 &'G!#	4d4#40:4  #4 2:4 	4
 4l AEfj] &*D$%7 "]c] #] 0:] "	] 19	]
 ] ]~  0  $WbWW(+WWr  *  ,       N N" & &, & &0 s
N 
N(&(.** "& "&H s : ! !  04!%//*9/b q@D D D * D  DD@2 ( (" 
F 
F ; ; D D,D@5> >B#(.J .J-N.Jr1   )r)   r3   r*   r7   r6  r3   )r<  
__future__r   collections.abcr   	functoolsr   r   r   typingr   r	   r
   numpyr   	scipy.fftr  r  scipy.signalr   scipy.signal.windowsr   __all__r   r;   r0   r   rA  r1   r/   <module>rK     s^    C( # % / / . .     +
 12 HIF~J ~Jr1   