def plot_html(self, filename="filename"): """ plotting the network using Bokeh package. plot1 is the article titles graph. based on doi plot2 is the authors graph. based on author id the input is the filename without extension """ # iterate over nodes,convert lists to string to avoid error and create "size" attribute for node in list(self.G): for key in self.G.nodes[node].keys(): if isinstance(self.G.nodes[node][key], list): self.G.nodes[node][key] = ' '.join( [str(elem) for elem in self.G.nodes[node][key]]) # Show with Bokeh plot1 = Plot(x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) plot1.title.text = self.plot_name graph_renderer = from_networkx(self.G, nx.spring_layout, scale=0.1, center=(0, 0)) graph_renderer.node_renderer.glyph = Circle(size=5, fill_color='color') graph_renderer.edge_renderer.glyph = MultiLine(line_color="edge_color", line_alpha=0.8, line_width=1) tooltips = [("title", "@title"), ("author", "@authors"), ("year", "@year"), ("journal", "@journal"), ("doi", "@doi")] node_hover_tool = HoverTool(tooltips=tooltips) plot1.add_tools( node_hover_tool, BoxZoomTool(), ResetTool(), PanTool(), ) plot1.renderers.append(graph_renderer) plot2 = Plot(x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) plot2.title.text = 'authors' graph2_renderer = from_networkx(self.A, nx.spring_layout, scale=0.1, center=(0, 0)) graph2_renderer.node_renderer.glyph = Circle(size=5, fill_color='color') tooltips2 = [ ("name", "@name"), ("author id", "@authorId"), ] node_hover_tool2 = HoverTool(tooltips=tooltips2) plot2.add_tools(node_hover_tool2, BoxZoomTool(), ResetTool(), PanTool()) plot2.renderers.append(graph2_renderer) output_file(filename + '.html', mode='cdn') show(row(plot1, plot2))
def bokeh_plot(G, package, output_file_name, layout=nx.spectral_layout): plot = Plot(plot_width=1500, plot_height=1000, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) plot.title.text = f'Dependency network for {package.name[:-6]}' node_hover_tool = HoverTool(tooltips=[("index", "@index")]) plot.add_tools(node_hover_tool, TapTool(), BoxSelectTool(), BoxZoomTool(), ResetTool(), WheelZoomTool(), PanTool()) graph_renderer = from_networkx(G, layout, scale=1, center=(0, 0)) graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0]) graph_renderer.node_renderer.selection_glyph = Circle( size=15, fill_color=Spectral4[2]) graph_renderer.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1]) graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5) graph_renderer.edge_renderer.selection_glyph = MultiLine( line_color=Spectral4[2], line_width=5) graph_renderer.edge_renderer.hover_glyph = MultiLine( line_color=Spectral4[1], line_width=5) graph_renderer.selection_policy = NodesAndLinkedEdges() plot.renderers.append(graph_renderer) output_file(output_file_name) show(plot)
def create_graph(layout_func, inspection_policy=None, selection_policy=None, **kwargs): plot = Plot(width=400, height=400, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) graph_renderer = from_networkx(G, layout_func, **kwargs) graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0]) graph_renderer.node_renderer.selection_glyph = Circle( size=15, fill_color=Spectral4[2]) graph_renderer.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1]) graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5) graph_renderer.edge_renderer.selection_glyph = MultiLine( line_color=Spectral4[2], line_width=5) graph_renderer.edge_renderer.hover_glyph = MultiLine( line_color=Spectral4[1], line_width=5) if inspection_policy is not None: graph_renderer.inspection_policy = inspection_policy if selection_policy is not None: graph_renderer.selection_policy = selection_policy plot.renderers.append(graph_renderer) return plot
def plot_graph1(G): """ Given a graph, plot it """ plot = Plot(plot_width=3000, plot_height=3000, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) plot.title.text = "Lightning Network Graph" node_hover_tool = HoverTool( tooltips=[("pubkey", "@index"), ("degree", "@degree"), ("capacity", "@capacity")]) plot.add_tools(node_hover_tool, BoxZoomTool(), ResetTool()) graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0)) # graph_renderer = from_networkx(nx.subgraph(G,list(G.nodes)[:1000]), nx.spring_layout, scale=1, center=(0, 0)) graph_renderer.node_renderer.glyph = Circle(size=15, fill_color='color') # graph_renderer.edge_renderer.glyph = MultiLine(line_color = "#CCCCCC", line_alpha = 0.8, line_width = 5) # graph_renderer.edge_renderer.selection_glyph = MultiLine(line_color = Spectral4[2], line_width = 5) # graph_renderer.edge_renderer.hover_glyph = MultiLine(line_color = Spectral4[1], line_width = 5) # graph_renderer.selection_policy = EdgesAndLinkedNodes() # graph_renderer.inspection_policy = EdgesAndLinkedNodes() plot.renderers.append(graph_renderer) output_file("lightning_network_visualization.html") show(plot)
def empty_plot(self): hover_tool = HoverTool( tooltips=[("id", "@artist_id"), ("name", "@artist_name")]) wheel_zoom_tool = WheelZoomTool() reset_tool = ResetTool() pan_tool = PanTool() plot = Plot(sizing_mode='scale_both', max_height=1000, max_width=1000, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1), outline_line_color=None, name='main_plot', toolbar_location=None, output_backend="webgl") plot.add_tools(hover_tool, wheel_zoom_tool, reset_tool, pan_tool) plot.toolbar.active_scroll = wheel_zoom_tool graph_renderer = from_networkx(self.graph_handler.graph, PLOT_LAYOUT, center=(0, 0), scale=PLOT_SCALE) plot.renderers.append(graph_renderer) return plot
def draw_model(M): """Returns a Bokeh Plot Model that draws the directed graph constructed by make_graph using the Bokeh graph plotting primitives. Typically one would use show() to view the result. Args: A bokeh model M """ K = make_graph(M) plot = figure(title="Structure Graph for Bokeh Model", height=600, width=600) plot.xaxis.visible = False plot.yaxis.visible = False plot.xgrid.visible = False plot.ygrid.visible = False K.graph["graph"] = {"rankdir": "LR"} graph_renderer = from_networkx(K, layout_function=nx.nx_pydot.graphviz_layout, prog="dot") graph_renderer.node_renderer.glyph = Circle(radius=4, fill_alpha=1, fill_color="lightblue") graph_renderer.edge_renderer.glyph = MultiLine(line_width=3, line_color="#ababab") plot.renderers = [graph_renderer] node_hover_tool = HoverTool(tooltips=[("id", "@index"), ("model", "@model"), ("in", "@in")]) plot.add_tools(node_hover_tool) x, y = zip(*graph_renderer.layout_provider.graph_layout.values()) xinterval = max(max(x) - min(x), 200) yinterval = max(max(y) - min(y), 200) plot.x_range = Range1d(start=min(x) - 0.15 * xinterval, end=max(x) + 0.15 * xinterval) plot.y_range = Range1d(start=min(y) - 0.15 * yinterval, end=max(y) + 0.15 * yinterval) D = {"x": x, "y": y, "model": list(dict(K.nodes(data="model")).values())} labels = LabelSet( x="x", y="y", text="model", source=ColumnDataSource(D), text_font_size="8pt", x_offset=-20, y_offset=7, ) plot.renderers.append(labels) return plot
def plot_bokeh(self, labels, output_file=None, node_size=4, node_color=None, edge_color=None, width=None, **kwargs): # Unfortunately, nodes in Bokeh have to be strings or ints plot_d = nx.relabel.relabel_nodes(self, labels) tooltips = [] for node, data in plot_d.nodes(data=True): for key in data: tooltips += [(key, f"@{key}")] break if node_color is None: node_color = {labels[node]: "green" if node in self.path else "lightgray" for node in self.nodes} nx.set_node_attributes(plot_d, node_color, "node_color") fill_color = "node_color" if edge_color is None: edge_color = {(labels[edge[0]], labels[edge[1]]): "limegreen" if edge in self.solution or edge[::-1] in self.solution else "gray" for edge in self.edges} nx.set_edge_attributes(plot_d, edge_color, "edge_color") line_color = "edge_color" if width is None: width = {(labels[edge[0]], labels[edge[1]]): 2 if edge in self.solution else 0.1 for edge in self.edges} nx.set_edge_attributes(plot_d, width, "edge_width") line_width = "edge_width" graph = bkplt.from_networkx(plot_d, nx.circular_layout) graph.node_renderer.glyph = mod.Circle(size=node_size, line_color=fill_color, fill_color=fill_color) graph.edge_renderer.glyph = mod.MultiLine(line_color=line_color, line_width=line_width) plot = mod.Plot() plot.renderers.append(graph) tooltips = [("Label", "@index")] + tooltips node_hover_tool = mod.HoverTool(tooltips=tooltips) plot.add_tools(node_hover_tool, mod.PanTool(), mod.BoxZoomTool(), mod.WheelZoomTool(), mod.SaveTool(), mod.ResetTool()) if output_file: bkplt.output_file(output_file) bkplt.show(plot)
def create_graph_render(self, G): graph = from_networkx(G, nx.spring_layout, scale=5, center=(0, 0)) graph.node_renderer.glyph = Circle(size=15, fill_color=Inferno6[1], fill_alpha=0.6) graph.node_renderer.hover_glyph = Circle(size=15, fill_color=Inferno6[4], fill_alpha=0.6) graph.edge_renderer.glyph = MultiLine(line_color=Inferno6[0], line_alpha=0.3, line_width=3) return graph
def get_plot(self, type, id): print(type, id) self.graph_handler = GraphHandler(type, id) graph_renderer = from_networkx(self.graph_handler.graph, PLOT_LAYOUT, center=(0, 0), scale=PLOT_SCALE) self.plot.renderers[0] = graph_renderer self.node_images() self.make_edges() return self.plot
def network_total_following(self, user_dict, n_neighbors=5): graph = nx.Graph() self.add_nodes(graph, user_dict) self.add_edges(graph, user_dict) for node in list(graph.nodes()): if len(list(graph.neighbors(node))) < n_neighbors: graph.remove_node(node) plot = Plot( plot_width=1140, plot_height=720, x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1)) plot.add_tools( HoverTool(tooltips=[('User','@name'), ('Neighbors', '@neighbors')], line_policy='nearest'), TapTool(), BoxSelectTool(), PanTool(), WheelZoomTool(), ResetTool()) graph_render = from_networkx(graph, nx.spring_layout, scale=2.5, center=(0,0)) graph_render.node_renderer.data_source.data['name'] = list(graph.nodes()) list_edges = self.get_list_of_edges(graph) graph_render.node_renderer.data_source.data['neighbors'] = list_edges mapper = linear_cmap('neighbors', palette=Plasma11, low=min(list_edges), high=max(list_edges)) graph_render.node_renderer.glyph = Circle( size=10, fill_color=mapper) graph_render.node_renderer.hover_glyph = Circle( size=200, fill_color=mapper) graph_render.node_renderer.selection_glyph = Circle( size=200, fill_color=mapper) graph_render.edge_renderer.glyph = MultiLine( line_color=Greys4[2], line_alpha=0.3, line_width=1) graph_render.edge_renderer.hover_glyph = MultiLine( line_color=Greys4[1], line_width=2) graph_render.edge_renderer.selection_glyph = MultiLine( line_color=Greys4[0], line_width=3) graph_render.selection_policy = NodesAndLinkedEdges() graph_render.inspection_policy = NodesAndLinkedEdges() plot.renderers.append(graph_render) show(plot)
def get_graph_renderer(S, line_dash): # we need a consistent ordering of the edges edgelist = S.edges() nodelist = S.nodes() # get the colors assigned to each edge based on friendly/hostile sign_edge_color = [ '#87DACD' if S[u][v]['sign'] == 1 else '#FC9291' for u, v in edgelist ] # get the colors assigned to each node by coloring try: coloring_node_color = [ '#4378F8' if nodelist[v]['color'] else '#FFE897' for v in nodelist ] except KeyError: coloring_node_color = ['#FFFFFF' for __ in nodelist] graph_renderer = from_networkx(S, layout_wrapper) circle_size = 10 graph_renderer.node_renderer.data_source.add(coloring_node_color, 'color') graph_renderer.node_renderer.glyph = Circle(size=circle_size, fill_color='color') edge_size = 2 graph_renderer.edge_renderer.data_source.add(sign_edge_color, 'color') try: graph_renderer.edge_renderer.data_source.add( [S[u][v]['event_year'] for u, v in edgelist], 'event_year') graph_renderer.edge_renderer.data_source.add( [S[u][v]['event_description'] for u, v in edgelist], 'event_description') plot.add_tools( HoverTool(tooltips=[("Year", "@event_year"), ("Description", "@event_description")], line_policy="interp")) except KeyError: pass graph_renderer.edge_renderer.glyph = MultiLine(line_color='color', line_dash=line_dash) graph_renderer.inspection_policy = EdgesAndLinkedNodes() return graph_renderer
def render(pkg): global current_rpm, level, hover, source current_rpm = pkg hist.append([pkg, level]) newG = Graph() nrn, nre = graphe(pkg, newG) if nrn == 0: return Div(text="This package is unknown") newgraph = from_networkx(newG, spring_layout, scale=4, center=(0, 0)) newplot = figure(title="RPM network", sizing_mode="scale_width", aspect_ratio=2, x_range=(-2.2, 2.2), y_range=(-2.1, 2.1), tools="tap", toolbar_location=None) newplot.axis.visible = False newplot.grid.visible = False newgraph.node_renderer.glyph = Rect(height=0.07, width=0.1, fill_color="color", fill_alpha=0.0, line_alpha=0.0) if nre != 0: newgraph.edge_renderer.glyph = MultiLine(line_color="color", line_alpha=0.8) newplot.renderers.append(newgraph) source = newgraph.node_renderer.data_source xcoord = CustomJSTransform(v_func=code % "0", args=dict(provider=newgraph.layout_provider)) ycoord = CustomJSTransform(v_func=code % "1", args=dict(provider=newgraph.layout_provider)) source.selected.on_change('indices', selected) labels = LabelSet(x=transform('index', xcoord), y=transform('index', ycoord), text='name', text_font_size="12px", y_offset=-6, x_offset="offset", background_fill_color='color', background_fill_alpha=0.85, border_line_color='color', border_line_alpha=1.0, source=source, render_mode='canvas') newplot.add_tools(hover) newplot.add_layout(labels) return newplot
def create_plot(self): ''' Create plot for rendering with Bokeh ''' if self.plot is None: G = nx.convert_node_labels_to_integers( self.G ) # Bokeh cannot handle non-primitive node keys (eg. tuples) self.layout = self.layout_func(G) plot = figure(x_range=(-1.1, 1.1), y_range=(-1.1, 1.1), tooltips=[]) plot.axis.visible = None plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = None renderer = from_networkx(G, self.layout) plot.renderers.append(renderer) self.plot = plot return self.plot
def make_single_node_plot(self): """ Plot single node graph with reducer :return: Bokeh plot with the graph :rtype: bokeh.plotting.figure.Figure """ HOVER_TOOLTIPS = [ ("Name", "@name"), ("Role", "@role"), ("Status", "@status"), ("Id", "@index"), ] G = networkx.Graph() G.add_node("reducer", adjusted_node_size=20, role='reducer', status='active', name='reducer', color_by_this_attribute=Spectral8[0]) network_graph = from_networkx(G, networkx.spring_layout) network_graph.node_renderer.glyph = Circle(size=20, fill_color = Spectral8[0]) network_graph.node_renderer.hover_glyph = Circle(size=20, fill_color='white', line_width=2) network_graph.node_renderer.selection_glyph = Circle(size=20, fill_color='white', line_width=2) plot = figure(tooltips=HOVER_TOOLTIPS, tools="pan,wheel_zoom,save,reset", active_scroll='wheel_zoom', width=725, height=460, sizing_mode='stretch_width', x_range=Range1d(-1.5, 1.5), y_range=Range1d(-1.5, 1.5)) plot.renderers.append(network_graph) plot.axis.visible = False plot.grid.visible = False plot.outline_line_color = None label = Label(x=0, y=0, text='reducer', background_fill_color='#4bbf73', text_font_size='15px', background_fill_alpha=.7, x_offset=-20, y_offset=10) plot.add_layout(label) return plot
def __init__(self, graph, coloring_df, my_palette): self.my_palette = my_palette self.bokeh_graph = create_bokeh_graph(graph, coloring_df, my_palette) self.plot = Plot(plot_width=700, plot_height=600, x_range=Range1d(-1, 1), y_range=Range1d(-1, 1), output_backend="svg", sizing_mode="stretch_both") node_hover_tool = HoverTool( tooltips=[("index", "@index"), ("size", "@size")] + [(name, '@{}'.format(name)) for name in coloring_df.columns]) zoom_tool = WheelZoomTool() self.plot.add_tools(PanTool(), node_hover_tool, zoom_tool, ResetTool(), SaveTool()) self.plot.toolbar.active_scroll = zoom_tool self.graph_renderer = from_networkx( self.bokeh_graph, nx.spring_layout, seed=24, scale=1, center=(0, 0), k=10 / np.sqrt(len(self.bokeh_graph.nodes)), iterations=2000) # nodes self.graph_renderer.node_renderer.glyph = Circle(size='size rescaled', fill_color='color', fill_alpha=0.8) # edges self.graph_renderer.edge_renderer.glyph = MultiLine(line_color='black', line_alpha=0.8, line_width=1) self.plot.renderers.append(self.graph_renderer)
def build_plot(term: str, g: nx.Graph, fpath: Optional[str] = None): plot = Plot( plot_width=1200, plot_height=800, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1), ) plot.title.text = f""""{term}" google vs. graph""" plot.add_tools(TapTool(), BoxSelectTool()) graph_renderer = from_networkx(g, nx.spring_layout, scale=1, center=(0, 0)) graph_renderer.node_renderer.glyph = Circle(size="total_weight", fill_color=Spectral4[0]) graph_renderer.node_renderer.selection_glyph = Circle( size=15, fill_color=Spectral4[2]) graph_renderer.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1]) graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width="weight") graph_renderer.edge_renderer.selection_glyph = MultiLine( line_color=Spectral4[2], line_width=5) graph_renderer.edge_renderer.hover_glyph = MultiLine( line_color=Spectral4[1], line_width=5) graph_renderer.selection_policy = NodesAndLinkedEdges() graph_renderer.inspection_policy = NodesAndLinkedEdges() plot.renderers.append(graph_renderer) node_hover_tool = HoverTool(tooltips=[("name", "@name")]) plot.add_tools(node_hover_tool, BoxZoomTool(), ResetTool(), TapTool(), WheelZoomTool()) if not fpath: fpath = f"vs_graph_{term.replace(' ', '_').replace('/', '-')}.html" output_file(fpath) show(plot)
def circuit_from(bqm): #G = bqm.to_networkx_graph() # workaround for G = nx.Graph() # https://github.com/dwavesystems/dimod/issues/735 G.add_nodes_from(bqm.variables) G.add_edges_from(bqm.quadratic) plot = Plot(plot_width=600, plot_height=400, x_range=Range1d(-0.1, 1.1), y_range=Range1d(-.1, 1.1)) plot.title.text = "Multiplication as a BQM" plot.add_tools(HoverTool(tooltips=None), TapTool(), BoxSelectTool()) graph_renderer = from_networkx(G, circuit_layout) circle_size = 25 graph_renderer.node_renderer.glyph = Circle(size=circle_size, fill_color="#F5F7FB") graph_renderer.node_renderer.selection_glyph = Circle(size=circle_size, fill_color="#EEA64E") graph_renderer.node_renderer.hover_glyph = Circle(size=circle_size, fill_color="#FFE86C") edge_size = 2 graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=edge_size) graph_renderer.edge_renderer.selection_glyph = MultiLine( line_color="#EEA64E", line_width=edge_size) graph_renderer.edge_renderer.hover_glyph = MultiLine(line_color="#FFE86C", line_width=edge_size) graph_renderer.selection_policy = NodesAndLinkedEdges() graph_renderer.inspection_policy = NodesAndLinkedEdges() plot.renderers.append(graph_renderer) plot.background_fill_color = "#202239" add_labels(plot) show(Row(plot))
def to_bokeh(g, pos=None, pos_by='force', iterations=2000, **attrs): from bokeh.plotting import from_networkx # gu=g.to_undirected() gu = g if not pos or pos_by == 'geo': pos = layout_graph(gu, pos=pos, pos_by=pos_by, iterations=iterations, **attrs) posnow = dict((n, x) for n, x in pos.items() if gu.has_node(n)) # # jitter? # xj = range_x * (range_fac/2) # yj = range_y * (range_fac/2) # for node in posnow: # x,y = posnow[node] # x2=x + random.normalvariate(-xj,xj) # y2=y + random.normalvariate(-yj,yj) # posnow[node]=(x2,y2) return from_networkx(gu, posnow), posnow
def plot_dag( functions, targets=None, columns_overriding_functions=None, check_minimal_specification="ignore", selectors=None, labels=True, tooltips=False, plot_kwargs=None, arrow_kwargs=None, edge_kwargs=None, label_kwargs=None, node_kwargs=None, ): """Plot the dag of the tax and transfer system. Parameters ---------- functions : str, pathlib.Path, callable, module, imports statements, dict Functions can be anything of the specified types and a list of the same objects. If the object is a dictionary, the keys of the dictionary are used as a name instead of the function name. For all other objects, the name is inferred from the function name. targets : str, list of str String or list of strings with names of functions whose output is actually needed by the user. columns_overriding_functions : str list of str Names of columns in the data which are preferred over function defined in the tax and transfer system. check_minimal_specification : {"ignore", "warn", "raise"}, default "ignore" Indicator for whether checks which ensure the most minimal configuration should be silenced, emitted as warnings or errors. selectors : str or list of str or dict or list of dict or list of str and dict Selectors allow to you to select and de-select nodes in the graph for visualization. For the full list of options, see the tutorial about `visualization <../docs/tutorials/visualize.ipynb>`_. By default, all nodes are shown. labels : bool, default True Annotate nodes with labels. tooltips : bool, default False Experimental feature which makes the source code of the functions accessible as a tooltip. Sometimes, the tooltip is not properly displayed. plot_kwargs : dict Additional keyword arguments passed to :class:`bokeh.models.Plot`. arrow_kwargs : dict Additional keyword arguments passed to :class:`bokeh.models.Arrow`. For example, change the size of the head with ``{"size": 10}``. edge_kwargs : dict Additional keyword arguments passed to :class:`bokeh.models.MultiLine`. For example, change the color with ``{"fill_color": "green"}``. label_kwargs : dict Additional keyword arguments passed to :class:`bokeh.models.LabelSet`. For example, change the fontsize with ``{"text_font_size": "12px"}``. node_kwargs : dict Additional keyword arguments passed to :class:`bokeh.models.Circle`. For example, change the color with ``{"fill_color": "orange"}``. """ targets = DEFAULT_TARGETS if targets is None else targets targets = parse_to_list_of_strings(targets, "targets") columns_overriding_functions = parse_to_list_of_strings( columns_overriding_functions, "columns_overriding_functions") # Load functions and perform checks. functions, internal_functions = load_user_and_internal_functions(functions) # Create one dictionary of functions and perform check. functions = {**internal_functions, **functions} functions = { k: v for k, v in functions.items() if k not in columns_overriding_functions } _fail_if_targets_not_in_functions(functions, targets) # Partial parameters to functions such that they disappear in the DAG. functions = _mock_parameters_arguments(functions) dag = create_dag(functions, targets, columns_overriding_functions, check_minimal_specification) selectors = [] if selectors is None else _to_list(selectors) plot_kwargs = {} if plot_kwargs is None else plot_kwargs arrow_kwargs = {} if arrow_kwargs is None else arrow_kwargs edge_kwargs = {} if edge_kwargs is None else edge_kwargs label_kwargs = {} if label_kwargs is None else label_kwargs node_kwargs = {} if node_kwargs is None else node_kwargs dag = _select_nodes_in_dag(dag, selectors) dag = _add_url_to_dag(dag) # Even if we do not use the source codes as tooltips, we need to remove the # functions. dag = _replace_functions_with_source_code(dag) plot_kwargs["title"] = _to_bokeh_title( plot_kwargs.get("title", "Tax and Transfer System")) plot = Plot(**{**PLOT_KWARGS_DEFAULTS, **plot_kwargs}) layout = _create_pydot_layout(dag) graph_renderer = from_networkx(dag, layout, scale=1, center=(0, 0)) graph_renderer.node_renderer.glyph = Circle(**{ **NODE_KWARGS_DEFAULTS, **node_kwargs }) graph_renderer.edge_renderer.visible = False for ( _, (start_node, end_node), ) in graph_renderer.edge_renderer.data_source.to_df().iterrows(): (x_start, y_start), (x_end, y_end) = _compute_arrow_coordinates( layout[start_node], layout[end_node]) plot.add_layout( Arrow( end=NormalHead(**{ **ARROW_KWARGS_DEFAULTS, **arrow_kwargs }), x_start=x_start, y_start=y_start, x_end=x_end, y_end=y_end, **{ **EDGE_KWARGS_DEFAULTS, **edge_kwargs }, )) plot.renderers.append(graph_renderer) tools = [BoxZoomTool(), ResetTool()] tools.append(TapTool(callback=OpenURL(url="@url"))) if tooltips: tools.append(HoverTool(tooltips=TOOLTIPS)) plot.add_tools(*tools) if labels: source = ColumnDataSource( pd.DataFrame(layout).T.rename(columns={ 0: "x", 1: "y" })) labels = LabelSet( x="x", y="y", text="index", source=source, **{ **LABEL_KWARGS_DEFAULT, **label_kwargs }, ) plot.add_layout(labels) output_notebook() show(plot) return plot
import networkx as nx from bokeh.io import show, output_file from bokeh.plotting import figure, from_networkx G = nx.karate_club_graph() plot = figure(title="Networkx Integration Demonstration", x_range=(-1.1, 1.1), y_range=(-1.1, 1.1), tools="", toolbar_location=None) graph = from_networkx(G, nx.spring_layout, scale=2, center=(0, 0)) plot.renderers.append(graph) output_file("networkx_graph.html") show(plot)
def plot(self, layout=None, fig_size=(400, 400), node_size=15, fill_color=None, title='Interactive graph', scale=0.5, center=(0.5, 0.5), **kwargs): if layout is None: if self.has_layout: # layout = lambda x: self.layout g = from_networkx(self.G, self.layout, scale=scale, center=center, **kwargs) else: layout = nx.random_layout g = from_networkx(self.G, layout, center=(0, 0)) else: g = from_networkx(self.G, layout, scale=scale, center=center, **kwargs) # Create canvas area plot = Plot(plot_width=fig_size[0], plot_height=fig_size[1], x_range=Range1d(-0.1, 1.1), y_range=Range1d(-0.1, 1.1)) plot.title.text = title plot.add_tools( PanTool(), HoverTool(tooltips=[(key, f"@{key}") for key in self.keys]), TapTool(), ZoomInTool(), ZoomOutTool()) # Settings for rendering the graph if fill_color is not None: g.node_renderer.data_source.data['colors'] = fill_color g.node_renderer.glyph = Circle(size=node_size, fill_color='colors', fill_alpha=0.5) else: g.node_renderer.glyph = Circle(size=node_size, fill_color=Spectral4[0], fill_alpha=0.5) g.node_renderer.selection_glyph = Circle(size=node_size, fill_color=Spectral4[2]) g.node_renderer.hover_glyph = Circle(size=node_size, fill_color=Spectral4[1]) g.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.5, line_width=2) g.edge_renderer.selection_glyph = MultiLine(line_color=Spectral4[2], line_width=2) g.edge_renderer.hover_glyph = MultiLine(line_color=Spectral4[1], line_width=2) # Make nodes and edges selectable and hoverable g.selection_policy = NodesAndLinkedEdges() g.inspection_policy = NodesOnly() plot.renderers.append(g) # show(plot) return plot
# plot_segment.view = new_corr_view # plot_segment.update() l_slider.on_change('value_throttled', ls_callback) # plot_scatter.visible = False G = nx.Graph() G.add_nodes_from(init_names) G.add_edges_from(itertools.combinations(init_names, 2)) fixed_positions = dict(zip(init_names, list(zip(init_x, init_y)))) # graph_renderer = from_networkx(G, nx.spring_layout, pos=fixed_positions, fixed=init_names, center=(0, 0)) node_attrs = {} for i, name in enumerate(init_names): node_attrs[name] = {} node_attrs[name]['size'] = init_sizes[i] node_attrs[name]['sector'] = init_sectors[i] node_attrs[name]['name'] = init_names[i] node_attrs[name]['full_name'] = init_full_names[i] node_attrs[name]['category'] = init_categories[i] nx.set_node_attributes(G, node_attrs) graph_renderer.node_renderer.data_source.data['sector'] = [
def Grap(df_graphe): G = networkx.from_pandas_edgelist(df_graphe, 'source', 'target') #titre titre = 'Graphes des mots du corpus de documents' #On calcule un degree pour chaque Noeud et on lui assigne un attribut. Un degree est le nombre de lien qu'un noeud comporte degrees = dict(networkx.degree(G)) networkx.set_node_attributes(G, name='degree', values=degrees) #La c'est pour la subrillance entre les liens et les noeuds quand on passe la souris dessus node_highlight_color = 'white' edge_highlight_color = 'black' #On ajuste les petits noeuds pour qu'ils soient toujours visible number_to_adjust_by = 7 adjusted_node_size = dict([(node, degree + number_to_adjust_by) for node, degree in networkx.degree(G)]) networkx.set_node_attributes(G, name='adjusted_node_size', values=adjusted_node_size) #Gestion des couleurs/tailles size_by_this_attribute = 'adjusted_node_size' color_by_this_attribute = 'adjusted_node_size' #La je choisie ma palette de couleur color_palette = Blues8 #Hover pour quand on survole le noeud HOVER_TOOLTIPS = [("Source", "@index"), ("Mot", "@degree")] #Création du plot — set dimensions, toolbar, et titre plot = figure(tooltips=HOVER_TOOLTIPS, tools="pan,wheel_zoom,save,reset", active_scroll='wheel_zoom', x_range=Range1d(-10.1, 10.1), y_range=Range1d(-10.1, 10.1), title=titre) #Création d'un graphe network_graph = from_networkx(G, networkx.spring_layout, scale=10, center=(0, 0)) #################################################################Ici on va pimper notre graph################################################################## #Surlignage des noeuds network_graph.node_renderer.hover_glyph = Circle( size=size_by_this_attribute, fill_color=node_highlight_color, line_width=2) network_graph.node_renderer.selection_glyph = Circle( size=size_by_this_attribute, fill_color=node_highlight_color, line_width=2) #Opacité et épaisseur network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width=1) #Couleur des liens etc network_graph.edge_renderer.selection_glyph = MultiLine( line_color=edge_highlight_color, line_width=2) network_graph.edge_renderer.hover_glyph = MultiLine( line_color=edge_highlight_color, line_width=2) #Ca c'est pour la subrillance des liens et des noeuds network_graph.selection_policy = NodesAndLinkedEdges() network_graph.inspection_policy = NodesAndLinkedEdges() #Ici on définit les couleurs et on les appliquent minimum_value_color = min( network_graph.node_renderer.data_source.data[color_by_this_attribute]) maximum_value_color = max( network_graph.node_renderer.data_source.data[color_by_this_attribute]) network_graph.node_renderer.glyph = Circle( size=size_by_this_attribute, fill_color=linear_cmap(color_by_this_attribute, color_palette, minimum_value_color, maximum_value_color)) ############################################################################################################################################################ #On fais le rendu final plot.renderers.append(network_graph) #Affichage show(plot) #Enregistrement dans le répertoire courant save(plot, filename=str(titre) + ".html")
TapTool, ) from bokeh.palettes import Spectral4 from bokeh.plotting import from_networkx G = nx.karate_club_graph() plot = Plot(plot_width=400, plot_height=400, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) plot.title.text = "Graph Interaction Demonstration" plot.add_tools(HoverTool(tooltips=None), TapTool(), BoxSelectTool()) graph_renderer = from_networkx(G, nx.circular_layout, scale=1, center=(0, 0)) graph_renderer.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0]) graph_renderer.node_renderer.selection_glyph = Circle(size=15, fill_color=Spectral4[2]) graph_renderer.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1]) graph_renderer.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5) graph_renderer.edge_renderer.selection_glyph = MultiLine( line_color=Spectral4[2], line_width=5) graph_renderer.edge_renderer.hover_glyph = MultiLine(line_color=Spectral4[1], line_width=5)
def draw_plot(G, query, expr): plot = Plot( x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1), sizing_mode="stretch_both") plot.title.text = "Relationship Graph for: " + expr tooltips = """ <div style="max-width : 300px"> <div><span style="">@type</span></div> <div><span style="font-weight: bold;">@title</span></div> <div><span style="">@authors</span></div> <div><span style="font-weight: bold;">@journal</span></div> <div><span style="font-weight: bold;">@year</span></div> <div><span style=""><a href="https://doi.org/@DOI">@DOI</a></span></div> </div> """ node_hover_tool = HoverTool(tooltips=tooltips) zoom_tool = WheelZoomTool() tap_tool_open = TapTool() #tap_tool_open.callback = OpenURL(url='https://doi.org/@DOI') #tap_tool_open.callback = OpenURL( # same_tab=True, # url="javascript:document.getElementById('showpaper').innerHTML='" + tooltips + "';") #tap_tool_open.callback = CustomJS( # args=dict(source=0, selected=0), # code = """document.getElementById('showpaper').innerHTML='""" + ''.join(tooltips.splitlines()) + "';") showpaper = """ <div style="max-width : 80%"> <div><span style="">@type</span></div> <div><span style="font-weight: bold;">@title</span></div> <div><span style="">@authors</span></div> <div><span style="font-weight: bold;">@journal</span></div> <div><span style="font-weight: bold;">@year</span></div> <div><span style=""><a target="_blank" href="https://doi.org/@DOI">@DOI</a></span></div> </div> """ code = ''' if (cb_data.source.selected.indices.length > 0){ var selected_index = cb_data.source.selected.indices[0]; var tooltip = document.getElementById("showpaper"); cb_data.source.data.color[selected_index] = 'grey' tp = tp.replace('@type', cb_data.source.data.type[selected_index]); tp = tp.replace('@title', cb_data.source.data.title[selected_index]); tp = tp.replace('@authors', cb_data.source.data.authors[selected_index]); tp = tp.replace('@journal', cb_data.source.data.journal[selected_index]); tp = tp.replace('@year', cb_data.source.data.year[selected_index]); tp = tp.replace('@DOI', cb_data.source.data.DOI[selected_index]); tp = tp.replace('@DOI', cb_data.source.data.DOI[selected_index]); tooltip.innerHTML = tp; } ''' tap_tool_open.callback = CustomJS( args = {'tp': showpaper}, code = code) tap_tool = TapTool() plot.add_tools( node_hover_tool, zoom_tool, # BoxZoomTool(), ResetTool(), tap_tool_open, tap_tool ) plot.toolbar.active_scroll = zoom_tool graph_renderer = from_networkx( G, nx.spring_layout, scale=1, center=(0, 0), seed=12345) # normal graph_renderer.node_renderer.glyph = Circle( size="size", fill_color="color") graph_renderer.edge_renderer.glyph = MultiLine( line_alpha=0.2) # selection graph_renderer.node_renderer.selection_glyph = Circle( fill_color="color", fill_alpha=1, line_alpha=1) graph_renderer.edge_renderer.selection_glyph = MultiLine( line_width=3, line_alpha=1) graph_renderer.node_renderer.nonselection_glyph = Circle( fill_color="color", fill_alpha=0.5, line_alpha=0.5) graph_renderer.edge_renderer.nonselection_glyph = MultiLine( line_alpha=0.2) # hover graph_renderer.node_renderer.hover_glyph = Circle( fill_color='#abdda4') graph_renderer.edge_renderer.hover_glyph = MultiLine( line_color='#abdda4', line_width=3) graph_renderer.inspection_policy = NodesAndLinkedEdges() graph_renderer.selection_policy = NodesAndLinkedEdges() plot.renderers.append(graph_renderer) script, div = components(plot) return script, div
def transformations(): graph_data_manager = None graph_title = None json_graph = None target_python_code = None compiled_c = None compiled_java = None python_code_generated = None if flask.request.method == "POST": success = False python_code: werkzeug.datastructures.FileStorage python_code = flask.request.files.get("python-code") if python_code is not None: buffer = io.BytesIO() python_code.save(buffer) buffer.seek(0) content = buffer.read() try: content = content.decode() parsed_code = ast.parse(content, python_code.filename) if parsed_code.body: node_id = 1 graph_data_manager = networkx.Graph() graph_data_manager.add_node(node_id, name=python_code.filename, kind="Script") node_id += 1 for node in parsed_code.body: if isinstance(node, ast.ImportFrom): import_id = node_id import_name = ("." * node.level) + node.module graph_data_manager.add_node(import_id, name=import_name, kind="ImportFrom") graph_data_manager.add_edge(1, import_id, label="From") node_id += 1 for name in node.names: graph_data_manager.add_node( node_id, name=name.name, kind="ImportFromTarget") graph_data_manager.add_edge(import_id, node_id, label="Import") node_id += 1 elif isinstance(node, ast.Import): for name in node.names: name: ast.alias graph_data_manager.add_node(node_id, name=name.name, kind="Module") graph_data_manager.add_edge(1, node_id, label="Imports") node_id += 1 elif isinstance(node, ast.ClassDef): class_name = node.name class_id = node_id graph_data_manager.add_node(class_id, name=class_name, kind="Class") graph_data_manager.add_edge(1, class_id, label="Defines") found_object_base = False node_id += 1 for base in node.bases: if isinstance(base, ast.Attribute): parts = [] while isinstance(base, ast.Attribute): parts.append(base.attr) base = base.value if isinstance(base, ast.Name): parts.append(base.id) else: parts.append("Unknown") base_name = ".".join(parts[::-1]) elif isinstance(base, ast.Name): base_name = base.id else: base_name = "Unknown" if base_name == "object": found_object_base = True graph_data_manager.add_node(node_id, name=base_name, kind="Base") graph_data_manager.add_edge(class_id, node_id, label="Implements") node_id += 1 if not found_object_base: graph_data_manager.add_node(node_id, name="object", kind="Base") graph_data_manager.add_edge(class_id, node_id, label="Implements") node_id += 1 for class_node in node.body: if isinstance(class_node, ast.FunctionDef): function_id = node_id graph_data_manager.add_node( node_id, name=class_node.name, kind="Class Method") graph_data_manager.add_edge( class_id, node_id) node_id += 1 for argument in class_node.args.args: graph_data_manager.add_node( node_id, name=argument.arg, kind="Argument") graph_data_manager.add_edge( function_id, node_id, label="Has") node_id += 1 elif isinstance(node, ast.FunctionDef): function_id = node_id graph_data_manager.add_node(function_id, name=node.name, kind="Function") graph_data_manager.add_edge(1, function_id, label="Defines") node_id += 1 for argument in node.args.args: graph_data_manager.add_node(node_id, name=argument.arg, kind="Argument") graph_data_manager.add_edge(function_id, node_id, label="Has") node_id += 1 target_python_code = content json_graph = json.dumps( networkx.readwrite.node_link_data(graph_data_manager)) graph_title = python_code.filename success = True python_code_generated = False except (SyntaxError, ValueError, Exception) as e: pass if not success: code_map: werkzeug.datastructures.FileStorage code_map = flask.request.files.get("code-map") if code_map is not None: buffer = io.BytesIO() code_map.save(buffer) buffer.seek(0) content = buffer.read() try: raw_graph_data = json.loads(content) graph_data_manager = networkx.readwrite.json_graph.node_link_graph( raw_graph_data) compiled_c, compiled_java, target_python_code = Compiler( raw_graph_data).compile_code() graph_title = raw_graph_data["nodes"][0]["name"] json_graph = json.dumps(raw_graph_data) success = True python_code_generated = True except (json.JSONDecodeError, Exception) as e: pass if success: network_graph = from_networkx(graph_data_manager, networkx.spring_layout, scale=100, center=(0, 0)) network_graph.node_renderer.glyph = bokeh.models.Circle( size=15, fill_color=bokeh.transform.factor_cmap( "kind", bokeh.palettes.Category20[20], factors=kinds)) network_graph.edge_renderer.glyph = bokeh.models.MultiLine( line_alpha=0.5, line_width=1, line_join='miter', ) plot = bokeh.plotting.figure( tooltips=[("Object Name", "@name"), ("Kind", "@kind")], tools="pan,wheel_zoom,save,reset", x_range=bokeh.models.Range1d(-150, 150), y_range=bokeh.models.Range1d(-150, 150), title=graph_title) plot.renderers.append(network_graph) script, div = bokeh.embed.components(plot) if compiled_c is None and compiled_java is None: compiled_c, compiled_java, _ = Compiler( json_graph).compile_code() target_python_code = target_python_code.replace("\n", "\n\t") compiled_c = compiled_c.replace("\n", "\n\t") compiled_java = compiled_java.replace("\n", "\n\t") return flask.render_template( "basic/page.html", page_name="Transformations", body_page="transformations/analyser.html", listed_objects=markdown.markdown( DescribeCode(json_graph).describe(), extensions=["codehilite", "extra"]), metalanguage=markdown.markdown( "# Metalanguage\n\nGenerated metalanguage useful for sharing the graph or regenerate a code " f"interface for future use. The metalanguage was stored in the JSON bellow.\n\n\t:::json\n\t{json_graph}", extensions=["codehilite", "extra"]), source_code=markdown.markdown(prepare_source_code( compiled_c, compiled_java, target_python_code, python_code_generated), extensions=[ "codehilite", "extra" ]), plot_script=script, plot_div=div, js_resources=bokeh.resources.INLINE.render_js(), css_resources=bokeh.resources.INLINE.render_css(), ) return flask.render_template("basic/page.html", page_name="Transformations", body_page="transformations/file-upload.html")
def generate_graph_internal_link_interactive(website, maximum): domain = urllib.parse.urlparse(website).netloc urls = add_edge({}, website, domain, maximum) # Generating graph and dict of degrees g = nx.Graph(urls) d = dict(g.degree) # Adding table table = dict(url=[k for k, v in d.items()], count=[v for k, v in d.items()]) source = ColumnDataSource(table) columns = [ TableColumn(field="url", title="URL"), TableColumn(field="count", title="Count"), ] data_table = DataTable(source=source, columns=columns, width=400, height_policy="max") # Generating node size and color maxi = 1 if len(d.values()) > 0: maxi = max(d.values()) node_size = {k: max(5, math.ceil((v / maxi) * 30)) for k, v in d.items()} node_color = {k: v for k, v in d.items()} mapper = linear_cmap(field_name='node_color', palette=Spectral6, low=min(node_color.values()), high=max(node_color.values())) nx.set_node_attributes(g, d, 'connection') nx.set_node_attributes(g, node_size, "node_size") nx.set_node_attributes(g, node_color, "node_color") plot = figure(title="Maillage Interne " + domain, plot_width=1200, plot_height=800, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1), sizing_mode='stretch_both') p = row([data_table, plot]) graph = from_networkx(g, nx.spring_layout, scale=2) node_hover_tool = HoverTool( tooltips=[("urls", "@index"), ("Connection", "@connection")]) plot.add_tools(node_hover_tool, BoxZoomTool(), ResetTool()) plot.toolbar.active_scroll = "auto" graph.node_renderer.hover_glyph = Circle(size=20, fill_color=Spectral4[1]) graph.edge_renderer.hover_glyph = MultiLine(line_color=Spectral8[6], line_width=1) graph.edge_renderer.glyph = MultiLine(line_alpha=0.8, line_width=0.03) graph.node_renderer.glyph = Circle(size='node_size', fill_color=mapper) graph.inspection_policy = NodesAndLinkedEdges() color_bar = ColorBar(color_mapper=mapper['transform'], width=8, location=(0, 0)) plot.add_layout(color_bar, 'right') plot.renderers.append(graph) return p, domain
# Display the slider and plot togeher in a column layout show(column(slider, p)) Bokeh also has a number of integrations to make plotting simple. One of these that is particularly useful when investigating network data is [integration with Networkx]("https://docs.bokeh.org/en/latest/docs/user_guide/graph.html?highlight=networkx").</br> Bokeh can take a Networkx graph and plot it on a figure, in addition you can apply a number of Bokeh's interactive options to this allowing for interactive networkx plots. # Create a edgelist from our dataset edgelist= pd.DataFrame({"source": clean_data['src_ip'].to_list(), "target": clean_data['dst_ip'].to_list(), "weight":clean_data['total_bytes'].to_list()}) # Create networkx graph from our edgelist G = nx.from_pandas_edgelist(edgelist) # Create our Bokeh figure p = figure(title="Network node communication graph", x_range=(-2.5,2.5), y_range=(-2.5,2.5)) # Set our hover items and add it to the plot node_hover_tool = HoverTool(tooltips=[("IP address", "@index")]) p.add_tools(node_hover_tool, BoxZoomTool(), ResetTool()) # Generate the graph from networkx and add it to the figure graph = from_networkx(G, nx.circular_layout, scale=2, center=(0,0)) p.renderers.append(graph) # Hide all axes p.xaxis.visible = False p.xgrid.visible = False p.yaxis.visible = False p.ygrid.visible = False show(p) ## Summary This is just a small sample of what you can do with Bokeh when investigating network data, there is a huge range of customization options avaliable to you. If you want to learn more Bokeh has some excellent [documentation]("https://docs.bokeh.org/en/latest/docs/user_guide.html") and if you are searching for inspiration thier [gallery]("https://docs.bokeh.org/en/latest/docs/gallery.html") has some excellent and innovative examples.
result_pos = result_df['coords'].to_dict() result_links = result_df['word_most_similar_indices'].to_dict() result_cds = ColumnDataSource(result_df) G = nx.from_dict_of_lists(result_links) reset_output() #output_notebook() #output_file('critrole_w2v_visualizer.html') # We could use figure here but don't want all the axes and titles plot = Plot(x_range=Range1d(-2, 2), y_range=Range1d(-2, 2)) # Create a Bokeh graph from the NetworkX input using nx.spring_layout #nx.set_node_attributes(G, result_pos, 'coord') graph = from_networkx(G, layout_function=result_pos) graph.node_renderer.glyph = Circle(size=4, fill_color='#2b83ba', line_width=0) graph.edge_renderer.glyph = MultiLine(line_color="#cccccc", line_alpha=0.8, line_width=0) graph.node_renderer.selection_glyph = Circle(size=4, fill_color='red', line_alpha=0.8, line_width=1) graph.edge_renderer.selection_glyph = MultiLine(line_color='red', line_alpha=0.8, line_width=3) plot.renderers.append(graph)
# initiate the plot plot2 = figure(width=1000, height=600) plot2.title.text = "Treasure Archive Drehem: Cliques" plot2.grid.visible = False plot2.xaxis.visible = False plot2.yaxis.visible = False # add tools node_hover_tool = HoverTool( tooltips=[("name", "@index"), ("eigenvector centrality", "@eigenvector_centrality"), ("degree", '@degree')]) plot2.add_tools(node_hover_tool, TapTool()) # add the graph graph = from_networkx(K, pos2) # add node renderers to the graph graph.node_renderer.data_source.data['node_size'] = list(node_sizes2.values()) graph.node_renderer.data_source.data['node_color'] = [ colmap[clique] for clique in graph.node_renderer.data_source.data['cliques'] ] graph.node_renderer.glyph = Circle(fill_color='node_color', size='node_size', fill_alpha=.75) graph.node_renderer.hover_glyph = Circle(size='node_size', fill_color='node_color') graph.node_renderer.selection_glyph = Circle(size='node_size', fill_color='node_color')