a
    ~b'                    @   s  d dl mZmZmZ d dlZ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mZmZmZmZmZmZmZmZmZmZmZ d dlmZ d dlmZ d dlmZ d	d
l m!Z! d	dl"m#Z# d	dl$m%Z%m&Z&m'Z'm(Z( d	dl)m*Z* d	dl+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJ ddlKmLZLmMZMmNZNmOZOmPZPmQZQ ddlRmSZSmTZT ddlUmVZVmWZWmXZX eWeVdkrdZYndZYG dd deZZ[G dd de[Z\G dd de[Z]G dd de\e]Z^G dd  d e^Z_G d!d" d"e_Z`G d#d$ d$e_ZaG d%d& d&e_ZbG d'd( d(e_ZcG d)d* d*ecZdG d+d, d,ecZeG d-d. d.ecZfG d/d0 d0ecZgG d1d2 d2e_ZhG d3d4 d4e_ZiG d5d6 d6e^ZjG d7d8 d8ejZkG d9d: d:ejZlG d;d< d<e^ZmG d=d> d>e^ZnG d?d@ d@e^ZoG dAdB dBeoZpG dCdD dDe^ZqG dEdF dFe^ZrG dGdH dHe^ZsG dIdJ dJe^ZtG dKdL dLe^ZuG dMdN dNe^ZvG dOdP dPevZwG dQdR dRewZxG dSdT dTewZyG dUdV dVewZzG dWdX dXezZ{G dYdZ dZewZ|G d[d\ d\ezZ}e,j~d] Ze_ee-< e`ee2< eaee3< ecee6< edee7< egee8< eeee;< efee<< ehee9< eiee:< ejee.< ekee0< elee1< eoee?< eqee4< eree5< eseeI< etee/< emee=< eneeJ< epeeH< ebee>< euee@< eveeE< e|eeA< exeeB< eyeeG< e{eeF< ezeeC< e}eeD< G d^d_ d_ejZG d`da daeZG dbdc dceZG ddde deeZG dfdg dgeZG dhdi dieZeLj~d] ZeeeO< eeeN< eeeP< eeeQ< eeeM< dS )j    )absolute_importdivisionunicode_literalsN)defaultdict)partial)CustomJSFactorRangeDatetimeAxis
ToolbarBoxRange1dDataRange1dPolyDrawToolBoxEditToolPolyEditToolFreehandDrawToolPointDrawTool)state)JS_CALLBACK)gen   )OrderedDict)CallbackError)datetime_typesdimension_sanitizerisscalar
dt64_to_dt)Table)Stream	PointerXYRangeXYSelection1DRangeXRangeYPointerXPointerYBoundsXBoundsYTap	SingleTap	DoubleTap
MouseEnter
MouseLeavePressUpPanEndPlotSizeDrawBoundsXY	PlotResetBoxEdit	PointDrawPolyDrawPolyEdit	CDSStreamFreehandDraw	CurveEditSelectionXYLasso
SelectMode   )LinkRectanglesTableLinkDataLinkRangeToolLinkSelectionLinkVertexTableLink)GenericElementPlotGenericOverlayPlot   )LooseVersionbokeh_versionconvert_timestampz2.3.0descriptionZcustom_tooltipc                   @   sx   e Zd ZdZi Zg Zg Zg Zg Zg Z	i Z
g Zdd Zdd Zdd Zdd	 Zd
d Zdd Zdd Zdd Zdd ZdS )MessageCallbackz
    A MessageCallback is an abstract baseclass used to supply Streams
    with events originating from bokeh plot interactions. The baseclass
    defines how messages are handled and the basic specification required
    to define a Callback.
    c                 C   s   | j D ]}||| }q|S N)_transforms)selfmsgZ	transform rO   Alib/python3.9/site-packages/holoviews/plotting/bokeh/callbacks.py
_transformK   s    
zMessageCallback._transformc                 C   s
   |  |S )zn
        Subclassable method to preprocess JSON message in callback
        before passing to stream.
        rQ   rM   rN   rO   rO   rP   _process_msgP   s    zMessageCallback._process_msgc                 K   s   || _ || _|jjdks$tjjdkr,d | _n8|jrDt	|jj
|j}nd }|jjj| jd| _|| j_
|| _tt| _|   d S )NZserverdefault)on_msg)plotstreamsrenderermodepnZconfigZcommscommZpaner   Z	_on_errorrootZcomm_managerZget_client_commrV   sourcer   dict
handle_idsreset)rM   rW   rX   r^   paramsZon_errorrO   rO   rP   __init__W   s    
zMessageCallback.__init__c                    s`       d  _d  _d  _g  _ jrBz j  W n   Y n0  fddtj	 D t_d S )Nc                    s   i | ]\}}| ur||qS rO   rO   ).0kcbrM   rO   rP   
<dictcomp>r   s   z+MessageCallback.cleanup.<locals>.<dictcomp>)
ra   r`   rW   r^   rX   r\   closeCallback
_callbacksitemsrg   rO   rg   rP   cleanupg   s    zMessageCallback.cleanupc                 C   sd   | j rN|  }| jD ]8}||vr"q|| }t|tt| f}| j|d  qg | _i | _g | _	d S rK   )
r`   _init_plot_handlesmodelsidtyperk   pop	callbacksplot_handles_queue)rM   handleshandle_namehandlecb_hashrO   rO   rP   ra   u   s    
zMessageCallback.resetc                 C   sN   i }|  D ]<\}}t|tr@d|v r@|d |v rH|d ||< q|||< q|S )z
        Filter event values that do not originate from the plotting
        handles associated with a particular stream using their
        ids to match them.
        rp   value)rl   
isinstancer_   )rM   rN   idsfiltered_msgre   vrO   rO   rP   _filter_msg   s    
zMessageCallback._filter_msgc              
      sP  g } j D ]h} j| }t| } ||} |}|s@q
|jf i |  fdd| D |_|	| q
zzt
| W n ty } z\ jjr jjjd tjv rtj jjjd  \}	}
|	jdt|idd n|W Y d }~n2d }~0  ty  } z|W Y d }~n
d }~0 0 W |D ]}i |_q(n|D ]}i |_q<0 d S )Nc                    s   i | ]\}}|| j d qS ))rp   events)	on_events)rd   hZhidrg   rO   rP   rh      s   z*MessageCallback.on_msg.<locals>.<dictcomp>rp   z	text/htmlT)raw)rX   r`   listvaluesr   rT   updaterl   Z	_metadataappendr   Ztriggerr   rW   r]   refr   Z_handlesstr	Exception)rM   rN   rX   streamr`   r|   r}   Zprocessed_msgerx   _rO   rg   rP   rV      s4    



zMessageCallback.on_msgc                 C   s   | j g}| j jr$|t| j j 7 }i }|D ] }|j D ]\}}|||< q:q,|| _i }| j| j D ]<}|| jv r|| ||< qd|| jv rdt	dt
| j|f  qd| j| | |S )z
        Find all requested plotting handles and cache them along
        with the IDs of the models the callbacks will be attached to.
        zNWarning %s could not find the %s model. The corresponding stream may not work.)rW   Zsubplotsr   r   rv   rl   rt   ro   extra_modelsprintrq   __name__r`   r   _get_stream_handle_ids)rM   plotsrv   rW   re   r~   Z	requestedr   rO   rO   rP   rn      s$    

z"MessageCallback._init_plot_handlesc                 C   sF   t t}| jD ]2}| jD ]&}||v r|| jd }||| |< qq|S )z
        Gather the ids of the plotting handles attached to this callback
        This allows checking that a stream is not given the state
        of a plotting handle it wasn't attached to
        rp   )r   r_   rX   ro   r   )rM   rv   Zstream_handle_idsr   r   Z	handle_idrO   rO   rP   r      s    

z&MessageCallback._get_stream_handle_idsN)r   
__module____qualname____doc__
attributesro   r   skipr   
on_changesrk   rL   rQ   rT   rc   rm   ra   r   rV   rn   r   rO   rO   rO   rP   rJ   .   s$   rJ   c                   @   s>   e Zd ZdZeZdZdZdZe	dd Z
ddd	Zd
d ZdS )CustomJSCallbackz
    The CustomJSCallback attaches CustomJS callbacks to a bokeh plot,
    which looks up the requested attributes and sends back a message
    to Python using a Comms instance.
     i N     c                 C   s   d}d}d}t | D ]\}}dj|d}|d}|d }	ddd	 |d
d D }
|	dvr|j||	|
d}||j|	|d7 }qd||	|
dg}||7 }q|S )a  
        Generates JS code to look up attributes on JS objects from
        an attributes specification dictionary. If the specification
        references a plotting particular plotting handle it will also
        generate JS code to get the ID of the object.

        Simple example (when referencing cb_data or cb_obj):

        Input  : {'x': 'cb_data.geometry.x'}

        Output : data['x'] = cb_data['geometry']['x']

        Example referencing plot handle:

        Input  : {'x0': 'x_range.attributes.start'}

        Output : if ((x_range !== undefined)) {
                    data['x0'] = {id: x_range['id'], value: x_range['attributes']['start']}
                 }
        zC{assign}{{id: {obj_name}["id"], value: {obj_name}{attr_getters}}};
z-if (({obj_name} != undefined)) {{ {assign} }}r   zdata["{key}"] = )key.r   c                 S   s   g | ]}d j |dqS )z
["{attr}"])attr)format)rd   r   rO   rO   rP   
<listcomp>
  s   z2CustomJSCallback.attributes_js.<locals>.<listcomp>rE   N)cb_objZcb_data)assignobj_nameattr_getters)r   r   z;
)sortedrl   r   splitjoin)clsr   Zassign_templateZconditional_templatecoder   	attr_pathZdata_assignattrsr   r   Z
assign_strrO   rO   rP   attributes_js   s(    




zCustomJSCallback.attributes_jsNc           	      C   s   |du r| j jpd}| jj| jj| j| j|d}| | j}dd | j	D }d}|rbdd
| }d	}|| | | j | }t||d
S )zm
        Creates a CustomJS callback that will send the requested
        attributes back to python.
        NZPLACEHOLDER_PLOT_ID)Zcomm_idtimeoutdebounceplot_idc                 S   s   g | ]}d | qS )z%srO   )rd   ZcondrO   rO   rP   r   '      z1CustomJSCallback.get_customjs.<locals>.<listcomp>r   zif (%s) { return };
z || zvar data = {};
argsr   )rW   rp   js_callbackr   r\   r   r   r   r   r   r   r   r   )	rM   
referencesr   Zself_callbackr   Z
conditionsZconditionaldatar   rO   rO   rP   get_customjs  s    zCustomJSCallback.get_customjsc                 C   s@   | j r| j D ]}||| q| jr<| jD ]}||| q*dS )z
        Generates a CustomJS callback by generating the required JS
        code and gathering all plotting handles and installs it on
        the requested callback handle.
        N)r   js_on_eventr   js_on_change)rM   r   rx   eventchangerO   rO   rP   set_customjs_callback/  s    

z&CustomJSCallback.set_customjs_callback)N)r   r   r   r   r   r   r   r   r   classmethodr   r   r   rO   rO   rO   rP   r      s   
+
r   c                       s   e Zd ZdZdZdZdZg Zg Z fddZ	e
ddd	Zd
d Zdd Zdd Zd ddZdd Zdd Zdd Zejdd Zejdd Zdd Z  ZS )!ServerCallbacka  
    Implements methods to set up bokeh server callbacks. A ServerCallback
    resolves the requested attributes on the Python end and then hands
    the msg off to the general on_msg handler, which will update the
    Stream(s) attached to the callback.

    The ServerCallback supports three different throttling modes:

    - adaptive (default): The callback adapts the throttling timeout
      depending on the rolling mean of the time taken to process each
      message. The rolling window is controlled by the `adaptive_window`
      value.
    - throttle: Uses the fixed `throttle_timeout` as the minimum amount
      of time between events.
    - debounce: Processes the message only when no new event has been
      received within the `throttle_timeout` duration.
    r   d   adaptivec                    s<   t t| j|||fi | d| _d | _t | _g | _d S )NF)superr   rc   _active	_prev_msgtime_last_event_history)rM   rW   rX   r^   rb   	__class__rO   rP   rc   Y  s
    
zServerCallback.__init__Nc                 C   sx   |st d| |du r|}|d}|}|dd D ]0}|dkrDq6t|trZ||}q6t||d}q6|jd |dS )z
        Resolves a Callback attribute specification looking the
        corresponding attribute up on the cb_obj, which should be a
        bokeh model. If not model is supplied cb_obj is assumed to
        be the same as the model.
        z*Bokeh plot attribute %s could not be foundNr   rE   r   rp   )rp   rz   )r   r   r{   r_   getgetattrr   )r   specr   ZmodelZresolvedprO   rO   rP   resolve_attr_spec`  s    

z ServerCallback.resolve_attr_specc                    s   t  fdd| jD S )Nc                 3   s   | ]}| V  qd S rK   rO   rd   r   r   rO   rP   	<genexpr>x  r   z,ServerCallback.skip_event.<locals>.<genexpr>)anyskip_eventsrM   r   rO   r   rP   
skip_eventw  s    zServerCallback.skip_eventc                    s   t  fdd| jD S )Nc                 3   s   | ]}| V  qd S rK   rO   r   rN   rO   rP   r   {  r   z-ServerCallback.skip_change.<locals>.<genexpr>)r   skip_changesrS   rO   r   rP   skip_changez  s    zServerCallback.skip_changec                 C   sL   dt jvrdS ddlm} |t  |t _W d   n1 s>0    Y  dS )z8
        Sets panel.state to busy if available.
        busyNr   )edit_readonly)r   paramZ
panel.utilr   r   )rM   r   r   rO   rO   rP   	_set_busy}  s
    

zServerCallback._set_busyTc                 C   s   |d u rf| j r2| jdkr2tt| j  d }n| j}| jdkrf|rft | j }t	||d  d}t
jjsddlm} | t|d | nt
jj|t| d S )Nr     r   2   r   )IOLoop     @@)r   throttling_schemeintnparraymeanthrottle_timeoutr   r   maxr[   r   ZcurdocZtornado.ioloopr   currentZ
call_laterZadd_timeout_callback)rM   rf   r   offsetdiffr   rO   rO   rP   _schedule_callback  s    z!ServerCallback._schedule_callbackc                 C   sJ   | j |||t f | jsF| jjrFd| _| d | j| jdd dS )z
        Process change events adding timeout to process multiple concerted
        value change at once rather than firing off multiple plot updates.
        TFr   N)	ru   r   r   r   rW   documentr   r   process_on_change)rM   r   oldnewrO   rO   rP   	on_change  s
    
zServerCallback.on_changec                 C   sF   | j |t f | jsB| jjrBd| _| d | j| jdd dS )z
        Process bokeh UIEvents adding timeout to process multiple concerted
        value change at once rather than firing off multiple plot updates.
        TFr   N)	ru   r   r   r   rW   r   r   r   process_on_eventr   rO   rO   rP   on_event  s
    
zServerCallback.on_eventc                 C   s   t   }| jd }| jdv r`|| j }| jrF| jdkrFt| j }||k rt|| d S n$| j	d d }|| }||k r| jS t   | _dS )Nr   )Zthrottler   r   r   F)
r   r   r   r   r   r   r   r   r   ru   )rM   Znowr   r   Z
prev_eventrO   rO   rP   	throttled  s    



zServerCallback.throttledc           
      C   s   | j sd| _| d dS |  }|r8| | j| dS ttdd | j D  }g | _ |D ]V}| 	|rnq^i }| j
 D ],\}}| j| jd }| |||||< q|| | q^| jd }t | j }	| j| d |	g | _| | j dS )zU
        Trigger callback change event and triggering corresponding streams.
        FNc                 S   s   g | ]\}}|j |fqS rO   )Z
event_name)rd   r   ZdtrO   rO   rP   r     s   z3ServerCallback.process_on_event.<locals>.<listcomp>r   rE   )ru   r   r   r   r   r   r   r   r   r   r   rl   rt   r   ro   r   rV   adaptive_windowr   r   r   )
rM   r   r   r   rN   r   pathZ	model_objwr   rO   rO   rP   r     s0    



zServerCallback.process_on_eventc                 C   s^  | j sd| _| d d S |  }|r8| | j| d S g | _ i }| j D ]n\}}|d}|d dkr| j	d }d
| j	d d |dd   }n|d }| j|}| ||||< qL| |rd}n&z|| jk}W n ty   d}Y n0 |rtdd | jD rN| | | jd }	t | j }
| j|	 d  |
g | _|| _| | j d S )	NFr   r   r   rE   Tc                 s   s   | ]}|j V  qd S rK   )Z	transientrd   srO   rO   rP   r     r   z3ServerCallback.process_on_change.<locals>.<genexpr>)ru   r   r   r   r   r   r   rl   r   ro   r   rt   r   r   r   r   r   r   rX   rV   r   r   r   r   )rM   r   rN   r   r   r   Z
obj_handler   Zequalr   r   rO   rO   rP   r     s>    


"



z ServerCallback.process_on_changec                 C   sN   | j r | j D ]}||| j q| jrJ| jD ]}|dv r:q,||| j q,dS )zH
        Set up on_change events for bokeh server interactions.
        )patchingZ	streamingN)r   r   r   r   )rM   rx   r   r   rO   rO   rP   set_server_callback  s    

z"ServerCallback.set_server_callback)N)NT)r   r   r   r   r   r   r   r   r   rc   r   r   r   r   r   r   r   r   r   r   	coroutiner   r   r   __classcell__rO   rO   r   rP   r   =  s*   


'r   c                   @   s   e Zd ZdZdddZdS )rj   aR  
    Provides a baseclass to define callbacks, which return data from
    bokeh model callbacks, events and attribute changes. The callback
    then makes this data available to any streams attached to it.

    The definition of a callback consists of a number of components:

    * models      : Defines which bokeh models the callback will be
                    attached on referencing the model by its key in
                    the plots handles, e.g. this could be the x_range,
                    y_range, plot, a plotting tool or any other
                    bokeh mode.

    * extra_models: Any additional models available in handles which
                    should be made available in the namespace of the
                    objects, e.g. to make a tool available to skip
                    checks.

    * attributes  : The attributes define which attributes to send
                    back to Python. They are defined as a dictionary
                    mapping between the name under which the variable
                    is made available to Python and the specification
                    of the attribute. The specification should start
                    with the variable name that is to be accessed and
                    the location of the attribute separated by
                    periods.  All models defined by the models and
                    extra_models attributes can be addressed in this
                    way, e.g. to get the start of the x_range as 'x'
                    you can supply {'x': 'x_range.attributes.start'}.
                    Additionally certain handles additionally make the
                    cb_data and cb_obj variables available containing
                    additional information about the event.

    * skip        : Conditions when the Callback should be skipped
                    specified as a list of valid JS expressions, which
                    can reference models requested by the callback,
                    e.g. ['pan.attributes.active'] would skip the
                    callback if the pan tool is active.

    * code        : Defines any additional JS code to be executed,
                    which can modify the data object that is sent to
                    the backend.

    * on_events   : If the Callback should listen to bokeh events this
                    should declare the types of event as a list (optional)

    * on_changes  : If the Callback should listen to model attribute
                    changes on the defined ``models`` (optional)

    If either on_events or on_changes are declared the Callback will
    be registered using the on_event or on_change machinery, otherwise
    it will be treated as a regular callback on the model.  The
    callback can also define a _process_msg method, which can modify
    the data sent by the callback before it is passed to the streams.
    Nc                 C   s&  |   }g }| jD ]@}||vrD|t| jjt| jf}td|  q|||  qdd |D }t|tt| f }|| j	v r| j	| }t
t|j| j |_| j D ]\}	}
|j|	 |
 q|   d S |D ]@}| jd u r| | q| j||d}| || | j| q| | j	|< d S )Nz4%s handle not found on %s, cannot attach %s callbackc                 S   s   g | ]}t |qS rO   )rp   )rd   r   rO   rO   rP   r   ^  r   z'Callback.initialize.<locals>.<listcomp>r   )rn   ro   rq   rW   r   r   r   tuplerp   rk   r   setrX   r`   rl   r   rm   r\   r   r   r   rs   )rM   r   rv   Z
cb_handlesrw   Z	warn_argsr`   ry   rf   re   r~   rx   r   rO   rO   rP   
initializeP  s8    



zCallback.initialize)N)r   r   r   r   r   rO   rO   rO   rP   rj     s   8rj   c                   @   sB   e Zd ZdZdddZdgZddgZdgZd	Zd
d Z	dd Z
dS )PointerXYCallback<
    Returns the mouse x/y-position on mousemove event.
    cb_obj.xcb_obj.y)xyrW   x_rangey_rangeZ	mousemovea  
    if (x_range.type.endsWith('Range1d')) {
      var xstart = x_range.start;
      var xend = x_range.end;
      if (xstart > xend) {
        [xstart, xend] = [xend, xstart]
      }
      if (cb_obj.x < xstart) {
        data['x'] = xstart;
      } else if (cb_obj.x > xend) {
        data['x'] = xend;
      }
    }
    if (y_range.type.endsWith('Range1d')) {
      var ystart = y_range.start;
      var yend = y_range.end;
      if (ystart > yend) {
        [ystart, yend] = [yend, ystart]
      }
      if (cb_obj.y < ystart) {
        data['y'] = ystart;
      } else if (cb_obj.y > yend) {
        data['y'] = yend;
      }
    }
    c                 C   s   t |tjrtt|}t |ttfr*t|}t |ttfr@t|}|| }}t |tjr^t|}t |tjrt|}n|||  }}}||k r|}n||kr|}|S )zClips out of bounds valuesr{   r   Z
datetime64r   r   floatrH   rM   rz   startendr~   r   r   rO   rO   rP   _process_out_of_bounds  s"    

z(PointerXYCallback._process_out_of_boundsc                 C   s  | j jd}| j jd}| j jd}| j jd}d|v rZt|trZt|d |d< d|v r|t|tr|t|d |d< | jd u }t|trt|dtt	fr|j
t|d  |d< nld|v r(t|ttfr(|r(|j|j }}||k r|| }}| |d ||}	|	d u r i }n|	|d< t|trbt|dtt	frb|j
t|d  |d< nld|v rt|ttfr|r|j|j }
}|
|kr||
 }
}| |d |
|}|d u ri }n||d< | |S )Nr  r  xaxisyaxisr  r  )rW   rv   r   r{   r	   rH   r\   r   r   r
  factorsr   r   r  r  r  rQ   )rM   rN   r  r  r  r  Zserver_modeZxstartZxendr  ZystartZyendr  rO   rO   rP   rT     s<    
 


" 


zPointerXYCallback._process_msgN)r   r   r   r   r   ro   r   r   r   r  rT   rO   rO   rO   rP   r  s  s   
r  c                   @   s"   e Zd ZdZddiZdgZdZdS )PointerXCallbackz:
    Returns the mouse x-position on mousemove event.
    r  r  r  aC  
    if (x_range.type.endsWith('Range1d')) {
      var xstart = x_range.start;
      var xend = x_range.end;
      if (xstart > xend) {
        [xstart, xend] = [xend, xstart]
      }
      if (cb_obj.x < xstart) {
        data['x'] = xstart;
      } else if (cb_obj.x > xend) {
        data['x'] = xend;
      }
    }
    Nr   r   r   r   r   r   r   rO   rO   rO   rP   r    s   r  c                   @   s"   e Zd ZdZddiZdgZdZdS )PointerYCallbackr  r  r  r  aC  
    if (y_range.type.endsWith('Range1d')) {
      var ystart = y_range.start;
      var yend = y_range.end;
      if (ystart > yend) {
        [ystart, yend] = [yend, ystart]
      }
      if (cb_obj.y < ystart) {
        data['y'] = ystart;
      } else if (cb_obj.y > yend) {
        data['y'] = yend;
      }
    }
    Nr  rO   rO   rO   rP   r    s   r  c                       sN   e Zd Zg dZdgZg dZddgZdddd	Z fd
dZdd Z	  Z
S )DrawCallback)panZpanstartpanendrW   )r  Zbox_zoomr  r  zpan && pan.attributes.activez&box_zoom && box_zoom.attributes.activer  r  zcb_obj.event_name)r  r  r   c                    s    d| _ tt| j|i | d S Nr   )stroke_countr   r  rc   )rM   r   kwargsr   rO   rP   rc     s    zDrawCallback.__init__c                 C   s4   | d}|dkr |  jd7  _| t|| jdS )Nr   r  rE   )r  )rr   r  rQ   r_   )rM   rN   r   rO   rO   rP   rT     s    
zDrawCallback._process_msg)r   r   r   r   ro   r   r   r   rc   rT   r   rO   rO   r   rP   r    s   r  c                   @   s$   e Zd ZdZdZddgZdd ZdS )TapCallbackz
    Returns the mouse x/y-position on tap event.

    Note: As of bokeh 0.12.5, there is no way to distinguish the
    individual tap events within a doubletap event.
    a  
    if (x_range.type.endsWith('Range1d')) {
      var xstart = x_range.start;
      var xend = x_range.end;
      if (xstart > xend) {
        [xstart, xend] = [xend, xstart]
      }
      if ((cb_obj.x < xstart) || (cb_obj.x > xend)) {
        return
      }
    }
    if (y_range.type.endsWith('Range1d')) {
      var ystart = y_range.start;
      var yend = y_range.end;
      if (ystart > yend) {
        [ystart, yend] = [yend, ystart]
      }
      if ((cb_obj.y < ystart) || (cb_obj.y > yend)) {
        return
      }
    }
    tap	doubletapc                 C   s   t |tjrtt|}t |ttfr*t|}t |ttfr@t|}|| }}t |tjr^t|}t |tjrt|}n|||  }}}||k s||krd}|S )z!Sets out of bounds values to NoneNr	  r  rO   rO   rP   r  8  s    

z"TapCallback._process_out_of_boundsN)r   r   r   r   r   r   r  rO   rO   rO   rP   r    s   r  c                   @   s   e Zd ZdZdgZdS )SingleTapCallbackz6
    Returns the mouse x/y-position on tap event.
    r  Nr   r   r   r   r   rO   rO   rO   rP   r  M  s   r  c                   @   s   e Zd ZdZdgZdS )PressUpCallbackzB
    Returns the mouse x/y-position of a pressup mouse event.
    ZpressupNr  rO   rO   rO   rP   r   T  s   r   c                   @   s   e Zd ZdZdgZdS )PanEndCallbackz<
    Returns the mouse x/y-position of a pan end event.
    r  Nr  rO   rO   rO   rP   r!  \  s   r!  c                   @   s   e Zd ZdZdgZdS )DoubleTapCallbackz<
    Returns the mouse x/y-position on doubletap event.
    r  Nr  rO   rO   rO   rP   r"  d  s   r"  c                   @   s   e Zd ZdZdgZdS )MouseEnterCallbackzi
    Returns the mouse x/y-position on mouseenter event, i.e. when
    mouse enters the plot canvas.
    Z
mouseenterNr  rO   rO   rO   rP   r#  l  s   r#  c                   @   s   e Zd ZdZdgZdS )MouseLeaveCallbackzi
    Returns the mouse x/y-position on mouseleave event, i.e. when
    mouse leaves the plot canvas.
    Z
mouseleaveNr  rO   rO   rO   rP   r$  u  s   r$  c                   @   s6   e Zd ZdZdddddZddgZd	d
gZdd ZdS )RangeXYCallbackz0
    Returns the x/y-axis ranges of a plot.
    x_range.attributes.startx_range.attributes.endy_range.attributes.starty_range.attributes.endx0x1y0y1r  r  r  r  c                 C   s   i }d|v r|d|v r||d |d  }}t | jjdtr^t |tsLt|}t |ts^t|}||krp|| }}||f|d< d|v rd|v r|d |d  }}t | jjdtrt |tst|}t |tst|}||kr|| }}||f|d< | |S )	Nr+  r,  r  r  r-  r.  r  r  )r{   rW   rv   r   r	   r   rH   rQ   )rM   rN   r   r+  r,  r-  r.  rO   rO   rP   rT     s,    





zRangeXYCallback._process_msgNr   r   r   r   r   ro   r   rT   rO   rO   rO   rP   r%  ~  s   r%  c                   @   s    e Zd ZdZdddZdgZdS )RangeXCallbackz-
    Returns the x-axis range of a plot.
    r&  r'  r+  r,  r  Nr   r   r   r   r   ro   rO   rO   rO   rP   r0    s
   r0  c                   @   s    e Zd ZdZdddZdgZdS )RangeYCallbackz-
    Returns the y-axis range of a plot.
    r(  r)  r-  r.  r  Nr2  rO   rO   rO   rP   r3    s
   r3  c                   @   s0   e Zd ZdZdgZdddZddgZdd	 Zd
S )PlotSizeCallbackz`
    Returns the actual width and height of a plot once the layout
    solver has executed.
    rW   zcb_obj.inner_widthzcb_obj.inner_height)widthheightZinner_widthZinner_heightc                 C   s&   | dr| dr| |S i S d S )Nr6  r7  )r   rQ   rS   rO   rO   rP   rT     s    
zPlotSizeCallback._process_msgN)r   r   r   r   ro   r   r   rT   rO   rO   rO   rP   r5    s   r5  c                   @   s,   e Zd ZdddZddgZdgZdd Zd	S )
SelectModeCallbackzbox_select.modezlasso_select.mode)box_mode
lasso_mode
box_selectlasso_selectrZ   c                 C   sV   | j d }d|v r.|d}||jkr.||d< d|v rR|d}||jkrR||d< |S )Nr   r9  rZ   r:  )rX   rr   rZ   )rM   rN   r   rZ   rO   rO   rP   rT     s    




zSelectModeCallback._process_msgN)r   r   r   r   ro   r   rT   rO   rO   rO   rP   r8    s   r8  c                   @   sN   e Zd ZdZdddddZdgZdgZd	gZd
gZdd dd gZ	dd Z
dS )BoundsCallbackz2
    Returns the bounds of a box_select tool.
    cb_obj.geometry.x0cb_obj.geometry.x1cb_obj.geometry.y0cb_obj.geometry.y1r*  rW   r;  selectiongeometry3(cb_obj.geometry.type != 'rect') || (!cb_obj.final)c                 C   s   | j d dkS Nrq   rectgeometryr   rO   rO   rP   <lambda>  r   zBoundsCallback.<lambda>c                 C   s   | j  S rK   finalr   rO   rO   rP   rH    r   c                    s   t  fdddD rt| jjdtrJt d  d< t d  d< t| jjdtr~t d  d< t d	  d	< d
 d  d  d  d	 fi |  S i S d S )Nc                 3   s   | ]}| v V  qd S rK   rO   rd   cr   rO   rP   r     r   z.BoundsCallback._process_msg.<locals>.<genexpr>)r+  r-  r,  r.  r  r+  r,  r  r-  r.  boundsallr{   rW   rv   r   r	   rH   rQ   rS   rO   r   rP   rT     s     
zBoundsCallback._process_msgNr   r   r   r   r   ro   r   r   r   r   rT   rO   rO   rO   rP   r=    s   r=  c                       s    e Zd ZdZ fddZ  ZS )SelectionXYCallbackzc
    Converts a bounds selection to numeric or categorical x-range
    and y-range selections.
    c                    s  t t| |}d|vr|S | jj}|d \}}}}| jjd }t|trtt	|tt	| }}|j
|| }|jr|jd r||jd d d }	|	rt|dr|j||	}
ztt||
}W n   Y n0 ||d< n||f|d< | jjd }t|trtt	|tt	| }}|j
|| }|jr|jd r||jd d d }|rt|dr|j||}
ztt||
}W n   Y n0 ||d< n||f|d< |S )NrM  r  r   	interfaceZx_selectionr  Zy_selection)r   rQ  rT   rW   current_framerv   r{   r   r   roundr  tagsZget_dimensionhasattrrR  dtyper   r   r   Zastype)rM   rN   elr+  r-  r,  r.  r  ZxfactorsZxdimrW  r  ZyfactorsZydimr   rO   rP   rT     sD    


z SelectionXYCallback._process_msg)r   r   r   r   rT   r   rO   rO   r   rP   rQ    s   rQ  c                   @   sJ   e Zd ZdZdddZdgZdgZdgZdgZd	d
 dd
 gZ	dd Z
dS )BoundsXCallbackz3
    Returns the bounds of a xbox_select tool.
    r>  r?  r1  rW   Zxbox_selectrB  rC  c                 C   s   | j d dkS rD  rF  r   rO   rO   rP   rH  4  r   zBoundsXCallback.<lambda>c                 C   s   | j  S rK   rI  r   rO   rO   rP   rH  5  r   c                    sp   t  fdddD rht| jjdtrJt d  d< t d  d< d d  d fi |  S i S d S )Nc                 3   s   | ]}| v V  qd S rK   rO   rK  r   rO   rP   r   8  r   z/BoundsXCallback._process_msg.<locals>.<genexpr>r1  r  r+  r,  ZboundsxrN  rS   rO   r   rP   rT   7  s    
zBoundsXCallback._process_msgNrP  rO   rO   rO   rP   rY  )  s   
rY  c                   @   sJ   e Zd ZdZdddZdgZdgZdgZdgZd	d
 dd
 gZ	dd Z
dS )BoundsYCallbackz3
    Returns the bounds of a ybox_select tool.
    r@  rA  r4  rW   Zybox_selectrB  rC  c                 C   s   | j d dkS rD  rF  r   rO   rO   rP   rH  M  r   zBoundsYCallback.<lambda>c                 C   s   | j  S rK   rI  r   rO   rO   rP   rH  N  r   c                    sp   t  fdddD rht| jjdtrJt d  d< t d  d< d d  d fi |  S i S d S )Nc                 3   s   | ]}| v V  qd S rK   rO   rK  r   rO   rP   r   Q  r   z/BoundsYCallback._process_msg.<locals>.<genexpr>r4  r  r-  r.  ZboundsyrN  rS   rO   r   rP   rT   P  s    
zBoundsYCallback._process_msgNrP  rO   rO   rO   rP   rZ  B  s   
rZ  c                   @   sF   e Zd ZdddZdgZdgZdgZdgZdd	 d
d	 gZdd Z	dS )LassoCallbackzcb_obj.geometry.xzcb_obj.geometry.yxsysrW   r<  rB  z3(cb_obj.geometry.type != 'poly') || (!cb_obj.final)c                 C   s   | j d dkS )Nrq   ZpolyrF  r   rO   rO   rP   rH  c  r   zLassoCallback.<lambda>c                 C   s   | j  S rK   rI  r   rO   rO   rP   rH  d  r   c                    s   t  fdddD si S  d  d  }}t|trZdd | D }dd t|D }t|trd	d | D }d
d t|D }|d u s|d u ri S dt||giS )Nc                 3   s   | ]}| v V  qd S rK   rO   rK  r   rO   rP   r   g  r   z-LassoCallback._process_msg.<locals>.<genexpr>r\  r]  r^  c                 s   s   | ]\}}t ||fV  qd S rK   r   )rd   ir  rO   rO   rP   r   k  r   c                 S   s   g | ]\}}|qS rO   rO   )rd   r   r  rO   rO   rP   r   l  r   z.LassoCallback._process_msg.<locals>.<listcomp>c                 s   s   | ]\}}t ||fV  qd S rK   r_  )rd   r`  r  rO   rO   rP   r   n  r   c                 S   s   g | ]\}}|qS rO   rO   )rd   r   r  rO   rO   rP   r   o  r   rG  )rO  r{   r_   rl   r   r   Zcolumn_stack)rM   rN   r]  r^  rO   r   rP   rT   f  s    

zLassoCallback._process_msgN)
r   r   r   r   ro   r   r   r   r   rT   rO   rO   rO   rP   r[  [  s   
r[  c                   @   s,   e Zd ZdZddiZdgZdgZdd ZdS )	Selection1DCallbackz>
    Returns the current selection on a ColumnDataSource.
    indexzcb_obj.indicesselectedindicesc                 C   sr   | j j}d|v rjddd |d D i}t|tr`|jdjd}|d ur`t||d kr`i S | |S i S d S )Nrb  c                 S   s   g | ]}t |qS rO   r_  rd   r~   rO   rO   rP   r     r   z4Selection1DCallback._process_msg.<locals>.<listcomp>rW   rc  )	rW   rS  r{   r   Zoptsr   r  r   rQ   )rM   rN   rX  ZselrO   rO   rP   rT   ~  s    

z Selection1DCallback._process_msgNr/  rO   rO   rO   rP   ra  u  s
   ra  c                   @   s$   e Zd ZdZdgZdgZdd ZdS )ResetCallbackzB
    Signals the Reset stream if an event has been triggered.
    rW   ra   c                 C   s   ddi}|  |S )NZ	resettingTrR   rS   rO   rO   rP   rT     s    zResetCallback._process_msgN)r   r   r   r   ro   r   rT   rO   rO   rO   rP   rf    s   rf  c                       s@   e Zd ZdZddiZdgZddgZd fdd	Zd	d
 Z  Z	S )CDSCallbackzb
    A Stream callback that syncs the data on a bokeh ColumnDataSource
    model with Python.
    r   zsource.datar^   r   Nc                    sL   t t| | | j}| d|jd jid }| jD ]}|j|d q6d S )Nr   r^   r   )	r   rg  r   rW   rT   rv   r   rX   r   )rM   r   rW   r   r   r   rO   rP   r     s
    
zCDSCallback.initializec           	      C   s  d|vri S t |d |d< |d  D ]X\}}t|t r|dd }|dd }|dd  tdd | D }dd |D }|d urtj||d|}nt|trT|rTt|d	 t rTg }|D ]}t|t rB|dd }|dd }|dd  td
d | D }dd |D }|d urBtj||d|}|	| q|}n"t
dd |D rvdd |D }||d |< q(| |S )Nr   shaperW  Z	dimensionc                 S   s   g | ]\}}t ||fqS rO   r_  rd   re   r~   rO   rO   rP   r     r   z,CDSCallback._process_msg.<locals>.<listcomp>c                 S   s   g | ]\}}|qS rO   rO   rj  rO   rO   rP   r     r   )rW  r   c                 S   s   g | ]\}}t ||fqS rO   r_  rj  rO   rO   rP   r     r   c                 S   s   g | ]\}}|qS rO   rO   rj  rO   rO   rP   r     r   c                 s   s   | ]}t |ttfV  qd S rK   )r{   r   r
  re  rO   rO   rP   r     r   z+CDSCallback._process_msg.<locals>.<genexpr>c                 S   s   g | ]}|d u rt jn|qS rK   )r   nanre  rO   rO   rP   r     r   )r_   rl   r{   rr   r   r   r   Zreshaper   r   r   rQ   )	rM   rN   colr   ri  rW  rl   Z
new_valuesZvalsrO   rO   rP   rT     s:    
"
zCDSCallback._process_msg)N)
r   r   r   r   r   ro   r   r   rT   r   rO   rO   r   rP   rg    s   rg  c                   @   s    e Zd ZdZdd Zdd ZdS )GlyphDrawCallbacka  
      var types = Bokeh.require("core/util/types");
      var changed = false
      for (var i = 0; i < cb_obj.length; i++) {
        for (var style in styles) {
          var value = styles[style];
          if (types.isArray(value)) {
            value = value[i % value.length];
          }
          if (cb_obj.data[style][i] !== value) {
            cb_obj.data[style][i] = value;
            changed = true;
          }
        }
      }
      if (changed)
        cb_obj.change.emit()
    c                    s   | j d }|jd }t|j| }|j D ]0\}  fddt|D |j|< t||| q,t| j	|j|j
dd}|d| d S )Nr   c                    s   g | ]} |t    qS rO   len)rd   r`  r   rO   rP   r     r   z<GlyphDrawCallback._create_style_callback.<locals>.<listcomp>)stylesempty)r   r   r   )rX   Zcolumn_namesro  r   rq  rl   rangesetattrr   _style_callbackempty_valuer   )rM   cdsglyphr   rl  lengthstylerf   rO   rp  rP   _create_style_callback  s    

z(GlyphDrawCallback._create_style_callbackc                 C   sv   | j j}| jd }|jD ]X}t|j}||v r0q||}t|tt|	 d krht
||jgg}|||< qdS )
        Add any value dimensions not already in the data ensuring the
        element can be reconstituted in entirety.
        r   N)rW   rS  rX   vdimsr   namedimension_valuesro  r   r   r   concatenaterv  )rM   r   elementr   ddimr   rO   rO   rP   _update_cds_vdims  s    



z#GlyphDrawCallback._update_cds_vdimsN)r   r   r   ru  r{  r  rO   rO   rO   rP   rm    s   rm  c                       s*   e Zd Zd fdd	Z fddZ  ZS )PointDrawCallbackNc           	         s   | j }| jd }|jd }|jd }|jd g}i }|jrD|j|d< |jrT|j|t< |jrf| || |jd urz|j|d< t	f t
dd | jD t
d	d | jD |d
|}| j jj| | |j tt| | d S )Nr   r^   rx  glyph_renderernum_objectsrv  c                 s   s   | ]}|j V  qd S rK   )addr   rO   rO   rP   r     r   z/PointDrawCallback.initialize.<locals>.<genexpr>c                 s   s   | ]}|j V  qd S rK   dragr   rO   rO   rP   r     r   r  r  	renderers)rW   rX   rv   r  tooltipCUSTOM_TOOLTIPrq  r{  rv  r   rO  r   toolsr   r  r   r   r  r   )	rM   r   rW   r   rw  rx  r  r  
point_toolr   rO   rP   r     s0    






zPointDrawCallback.initializec                    s   |  |d  tt| |S Nr   )r  r   r  rT   rS   r   rO   rP   rT     s    zPointDrawCallback._process_msg)N)r   r   r   r   rT   r   rO   rO   r   rP   r    s   r  c                       s2   e Zd Zd fdd	Z fddZdd Z  ZS )	CurveEditCallbackNc                    s   | j }| jd }|jd }|jd }|jj|j|jf|dd|j}|g}i }|jr`|j|t	< t
f dd|d|}	d}
t|||	d	|
d
}|	d| |jd| | j jj|	 | |j tt| | d S )Nr   rw  rx  F)r^   ZvisibleTr  zCrenderer.visible = tool.active || (cds.selected.indices.length > 0))rY   rw  toolr   zchange:activerd  )rW   rX   rv   r   scatterr  r  rz  r  r  r   r   r   rc  r  r   r  r   r   r  r   )rM   r   rW   r   rw  rx  rY   r  r  r  r   show_verticesr   rO   rP   r     s2    



zCurveEditCallback.initializec                    s   |  |d  tt| |S r  )r  r   r  rT   rS   r   rO   rP   rT   6  s    zCurveEditCallback._process_msgc                 C   s8   | j j}|jD ]$}t|j}||vr||||< qdS )r|  N)rW   rS  r}  r   r~  r  )rM   r   r  r  r  rO   rO   rP   r  :  s
    

z#CurveEditCallback._update_cds_vdims)Nr   r   r   r   rT   r  r   rO   rO   r   rP   r    s   r  c                       s2   e Zd Zd fdd	Z fddZdd Z  ZS )	PolyDrawCallbackNc                    s
  | j }| jd }| j jd }| j jd }|jd g}i }|jrH|j|d< |jrtddifi |j}|jjg g fi |}	|	|d< |j	r| 
|| |jr|j|t< |jd ur|j|d	< tf td
d | jD |d|}
|jj|
 | |j tt| | d S )Nr   rw  rx  r  r  size
   vertex_rendererrv  c                 s   s   | ]}|j V  qd S rK   r  r   rO   rO   rP   r   \  r   z.PolyDrawCallback.initialize.<locals>.<genexpr>)r  r  )rW   rX   rv   r  r  r_   vertex_styler   r  rq  r{  r  r  rv  r   rO  r  r   r  r   r   r  r   )rM   r   rW   r   rw  rx  r  r  r  r1	poly_toolr   rO   rP   r   H  s4    




zPolyDrawCallback.initializec                    s   |  |d  tt| |S r  )r  r   r  rT   rS   r   rO   rP   rT   c  s    zPolyDrawCallback._process_msgc           
      C   s   | j j}| jd }|j}|jr&ddini }|jD ]}|jj||fi |}t|j}||vr0|rp|	|| }	ndd |j
d|gdD }	t|	t|d krt|	|jgg}	|	||< q0d	S )
r|  r   Zper_geomTc                 S   s   g | ]}|d d df qS r  rO   )rd   ZarrrO   rO   rP   r   w  r   z6PolyDrawCallback._update_cds_vdims.<locals>.<listcomp>r   )ZdatatypeZ
dimensionsr]  N)rW   rS  rX   rR  Zmultir}  Zisuniquer   r~  r  r   ro  r   r  rv  )
rM   r   r  r   rR  Zscalar_kwargsr  Zscalarr  r   rO   rO   rP   r  g  s    


z"PolyDrawCallback._update_cds_vdims)Nr  rO   rO   r   rP   r  F  s   r  c                   @   s   e Zd ZdddZdS )FreehandDrawCallbackNc                 C   s   | j }|jd }|jd }| jd }|jr6| || i }|jrJ|j|t< |jd ur^|j|d< tf |j	|jd gd|}|j
j| | |j t| | d S )Nrw  rx  r   rv  r  )r  r  )rW   rv   rX   rq  r{  r  r  rv  r   r  r   r  r   r  r   rg  r   )rM   r   rW   rw  rx  r   r  r  rO   rO   rP   r     s(    






zFreehandDrawCallback.initialize)Nr   r   r   r   rO   rO   rO   rP   r  }  s   r  c                       s@   e Zd ZddiZdgZdd Zd fdd	Z fd	d
Z  ZS )BoxEditCallbackr   zcds.datarw  c                    s|  | j }|jd }|j}| j j g g g g f\}}}}t|d |d D ]t\}}	t|t| }
}t|	t|	 }}||
| d  ||| d  |||
  |||  qD||||d}|	 fdd j
D  |j	| | j j| j j }|dd  |jjdd	|i|}|jd
 | j jjv rL| j jj|jd
  | d|id }| jD ]}|j	|d qd|S )Nrw  r]  r^         @r  r  r6  r7  c                    s   i | ]}|j  j|d dqS )F)Zexpanded)r~  r  )rd   Zvdr  rO   rP   rh     r   z4BoxEditCallback._path_initialize.<locals>.<dictcomp>Zcmapr^   r  r   rh  )rW   rv   r   rS  zipr   ZnanminZnanmaxr   r   r}  rz  Zcyclic_indexrr   r   rE  r  removerT   rX   )rM   rW   rw  r   r]  r^  ZwidthsZheightsr  r  r+  r,  r-  r.  rz  r  r   rO   r  rP   _path_initialize  s0    

z BoxEditCallback._path_initializeNc                    s   ddl m} | jd }| jjd }i }|jr6|j|d< |jrF|j|t< | jjd }t| j|rf| 	 }|j
rz| ||j tf d|gi|}| jjj| | |j tt|   d S )NrE   )PathPlotr   rw  r  r  r  )r   r  rX   rW   rv   r  r  r  r{   r  rq  r{  rx  r   r   r  r   r  r   r   rg  r   )rM   r   r  r   rw  r  rY   Zbox_toolr   rO   rP   r     s"    


zBoxEditCallback.initializec                    s   t t| |}d|vri S |d }g g g g f\}}}}t|d |d |d |d D ]T\}}}	}
|||	d   |||	d   |||
d   |||
d   qVi }|D ]}|dv rq|| ||< qdt|||||di}| |d  | |S )	Nr   r  r  r6  r7  r  r  r*  )r   r  rT   r  r   r_   r  rQ   )rM   rN   r   Zx0sZx1sZy0sZy1sr  r  r   r   r   rl  r   rO   rP   rT     s$    *zBoxEditCallback._process_msg)N)	r   r   r   r   ro   r  r   rT   r   rO   rO   r   rP   r    s
   r  c                   @   s   e Zd ZdddZdS )PolyEditCallbackNc           
      C   s   | j }|jd }d }tdd | jD rJdd |jjD }|rF|d nd }| jd }i }|jrh|j|t< |d u rtddifi |j	}|jj
g g fi |}	tf d	|	i|}|jj| |j|jd
  | |j t| | d S )Nrw  c                 s   s   | ]}|j V  qd S rK   )Zsharedr   rO   rO   rP   r     r   z.PolyEditCallback.initialize.<locals>.<genexpr>c                 S   s   g | ]}t |tr|qS rO   )r{   r   )rd   r  rO   rO   rP   r     r   z/PolyEditCallback.initialize.<locals>.<listcomp>r   r  r  r  r  )rW   rv   rO  rX   r   r  r  r  r_   r  r  r   r   r  r  r   rg  r   )
rM   r   rW   rw  Zvertex_toolr  r   r  r  r  rO   rO   rP   r     s$    


zPolyEditCallback.initialize)Nr  rO   rO   rO   rP   r    s   r  Zbokehc                   @   s`   e Zd ZdZdZg Zg Zg Zg Zg Z	g Z
dZdZd
ddZedd ZedddZdd	 ZdS )LinkCallbackNc                 C   s  || _ || _|| _|| _|   dd |j D }| j| jg D ] }d	d|g}|j
| ||< qB|j D ]\}}	|dv rqn|	||< qn|d ur| j| jg D ] }d	d|g}|j
| ||< q| j|j
v r$|j
| j }
t|| jd}| jD ]}|
|| q| jD ]}|
|| q|| _nd | _|d ur| j|j
v r| jr|j
| j }t|| jd}| jD ]}||| qj| jD ]}||| q|| _nd | _d S )Nc                 S   s   i | ]\}}|d vr||qS ))r^   targetr~  rO   rj  rO   rO   rP   rh   3  s   z)LinkCallback.__init__.<locals>.<dictcomp>r   r^   )r~  r^   r  r  r   )
root_modellinksource_plottarget_plotvalidater   Zget_param_valuessource_handlessource_modelr   rv   target_handlestarget_modelr   source_codeon_source_changesr   on_source_eventsr   src_cbtarget_codeon_target_changeson_target_eventstgt_cb)rM   r  r  r  r  r   shr   r   rz   Z	src_modelr  ZchZevZ	tgt_modelr  rO   rO   rP   rc   ,  sF    


 

zLinkCallback.__init__c           
         s   dd }| dd |g} fdd|D }dd |D }g }|D ]h\}}|D ]Zjsj||df qN fdd|D }d	d |D }	|	rN|||	d
 d
 f qNqB|S )zh
        Traverses the supplied plot and searches for any Links on
        the plotted objects.
        c                 S   s   t | tot | t S rK   )r{   rC   rD   r  rO   rO   rP   rH  `  r   z)LinkCallback.find_links.<locals>.<lambda>c                 S   s   | S rK   rO   r  rO   rO   rP   rH  a  r   c                    s   g | ]}  |qS rO   	find_link)rd   rW   )r   rO   rP   r   b  r   z+LinkCallback.find_links.<locals>.<listcomp>c                 S   s   g | ]}|d ur|qS rK   rO   rd   r   rO   rO   rP   r   c  r   Nc                    s   g | ]}  |qS rO   r  r  r   r  rO   rP   r   k  r   c                 S   s   g | ]}|d ur|qS rK   rO   r  rO   rO   rP   r   l  r   r   )ZtraverseZ_requires_targetr   )
r   Z	root_plotZplot_fnr   Z
potentialsZsource_linksfoundrW   linksZ	tgt_linksrO   r  rP   
find_linksZ  s    zLinkCallback.find_linksc                    s   t j }|jD ]l |du r@ fdd|D }|r|||f  S q|j u sn|jdur|jjdur|jj jkr||gf  S qdS )z;
        Searches a GenericElementPlot for a Link.
        Nc                    s<   g | ]4\}}|D ]&}| u s2|j d ur|j  j kr|qqS rK   )_plot_id)rd   srcr  lr^   rO   rP   r   y  s   z*LinkCallback.find_link.<locals>.<listcomp>)r=   registryrl   Zlink_sourcesr  r  )r   rW   r  r  r  rO   r  rP   r  q  s     




zLinkCallback.find_linkc                 C   s   dS )z}
        Should be subclassed to check if the source and target plots
        are compatible to perform the linking.
        NrO   rg   rO   rO   rP   r    s    zLinkCallback.validate)N)N)r   r   r   r  r  r  r  r  r  r  r  r  r  rc   r   r  r  r  rO   rO   rO   rP   r    s    
.
r  c                   @   s   e Zd ZdZdd ZdS )RangeToolLinkCallbackzk
    Attaches a RangeTool to the source plot and links it to the
    specified axes on the target plot
    c           
      C   s   zddl m} W n   tdY n0 t|dti}i }d|jv rT|jd |d< d|jv rl|jd |d< |f i |}|j	| |r|d j
}	|	j| d S )	Nr   )	RangeToolz$RangeToolLink requires bokeh >= 0.13rq   r  r  r  r  )Zbokeh.models.toolsr  r   r   Zselectr
   axesrv   r   Z	add_toolstoolbarr  r   )
rM   r  r  r  r  r  Ztoolbarsr  r  r  rO   rO   rP   rc     s    


zRangeToolLinkCallback.__init__Nr   r   r   r   rc   rO   rO   rO   rP   r    s   r  c                   @   s   e Zd ZdZdd ZdS )DataLinkCallbackz7
    Merges the source and target ColumnDataSource
    c                 C   s  |j d }|j d }||u r d S dd |j D }dd |j D }|rx|rx|d |d krxtd|d |d f |j D ]\}	}
|	|jvrqt|
}
t|j|	 }t|
rt|
d tj	rqt
|
r|
|ks|
jjdvr|
|k stj|
t|j|	 dd	std
|	 q|j|j |j d}|d u rBn(d| v r^|j|d n|j|d t|dr|jj|d ||j d< ||j d< |jD ]}|j|jd d qd S )Nr^   c                 S   s   g | ]}t |qS rO   rn  re  rO   rO   rP   r     r   z-DataLinkCallback.__init__.<locals>.<listcomp>c                 S   s   g | ]}t |qS rO   rn  re  rO   rO   rP   r     r   r   zmDataLink source data length must match target data length, found source length of %d and target length of %d.ZiufcT)Z	equal_nanzqDataLink can only be applied if overlapping dimension values are equal, %s column on source does not match targetr  data_source)r  r  viewrw  rp   r   )rv   r   r   r   rl   r   Zasarrayro  r{   Zndarrayr   rW  kindrO  Zallclose
ValueErrorr   r   Z
propertiesrV  r  rs   r   r   )rM   r  r  r  r  Zsrc_cdsZtgt_cdsZsrc_lenZtgt_lenre   r~   rl  rY   callbackrO   rO   rP   rc     sP    









zDataLinkCallback.__init__Nr  rO   rO   rO   rP   r    s   r  c                   @   s4   e Zd ZdZdZdgZdgZdgZdgZdZ	dZ
dS )SelectionLinkCallbackrc  rd  rw  zl
    target_selected.indices = source_selected.indices
    target_cds.properties.selected.change.emit()
    zl
    source_selected.indices = target_selected.indices
    source_cds.properties.selected.change.emit()
    N)r   r   r   r  r  r  r  r  r  r  r  rO   rO   rO   rP   r    s   r  c                   @   s:   e Zd ZdZdZdgZddgZdgZdZdZ	dd	d
Z
dS )RectanglesTableLinkCallbackrw  rx  rc  r   r   ao  
    var xs = source_cds.data[source_glyph.x.field]
    var ys = source_cds.data[source_glyph.y.field]
    var ws = source_cds.data[source_glyph.width.field]
    var hs = source_cds.data[source_glyph.height.field]

    var x0 = []
    var x1 = []
    var y0 = []
    var y1 = []
    for (var i = 0; i < xs.length; i++) {
      var hw = ws[i]/2.
      var hh = hs[i]/2.
      x0.push(xs[i]-hw)
      x1.push(xs[i]+hw)
      y0.push(ys[i]-hh)
      y1.push(ys[i]+hh)
    }
    target_cds.data[columns[0]] = x0
    target_cds.data[columns[1]] = y0
    target_cds.data[columns[2]] = x1
    target_cds.data[columns[3]] = y1
    a  
    var x0s = target_cds.data[columns[0]]
    var y0s = target_cds.data[columns[1]]
    var x1s = target_cds.data[columns[2]]
    var y1s = target_cds.data[columns[3]]

    var xs = []
    var ys = []
    var ws = []
    var hs = []
    for (var i = 0; i < x0s.length; i++) {
      var x0 = Math.min(x0s[i], x1s[i])
      var y0 = Math.min(y0s[i], y1s[i])
      var x1 = Math.max(x0s[i], x1s[i])
      var y1 = Math.max(y0s[i], y1s[i])
      xs.push((x0+x1)/2.)
      ys.push((y0+y1)/2.)
      ws.push(x1-x0)
      hs.push(y1-y0)
    }
    source_cds.data['x'] = xs
    source_cds.data['y'] = ys
    source_cds.data['width'] = ws
    source_cds.data['height'] = hs
    Nc                 C   sR   t | |||| t| |||| dd |jjD }|| jjd< || jjd< d S )Nc                 S   s   g | ]
}|j qS rO   )r~  )rd   ZkdrO   rO   rP   r   *  r   z8RectanglesTableLinkCallback.__init__.<locals>.<listcomp>columns)r  rc   r  rS  Zkdimsr  r   r  )rM   r  r  r  r  r  rO   rO   rP   rc   '  s
    z$RectanglesTableLinkCallback.__init__)N)r   r   r   r  r  r  r  r  r  r  rc   rO   rO   rO   rP   r    s   r  c                   @   s,   e Zd ZdZdZg dZddgZdZdZdS )VertexTableLinkCallbackrw  )rc  r   r   r   r   a  
    var index = source_cds.selected.indices[0];
    if (index == undefined) {
      var xs_column = [];
      var ys_column = [];
    } else {
      var xs_column = source_cds.data['xs'][index];
      var ys_column = source_cds.data['ys'][index];
    }
    if (xs_column == undefined) {
      var xs_column = [];
      var ys_column = [];
    }
    var xs = []
    var ys = []
    var empty = []
    for (var i = 0; i < xs_column.length; i++) {
      xs.push(xs_column[i])
      ys.push(ys_column[i])
      empty.push(null)
    }
    var [x, y] = vertex_columns
    target_cds.data[x] = xs
    target_cds.data[y] = ys
    var length = xs.length
    for (var col in target_cds.data) {
      if (vertex_columns.indexOf(col) != -1) { continue; }
      else if (col in source_cds.data) {
        var path = source_cds.data[col][index];
        if ((path == undefined)) {
          var data = empty;
        } else if (path.length == length) {
          var data = source_cds.data[col][index];
        } else {
          var data = empty;
        }
      } else {
        var data = empty;
      }
      target_cds.data[col] = data;
    }
    target_cds.change.emit()
    target_cds.data = target_cds.data
    a  
    if (!source_cds.selected.indices.length) { return }
    var [x, y] = vertex_columns
    var xs_column = target_cds.data[x]
    var ys_column = target_cds.data[y]
    var xs = []
    var ys = []
    var points = []
    for (var i = 0; i < xs_column.length; i++) {
      xs.push(xs_column[i])
      ys.push(ys_column[i])
      points.push(i)
    }
    var index = source_cds.selected.indices[0]
    var xpaths = source_cds.data['xs']
    var ypaths = source_cds.data['ys']
    var length = source_cds.data['xs'].length
    for (var col in target_cds.data) {
      if ((col == x) || (col == y)) { continue; }
      if (!(col in source_cds.data)) {
        var empty = []
        for (var i = 0; i < length; i++)
          empty.push([])
        source_cds.data[col] = empty
      }
      source_cds.data[col][index] = target_cds.data[col]
      for (var p of points) {
        for (var pindex = 0; pindex < xpaths.length; pindex++) {
          if (pindex != index) { continue }
          var xs = xpaths[pindex]
          var ys = ypaths[pindex]
          var column = source_cds.data[col][pindex]
          if (column.length != xs.length) {
            for (var ind = 0; ind < xs.length; ind++) {
              column.push(null)
            }
          }
          for (var ind = 0; ind < xs.length; ind++) {
            if ((xs[ind] == xpaths[index][p]) && (ys[ind] == ypaths[index][p])) {
              column[ind] = target_cds.data[col][p]
              xs[ind] = xs[p];
              ys[ind] = ys[p];
            }
          }
        }
      }
    }
    xpaths[index] = xs;
    ypaths[index] = ys;
    source_cds.change.emit()
    source_cds.properties.data.change.emit();
    source_cds.data = source_cds.data
    N)	r   r   r   r  r  r  r  r  r  rO   rO   rO   rP   r  /  s   -r  )Z
__future__r   r   r   r   collectionsr   	functoolsr   Znumpyr   Zpanelr[   r   Zbokeh.modelsr   r   r	   r
   r   r   r   r   r   r   r   Zpanel.io.stater   Zpyviz_commsr   Ztornador   corer   Zcore.optionsr   Z	core.utilr   r   r   r   r  r   rX   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r  r=   r>   r?   r@   rA   rB   rW   rC   rD   utilrF   rG   rH   r  objectrJ   r   r   rj   r  r  r  r  r  r  r   r!  r"  r#  r$  r%  r0  r3  r5  r8  r=  rQ  rY  rZ  r[  ra  rf  rg  rm  r  r  r  r  r  r  rk   rs   ZParameterizedr  r  r  r  r  r  rO   rO   rO   rP   <module>   s   4  /a [\e7		%
-12 )7K
q1Dl
