a
    `\                     @   s8  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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mZ g dZdd Zdd Zdd Zdd Zd&ddZG dd dejjZG dd deZ G dd de Z!G dd  d e Z"e# ddddddd!d!f	ddddded"ddddd#d$d%Z$dS )'    )OrderedDictN)
_ImageBasePatch)BboxTransformedBboxBboxTransform   )
reductions)transfer_functions)Sets1to3)bypixelCanvas)ScalarDSArtistCategoricalDSArtistalpha_colormapdsshowc                 C   s   | j tjd| jd S )z5Cast a uint32 raster to a 4-channel uint8 RGBA array.dtype)   )viewnpZuint8reshapeshapeimg r   1lib/python3.9/site-packages/datashader/mpl_ext.pyuint32_to_uint8   s    r   c                 C   s   | j tjd| jdd S )z2Cast a 4-channel uint8 RGBA array to uint32 rasterr   N)r   r   Zuint32r   r   r   r   r   r   uint8_to_uint32   s    r    c              	   C   s   | j dkr"tjt|| j| jdS | j dkr~tjt|| jd d t| jd | j| jd  f| jd | j| jd  fgdS tdd S )	N   )coordsdims   r   r	   r   )r#   r"   zAggregate must be 2D or 3D.)ndimtfZImager    r"   r#   r   
ValueError)binnedrgbar   r   r   to_ds_image   s    

r*   c                 C   s<   t | jt jr|  }n | jjdkr.| dk}n
t | }|S )Nur   )r   Z
issubdtyper   Zbool_kindZisnan)r(   maskr   r   r   compute_mask.   s    

r.   (         c              
   C   s   ||fD ]}|dk s|dkrt dqtj| \}}}tjjdd||fd||fgd||fd||fgd||fd||fgd|d |d fd|d |d fgd|dS )	a  
    Generate a transparency-based monochromatic colormap.

    Parameters
    ----------
    color : str or tuple
        Color name, hex code or RGB tuple.
    min_alpha, max_alpha: int
        Values between 0 - 255 representing the range of alpha values to use for
        colormapped pixels that contain data.

    Returns
    -------
    :class:`matplotlib.colors.LinearSegmentedColormap`

    r   r0   z/Alpha values must be integers between 0 and 255Z_datashader_alphag              ?)ZredZgreenZbluealpha)N)r'   mplcolorsZto_rgbLinearSegmentedColormap)color	min_alphaZ	max_alphar4   argbr   r   r   r   :   s    
	r   c                       sf   e Zd Zd fdd	ZdddZdd	d
Zdd Zdd Z fddZ fddZ	 fddZ
  ZS )EqHistNormalizeNF   r1   c                    s:   t t| ||| || _d | _|| _tdd|| _d S )Nr   r	   )	superr>   __init___nbins
_bin_edges_ncolorsr   linspace_color_bins)selfvminvmaxclipnbinsZncolors	__class__r   r   rA   _   s
    zEqHistNormalize.__init__c                 C   s  t j|r||j  }| jd u r*| n| j}| jd u rB| n| j}| j}t 	|||d }t 
||\}}t j|ddgdd}	t |}
|
d }|
| }|d }g }d}|d }||krB|dk rB|dkrB|| }|d	krqBt t|| |}t d|}||d  }t |||	}t |}t|d }|d7 }q|dkrb|g|g|d   }n"|| d  }||krtd
 |S )Nr	         ?Zvalid)moder   r   r!   r   i  zCEqHistColorMapper warning: Histogram equalization did not converge.)r   maZ	is_maskedr-   rH   minrI   maxrB   rE   Z	histogramZconvolveZcumsumroundZarangeinterpuniquelenwarningswarn)rG   datanZlowZhighrK   Zeq_bin_edgesZhist_Zeq_bin_centersZcdfZcdf_maxZnorm_cdfZfinite_binsZbinningZ
iterationsZguessZratioZpalette_edgesZpalette_cdfZ	uniq_binsr   r   r   _binningf   sD    




zEqHistNormalize._binningc                 C   s(   t j|}| |d }t j||S )Nr   )r   rP   Zgetmaskprocess_valuemasked_array)rG   rY   rJ   r-   resultr   r   r   __call__   s    zEqHistNormalize.__call__c                 C   sJ   | j d u rtdt|}|r,t|gn|}t|| j | j}||fS )Nz*Not usable until eq_hist has been computed)rC   r'   r   isscalararrayrT   rF   )rG   rY   ra   Zinterpedr   r   r   r]      s    

zEqHistNormalize.process_valuec                 C   s*   | j d u rtdt|g| j| j d S )Nz.Not invertible until eq_hist has been computedr   )rC   r'   r   rT   rF   )rG   valuer   r   r   inverse   s    
zEqHistNormalize.inversec                    s$   t t| | | || j| _d S N)r@   r>   	autoscaler\   rD   rC   rG   ArL   r   r   rf      s    zEqHistNormalize.autoscalec                    s$   t t| | | || j| _d S re   )r@   r>   autoscale_Noner\   rD   rC   rg   rL   r   r   ri      s    zEqHistNormalize.autoscale_Nonec                    s   t t|  o| jd uS re   )r@   r>   scaledrC   rG   rL   r   r   rj      s    zEqHistNormalize.scaled)NNFr?   r1   )r1   )N)__name__
__module____qualname__rA   r\   r`   r]   rd   rf   ri   rj   __classcell__r   r   rL   r   r>   ^   s   
.
r>   c                       sX   e Zd Zd fdd	Zdd Zdd ZdddZdd Zdd Zdd Z	dd Z
  ZS )DSArtistlowernonec                    s   t  j|f||d| || _|| _|| _|| _|| _|| _|| _|| _	|| _
|| _|	d u r||j}||  ||  f}	|
d u r|j}||  ||  f}
||	 ||
 d S )N)origininterpolation)r@   rA   axesdfglyph
aggregatoragg_hook
shade_hook
plot_widthplot_heightwidth_scaleheight_scaleZx_labelrQ   rR   Zy_labelZset_xlimZset_ylim)rG   axrv   rw   rx   ry   rz   r{   r|   x_rangey_ranger}   r~   rs   rt   kwargsZx_colZy_colrL   r   r   rA      s&    
zDSArtist.__init__c                 C   s   | j j j}| jdu r4tt|d d | j }n| j}| jdu r`tt|d d | j }n| j}t	||||d}t
| j|| j| j}|S )z7Aggregate data in given range to the window dimensions.Nr!   rN   r$   )r{   r|   r   r   )ru   ZpatchZget_window_extentZboundsr{   intr}   r|   r~   r   r   rv   rw   rx   )rG   r   r   r#   r{   r|   Zcanvasr(   r   r   r   	aggregate   s    

zDSArtist.aggregatec                 C   s   t dS )z(Convert an aggregate into an RGBA array.N)NotImplementedErrorrG   r(   r   r   r   shade   s    zDSArtist.shader2   Tc                 C   s   |   \}}}}tt||g||gg}|  }	t||	}
| jdusd| jdusd| jdksd| j	dkrhd}| 
||g||g}| jdur| |}| | | |}| jdurt||}| |}t|j}| | | j|||
| jj||dS )am  
        Normalize, rescale, and colormap this image's data for rendering using
        *renderer*, with the given *magnification*.

        If *unsampled* is True, the image will not be scaled, but an
        appropriate affine transformation will be returned instead.

        Returns
        -------
        image : (M, N, 4) uint8 array
            The RGBA image, resampled unless *unsampled* is True.
        x, y : float
            The upper left corner where the image should be drawn, in pixel
            space.
        trans : Affine2D
            The affine transformation from image to pixel space.
        Nr2   F)magnification	unsampled)
get_extentr   r   rb   Zget_transformr   r{   r|   r}   r~   r   ry   set_ds_datar   rz   r*   r   rY   	set_arrayZ_make_imageru   bbox)rG   Zrendererr   r   x1x2y1y2r   transZtransformed_bboxr(   r)   r   r   r   r   
make_image   s>    









zDSArtist.make_imagec                 C   s
   || _ dS )z
        Set the aggregate data for the bounding box currently displayed.
        Should be a :class:`xarray.DataArray`.
        NZ_ds_datar   r   r   r   r   -  s    zDSArtist.set_ds_datac                 C   s   | j S )z
        Return the aggregated, pre-shaded :class:`xarray.DataArray` backing the
        bounding box currently displayed.
        r   rk   r   r   r   get_ds_data4  s    zDSArtist.get_ds_datac                 C   s*   | j  | j   \}}\}}||||fS )z;Return the image extent as tuple (left, right, bottom, top))ru   get_xlimget_ylim)rG   r   r   r   r   r   r   r   r   ;  s    zDSArtist.get_extentc                 C   s   |   \}}}}| jdkr$|| }}|  j}t||g||gg}tddg|jdd g}t||d}	|j|j }
}|		|
|g
t\}}d|  kr|jd k rn nd|  kr|jd k sn dS |||f S dS )z
        Return the aggregated data at the event position or *None* if the
        event is outside the bounds of the current view.
        upperr   Nr!   )ZboxinZboxoutr	   )r   rs   r   rY   r   r   r   ZydataZxdataZtransform_pointZastyper   )rG   ZeventZxminZxmaxZyminZymaxZarrZdata_extentZarray_extentr   yxijr   r   r   get_cursor_data@  s    


:zDSArtist.get_cursor_data)rq   rr   )r2   T)rl   rm   rn   rA   r   r   r   r   r   r   r   ro   r   r   rL   r   rp      s     &
7rp   c                       s6   e Zd Zd fdd	Zdd Zdd Zd	d
 Z  ZS )r   Nr2   c                    s   t  j|||||||||	|
||fi | |j| _|j| _| | | | | | | 	| j
 | j
 }| jd ur| |}| | | td d S Nr!   )r@   rA   rH   _vminrI   _vmaxZset_normZset_cmapZ	set_alphar   ru   r   r   ry   r   r   r   eye)rG   r   rv   rw   rx   ry   rz   r{   r|   r   r   r}   r~   normcmapr3   r   r(   rL   r   r   rA   Y  s4    





zScalarDSArtist.__init__c                 C   sP   t |j}tj|j|}| | | j| j_| j	| j_
|   | j|dddS NT)bytesr   )r.   rY   r   rP   r^   r   r   r   rH   r   rI   ri   to_rgba)rG   r(   r-   rh   r   r   r   r     s    



zScalarDSArtist.shadec                 C   s&   |   }| j|  ddd}t||S r   )r   r   	get_arrayr*   rG   r(   r)   r   r   r   get_ds_image  s    zScalarDSArtist.get_ds_imagec                 C   s   d S re   r   rk   r   r   r   get_legend_elements  s    z"ScalarDSArtist.get_legend_elements)NNNNNNr2   r2   NNNrl   rm   rn   rA   r   r   r   ro   r   r   rL   r   r   X  s              1r   c                       s6   e Zd Zd fdd	Zdd Zdd	 Zd
d Z  ZS )r   Nr2   r/   r0   c                    s   t  j|||||||||	|
||fi | || _|| _|| _| | j | j }| j	d urh| 	|}| 
| | td d S r   )r@   rA   
_color_key_alpha_range_color_baseliner   ru   r   r   ry   r   r   r   r   )rG   r   rv   rw   rx   ry   rz   r{   r|   r   r   r}   r~   	color_keyalpha_rangecolor_baseliner   r(   rL   r   r   rA     s0    


zCategoricalDSArtist.__init__c                 C   s2   t j|| j| jd | jd | jd}t|j}|S )Nr   r	   )r   r9   r3   r   )r&   r   r   r   r   r   rY   )rG   r(   r   r)   r   r   r   r     s    
zCategoricalDSArtist.shadec                 C   s   |   }|  }t||S re   )r   r   r*   r   r   r   r   r     s    z CategoricalDSArtist.get_ds_imagec                 C   sP   t | jts8|  }|j|jd  j}tt|| j}n| j}dd | D S )zU
        Return legend elements to display the color code for each category.
        r!   c                 S   s   g | ]\}}t |d |dqS )rr   )Z	facecolorZ	edgecolorZlabelr   ).0categoryr8   r   r   r   
<listcomp>  s   z;CategoricalDSArtist.get_legend_elements.<locals>.<listcomp>)	
isinstancer   dictr   r"   r#   rY   zipitems)rG   r(   
categoriesZ
color_dictr   r   r   r     s    z'CategoricalDSArtist.get_legend_elements)NNNNNNr2   r2   Nr   Nr   r   r   rL   r   r     s              /r   r2   r   )r   r   r3   rH   rI   r   r   r   r   fignumaspectc                K   s  ddl m} |dkr| }n |du r>||}|g d}t|tjrzt|| ||||f|||||	|
|||d	|}n|durt|t	rt
jjd|}|du rt
j }nZt|tr
|dkrt
j }n:|dkrt
j }n&|dkrt
jd	}n|d
kr
t }t|t
jjs"td|dur2||_|durB||_t|| ||||f|||||	|
|||d	|}|| |du r|jd }|| |S )a  
    Display the output of a data shading pipeline applied to a dataframe.

    The plot will respond to changes in the data space bounds displayed, such
    as pan/zoom events. Both scalar and categorical pipelines are supported.

    Parameters
    ----------
    df : pandas.DataFrame, dask.DataFrame
        Dataframe to apply the datashading pipeline to.
    glyph : Glyph
        The glyph to bin by.
    aggregator : Reduction, optional, default: :class:`~.count`
        The reduction to compute per-pixel.
    agg_hook : callable, optional
        A callable that takes the computed aggregate as an argument, and
        returns another aggregate. This can be used to do preprocessing before
        the aggregate is converted to an image.
    shade_hook : callable, optional
        A callable that takes the image output of the shading pipeline, and
        returns another :class:`~.Image` object. See :func:`~.dynspread` and
        :func:`~.spread` for examples.
    plot_width, plot_height : int, optional
        Grid dimensions, i.e. the width and height of the output aggregates in
        pixels. Default is to use the native width and height dimensions of
        the axes bounding box.
    x_range, y_range : pair of float, optional
        A tuple representing the initial bounds inclusive space ``[min, max]``
        along the axis. If None, the initial bounds will encompass all of the
        data along the axis.
    height_scale : float, optional
        Factor by which to scale the height of the image in pixels relative to
        the height of the display space in pixels.
    width_scale : float, optional
        Factor by which to scale the width of the image in pixels relative to
        the width of the display space in pixels.
    norm : str or :class:`matplotlib.colors.Normalize`, optional
        For scalar aggregates, a matplotlib norm to normalize the
        aggregate data to [0, 1] before colormapping. The datashader arguments
        'linear', 'log', 'cbrt' and 'eq_hist' are also supported and correspond
        to equivalent matplotlib norms. Default is the linear norm.
    cmap : str or list or :class:`matplotlib.cm.Colormap`, optional
        For scalar aggregates, a matplotlib colormap name or instance.
        Alternatively, an iterable of colors can be passed and will be converted
        to a colormap. For a single-color, transparency-based colormap, see
        :func:`alpha_colormap`.
    alpha : float
        For scalar aggregates, the alpha blending value, between 0
        (transparent) and 1 (opaque).
    vmin, vmax : float, optional
        For scalar aggregates, the data range that the colormap covers.
        If vmin or vmax is None (default), the colormap autoscales to the
        range of data in the area displayed, unless the corresponding value is
        already set in the norm.
    color_key : dict or iterable, optional
        For categorical aggregates, the colors to use for blending categories.
        See `tf.shade`.
    alpha_range : pair of int, optional
        For categorical aggregates, the minimum and maximum alpha values in
        [0, 255] to use to indicate data values of non-empty pixels. The
        default range is (40, 255).
    color_baseline : float, optional
        For categorical aggregates, the baseline for calculating how
        categorical data mixes to determine the color of a pixel. See
        `tf.shade` for more information.

    Other Parameters
    ----------------
    ax : `matplotlib.Axes`, optional
        Axes to draw into. If *None*, create a new figure or use ``fignum`` to
        draw into an existing figure.
    fignum : None or int or False, optional
        If *None* and ``ax`` is *None*, create a new figure window with
        automatic numbering.
        If a nonzero integer and ``ax`` is *None*, draw into the figure with
        the given number (create it if it does not exist).
        If 0, use the current axes (or create one if it does not exist).
    aspect : {'equal', 'auto'} or float, default: ``rcParams["image.aspect"]``
        The aspect ratio of the axes.
    **kwargs
        All other kwargs are passed to the artist.

    Returns
    -------
    :class:`ScalarDSArtist` or :class:`CategoricalDSArtist`

    Notes
    -----
    If the aggregation is scalar/single-category (i.e. generates a 2D scalar
    mappable), the artist can be used to make a colorbar. See example.

    If the aggregation is multi-category (i.e. generates a 3D array with
    two or more components that get composited to form an image), you can use
    the :meth:`CategoricalDSArtist.get_legend_elements` method to obtain patch
    handles that can be used to make a legend. See example.

    Examples
    --------
    Generate two Gaussian point clouds and (1) plot the density as a
    quantitative map and (2) color the points by category.

    .. plot::
        :context: close-figs

        >>> import pandas as pd
        >>> import datashader as ds
        >>> import matplotlib.pyplot as plt
        >>> from datashader.mpl_ext import dsshow
        >>> n = 10000
        >>> df = pd.DataFrame({
        ...     'x': np.r_[np.random.randn(n) - 1, np.random.randn(n) + 1],
        ...     'y': np.r_[np.random.randn(n), np.random.randn(n)],
        ...     'c': pd.Categorical(np.r_[['cloud 1'] * n, ['cloud 2'] * n])
        ... })
        >>> da1 = dsshow(
        ...     df,
        ...     ds.Point('x', 'y'),
        ...     aspect='equal'
        ... )
        >>> plt.colorbar(da1);  # doctest: +SKIP
        >>> da2 = dsshow(
        ...     df,
        ...     ds.Point('x', 'y'),
        ...     ds.count_cat('c'),
        ...     aspect='equal'
        ... )
        >>> plt.legend(handles=da2.get_legend_elements());  # doctest: +SKIP

    r   N)g333333?g
ףp=
??r   )	r{   r|   r   r   r}   r~   r   r   r   Z_datashaderZlinearlogZcbrtgUUUUUU?Zeq_histzX`norm` must be one of 'linear', 'log', 'cbrt', 'eq_hist', or a matplotlib norm instance.)	r{   r|   r   r   r}   r~   r   r   r3   zimage.aspect)Zmatplotlib.pyplotZpyplotZgcaZfigureZadd_axesr   r
   Zbyr   listr5   r6   r7   	from_list	NormalizestrZLogNormZ	PowerNormr>   r'   rH   rI   r   Z
add_artistZrcParamsZ
set_aspect)rv   rw   rx   ry   rz   r{   r|   r   r   r}   r~   r   r   r3   rH   rI   r   r   r   r   r   r   r   ZpltZfigZartistr   r   r   r     s     









r   )r/   r0   r1   )%collectionsr   rW   Zmatplotlib.imager   Zmatplotlib.patchesr   Zmatplotlib.transformsr   r   r   Z
matplotlibr5   Znumpyr    r
   r   r&   r6   r   corer   r   __all__r   r    r*   r.   r   r   r>   rp   r   r   countr   r   r   r   r   <module>   sV   
$U &IT