Skip to content

Instantly share code, notes, and snippets.

@cvanelteren
Last active October 19, 2020 16:41
Show Gist options
  • Save cvanelteren/736b4fd189727086ce98a3db5a183423 to your computer and use it in GitHub Desktop.
Save cvanelteren/736b4fd189727086ce98a3db5a183423 to your computer and use it in GitHub Desktop.
Using networkx layouts and numpy coordinates for vispy.
from vispy.visuals.graphs.util import _straight_line_vertices, issparse
import networkx as nx, numpy as np
class NetworkxCoordinates:
def __init__(self, graph, layout = None, *args, **kwargs):
self.graph = graph
self.positions = np.zeros((len(graph), 2), dtype = np.float32)
# default random positions
if type(layout) is type(None):
self.positions = np.random.rand(*self.positions.shape)
# check for networkx
elif isinstance(layout, str):
layout += "_layout" # append for nx
if f := getattr(nx, layout):
self.positions = np.asarray([i for i in dict(f(graph, **kwargs)).values()])
else:
raise ValueError("Check networkx for layouts")
# assume dict from networkx; values are 2-array
elif isinstance(layout, dict):
self.positions = np.asarray([i for i in layout.values()])
# assume given values
elif isinstance(layout, np.ndarray):
assert layout.ndim == 2
assert layout.shape[0] == len(graph)
self.positions = layout
else:
raise ValueError("Input not understood")
# normalize coordinates
self.positions = (self.positions - self.positions.min()) / (self.positions.max() - self.positions.min())
self.positions = self.positions.astype(np.float32)
def __call__(self, adjacency_mat, directed = False):
if issparse(adjacency_mat):
adjacency_mat = adjacency_mat.tocoo()
line_vertices, arrows = _straight_line_vertices(adjacency_mat, self.positions, directed)
yield self.positions, line_vertices, arrows
@property
def adj(self):
return nx.adjacency_matrix(self.graph)
@cvanelteren
Copy link
Author

Example:

g = nx.erdos_renyi_graph(100, .2)
layout = NetworkxCoordinates(graph = g, layout = "spring")

# create canvas
canvas = scene.SceneCanvas(title='Simple NetworkX Graph', size=(600, 600),
                           bgcolor='black', show=True)
view = canvas.central_widget.add_view('panzoom')
visual = scene.visuals.Graph(
    layout.adj, layout= layout, line_color= (1, 1, 1,  .5), arrow_type="stealth",
    arrow_size=30, node_symbol="disc", node_size=20,
    face_color=(1, 0, 0, 1), border_width=0.0, animate=False, directed=False,
    parent=view.scene)


@canvas.events.draw.connect
def on_draw(event):
    if not visual.animate_layout():
        canvas.update()
    
canvas.show()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment