Skip to content

Commit

Permalink
🆕 add support for node labels
Browse files Browse the repository at this point in the history
  • Loading branch information
GiulioRossetti committed Nov 19, 2020
1 parent dbeb214 commit e7f1ec2
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 10 deletions.
61 changes: 57 additions & 4 deletions dynetx/classes/dyndigraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,16 @@ def __init__(self, data=None, edge_removal=True, **attr):
self.edge_removal = edge_removal
self.directed = True

def nodes_iter(self, t=None):
def nodes_iter(self, t=None, data=False):
"""Return an iterator over the nodes with respect to a given temporal snapshot.
Parameters
----------
t : snapshot id (default=None).
If None the iterator returns all the nodes of the flattened graph.
data: node data(default=False)
Returns
-------
niter : iterator
Expand All @@ -142,8 +144,15 @@ def nodes_iter(self, t=None):
[0, 1, 2]
"""
if t is not None:
return iter([n for n in self.degree(t=t).values() if n > 0])
return iter(self._node)
if not data:
return [n for n, d in self.degree(t=t).items() if d > 0]
else:
return {n: self._node[n] for n, d in self.degree(t=t).items() if d > 0}

if not data:
return iter(self._node)
else:
return self._node

def nodes(self, t=None, data=False):
"""Return a list of the nodes in the graph at a given snapshot.
Expand Down Expand Up @@ -173,7 +182,10 @@ def nodes(self, t=None, data=False):
>>> G.nodes(t=0)
[0, 1]
"""
return list(self.nodes_iter(t=t))
if data:
return [(k, v) for k, v in self.nodes_iter(t=t, data=data).items()]
else:
return [k for k in self.nodes_iter(t=t, data=data)]

def has_node(self, n, t=None):
"""Return True if the graph, at time t, contains the node n.
Expand Down Expand Up @@ -1289,8 +1301,49 @@ def time_slice(self, t_from, t_to=None):
H.add_interaction(u, v, i_to, b)
elif i_to <= a <= f_from <= b:
H.add_interaction(u, v, a, f_from)

for n in H.nodes():
H._node[n] = self._node[n]

return H

def update_node_attr(self, n, **data):
"""Updates the attributes of a specified node.
Parameters
----------
n : node id
**data : the attributes and their new values
Examples
--------
>>> import dynetx as dn
>>> G = dn.DynGraph()
>>> G.add_node(0, Label="A")
>>> G.update_node_attr(0, Label="B")
"""
self._node[n] = data

def update_node_attr_from(self, nlist, **data):
"""Updates the attributes of a specified node.
Parameters
----------
nlist : list of node ids
**data : the attributes and their new values
Examples
--------
>>> import dynetx as dn
>>> G = dn.DynGraph()
>>> G.add_nodes_from([0, 1, 2], Label="A")
>>> G.update_node_attr_from([0, 2], Label="B")
"""
for n in nlist:
self._node[n] = data

def temporal_snapshots_ids(self):
"""Return the ordered list of snapshot ids present in the dynamic graph.
Expand Down
63 changes: 59 additions & 4 deletions dynetx/classes/dyngraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,16 @@ def __init__(self, data=None, edge_removal=True, **attr):
self.edge_removal = edge_removal
self.directed = False

def nodes_iter(self, t=None):
def nodes_iter(self, t=None, data=False):
"""Return an iterator over the nodes with respect to a given temporal snapshot.
Parameters
----------
t : snapshot id (default=None).
If None the iterator returns all the nodes of the flattened graph.
data: node data(default=False)
Returns
-------
niter : iterator
Expand All @@ -149,8 +151,15 @@ def nodes_iter(self, t=None):
[0, 1, 2]
"""
if t is not None:
return iter([n for n in self.degree(t=t).values() if n > 0])
return iter(self._node)
if not data:
return [n for n, d in self.degree(t=t).items() if d > 0]
else:
return {n: self._node[n] for n, d in self.degree(t=t).items() if d > 0}

if not data:
return iter(self._node)
else:
return self._node

def nodes(self, t=None, data=False):
"""Return a list of the nodes in the graph at a given snapshot.
Expand Down Expand Up @@ -180,7 +189,11 @@ def nodes(self, t=None, data=False):
>>> G.nodes(t=0)
[0, 1, 2]
"""
return list(self.nodes_iter(t=t))

if data:
return [(k, v) for k, v in self.nodes_iter(t=t, data=data).items()]
else:
return [k for k in self.nodes_iter(t=t, data=data)]

def interactions(self, nbunch=None, t=None):
"""Return the list of interaction present in a given snapshot.
Expand Down Expand Up @@ -1037,6 +1050,7 @@ def time_slice(self, t_from, t_to=None):
f_from = t_from

for a, b in ts['t']:

if i_to <= a and b <= f_from:
H.add_interaction(u, v, a, b)
elif a <= i_to and f_from <= b:
Expand All @@ -1045,8 +1059,49 @@ def time_slice(self, t_from, t_to=None):
H.add_interaction(u, v, i_to, b)
elif i_to <= a <= f_from <= b:
H.add_interaction(u, v, a, f_from)

for n in H.nodes():
H._node[n] = self._node[n]

return H

def update_node_attr(self, n, **data):
"""Updates the attributes of a specified node.
Parameters
----------
n : node id
**data : the attributes and their new values
Examples
--------
>>> import dynetx as dn
>>> G = dn.DynGraph()
>>> G.add_node(0, Label="A")
>>> G.update_node_attr(0, Label="B")
"""
self._node[n] = data

def update_node_attr_from(self, nlist, **data):
"""Updates the attributes of a specified node.
Parameters
----------
nlist : list of node ids
**data : the attributes and their new values
Examples
--------
>>> import dynetx as dn
>>> G = dn.DynGraph()
>>> G.add_nodes_from([0, 1, 2], Label="A")
>>> G.update_node_attr_from([0, 2], Label="B")
"""
for n in nlist:
self._node[n] = data

def temporal_snapshots_ids(self):
"""Return the ordered list of snapshot ids present in the dynamic graph.
Expand Down
17 changes: 15 additions & 2 deletions dynetx/test/test_dyndigraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,21 @@ def test_in_out_interactions(self):
sr = g.out_interactions([0, 1], 7)
self.assertEqual(sr, [])

def test_update_node_attr(self):
g = dn.DynDiGraph()

for n in [0, 1, 2, 3, 4, 5, 6, 7, 8]:
g.add_node(n, Label="A")

for n in g.nodes():
g.update_node_attr(n, Label="B")

for n in g.nodes(data=True):
self.assertEqual(n[1]['Label'], "B")

g.update_node_attr_from([0, 1, 2], Label="C")
self.assertEqual(g._node[0]['Label'], "C")

def test_neighbors(self):
g = dn.DynDiGraph()
g.add_interaction(0, 1, 5)
Expand Down Expand Up @@ -337,7 +352,6 @@ def test_time_slice(self):
self.assertEqual(h.number_of_nodes(), 5)
self.assertEqual(h.number_of_interactions(), 4)


h = g.time_slice(5, 5)
self.assertIsInstance(h, dn.DynDiGraph)
self.assertEqual(h.number_of_nodes(), 5)
Expand Down Expand Up @@ -504,7 +518,6 @@ def test_conversion(self):
H = G.to_undirected()
self.assertIsInstance(H, dn.DynGraph)
self.assertEqual(H.number_of_nodes(), 3)
print(H.edges, H.number_of_edges())
self.assertEqual(H.number_of_edges(), 3)

if __name__ == '__main__':
Expand Down
55 changes: 55 additions & 0 deletions dynetx/test/test_dyngraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,61 @@ def test_number_of_nodes(self):
avg = g.avg_number_of_nodes()
self.assertEqual(avg, 5)

def test_update_node_attr(self):
g = dn.DynGraph()

for n in [0, 1, 2, 3, 4, 5, 6, 7, 8]:
g.add_node(n, Label="A")

for n in g.nodes():
g.update_node_attr(n, Label="B")

for n in g.nodes(data=True):
self.assertEqual(n[1]['Label'], "B")

g.update_node_attr_from([0, 1, 2], Label="C")
self.assertEqual(g._node[0]['Label'], "C")

def test_add_node_attr(self):
g = dn.DynGraph()

for n in [0, 1, 2, 3, 4, 5, 6, 7, 8]:
g.add_node(n, Label="A")

g.add_nodes_from([9, 10, 11, 12], Label="A")

g.add_path([0, 1, 2, 3, 4], t=5)
g.add_path([4, 5, 6, 7, 8], t=6)

for n in g.nodes(data=True):
self.assertEqual(n[1]['Label'], "A")

nds5 = []
for n in g.nodes(data=True, t=5):
nds5.append(n[0])
self.assertEqual(n[1]['Label'], "A")

self.assertListEqual(nds5, [0, 1, 2, 3, 4])

def test_time_slice_node_attr(self):
g = dn.DynGraph()

for n in [0, 1, 2, 3, 4, 5, 6, 7, 8]:
g.add_node(n, Label="A")

g.add_path([0, 1, 2, 3, 4], t=5)
g.add_path([4, 5, 6, 7, 8], t=6)

h = g.time_slice(5)
for n in h.nodes(data=True):
self.assertEqual(n[1]['Label'], "A")

self.assertIsInstance(h, dn.DynGraph)
self.assertEqual(h.number_of_nodes(), 5)
self.assertEqual(h.number_of_interactions(), 4)



def test_time_slice(self):
g = dn.DynGraph()
g.add_path([0, 1, 2, 3, 4], t=5)
Expand Down

0 comments on commit e7f1ec2

Please sign in to comment.