o
    i1g                     @  s  d dl mZ d dlmZ d dlmZ d dlZd dlZd dlm	Z	 d dl
Z
d dlZd dlZd dlZd dlmZ d dlmZ d dlmZ d dlm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 d dl m!Z!m"Z" d dl#m$Z$m%Z%m&Z& 		drdsddZ'dtddZ(dudd Z)	!	dvdwd#d$Z*	%	dxdyd)d*Z+	!	dvdwd+d,Z,	%	dxdyd-d.Z-	 	dzd{d8d9Z.d|dCdDZ/d}d~dFdGZ0	H			J	L		Nddd[d\Z1	]		^	/ddd_d`Z2	I		J	L	adddddeZ3	I		J	L	adddfdgZ4ddidjZ5	I		K	/	kdddpdqZ6dS )    )annotations)Sequence)partialN)Callable)lax)_ensure_index_tuple)dtypes)PrecisionLike)linalg)check_arraylikepromote_dtypes_inexactpromote_dtypes_complex)signal_helper)Array	ArrayLike)canonicalize_axistuple_deletetuple_insertfullin1r   in2modestraxesSequence[int] | Nonereturnr   c                   s   t d  t \  jjkrtd|dvrtdtt|d}|du r.| S t|}t fdd|D }tt	 jt| }t
 fd	d|D rctd
 jdjd|t|D ]
}tj|||d}qg| S )a&  
  Convolve two N-dimensional arrays using Fast Fourier Transform (FFT).

  JAX implementation of :func:`scipy.signal.fftconvolve`.

  Args:
    in1: left-hand input to the convolution.
    in2: right-hand input to the convolution. Must have ``in1.ndim == in2.ndim``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full convolution of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    axes: optional sequence of axes along which to apply the convolution.

  Returns:
    Array containing the convolved result.

  See Also:
    - :func:`jax.numpy.convolve`: 1D convolution
    - :func:`jax.scipy.signal.convolve`: direct convolution

  Examples:
    A few 1D convolution examples. Because FFT-based convolution is approximate,
    We use :func:`jax.numpy.printoptions` below to adjust the printing precision:

    >>> x = jnp.array([1, 2, 3, 2, 1])
    >>> y = jnp.array([1, 1, 1])

    Full convolution uses implicit zero-padding at the edges:

    >>> with jax.numpy.printoptions(precision=3):
    ...   print(jax.scipy.signal.fftconvolve(x, y, mode='full'))
    [1. 3. 6. 7. 6. 3. 1.]

    Specifying ``mode = 'same'`` returns a centered convolution the same size
    as the first input:

    >>> with jax.numpy.printoptions(precision=3):
    ...   print(jax.scipy.signal.fftconvolve(x, y, mode='same'))
    [3. 6. 7. 6. 3.]

    Specifying ``mode = 'valid'`` returns only the portion where the two arrays
    fully overlap:

    >>> with jax.numpy.printoptions(precision=3):
    ...   print(jax.scipy.signal.fftconvolve(x, y, mode='valid'))
    [6. 7. 6.]
  fftconvolvez/in1 and in2 should have the same dimensionality)samer   validz-mode must be one of ['same', 'full', 'valid']r   Nc                 3  s    | ]	}t | jV  qd S N)r   ndim).0ax)r    R/var/www/html/emociones/venv/lib/python3.10/site-packages/jax/_src/scipy/signal.py	<genexpr>i       zfftconvolve.<locals>.<genexpr>c                 3  s$    | ]} j | j | kV  qd S r    shape)r"   ir   r   r$   r%   r&   k   s   " z0mapped axes must have same shape; got in1.shape=z in2.shape=z axes=)in_axesout_axes)r   r   r!   
ValueErrorr   _fftconvolve_unbatchedr   tuplesetrangeanyr)   sortedjaxvmap)r   r   r   r   _fftconvolvemapped_axesr#   r$   r+   r%   r   )   s"   6

r   c                 C  sH  t dd t| j|jD }|}|dkr?tdd t| j|jD }tdd t| j|jD }|s8|s8td|r?|| } }t| rNtjjtjj	}}n	tjj
tjj}}|| |}	|||}
||	|
 |}|dkro|}n"|dkrw| j}n|dkrt d	d t| j|jD }ntd
|t dd t||D }t|||S )Nc                 s  s     | ]\}}|| d  V  qdS    Nr$   r"   s1s2r$   r$   r%   r&   r       z)_fftconvolve_unbatched.<locals>.<genexpr>r   c                 s      | ]	\}}||kV  qd S r    r$   r;   r$   r$   r%   r&   x   r'   c                 s      | ]	\}}||kV  qd S r    r$   r;   r$   r$   r%   r&   y   r'   zVFor 'valid' mode, One input must be at least as large as the other in every dimension.r   r   c                 s  s     | ]\}}|| d  V  qdS r9   r$   r;   r$   r$   r%   r&      r>   zUnrecognized mode=c                 s  s     | ]\}}|| d  V  qdS )   Nr$   )r"   	full_sizeout_sizer$   r$   r%   r&      s    )r0   zipr)   allr.   jnpiscomplexobjfftfftnifftnrfftnirfftnr   dynamic_slice)r   r   r   
full_shape	fft_shapeno_swapswaprH   ifftsp1sp2conv	out_shapestart_indicesr$   r$   r%   r/   q   s4   



r/   	precisionr	   c                C  sN  |dvrt d| j|jkrt d| jdks|jdkr)t d| j d|j dt| |\} }tdd	 t| j|jD }td
d	 t| j|jD }|sT|sTt d|j}|r^|| } }|j}t|}|dkrrdd |D }n|dkrdd t||D }n|dkrdd |D }t	dd	 |D }	t
j| d |d |	||d}
|
d S )N)r   r   r   z-mode must be one of ['full', 'same', 'valid']z3in1 and in2 must have the same number of dimensionsr   z;zero-size arrays not supported in convolutions, got shapes z and .c                 s  r?   r    r$   r;   r$   r$   r%   r&      r'   z_convolve_nd.<locals>.<genexpr>c                 s  r@   r    r$   r;   r$   r$   r%   r&      r'   z<One input must be smaller than the other in every dimension.r   c                 S     g | ]}d qS r   r   r$   r"   sr$   r$   r%   
<listcomp>       z _convolve_nd.<locals>.<listcomp>r   c                 S  s8   g | ]\}}|d  |d  d  || |d  d  fqS )r:   rA   r$   )r"   r^   s_or$   r$   r%   r_      s    ,r   c                 S  s   g | ]
}|d  |d  fqS r:   r$   r]   r$   r$   r%   r_      s    c                 s  s    | ]}d V  qdS r9   r$   r]   r$   r$   r%   r&      s    )NNrX   r\   )r.   r!   sizer)   r   rE   rD   rF   flipr0   r   conv_general_dilated)r   r   r   rX   rP   rQ   shape_or)   paddingstridesresultr$   r$   r%   _convolve_nd   s:   

rk   automethodc                 C  s>   |dkrt | ||dS |dv rt| |||dS td|d)a  Convolution of two N-dimensional arrays.

  JAX implementation of :func:`scipy.signal.convolve`.

  Args:
    in1: left-hand input to the convolution.
    in2: right-hand input to the convolution. Must have ``in1.ndim == in2.ndim``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full convolution of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    method: controls the computation method. Options are

      * ``"auto"``: (default) always uses the ``"direct"`` method.
      * ``"direct"``: lower to :func:`jax.lax.conv_general_dilated`.
      * ``"fft"``: compute the result via a fast Fourier transform.

    precision: Specify the precision of the computation. Refer to
      :class:`jax.lax.Precision` for a description of available values.

  Returns:
    Array containing the convolved result.

  See Also:
    - :func:`jax.numpy.convolve`: 1D convolution
    - :func:`jax.scipy.signal.convolve2d`: 2D convolution
    - :func:`jax.scipy.signal.correlate`: ND correlation

  Examples:
    A few 1D convolution examples:

    >>> x = jnp.array([1, 2, 3, 2, 1])
    >>> y = jnp.array([1, 1, 1])

    Full convolution uses implicit zero-padding at the edges:

    >>> jax.scipy.signal.convolve(x, y, mode='full')
    Array([1., 3., 6., 7., 6., 3., 1.], dtype=float32)

    Specifying ``mode = 'same'`` returns a centered convolution the same size
    as the first input:

    >>> jax.scipy.signal.convolve(x, y, mode='same')
    Array([3., 6., 7., 6., 3.], dtype=float32)

    Specifying ``mode = 'valid'`` returns only the portion where the two arrays
    fully overlap:

    >>> jax.scipy.signal.convolve(x, y, mode='valid')
    Array([6., 7., 6.], dtype=float32)
  rH   r   )directrl   rc   zGot method=z&; expected 'auto', 'fft', or 'direct'.)r   rk   r.   r   r   r   rm   rX   r$   r$   r%   convolve   s
   9rp   fillboundary	fillvaluefloatc                 C  sL   |dks|dkrt dt| dkst|dkrtdt| |||dS )a	  Convolution of two 2-dimensional arrays.

  JAX implementation of :func:`scipy.signal.convolve2d`.

  Args:
    in1: left-hand input to the convolution. Must have ``in1.ndim == 2``.
    in2: right-hand input to the convolution. Must have ``in2.ndim == 2``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full convolution of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    boundary: only ``"fill"`` is supported.
    fillvalue: only ``0`` is supported.
    method: controls the computation method. Options are

      * ``"auto"``: (default) always uses the ``"direct"`` method.
      * ``"direct"``: lower to :func:`jax.lax.conv_general_dilated`.
      * ``"fft"``: compute the result via a fast Fourier transform.

    precision: Specify the precision of the computation. Refer to
      :class:`jax.lax.Precision` for a description of available values.

  Returns:
    Array containing the convolved result.

  See Also:
    - :func:`jax.numpy.convolve`: 1D convolution
    - :func:`jax.scipy.signal.convolve`: ND convolution
    - :func:`jax.scipy.signal.correlate`: ND correlation

  Examples:
    A few 2D convolution examples:

    >>> x = jnp.array([[1, 2],
    ...                [3, 4]])
    >>> y = jnp.array([[2, 1, 1],
    ...                [4, 3, 4],
    ...                [1, 3, 2]])

    Full 2D convolution uses implicit zero-padding at the edges:

    >>> jax.scipy.signal.convolve2d(x, y, mode='full')
    Array([[ 2.,  5.,  3.,  2.],
           [10., 22., 17., 12.],
           [13., 30., 32., 20.],
           [ 3., 13., 18.,  8.]], dtype=float32)

    Specifying ``mode = 'same'`` returns a centered 2D convolution of the same size
    as the first input:

    >>> jax.scipy.signal.convolve2d(x, y, mode='same')
    Array([[22., 17.],
           [30., 32.]], dtype=float32)

    Specifying ``mode = 'valid'`` returns only the portion of 2D convolution
    where the two arrays fully overlap:

    >>> jax.scipy.signal.convolve2d(x, y, mode='valid')
    Array([[22., 17.],
           [30., 32.]], dtype=float32)
  rq   r   z7convolve2d() only supports boundary='fill', fillvalue=0rA   z0convolve2d() only supports 2-dimensional inputs.rc   )NotImplementedErrorrF   r!   r.   rk   )r   r   r   rr   rs   rX   r$   r$   r%   
convolve2d   s
   Crv   c                 C  s   t | t| |||dS )a  Cross-correlation of two N-dimensional arrays.

  JAX implementation of :func:`scipy.signal.correlate`.

  Args:
    in1: left-hand input to the cross-correlation.
    in2: right-hand input to the cross-correlation. Must have ``in1.ndim == in2.ndim``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full cross-correlation of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    method: controls the computation method. Options are

      * ``"auto"``: (default) always uses the ``"direct"`` method.
      * ``"direct"``: lower to :func:`jax.lax.conv_general_dilated`.
      * ``"fft"``: compute the result via a fast Fourier transform.

    precision: Specify the precision of the computation. Refer to
      :class:`jax.lax.Precision` for a description of available values.

  Returns:
    Array containing the cross-correlation result.

  See Also:
    - :func:`jax.numpy.correlate`: 1D cross-correlation
    - :func:`jax.scipy.signal.correlate2d`: 2D cross-correlation
    - :func:`jax.scipy.signal.convolve`: ND convolution

  Examples:
    A few 1D correlation examples:

    >>> x = jnp.array([1, 2, 3, 2, 1])
    >>> y = jnp.array([1, 3, 2])

    Full 1D correlation uses implicit zero-padding at the edges:

    >>> jax.scipy.signal.correlate(x, y, mode='full')
    Array([ 2.,  7., 13., 15., 11.,  5.,  1.], dtype=float32)

    Specifying ``mode = 'same'`` returns a centered 1D correlation of the same
    size as the first input:

    >>> jax.scipy.signal.correlate(x, y, mode='same')
    Array([ 7., 13., 15., 11.,  5.], dtype=float32)

    Specifying ``mode = 'valid'`` returns only the portion of 1D correlation
    where the two arrays fully overlap:

    >>> jax.scipy.signal.correlate(x, y, mode='valid')
    Array([13., 15., 11.], dtype=float32)
  )rX   rm   )rp   rF   re   conjro   r$   r$   r%   	correlateF  s   9rx   c           	      C  sn  |dks|dkrt dt| dkst|dkrtdtdd t| j|jD }tdd t| j|jD }|d	krUt| | } }tt	| |||d
}|S |dkr|rq|sqt||  } }t	| |||d
}|S t| | } }tt	| |||d
}|S |rt||  } }t	| |||d
 }|S t| | } }tt	| |||d
}|S )aX	  Cross-correlation of two 2-dimensional arrays.

  JAX implementation of :func:`scipy.signal.correlate2d`.

  Args:
    in1: left-hand input to the cross-correlation. Must have ``in1.ndim == 2``.
    in2: right-hand input to the cross-correlation. Must have ``in2.ndim == 2``.
    mode: controls the size of the output. Available operations are:

      * ``"full"``: (default) output the full cross-correlation of the inputs.
      * ``"same"``: return a centered portion of the ``"full"`` output which
        is the same size as ``in1``.
      * ``"valid"``: return the portion of the ``"full"`` output which do not
        depend on padding at the array edges.

    boundary: only ``"fill"`` is supported.
    fillvalue: only ``0`` is supported.
    method: controls the computation method. Options are

      * ``"auto"``: (default) always uses the ``"direct"`` method.
      * ``"direct"``: lower to :func:`jax.lax.conv_general_dilated`.
      * ``"fft"``: compute the result via a fast Fourier transform.

    precision: Specify the precision of the computation. Refer to
      :class:`jax.lax.Precision` for a description of available values.

  Returns:
    Array containing the cross-correlation result.

  See Also:
    - :func:`jax.numpy.correlate`: 1D cross-correlation
    - :func:`jax.scipy.signal.correlate`: ND cross-correlation
    - :func:`jax.scipy.signal.convolve`: ND convolution

  Examples:
    A few 2D correlation examples:

    >>> x = jnp.array([[2, 1, 3],
    ...                [1, 3, 1],
    ...                [4, 1, 2]])
    >>> y = jnp.array([[1, 3],
    ...                [4, 2]])

    Full 2D correlation uses implicit zero-padding at the edges:

    >>> jax.scipy.signal.correlate2d(x, y, mode='full')
    Array([[ 4., 10., 10., 12.],
           [ 8., 15., 24.,  7.],
           [11., 28., 14.,  9.],
           [12.,  7.,  7.,  2.]], dtype=float32)

    Specifying ``mode = 'same'`` returns a centered 2D correlation of the same
    size as the first input:

    >>> jax.scipy.signal.correlate2d(x, y, mode='same')
    Array([[15., 24.,  7.],
           [28., 14.,  9.],
           [ 7.,  7.,  2.]], dtype=float32)

    Specifying ``mode = 'valid'`` returns only the portion of 2D correlation
    where the two arrays fully overlap:

    >>> jax.scipy.signal.correlate2d(x, y, mode='valid')
    Array([[15., 24.],
           [28., 14.]], dtype=float32)
  rq   r   z8correlate2d() only supports boundary='fill', fillvalue=0rA   z1correlate2d() only supports 2-dimensional inputs.c                 s  r@   r    r$   r;   r$   r$   r%   r&     r'   zcorrelate2d.<locals>.<genexpr>c                 s  s    | ]	\}}||kV  qd S r    r$   r;   r$   r$   r%   r&     r'   r   rc   r   )
ru   rF   r!   r.   rE   rD   r)   re   rw   rk   )	r   r   r   rr   rs   rX   rQ   
same_shaperj   r$   r$   r%   correlate2d  s2   Drz   lineardataaxisinttypebpoverwrite_dataNonec              	   C  st  |durt d|dvrtdtt| \}|dkr%||j|dd S |j| }tt	tj
d||f }|d dk sD|d	 |krHtd
t||d}|j}||d	}tt|d D ]O}	||	d  ||	  }
ttj|
|jdtjd|
d |jd|
|j gj}t||	 ||	d  }t||| ^}}|j| tj||tjjd }q`t||d|S )a  
  Remove linear or piecewise linear trends from data.

  JAX implementation of :func:`scipy.signal.detrend`.

  Args:
    data: The input array containing the data to detrend.
    axis: The axis along which to detrend. Default is -1 (the last axis).
    type: The type of detrending. Can be:

      * ``'linear'``: Fit a single linear trend for the entire data.
      * ``'constant'``: Remove the mean value of the data.

    bp: A sequence of breakpoints. If given, piecewise linear trends
      are fit between these breakpoints.
    overwrite_data: This argument is not supported by JAX's implementation.

  Returns:
    The detrended data array.

  Example:
    A simple detrend operation in one dimension:

    >>> data = jnp.array([1., 4., 8., 8., 9.])

    Removing a linear trend from the data:

    >>> detrended = jax.scipy.signal.detrend(data)
    >>> with jnp.printoptions(precision=3, suppress=True):  # suppress float error
    ...   print("Detrended:", detrended)
    ...   print("Underlying trend:", data - detrended)
    Detrended: [-1. -0.  2. -0. -1.]
    Underlying trend: [ 2.  4.  6.  8. 10.]

    Removing a constant trend from the data:

    >>> detrended = jax.scipy.signal.detrend(data, type='constant')
    >>> with jnp.printoptions(precision=3):  # suppress float error
    ...   print("Detrended:", detrended)
    ...   print("Underlying trend:", data - detrended)
    Detrended: [-5. -2.  2.  2.  3.]
    Underlying trend: [6. 6. 6. 6. 6.]
  Nz(overwrite_data argument not implemented.)constantr|   z*Trend type must be 'linear' or 'constant'.r   T)keepdimsr   r{   zOBreakpoints must be non-negative and less than length of data along given axis.r:   dtyperc   )ru   r.   r   rF   asarraymeanr)   npsortuniquer_moveaxisreshaper2   lenvstackonesr   arangeastypeTslicer
   lstsqataddmatmulr   	PrecisionHIGHEST)r}   r~   r   r   r   data_arrNbp_arrr)   mNptsAslcoef_r$   r$   r%   detrend  s4   -
 $r   xwindetrend_funcCallable[[Array], Array]npersegnoverlapnfft
int | Nonesidesc                 C  s
  | j jdkr| |j } | j^ }}|dkr"|dkr"| dtjf }	n/|| }
t|}| t	||df} t
jj| |f|
fddd}	|	jg ||	jdd	 R  }	||	}	t|r_t|	\}	|d
t| d|f |	 }	|dkr{t
jjj|	|dS t
jjj|	j|dS )zBCalculate windowed FFT in the same way the original SciPy does.
  r*   r:   r   .VALID)NTCOITr   )dimension_numbersNrb   twosided)n)r   kindr   r)   r   newaxislistr   mathprodr5   r   conv_general_dilated_patchesrF   rG   r   r   numpyrH   rfftreal)r   r   r   r   r   r   r   batch_shapesignal_lengthrj   stepr$   r$   r%   _fft_helper+  s*   


r   r   c                 C  s   |dk r| S || j | d krtd| d| j | d  dtj| dd|d}tjtj| d|d |d|d}tj| dd|d}tjtj| |d  d|d|d}tjd	| | | d	| | f|d}|S )
a  Extends `x` along with `axis` by odd-extension.

  This function was previously a part of "scipy.signal.signaltools" but is no
  longer exposed.

  Args:
    x : input array
    n : the number of points to be added to the both end
    axis: the axis to be extended
  r:   zThe extension length n (z;) is too big. It must not exceed x.shape[axis]-1, which is rY   r   r~   r{   NrA   )r)   r.   r   slice_in_dimrF   re   concatenate)r   r   r~   left_endleft_ext	right_end	right_extextr$   r$   r%   odd_extO  s&    "
r         ?hannr   TdensitypsdFyArrayLike | Nonefswindowdetrend_type%bool | str | Callable[[Array], Array]return_onesidedboolscaling
str | Nonepaddedtuple[Array, Array, Array]c           &   
     s  |dvrt d| ddd }|dt|d|dd	d
dd d}||vr4t d| dt|  tjtj d t	 | j
 |du rZtd|  t| \} | }t| j }nA|dkrbt dtd| | t| |\} }| j
|j
kryt dztt| j t|j }W n t y } zt d|d}~ww t| j}t|j}d}d}d}|durtjt|d}|dk rt dtj||du r|n|| j  | jd\}}|du r|d }ntjt|d}|du r|}ntjt|d}|du r| jdkrt| j|t| j|t| j|fS n,| jdks"|jdkrBt|t| j  |j   }t||t||t||fS t|  d} |dur[|j
dkr[t| d}|dur| jd |jd kr| jd |jd k rt| j}|jd | jd  |d< t| tj| |d fd} nt|j}| jd |jd  |d< t|tj| |d fd}||k rt d!||krt d"|| }|dur|| }|| |d dd#} |dur|||d dd#}|r-| jd |  | | }tj| tj| g | jdd |R d fdd#} |dur-tj|tj| g |jdd |R d fdd#}s5d$d }nt sBt!t"dd%}n dkrO fd&d'}n}|	d(krad)||| #   }n|	d*krod)|# d  }nt d+|	 |d,krt$|}t%|\}|rd-} t&| st&|rd.} t'(d/ nd.} | d.krtj)j*j+|d| |d0}!n| d-krtj)j*j,|d| |d0}!t-| |||||| }"|durt-||||||| }#t.|"|# }"n|dkrt.|"|" }"|"|9 }"| d-kr|dkr|d rdnd}$|"j/d1d|$f 0d}"tj1|d | jd |d  d || |d0| }%|dur8|%|d | 8 }%|"2|}"|du rJ|d,krJ|"j3}"t|"d }"|!|%|"fS )2a3  LAX-backend implementation of `scipy.signal._spectral_helper`.

  Unlike the original helper function, `y` can be None for explicitly
  indicating auto-spectral (non cross-spectral) computation.  In addition to
  this, `detrend` argument is renamed to `detrend_type` for avoiding internal
  name overlap.
  )r   stftzUnknown value for mode z!, must be one of: ('psd', 'stft')c                   s   d fdd	}|S )Nr{   c                   s6   dd t | jD }||f||< tj| |fi  S )Nc                 S  rZ   r[   r$   )r"   unused_nr$   r$   r%   r_     r`   zC_spectral_helper.<locals>.make_pad.<locals>.pad.<locals>.<listcomp>)r2   r!   rF   pad)r   r   r~   	pad_widthkwargsr   r$   r%   r   ~  s   z/_spectral_helper.<locals>.make_pad.<locals>.padr{   r$   )r   r   r   r$   r   r%   make_pad}  s   z"_spectral_helper.<locals>.make_padreflectedger   g        )constant_valuesc                 _     | S r    r$   )r   argsr   r$   r$   r%   <lambda>      z"_spectral_helper.<locals>.<lambda>)evenoddr   zerosNzUnknown boundary option 'z', must be one of: zaxis of windowed-FFTNspectral_helperr   z4two-argument mode is available only when mode=='psd'z=two-arguments must have the same rank ({x.ndim} vs {y.ndim}).z%x and y cannot be broadcast together.r   znperseg of windowed-FFTr:   "nperseg must be a positive integer)input_lengthr   rA   znoverlap of windowed-FFTznfft of windowed-FFTr{   r(   z.nfft must be greater than or equal to nperseg.#noverlap must be less than nperseg.r   c                 S  r   r    r$   dr$   r$   r%   r     r   )r   r~   c                   s$   t |  d} | } t | d S )Nr{   )rF   r   r   r~   r   r$   r%   r     s   z&_spectral_helper.<locals>.detrend_funcr   r   spectrumzUnknown scaling: r   onesidedr   z9Input data is complex, switching to return_onesided=Falser   .)4r.   r   r   keysr5   coreconcrete_or_erroroperatorindexr   r!   r   r   r   r)   rF   broadcast_shapesr   to_complex_dtyper   r   finfor   r   _triage_segmentsrd   r   r   minr   r   
zeros_likecallabler   r   sumsqrtr   rG   warningswarnr   rH   fftfreqrfftfreqr   	conjugater   mulr   r   r   )&r   r   r   r   r   r   r   r   r   r   r~   r   rr   r   r   boundary_funcsy_arr
outershapeerrresult_dtype
freq_dtypenperseg_intnfft_intnoverlap_intr   r)   	pad_shapenstepext_funcnaddr   scaler   freqsrj   result_yendtimer$   r   r%   _spectral_helperk  s(  
	










(" 





0
0















r     r   c                 C  s$   t | d|||||||d|
d||	dS )a  
  Compute the short-time Fourier transform (STFT).

  JAX implementation of :func:`scipy.signal.stft`.

  Args:
    x: Array representing a time series of input values.
    fs: Sampling frequency of the time series (default: 1.0).
    window: Data tapering window to apply to each segment. Can be a window function name,
      a tuple specifying a window length and function, or an array (default: ``'hann'``).
    nperseg: Length of each segment (default: 256).
    noverlap: Number of points to overlap between segments (default: ``nperseg // 2``).
    nfft: Length of the FFT used, if a zero-padded FFT is desired. If ``None`` (default),
      the FFT length is ``nperseg``.
    detrend: Specifies how to detrend each segment. Can be ``False`` (default: no detrending),
      ``'constant'`` (remove mean), ``'linear'`` (remove linear trend), or a callable
      accepting a segment and returning a detrended segment.
    return_onesided: If True (default), return a one-sided spectrum for real inputs.
      If False, return a two-sided spectrum.
    boundary: Specifies whether the input signal is extended at both ends, and how.
      Options are ``None`` (no extension), ``'zeros'`` (default), ``'even'``, ``'odd'``,
      or ``'constant'``.
    padded: Specifies whether the input signal is zero-padded at the end to make its
      length a multiple of `nperseg`. If True (default), the padded signal length is
      the next multiple of ``nperseg``.
    axis: Axis along which the STFT is computed; the default is over the last axis (-1).

  Returns:
    A length-3 tuple of arrays ``(f, t, Zxx)``. ``f`` is the Array of sample frequencies.
    ``t`` is the Array of segment times, and ``Zxx`` is the STFT of ``x``.

  See Also:
    :func:`jax.scipy.signal.istft`: inverse short-time Fourier transform.
  Nr   r   )r   r~   r   rr   r   )r  )r   r   r   r   r   r   r   r   rr   r   r~   r$   r$   r%   r   @  s   &r   r   averagetuple[Array, Array]c                 C  s  t | |||||||||	|
dd\}}}|dur|d }|jdkr|jdkr|jd dkr||d	krgt|jd |j}t	|rXtj
t|dd
dtj
t|dd
  }ntj
|dd
}|| }||fS |dkru|jdd
}||fS td| t||jdd }||fS )aM	  
  Estimate cross power spectral density (CSD) using Welch's method.

  This is a JAX implementation of :func:`scipy.signal.csd`. It is similar to
  :func:`jax.scipy.signal.welch`, but it operates on two input signals and
  estimates their cross-spectral density instead of the power spectral density
  (PSD).

  Args:
    x: Array representing a time series of input values.
    y: Array representing the second time series of input values, the same length as ``x``
      along the specified ``axis``. If not specified, then assume ``y = x`` and compute
      the PSD ``Pxx`` of ``x`` via Welch's  method.
    fs: Sampling frequency of the inputs (default: 1.0).
    window: Data tapering window to apply to each segment. Can be a window function name,
      a tuple specifying a window length and function, or an array (default: ``'hann'``).
    nperseg: Length of each segment (default: 256).
    noverlap: Number of points to overlap between segments (default: ``nperseg // 2``).
    nfft: Length of the FFT used, if a zero-padded FFT is desired. If ``None`` (default),
      the FFT length is ``nperseg``.
    detrend: Specifies how to detrend each segment. Can be ``False`` (default: no detrending),
      ``'constant'`` (remove mean), ``'linear'`` (remove linear trend), or a callable
      accepting a segment and returning a detrended segment.
    return_onesided: If True (default), return a one-sided spectrum for real inputs.
      If False, return a two-sided spectrum.
    scaling: Selects between computing the power spectral density (``'density'``, default)
      or the power spectrum (``'spectrum'``)
    axis: Axis along which the CSD is computed (default: -1).
    average: The type of averaging to use on the periodograms; one of ``'mean'`` (default)
      or ``'median'``.

  Returns:
    A length-2 tuple of arrays ``(f, Pxy)``. ``f`` is the array of sample frequencies,
    and ``Pxy`` is the cross spectral density of `x` and `y`

  Notes:
    The original SciPy function exhibits slightly different behavior between
    ``csd(x, x)`` and ``csd(x, x.copy())``.  The LAX-backend version is designed
    to follow the latter behavior.  To replicate the former, call this function
    function as ``csd(x, None)``.

  See Also:
    - :func:`jax.scipy.signal.welch`: Power spectral density.
    - :func:`jax.scipy.signal.stft`: Short-time Fourier transform.
  r   r   Ny                rA   r   r{   r:   medianr   y              ?r   z(average must be "median" or "mean", got )r  r!   rd   r)   r   _median_biasr   r   rF   rG   r"  r   imagr   r.   r   )r   r   r   r   r   r   r   r   r   r   r~   r   r  r   Pxybiasr$   r$   r%   csdm  s.   2
r'  c                 C  s.   t | d|||||||||	|
d\}}||jfS )aE  
  Estimate power spectral density (PSD) using Welch's method.

  This is a JAX implementation of :func:`scipy.signal.welch`. It divides the
  input signal into overlapping segments, computes the modified periodogram for
  each segment, and averages the results to obtain a smoother estimate of the PSD.

  Args:
    x: Array representing a time series of input values.
    fs: Sampling frequency of the inputs (default: 1.0).
    window: Data tapering window to apply to each segment. Can be a window function name,
      a tuple specifying a window length and function, or an array (default: ``'hann'``).
    nperseg: Length of each segment (default: 256).
    noverlap: Number of points to overlap between segments (default: ``nperseg // 2``).
    nfft: Length of the FFT used, if a zero-padded FFT is desired. If ``None`` (default),
      the FFT length is ``nperseg``.
    detrend: Specifies how to detrend each segment. Can be ``False`` (default: no detrending),
      ``'constant'`` (remove mean), ``'linear'`` (remove linear trend), or a callable
      accepting a segment and returning a detrended segment.
    return_onesided: If True (default), return a one-sided spectrum for real inputs.
      If False, return a two-sided spectrum.
    scaling: Selects between computing the power spectral density (``'density'``, default)
      or the power spectrum (``'spectrum'``)
    axis: Axis along which the PSD is computed (default: -1).
    average: The type of averaging to use on the periodograms; one of ``'mean'`` (default)
      or ``'median'``.

  Returns:
    A length-2 tuple of arrays ``(f, Pxx)``. ``f`` is the array of sample frequencies,
    and ``Pxx`` is the power spectral density of ``x``.

  See Also:
    - :func:`jax.scipy.signal.csd`: Cross power spectral density.
    - :func:`jax.scipy.signal.stft`: Short-time Fourier transform.
  N)
r   r   r   r   r   r   r   r   r~   r   )r'  r   )r   r   r   r   r   r   r   r   r   r~   r   r  Pxxr$   r$   r%   welch  s   (

r)  	step_sizec           
      C  sD  t d|  tjt|d}| jdk rtd| j^ }}}t	|}| 
|||f} ||d  | }d|d |  }|| }t| ddd|| ff} | 
||||f} | d} t| ddd|fdf} | jd d }	| 
|d	f} | d
d
d
||	 | f } | 
|||	| f} | jddd
d
d
|f } | 
t|d S )a4  Utility function compatible with tf.signal.overlap_and_add.

  Args:
    x: An array with `(..., frames, frame_length)`-shape.
    step_size: An integer denoting overlap offsets. Must be less than
      `frame_length`.

  Returns:
    An array with `(..., output_size)`-shape containing overlapped signal.
  _overlap_and_addzstep_size for overlap_and_addrA   z2Input must have (..., frames, frame_length) shape.r:   r\   r   )r   rA   r:      r{   Nr   r   )r   r5   r   r   r   r!   r.   r)   r   r   r   rF   r   	transposer  r0   )
r   r*  r   nframessegment_lenflat_batchsizeoutput_sizenstep_per_segmentpadded_segment_lenshrinkedr$   r$   r%   r+    s,   




r+  r   Zxxinput_onesided	time_axis	freq_axisc
              
     s  t d|  | jdk rtdt | j t| j kr"tdtj| tjt	
| t	jd} |r=d| j  d  n| j  }
tjt|pI|
d}|dk rTtdd	}|d
u ri|
}|rh||
d krh|d7 }ntjt|d}||k rtd| d| dtjt|p|d d}||krtd|| }| jd ks | jd krt fddt| jD }t| | f } |rtjjjntjjj}|| d|ddd
|d
d
f }|dkr|dkrtdgnttjd	tj|ddd }||j}nTt|ttfr3zd	dlm } W n t!y$ } zt!d||d
}~ww |||}tj||jd}n t|}t"|jdkrDtd|jd	 |krStd| ||# 9 }t$%|g t|jd dR }t&|| 'dd|}tj(|| |jd dd}t&|'dd|}|r|d|d |d  f }|d|d |d  f }|t)|d k|d }|jdkrЈ| jd krЈ k rɈd8 t*|d}tj+|jd	 t	,|jjd| }||fS )!a6  
  Perform the inverse short-time Fourier transform (ISTFT).

  JAX implementation of :func:`scipy.signal.istft`; computes the inverse of
  :func:`jax.scipy.signal.stft`.

  Args:
    Zxx: STFT of the signal to be reconstructed.
    fs: Sampling frequency of the time series (default: 1.0)
    window: Data tapering window to apply to each segment. Can be a window function name,
      a tuple specifying a window length and function, or an array (default: ``'hann'``).
    nperseg: Number of data points per segment in the STFT. If ``None`` (default), the
      value is determined from the size of ``Zxx``.
    noverlap: Number of points to overlap between segments (default: ``nperseg // 2``).
    nfft: Number of FFT points used in the STFT. If ``None`` (default), the
      value is determined from the size of ``Zxx``.
    input_onesided: If Tru` (default), interpret the input as a one-sided STFT
      (positive frequencies only). If False, interpret the input as a two-sided STFT.
    boundary: If True (default), it is assumed that the input signal was extended at
      its boundaries by ``stft``. If `False`, the input signal is assumed to have been truncated at the boundaries by `stft`.
    time_axis: Axis in `Zxx` corresponding to time segments (default: -1).
    freq_axis: Axis in `Zxx` corresponding to frequency bins (default: -2).

  Returns:
    A length-2 tuple of arrays ``(t, x)``. ``t`` is the Array of signal times, and ``x``
    is the reconstructed time series.

  See Also:
    :func:`jax.scipy.signal.stft`: short-time Fourier transform.

  Example:
    Demonstrate that this gives the inverse of :func:`~jax.scipy.signal.stft`:

    >>> x = jnp.array([1., 2., 3., 2., 1., 0., 1., 2.])
    >>> f, t, Zxx = jax.scipy.signal.stft(x, nperseg=4)
    >>> print(Zxx)  # doctest: +SKIP
    [[ 1. +0.j   2.5+0.j   1. +0.j   1. +0.j   0.5+0.j ]
     [-0.5+0.5j -1.5+0.j  -0.5-0.5j -0.5+0.5j  0. -0.5j]
     [ 0. +0.j   0.5+0.j   0. +0.j   0. +0.j  -0.5+0.j ]]
    >>> t, x_reconstructed = jax.scipy.signal.istft(Zxx)
    >>> print(x_reconstructed)
    [1. 2. 3. 2. 1. 0. 1. 2.]
  istftrA   zInput stft must be at least 2d!z/Must specify differing time and frequency axes!r   r:   znperseg: segment length of STFTr   r   Nznfft of STFTzFFT length (z) must be longer than nperseg (z).znoverlap of STFTr   c                 3  s     | ]}| hvr|V  qd S r    r$   )r"   idxr8  r7  r$   r%   r&   q  s    zistft.<locals>.<genexpr>r   )r~   r   .r   r   F)endpoint)
get_windowz&scipy must be available to use window=zwindow must be 1-Dzwindow must have length of r{   r   g|=)-r   r!   r.   r   rF   r   r5   r   canonicalize_dtyper   result_type	complex64r)   r   r   r   r0   r2   r-  r   rH   irfftrR   arraysinlinspacepir   r   
isinstancer   scipy.signalr=  ImportErrorr   r  r   expand_dimsr+  swapaxesrepeatwherer   r   r   )r5  r   r   r   r   r   r6  rr   r7  r8  	n_defaultr  r  r  r  
outer_idxsifuncxsubsr   r=  r  r   win_squarednormr  r$   r;  r%   r9    s   
1
 2

 
"r9  )r   N)
r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )
r   r   r   r   r   r   rX   r	   r   r   )r   rl   N)r   r   r   r   r   r   rm   r   rX   r	   r   r   )r   rq   r   N)r   r   r   r   r   r   rr   r   rs   rt   rX   r	   r   r   )r{   r|   r   N)r}   r   r~   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r~   r   r   r   )r   r   NNNr   Tr   r{   r   NF)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r~   r   r   r   rr   r   r   r   r   r   )
r   r   r  NNFTr   Tr{   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rr   r   r   r   r~   r   r   r   )
r   r   NNNr   Tr   r{   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r~   r   r   r   r   r!  )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r~   r   r   r   r   r!  )r   r   r*  r   r   r   )	r   r   NNNTTr{   r   )r5  r   r   r   r   r   r   r   r   r   r   r   r6  r   rr   r   r7  r   r8  r   r   r!  )7
__future__r   collections.abcr   	functoolsr   r   r   typingr   r  r   r   r5   jax.numpy.fft	jax.numpyrF   r   jax._src.api_utilr   jax._srcr   jax._src.lax.laxr	   jax._src.numpyr
   jax._src.numpy.utilr   r   r   jax._src.third_party.scipyr   jax._src.typingr   r   jax._src.utilr   r   r   r   r/   rk   rp   rv   rx   rz   r   r   r   r  r   r'  r)  r+  r9  r$   r$   r$   r%   <module>   s   
H
("AJ<`
I$ V-M
00