B
    \Q                 @   s   d dl Z d dlmZ d dl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 ddlmZmZ dd	lmZmZ d
ddddddgZddd
Zdd ZdddZdd ZdddZdddZdS )    N)product   )_have_c99_complex)idwt_single)swt_max_levelswtswt_axis)Modes_check_dtype)idwt2idwtn)_as_wavelet_wavelets_per_axisr   r   iswtswt2iswt2swtniswtnc             C   s  t s~t| r~t| } t| j|||}t| j|||}g }x<t||D ].\\}}	\}
}||d|
  |	d|  f qHW |S t	| }tj
| |d} t|}|dk r|| j }d|  kr| jk sn td|dkrt| j| }| jdkrt| |||}nt| ||||}dd |D S )	a  
    Multilevel 1D stationary wavelet transform.

    Parameters
    ----------
    data :
        Input signal
    wavelet :
        Wavelet to use (Wavelet object or name)
    level : int, optional
        The number of decomposition steps to perform.
    start_level : int, optional
        The level at which the decomposition will begin (it allows one to
        skip a given number of transform steps and compute
        coefficients starting from start_level) (default: 0)
    axis: int, optional
        Axis over which to compute the SWT. If not given, the
        last axis is used.

    Returns
    -------
    coeffs : list
        List of approximation and details coefficients pairs in order
        similar to wavedec function::

            [(cAn, cDn), ..., (cA2, cD2), (cA1, cD1)]

        where n equals input parameter ``level``.

        If ``start_level = m`` is given, then the beginning m steps are
        skipped::

            [(cAm+n, cDm+n), ..., (cAm+1, cDm+1), (cAm, cDm)]

    Notes
    -----
    The implementation here follows the "algorithm a-trous" and requires that
    the signal length along the transformed axis be a multiple of ``2**level``.
    If this is not the case, the user should pad up to an appropriate size
    using a function such as ``numpy.pad``.
    y              ?)dtyper   z!Axis greater than data dimensionsNr   c             S   s$   g | ]\}}t |t |fqS  )npasarray).0cAcDr   r   (lib/python3.7/site-packages/pywt/_swt.py
<listcomp>V   s    zswt.<locals>.<listcomp>)r   r   iscomplexobjr   r   realimagzipappendr
   arrayr   ndim
ValueErrorr   shape_swt	_swt_axis)datawaveletlevelstart_levelaxiscoeffs_realcoeffs_imagZcoeffs_cplxZcA_rZcD_rZcA_iZcD_idtretr   r   r   r      s*    *
"

c             C   s  t | d d }tj| d d |dd}tsjt|rjdd | D }dd | D }t||dt||  S t| }t|}t	d}x*t
|dd	D ]}ttd
|d }	|	}
| ||  \}}tj|t |d}|j|jkr$|jjdks|jjdkrtj}ntj}tj||d}tj||d}xt
|
D ]|}t|t||	}|ddd
 }|ddd
 }t|| || ||}t|| || ||}t|d}|| d ||< q.W qW |S )a  
    Multilevel 1D inverse discrete stationary wavelet transform.

    Parameters
    ----------
    coeffs : array_like
        Coefficients list of tuples::

            [(cAn, cDn), ..., (cA2, cD2), (cA1, cD1)]

        where cA is approximation, cD is details.  Index 1 corresponds to
        ``start_level`` from ``pywt.swt``.
    wavelet : Wavelet object or name string
        Wavelet to use

    Returns
    -------
    1D array of reconstructed data.

    Examples
    --------
    >>> import pywt
    >>> coeffs = pywt.swt([1,2,3,4,5,6,7,8], 'db2', level=2)
    >>> pywt.iswt(coeffs, 'db2')
    array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.])
    r   T)r   copyc             S   s   g | ]\}}|j |j fqS r   )r   )r   r   r   r   r   r   r   z   s    ziswt.<locals>.<listcomp>c             S   s   g | ]\}}|j |j fqS r   )r    )r   r   r   r   r   r   r   {   s    y              ?periodizationr      r   )r   cNg       @)r
   r   r#   r   r   r   lenr   r	   Zfrom_objectrangeintpowr   r   ZkindZ
complex128Zfloat64Zaranger   roll)coeffsr*   r0   outputr.   r/   
num_levelsmodej	step_size
last_index_r   r   firstindiceseven_indicesodd_indicesx1x2r   r   r   r   Y   sB    
r   c             C   s   t |}t| } t|dkr&tdt|tt|krBtd| jtt|k r^tdt| ||||}g }x0|D ](}|	|d |d |d |d ff qxW |S )	a  
    Multilevel 2D stationary wavelet transform.

    Parameters
    ----------
    data : array_like
        2D array with input data
    wavelet : Wavelet object or name string, or 2-tuple of wavelets
        Wavelet to use.  This can also be a tuple of wavelets to apply per
        axis in ``axes``.
    level : int
        The number of decomposition steps to perform.
    start_level : int, optional
        The level at which the decomposition will start (default: 0)
    axes : 2-tuple of ints, optional
        Axes over which to compute the SWT. Repeated elements are not allowed.

    Returns
    -------
    coeffs : list
        Approximation and details coefficients (for ``start_level = m``)::

            [
                (cA_m+level,
                    (cH_m+level, cV_m+level, cD_m+level)
                ),
                ...,
                (cA_m+1,
                    (cH_m+1, cV_m+1, cD_m+1)
                ),
                (cA_m,
                    (cH_m, cV_m, cD_m)
                )
            ]

        where cA is approximation, cH is horizontal details, cV is
        vertical details, cD is diagonal details and m is ``start_level``.

    Notes
    -----
    The implementation here follows the "algorithm a-trous" and requires that
    the signal length along the transformed axes be a multiple of ``2**level``.
    If this is not the case, the user should pad up to an appropriate size
    using a function such as ``numpy.pad``.
    r4   zExpected 2 axesz'The axes passed to swt2 must be unique.z8Input array has fewer dimensions than the specified axesZaaZdaZadZdd)
tupler   r   r6   r%   setr$   uniquer   r"   )r)   r*   r+   r,   axesZcoefsr1   r5   r   r   r   r      s    .

(c          
   C   s  t | d d }tj| d d |dd}|jdkr:tdt| }t|dd}xvt|D ]h}tt	d|| d }|}| | \}	\}
}}|
j
|j
ks|
j
|j
krtd	tj|gd
d |
||gD   }|j|kr||}xt|D ]}xt|D ]}t||
j
d |}t||
j
d |}t||
j
d d| }t||
j
d d| }t|| |
j
d d| }t|| |
j
d d| }t|||f |
||f |||f |||f ff|d}t|||f |
||f |||f |||f ff|d}t|||f |
||f |||f |||f ff|d}t|||f |
||f |||f |||f ff|d}tj|ddd}tj|ddd}tj|ddd}tj|ddd}|| | | d |||f< qW qW qZW |S )a  
    Multilevel 2D inverse discrete stationary wavelet transform.

    Parameters
    ----------
    coeffs : list
        Approximation and details coefficients::

            [
                (cA_n,
                    (cH_n, cV_n, cD_n)
                ),
                ...,
                (cA_2,
                    (cH_2, cV_2, cD_2)
                ),
                (cA_1,
                    (cH_1, cV_1, cD_1)
                )
            ]

        where cA is approximation, cH is horizontal details, cV is
        vertical details, cD is diagonal details and n is the number of
        levels.  Index 1 corresponds to ``start_level`` from ``pywt.swt2``.
    wavelet : Wavelet object or name string, or 2-tuple of wavelets
        Wavelet to use.  This can also be a 2-tuple of wavelets to apply per
        axis.

    Returns
    -------
    2D array of reconstructed data.

    Examples
    --------
    >>> import pywt
    >>> coeffs = pywt.swt2([[1,2,3,4],[5,6,7,8],
    ...                     [9,10,11,12],[13,14,15,16]],
    ...                    'db1', level=2)
    >>> pywt.iswt2(coeffs, 'db1')
    array([[  1.,   2.,   3.,   4.],
           [  5.,   6.,   7.,   8.],
           [  9.,  10.,  11.,  12.],
           [ 13.,  14.,  15.,  16.]])

    r   T)r   r2   r4   zKiswt2 only supports 2D arrays.  see iswtn for a general n-dimensionsal ISWT)r   r   )rN   r   z4Mismatch in shape of intermediate coefficient arraysc             S   s   g | ]}t |qS r   )r
   )r   r5   r   r   r   r   4  s    ziswt2.<locals>.<listcomp>r3   )r-      )r
   r   r#   r$   r%   r6   r   r7   r8   r9   r&   RuntimeErrorresult_typer   astypeslicer   r:   )r;   r*   r0   r<   r=   waveletsr?   r@   rA   rB   ZcHZcVr   common_dtypeZfirst_hZfirst_wZ	indices_hZ	indices_wZ
even_idx_hZ
even_idx_wZ	odd_idx_hZ	odd_idx_wrG   rH   Zx3Zx4r   r   r   r      sh    0










(c          
      s  t   ts~t  r~t j||||}t j||||}g }x8t||D ]*\|t	fdd
 D  qLW |S  jt dkrtd jdk rtd|dkrt j} fdd	|D }t|tt|krtd
t|}t||}	g }
xt||| D ]}d fg}xlt||	D ]^\}}g }xJ|D ]B\}}t||d||dd \}}||d |f|d |fg q:W |}q(W t	|}|
| |d|   qW |
  |
S )a  
    n-dimensional stationary wavelet transform.

    Parameters
    ----------
    data : array_like
        n-dimensional array with input data.
    wavelet : Wavelet object or name string, or tuple of wavelets
        Wavelet to use.  This can also be a tuple of wavelets to apply per
        axis in ``axes``.
    level : int
        The number of decomposition steps to perform.
    start_level : int, optional
        The level at which the decomposition will start (default: 0)
    axes : sequence of ints, optional
        Axes over which to compute the SWT. A value of ``None`` (the
        default) selects all axes. Axes may not be repeated.

    Returns
    -------
    [{coeffs_level_n}, ..., {coeffs_level_1}]: list of dict
        Results for each level are arranged in a dictionary, where the key
        specifies the transform type on each dimension and value is a
        n-dimensional coefficients array.

        For example, for a 2D case the result at a given level will look
        something like this::

            {'aa': <coeffs>  # A(LL) - approx. on 1st dim, approx. on 2nd dim
             'ad': <coeffs>  # V(LH) - approx. on 1st dim, det. on 2nd dim
             'da': <coeffs>  # H(HL) - det. on 1st dim, approx. on 2nd dim
             'dd': <coeffs>  # D(HH) - det. on 1st dim, det. on 2nd dim
            }

        For user-specified ``axes``, the order of the characters in the
        dictionary keys map to the specified ``axes``.

    Notes
    -----
    The implementation here follows the "algorithm a-trous" and requires that
    the signal length along the transformed axes be a multiple of ``2**level``.
    If this is not the case, the user should pad up to an appropriate size
    using a function such as ``numpy.pad``.
    c             3   s&   | ]}|| d  |   fV  qdS )y              ?Nr   )r   k)idictrdictr   r   	<genexpr>  s    zswtn.<locals>.<genexpr>objectz"Input must be a numeric array-liker   zInput data must be at least 1DNc                s"   g | ]}|d k r| j  n|qS )r   )r$   )r   a)r)   r   r   r     s    zswtn.<locals>.<listcomp>z'The axes passed to swtn must be unique. )r+   r,   r-   r   r[   d)r   r   r   r   r   r   r    r!   r"   dictkeysr   	TypeErrorr$   r%   r7   r6   rL   r   r(   extendreverse)r)   r*   r+   r,   rN   r   r    ZcplxZnum_axesrT   r1   ir;   r-   Z
new_coeffsZsubbandxr   r   r   )r)   rW   rX   r   r   d  sH    -
"






c          	      sZ  t dd | d  D }t| d d|  }tj| d d|  |dd}|j |dkrbt|j} fdd	|D }t|tt|krt	d
|t|krt	dt| }t
||}tdg  }tdg  }	tdg  }
tdg  }xdt|D ]V}ttd|| d }|}| | d| }| | }tj|gdd	 | D   }|j|krh||}dd	 | D ttdkrtdtfdd	|D }xtt|g|  D ]|}xXt|||D ]H\}}}t|||||< t||d| |	|< t|| |d| |
|< qW | }d|t|< d}xtdg|  D ]}x8t||D ]*\}}|rt|
| ||< n|	| ||< qXW i }x&| D ]\}}|t| ||< qW |t| |d| < t||d|d}x.t||D ] \}}|rtj|d|d}qW |t|  |7  < |d7 }qHW |t|  |  < qW || | d| < qW |S )a  
    Multilevel nD inverse discrete stationary wavelet transform.

    Parameters
    ----------
    coeffs : list
        [{coeffs_level_n}, ..., {coeffs_level_1}]: list of dict
    wavelet : Wavelet object or name string, or tuple of wavelets
        Wavelet to use.  This can also be a tuple of wavelets to apply per
        axis in ``axes``.
    axes : sequence of ints, optional
        Axes over which to compute the inverse SWT. Axes may not be repeated.
        The default is ``None``, which means transform all axes
        (``axes = range(data.ndim)``).

    Returns
    -------
    nD array of reconstructed data.

    Examples
    --------
    >>> import pywt
    >>> coeffs = pywt.swtn([[1,2,3,4],[5,6,7,8],
    ...                     [9,10,11,12],[13,14,15,16]],
    ...                    'db1', level=2)
    >>> pywt.iswtn(coeffs, 'db1')
    array([[  1.,   2.,   3.,   4.],
           [  5.,   6.,   7.,   8.],
           [  9.,  10.,  11.,  12.],
           [ 13.,  14.,  15.,  16.]])

    c             s   s   | ]}t |V  qd S )N)r6   )r   keyr   r   r   rY     s    ziswtn.<locals>.<genexpr>r   r[   T)r   r2   Nc                s    g | ]}|d k r|  n|qS )r   r   )r   r[   )r$   r   r   r     s    ziswtn.<locals>.<listcomp>z'The axes passed to swtn must be unique.zYThe number of axes used in iswtn must match the number of dimensions transformed in swtn.r4   r   c             S   s   g | ]
}|j qS r   )r   )r   vr   r   r   r     s    c             S   s   g | ]\}}|j qS r   )r&   )r   rV   rf   r   r   r   r   	  s    z4Mismatch in shape of intermediate coefficient arraysc                s   g | ]} d  | qS )r   r   )r   ax)shapesr   r   r     s    )r   r   r3   )rN   )r-   )maxr_   r
   r   r#   r$   r7   r6   rL   r%   r   rS   r8   r9   poprQ   valuesr   rR   itemsrP   rK   r   r!   r2   r   r:   )r;   r*   rN   Zndim_transformr0   r<   r=   rT   rD   rE   rF   Zodd_even_slicesr?   r@   rA   r[   ZdetailsrU   Zcoeff_trans_shapeZfirstsrC   Zshrg   ZapproxZntransformsZoddsoZdetails_slicere   valuerd   r   )r$   rh   r   r     st    #


)Nr   r   )r   rI   )r   N)N)warnings	itertoolsr   Znumpyr   Z_c99_configr   Z_extensions._dwtr   Z_extensions._swtr   r   r'   r   r(   Z_extensions._pywtr	   r
   Z	_multidimr   r   Z_utilsr   r   __all__r   r   r   r   r   r   r   r   r   <module>   s   
HT
@w
[