Source code for cellcomplex.graph.property_graph

# -*- python -*-
#
#       OpenAlea.Core
#
#       Copyright 2006-2009 INRIA - CIRAD - INRA
#
#       File author(s): Jerome Chopard <jerome.chopard@sophia.inria.fr>
#                       Fred Theveny <frederic.theveny@cirad.fr>
#                       Jonathan Legrand <jonathan.legrand@ens-lyon.fr>
#
#       Distributed under the Cecill-C License.
#       See accompanying file LICENSE.txt or copy at
#           http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
#       OpenAlea WebSite: http://openalea.gforge.inria.fr
#
################################################################################
"""This module provide a set of concepts to add properties to graph elements"""

__license__ = "Cecill-C"
__revision__ = " $Id$ "

from .interface.property_graph import IPropertyGraph, PropertyError
from .graph import Graph, InvalidVertex, InvalidEdge
import numpy as np
from heapq import heappop, heappush
import warnings

VertexProperty, EdgeProperty, GraphProperty = list(range(3))
VertexIdType, EdgeIdType, ValueType = list(range(3))

[docs]class PropertyGraph(IPropertyGraph, Graph): """ Simple implementation of IPropertyGraph using dict as properties and two dictionaries to maintain these properties """ metavidtypepropertyname = "valueproperty_as_vid" metaeidtypepropertyname = "valueproperty_as_eid" def __init__(self, graph=None, **kwds): self._vertex_property = {} self._edge_property = {} self._graph_property = {} Graph.__init__(self, graph, **kwds)
[docs] def vertex_property_names(self): """todo""" return self._vertex_property.keys()
vertex_property_names.__doc__ = IPropertyGraph.vertex_property_names.__doc__
[docs] def vertex_properties(self): """todo""" return self._vertex_property
# vertex_properties.__doc__ = IPropertyGraph.vertex_properties.__doc__
[docs] def vertex_property(self, property_name, vids = None): """todo""" try: if vids is not None: return dict([(k,v) for k,v in self._vertex_property[property_name].items() if k in vids]) else: return self._vertex_property[property_name] except KeyError: raise PropertyError("property %s is undefined on vertices" % property_name)
vertex_property.__doc__=IPropertyGraph.vertex_property.__doc__
[docs] def edge_property_names(self): """todo""" return self._edge_property.keys()
edge_property_names.__doc__ = IPropertyGraph.edge_property_names.__doc__
[docs] def edge_properties(self): """todo""" return self._edge_property
# edge_properties.__doc__ = IPropertyGraph. edge_properties.__doc__
[docs] def edge_property(self, property_name): """todo""" try: return self._edge_property[property_name] except KeyError: raise PropertyError("property %s is undefined on edges" % property_name)
edge_property.__doc__ = IPropertyGraph.edge_property.__doc__
[docs] def graph_property(self, property_name): """todo""" try: return self._graph_property[property_name] except KeyError: raise PropertyError("property %s is undefined on graph" % property_name)
graph_property.__doc__ = IPropertyGraph.graph_property.__doc__
[docs] def graph_properties(self): return self._graph_property
[docs] def graph_property_names(self): """todo""" return self._graph_property.keys()
[docs] def add_vertex_property(self, property_name, values = None): """todo""" if property_name in self._vertex_property: raise PropertyError("property %s is already defined on vertices" % property_name) if values is None: values = {} self._vertex_property[property_name] = values
add_vertex_property.__doc__ = IPropertyGraph.add_vertex_property.__doc__
[docs] def extend_vertex_property(self, property_name, values ): """todo AND TO CHECK AND TEST !!""" if not isinstance(values, dict): raise TypeError("Values %s is not a type 'dict'" % values) if property_name not in self._vertex_property: print(PropertyError("Property %s is not defined on vertices" % property_name)) print("Creating vertex property %s" % property_name) self._vertex_property[property_name] = {} for k,v in values.items(): if k in self.vertices(): if k not in self._vertex_property[property_name]: self._vertex_property[property_name][k] = v else: print("Vertex id {} already has a value for vertex property {}".format(k, property_name)) else: print("Vertex id {} doesn't exist in the graph !!".format(k))
[docs] def remove_vertex_property(self, property_name): """todo""" try: del self._graph_property['units'][property_name] except: pass try: del self._vertex_property[property_name] except KeyError: raise PropertyError("property %s is undefined on vertices" % property_name)
remove_vertex_property.__doc__ = IPropertyGraph.remove_vertex_property.__doc__
[docs] def add_edge_property(self, property_name, values = None): """todo""" if property_name in self._edge_property: raise PropertyError("property %s is already defined on edges" % property_name) if values is None: values = {} self._edge_property[property_name] = values
add_edge_property.__doc__ = IPropertyGraph.add_edge_property.__doc__
[docs] def remove_edge_property(self, property_name): """todo""" try: del self._graph_property['units'][property_name] except: pass try: del self._edge_property[property_name] except KeyError: raise PropertyError("property %s is undefined on edges" % property_name)
remove_edge_property.__doc__ = IPropertyGraph.remove_edge_property.__doc__
[docs] def add_graph_property(self, property_name, values = None): """todo""" if property_name in self._graph_property: raise PropertyError("property %s is already defined on graph" % property_name) if values is None: values = {} self._graph_property[property_name] = values
[docs] def extend_graph_property(self, property_name, values): """todo""" assert values is not None if property_name not in self._graph_property: raise PropertyError("property %s is not defined on graph" % property_name) if self.graph_property(property_name) is not None or self.graph_property(property_name) != []: assert isinstance(values, type(self.graph_property(property_name))) if isinstance(self.graph_property(property_name), list): self._graph_property[property_name].extend(values) elif isinstance(self.graph_property(property_name), dict): self._graph_property[property_name].update( dict([(k,v) for k,v in values.items() if k not in self.graph_property(property_name).keys()]) ) else: print("Unable to extend 'graph_property' with this type of data: {}".format(type(values)))
[docs] def remove_graph_property(self, property_name): """todo""" try: del self._graph_property[property_name] except KeyError: raise PropertyError("property %s is undefined on graph" % property_name) try: del self._graph_property['units'][property_name] except KeyError: pass
[docs] def remove_vertex(self, vid): """todo""" for prop in self._vertex_property.values(): prop.pop(vid, None) Graph.remove_vertex(self, vid)
remove_vertex.__doc__ = Graph.remove_vertex.__doc__
[docs] def clear(self): """todo""" for prop in self._vertex_property.values(): prop.clear() for prop in self._edge_property.values(): prop.clear() for prop in self._graph_property.values(): prop.clear() Graph.clear(self)
clear.__doc__ = Graph.clear.__doc__
[docs] def remove_edge(self, eid): """todo""" for prop in self._edge_property.values(): prop.pop(eid, None) Graph.remove_edge(self, eid)
remove_edge.__doc__ = Graph.remove_edge.__doc__
[docs] def clear_edges(self): """todo""" for prop in self._edge_property.values(): prop.clear() Graph.clear_edges(self)
clear_edges.__doc__ = Graph.clear_edges.__doc__ @staticmethod def _translate_property(values, trans_vid, trans_eid, key_translation = ValueType, value_translation = ValueType): # translation function from copy import deepcopy id_value = lambda value: value trans_vid = deepcopy(trans_vid) trans_vid[None] = None def translate_vid(vid): if isinstance(vid, list): return [trans_vid[i] for i in vid] if isinstance(vid, tuple): return tuple([trans_vid[i] for i in vid]) return trans_vid[vid] trans_eid = deepcopy(trans_eid) trans_eid[None] = None def translate_eid(eid): if isinstance(eid, list): return [trans_eid[i] for i in eid] if isinstance(eid, tuple): return tuple([trans_eid[i] for i in eid]) return trans_eid[eid] translator = { ValueType : id_value, VertexIdType : translate_vid, EdgeIdType : translate_eid } key_translator = translator[key_translation] value_translator = translator[value_translation] # translate vid and value return dict([(key_translator(vid),value_translator(val)) for vid, val in values.items()]) def _relabel_and_add_vertex_edge_properties(self,graph, trans_vid, trans_eid): # update properties on vertices for prop_name in graph.vertex_property_names(): if prop_name not in self._vertex_property: self.add_vertex_property(prop_name) value_translator = graph.get_property_value_type(prop_name,VertexProperty) # import property into self. translate vid and value self.vertex_property(prop_name).update(self._translate_property(graph.vertex_property(prop_name), trans_vid, trans_eid, VertexIdType, value_translator)) # update properties on edges for prop_name in graph.edge_property_names(): if prop_name not in self._edge_property: self.add_edge_property(prop_name) # Check what type of translation is required for value of the property value_translator = graph.get_property_value_type(prop_name,EdgeProperty) # import property into self. translate vid and value self.edge_property(prop_name).update(self._translate_property(graph.edge_property(prop_name), trans_vid, trans_eid, EdgeIdType, value_translator))
[docs] def translate_graph_property(self, prop_name, trans_vid, trans_eid): """ Translate a graph property according to meta info """ old_prop = self.graph_property(prop_name) print(type(old_prop)) key_translator = self.get_graph_property_key_type(prop_name) value_translator = self.get_property_value_type(prop_name, GraphProperty) print('translate_graph_property',prop_name, key_translator, value_translator) return self._translate_property(old_prop, trans_vid, trans_eid, key_translator, value_translator)
[docs] def extend(self, graph): """todo""" # add and translate the vertex and edge ids of the second graph trans_vid, trans_eid = Graph.extend(self,graph) # relabel the edge and vertex property self.__relabel_and_add_vertex_edge_properties(graph, trans_vid, trans_eid) # update properties on graph #gproperties = self.graph_property() newgproperties = {} for pname, prop in graph.graph_property_names(): newgproperty = graph.translate_graph_property(pname,trans_vid, trans_eid) newgproperties[pname] = newgproperty prop.update(newgproperties) return trans_vid, trans_eid
extend.__doc__ = Graph.extend.__doc__
[docs] def set_graph_property_value_to_vid_type(self, propertyname, property_type = VertexProperty): """ Give meta info on property value type. Associate it to Vertex Id type """ if self.metavidtypepropertyname not in self._graph_property: self.add_graph_property(self.metavidtypepropertyname,([],[],[],[])) prop = self.graph_property(self.metavidtypepropertyname)[property_type] prop.append(propertyname)
[docs] def set_graph_property_value_to_eid_type(self, propertyname, property_type = EdgeProperty): """ Give meta info on property value type. Associate it to Edge Id type """ if self.metaeidtypepropertyname not in self._graph_property: self.add_graph_property(self.metaeidtypepropertyname,([],[],[],[])) prop = self.graph_property(self.metaeidtypepropertyname)[property_type] prop.append(propertyname)
[docs] def set_graph_property_key_to_vid_type(self, propertyname): """ Give meta info on graph property key type. Associate it to Vertex Id type""" self.set_graph_property_value_to_vid_type(propertyname, 3)
[docs] def set_graph_property_key_to_eid_type(self, propertyname): """ Give meta info on graph property key type. Associate it to Edge Id type """ self.set_graph_property_value_to_eid_type(propertyname, 3)
[docs] def get_property_value_type(self, propertyname, property_type = VertexProperty): """ Return meta info on property value type. """ try: prop = self.graph_property(self.metavidtypepropertyname)[property_type] if propertyname in prop : return VertexIdType except: pass try: prop = self.graph_property(self.metaeidtypepropertyname)[property_type] if propertyname in prop : return EdgeIdType except: return ValueType
[docs] def get_graph_property_key_type(self, propertyname): """ Return meta info on graph property key type. """ return self.get_property_value_type(propertyname, 3)
def __to_set(self, s): if not isinstance(s, set): if isinstance(s, list): s=set(s) else: s=set([s]) return s
[docs] def in_neighbors(self, vid, edge_type=None): """ Return the in vertices of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider (can be a set) :Returns -------- - `neighbors_list` : the set of parent vertices of the vertex vid """ if vid not in self : raise InvalidVertex(vid) if edge_type==None: neighbors_list=set([self.source(eid) for eid in self._vertices[vid][0] ]) else: edge_type=self.__to_set(edge_type) edge_type_property = self._edge_property['edge_type'] neighbors_list=set([self.source(eid) for eid in self._vertices[vid][0] if edge_type_property[eid] in edge_type]) return neighbors_list
[docs] def iter_in_neighbors(self, vid, edge_type=None): """ Return the in vertices of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider (can be a set) :Returns -------- - `iterator` : an iterator on the set of parent vertices of the vertex vid """ return iter(self.in_neighbors(vid, edge_type))
[docs] def out_neighbors(self, vid, edge_type=None): """ Return the out vertices of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider (can be a set) :Returns -------- - `neighbors_list` : the set of child vertices of the vertex vid """ if vid not in self : raise InvalidVertex(vid) if edge_type==None: neighbors_list=set([self.target(eid) for eid in self._vertices[vid][1] ]) else: edge_type=self.__to_set(edge_type) edge_type_property = self._edge_property['edge_type'] neighbors_list=set([self.target(eid) for eid in self._vertices[vid][1] if edge_type_property[eid] in edge_type]) return neighbors_list
[docs] def iter_out_neighbors(self, vid, edge_type=None): """ Return the out vertices of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider (can be a set) :Returns -------- - `iterator` : an iterator on the set of child vertices of the vertex vid """ return iter(self.out_neighbors(vid, edge_type))
[docs] def neighbors(self, vid, edge_type=None): """ Return the neighbors vertices of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider (can be a set) :Returns -------- - `neighbors_list` : the set of neighobrs vertices of the vertex vid """ return self.in_neighbors(vid, edge_type) | self.out_neighbors(vid, edge_type)
[docs] def iter_neighbors(self, vid, edge_type=None): """ Return the neighbors vertices of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider (can be a set) :Returns -------- - `iterartor` : iterator on the set of neighobrs vertices of the vertex vid """ return iter(self.neighbors(vid, edge_type))
[docs] def in_edges(self, vid, edge_type=None): """ Return in edges of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider (can be a set) :Returns -------- - `edge_list` : the set of the in edges of the vertex vid """ if vid not in self : raise InvalidVertex(vid) if not edge_type: edge_list=set([eid for eid in self._vertices[vid][0]]) else: edge_type=self.__to_set(edge_type) edge_type_property = self._edge_property['edge_type'] edge_list=set([eid for eid in self._vertices[vid][0] if edge_type_property[eid] in edge_type]) return edge_list
[docs] def iter_in_edges(self, vid, edge_type=None): """ Return in edges of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider (can be a set) :Returns -------- - `iterator` : an iterator on the set of the in edges of the vertex vid """ return iter(self.in_edges(vid, edge_type))
[docs] def out_edges(self, vid, edge_type=None): """ Return out edges of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider (can be a set) :Returns -------- - `edge_list` : the set of the out edges of the vertex vid """ if vid not in self : raise InvalidVertex(vid) if edge_type==None: edge_list=set([eid for eid in self._vertices[vid][1]]) else: edge_type=self.__to_set(edge_type) edge_type_property = self._edge_property['edge_type'] edge_list=set([eid for eid in self._vertices[vid][1] if edge_type_property[eid] in edge_type]) return edge_list
[docs] def iter_out_edges(self, vid, edge_type=None): """ Return in edges of the vertex vid :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider :Returns -------- - `iterator` : an iterator on the set of the in edges of the vertex vid """ return iter(self.out_edges(vid, edge_type))
[docs] def edges(self, vid=None, edge_type=None): """ Return edges of the vertex vid If vid=None, return all edges of the graph :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider :Returns -------- - `edge_list` : the set of the edges of the vertex vid """ if vid==None: return set(self._edges.keys()) return self.out_edges(vid, edge_type) | self.in_edges(vid, edge_type)
[docs] def iter_edges(self, vid, edge_type=None): """ Return in edges of the vertex vid If vid=None, return all edges of the graph :Parameters: - `vid` : a vertex id - `edges_type` : type of edges we want to consider :Returns -------- - `iterator` : an iterator on the set of the edges of the vertex vid """ return iter(self.edges(vid, edge_type))
[docs] def neighborhood(self, vid, max_distance=1, edge_type=None): """ Return the neighborhood of the vertex vid at distance max_distance (the disc, not the circle) :Parameters: - `vid` : vertex id :Returns -------- - `neighbors_list` : the set of the vertices at distance below max_distance of the vertex vid (including vid) """ dist=self.topological_distance(vid, edge_type=edge_type, max_depth=max_distance, full_dict=False) return set(dist.keys())
[docs] def iter_neighborhood(self, vid, n, edge_type=None): """ Return the neighborhood of the vertex vid at distance n (the disc, not the circle) :Parameters: - `vids` : a set of vertex id :Returns -------- - `iterator` : an iterator on the set of the vertices at distance n of the vertex vid """ return iter(self.neighborhood(vid, n, edge_type))
[docs] def topological_distance(self, vid, edge_type = None, edge_dist = lambda x,y : 1, max_depth=float('inf'), full_dict=True, return_inf = True): """ Return the distances of each vertices from the vertex `vid` according a cost function :Parameters: - `vid` (int) - a vertex id - `edges_type` (str) - type of edges we want to consider e.g. 's' or 't' - `edge_dist` (function) - the cost function - `max_depth` (float) - the maximum depth that we want to reach - `full_dict` (bool) - if True this function will return the entire dictionary (with inf values) - `return_inf` (bool) - if True (default) return 'inf' values, else 'nan'. :Returns -------- - `dist_dict` : a dictionary of the distances, key : vid, value : distance """ dist={} reduced_dist={} reduced_dist[vid]=0 Q=[] infinite_distance = float('inf') for k in self._vertices.keys(): dist[k] = infinite_distance heappush(Q, (dist[k], k)) dist[vid]=0 heappush(Q, (dist[vid], vid)) treated=set() modif=True n = self.nb_vertices() while (len(treated)!=n and modif): modif = False actualVid = heappop(Q) while actualVid[1] in treated and actualVid[0] == infinite_distance: actualVid = heappop(Q) if actualVid[0] != infinite_distance: actualVid = actualVid[1] treated.add(actualVid) for neighb in self.iter_neighbors(actualVid, edge_type): dist_neighb = dist[neighb] if (((dist_neighb == infinite_distance) or (dist_neighb > dist[actualVid] + edge_dist(neighb, actualVid))) and (dist[actualVid] + edge_dist(neighb, actualVid) < max_depth+1 ) ): dist_neighb = dist[actualVid] + edge_dist(neighb, actualVid) dist[neighb] = dist_neighb reduced_dist[neighb] = dist_neighb heappush(Q, (dist_neighb, neighb)) modif = True #~ return (reduced_dist, dist)[full_dict], Q if not return_inf: dist = dict( [(k,(v if v != infinite_distance else np.nan)) for k,v in dist.items()] ) return (reduced_dist, dist)[full_dict]
[docs] def adjacency_matrix(self, edge_type = None, edge_dist = 1, no_edge_val = 0, oriented = True, reflexive = True, reflexive_value = 0): """ Return the adjacency matrix of the graph. :Parameters: - `edge_type` : type of edges we want to consider - `edge_dist` : cost ot cost function to apply between two edges, default : 1 - `no_edge_val` : cost to put if there is no edge between two vertices, default : 0 - `oriented` : if True, the graph is considered oriented and we always add an edge j -> i if i -> j exists - `reflexive` : if True, the graph is considered reflexive and we will put the cost or the cost_function `reflexive_value` on the diagonal of the adjacency_matrix, default : 0 :Return: - `numpy.array` : a NxN matrix """ if not isinstance(edge_dist, type(lambda m: 1)): val_edge_dist = edge_dist edge_dist = lambda g, x, y : val_edge_dist if not isinstance(reflexive_value, type(lambda m: 1)): val_reflexive_value = reflexive_value reflexive_value = lambda g, x, y : val_reflexive_value n = self.nb_vertices() adjacency_matrix = np.array(n*[n*[no_edge_val]]) for edge in self.edges(edge_type=edge_type): v1, v2 = self.edge_vertices(edge) adjacency_matrix[v1, v2] = edge_dist(self, v1, v2) if not oriented: adjacency_matrix[v2, v1] = edge_dist(self, v2, v1) if reflexive: for i in range(n) : adjacency_matrix[i, i] = reflexive_value(self, i, i) return adjacency_matrix
[docs] def floyd_warshall(self, edge_type = None, edge_dist = 1, oriented = False): adjacency_matrix = self.adjacency_matrix(edge_type, edge_dist, float('inf'), oriented) n = self.nb_vertices() for k in range(n): for i in range(n): for j in range(n): adjacency_matrix[i, j]=min(adjacency_matrix[i, j], adjacency_matrix[i, k] + adjacency_matrix[k, j]) return adjacency_matrix
def _add_vertex_to_region(self, vids, region_name): """ Add a set of vertices to a region. Save it in two places: - self.graph_property[region_name] will return the list of all vertices belonging to 'region_name'; - self.vertex_property["regions"][vid] will return the list of all regions `vid` belong to. """ if not "regions" in self._vertex_property: self._vertex_property["regions"] = {} for vid in vids: # Adding region_name to the "region" property of each `vid`: if vid in self._vertex_property["regions"]: self._vertex_property["regions"][vid].append(region_name) else: self._vertex_property["regions"][vid]=[region_name] # Adding `vid` to the `region_name` (graph_property) it belong to: self._graph_property[region_name].append(vid) def _remove_vertex_from_region(self, vids, region_name): """Remove a set of vertices `vids` from a region `region_name`.""" for vid in vids: self._vertex_property["regions"][vid].remove(region_name) if self._vertex_property["regions"][vid]==[]: self._vertex_property["regions"].pop(vid) self._graph_property[region_name].remove(vid)
[docs] def add_vertex_to_region(self, vids, region_name): """ Add a set of vertices `vids` to a region `region_name`. Save it in two places: - self.graph_property[region_name] will return the list of all vertices belonging to 'region_name'; - self.vertex_property["regions"][vid] will return the list of all regions `vid` belong to. """ if not region_name in self._graph_property: #~ raise PropertyError("property %s is not defined on graph" % region_name) print("Property %s is not defined for vertices on the graph, adding it..." % region_name) self._graph_property[region_name] = vids self._add_vertex_to_region(self.__to_set(vids), region_name)
[docs] def remove_vertex_from_region(self, vids, region_name): """Remove a set of vertices `vids` from a region `region_name`.""" if not region_name in self._graph_property: raise PropertyError("property %s is not defined on graph" % region_name) self._remove_vertex_from_region(self.__to_set(vids), region_name)
[docs] def add_region_from_func(self, func, region_name): """ Create a region `region_name` of vertices according to a function `func`. :Parameters: - `func` : the function to make the region (might return True or False) - `region_name` : the name of the region """ if region_name in self._graph_property: raise PropertyError("property %s is already defined on graph" % region_name) self._graph_property[region_name]=[] if not "regions" in self._vertex_property.keys(): self.add_vertex_property("regions") for vid in self._vertices.keys(): if func(self, vid): self._add_vertex_to_region(set([vid]), region_name)
[docs] def add_regions_from_dict(self, dict_regions, region_names): """ If one already posses a dict indicating for a list of vertex which region they belong to, it can be given to the graph directly. :Parameters: - `dict_regions` (dict) - *keys = ids (SpatialImage); *values = intergers indicating the region(s) - `region_name` (list) - a list containing the name of the region(s) """ list_regions = np.unique(dict_regions.values()) if len(region_names) != len(list_regions): warnings.warn("You didn't provided the same number of regions and region names.") pass if not "regions" in self._vertex_property.keys(): self.add_vertex_property("regions") for region, region_name in enumerate(region_names): if region_name in self._graph_property: raise PropertyError("property %s is already defined on graph" % region_name) self._graph_property[region_name]=[] for vid in dict_regions: if dict_regions[vid] == list_regions[region]: self._add_vertex_to_region(set([vid]), region_name)
[docs] def iter_region(self, region_name): if not region_name in self._graph_property: raise PropertyError("property %s is not defined on graph" % region_name) return iter(self._graph_property[region_name])
[docs] def remove_region(self, region_name): """Remove a region `region_name`.""" if not region_name in self._graph_property: raise PropertyError("property %s is not defined on graph" % region_name) for vid in self.iter_region(region_name): self._vertex_property["regions"][vid].remove(region_name) if self._vertex_property["regions"][vid]==[]: self._vertex_property["regions"].pop(vid) return self._graph_property.pop(region_name)
[docs] def is_connected_region(self, region_name, edge_type=None): """Return True if a region is connected.""" if not region_name in self._graph_property: raise PropertyError("property %s is not defined on graph" % region_name) region_sub_graph=Graph.sub_graph(self, self._graph_property[region_name]) distances=region_sub_graph.topological_distance(region_sub_graph._vertices.keys()[0], edge_type=edge_type) return not float('inf') in distances.values()
[docs] def to_networkx(self): import networkx as nx """ Return a NetworkX Graph from a graph. :Parameters: - `g` - TemporalPropertyGraph (property graphs temporaly linked) :Returns -------- - A NetworkX graph. """ g = self graph = nx.Graph() graph.add_nodes_from(g.vertices()) graph.add_edges_from(( (g.source(eid), g.target(eid)) for eid in g.edges())) # Add graph, vertex and edge properties for k, v in g.graph_properties().items(): graph.graph[k] = v vp = g._vertex_property for prop in vp: for vid, value in vp[prop].items(): graph.node[vid][prop] = value ep = g._edge_property for eid in g.edges(): graph.edge[g.source(eid)][g.target(eid)]['eid'] = eid for prop in ep: for eid, value in ep[prop].items(): graph.edge[g.source(eid)][g.target(eid)][prop] = value return graph
[docs] def from_networkx(self, graph): """ Return a Graph from a NetworkX Directed graph. :Parameters: - `graph` : A NetworkX graph. :Returns: """ self.clear() g = self if not graph.is_directed(): graph = graph.to_directed() vp = self._vertex_property for vid in graph.nodes_iter(): g.add_vertex(vid) d = graph.node[vid] for k, v in d.items(): vp.setdefault(k,{})[vid] = v ep = self._edge_property for source, target in graph.edges_iter(): d = graph[source][target] eid = d.get('eid') eid = g.add_edge(source, target, eid) for k, v in d.items(): if k != 'eid': ep.setdefault(k,{})[eid] = v gp = self._graph_property gp.update(graph.graph) return g