B
    T\]*              	   @   s  d Z ddlmZmZmZ ddlmZ ddlmZ ddl	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 ddlmZ yddl	mZ W n ek
r   ejZY nX dd Ze
jZe
jZe
jZe
jZee
jZee
j Z ee
j!Z!ee
j"Z"e
j#Z#e
j$Z$e
j%Z%e
j&Z&yddl	m'Z'm(Z( W n" ek
r>   ej'Z'ej(Z(Y nX e
j)Z)e
j*Z*e
j+Z+ee, e
j-Z-W dQ R X e
j.Z.ee, e
j/Z/W dQ R X e
j0Z0ee, e
j1Z1W dQ R X d+ddZ2d,ddZ3dd Z4dd Z5dd Z6dd Z7dd Z8d d! Z9d-d"d#Z:d.d%d&Z;d'd( Z<d)d* Z=dS )/z- A set of NumPy functions to apply per chunk     )absolute_importdivisionprint_function)wraps)concatN   )numpy_compat   )	ContainerIterableSequence)flatten)ignoring)Integral)take_along_axisc                s   t  d fdd	}|S )zU
    A wrapper for functions that don't provide keepdims to ensure that they do.
    Nc       	         s    | f|d|i|}|s |S |}|d kr6t | j}t|tttfsL|g}t }x2t | jD ]$}||krt|d7 }q^|td f7 }q^W || }|S )Naxis)N)rangendim
isinstancer
   r   r   tupleslice)	xr   keepdimsargskwargsraxesZr_sliceZ	each_axis)
a_callable /lib/python3.7/site-packages/dask/array/chunk.pykeepdims_wrapped_callable   s    

z3keepdims_wrapper.<locals>.keepdims_wrapped_callable)NN)r   )r   r    r   )r   r   keepdims_wrapper   s    r!   )
nancumprod	nancumsumFc                s   x"t jD ]}| krd |< qW |rLt fddtjD }| tt fddt jD }| |tt djd ddS )a   Coarsen array by applying reduction to fixed size neighborhoods

    Parameters
    ----------
    reduction: function
        Function like np.sum, np.mean, etc...
    x: np.ndarray
        Array to be coarsened
    axes: dict
        Mapping of axis to coarsening factor

    Examples
    --------
    >>> x = np.array([1, 2, 3, 4, 5, 6])
    >>> coarsen(np.sum, x, {0: 2})
    array([ 3,  7, 11])
    >>> coarsen(np.max, x, {0: 3})
    array([3, 6])

    Provide dictionary of scale per dimension

    >>> x = np.arange(24).reshape((4, 6))
    >>> x
    array([[ 0,  1,  2,  3,  4,  5],
           [ 6,  7,  8,  9, 10, 11],
           [12, 13, 14, 15, 16, 17],
           [18, 19, 20, 21, 22, 23]])

    >>> coarsen(np.min, x, {0: 2, 1: 3})
    array([[ 0,  3],
           [12, 15]])

    You must avoid excess elements explicitly

    >>> x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
    >>> coarsen(np.min, x, {0: 3}, trim_excess=True)
    array([1, 4])
    r   c             3   s<   | ]4\}}| |  r*t d | |   nt ddV  qdS )r   N)r   ).0id)r   r   r   	<genexpr>   s   zcoarsen.<locals>.<genexpr>c                s&   g | ]}j |  |   | fqS r   )shape)r$   r%   )r   r   r   r   
<listcomp>   s   zcoarsen.<locals>.<listcomp>r	   )r   )r   r   r   	enumerater(   r   Zreshape)Z	reductionr   r   Ztrim_excessr%   ZindZnewshaper   )r   r   r   coarsen^   s    (r+   c                sN   t  tr g| j  t  tr8 fddt| jD  | tdd  D  S )aD   Trim boundaries off of array

    >>> x = np.arange(24).reshape((4, 6))
    >>> trim(x, axes={0: 0, 1: 1})
    array([[ 1,  2,  3,  4],
           [ 7,  8,  9, 10],
           [13, 14, 15, 16],
           [19, 20, 21, 22]])

    >>> trim(x, axes={0: 1, 1: 1})
    array([[ 7,  8,  9, 10],
           [13, 14, 15, 16]])
    c                s   g | ]}  |d qS )r   )get)r$   r%   )r   r   r   r)      s    ztrim.<locals>.<listcomp>c             s   s"   | ]}t ||r| nd V  qd S )N)r   )r$   Zaxr   r   r   r'      s    ztrim.<locals>.<genexpr>)r   r   r   dictr   r   )r   r   r   )r   r   trim   s
    

r.   c                s|   |dkst  d  t|| j  kr*| S tj| |  d} |dkrPt| dnt| | t fddt| jD  S )a	   Chunk and combine function of topk

    Extract the k largest elements from a on the given axis.
    If k is negative, extract the -k smallest elements instead.
    Note that, unlike in the parent function, the returned elements
    are not sorted internally.
    Tr   )r   Nc             3   s"   | ]}| krnt d V  qd S )N)r   )r$   r%   )r   k_slicer   r   r'      s   ztopk.<locals>.<genexpr>)	AssertionErrorabsr(   np	partitionr   r   r   r   )akr   r   r   )r   r/   r   topk   s    r6   c                s\   |dkst t| | |}  d  tj|  d} |dk r<| S | t fddt| jD  S )zn Final aggregation function of topk

    Invoke topk one final time and then sort the results internally.
    Tr   )r   c             3   s*   | ]"}| krt d d dnt d V  qd S )N)r   )r$   r%   )r   r   r   r'      s   z!topk_aggregate.<locals>.<genexpr>)r0   r6   r2   sortr   r   r   )r4   r5   r   r   r   )r   r   topk_aggregate   s    r9   c             C   s   | |fS )z_ Preparatory step for argtopk

    Put data together with its original indices in a tuple.
    r   )r4   idxr   r   r   argtopk_preprocess   s    r;   c                s   |dkst  d  t| trXtt| } tdd | D  }tdd | D  }n| \}}t||j  krv| S tj||  d}|dkrt	| dnt	| |t
 fdd	t|jD  }t|| t|| fS )
a*   Chunk and combine function of argtopk

    Extract the indices of the k largest elements from a on the given axis.
    If k is negative, extract the indices of the -k smallest elements instead.
    Note that, unlike in the parent function, the returned elements
    are not sorted internally.
    Tr   c             S   s   g | ]\}}|qS r   r   )r$   ai_r   r   r   r)      s    zargtopk.<locals>.<listcomp>c             S   s   g | ]\}}t ||jqS r   )r2   Zbroadcast_tor(   )r$   r<   Zidxir   r   r   r)      s   )r   Nc             3   s"   | ]}| krnt d V  qd S )N)r   )r$   r%   )r   r/   r   r   r'      s   zargtopk.<locals>.<genexpr>)r0   r   listr   r2   Zconcatenater1   r(   Zargpartitionr   r   r   r   r   )
a_plus_idxr5   r   r   r4   r:   idx2r   )r   r/   r   argtopk   s    

rA   c                sl   |dkst t| | |\}} d  tj| d}t|| }|dk rL|S |t fddt|jD  S )z Final aggregation function of argtopk

    Invoke argtopk one final time, sort the results internally, drop the data
    and return the index only.
    Tr   )r   c             3   s*   | ]"}| krt d d dnt d V  qd S )Nr7   )r   )r$   r%   )r   r   r   r'     s   z$argtopk_aggregate.<locals>.<genexpr>)r0   rA   r2   Zargsortr   r   r   r   )r?   r5   r   r   r4   r:   r@   r   )r   r   argtopk_aggregate   s    rB   c             C   s,   t | |||}t||kr(|d d S |S )Nr7   )r2   arangelen)startstopsteplengthdtypeZresr   r   r   rC     s    rC   c             K   s   | j |f|S )N)astype)r   Zastype_dtyper   r   r   r   rJ     s    rJ   Cc             C   s8   |dkrt | } | |S t | } | j|jS d S )NrK   )r2   ZascontiguousarrayviewZasfortranarrayT)r   rI   orderr   r   r   rL     s
    


rL   c                sj    tjtdk | | dk| j  k @ }| | t fddt| jD  S )a   Chunk function of `slice_with_int_dask_array_on_axis`.
    Slice one chunk of x by one chunk of idx.

    Parameters
    ----------
    x: ndarray, any dtype, any shape
        i-th chunk of x
    idx: ndarray, ndim=1, dtype=any integer
        j-th chunk of idx (cartesian product with the chunks of x)
    offset: ndarray, shape=(1, ), dtype=int64
        Index of the first element along axis of the current chunk of x
    x_size: int
        Total size of the x da.Array along axis
    axis: int
        normalized axis to take elements from (0 <= axis < x.ndim)

    Returns
    -------
    x sliced along axis, using only the elements of idx that fall inside the
    current chunk.
    r   c             3   s"   | ]}| krnt d V  qd S )N)r   )r$   r%   )r   r:   r   r   r'   @  s   z,slice_with_int_dask_array.<locals>.<genexpr>)rJ   r2   int64wherer(   r   r   r   )r   r:   offsetZx_sizer   
idx_filterr   )r   r:   r   slice_with_int_dask_array  s    rS   c       	         s   |  tj} t| dk | t| | } d}d}t| xb|D ]Z}| |k| || k @ }t|}t||d | d7 ||7 }|jdkr>||d 7 }q>W |t fddt	|j
D  S )aT   Final aggregation function of `slice_with_int_dask_array_on_axis`.
    Aggregate all chunks of x by one chunk of idx, reordering the output of
    `slice_with_int_dask_array`.

    Note that there is no combine function, as a recursive aggregation (e.g.
    with split_every) would not give any benefit.

    Parameters
    ----------
    idx: ndarray, ndim=1, dtype=any integer
        j-th chunk of idx
    chunk_outputs: ndarray
        concatenation along axis of the outputs of `slice_with_int_dask_array`
        for all chunks of x and the j-th chunk of idx
    x_chunks: tuple
        dask chunks of the x da.Array along axis, e.g. ``(3, 3, 2)``
    axis: int
        normalized axis to take elements from (0 <= axis < x.ndim)

    Returns
    -------
    Selection from all chunks of x for the j-th chunk of idx, in the correct
    order
    r   r   r7   c             3   s"   | ]}| krnt d V  qd S )N)r   )r$   r%   )r   	idx_finalr   r   r'   w  s   z6slice_with_int_dask_array_aggregate.<locals>.<genexpr>)rJ   r2   rO   rP   sumZ
zeros_likeZcumsumsizer   r   r   )	r:   Zchunk_outputsZx_chunksr   Zx_chunk_offsetZchunk_output_offsetZx_chunkrR   Zidx_cumr   )r   rT   r   #slice_with_int_dask_array_aggregateE  s    



rW   )F)N)N)rK   )>__doc__Z
__future__r   r   r   	functoolsr   Ztoolzr   Znumpyr2    r   ZnpcompatZcompatibilityr
   r   r   Zcorer   Zutilsr   Znumbersr   r   ImportErrorr!   rU   ZprodminmaxZargminZ	nanargminZargmaxZ	nanargmaxanyallZnansumZnanprodr"   r#   ZnanminZnanmaxZmeanAttributeErrorZnanmeanvarZnanvarZstdZnanstdr+   r.   r6   r9   r;   rA   rB   rC   rJ   rL   rS   rW   r   r   r   r   <module>   sl   #







9


	-