Example #1
0
def test_from_networkx_with_bad_attributes() -> None:
    G = nx.Graph()
    G.add_nodes_from([(0, {"index": "a", "attr_1": 10}),
                      (1, {"index": "b", "attr_1": 20})])
    G.add_edges_from([[0, 1]])

    with pytest.warns(UserWarning):
        renderer = bpg.from_networkx(G, nx.circular_layout)
        assert renderer.node_renderer.data_source.data["index"] == [0, 1]
        assert renderer.node_renderer.data_source.data["attr_1"] == [10, 20]

    G = nx.Graph()
    G.add_nodes_from([0, 1])
    G.add_edges_from([(0, 1, {"start": "A", "attr_1": 10})])

    with pytest.warns(UserWarning):
        renderer = bpg.from_networkx(G, nx.circular_layout)
        assert renderer.edge_renderer.data_source.data["start"] == [0]
        assert renderer.edge_renderer.data_source.data["end"] == [1]
        assert renderer.edge_renderer.data_source.data["attr_1"] == [10]

    G = nx.Graph()
    G.add_nodes_from([0, 1])
    G.add_edges_from([(0, 1, {"end": "A", "attr_1": 10})])

    with pytest.warns(UserWarning):
        renderer = bpg.from_networkx(G, nx.circular_layout)
        assert renderer.edge_renderer.data_source.data["start"] == [0]
        assert renderer.edge_renderer.data_source.data["end"] == [1]
        assert renderer.edge_renderer.data_source.data["attr_1"] == [10]
Example #2
0
def test_from_networkx_errors_with_mixed_attributes() -> None:
    G = nx.Graph()
    G.add_nodes_from([(0, {"attr_1": [1, 2], "attr_2": 10}),
                      (1, {}),
                      (2, {"attr_1": 3, "attr_2": 30})])

    with pytest.raises(ValueError):
        bpg.from_networkx(G, nx.circular_layout)

    G = nx.Graph()
    G.add_edges_from([(0, 1, {"attr_1": [1, 11]}),
                      (0, 2, {"attr_1": 2, "attr_2": 10})])

    with pytest.raises(ValueError):
        bpg.from_networkx(G, nx.circular_layout)
Example #3
0
def test_from_networkx_with_sequence_attributes(typ):
    G = nx.Graph()
    G.add_nodes_from([(0, {
        "attr_1": typ([1, 2]),
        "attr_2": 10
    }), (1, {}), (2, {
        "attr_1": typ([3]),
        "attr_2": 30
    })])
    G.add_edges_from([(0, 1, {
        "attr_1": typ([1, 11])
    }), (0, 2, {
        "attr_1": typ([2, 22]),
        "attr_2": 10
    })])

    renderer = bpg.from_networkx(G, nx.circular_layout)

    assert renderer.node_renderer.data_source.data["index"] == [0, 1, 2]
    assert renderer.node_renderer.data_source.data["attr_1"] == [[1, 2], [],
                                                                 [3]]
    assert renderer.node_renderer.data_source.data["attr_2"] == [10, None, 30]

    assert renderer.edge_renderer.data_source.data["start"] == [0, 0]
    assert renderer.edge_renderer.data_source.data["end"] == [1, 2]
    assert renderer.edge_renderer.data_source.data["attr_1"] == [[1, 11],
                                                                 [2, 22]]
    assert renderer.edge_renderer.data_source.data["attr_2"] == [None, 10]
Example #4
0
def test_from_networkx_with_scalar_attributes():
    G = nx.Graph()
    G.add_nodes_from([(0, {
        "attr_1": "a",
        "attr_2": 10
    }), (1, {
        "attr_1": "b"
    }), (2, {
        "attr_1": "c",
        "attr_2": 30
    })])
    G.add_edges_from([(0, 1, {
        "attr_1": "A"
    }), (0, 2, {
        "attr_1": "B",
        "attr_2": 10
    })])

    renderer = bpg.from_networkx(G, nx.circular_layout)

    assert renderer.node_renderer.data_source.data["index"] == [0, 1, 2]
    assert renderer.node_renderer.data_source.data["attr_1"] == ["a", "b", "c"]
    assert renderer.node_renderer.data_source.data["attr_2"] == [10, None, 30]

    assert renderer.edge_renderer.data_source.data["start"] == [0, 0]
    assert renderer.edge_renderer.data_source.data["end"] == [1, 2]
    assert renderer.edge_renderer.data_source.data["attr_1"] == ["A", "B"]
    assert renderer.edge_renderer.data_source.data["attr_2"] == [None, 10]
Example #5
0
def test_from_networkx_method_with_kwargs() -> None:
    G=nx.Graph()
    G.add_nodes_from([0,1,2,3])
    G.add_edges_from([[0,1], [0,2], [2,3]])

    renderer = bpg.from_networkx(G, nx.circular_layout, scale=2)

    gl = renderer.layout_provider.graph_layout
    assert set(gl.keys()) == {0, 1, 2, 3}
    assert_allclose(gl[0], np.array([2.0, 0.0]), atol=1e-7)
Example #6
0
def test_from_networkx_method() -> None:
    G=nx.Graph()
    G.add_nodes_from([0,1,2,3])
    G.add_edges_from([[0,1], [0,2], [2,3]])

    renderer = bpg.from_networkx(G, nx.circular_layout)
    assert renderer.node_renderer.data_source.data["index"] == [0,1,2,3]
    assert renderer.edge_renderer.data_source.data["start"] == [0,0,2]
    assert renderer.edge_renderer.data_source.data["end"] == [1,2,3]

    gl = renderer.layout_provider.graph_layout
    assert set(gl.keys()) == {0, 1, 2, 3}
    assert_allclose(gl[0], np.array([1.0, 0.0]), atol=1e-7)
Example #7
0
def test_from_networkx_with_missing_layout() -> None:
    G = nx.Graph()
    G.add_nodes_from([0, 1, 2])
    G.add_edges_from([[0, 1], [0, 2]])

    missing_fixed_layout = {0: [0, 1],
                            1: [-1, 0]}

    with pytest.warns(UserWarning):
        renderer = bpg.from_networkx(G, missing_fixed_layout)
        gl = renderer.layout_provider.graph_layout
        assert set(gl.keys()) == {0, 1}
        assert renderer.layout_provider.graph_layout[0] == missing_fixed_layout[0]
        assert renderer.layout_provider.graph_layout[1] == missing_fixed_layout[1]
Example #8
0
def test_from_networkx_fixed_layout():
    G = nx.Graph()
    G.add_nodes_from([0, 1, 2])
    G.add_edges_from([[0, 1], [0, 2]])

    fixed_layout = {0: [0, 1], 1: [-1, 0], 2: [1, 0]}

    renderer = bpg.from_networkx(G, fixed_layout)
    assert renderer.node_renderer.data_source.data["index"] == [0, 1, 2]
    assert renderer.edge_renderer.data_source.data["start"] == [0, 0]
    assert renderer.edge_renderer.data_source.data["end"] == [1, 2]

    gl = renderer.layout_provider.graph_layout
    assert set(gl.keys()) == set([0, 1, 2])
    assert renderer.layout_provider.graph_layout[0] == fixed_layout[0]
    assert renderer.layout_provider.graph_layout[1] == fixed_layout[1]
    assert renderer.layout_provider.graph_layout[2] == fixed_layout[2]
Example #9
0
def create_bokeh(G, title, fname, extract_size=15, feature_size=10):
    # Add attributes this way
    try:
        max_weight = max(nx.get_edge_attributes(G, 'weight').values())
    except ValueError:
        max_weight = 1.0
    calc_alpha = lambda x: 0.1 + 0.6 * (x / max_weight)
    edge_attrs = {(s,e): calc_alpha(d['weight']) for s,e,d in G.edges(data=True)}

    node_attrs = {
        k: {
            "_size": feature_size if v['_type']=='spin' else extract_size,
            "_num_members": len(eval(v.get('members', '[]')))
        }
        for k,v in G.nodes(data=True) }
    nx.set_edge_attributes(G, edge_attrs, "_alpha")
    nx.set_node_attributes(G, node_attrs)

    # Show with Bokeh
    plot = Plot(plot_width=1100, plot_height=700,
                x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1))
    plot.title.text = title

    node_hover_tool = HoverTool(tooltips=[("Name", "@index"), ("Members", "@members")])
    plot.add_tools(node_hover_tool, WheelZoomTool(), BoxZoomTool(), ResetTool(), TapTool())

    # Tried this but default layout is just better...
    # def layout(x, **kwargs):
    #     return nx.spring_layout(x, **kwargs, k=1.1/sqrt(x.number_of_nodes()),iterations=10000)
    # graph_renderer = from_networkx(G, layout, scale=1, center=(0, 0))

    graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))

    graph_renderer.node_renderer.glyph = Circle(size='_size', fill_color="_color")
    graph_renderer.node_renderer.selection_glyph = Circle(size=15, fill_color="orange")#works
    graph_renderer.node_renderer.hover_glyph = Circle(size=15, fill_color="red")#works
    graph_renderer.edge_renderer.glyph = MultiLine(line_alpha="_alpha", line_width=1)
    plot.renderers.append(graph_renderer)

    # Add filter slider
    df = nx.to_pandas_edgelist(G)
    max_members = max(nx.get_node_attributes(G,"_num_members").values())
    backup_node_data = graph_renderer.node_renderer.data_source.data
    backup_edge_data = graph_renderer.edge_renderer.data_source.data
    code = """
        const min_nodes = cb_obj.value[0];
        const max_nodes = cb_obj.value[1];
        var to_keep;

        to_keep = ndata.index.map((v,i) =>{
            if (ndata._type[i] !== "spin"){return i}
            else{if(ndata._num_members[i]<=max_nodes && ndata._num_members[i]>=min_nodes)
            {return i}}
        }).filter(x => Boolean(x) | x === 0);

        let keep_names = ndata.index.filter((_,i)=>to_keep.includes(i))

        let new_nodes = {};
        Object.keys(ndata).forEach(k => {
            new_nodes[k] = ndata[k].filter((_,i)=>to_keep.includes(i));
        })

        let new_edges = {};

        Object.keys(edata).forEach(k => {
            new_edges[k] = edata[k].filter((_,i)=>{
                let end = false;
                let start = false;
                if (keep_names.includes(edata.start[i]))
                    start = true
                if (keep_names.includes(edata.end[i]))
                    end = true
                return end && start;
            });
        });

        // Update graph
        graph_setup.node_renderer.data_source.data = new_nodes;
        graph_setup.edge_renderer.data_source.data = new_edges;
        graph_setup.node_renderer.data_source.change.emit();
        graph_setup.edge_renderer.data_source.change.emit();
    """
    min_cb = CustomJS(args=dict(graph_setup=graph_renderer,
                                start=df['source'].values,
                                end=df['target'].values,
                                ndata=backup_node_data,
                                edata=backup_edge_data,
                                type="min"),
                        code=code)
    min_slider = RangeSlider(title='Filter by Number of Members', start=1, end=max_members, value=(1, max_members))

    min_slider.js_on_change('value', min_cb)
    output_file(fname)
    layout = Column(plot, min_slider)
    save(layout)