a
    `K                     @   s  d dl m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	Z	d dl
mZ d dlmZmZmZmZmZ d dlmZmZmZmZ d dlmZ dd	lmZ dd
lmZmZmZ ee	jZ e dkrd dl!m"Z" d dl#m$Z$ zd dl#m%Z% W n   dd Z%Y n0 d dl&m'Z'm(Z( n$d dl)m*Z* d dl+m,Z' d dl-m(Z( dZ.dd Z/dd Z0dd Z1G dd de2Z3G dd de2Z4d'd"d#Z5d(d%d&Z6dS ))    )absolute_import)LooseVersionN)Document)CustomJSColumnDataSourceSquare	HoverToolGlyphRenderer)PlotTextCircleRange1d)Figure   )transfer_functions)VisibleDeprecationWarningdownsample_aggregatesummarize_aggregate_values0.12.9)Protocol)notebook_content)encode_utf8c                 C   s   | S N )sr   r   3lib/python3.9/site-packages/datashader/bokeh_ext.py<lambda>        r   )CommsHandle	get_comms)notebook_div)_CommsHandle)r   zF
{plot_div}
<script type="text/javascript">
  {plot_script}
</script>
c                 C   sP   t dkr>t| j| j\}}}tj||d}t|}| j  nt	| j| j}|S )a  "
    Generates an HTML div to embed in the notebook.

    Parameters
    ----------
    image: InteractiveImage
        InteractiveImage instance with a plot

    Returns
    -------
    div: str
        HTML string containing the bokeh plot to be displayed
    r   )Zplot_scriptZplot_div)
bokeh_versionr   prefNOTEBOOK_DIVformatr   docZholdr    )imageZjsZdiv_Zhtmlr   r   r   bokeh_notebook_div/   s    r*   c                 C   s   t dkrLt| jj}|sdS t dkr,t }ntd}|d|}g | j_|S t| jj}|d d 	 g|d< t
dd	| jj|d
gg dS )a  
    Generates a bokeh patch event message given an InteractiveImage
    instance. Uses the bokeh messaging protocol for bokeh>=0.12.10
    and a custom patch for previous versions.

    Parameters
    ----------
    image: InteractiveImage
        InteractiveImage instance with a plot

    Returns
    -------
    msg: str
        JSON message containing patch events to update the plot
    r   Nz2.0.0z1.0z	PATCH-DOCr(   r   dataZModelChanged)attrkindZmodelnew)events
references)r"   listr'   Z_held_eventsr   Zcreatedictdsr+   tolistjsondumpsr$   )r(   r/   Zprotocolmsgr+   r   r   r   patch_eventH   s&    r8   c                 C   sj   t dkr\|| j || j || j | jD ]&\}}|t| |j|gd q2n
||  dS )a5  
    Sends a bokeh patch event message via the supplied comm, using
    binary buffers for bokeh versions >= 0.12.10.

    Parameters
    ----------
    msg: str
        JSON message containing patch events to update the plot
    comm: Comm
        Jupyter comm used to send data to the notebook frontend
    r   )buffersN)r"   sendZheader_jsonZmetadata_jsonZcontent_jsonr9   r5   r6   )r7   commheaderZpayloadr   r   r   
send_patchl   s    r=   c                   @   sX   e Zd ZdZdZdZi ZdddZd	d
 Zdd Z	dddZ
dd Zdd Zdd ZdS )InteractiveImagea3  
    Bokeh-based interactive image object that updates on pan/zoom
    events.

    Given a Bokeh plot and a callback function, calls the function
    whenever the pan or zoom changes the plot's extent, regenerating
    the image dynamically.  Works in a Jupyter/IPython notebook cell,
    using the existing notebook kernel Python process (not a separate
    Bokeh server).  Does not yet support usage outside the notebook,
    but could be extened to use Bokeh server in that case.

    Parameters
    ----------
    bokeh_plot : plot or figure
        Bokeh plot the image will be drawn on
    callback : function
        Python callback function with the signature::

           fn(x_range=(xmin, xmax), y_range=(ymin, ymax),
              w, h, **kwargs)

        and returning a PIL image object.
    delay : int
        Specifies the delay between the first received event
        and when events are actually processed. Useful to
        ignore events generated immediately after initiating
        zooming.
    timeout: int
        Determines the timeout after which the callback will
        process new events without the previous one having
        reported completion. Increase for very long running
        callbacks.
    **kwargs
        Any kwargs provided here will be passed to the callback
        function.
    a  
        // Define a callback to capture errors on the Python side
        function callback(msg){{
          if (msg.msg_type == "execute_result") {{
            if (msg.content.data['text/plain'] === "'Complete'") {{
               if (Bokeh._queued.length) {{
                   update_plot();
               }} else {{
                   Bokeh._blocked = false;
               }}
               Bokeh._timeout = Date.now();
            }}
          }} else {{
            console.log("Python callback returned unexpected message:", msg)
          }}
        }}
        var callbacks = {{iopub: {{output: callback}}}};

        function update_plot() {{
            var range = Bokeh._queued;
            var cmd = "{cmd}(" + range + ")"
            // Execute the command on the Python kernel
            if (IPython.notebook.kernel !== undefined) {{
                var kernel = IPython.notebook.kernel;
                kernel.execute(cmd, callbacks, {{silent : false}});
            }}
            Bokeh._queued = [];
        }}

        var plot = x_range.plots[0];
        // Generate a command to execute in Python
        var ranges = {{xmin: x_range.start,
                       ymin: y_range.start,
                       xmax: x_range.end,
                       ymax: y_range.end,
                       w: Math.floor(plot.width),
                       h: Math.floor(plot.height)}}
        var range_str = JSON.stringify(ranges)

        if (!Bokeh._queued) {{
            Bokeh._queued = [];
            Bokeh._blocked = false;
            Bokeh._timeout = Date.now();
        }}

        var timeout = Bokeh._timeout + {timeout};
        if (typeof _ === "undefined") {{
        }} else if ((Bokeh._blocked && (Date.now() < timeout))) {{
            Bokeh._queued = [range_str];
        }} else {{
            Bokeh._queued = [range_str];
            setTimeout(update_plot(), {delay});
            Bokeh._blocked = true;
            Bokeh._timeout = Date.now();
        }}
    z<from {module} import {cls}; {cls}._callbacks['{ref}'].update     Nc                 K   s   t dt || _|| _|| _tt | _	d | _
|| _|| _|rJtd |  \| _| _|  }| jjd| | jjd| d S )NzInteractiveImage has been deprecated as of datashader 0.8.0. It is not supported in JupyterLab and Bokeh server environments. Please use the HoloViews datashader integration instead.zXWarning: throttle parameter no longer supported; will not be accepted in future versionsstart)warningswarnr   r#   callbackkwargsstruuidZuuid4r$   comms_handledelaytimeoutprint_init_imager3   renderer_init_callbackx_rangeZjs_on_changey_range)selfZ
bokeh_plotrD   rI   rJ   ZthrottlerE   r   r   r   __init__   s     zInteractiveImage.__init__c                 C   sn   t | }| |j| j< |jj|j|j| jd}|jj|| jdd| j	| j
d}t| jj| jjd}t||dS )z2
        Generate CustomJS from template.
        )moduleclsr$   -r)   )cmdr$   rI   rJ   )rO   rP   argscode)type
_callbacksr$   cmd_templater&   
__module____name__jscodereplacerI   rJ   r2   r#   rO   rP   r   )rQ   rT   rV   Zcb_codeZcb_argsr   r   r   rN      s    
zInteractiveImage._init_callbackc              	   C   s   | j j| j j }}| j jj| j jj }}| j jj| j jj }}||f}||f}|| ||  }	}
| j||||fi | j}t	t
|jg|g|g|	g|
gdd}| j j|ddddddd	}||fS )
z<
        Initialize RGBA image glyph and datasource
        r(   xydwdhr+   r(   rb   rc   rd   re   F)sourcer(   rb   rc   rd   re   Zdilate)r#   
plot_widthplot_heightrO   rA   endrP   rD   rE   r   r2   r+   
image_rgba)rQ   widthZheightxminxmaxyminymaxrO   rP   rd   re   r(   r3   rM   r   r   r   rL     s    
zInteractiveImage._init_imagec                 C   s`   | j s8t| j}tdkr"|| jfn
|| ji f}t| | _ | | |  }| j j}t	|| dS )a  
        Update the image datasource based on the new ranges,
        serialize the data to JSON and send to notebook via
        a new or existing notebook comms handle.

        Parameters
        ----------
        ranges : dict(xmin=float, xmax=float, ymin=float, ymax=float,
                      h=int, w=int)
            Dictionary with of x/y-ranges, width and height.
        r   ZComplete)
rH   r   r$   r"   r'   r   update_imageget_update_eventZcommsr=   )rQ   rangesr.   r;   Z	comm_argsr7   r   r   r   update%  s    



zInteractiveImage.updatec                 C   s   t | S )z8
        Generate an update event json message.
        )r8   rQ   r   r   r   rr   ;  s    z!InteractiveImage.get_update_eventc                 C   s   |d |d f}|d |d f}|d |d  }|d |d  }| j |||d |d fi | j}t|jg|d g|d g|g|gd	}| jj| d
S )z>
        Updates image with data returned by callback
        rm   rn   ro   rp   r   r   whra   N)rD   rE   r2   r+   r3   rt   )rQ   rs   rO   rP   re   rd   r(   Znew_datar   r   r   rq   A  s    zInteractiveImage.update_imagec                 C   s4   t  | _| j D ]
}d |_q| j| j t| S r   )r   r'   r#   r0   Z	_documentZadd_rootr*   )rQ   mr   r   r   _repr_html_P  s
    zInteractiveImage._repr_html_)r?   r@   N)N)r^   r]   __qualname____doc__r_   r\   r[   rR   rN   rL   rt   rr   rq   ry   r   r   r   r   r>      s   %9

r>   c                   @   sV   e Zd ZdZddd	Zed
d Zejdd Zedd Zejdd Zdd Z	dS )
HoverLayeram  
    Wrapper for adding a HoverTool instance to a plot tools which
    highlights values under the user's mouse location.

    Parameters
    ----------
    field_name : str
        Field title which will appear in hover tooltip

    highlight_fill_color : str
        Fill color for glyph which appears on mouse over.

    highlight_line_color : str
        Line color for glyph which appears on mouse over.

    size : int
        Defined hover layer resolution in pixels
        (i.e. height/width of hover grid)

    extent : list
        ``[xmin, ymin, xmax, ymax]`` in data coordinates representing aggregate bounds

    agg : xarray
        Datashader aggregate object (e.g. result of Canvas.points())

    how : str
        Downsample method for summarizing ordinal aggregates (default: mean).
        Options include: mean, sum, max, min, median, std, var, count.
    Value#79DCDE   FNmeanc	           
   	   C   s   |dvrt dttg g g dd| _tddd d |d| _tdd|d|d	|d
| _g | _d}	td| ji|	d| _	t
 | _| j| j_| j| j_| j| j_| j| j_t| j	| jgdd| _|| _|| _|| _|| _|pd| _|| _| jd ur| jd ur|   d S )N)r   summaxminZmedianZstdvarcountzinvalid 'how' downsample method)rb   rc   valuerf   rb   rc   )rb   rc   
fill_color
line_colorsizeg      ?r   )rb   rc   r   
fill_alphar   Z
line_alphar   z#source.selected = cb_data['index'];rg   rW   Zmouse)rD   Z	renderersmoder   )
ValueErrorr   r2   
hover_datar   invisible_squarevisible_squaretooltipsr   Z	_callbackr	   rM   Zdata_sourceZglyphZselection_glyphZnonselection_glyphr   toolextentis_categorical
field_name_agg_sizehowaggcompute)
rQ   r   Zhighlight_fill_colorZhighlight_line_colorr   r   r   r   r   rY   r   r   r   rR   w  sJ    





zHoverLayer.__init__c                 C   s   | j S r   )r   ru   r   r   r   r     s    zHoverLayer.sizec                 C   s6   || _ || j_|| j_| jd ur2| jd ur2|   d S r   )r   r   r   r   r   r   r   rQ   r   r   r   r   r     s
    c                 C   s   | j S r   )r   ru   r   r   r   r     s    zHoverLayer.aggc                 C   s&   || _ | jd ur"| jd ur"|   d S r   )r   r   r   r   r   r   r   r   r     s    c           
      C   sH  t | jd | jd | jjd | j }t | jd | jd | jjd | j }t ||\}}| | d}t| jj	| j| j
d| _g }| jr| j| jjd  j	 }t|D ]H\}}	| jd d d d |f  |t|	< |t|	dt|	f qn| j |d< || jd	f | jj  | jj| || j_| jS )
Nr      r      )rb   rc   r   z@{}r   z@value)npZlinspacer   r   shaper   ZmeshgridZflattenr   valuesr   Z	hover_aggr   Zdimsr4   	enumeraterF   appendr&   r   r   r+   clearrt   r   r   )
rQ   Zsq_xsZsq_ysZagg_xsZagg_ysZnew_hover_datar   Zcatsier   r   r   r     s.    $ zHoverLayer.compute)r}   r~   r~   r   FNNr   )
r^   r]   rz   r{   rR   propertyr   setterr   r   r   r   r   r   r|   X  s&           
7



r|   linearX  c           
   	   C   s   t | |d\}}}tj|||d}|}|dks:|dks:J t||fd|ddd|d}	d	|	_d
|	_d|	_d|	_d|	j_	d	|	j
_|	j|jg|gd	g|| gdgdd |	S )as  
    Helper function to create a Bokeh ``Figure`` object
    with a color ramp corresponding to input aggregate and transfer function.

    Parameters
    ----------
    agg : xarray
        Datashader aggregate object (e.g. result of Canvas.points())

    cmap : list of colors or matplotlib.colors.Colormap, optional
        The colormap to use. Can be either a list of colors (in any of the
        formats described above), or a matplotlib colormap object.

    how : str
        Datashader transfer function name (either linear or log)

    width : int
        Width in pixels of resulting legend figure (default=600)
    r   )cmapr   r   log2   N)r      )rO   ri   rh   Zlod_thresholdtoolbar_locationrP   x_axis_typer   
      Fr   Zscreen)r(   rb   rc   rd   re   Zdw_units)r   tfZshader   min_border_topmin_border_bottommin_border_leftmin_border_rightZyaxisZvisibleZgridZgrid_line_alphark   r   )
r   r   r   rl   Zvals_arrZmin_valZmax_valZimgr   Z
legend_figr   r   r   create_ramp_legend  s4    
r   r   c                 C   s  |d t |  }i }tddd|d< td|d|d< |d|  |d< d|d	< d|d
< d|d< d|d< d|d< d|d< d|d< tf i |}t|  D ]~\}\}}||d  || d  }	|r|| n|}
|td|	|d  |
gd|dd |td|	|d  ||ddd q|S )a  
    Creates a bokeh plot object with circle legend
    swatches and text corresponding to the ``colormap`` key values
    or the optional aliases values.

    Parameters
    ----------
    colormap : dict
        Dictionary of category value to color value

    aliases : dict
        Dictionary of category value to aliases name

    font_size: int
        Font size to use in the legend text
    r   r   r?   )rA   rj   rO   rP   ri      rh   r   r   r   r   Zoutline_line_widthNr   (   g333333?z{}ptz#666666)rb   rc   textZtext_font_sizeZ
text_colorr   g?)rb   rc   r   r   r   r   )	lenr   r
   r   itemsZ	add_glyphr   r&   r   )ZcolormapaliasesZ	font_sizeZy_maxZplot_optionsZlegendr   catZcolorZtext_yZtext_valr   r   r   create_categorical_legend  s<    


r   )r   r   )Nr   )7Z
__future__r   Zdistutils.versionr   rG   r5   rB   Znumpyr   ZbokehZbokeh.documentr   Zbokeh.modelsr   r   r   r   r	   r
   r   r   r   Zbokeh.plottingr    r   r   Zutilsr   r   r   __version__r"   Zbokeh.protocolr   Zbokeh.embed.notebookr   r   Zbokeh.io.notebookr   r   Zbokeh.embedr    Zbokeh.ior!   Zbokeh.util.notebookr%   r*   r8   r=   objectr>   r|   r   r   r   r   r   r   <module>   sD   

$ U 
0