
    0-Ph                         d dl mZ d dlZddlmZ ddlmZ 	 d dlZdZ	n# e
$ r dZ	Y nw xY wdd	Z ej                    	 	 	 ddd
d            ZdS )    )productN   )utils)warnTF   c                    t          |          }t          j        |          r|f| |z
  z  d|z  z   }nM|r)t          |          | dz
  k    rt	          |          dz   }n"t          |          | k    rt          d          t          j        |          r|f| |z
  z  d|z  z   }nM|r)t          |          | dz
  k    rt	          |          dz   }n"t          |          | k    rt          d          t          d |D                       rt          d          |r|d         dk    rt          d	          t          d
 t          ||          D              S )a  Returns all combinations of shifts in n dimensions over the specified
    max_shifts and step sizes.

    Examples
    --------
    >>> s = list(_generate_shifts(2, False, max_shifts=(1, 2), shift_steps=1))
    >>> print(s)
    [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]
    )r   r   z"max_shifts should have length ndimr   c              3   "   K   | ]
}|d k     V  dS )r   N .0ss     _/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/skimage/restoration/_cycle_spin.py	<genexpr>z#_generate_shifts.<locals>.<genexpr>'   s&      
&
&Q1q5
&
&
&
&
&
&    zshift_steps must all be >= 1r   zGMultichannel cycle spinning should not have shifts along the last axis.c                 <    g | ]\  }}t          d |dz   |          S )r   r   )range)r   r   ts      r   
<listcomp>z$_generate_shifts.<locals>.<listcomp>/   s,    QQQDAqU1a!eQ''QQQr   )	intnpisscalarlentuple
ValueErroranyr   zip)ndimmultichannel
max_shiftsshift_stepsmcs        r   _generate_shiftsr$      s    
\		B	{: ? ]dRi04"9<

	 ?#j//TAX55:&&-

	ZD	 	 =>>>	{; ?"nr	2TBY>	 ?#k**dQh66K((4/	[		T	!	!=>>>

&
&+
&
&
&&& 97888 

2!++X
 
 	
 QQC
K4P4PQQQRRr   )channel_axisc                6    i t          j                    |du}t           j        |||          }t	          |          }t          t           j                             fdt          s||dk    rd}t          d           |dk    r? |d                   }	|dd         D ]}
|	 |
          z  }	|	t          |          z  }	nCfd|D             }t          |          t          |          z  }	|	                    |          }	|	S )a
  Cycle spinning (repeatedly apply func to shifted versions of x).

    Parameters
    ----------
    x : array-like
        Data for input to ``func``.
    func : function
        A function to apply to circularly shifted versions of ``x``.  Should
        take ``x`` as its first argument. Any additional arguments can be
        supplied via ``func_kw``.
    max_shifts : int or tuple
        If an integer, shifts in ``range(0, max_shifts+1)`` will be used along
        each axis of ``x``. If a tuple, ``range(0, max_shifts[i]+1)`` will be
        along axis i.
    shift_steps : int or tuple, optional
        The step size for the shifts applied along axis, i, are::
        ``range((0, max_shifts[i]+1, shift_steps[i]))``. If an integer is
        provided, the same step size is used for all axes.
    num_workers : int or None, optional
        The number of parallel threads to use during cycle spinning. If set to
        ``None``, the full set of available cores are used.
    func_kw : dict, optional
        Additional keyword arguments to supply to ``func``.
    channel_axis : int or None, optional
        If None, the image is assumed to be a grayscale (single channel) image.
        Otherwise, this parameter indicates which axis of the array corresponds
        to channels.

        .. versionadded:: 0.19
           ``channel_axis`` was added in 0.19.

    Returns
    -------
    avg_y : np.ndarray
        The output of ``func(x, **func_kw)`` averaged over all combinations of
        the specified axis shifts.

    Notes
    -----
    Cycle spinning was proposed as a way to approach shift-invariance via
    performing several circular shifts of a shift-variant transform [1]_.

    For a n-level discrete wavelet transforms, one may wish to perform all
    shifts up to ``max_shifts = 2**n - 1``. In practice, much of the benefit
    can often be realized with only a small number of shifts per axis.

    For transforms such as the blockwise discrete cosine transform, one may
    wish to evaluate shifts up to the block size used by the transform.

    References
    ----------
    .. [1] R.R. Coifman and D.L. Donoho.  "Translation-Invariant De-Noising".
           Wavelets and Statistics, Lecture Notes in Statistics, vol.103.
           Springer, New York, 1995, pp.125-150.
           :DOI:`10.1007/978-1-4612-2544-7_9`

    Examples
    --------
    >>> import skimage.data
    >>> from skimage import img_as_float
    >>> from skimage.restoration import denoise_tv_chambolle, cycle_spin
    >>> img = img_as_float(skimage.data.camera())
    >>> sigma = 0.1
    >>> img = img + sigma * np.random.standard_normal(img.shape)
    >>> denoised = cycle_spin(img, func=denoise_tv_chambolle,
    ...                       max_shifts=3)  # doctest: +IGNORE_WARNINGS

    Nc                     t          j        |           } |fi }t          j        |t          d | D                                 S )N)axisc              3      K   | ]}| V  d S )Nr   r   s     r   r   z5cycle_spin.<locals>._run_one_shift.<locals>.<genexpr>   s$      !4!41"!4!4!4!4!4!4r   )r   rollr   )shiftxstmpfuncfunc_kw	roll_axesxs      r   _run_one_shiftz"cycle_spin.<locals>._run_one_shift   s^    WQI...d2!!!!wsE!4!4e!4!4!4449EEEEr   r   zThe optional dask dependency is not installed. The number of workers is set to 1. To silence this warning, install dask or explicitly set `num_workers=1` when calling the `cycle_spin` functionr   c                 J    g | ]} t          j                  |           S r   )daskdelayed)r   r   r2   s     r   r   zcycle_spin.<locals>.<listcomp>   s.    GGGq/4<//22GGGr   )num_workers)r   
asanyarrayr$   r   listr   r   dask_availabler   r   sumcompute)r1   r.   r!   r"   r6   r/   r%   r    
all_shiftsmeanr+   futuresr2   r0   s   ``   `      @@r   
cycle_spinr?   2   sp   ^ 
aAt+L!!&,
KPPJj!!JeAFmm$$IF F F F F F F F  
{2kAoo5	
 	
 	
 a~jm,,^ 	* 	*ENN5)))DDJ HGGGJGGG7||c'll*|||44Kr   r	   )r   NN)	itertoolsr   numpyr   _sharedr   _shared.utilsr   r4   r9   ImportErrorr$   channel_as_last_axisr?   r   r   r   <module>rF      s                               KKKNN   NNN!S !S !S !SH 
 q q q q q q q qs    ))