U
    /e0                     @  s  d Z ddlmZ ddlZeeZddlmZ ddl	m
Z
mZmZ e
rPddlZnddlmZ edZdd	lm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mZm Z m!Z!m"Z"m#Z#m$Z$m%Z% e
rddl&m'Z' ddl(m)Z) dZ*dddddZ+G dd dZ,dS )a   Functions to draw the a clickable graph of the submodels of a bokeh model.

Clicking on the nodes representing the submodels reveals the attributes of that submodel.
Uses simple custom javascript callbacks so no server is necessary;
works in a jupyter notebook.

Suppose M is a bokeh model (i.e. a plot or figure).  Then
generate_structure_plot(M) is a bokeh model that displays the submodel graph.

Based on a private class, _BokehStructureGraph.

- K = _BokehStructureGraph(M) creates the object.
- K.model returns the model consisting of the structure graph and associated datatable.
- K.graph returns the directed graph in networkx format
- K.property_df returns the dataframe of models, submodels and their properties.

    )annotationsN)permutations)TYPE_CHECKINGDictSet   )import_optionalpandas)column)BoxZoomToolCDSViewCircleColumnDataSourceCustomJS	DataTableGlyphRendererGroupFilter	HoverToolLabelLabelSet	MultiLinePanToolPlotRange1d	ResetToolTableColumnTapTool)ID)Model)generate_structure_plotr   )freturnc                 C  s
   t | jS )z  Given a bokeh model f, return a model that displays the graph of its submodels.

    Clicking on the nodes of the graph reveals the attributes of that submodel.

    )_BokehStructureGraphmodel)r     r$   ?/tmp/pip-unpacked-wheel-f5fndrjf/bokeh/models/util/structure.pyr   V   s    r   c                   @  s   e Zd ZdZdddddZedddd	Zed
d Zedd ZddddZ	ddddZ
ddddZddddZddddZddddZdS ) r"   a#   Class for exploring the graph of submodels of a Bokeh model.

    If M is such a model and X=_BokehStructureGraph(M), then:

    - X.model is the interactive model itself of
    the submodel graph; pass it to show or file_html.  Self contained so
    works in a jupyter notebook, no server needed.

    - X.graph is the networkx DiGraph of submodels.

    - X.property_df is a pandas dataframe including all of the properties of
    all of the submodels, with their docstrings.  Used for the datatable
    displayed when clicking on X.model

    r   None)r#   r!   c                 C  sn   || _ | || _ddi| jjd< |  | _|  | _|  | _	d| j j
j d| j j | jj_|  | _d S )NZrankdirZLRgraphzStructure of model type z	 with id )_model_make_graph_graphr'   _make_prop_dict_prop_df_make_graph_plot_graph_plot_make_data_table_data_table	__class____name__idtitletext	_combined_structure_graph)selfr#   r$   r$   r%   __init__u   s    


 z_BokehStructureGraph.__init__)r!   c                 C  s   | j S )z The bokeh model consisting of the structure graph and the datatable
        for the attributes.

        Can be passed to show or file_html. Self contained,
        so remains interactive in a notebook or html file; no server needed.

        )r7   r8   r$   r$   r%   r#      s    	z_BokehStructureGraph.modelc                 C  s   | j S )z@ The networkx digraph of submodels of the given model.

        )r*   r:   r$   r$   r%   r'      s    z_BokehStructureGraph.graphc                 C  s   | j S )z A pandas dataframe of all of the properties of the model with their
        values, types, and docstrings.  The base information for the datatable.

        )r,   r:   r$   r$   r%   property_df   s    z _BokehStructureGraph.property_dfMc                   s  ddl }ddddddd}| }i   D ]}d	d
 | D |j< q0| fddD  fddtdD }|| g }|jD ]d} d|i}	|	|D ]F}
|	d|
i}d}|	
 D ]}||||	rd}q|s|||
f qq|| |S )aq   Builds a networkx DiGraph() G from the model M.


        G.nodes are the submodels of M, with node attributes
            - "model" giving the class name of of the submodel
            - "id" giving the id of the submodel

        An edge runs from a to b if the submodel b belongs to an attribute of
            a

        Args:
            A bokeh model M

        r   Nr   strbool)syHr!   c              	   S  s   d}d}d}z| t ||k}W n tk
r2   Y nX z| t ||k}W n tk
rZ   Y nX z| t || k}W n ttfk
r   Y nX ||B |B S )NF)getattr	TypeErrorvaluesAttributeError
ValueError)r@   rA   rB   Zanswer1Zanswer2Zanswer3r$   r$   r%   test_condition   s     z8_BokehStructureGraph._make_graph.<locals>.test_conditionc                 S  s   h | ]
}|j qS r$   r3   ).0rA   r$   r$   r%   	<setcomp>   s     z3_BokehStructureGraph._make_graph.<locals>.<setcomp>c                   s&   g | ]}|d   d|ijjifqS )r#   r3   )
select_oner1   r2   rJ   xr<   r$   r%   
<listcomp>   s     z4_BokehStructureGraph._make_graph.<locals>.<listcomp>c                   s(   g | ] \}} |  | kr||fqS r$   r$   )rJ   rN   rA   )Tr$   r%   rO      s         r3   FT)networkxZDiGraphZ
referencesr3   Zadd_nodes_fromr   Zadd_edges_fromnodesrL   Z	neighborsZ
propertiesappendZremove_edges_from)r8   r=   nxrH   KmEZ
dead_edgesr3   rB   rN   r@   Z	keep_edgerA   r$   )r=   rP   r%   r)      s0    


z _BokehStructureGraph._make_graphobjc                   sV      } fdd| D } fdd| D }t| t| ||d}|S )z Returns a pandas dataframe of the properties of a bokeh model

        Each row contains  an attribute, its type (a bokeh property), and its docstring.

        c                   s   g | ]}  |qS r$   )lookuprM   rY   r$   r%   rO      s     z:_BokehStructureGraph._obj_props_to_df2.<locals>.<listcomp>c                   s   g | ]}t t |jqS r$   )rC   type__doc__rM   rY   r$   r%   rO      s     )propsrE   typesdoc)Zproperties_with_valueskeyslistrE   )r8   rZ   Zobj_dictr_   Zdocsdfr$   rY   r%   _obj_props_to_df2   s    

z&_BokehStructureGraph._obj_props_to_df2r   c              
     s2  ddl }|jj jdd}t|  \}} fdd|D }t| }t||||d}g }g }	 jj	D ]H\}
}|
||
 d || d gg |	
||
 d || d gg qjt||	d	}td
d}tt|t| d}tt|t| d}tt|d|  t|d|  d|_tt|d|  t|d|  d|_t|tdddddtdddddtdddddd}t|tddd	d}tddgd}|g|_t }|g|_tddd|dddd }td!d!d"d"dd#d$d%}|| || || |j
||t t t g |j| | _| _ |S )&z7 Builds the graph portion of the final model.

        r   Ndot)progc                   s   g | ]} j j| d  qS )r#   )r*   rS   rM   r:   r$   r%   rO      s     z9_BokehStructureGraph._make_graph_plot.<locals>.<listcomp>)rN   rA   indexr#      )xsysg        )Zoutline_line_alpha   g333333?)startendrN   rA      Z	lightblue)rN   rA   sizeZ
fill_colorZgreen)data_sourceglyphZnonselection_glyphZselection_glyphri   rj   )rp   rq   )r3   z@index)r#   z@model)Ztooltipsr#   Z8pti   )rN   rA   r5   sourcetext_font_sizeZx_offsetZy_offset   ZscreenZitalicz&Click on a model to see its attributes)rN   rA   Zx_unitsZy_unitsrt   Ztext_font_styler5   )!rR   Znx_pydotZgraphviz_layoutr*   ziprE   rb   ra   r   edgesextendr   maxminr   Zx_rangeZy_ranger   r   r   r   Z	renderersr   r   r   Z
add_layoutZtoolsr   r   r   rT   _node_sourceZ_edge_source)r8   rU   rS   Znode_xZnode_ymodelsZnode_idnode_sourceZedge_x_coordsZedge_y_coordsZ
start_nodeZend_nodeZedge_sourcep2Z	xintervalZ	yintervalZnode_rendererZedge_rendererZnode_hover_toolZtap_toollabelshelpr$   r:   r%   r-      s     "
   

	


z%_BokehStructureGraph._make_graph_plotzpd.DataFramec                 C  s   ddl }| }| jjddD ]x}| jt|d d}|| |}|d |d< t||d< |d 	d	d
 |d< |d 	dd
 |d< |
|}q|S )z Returns a dataframe containing all the properties of all the submodels of the model being
        analyzed. Used as datasource to show attributes.

        r   NT)datarI   r3   r#   rE   c                 S  s   t | S Nr>   rN   r$   r$   r%   <lambda>?      z6_BokehStructureGraph._make_prop_dict.<locals>.<lambda>r_   c                 S  s   t | S r   r   r   r$   r$   r%   r   @  r   )r	   Z	DataFramer*   rS   r(   rL   dictrd   r>   maprT   )r8   pdrc   rN   r=   Zr$   r$   r%   r+   3  s    z$_BokehStructureGraph._make_prop_dictr   c              	   C  sr   t dddt dddg}t| j}| jjd d }td|d	}t||gd
}t|||ddddd}|| _|| _	|S )z: Builds the datatable portion of the final plot.

        r^   ZProperty)fieldr4   rE   Valuerg   r   r3   )Zcolumn_namegroup)rs   filtersFNT)rs   viewcolumnsZvisibleZindex_positionZfit_columnseditable)
r   r   r,   r{   r   r   r   r   _groupfilter_prop_source)r8   r   prop_sourceZmodel_idZgroupfilterZdata_table2_viewZdata_table2r$   r$   r%   r/   D  s&    



z%_BokehStructureGraph._make_data_tablec                 C  sF   d}t t| j| j| j| jd|d}| jjd| t| j	| j}|S )z Connects the graph and the datatable with a simple CustomJS callback.

        Clicking on a node/submodel narrows the view in the datatable to the
        attributes associated with that submodel.

        z            const index = node_source.selected.indices[0];
            f['group'] = node_source.data['index'][index];
            table['visible'] = true;
            prop_source.change.emit();
        )r}   r   r    table)argscodeindices)
r   r   r{   r   r   r0   selectedZjs_on_changer
   r.   )r8   Zjs_codeZjsZlayoutr$   r$   r%   r6   _  s    
z_BokehStructureGraph._combinedN)r2   
__module____qualname__r]   r9   propertyr#   r'   r;   r)   rd   r-   r+   r/   r6   r$   r$   r$   r%   r"   d   s   


;Mr"   )-r]   
__future__r   logging	getLoggerr2   log	itertoolsr   typingr   r   r   r	   r   Zutil.dependenciesr   Zbokeh.layoutsr
   Zbokeh.modelsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Z
core.typesr   r#   r   __all__r   r"   r$   r$   r$   r%   <module>   s"   

P