def to_DynGraphIG(self): """ Convert the graph into a DynGraph_IG. ##Can be optimized ! :return: """ sn_duration = self.frequency() by_edges = dict() by_nodes = dict() for t, g in self.snapshots().items(): for e in g.edges(): by_edges.setdefault(frozenset(e), []).append(t) for n in g.nodes(): by_nodes.setdefault(n, []).append(t) by_edges = { tuple(e): tn.Intervals.from_time_list(v, sn_duration) for e, v in by_edges.items() } by_nodes = { n: tn.Intervals.from_time_list(v, sn_duration) for n, v in by_nodes.items() } return tn.DynGraphIG(start=min(self.snapshots_timesteps()), end=max(self.snapshots_timesteps()) + sn_duration, edges=by_edges, nodes=by_nodes, frequency=sn_duration)
def local_format_to_dyn_graph(self): to_return = dn.DynGraphIG() for n in self._dyn_graph_nodes: intv = Intervals(self._dyn_graph_nodes[n]) to_return.add_node_presence(n,intv) for e in self._dyn_graph_edges: [n1,n2] = list(e) intv = Intervals(self._dyn_graph_edges[e]) to_return._add_interaction_safe(n1,n2,intv) return to_return
def local_format_to_dyn_graph(self): to_return = dn.DynGraphIG() print(self._dyn_graph_nodes) for n in self._dyn_graph_nodes: intv = Intervals(self._dyn_graph_nodes[n]) print(n, intv) to_return.add_node_presence(n, intv) print(nx.get_node_attributes(to_return._graph, "t")) for e in self._dyn_graph_edges: [n1, n2] = list(e) intv = Intervals(self._dyn_graph_edges[e]) to_return._add_interaction_safe(n1, n2, intv) print(to_return.node_presence()) return to_return
def test_add_nodes_ig(self): dg = tn.DynGraphIG() dg.add_node_presence(1,(1,2)) dg.add_node_presence(2,(1,2)) dg.add_nodes_presence_from(3,(1,7)) dg.add_nodes_presence_from([4,5],(1,2)) dg.add_nodes_presence_from([6, 7], (1,3)) dg.remove_node_presence(2,(1,2)) dg.remove_node_presence(3, (2,3)) self.assertEqual(set(dg.graph_at_time(1).nodes()),set([1,3,4,5,6,7])) self.assertEqual(set(dg.graph_at_time(2).nodes()),set([6,7])) self.assertEqual(set(dg.graph_at_time(3).nodes()),set([3])) self.assertEqual(set(dg.graph_at_time(4).nodes()),set([3])) self.assertEqual(set(dg.graph_at_time(6).nodes()),set([3]))
def to_DynGraphIG(self, sn_duration, convert_time_to_integer=False): """ Convert the graph into a DynGraph_IG. By default, snapshot_affiliations last from their time ID to the time ID of the next snapshot. Be careful, for the last snaphsot, we cannot know his duration, therefore, if sn_duration is not provided, it has a default duration equal to the min of all durations :param sn_duration: duration of sns, None for automatic behavior :param convert_time_to_integer: if True, use the snapshot order in the list of SN rather than its time step :return: """ toReturn = tn.DynGraphIG() for i in range(len(self._snapshots)): if convert_time_to_integer: current_t = i tNext = i + 1 else: current_t = self._snapshots.peekitem(i)[0] if sn_duration != None: tNext = current_t + sn_duration else: if i < len(self._snapshots) - 1: tNext = self._snapshots.peekitem(i + 1)[0] else: #computing the min duration to choose as duration of the last period dates = self.snapshots_timesteps() minDuration = min([ dates[i + 1] - dates[i] for i in range(len(dates) - 1) ]) tNext = current_t + minDuration if (len(self._snapshots.peekitem(i)[1].nodes())) > 0: toReturn.add_nodes_presence_from( self._snapshots.peekitem(i)[1].nodes(), (current_t, tNext)) if len(list(self._snapshots.peekitem(i)[1].edges())) > 0: toReturn.add_interactions_from( list(self._snapshots.peekitem(i)[1].edges()), (current_t, tNext)) return toReturn
def slice(self, start, end): """ Keep only the selected period :param start: time of the beginning of the slice :param end: time of the end of the slice """ to_return = tn.DynGraphIG() slice_time = Intervals((start, end)) for n, presence in self.node_presence().items(): to_return.add_node_presence(n, slice_time.intersection(presence)) for e, presence in self.interactions().items(): to_return.add_interaction(e[0], e[1], slice_time.intersection(presence)) return to_return
def _local_formats_to_dyn_structures(self): to_return_graph = dn.DynGraphIG() for n in self._dyn_graph_local_nodes: intv = Intervals(self._dyn_graph_local_nodes[n]) to_return_graph.add_node_presence(n, intv) for e in self._dyn_graph_local_edges: [n1, n2] = list(e) intv = Intervals(self._dyn_graph_local_edges[e]) to_return_graph._add_interaction_safe(n1, n2, intv) for c in self._dyn_com_local: for n in self._dyn_com_local[c]: self._dyn_com_local[c][n] = Intervals( self._dyn_com_local[c][n]) to_return_com = dn.DynCommunitiesIG() to_return_com._fast_set_affiliations(self._dyn_com_local) return to_return_graph, to_return_com
def from_pandas_interaction_list(interactions, format, frequency=1, source="n1", target="n2", time="time"): interactions = two_columns2unidrected_edge(interactions, source="n1", target="n2") if format == tn.DynGraphSN: all_times = set(interactions[time]) all_graphs = {} for t in all_times: this_t = interactions[interactions["time"] == t] all_graphs[t] = nx.from_pandas_edgelist(this_t, source=source, target=target) return tn.DynGraphSN(all_graphs, frequency=frequency) if format == tn.DynGraphLS: #all_edges = set(interactions["e"]) #print(len(all_edges)) edges_time = {} for i, row in interactions.iterrows(): edges_time.setdefault(row["e"], []).append(row[time]) #for e in all_edges: # edges_time[e]= list(interactions[interactions["e"]==e][time]) to_return = tn.DynGraphLS(edges=edges_time, frequency=frequency) return to_return if format == tn.DynGraphIG: #all_edges = set(interactions["e"]) edges_time = {} for i, row in interactions.iterrows(): edges_time.setdefault(row["e"], []).append(row[time]) for e, v in edges_time.items(): edges_time[e] = tn.Intervals.from_time_list(v, frequency) #for e in all_edges: # edges_time[e]= list(interactions[interactions["e"]==e][time]) # edges_time[e]=tn.Intervals.from_time_list(edges_time) to_return = tn.DynGraphIG(edges_time) return to_return
def read_IG(file_address: str): """ Read as list of periods Read an interval graph as a list of periods, for the graph, the nodes, and the edges See write_IG for an explanation of the format :param file_address: """ aDynGraph = tn.DynGraphIG() file = open(file_address) for line in file: parts = line.split("\t") if parts[0] == "SG": for period in parts[1:]: times = period.split(":") aDynGraph.start = int(times[0]) aDynGraph.end = int(times[1]) if parts[0] == "N": nodeName = parts[1] parts = parts[2:] for period in parts: times = period.split(":") start = int(times[0]) end = int(times[1]) aDynGraph.add_node_presence(nodeName, (start, end)) if parts[0] == "E": n1 = parts[1] n2 = parts[2] parts = parts[3:] for period in parts: times = period.split(":") start = int(times[0]) end = int(times[1]) aDynGraph.add_interaction(n1, n2, (start, end)) return aDynGraph
def test_add_interactions_ig(self): dg = tn.DynGraphIG() dg.add_interaction(1,2,(4,5)) self.assertEqual(set(dg.graph_at_time(4).edges()),set([(1,2)])) dg.add_interaction(1, 2, (6,7)) self.assertEqual(dg.edge_presence((1,2),as_intervals=True),tn.Intervals([(4,5),(6,7)])) dg.add_interactions_from({2, 3}, (6,7,9)) self.assertEqual(list(dg.graph_at_time(6).edges()),[(1,2),(2,3)]) dg.add_interactions_from([(5, 6),(6,7)], (9,10)) self.assertEqual(list(dg.graph_at_time(9).edges()),[(5,6),(6,7)]) dg.add_interactions_from([(1, 2),(1,3)], (10,12)) self.assertEqual(list(dg.graph_at_time(10).edges()),[(1,2),(1,3)]) self.assertEqual(list(dg.graph_at_time(11).edges()),[(1,2),(1,3)])
def slice(self,start,end): """ Keep only the selected period :param start: time of the beginning of the slice :param end: time of the end of the slice """ to_return = tn.DynGraphIG() slice_time = Intervals((start,end)) for n,presence in self.node_presence().items(): duration = slice_time.intersection(presence) if duration.duration()>0: to_return.add_node_presence(n,duration) for e,presence in self.interactions_intervals().items(): el = list(e) duration = slice_time.intersection(presence) if duration.duration()>0: to_return.add_interaction(el[0],el[1],duration) return to_return
def plot_longitudinal(dynamic_graph=None,communities=None, sn_duration=None,to_datetime=False, nodes=None,width=800,height=600,bokeh=False,auto_show=False): """ A longitudinal view of nodes/snapshot_communities Plot snapshot_affiliations such as each node corresponds to a horizontal line and time corresponds to the horizontal axis :param dynamic_graph: DynGraphSN or DynGraphIG :param communities: dynamic snapshot_affiliations, DynCommunitiesSN or DynCommunitiesIG :param sn_duration: the duration of a snapshot, as int or timedelta. If none, inferred automatically as lasting until next snpashot :param to_datetime: one of True/False/function. If True, step IDs are converted to dates using datetime.utcfromtimestamp. If a function, should take a step ID and return a datetime object. :param nodes: If none, plot all nodes in lexicographic order. If a list of nodes, plot only those nodes, in that order :param width: width of the figure :param height: height of the figure """ if dynamic_graph==None: if isinstance(communities,tn.DynCommunitiesSN): dynamic_graph = tn.DynGraphSN() else: dynamic_graph = tn.DynGraphIG() if to_datetime==True: to_datetime=datetime.utcfromtimestamp if sn_duration!=None and not isinstance(sn_duration,timedelta): sn_duration=timedelta(seconds=sn_duration) if isinstance(dynamic_graph,tn.DynGraphSN): if communities == None: communities = tn.DynCommunitiesSN() t = list(dynamic_graph.snapshots_timesteps()) if communities != None and isinstance(communities,tn.DynCommunitiesSN): t = t + list(communities.snapshots.keys()) t = sorted(list(set(t))) CDS = _sn_graph2CDS(dynamic_graph, communities, to_datetime=to_datetime,ts=t) else: if communities == None: communities = tn.DynCommunitiesIG() CDS = _ig_graph2CDS(dynamic_graph, communities, to_datetime=to_datetime) if isinstance(dynamic_graph,tn.DynGraphSN) and sn_duration!=None: CDS.data["duration"] = [sn_duration]*len(CDS.data["time"]) if to_datetime!=False: CDS.data["duration_display"] = [x/1000 for x in CDS.data["duration"]] else: CDS.data["duration_display"]=CDS.data["duration"] #CDS.data["duration"] = [v+0.1 for v in CDS.data["duration"]] #should work for timedelta and integers CDS.data["time_shift"] = [CDS.data["time"][i] + CDS.data["duration"][i] / 2 for i in range(len(CDS.data["duration"]))] if nodes==None: nodes = sorted(list(set(CDS.data["node"]))) nodes = [str(x) for x in nodes] #return _plot_longitudinal_bokeh(CDS,nodes,to_datetime,width,height,auto_show) if bokeh: return _plot_longitudinal_bokeh(CDS,nodes,to_datetime,width,height, auto_show) else: return _plot_longitudinal_pyplot(CDS,nodes,to_datetime,width,height)