Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add edges with options via add_edges #183

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 30 additions & 13 deletions pyvis/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def add_nodes(self, nodes, **kwargs):
:type nodes: list
"""
valid_args = ["size", "value", "title",
"x", "y", "label", "color", "shape"]
"x", "y", "label", "color", "shape"]
for k in kwargs:
assert k in valid_args, "invalid arg '" + k + "'"

Expand Down Expand Up @@ -385,24 +385,41 @@ def add_edge(self, source, to, **options):
e = Edge(source, to, self.directed, **options)
self.edges.append(e.options)

def add_edges(self, edges):
def add_edges(self, edges, **kwargs):
"""
This method serves to add multiple edges between existing nodes
in the network instance. Adding of the edges is done based off
of the IDs of the nodes. Order does not matter unless dealing with a
directed graph.

:param edges: A list of tuples, each tuple consists of source of edge,
edge destination and and optional width.
edge destination and optional width.

:type arrowStrikethrough: list of tuples
"""
valid_args = ["arrowStrikethrough", "hidden", "physics", "title", "from", "to", "value", "width"]

for k in kwargs:
assert k in valid_args, "invalid arg '" + k + "'"

ed = defaultdict(dict)
for i in range(len(edges)):
for k, v in kwargs.items():
assert (
len(v) == len(edges)
), "keyword arg %s [length %s] does not match" \
"[length %s] of nodes" % \
(
k, len(v), len(edges)
)
ed[edges[i]].update({k: v[i]})

for edge in edges:
# if incoming tuple contains a weight
if len(edge) == 3:
self.add_edge(edge[0], edge[1], width=edge[2])
self.add_edge(edge[0], edge[1], width=edge[2], **ed[edge])
else:
self.add_edge(edge[0], edge[1])
self.add_edge(edge[0], edge[1], **ed[edge])

def get_network_data(self):
"""
Expand Down Expand Up @@ -651,7 +668,7 @@ def neighbors(self, node):
return self.get_adj_list()[node]

def from_nx(self, nx_graph, node_size_transf=(lambda x: x), edge_weight_transf=(lambda x: x),
default_node_size =10, default_edge_weight=1, show_edge_weights=True, edge_scaling=False):
default_node_size=10, default_edge_weight=1, show_edge_weights=True, edge_scaling=False):
"""
This method takes an exisitng Networkx graph and translates
it to a PyVis graph format that can be accepted by the VisJs
Expand Down Expand Up @@ -679,18 +696,18 @@ def from_nx(self, nx_graph, node_size_transf=(lambda x: x), edge_weight_transf=(
>>> nt.from_nx(nx_graph)
>>> nt.show("nx.html")
"""
assert(isinstance(nx_graph, nx.Graph))
edges=nx_graph.edges(data = True)
nodes=nx_graph.nodes(data = True)
assert (isinstance(nx_graph, nx.Graph))
edges = nx_graph.edges(data=True)
nodes = nx_graph.nodes(data=True)

if len(edges) > 0:
for e in edges:
if 'size' not in nodes[e[0]].keys():
nodes[e[0]]['size']=default_node_size
nodes[e[0]]['size']=int(node_size_transf(nodes[e[0]]['size']))
nodes[e[0]]['size'] = default_node_size
nodes[e[0]]['size'] = int(node_size_transf(nodes[e[0]]['size']))
if 'size' not in nodes[e[1]].keys():
nodes[e[1]]['size']=default_node_size
nodes[e[1]]['size']=int(node_size_transf(nodes[e[1]]['size']))
nodes[e[1]]['size'] = default_node_size
nodes[e[1]]['size'] = int(node_size_transf(nodes[e[1]]['size']))
self.add_node(e[0], **nodes[e[0]])
self.add_node(e[1], **nodes[e[1]])

Expand Down
36 changes: 25 additions & 11 deletions pyvis/tests/test_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,24 @@ def test_add_edges_mixed_weights(self):
list([1, None, 3, None, 5, None]),
list(map(lambda x: x.get("width", None), self.g.edges)))

def test_add_edges_with_options(self):
self.g.add_edges(
[
(0, 1), (0, 2), (0, 3),
(1, 2), (1, 3), (2, 3)
], width=[1, 2, 3, 4, 5, 6]
)
self.assertEqual(self.g.num_edges(), 6)
self.assertEqual(self.g.neighbors(0), set([1, 2, 3]))
self.assertEqual(self.g.neighbors(1), set([0, 2, 3]))
self.assertEqual(self.g.neighbors(2), set([0, 1, 3]))
self.assertEqual(self.g.neighbors(3), set([0, 1, 2]))
for edges in self.g.edges:
self.assertTrue("width" in edges)
self.assertEqual(
list([1, 2, 3, 4, 5, 6]),
list(map(lambda x: x["width"], self.g.edges)))

def test_add_edge_directed(self):
self.g.directed = True
self.g.add_edge(0, 1)
Expand Down Expand Up @@ -308,23 +326,23 @@ def setUp(self):

def test_can_enable_init(self):
self.assertTrue(self.g.options['layout'])

def test_layout_disabled(self):
self.g = Network()
self.assertRaises(KeyError, lambda: self.g.options['layout'])

def test_levelSeparation(self):
self.assertTrue(self.g.options.layout.hierarchical.levelSeparation)

def test_treeSpacing(self):
self.assertTrue(self.g.options.layout.hierarchical.treeSpacing)

def test_blockShifting(self):
self.assertTrue(self.g.options.layout.hierarchical.blockShifting)

def test_edgeMinimization(self):
self.assertTrue(self.g.options.layout.hierarchical.edgeMinimization)

def test_parentCentralization(self):
self.assertTrue(self.g.options.layout.hierarchical.parentCentralization)

Expand All @@ -334,7 +352,7 @@ def test_sortMethod(self):
def test_set_edge_minimization(self):
self.g.options.layout.set_separation(10)
self.assertTrue(self.g.options.layout.hierarchical.levelSeparation == 10)

def test_set_tree_spacing(self):
self.g.options.layout.set_tree_spacing(10)
self.assertTrue(self.g.options.layout.hierarchical.treeSpacing == 10)
Expand All @@ -344,7 +362,3 @@ def test_set_edge_minimization(self):
self.assertTrue(self.g.options.layout.hierarchical.edgeMinimization == True)
self.g.options.layout.set_edge_minimization(False)
self.assertTrue(self.g.options.layout.hierarchical.edgeMinimization == False)