def _init_glyphs(self, plot, element, ranges, source): # Get data and initialize data source style = self.style[self.cyclic_index] data, mapping, style = self.get_data(element, ranges, style) self.handles['previous_id'] = element._plot_id properties = {} mappings = {} for key in list(mapping): if not any(glyph in key for glyph in ('scatter_1', 'multi_line_1')): continue source = self._init_datasource(data.pop(key, {})) self.handles[key + '_source'] = source glyph_props = self._glyph_properties(plot, element, source, ranges, style) properties.update(glyph_props) mappings.update(mapping.pop(key, {})) properties = { p: v for p, v in properties.items() if p not in ('legend', 'source') } properties.update(mappings) layout = data.pop('layout', {}) if data and mapping: CompositeElementPlot._init_glyphs(self, plot, element, ranges, source, data, mapping, style) # Define static layout layout = StaticLayoutProvider(graph_layout=layout) node_source = self.handles['scatter_1_source'] edge_source = self.handles['multi_line_1_source'] renderer = plot.graph(node_source, edge_source, layout, **properties) # Initialize GraphRenderer if self.selection_policy == 'nodes': renderer.selection_policy = NodesAndLinkedEdges() elif self.selection_policy == 'edges': renderer.selection_policy = EdgesAndLinkedNodes() else: renderer.selection_policy = None if self.inspection_policy == 'nodes': renderer.inspection_policy = NodesAndLinkedEdges() elif self.inspection_policy == 'edges': renderer.inspection_policy = EdgesAndLinkedNodes() else: renderer.inspection_policy = None self.handles['layout_source'] = layout self.handles['glyph_renderer'] = renderer self.handles['scatter_1_glyph_renderer'] = renderer.node_renderer self.handles['multi_line_1_glyph_renderer'] = renderer.edge_renderer self.handles['scatter_1_glyph'] = renderer.node_renderer.glyph self.handles['multi_line_1_glyph'] = renderer.edge_renderer.glyph if 'hover' in self.handles: self.handles['hover'].renderers.append(renderer)
def _set_interaction_policies(self, renderer): if self.selection_policy == 'nodes': renderer.selection_policy = NodesAndLinkedEdges() elif self.selection_policy == 'edges': renderer.selection_policy = EdgesAndLinkedNodes() else: renderer.selection_policy = NodesOnly() if self.inspection_policy == 'nodes': renderer.inspection_policy = NodesAndLinkedEdges() elif self.inspection_policy == 'edges': renderer.inspection_policy = EdgesAndLinkedNodes() else: renderer.inspection_policy = NodesOnly()
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 style(): global G zip_xy = zip(networkLayout.all_x, networkLayout.all_y) all_cells_numbers = actualNetwork.getAllCellsNumbers() graph_layout = dict(zip(all_cells_numbers, zip_xy)) # layout G.layout_provider = StaticLayoutProvider(graph_layout=graph_layout) G.inspection_policy = NodesAndLinkedEdges() return graph_layout
def style(): global G global node_indices, plot x = [cell_no * FlowParams.d_x for cell_no in range(len(nodeCells))] y = [0] * len(nodeCells) nodeCellNumbers = [cell.number for cell in nodeCells] zip_xy = zip(x, y) nodecellsNumber = [x.number for x in nodeCells] graph_layout = dict(zip(nodecellsNumber, zip_xy)) # layout G.layout_provider = StaticLayoutProvider(graph_layout=graph_layout) G.inspection_policy = NodesAndLinkedEdges() return graph_layout
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 plot_create(self, doc): plot = figure(title="Belief Graph") plot.axis.visible = False node_labels = nx.get_node_attributes(self.bel_graph, 'id') node_labels = tuple([label for label in node_labels.values()]) ncolor = ['#2b83ba' for name in node_labels] nsize = [15 for name in node_labels] graph = from_networkx(self.bel_graph, nx.spring_layout, scale=1, center=(0, 0)) graph.node_renderer.glyph = Circle(size='nsize', fill_color='ncolor') graph.node_renderer.selection_glyph = Circle(size='nsize', fill_color='#054872') graph.node_renderer.hover_glyph = Circle(size='nsize', fill_color='#abdda4') graph.name = "bel_graph" graph.node_renderer.data_source.data.update( dict(id=node_labels, ncolor=ncolor, nsize=nsize)) graph.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5) graph.edge_renderer.selection_glyph = MultiLine(line_color='#054872', line_width=5) graph.edge_renderer.hover_glyph = MultiLine(line_color='#abdda4', line_width=5) graph.selection_policy = NodesAndLinkedEdges() # graph.inspection_policy = EdgesAndLinkedNodes() plot.renderers.append(graph) x, y = zip(*graph.layout_provider.graph_layout.values()) source_graph = ColumnDataSource(data=dict(x=x, y=y, id=node_labels)) labels = LabelSet(x='x', y='y', text='id', source=source_graph) plot.renderers.append(labels) # add tools to the plot plot.add_tools(HoverTool(names=["bel_graph"]), TapTool()) doc.add_root(plot)
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")
def graphPlot(DG, DGspecies, DGreactions, plot, layout="force", positions=None, posscale=1.0, layoutfunc=None, iterations=2000, rseed=30): """given a directed graph, plot it! Inputs: DG: a directed graph of type DiGraph DGspecies: a directed graph which only contains the species nodes DGreactions: a directed graph which only contains the reaction nodes plot: a bokeh plot object layout: graph layout function. 'force' uses fa2 to push nodes apart 'circle' plots the nodes and reactions in two overlapping circles, with the reactions on the inside of the circle 'custom' allows user input "layoutfunc". Internally, layoutfunc is passed the three inputs (DG, DGspecies, DGreactions) and should output a position dictionary with node {<node number>:(x,y)} positions: a dictionary of node names and x,y positions. this gets passed into the layout function posscale: multiply the scaling of the plot. This only affects the arrows because the arrows are a hack :(""" random.seed(rseed) if (not PLOT_NETWORK): warn("network plotting disabled because some libraries are not found") return if (layout == "force"): #below are parameters for the force directed graph visualization forceatlas2 = ForceAtlas2( # Behavior alternatives outboundAttractionDistribution=True, # Dissuade hubs linLogMode=False, # NOT IMPLEMENTED adjustSizes=False, # Prevent overlap (NOT IMPLEMENTED) edgeWeightInfluence=1.0, # Performance jitterTolerance=1.0, # Tolerance barnesHutOptimize=True, barnesHutTheta=1.2, multiThreaded=False, # NOT IMPLEMENTED # Tuning scalingRatio=2.4 * posscale, strongGravityMode=False, gravity=1.0, # Log verbose=False) positions = forceatlas2.forceatlas2_networkx_layout( DG, pos=positions, iterations=iterations) elif (layout == "circle"): positions = nx.circular_layout(DGspecies, scale=50 * posscale) positions.update(nx.circular_layout(DGreactions, scale=35 * posscale)) elif (layout == "custom"): positions = layoutfunc(DG, DGspecies, DGreactions) reaction_renderer = from_networkx(DGreactions, positions, center=(0, 0)) species_renderer = from_networkx(DGspecies, positions, center=(0, 0)) edges_renderer = from_networkx(DG, positions, center=(0, 0)) #edges edges_renderer.node_renderer.glyph = Circle(size=12, line_alpha=0, fill_alpha=0, fill_color="color") edges_renderer.edge_renderer.glyph = MultiLine(line_alpha=0.2, line_width=4, line_join="round") edges_renderer.edge_renderer.selection_glyph = MultiLine( line_color=Spectral4[2], line_width=5, line_join="round") edges_renderer.edge_renderer.hover_glyph = MultiLine( line_color=Spectral4[1], line_width=5, line_join="round") xbounds, ybounds = makeArrows2(edges_renderer, DG, positions, headsize=5) #make the arrows! #we want to find the middle of the graph and plot a square that is 1:1 aspect ratio #find the midpoint of the graph xmid = statistics.mean(xbounds) ymid = statistics.mean(ybounds) #now, subtract the middle from the edges xmiddlized = [a - xmid for a in xbounds] ymiddlized = [a - ymid for a in ybounds] #now, find the biggest dimension absdim = max([abs(a) for a in xmiddlized + ymiddlized]) xlim = [xmid - absdim * 1.05, xmid + absdim * 1.05] ylim = [ymid - absdim * 1.05, ymid + absdim * 1.05] #now set it on the plot! plot.x_range = Range1d(xlim[0], xlim[1]) plot.y_range = Range1d(ylim[0], ylim[1]) #reactions reaction_renderer.node_renderer.glyph = Square(size=8, fill_color=Spectral4[0]) reaction_renderer.node_renderer.selection_glyph = Square( size=8, fill_color=Spectral4[2]) reaction_renderer.node_renderer.hover_glyph = Square( size=8, fill_color=Spectral4[1]) #nodes species_renderer.node_renderer.glyph = Circle(size=12, fill_color="color") species_renderer.node_renderer.selection_glyph = Circle( size=15, fill_color=Spectral4[2]) species_renderer.node_renderer.hover_glyph = Circle( size=15, fill_color=Spectral4[1]) #this part adds the interactive elements that make it so that the lines are highlighted #when you mouse over and click edge_hover_tool = HoverTool(tooltips=None, renderers=[edges_renderer]) species_hover_tool = HoverTool(tooltips=[("name", "@species"), ("type", "@type")],\ renderers=[species_renderer],attachment="right") rxn_hover_tool = HoverTool(tooltips=[("reaction", "@species"), ("type", "@type"),("k_f","@k"),("k_r","@k_r")],\ renderers=[reaction_renderer],attachment="right") plot.add_tools(edge_hover_tool, species_hover_tool, rxn_hover_tool, TapTool(), BoxSelectTool(), PanTool(), WheelZoomTool()) edges_renderer.selection_policy = NodesAndLinkedEdges() edges_renderer.inspection_policy = EdgesAndLinkedNodes() plot.renderers.append(edges_renderer) plot.renderers.append(reaction_renderer) plot.renderers.append(species_renderer)
def save_graph(fol_path): df = folderstats.folderstats(fol_path, ignore_hidden=True) df.loc[list(np.where(df["folder"] == True)[0]), "name"] = df[df["folder"] == True]["path"].apply(ret_name).values # df["name"] = df["name"]+"."+df["extension"] df_sorted = df.sort_values(by='id') G = nx.Graph() for i, row in df_sorted.iterrows(): if row.parent: G.add_edge(row.id, row.parent) plot = Plot(plot_width=1000, plot_height=1000, x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1)) plot.title.text = "File System" plot.add_tools(TapTool(), BoxSelectTool(), BoxZoomTool(), ResetTool(), WheelZoomTool(), PanTool()) graph_renderer = from_networkx(G, nx.spring_layout, scale=2, center=(0, 0)) graph_renderer.node_renderer.data_source.data["id"] = df_sorted[ "id"].astype('str').values graph_renderer.node_renderer.data_source.data["name"] = df_sorted["name"] graph_renderer.node_renderer.data_source.data["links"] = df_sorted["path"] graph_renderer.node_renderer.data_source.add(Spectral8, 'color') graph_renderer.node_renderer.glyph = Circle(size=20, fill_color="color") graph_renderer.node_renderer.selection_glyph = Circle(size=20, fill_color="color") graph_renderer.node_renderer.hover_glyph = Circle(size=20, 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 = NodesAndLinkedEdges() graph_renderer.inspection_policy = EdgesAndLinkedNodes() pos = graph_renderer.layout_provider.graph_layout x, y = zip(*pos.values()) url = "@links" code = """ console.log(source.data) var data = source.data.file; var ind= cb_data.source.selected.indices; console.log(data[ind]) window.open(data[ind]) //window.location.href = data[ind] """ source = ColumnDataSource({ 'x': x, 'y': y, 'field': df_sorted["name"].values, 'file': df_sorted["path"].values }) labels = LabelSet(x='x', y='y', text='field', source=source) taptool = plot.select(type=TapTool) taptool.callback = CustomJS(args=dict(source=source), code=code) plot.renderers.append(graph_renderer) plot.renderers.append(labels) output_file("interactive_graphs.html") show(plot)
def breakdown_flowchart_graph(df, columns=None, x_coords=None, bar_width=1, gap=3, palette=cc.glasbey_dark, hover_line_color="#ff0000", line_cap="butt", line_width_mode="clamp", max_line_width=100, circle_k=3, hover_tooltips={}): """ Given a dataframe with categorical data across columns, produce a breakdown figure which shows how things regroup from one column to the next. By default, uses all columns in `data_df` which can potentially cause problems `line_width_mode = "clamp"` will apply min(w, max_line_width) to the edge widths, any other option will just use the actual edge width (might make the graph unreadable though) """ graph = GraphRenderer() # handle missing parameters if columns is None: columns = df.columns if x_coords is None: x_coords = [gap * i for i in range(len(columns))] # set up the node data node_index = [] node_x, node_y, node_height = [], [], [] col_name, col_value = [], [] for c, x in zip(columns, x_coords): val_counts = df[c].value_counts() new_indices = index_to_unique_list(val_counts.index, c) node_index += new_indices col_name += [c] * len(new_indices) col_value += val_counts.index.to_list() node_x += [x] * len(new_indices) node_y += list(val_counts.values.cumsum() - val_counts.values / 2) node_height += val_counts.values.tolist() n_nodes = len(node_index) graph = GraphRenderer() palette = repeat_to_match_lengths(palette, n_nodes) # add the node renderer graph.node_renderer.data_source.data = {"index": node_index, "col_name": col_name, "col_value": col_value, "height": node_height, "color": palette, "node_x": node_x, "node_y": node_y} graph_layout = dict(zip(node_index, zip(node_x, node_y))) graph.layout_provider = StaticLayoutProvider(graph_layout=graph_layout) color_mapper = dict(zip(node_index, palette)) # used for coloring edges # style the nodes graph.node_renderer.glyph = Rect(width=bar_width, height="height", fill_color="color") graph.node_renderer.hover_glyph = Rect(width=bar_width, height="height", fill_color="color", line_color=hover_line_color, line_width=2) graph.node_renderer.selection_glyph = Rect(width=bar_width, height="height", fill_color="color") # construct the edges and their paths start, end = [], [] xs, ys = [], [] edge_width, edge_color = [], [] for c0, c1 in zip(columns[:-1], columns[1:]): vc = df[[c0, c1]].value_counts() new_starts = index_to_unique_list(vc.index.get_level_values(0), c0) new_ends = index_to_unique_list(vc.index.get_level_values(1), c1) for s, e in zip(new_starts, new_ends): P = np.array(graph_layout[s]) Q = np.array(graph_layout[e]) curve_xs, curve_ys = flowchart_quarter_circle_curve(P, Q, bar_width / 2, circle_k) xs.append(curve_xs) ys.append(curve_ys) start += new_starts end += new_ends if line_width_mode == "clamp": edge_width += [min(v, max_line_width) for v in vc.values] else: edge_width += vc.values.tolist() edge_color += [color_mapper[s] for s in new_starts] # add the edge data to the renderer graph.edge_renderer.data_source.data = {"start": start, "end": end, "line_width": edge_width, "xs": xs, "ys": ys, "color": edge_color} graph.edge_renderer.glyph = MultiLine(line_width="line_width", line_color="color", line_alpha=0.5, line_cap=line_cap) graph.edge_renderer.hover_glyph = MultiLine(line_width="line_width", line_color="color", line_alpha=1.0, line_cap=line_cap) graph.edge_renderer.selection_glyph = MultiLine(line_width="line_width", line_color="color", line_alpha=1.0, line_cap=line_cap) graph.edge_renderer.nonselection_glyph = MultiLine(line_width="line_width", line_color="color", line_alpha=0.2, line_cap=line_cap) graph.selection_policy = NodesAndLinkedEdges() graph.inspection_policy = NodesAndLinkedEdges() tools = [TapTool(), HoverTool(tooltips=[(k, v) for k, v in hover_tooltips.items()])] suggested_x_range = (min(node_x) - bar_width / 2, max(node_x) + bar_width / 2) suggested_y_range = (0, max(y + h / 2 for y, h in zip(node_y, node_height))) return graph, tools, (suggested_x_range, suggested_y_range)
def circle_layout_graph(node_df, edge_df, node_data_cols=[], node_index_name="id", use_node_df_index=True, node_fill_by="index", node_line_by="index", node_line_width=3, scale_nodes_by=None, log_scale_nodes_by=None, node_properties={}, default_line_color="#111111", hover_fill_color="#00ff00", hover_line_color="#00aa00", selected_fill_color="#ff0000", selected_line_color="#ff0000", edge_start_col="node1", edge_end_col="node2", edge_weight_col="total_weight", edge_data_cols=[], use_alpha=True, log_weight=True, node_fill_palette=cc.glasbey_dark, node_line_palette=cc.glasbey_light, layout_origin=np.zeros(2), layout_radius=1.0, circular_arcs=True, circle_k=3, hover_tooltips={"id": "@index"}): """ Return a `bokeh.GraphRenderer` object and list of tools that display the graph specified by the input dataframes. Required arguments are `node_df`, `edge_df` which specify the structure of the graph. The column `node_df[node_index_name]` or `node.index` will be used as the graph renderer index. Other columns can be stored in the graph renderer by specifying a list `node_data_cols` (default empty list `[]`). `node_fill_by` and `node_line_by` specify how colors are chosen for the nodes. Valid options are the default "index", or a list of columns in `node_df`. In the first case, the specified palettes[1] will be repeated to match the length of the node index. Otherwise each unique combination of values in those columns will be mapped to a color in the palette (repeating if necessary). The dataframe will be sorted by the fill color columns, if specified. [1] A `bokeh` palette is a list of strings, each a hex code for a color; see https://docs.bokeh.org/en/latest/docs/reference/palettes.html """ graph = GraphRenderer() n_nodes = node_df.shape[0] # set up fill color, if specified if node_fill_by == "index": node_df["fill_color"] = repeat_to_match_lengths(node_fill_palette, n_nodes) elif node_fill_by is not None: node_df = node_df.sort_values(by=node_fill_by) uniques_df = pd.DataFrame(node_df[node_fill_by].value_counts()) uniques_df["fill_color"] = repeat_to_match_lengths(node_fill_palette, uniques_df.shape[0]) node_df = node_df.merge(uniques_df[["fill_color"]], left_on=node_fill_by, right_index=True) del uniques_df if "fill_color" in node_df.columns and "fill_color" not in node_data_cols: node_data_cols.append("fill_color") # set up line color, if specified if node_line_by == "index": node_df["line_color"] = repeat_to_match_lengths(node_line_palette, n_nodes) elif node_line_by is not None: uniques_df = pd.DataFrame(node_df[node_line_by].value_counts()) uniques_df["line_color"] = repeat_to_match_lengths(node_line_palette, uniques_df.shape[0]) node_df = node_df.merge(uniques_df[["line_color"]], left_on=node_line_by, right_index=True) del uniques_df if "line_color" in node_df.columns and "line_color" not in node_data_cols: node_data_cols.append("line_color") # Use the node DF as the data source for the node renderer if len(node_data_cols) == 0: node_data_cols = node_df.columns graph.node_renderer.data_source.data = node_df[node_data_cols] if use_node_df_index: node_index = node_df.index else: node_index = node_df[node_index_name] graph.node_renderer.data_source.data["index"] = node_index # add node layout info if "theta" not in node_df.columns: theta = np.linspace(0, 2 * np.pi, n_nodes + 1)[:-1] else: theta = node_df['theta'] nodes_x = layout_origin[0] + layout_radius * np.cos(theta) nodes_y = layout_origin[1] + layout_radius * np.sin(theta) graph_layout = dict(zip(node_index, zip(nodes_x, nodes_y))) graph.layout_provider = StaticLayoutProvider(graph_layout=graph_layout) # add edges edge_data = {"start": edge_df[edge_start_col], "end": edge_df[edge_end_col], **{k: edge_df[k] for k in edge_data_cols}} if edge_weight_col is not None: edge_data["weight"] = edge_df[edge_weight_col] else: edge_data["weight"] = np.ones(edge_df.shape[0]) if log_weight: edge_data["weight"] = np.log(edge_data["weight"]) + 1 if use_alpha: edge_data["alpha"] = edge_data["weight"] / np.max(edge_data["weight"]) graph.edge_renderer.data_source.data = edge_data # style the nodes if log_scale_nodes_by is not None: graph.node_renderer.data_source.data["radius"] = sin(2 * pi / n_nodes / 3) * np.log(node_df[log_scale_nodes_by]) / np.log(node_df[log_scale_nodes_by]).max() elif scale_nodes_by is not None: graph.node_renderer.data_source.data["radius"] = sin(2 * pi / n_nodes / 3) * node_df[scale_nodes_by] / node_df[scale_nodes_by].max() else: graph.node_renderer.data_source.data["radius"] = [sin(2 * pi / n_nodes / 3)] * n_nodes graph.node_renderer.glyph = Circle(radius="radius", fill_color="fill_color", line_color="line_color", line_width=node_line_width, **node_properties) graph.node_renderer.hover_glyph = Circle(radius="radius", fill_color=hover_fill_color, line_color=hover_line_color, line_width=node_line_width, **node_properties) graph.node_renderer.selection_glyph = Circle(radius="radius", fill_color=selected_fill_color, line_color=selected_line_color, line_width=node_line_width, **node_properties) graph.edge_renderer.glyph = MultiLine(line_color=default_line_color, line_width="weight", line_alpha="alpha") graph.edge_renderer.hover_glyph = MultiLine(line_color=hover_line_color, line_width="weight", line_alpha=1.0) graph.edge_renderer.selection_glyph = MultiLine(line_color=selected_line_color, line_width="weight", line_alpha=1.0) graph.selection_policy = NodesAndLinkedEdges() graph.inspection_policy = NodesAndLinkedEdges() if circular_arcs: xs, ys = [], [] for start_index, end_index in zip(graph.edge_renderer.data_source.data["start"], graph.edge_renderer.data_source.data["end"]): Q = np.array(graph_layout[start_index]) R = np.array(graph_layout[end_index]) circle_xs, circle_ys = inverted_circle_arc(layout_origin, Q, R, circle_k) xs.append(circle_xs) ys.append(circle_ys) graph.edge_renderer.data_source.data['xs'] = xs graph.edge_renderer.data_source.data['ys'] = ys tools = [TapTool(), HoverTool(tooltips=[(k, v) for k, v in hover_tooltips.items()])] return graph, tools
def _init_glyphs(self, plot, element, ranges, source): # Get data and initialize data source style = self.style[self.cyclic_index] data, mapping, style = self.get_data(element, ranges, style) edge_mapping = {k: v for k, v in mapping[self.edge_glyph].items() if 'color' not in k} self.handles['previous_id'] = element._plot_id properties = {} mappings = {} for key in list(mapping): if not any(glyph in key for glyph in ('scatter_1', self.edge_glyph)): continue source = self._init_datasource(data.pop(key, {})) self.handles[key+'_source'] = source group_style = dict(style) style_group = self._style_groups.get('_'.join(key.split('_')[:-1])) others = [sg for sg in self._style_groups.values() if sg != style_group] glyph_props = self._glyph_properties(plot, element, source, ranges, group_style, style_group) for k, p in glyph_props.items(): if any(k.startswith(o) for o in others): continue properties[k] = p mappings.update(mapping.pop(key, {})) properties = {p: v for p, v in properties.items() if p not in ('legend', 'source')} properties.update(mappings) layout = data.pop('layout', {}) # Define static layout layout = StaticLayoutProvider(graph_layout=layout) node_source = self.handles['scatter_1_source'] edge_source = self.handles[self.edge_glyph+'_source'] renderer = plot.graph(node_source, edge_source, layout, **properties) # Initialize GraphRenderer if self.selection_policy == 'nodes': renderer.selection_policy = NodesAndLinkedEdges() elif self.selection_policy == 'edges': renderer.selection_policy = EdgesAndLinkedNodes() else: renderer.selection_policy = None if self.inspection_policy == 'nodes': renderer.inspection_policy = NodesAndLinkedEdges() elif self.inspection_policy == 'edges': renderer.inspection_policy = EdgesAndLinkedNodes() else: renderer.inspection_policy = None self.handles['layout_source'] = layout self.handles['glyph_renderer'] = renderer self.handles['scatter_1_glyph_renderer'] = renderer.node_renderer self.handles[self.edge_glyph+'_glyph_renderer'] = renderer.edge_renderer self.handles['scatter_1_glyph'] = renderer.node_renderer.glyph if self.filled or self.bezier: glyph_model = Patches if self.filled else Bezier allowed_properties = glyph_model.properties() for glyph_type in ('', 'selection_', 'nonselection_', 'hover_', 'muted_'): glyph = getattr(renderer.edge_renderer, glyph_type+'glyph', None) if glyph is None: continue group_properties = dict(properties) props = self._process_properties(self.edge_glyph, group_properties, mappings) filtered = self._filter_properties(props, glyph_type, allowed_properties) new_glyph = glyph_model(**dict(filtered, **edge_mapping)) setattr(renderer.edge_renderer, glyph_type+'glyph', new_glyph) if data and mapping: CompositeElementPlot._init_glyphs(self, plot, element, ranges, source, data, mapping, style) self.handles[self.edge_glyph+'_glyph'] = renderer.edge_renderer.glyph if 'hover' in self.handles: if self.handles['hover'].renderers == 'auto': self.handles['hover'].renderers = [] self.handles['hover'].renderers.append(renderer)
def plot_data(data_df, connections, year, geoSource_new, df): d_yr = df[df['Years'] == year] data_df_countries = d_yr.merge(data_df, left_on='Origin_Country', right_on='Country') #data_df_countries = node_dt #.drop_duplicates(subset=None, keep='first', inplace=True) connections_df = connections # node_source = ColumnDataSource(data_df_countries[["country_id","Country", "Longitude", "Latitude"]]) node_source = ColumnDataSource(data_df_countries) edge_source = ColumnDataSource(connections_df[["start", "end"]]) node_renderer = GlyphRenderer(data_source=node_source, glyph=node_glyph, selection_glyph=node_selection, nonselection_glyph=node_nonselection) ## Create edge_renderer edge_renderer = GlyphRenderer(data_source=edge_source, glyph=edge_glyph, hover_glyph=edge_hover, selection_glyph=edge_selection, nonselection_glyph=edge_nonselection) ## Create layout_provider graph_layout = dict( zip(data_df_countries.country_id.astype(str), zip(data_df_countries.Longitude, data_df_countries.Latitude))) layout_provider = StaticLayoutProvider(graph_layout=graph_layout) ## Create graph renderer graph = GraphRenderer(edge_renderer=edge_renderer, node_renderer=node_renderer, layout_provider=layout_provider, inspection_policy=NodesAndLinkedEdges(), selection_policy=NodesAndLinkedEdges()) plot = Plot(x_range=Range1d(-150, 150), y_range=Range1d(15, 75), plot_width=800, plot_height=600, background_fill_color=Set3_12[4], background_fill_alpha=0.2) plot.title.text = "Human Trafficing Visualization for " + str(year) plot.add_glyph( geoSource_new, Patches(xs='xs', ys='ys', line_color='grey', line_width=.2, fill_color={ 'field': 'Tier', 'transform': mapper2 }, fill_alpha=0.40)) plot.renderers.append(graph) plot.add_layout(LinearAxis(axis_label="Latitude"), "below") plot.add_layout(LinearAxis(axis_label="Longitude"), "left") # tooltips=""" # <div> # <div> # <span style="font-size: 17px; font-weight: bold;">@desc</span> # <span style="font-size: 15px; color: #966;">[$index]</span> # </div> # <div> # <span style="font-size: 15px;">Country Involved</span> # <span style="font-size: 10px; color: #696;">@Country</span> # </div> # </div> # """, hover = HoverTool( show_arrow=True, # tooltips= # [("Country Involved: ", "@Country")], tooltips=""" <div> <div> <span style="font-size: 13px;">Country Info</span> <span style="font-size: 12px; color: #696;">@Destination_Country, @Type_Of_Trafficking</span> </div> </div> """, renderers=[node_renderer], name='Test') hover_no_tooltips = HoverTool(tooltips=None, renderers=[graph]) box_zoom = BoxZoomTool() plot.add_tools(hover, hover_no_tooltips, box_zoom, TapTool(), BoxSelectTool(), ResetTool(), WheelZoomTool()) plot.toolbar.active_inspect = [hover, hover_no_tooltips] plot.toolbar.active_drag = box_zoom plot.outline_line_color = "navy" plot.outline_line_alpha = 0.3 plot.outline_line_width = 1 select_overlay = plot.select_one(BoxSelectTool).overlay select_overlay.fill_color = "firebrick" select_overlay.line_color = None zoom_overlay = plot.select_one(BoxZoomTool).overlay zoom_overlay.line_color = "olive" zoom_overlay.line_width = 3 zoom_overlay.line_dash = "solid" zoom_overlay.fill_color = None plot.add_tile(STAMEN_TONER_LABELS) return plot
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.inspection_policy = inspection_policy graph_renderer.selection_policy = selection_policy plot.renderers.append(graph_renderer) return plot plot_1 = create_graph(nx.circular_layout, inspection_policy=NodesAndLinkedEdges(), scale=1, center=(0,0)) plot_1.title.text = "Circular Layout (NodesAndLinkedEdges inspection policy)" plot_1.add_tools(HoverTool(tooltips=None)) plot_2 = create_graph(nx.spring_layout, selection_policy=NodesAndLinkedEdges(), scale=2, center=(0,0)) plot_2.title.text = "Spring Layout (NodesAndLinkedEdges selection policy)" plot_2.add_tools(TapTool(), BoxSelectTool()) plot_3 = create_graph(nx.random_layout, inspection_policy=EdgesAndLinkedNodes(), center=(0,0)) plot_3.title.text = "Random Layout (EdgesAndLinkedNodes inspection policy)" plot_3.add_tools(HoverTool(tooltips=None)) plot_4 = create_graph(nx.fruchterman_reingold_layout, selection_policy=EdgesAndLinkedNodes(), scale=2, center=(0,0), dim=2) plot_4.title.text = "FR Layout (EdgesAndLinkedNodes selection policy)" plot_4.add_tools(TapTool())
def plot_data(data_df, connections, year, geoSource_new): data_df_countries = data_df #.drop_duplicates(subset=None, keep='first', inplace=True) connections_df = connections node_source = ColumnDataSource( data_df_countries[["country_id", "Country", "Longitude", "Latitude"]]) edge_source = ColumnDataSource(connections_df[["start", "end"]]) node_renderer = GlyphRenderer(data_source=node_source, glyph=node_glyph, selection_glyph=node_selection, nonselection_glyph=node_nonselection) ## Create edge_renderer edge_renderer = GlyphRenderer(data_source=edge_source, glyph=edge_glyph, hover_glyph=edge_hover, selection_glyph=edge_selection, nonselection_glyph=edge_nonselection) ## Create layout_provider graph_layout = dict( zip(data_df_countries.country_id.astype(str), zip(data_df_countries.Longitude, data_df_countries.Latitude))) layout_provider = StaticLayoutProvider(graph_layout=graph_layout) ## Create graph renderer graph = GraphRenderer(edge_renderer=edge_renderer, node_renderer=node_renderer, layout_provider=layout_provider, inspection_policy=NodesAndLinkedEdges(), selection_policy=NodesAndLinkedEdges()) plot = Plot(x_range=Range1d(-150, 150), y_range=Range1d(15, 75), plot_width=800, plot_height=600, background_fill_color=Set3_12[4], background_fill_alpha=0.2) plot.title.text = "Human Trafficing Visualization for " + str(year) # plot.add_glyph( geoSource_data, Patches(xs='xs', ys='ys', line_color='grey' # , line_width=.5, fill_color=Set3_12[6], fill_alpha=0.25)) plot.add_glyph( geoSource_new, Patches(xs='xs', ys='ys', line_color='grey', line_width=.2, fill_color={ 'field': 'Tier', 'transform': mapper2 }, fill_alpha=0.25)) plot.renderers.append(graph) plot.add_layout(LinearAxis(axis_label="Latitude"), "below") plot.add_layout(LinearAxis(axis_label="Longitude"), "left") hover = HoverTool( show_arrow=True, # tooltips= # [("Country Involved: ", "@Country")], tooltips=""" <div> <div> <span style="font-size: 15px;">Country Information </span> <span style="font-size: 12px; color: #696;">@Destination_Country </span> </div> </div> """, renderers=[graph]) hover_no_tooltips = HoverTool(tooltips=None, renderers=[graph]) box_zoom = BoxZoomTool() plot.add_tools(hover, hover_no_tooltips, box_zoom, TapTool(), BoxSelectTool(), ResetTool(), WheelZoomTool()) plot.toolbar.active_inspect = [hover, hover_no_tooltips] plot.toolbar.active_drag = box_zoom plot.outline_line_color = "navy" plot.outline_line_alpha = 0.3 plot.outline_line_width = 3 plot.add_tile(STAMEN_TONER_LABELS) return plot
# plot.renderers.append(network_graph) network_graph.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0]) network_graph.node_renderer.selection_glyph = Circle(size=15, fill_color=Spectral4[2]) network_graph.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1]) height_slider = Slider(start=1, end=10, value=1, step=1, title="Height") network_graph.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5) network_graph.edge_renderer.selection_glyph = MultiLine( line_color=Spectral4[2], line_width=5) network_graph.edge_renderer.hover_glyph = MultiLine(line_color=Spectral4[1], line_width=5) network_graph.selection_policy = NodesAndLinkedEdges() network_graph.inspection_policy = EdgesAndLinkedNodes() plot.renderers.append(network_graph) text_input = TextInput(value="Enter Concept ID", title="Concept ID:") layout = column(row(height_slider, plot), row(text_input), sizing_mode="stretch_both") curdoc().add_root(layout) def find_shortest_path(G, start, end, path=[]): if start not in G.nodes(): return None elif end not in G.nodes():
def render(G, N, concept_data, Title, titles, html_content, node_conections, node_conectivity): plot_size = 800 #px plot = figure(toolbar_location=None, x_range=(-1, 1), y_range=(-1, 1), height=plot_size, width=plot_size, sizing_mode="scale_both") plot.xgrid.visible = False plot.ygrid.visible = False plot.axis.visible = False plot.outline_line_alpha = 0 plot.toolbar.active_drag = None # Create the graph object from the NetworkX nodes graph_rel_size = 0.8 graph = from_networkx(G, nx.circular_layout, scale=graph_rel_size, center=(0, 0)) # Size of the node depends on amount of conections: node_sizes = [ (plot_size * graph_rel_size * np.pi / N) * (1.5 + np.log(node)) / 4 for node in node_conectivity ] # Add data to the nodes graph.node_renderer.data_source.add(titles, 'title') graph.node_renderer.data_source.add(node_conectivity, 'node_conectivity') graph.node_renderer.data_source.add(node_sizes, 'node_size') graph.node_renderer.data_source.add([ ", ".join([concept_data[n]["name"] for n in node]) for node in node_conections ], 'node_conections') # Set up tooltips and enable selection. graph.selection_policy = NodesAndLinkedEdges() node_hover_name = HoverTool(tooltips=[( "Concepto", "@title"), ("Conectividad", "@node_conectivity"), ("Conecciones", "@node_conections")]) plot.add_tools(node_hover_name, TapTool()) # Configure the nodes's apparence graph.node_renderer.glyph = Circle(size="node_size", fill_color=color_palette[1]) graph.node_renderer.selection_glyph = Circle(size="node_size", fill_color=color_palette[4]) graph.node_renderer.hover_glyph = Circle(size="node_size", fill_color=color_palette[3]) # Configure the edge's apparence graph.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=2) graph.edge_renderer.selection_glyph = MultiLine( line_color=color_palette[4], line_width=3) # Node labels: # Organize the lable data and keep it separated from the graph data labels_pos = np.transpose(list( graph.layout_provider.graph_layout.values())) label_angles = np.arctan( labels_pos[1] / labels_pos[0]) # Used to calculate position offset labeldata = ColumnDataSource(data=dict( x_pos=labels_pos[0], y_pos=labels_pos[1], # This makes that labels are only showed for the nodes with most conections: text=[titles[i] if node_conectivity[i] > 4 else "" for i in range(N)], x_off=25 * np.cos(label_angles), y_off=50 * np.sin(label_angles))) labels = LabelSet(x="x_pos", y="y_pos", text='text', level='glyph', x_offset="x_off", y_offset="y_off", source=labeldata, render_mode='canvas') # Add all graph elements to plot plot.add_layout(labels) plot.renderers.append(graph) ## Create side panel with content default_text = md.markdown(f"""## Mapa de {Title} Este es un mapa que conecta todos los conceptos de {Title} en un gráfico interactivo Cada círculo representa un concepto, y las lineas representan las conexiones entre conceptos. Al pasar el mouse por sobre los circulos podrás ver información sobre el concepto y sus conecciones. Al hacer click en los circulos, este panel mostrará información detallada sobre el concepto. """) # Default side panel content div_content = Div(text=default_text, css_classes=["scroll", "sidebar"], height=plot_size, width=plot_size, sizing_mode="scale_width") # This script handels the text changes and Katex redrawing displayDetails = CustomJS(args=dict(src=graph.node_renderer.data_source, target=div_content, label_texts=html_content), code=""" const index = src.selected.indices[0] target.text = label_texts[index]; renderMathInElement(document.body, { delimiters:[ {left: "$$", right: "$$", display: true}, {left: "$", right: "$", display: false} ] }); """) taptool = plot.select(type=TapTool) taptool.callback = displayDetails # Export everything as an html file # get bokeh parts sep_line = Div( style=dict(zip(["border", "height"], ["1px solid black", "100%"]))) script_bokeh, div_bokeh = components(row(plot, sep_line, div_content)) resources_bokeh = CDN.render() # render everything together html = template.render(title=Title, resources=resources_bokeh, script=script_bokeh, div=div_bokeh) return html
def _plot_network(from_year): G, _, nodes, degrees, communities = _load_graph(from_year) #Choose colors for node and edge highlighting node_highlight_color = 'white' edge_highlight_color = 'black' #Choose attributes from G network to size and color by — setting manual size (e.g. 10) or color (e.g. 'skyblue') also allowed size_by_this_attribute = 'adjusted_node_size' color_by_this_attribute = 'modularity_color' # Modularity class and colors modularity_class = {} modularity_color = {} #Loop through each community in the network for community_number, community in enumerate(communities): #For each member of the community, add their community number and a distinct color for name in community: modularity_class[name] = community_number modularity_color[name] = Spectral11[min( len(Spectral11) - 1, community_number)] #Graph metrics to be shown below plot total_nodes = networkx.number_of_nodes(G) total_edges = networkx.number_of_edges(G) avg_degree = round(np.mean(list(degrees.values())), 2) sorted_degrees = dict( sorted(degrees.items(), key=lambda item: item[1], reverse=True)) top_degree_keys = list(sorted_degrees.keys())[:5] top_degrees = { nodes[k]: (sorted_degrees[k], modularity_class[k], modularity_color[k]) for k in top_degree_keys } modularity_classes = len(communities) # Add modularity class and color as attributes from the network above networkx.set_node_attributes(G, modularity_class, 'modularity_class') networkx.set_node_attributes(G, modularity_color, 'modularity_color') #Establish which categories will appear when hovering over each node HOVER_TOOLTIPS = [("Company", "@index"), ("Name", "@name"), ("Degree", "@degree"), ("Modularity Class", "@modularity_class")] #to_year = from_year + 1 plot_title = f'Collaborative structure between {from_year} and {from_year+1}' #Create a plot — set dimensions, toolbar, and title 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=plot_title) plot.add_tools(TapTool(), BoxSelectTool()) #Create a network graph object with spring layout # https://networkx.github.io/documentation/networkx-1.9/reference/generated/networkx.drawing.layout.spring_layout.html network_graph = from_networkx(G, networkx.spring_layout, scale=10, center=(0, 0)) #Set node size and color network_graph.node_renderer.glyph = Circle( size=size_by_this_attribute, fill_color=color_by_this_attribute) #Set node highlight colors 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) #Set edge opacity and width network_graph.edge_renderer.glyph = MultiLine(line_alpha=0, line_width=1) #Set edge highlight colors 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) #Highlight nodes and edges network_graph.selection_policy = NodesAndLinkedEdges() network_graph.inspection_policy = NodesAndLinkedEdges() #Add network graph to the plot plot.renderers.append(network_graph) return plot, G, nodes, avg_degree, top_degrees, modularity_classes, total_nodes, total_edges
network_graph.node_renderer.selection_glyph = Circle( size=size_by_this_attribute, fill_color=node_highlight_color, line_width=2) #Set edge opacity and width network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width=1) #Set edge highlight colors network_graph.edge_renderer.selection_glyph = MultiLine( line_color=edge_highlight_color, line_width="priced_degree") network_graph.edge_renderer.hover_glyph = MultiLine( line_color=edge_highlight_color, line_width="priced_degree") #Highlight nodes and edges network_graph.selection_policy = NodesAndLinkedEdges() network_graph.inspection_policy = NodesAndLinkedEdges( ) #EdgesAndLinkedNodes() plot.renderers.append(network_graph) st.bokeh_chart(plot) elif add_selectbox == 'References': st.subheader('References') st.markdown( "[1] Public Procurement Data in the Philippines and Where to Find It: \ https://schoolofdata.org/2019/03/06/public-procurement-data-in-the-philippines-and-where-to-find-it/", unsafe_allow_html=True) st.markdown("[2] Networks on Maps (with Python): \ http://www.sociology-hacks.org/?p=67",
def show(self): node_indices = [ self.graph.vertices[vertex].value for vertex in self.graph.vertices ] # edge__start = [ # self.graph.vertices[vertex].value for vertex in self.graph.vertices] nodes__and__edges = [ tuple((self.graph.vertices[vertex].value, self.graph.vertices[vertex].edges)) for vertex in self.graph.vertices ] # print('\n vertes: ', edge__start) print('\n nodes__and__edges: ', nodes__and__edges) plot = figure( title="Graph Layout", x_range=(-1, 10), y_range=(-1, 10)) # tools="pan,lasso_select,box_select,poly_select", graph = GraphRenderer() graph.node_renderer.data_source.add(node_indices, 'index') graph.node_renderer.data_source.add([ self.graph.vertices[vertex].color for vertex in self.graph.vertices ], 'color') r = 30 graph.node_renderer.glyph = Circle(size=r, fill_color='color') graph.node_renderer.selection_glyph = Circle( size=r, fill_color=Spectral4[2]) # make the shape of the node selectable graph.node_renderer.hover_glyph = Circle( size=r, fill_color=Spectral4[1]) # hover effect on node start_i = [] end_i = [] for vertex in self.graph.vertices: for end_point in self.graph.vertices[vertex].edges: start_i.append(vertex) end_i.append(end_point) graph.edge_renderer.data_source.data = dict(start=start_i, end=end_i) graph.edge_renderer.glyph = MultiLine( line_color="#CCCCCC", line_alpha=0.8, line_width=5) # make the shape of the edge graph.edge_renderer.selection_glyph = MultiLine( line_color=Spectral4[2], line_width=5) # make the shape of the edge selectable graph.edge_renderer.hover_glyph = MultiLine( line_color=Spectral4[1], line_width=5) # hover effect on node x = [self.graph.vertices[vertex].x for vertex in self.graph.vertices] y = [self.graph.vertices[vertex].y for vertex in self.graph.vertices] graph_layout = dict(zip(node_indices, zip(x, y))) graph.layout_provider = StaticLayoutProvider(graph_layout=graph_layout) # will cause the start and end nodes of an edge to also be inspected upon hovering an edge with the HoverTool graph.inspection_policy = EdgesAndLinkedNodes() # will cause a selected node to also select the associated edges graph.selection_policy = NodesAndLinkedEdges() plot.renderers.append(graph) labelSource = ColumnDataSource(data=dict(x=x, y=y, names=node_indices)) labels = LabelSet(x='x', y='y', text='names', level='glyph', text_align='center', text_baseline='middle', source=labelSource, render_mode='canvas') # calculate the ave distance, from starting_node (x, y) to ending node (x, y) w_x = [((self.graph.vertices[end_i[i]].x - self.graph.vertices[start_i[i]].x) / 2) + self.graph.vertices[start_i[i]].x for (i, x) in enumerate(start_i)] w_y = [((self.graph.vertices[end_i[i]].y - self.graph.vertices[start_i[i]].y) / 2) + self.graph.vertices[start_i[i]].y for (i, x) in enumerate(start_i)] # calculate wighted edge w_name = [abs(end_i[i] - start_i[i]) for (i, x) in enumerate(start_i)] weight_labelSource = ColumnDataSource( data=dict(x=w_x, y=w_y, names=w_name)) weight_labels = LabelSet(x='x', y='y', text='names', text_color="red", level='glyph', text_align='center', text_baseline='middle', source=weight_labelSource, render_mode='canvas') plot.add_layout(labels) plot.add_layout(weight_labels) plot.add_tools(HoverTool(tooltips=None), TapTool(), BoxSelectTool()) # add the hover output_file('graph.html') show(plot)
def drawInteractiveNW(df, nw=None, edgesdf=None, color_attr="Cluster", label_attr="name", title="Interactive Network Visualization", plotfile=None, inline=False): def buildNetworkX(linksdf, id1='Source', id2='Target', directed=False): linkdata = [(getattr(link, id1), getattr(link, id2)) for link in linksdf.itertuples()] g = nx.DiGraph() if directed else nx.Graph() g.add_edges_from(linkdata) return g if inline: output_notebook() if plotfile: output_file(plotfile+".html") if nw is None: if edgesdf is None: print("Must specify either network or edges DataFrame") return nw = buildNetworkX(edgesdf) node_colors, edge_colors, attr_colors = dn.getCategoricalColors(nw, df, color_attr, None, True, None) xmin = df['x'].min() xmax = df['x'].max() ymin = df['y'].min() ymax = df['y'].max() rng = max((xmax-xmin), (ymax-ymin)) nNodes = len(df) size = 4*rng/math.sqrt(nNodes) node_indices = list(range(nNodes)) tooltips=[ (label_attr, "@"+label_attr), (color_attr, "@"+color_attr) ] plot = figure(title=title, plot_width=800, plot_height=800, x_range=(xmin-size, xmax+size), y_range=(ymin-size, ymax+size), tools="pan,wheel_zoom,box_zoom,reset", toolbar_location="right", output_backend="webgl") plot.add_tools(HoverTool(tooltips=tooltips), TapTool(), BoxSelectTool()) graph = GraphRenderer() # set node renderer and data graph.node_renderer.glyph = Circle(size=size, fill_color="fill_color", line_color='gray') graph.node_renderer.selection_glyph = Circle(size=size, fill_color="fill_color", line_color='black', line_width=2) graph.node_renderer.hover_glyph = Circle(size=size, fill_color="fill_color", line_color='black') graph.node_renderer.data_source.data = {'index': node_indices, label_attr: df[label_attr].tolist(), 'fill_color': node_colors, color_attr: df[color_attr].fillna('').tolist(), 'x': df['x'].tolist(), 'y': df['y'].tolist(), } # set edge renderer and data graph.edge_renderer.glyph = MultiLine(line_color="line_color", line_width=1) graph.edge_renderer.data_source.data = {'start': [e[0] for e in nw.edges], 'end': [e[1] for e in nw.edges], 'line_color': edge_colors } # set layout graph_layout = dict(zip(node_indices, zip(df['x'], df['y']))) graph.layout_provider = StaticLayoutProvider(graph_layout=graph_layout) # set legend by adding dummy glyph with legend plot.circle( x='x', y='y', radius=0.0, color='fill_color', legend=field(color_attr), source=graph.node_renderer.data_source.data) plot.legend.location = "top_left" plot.legend.padding = 0 plot.legend.margin = 0 graph.selection_policy = NodesAndLinkedEdges() # hide axes and grids plot.xaxis.visible = False plot.yaxis.visible = False plot.xgrid.visible = False plot.ygrid.visible = False plot.renderers.append(graph) show(plot)
fill_color='node_color') graph.node_renderer.selection_glyph = Circle(size='node_size', fill_color='node_color') # add the edge renderers to the graph graph.edge_renderer.glyph = MultiLine(line_alpha=.5, line_width='weight') graph.edge_renderer.data_source.data['edge_color'] = [ colmap[clique] for clique in graph.edge_renderer.data_source.data['clique'] ] graph.edge_renderer.hover_glyph = MultiLine(line_color='edge_color', line_width='weight') graph.edge_renderer.selection_glyph = MultiLine(line_color='edge_color', line_width='weight') # add inspect/selection policy (hovering and clicking) to the graph graph.inspection_policy = NodesAndLinkedEdges() graph.selection_policy = NodesAndLinkedEdges() # add graph to the plot plot2.renderers.append(graph) # add labels x, y = zip(*pos2.values()) source2 = ColumnDataSource({'x': x, 'y': y, 'label': labels}) labelset2 = LabelSet(x='x', y='y', text='label', source=source2, background_fill_color='white', text_font_size='12px', background_fill_alpha=.7)
def make_netgraph_plot(self, df, df_nodes): """ Create FEDn network visualization. :param df: pandas dataframe with defined edges :type df: pandas.Dataframe :param df_nodes:pandas dataframe with defined nodes :type df_nodes: pandas.Dataframe :return: Bokeh plot with the graph :rtype: bokeh.plotting.figure.Figure """ if df.empty: #no combiners and thus no clients, plot only reducer plot = self.make_single_node_plot() return plot G = networkx.from_pandas_edgelist(df, 'source', 'target', create_using=networkx.Graph()) degrees = dict(networkx.degree(G)) networkx.set_node_attributes(G, name='degree', values=degrees) number_to_adjust_by = 20 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) # community from networkx.algorithms import community communities = community.greedy_modularity_communities(G) # Create empty dictionaries modularity_class = {} modularity_color = {} # Loop through each community in the network for community_number, community in enumerate(communities): # For each member of the community, add their community number and a distinct color for name in community: modularity_class[name] = community_number modularity_color[name] = Spectral8[community_number] # Add modularity class and color as attributes from the network above networkx.set_node_attributes(G, modularity_class, 'modularity_class') networkx.set_node_attributes(G, modularity_color, 'modularity_color') node_role = {k:v for k,v in zip(df_nodes.id, df_nodes.role)} networkx.set_node_attributes(G, node_role, 'role') node_status = {k:v for k,v in zip(df_nodes.id, df_nodes.status)} networkx.set_node_attributes(G, node_status, 'status') node_name = {k:v for k,v in zip(df_nodes.id, df_nodes.name)} networkx.set_node_attributes(G, node_name, 'name') # Choose colors for node and edge highlighting node_highlight_color = 'white' edge_highlight_color = 'black' # Choose attributes from G network to size and color by — setting manual # size (e.g. 10) or color (e.g. 'skyblue') also allowed size_by_this_attribute = 'adjusted_node_size' color_by_this_attribute = 'modularity_color' # Establish which categories will appear when hovering over each node HOVER_TOOLTIPS = [ ("Name", "@name"), ("Role", "@role"), ("Status", "@status"), ("Id", "@index"), ] # Create a plot — set dimensions, toolbar, and title 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)) # Create a network graph object # https://networkx.github.io/documentation/networkx-1.9/reference/generated/networkx.drawing.layout.spring_layout.html # if one like lock reducer add args: pos={'reducer':(0,1)}, fixed=['reducer'] network_graph = from_networkx(G, networkx.spring_layout, scale=1, center=(0, 0), seed=45) # Set node sizes and colors according to node degree (color as category from attribute) network_graph.node_renderer.glyph = Circle(size=size_by_this_attribute, fill_color=color_by_this_attribute) # Set node highlight colors 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) # Set edge opacity and width network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width=1) # Set edge highlight colors 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) # Highlight nodes and edges network_graph.selection_policy = NodesAndLinkedEdges() network_graph.inspection_policy = NodesAndLinkedEdges() plot.renderers.append(network_graph) #Node labels, red if status is offline, green is active x, y = zip(*network_graph.layout_provider.graph_layout.values()) node_names = list(G.nodes(data='name')) node_status = list(G.nodes(data='status')) idx_offline = [] idx_online = [] node_labels = [] for e, n in enumerate(node_names): if node_status[e][1] == 'active': idx_online.append(e) else: idx_offline.append(e) node_labels.append(n[1]) source_on = ColumnDataSource({'x': numpy.asarray(x)[idx_online], 'y': numpy.asarray(y)[idx_online], 'name': numpy.asarray(node_labels)[idx_online]}) labels = LabelSet(x='x', y='y', text='name', source=source_on, background_fill_color='#4bbf73', text_font_size='15px', background_fill_alpha=.7, x_offset=-20, y_offset=10) plot.renderers.append(labels) source_off = ColumnDataSource({'x': numpy.asarray(x)[idx_offline], 'y': numpy.asarray(y)[idx_offline], 'name': numpy.asarray(node_labels)[idx_offline]}) labels = LabelSet(x='x', y='y', text='name', source=source_off, background_fill_color='#d9534f', text_font_size='15px', background_fill_alpha=.7, x_offset=-20, y_offset=10) plot.renderers.append(labels) plot.axis.visible = False plot.grid.visible = False plot.outline_line_color = None return plot
new_pal, pd.Series(init_sectors).unique(), nan_color='black'), fill_alpha=0.0, line_alpha=0.0) graph_renderer.node_renderer.selection_glyph = Circle( size='size', fill_color=factor_cmap('sector', new_pal, pd.Series(init_sectors).unique(), nan_color='black'), fill_alpha=0.0, line_alpha=0.0) graph_renderer.selection_policy = NodesAndLinkedEdges() # graph_renderer.inspection_policy = EdgesAndLinkedNodes() plot.renderers.append(graph_renderer) plot_scatter = plot.scatter(source=ds, x='x', y='y', radius='size', fill_alpha=0.5, fill_color=init_colors, line_alpha=0.8, line_color=init_colors, selection_fill_alpha=0.9, selection_line_alpha=0.9, selection_line_color='black',
def create_plot(G, layout): ''' Returns a bokeh plot using the given netowrkx graph and layout. Depending on the layout the dimensions of the graphs grid change Parameters: G (networkx graph) : Netoworkx graph that will be plotted layout (networkx layout): The layout of the network graph Return: plot (bokeh Plot): the plot generated using bokehs functions ''' # the grouped layout is a special layout that uses the positions generated # by makegraph.py if layout == "grouped": G, sidel = get_vertices() hsidel = sidel / 2 plot = Plot(plot_width=1200, plot_height=600, x_range=Range1d(-(hsidel + .1), hsidel + .1), y_range=Range1d(-(hsidel + .1), hsidel + .1), align='center') else: plot = Plot(plot_width=1200, plot_height=600, x_range=Range1d(-2.1, 2.1), y_range=Range1d(-2.1, 2.1), align='center') plot.title.text = "TV Shows Connected By Recommendation" plot.background_fill_color = "black" plot.background_fill_alpha = 0.1 if layout == "grouped": pos_dict = {} for node in G.nodes: pos_dict[node] = G.nodes[node]["pos"] graph_renderer = from_networkx(G, pos_dict, scale=hsidel, center=(0, 0)) # The discover layout uses the positions assigned in discover.py elif layout == "discover": pos_dict = {} for node in G.nodes: pos_dict[node] = G.nodes[node]["pos"] graph_renderer = from_networkx(G, pos_dict, scale=2, center=(0, 0)) else: graph_renderer = from_networkx(G, layout, scale=2, center=(0, 0)) # The colors for each node is assigned using a scale and if the number of nodes goes over # 256 the same color is used for the remaining nodes if len(G.nodes) > 256: Inferno = [Spectral4[1]] * len(G.nodes) - 256 Inferno.extend(viridis(len(G.nodes))) else: Inferno = list(viridis(len(G.nodes))) source = graph_renderer.node_renderer.data_source nodes = graph_renderer.node_renderer edges = graph_renderer.edge_renderer source.data['name'] = [x for x in source.data['index']] source.data['colors'] = Inferno nodes.glyph = Circle(size=15, fill_color='colors', fill_alpha=0.9, line_color='colors') nodes.selection_glyph = Circle(size=15, fill_color=Plasma11[10], fill_alpha=0.8) nodes.hover_glyph = Circle(size=15, fill_color=Plasma11[9]) nodes.glyph.properties_with_values() edges.glyph = MultiLine(line_color="black", line_alpha=0.1, line_width=2) edges.selection_glyph = MultiLine(line_color=Plasma11[10], line_width=2) edges.hover_glyph = MultiLine(line_color=Plasma11[9], line_width=2) # This functions allow nodes to be highlighted when hovered over or clicked on graph_renderer.selection_policy = NodesAndLinkedEdges() graph_renderer.inspection_policy = NodesAndLinkedEdges() #graph_renderer.selection_policy = EdgesAndLinkedNodes() # The tooltips to show the data for the plots if layout == "grouped": node_hover_tool = HoverTool(tooltips=[("", "@name"), ("", "@genre")]) else: node_hover_tool = HoverTool(tooltips=[("", "@name")]) plot.add_tools(node_hover_tool, WheelZoomTool(), TapTool(), BoxSelectTool()) plot.renderers.append(graph_renderer) return 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
def plot_create_graph(self, doc): if self.subgraph: plot = figure(x_range=(-1.1, 1.1), y_range=(-1.1, 1.1)) plot.axis.visible = False node_labels = nx.get_node_attributes(self.subgraph, 'id') node_labels = tuple([label for label in node_labels.values()]) node_urls = nx.get_node_attributes(self.subgraph, 'url') node_urls = tuple([value for value in node_urls.values()]) node_lim_inf = nx.get_node_attributes(self.subgraph, 'lim_inf') node_lim_inf = tuple([value for value in node_lim_inf.values()]) node_lim_sup = nx.get_node_attributes(self.subgraph, 'lim_sup') node_lim_sup = tuple([value for value in node_lim_sup.values()]) ncolor = ['#2b83ba' for name in node_labels] nsize = [15 for name in node_labels] if self.name != 'launcher': node_labels_low = [name.lower() for name in node_labels] ncolor[node_labels_low.index(self.name)] = '#ff0202' nsize[node_labels_low.index(self.name)] = 25 graph = from_networkx(self.subgraph, nx.spring_layout, scale=1, center=(0, 0)) graph.node_renderer.glyph = Circle(size='nsize', fill_color='ncolor') graph.node_renderer.selection_glyph = Circle(size='nsize', fill_color='#054872') graph.node_renderer.hover_glyph = Circle(size='nsize', fill_color='#abdda4') graph.name = "graph" graph.node_renderer.data_source.data.update( dict(id=node_labels, url=node_urls, inf=node_lim_inf, sup=node_lim_sup, ncolor=ncolor, nsize=nsize)) graph.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5) graph.edge_renderer.selection_glyph = MultiLine( line_color='#054872', line_width=5) graph.edge_renderer.hover_glyph = MultiLine(line_color='#abdda4', line_width=5) graph.selection_policy = NodesAndLinkedEdges() # graph.inspection_policy = EdgesAndLinkedNodes() plot.renderers.append(graph) x, y = zip(*graph.layout_provider.graph_layout.values()) source_graph = ColumnDataSource( data=dict(x=x, y=y, id=node_labels, url=node_urls)) labels = LabelSet(x='x', y='y', text='id', source=source_graph) plot.renderers.append(labels) # add tools to the plot plot.add_tools( HoverTool(tooltips=[("url", "@url"), ("range", "[@inf, @sup]")], names=["graph"]), TapTool()) url = "http://@url" taptool = plot.select(type=TapTool) taptool.callback = OpenURL(url=url) doc.add_root(plot)
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.inspection_policy = inspection_policy graph_renderer.selection_policy = selection_policy plot.renderers.append(graph_renderer) return plot plot_1 = create_graph(nx.circular_layout, inspection_policy=NodesAndLinkedEdges(), scale=1, center=(0, 0)) plot_1.title.text = "Circular Layout (NodesAndLinkedEdges inspection policy)" plot_1.add_tools(HoverTool(tooltips=None)) plot_2 = create_graph(nx.spring_layout, selection_policy=NodesAndLinkedEdges(), scale=2, center=(0, 0)) plot_2.title.text = "Spring Layout (NodesAndLinkedEdges selection policy)" plot_2.add_tools(TapTool(), BoxSelectTool()) plot_3 = create_graph(nx.random_layout, inspection_policy=EdgesAndLinkedNodes(), center=(0, 0))
# Network Graph - h, w, csvSrc, graphTileTextColor, currFrame, mySkeleton, myStudy xmin, ymin, xmax, ymax = zoomCenterSmCoords(h,w) graphTileTextColor="#7e685a" #brown silver? skPlot = figure(x_range=(0, w), y_range=(h, 0), name="netGraph", outline_line_color=None, tools='pan,wheel_zoom,box_zoom,reset,tap,box_select,hover', plot_width=570,plot_height=300, tooltips=[("coord", "$x{0.0} $y{0.0}"), ("art", "$index")]) skPlot.xaxis.visible = False skPlot.title.text_color = graphTileTextColor skPlot.title.text_font_size="15px" skPlot.title.align = "center" netGraph.selection_policy = NodesAndLinkedEdges() netGraph.inspection_policy = EdgesAndLinkedNodes() netGraph.node_renderer.data_source.add(myBkSkeleton.index, 'index') netGraph.node_renderer.data_source.add(myBkSkeleton['color'], 'color') netGraph.node_renderer.glyph = Circle(size=10, line_color='color', fill_color='color', fill_alpha=0.4) netGraph.node_renderer.selection_glyph = Circle(size=12, fill_color='color', fill_alpha=0.7) netGraph.node_renderer.hover_glyph = Circle(size=12, fill_color='color') netGraph.edge_renderer.data_source.data = connxs netGraph.edge_renderer.glyph = MultiLine(line_color="#c8c8c8", line_width=2) netGraph.edge_renderer.selection_glyph = MultiLine(line_color='#777777', line_width=2) netGraph.edge_renderer.hover_glyph = MultiLine(line_color='#888888', line_width=2) graph_layout = dict(zip(myBkSkeleton.index, myBkSkeleton["coord2d"])) netGraph.layout_provider = StaticLayoutProvider(graph_layout=graph_layout) skPlot.renderers.append(netGraph)