def test_graphrenderer_check_malformed_graph_source_no_edge_start_or_end(): edge_source = ColumnDataSource() edge_renderer = GlyphRenderer(data_source=edge_source, glyph=MultiLine()) renderer = GraphRenderer(edge_renderer=edge_renderer) check = renderer._check_malformed_graph_source() assert check != []
def test_graphrenderer_check_malformed_graph_source_no_node_index(): node_source = ColumnDataSource() node_renderer = GlyphRenderer(data_source=node_source, glyph=Circle()) renderer = GraphRenderer(node_renderer=node_renderer) check = renderer._check_malformed_graph_source() assert check != []
def test_graphrenderer_init_props(): renderer = GraphRenderer() assert renderer.x_range_name == "default" assert renderer.y_range_name == "default" assert renderer.node_renderer.data_source.data == dict(index=[]) assert renderer.edge_renderer.data_source.data == dict(start=[], end=[]) assert renderer.layout_provider is None
def test_graphrenderer_check_malformed_graph_source_no_errors(): renderer = GraphRenderer() check = renderer._check_malformed_graph_source() assert check == []
def get_graph_elems(graph): ''' Convert the Networkx graph object into a graph that can be rendered by Bokeh. Creates node and edge renderers for the graph, labels for the nodes and interactivity for clicking on nodes (displaying just the node and all its linked edges). ''' # get all nodes node_ids = list(graph.nodes()) # get all edges including for each edge: # -start and end nodes (the players in the player pair)-- kind of arbitrary since the graph is # undirected # -weight (the estimated net points for each player pair) # -color (red if negative, black if positive) start_ids = [a for a, b in graph.edges()] end_ids = [b for a, b in graph.edges()] weights = [.025 * graph[a][b]['weight'] for a, b in graph.edges()] colors = [graph[a][b]['color'] for a, b in graph.edges()] # define data sources for nodes and edges graph_layout, label_layout = get_graph_layout(graph) x_graph, y_graph = [v[0] for v in graph_layout.values() ], [v[1] for v in graph_layout.values()] x_label, y_label = [v[0] for v in label_layout.values() ], [v[1] for v in label_layout.values()] node_ds = ColumnDataSource(data=dict(index=list(graph.nodes()), x=x_graph, y=y_graph, color=[Spectral4[0]] * len(list(graph.nodes()))), name="Node Renderer") edge_ds = ColumnDataSource(data=dict(start=start_ids, end=end_ids, weight=weights, color=colors), name="Edge Renderer") # create bokeh graph object # note that both nodes and edges both have specified "glyphs" for regular and selection/nonselection (as well as # the selection policy (NodesAndLinkedEdges()) # when a node is selected, its outgoing edges are highlighted graph_plot = GraphRenderer( node_renderer=GlyphRenderer(glyph=Circle(size=15, fill_color="color"), selection_glyph=Circle(size=15, fill_color="color"), data_source=node_ds), edge_renderer=GlyphRenderer( glyph=MultiLine(line_alpha=0.3, line_width='weight', line_color='color'), selection_glyph=MultiLine(line_alpha=1, line_width='weight', line_color='color'), nonselection_glyph=MultiLine(line_alpha=0, line_width='weight', line_color='color'), data_source=edge_ds), layout_provider=StaticLayoutProvider(graph_layout=graph_layout), selection_policy=NodesAndLinkedEdges()) # create labels for each node as well as their positions when plotted label_ds = ColumnDataSource( data=dict(index=list(graph.nodes()), x=x_label, y=y_label)) labels = LabelSet(x='x', y='y', text='index', source=label_ds, background_fill_color='lightgrey') return graph_plot, labels