コード例 #1
0
class RoadMap(object):
    def __init__(self, mapfile):
        self._mapfile = mapfile
        self.DIRECTION_index = 6
        self.PATHCLASS_index = 20
        self.g = Graph()
        self.g.edge_properties["length"] = self.g.new_edge_property("double")
        self.g.edge_properties["level"] = self.g.new_edge_property("int")
        self.g.vertex_properties["pos"] = self.g.new_vertex_property("vector<double>")
        self.cross_pos_index = {}

    def load(self):
        if self._mapfile[-3:] != 'shp':
            self.g = load_graph(self._mapfile)
            return

        try:
            sf = shapefile.Reader(self._mapfile)
        except Exception as e:
            print(str(e))
            return False
        roads_records = sf.shapeRecords()  # 获取路段信息'
        for road_record in roads_records:
            cross_s_index = self.add_cross(road_record.shape.points[0])
            cross_e_index = self.add_cross(road_record.shape.points[-1])
            self.add_road_edge(cross_s_index, cross_e_index, road_record)
            if int(road_record.record[self.DIRECTION_index]) == 0:  # 若路段是双向车道
                self.add_road_edge(cross_e_index, cross_s_index, road_record)
        return True

    def has_edge(self, s_vertex, e_vertex):
        if self.g.num_vertices() >= max(s_vertex, e_vertex):
            return self.g.edge(s_vertex, e_vertex)
        else:
            return None

    def add_cross(self, cross_pos):
        if cross_pos in self.cross_pos_index:
            return self.cross_pos_index.get(cross_pos)
        else:
            cross_index = self.g.add_vertex()
            self.g.vp.pos[cross_index] = cross_pos
            self.cross_pos_index[cross_pos] = cross_index
            return cross_index

    def add_road_edge(self, s_vertex, e_vertex, road):
        if self.has_edge(s_vertex, e_vertex):
            return self.g.edge(s_vertex, e_vertex)
        else:
            edge = self.g.add_edge(s_vertex, e_vertex)
            self.g.ep.level[edge] = int(road.record[self.PATHCLASS_index])
            self.g.ep.length[edge] = self.road_length(road)
            return edge

    @staticmethod
    def road_length(road):
        length = 0
        for sub_road in zip(road.shape.points[:-1], road.shape.points[1:]):
            length += distance.euclidean(sub_road[0], sub_road[1])
        return length
コード例 #2
0
def compose_graph(uid_pid_pairs):

    # set up graph
    g = Graph()
    g.vp['pid'] = v_pid_p = g.new_vertex_property('string')
    g.vp['count'] = v_count_p = g.new_vertex_property('int')
    g.ep['count'] = e_count_p = g.new_edge_property('int')

    pid_v_map = {}
    uid_last_v_map = {}
    vv_e_map = {}

    for uid, pid in uid_pid_pairs:

        # vertex

        v = pid_v_map.get(pid)
        if v is None:
            v = g.add_vertex()
            v_pid_p[v] = pid
            v_count_p[v] = 0
            pid_v_map[pid] = v
        v_count_p[v] += 1

        # edge

        last_v = uid_last_v_map.get(uid)
        uid_last_v_map[uid] = v
        if last_v is None:
            continue

        vv = (last_v, v)
        e = vv_e_map.get(vv)
        if e is None:
            e = g.add_edge(*vv)
            e_count_p[e] = 0
            vv_e_map[vv] = e
        e_count_p[e] += 1

    # calculate closeness
    g.vp['closeness'] = v_closeness_p = g.new_vertex_property('float')
    e_inverse_count_p = g.new_edge_property('int')
    e_inverse_count_p.a = e_count_p.a.max()-e_count_p.a
    debug('e_inverse_count_p.a: {}', e_inverse_count_p.a)
    closeness(g, weight=e_inverse_count_p, vprop=v_closeness_p)
    debug('v_closeness_p.a    : {}', v_closeness_p.a)
    v_closeness_p.a = nan_to_num(v_closeness_p.a)
    debug('v_closeness_p.a    : {}', v_closeness_p.a)

    # fillter
    g.vp['picked'] = v_picked_p = g.new_vertex_property('bool')
    debug('v_count_p.a.mean() : {}', v_count_p.a.mean())
    v_picked_p.a = v_count_p.a > v_count_p.a.mean()
    debug('v_picked_p.a       : {}', v_picked_p.a)
    g.set_vertex_filter(v_picked_p)
    g.set_vertex_filter(None)

    return g
コード例 #3
0
def gen_er(dicProperties):
	np.random.seed()
	# initialize graph
	graphER = Graph()
	nNodes = 0
	nEdges = 0
	rDens = 0.0
	if "Nodes" in dicProperties.keys():
		nNodes = dicProperties["Nodes"]
		graphER.add_vertex(nNodes)
		if "Edges" in dicProperties.keys():
			nEdges = dicProperties["Edges"]
			rDens = nEdges / float(nNodes**2)
			dicProperties["Density"] = rDens
		else:
			rDens = dicProperties["Density"]
			nEdges = int(np.floor(rDens*nNodes**2))
			dicProperties["Edges"] = nEdges
	else:
		nEdges = dicProperties["Edges"]
		rDens = dicProperties["Density"]
		nNodes = int(np.floor(np.sqrt(nEdges/rDens)))
		graphER.add_vertex(nNodes)
		dicProperties["Nodes"] = nNodes
	# generate edges
	numTest,numCurrentEdges = 0,0
	while numCurrentEdges != nEdges and numTest < n_MAXTESTS:
		lstEdges = np.random.randint(0,nNodes,(nEdges-numCurrentEdges,2))
		graphER.add_edge_list(lstEdges)
		# remove loops and duplicate edges
		remove_self_loops(graphER)
		remove_parallel_edges(graphER)
		numCurrentEdges = graphER.num_edges()
		numTest += 1
	graphER.reindex_edges()
	nEdges = graphER.num_edges()
	rDens = nEdges / float(nNodes**2)
	# generate types
	rInhibFrac = dicProperties["InhibFrac"]
	lstTypesGen = np.random.uniform(0,1,nEdges)
	lstTypeLimit = np.full(nEdges,rInhibFrac)
	lstIsExcitatory = np.greater(lstTypesGen,lstTypeLimit)
	nExc = np.count_nonzero(lstIsExcitatory)
	epropType = graphER.new_edge_property("int",np.multiply(2,lstIsExcitatory)-np.repeat(1,nEdges)) # excitatory (True) or inhibitory (False)
	graphER.edge_properties["type"] = epropType
	# and weights
	if dicProperties["Weighted"]:
		lstWeights = dicGenWeights[dicProperties["Distribution"]](graphER,dicProperties,nEdges,nExc) # generate the weights
		epropW = graphER.new_edge_property("double",lstWeights) # crée la propriété pour stocker les poids
		graphER.edge_properties["weight"] = epropW
	return graphER
コード例 #4
0
def build_minimum_tree(g, root, terminals, edges, directed=True):
    """remove redundant edges from `edges` so that root can reach each node in terminals
    """
    # build the tree
    t = Graph(directed=directed)

    for _ in range(g.num_vertices()):
        t.add_vertex()

    for (u, v) in edges:
        t.add_edge(u, v)

    # mask out redundant edges
    vis = init_visitor(t, root)
    pbfs_search(t, source=root, terminals=list(terminals), visitor=vis)

    minimum_edges = {
        e
        for u in terminals
        for e in extract_edges_from_pred(t, root, u, vis.pred)
    }
    # print(minimum_edges)
    efilt = t.new_edge_property('bool')
    efilt.a = False
    for u, v in minimum_edges:
        efilt[u, v] = True
    t.set_edge_filter(efilt)

    return filter_nodes_by_edges(t, minimum_edges)
コード例 #5
0
def build_closure(g, terminals, debug=False, verbose=False):
    terminals = list(terminals)
    # build closure
    gc = Graph(directed=False)
    gc.add_vertex(g.num_vertices())

    edges_with_weight = set()
    r2pred = {}

    for r in terminals:
        if debug:
            print('root {}'.format(r))
        vis = init_visitor(g, r)
        pbfs_search(g, source=r, terminals=terminals, visitor=vis)
        new_edges = set(get_edges(vis.dist, r, terminals))
        if debug:
            print('new edges {}'.format(new_edges))
        edges_with_weight |= new_edges
        r2pred[r] = vis.pred

    for u, v, c in edges_with_weight:
        gc.add_edge(u, v)

    eweight = gc.new_edge_property('int')
    weights = np.array([c for _, _, c in edges_with_weight])
    eweight.set_2d_array(weights)

    vfilt = gc.new_vertex_property('bool')
    vfilt.a = False
    for v in terminals:
        vfilt[v] = True
    gc.set_vertex_filter(vfilt)
    return gc, eweight, r2pred
コード例 #6
0
def build_minimum_tree(g, root, terminals, edges, directed=True):
    """remove redundant edges from `edges` so that root can reach each node in terminals
    """
    # build the tree
    t = Graph(directed=directed)

    for _ in range(g.num_vertices()):
        t.add_vertex()

    for (u, v) in edges:
        t.add_edge(u, v)

    # mask out redundant edges
    vis = init_visitor(t, root)
    pbfs_search(t, source=root, terminals=list(terminals), visitor=vis)

    minimum_edges = {e
                     for u in terminals
                     for e in extract_edges_from_pred(t, root, u, vis.pred)}
    # print(minimum_edges)
    efilt = t.new_edge_property('bool')
    efilt.a = False
    for u, v in minimum_edges:
        efilt[u, v] = True
    t.set_edge_filter(efilt)

    return filter_nodes_by_edges(t, minimum_edges)
コード例 #7
0
ファイル: languageGraphs.py プロジェクト: optas/graph_roles
def build_cooc_graph(coDic, posMap):
    '''    
    Converts a dictionary keeping word-word co-occurrences to a graph object where the edge weight
    between nodes (words) corresponds to their co-occurrence.

    Args:
        coOcDic: A dictionary where keys are tuples with 2 elements, (string1, string2) corresponding to the co-occurrence of two words. 
        The corresponding value is an integer capturing the times the co-occurrence happened (e.g., through out a book).
        posMap: A dictionary from word to Part Of Speech.
    Returns:
        A graph object.
    
    '''
    g = Graph(directed=False)
    wordToNodeID = dict(
    )  #maps a word to the ID of the node that it will be stored
    eWeight = g.new_edge_property(
        "int")  #edges have weights capturing number of co-occurrences
    words = g.new_vertex_property(
        "object"
    )  #keep for each node the (potentially unicode) corresponding word as an attribute
    POS = g.new_vertex_property("string")  #keep the Part Of Speech
    nodeID = 0
    for word1, word2 in coDic.keys(
    ):  #Each key is a (noun, noun) string. It will become an edge
        if word1 not in wordToNodeID:
            wordToNodeID[word1] = nodeID
            v = g.add_vertex()
            assert (str(v) == str(nodeID))
            words[v] = word1
            POS[v] = posMap[word1]
            nodeID += 1
        if word2 not in wordToNodeID:
            wordToNodeID[word2] = nodeID
            v = g.add_vertex()
            assert (str(v) == str(nodeID))
            words[v] = word2
            POS[v] = posMap[word2]
            nodeID += 1
        source = wordToNodeID[word1]
        target = wordToNodeID[word2]
        e = g.add_edge(source, target)
        eWeight[e] = coDic[(word1, word2)]

    g.edge_properties["co-occurrence"] = eWeight
    g.vertex_properties["word"] = words
    g.vertex_properties["partOfSpeach"] = POS

    #Encode the POS as a short number
    POS_encoded = g.new_vertex_property("short")
    posEncoder = part_of_speech_int_map(posToInt=True)

    for v in g.vertices():
        POS_encoded[v] = posEncoder[POS[v][0]]

    g.vertex_properties["partOfSpeach_encoded"] = POS_encoded

    return g
def build_closure(g, terminals, p=None, debug=False, verbose=False):
    """build the transitive closure on terminals"""
    def get_edges(dist, root, terminals):
        """get adjacent edges to root with weight"""
        return {(root, t, dist[t])
                for t in terminals if dist[t] != -1 and t != root}

    terminals = list(terminals)
    gc = Graph(directed=False)

    gc.add_vertex(g.num_vertices())

    edges_with_weight = set()
    r2pred = {}  # root to predecessor map (from bfs)

    # shortest path to all other nodes
    for r in terminals:
        if debug:
            print('root {}'.format(r))

        targets = list(set(terminals) - {r})
        dist_map, pred_map = shortest_distance(g,
                                               source=r,
                                               target=targets,
                                               weights=p,
                                               pred_map=True)
        dist_map = dict(zip(targets, dist_map))
        # print(dist_map)
        # print(pred_map)
        new_edges = get_edges(dist_map, r, targets)
        # if p is None:
        #     vis = init_visitor(g, r)
        #     bfs_search(g, source=r, visitor=vis)
        #     new_edges = set(get_edges(vis.dist, r, terminals))
        # else:
        #     print('weighted graph')

        if debug:
            print('new edges {}'.format(new_edges))
        edges_with_weight |= new_edges
        # r2pred[r] = vis.pred
        r2pred[r] = pred_map

    for u, v, c in edges_with_weight:
        gc.add_edge(u, v)

    # edge weights
    eweight = gc.new_edge_property('int')
    weights = np.array([c for _, _, c in edges_with_weight])
    eweight.set_2d_array(weights)

    vfilt = gc.new_vertex_property('bool')
    vfilt.a = False
    for v in terminals:
        vfilt[v] = True
    gc.set_vertex_filter(vfilt)
    return gc, eweight, r2pred
コード例 #9
0
ファイル: main.py プロジェクト: karlek/avant-graph
def main():
    """
    Visualizes the research network of KTH as a graph.
    """
    start_time = time()

    # Create our undirected graph to return.
    g = Graph(directed=False)
    # The edge properties measuring collaboration.
    e_times = g.new_edge_property("float")
    # Grouping value for the verticies, verticies are in the same group if the
    # have the same value.
    v_groups = g.new_vertex_property("int")
    # Color the verticies based on their faculties colors.
    v_colors = g.new_vertex_property("vector<double>")

    db_path = '/home/_/kth/kexet/db/kex.db'
    query = """SELECT *
               FROM final
               WHERE (
                 name LIKE '%kth%' and
                 name LIKE '%;%' and
                 keywords is not null and
                 year >= 2013 and
                 ContentType = 'Refereegranskat' and
                 PublicationType = 'Artikel i tidskrift'
               );"""
    rows = load.rows(db_path, query)
    for row in rows:
        nobjs = parse.names(row['name'].split(';'))
        graph.add_relation(g, nobjs, e_times, v_colors, v_groups)

    g.edge_properties["times"] = e_times
    g.vertex_properties["colors"] = v_colors
    g.vertex_properties["groups"] = v_groups

    log.info(g.num_vertices())
    log.info(g.num_edges())
    g.save('a.gt')
    log.info('graph saved: a.gt')
    log.info("db & parse %ss" % round(time() - start_time, 2))

    # start_time = time()
    # g = load_graph('a.gt')
    # log.info("loading %ss" % round(time() - start_time, 2))

    draw.largest(g.copy())
    draw.radial_highest(g.copy())
    draw.sfdp(g.copy())
    draw.grouped_sfdp(g.copy())
    draw.min_tree(g.copy())
    draw.radial_random(g.copy())
    draw.hierarchy(g.copy())
    draw.minimize_blockmodel(g.copy())
    draw.netscience(g.copy())
    draw.fruchterman(g.copy())
コード例 #10
0
def import_carribean_food_web_graph(save=True, export=True):
    saveLoadFolder = "Carribean_FoodWeb"
    graphFile = saveLoadPath + saveLoadFolder + "/Carribean_Adjacency_Matrix_raw.txt"
    g = Graph(directed=False)
    edgeWeights = g.new_edge_property("double")
    counter = -1

    with open(graphFile, "r") as inF:
        for line in inF:
            if line[0] == "#":  # This line is a header. Skip it.
                continue

            if counter == -1:  # First non header line revels all the species/categories.
                categories = line.split()
                num_nodes = int(len(categories))
                print num_nodes
                counter += 1
                g.add_vertex(num_nodes)
                continue

            splitted = line.split()
            category = splitted[0]
            assert (category == categories[counter])

            for neighbor, weight in enumerate(splitted[1:]):
                if weight != "0":
                    e = g.add_edge(g.vertex(neighbor),
                                   g.vertex(counter))  # Neighbor eats him.
                    edgeWeights[e] = float(weight)
            counter += 1

    taxaToInt = {"D": 0, "A": 1, "I": 2, "F": 3, "R": 4, "B": 5}
    troClass = g.new_vertex_property("int")
    for i, categ in enumerate(categories):
        troClass.a[i] = taxaToInt[categ[0]]

    g.vp["trophic_class"] = troClass
    g.ep["edge_weight"] = edgeWeights

    g = make_simple_graph(g, undirected=True, gcc=True)

    graphName = saveLoadFolder
    if save:
        save_data(
            saveLoadPath + saveLoadFolder + "/" + graphName + ".GT.graph", g)
        g.save(saveLoadPath + saveLoadFolder + "/" + graphName + ".graph.xml",
               fmt="xml")
    if export:
        from_GT_To_Greach(
            g,
            saveLoadPath + saveLoadFolder + "/" + graphName + ".greach.graph")
        from_GT_To_Snap(
            g, saveLoadPath + saveLoadFolder + "/" + graphName + ".snap.graph")

    return g
コード例 #11
0
def shortest_path_cover_logn_apx(g: gt.Graph, weight: gt.EdgePropertyMap):
    started_with_directed = g.is_directed()
    if not g.is_directed():
        reversed_edges = np.fliplr(g.get_edges())
        g.set_directed(True)
        g.add_edge_list(reversed_edges)
        weight.a[-reversed_edges.shape[0]:] = weight.a[:reversed_edges.
                                                       shape[0]]

    if weight.value_type() not in [
            "bool", "int", "int16_t", "int32_t", "int64_t"
    ]:
        #min = np.min(weight.a)
        #min_second = np.min(weight.a[weight.a > min])

        eps = 1  #min_second - min
        scaled_weight = (np.ceil(weight.a / eps) *
                         (g.num_vertices() + 1)).astype(np.int)  # ints >= 1
    else:
        scaled_weight = weight.a * (g.num_vertices() + 1)

    summed_edge_weight = np.sum(scaled_weight)

    adjusted_weight = g.new_edge_property("long", vals=scaled_weight - 1)

    paths = []

    covered_vertices = set()

    while len(covered_vertices) != g.num_vertices():
        curr_paths = shortest_path_visiting_most_nodes(g, adjusted_weight,
                                                       covered_vertices,
                                                       summed_edge_weight)

        for path in curr_paths:
            paths.append(path)

            #if len(path) <= 2 switch to fast mode and just add single edges/vertices until done.
            path_vertices = set(path)
            for v in path_vertices.difference(covered_vertices):
                for w in g.get_in_neighbors(v):
                    adjusted_weight[g.edge(w, v)] += 1  #.a[list()] -= 1
                    if adjusted_weight[g.edge(
                            w, v)] % (g.num_vertices() + 1) != 0:
                        exit(5)

            new_covered = path_vertices.difference(covered_vertices)
            covered_vertices = covered_vertices.union(path_vertices)
            print(len(new_covered), len(path), len(covered_vertices), path)
    if not started_with_directed:
        g.set_directed(False)
        for e in reversed_edges:
            g.remove_edge(g.edge(e[0], e[1]))
    return paths
コード例 #12
0
def co_graph_directed():
    '''co_graph_directed
    '''
    g = Graph(directed=True)
    g.add_vertex(2)
    edges = [(0, 1), (1, 0), (0, 2), (2, 0), (1, 2), (2, 1)]
    g.add_edge_list(edges)
    o = g.new_vertex_property('int')
    o.a = np.array([3, 4, 2])
    co = g.new_edge_property('int')
    co.a = np.array([2, 2, 1, 1, 2, 2])
    return g, o, co
コード例 #13
0
ファイル: Constructors.py プロジェクト: ChenghaoMou/NodeRank
    def largest_strongly_connected_component(self, graph):
        from graph_tool import Graph
        import graph_tool.all as gt

        largest_connected_component = Graph(directed=True)
        if not self.is_relationship:
            edge_prop_time = largest_connected_component.new_edge_property(
                "int")
            edge_prop_type = largest_connected_component.new_edge_property(
                "string")

        for edge in tqdm(graph.edges(data=True)):
            e = tuple(edge[:2])
            largest_connected_component.add_edge(e[0], e[1])
            if not self.is_relationship:
                edge_prop_time[e] = edge[-1]["time"]
                edge_prop_type[e] = edge[-1]["type"]

        largest_connected_component_view = gt.label_largest_component(
            largest_connected_component)
        largest_connected_component = gt.GraphView(
            largest_connected_component,
            vfilt=largest_connected_component_view)

        print(
            "Total nodes {0} in largest strongly connected component.".format(
                largest_connected_component.num_vertices()))
        print(
            "Total edges {0} in largest strongly connected component.".format(
                largest_connected_component.num_edges()))

        with open(self.output, "w+") as output_file:
            for edge in tqdm(largest_connected_component.edges()):
                if not self.is_relationship:
                    output_file.write("{0} {1} {2} {3}\n".format(
                        edge.source(), edge.target(), edge_prop_time[edge],
                        edge_prop_type[edge]))
                else:
                    output_file.write("{0} {1}\n".format(
                        edge.source(), edge.target()))
コード例 #14
0
ファイル: convert.py プロジェクト: golizheh/Drones4EnergyMain
def transform_nx_gt(g, rescale=False):
    from graph_tool import Graph
    from limic.util import haversine_distance
    h = Graph(directed=False)
    h.vp.id = h.new_vertex_property("int64_t")
    if rescale:
        h.vp.lat = h.new_vertex_property("int32_t")
        h.vp.long = h.new_vertex_property("int32_t")
        h.ep.weight = h.new_edge_property("int32_t")
    else:
        h.vp.lat = h.new_vertex_property("double")
        h.vp.long = h.new_vertex_property("double")
        h.ep.weight = h.new_edge_property("float")
    h.ep.type = h.new_edge_property("int32_t")
    h.gp.rescaled = h.new_graph_property("bool")
    h.gp.rescaled = rescale
    pos2vertex = {}
    intersection_id = 0
    for n in g.nodes():
        v = h.add_vertex()
        pos2vertex[n[1], n[2]] = v
        if n[0] < 0:
            intersection_id -= 1
            h.vp.id[v] = intersection_id
        else:
            h.vp.id[v] = n[0]
        h.vp.lat[v] = int(n[1] * 10000000) if rescale else n[1]
        h.vp.long[v] = int(n[2] * 10000000) if rescale else n[2]
    for n, m, d in g.edges.data(data=True):
        w = d['weight']
        air = d['type']
        e = h.add_edge(pos2vertex[n[1], n[2]], pos2vertex[m[1], m[2]])
        h.ep.type[e] = air
        if rescale and air < 0:
            w = haversine_distance(longx=n[2],
                                   latx=n[1],
                                   longy=m[2],
                                   laty=m[1])
        h.ep.weight[e] = int(w * 1000) if rescale else w
    return h
コード例 #15
0
ファイル: hdfgraph.py プロジェクト: DamCB/hdfgraph
def graph_from_dataframes(vertex_df, edge_df):
    '''Re-creates a Graph object with PropertyMaps taken
    from the vertex_df and edge_df DataFrames

    Paramters:
    ==========
    verex_df: a DataFrame with an index named 'vertex_index'
    edge_df: a DataFrame with a multi-index named ('source', 'target')

    Returns:
    ========
    graph: a grah-tool Graph with PropertyMaps copied
        from the columns of the input DataFrames
    '''

    graph = Graph(directed=True)

    vertex_index = vertex_df.index.get_level_values(level='vertex_index')
    vertices = graph.add_vertex(n=vertex_index.shape[0])
    for col in vertex_df.columns:
        in_type = vertex_df[col].dtype.name
        try:
            dtype = ALIASES[in_type]
        except KeyError:
            log.info('Data type {} not supported'.format(in_type))
            continue
        prop = graph.new_vertex_property(dtype)
        prop.fa = vertex_df[col]
        graph.vertex_properties[col] = prop

    src = edge_df.index.names.index('source')
    trgt = edge_df.index.names.index('target')
    ### TODO: use the list edge creation
    for tup in edge_df.index:
        source, target = tup[src], tup[trgt]
        try:
            edge = graph.add_edge(source, target)
        except ValueError:
            log.info('Invalid vertex in (source: {}, target: {})'.format(
                source, target))
    for col in edge_df.columns:
        in_type = edge_df[col].dtype.name
        try:
            dtype = ALIASES[in_type]
        except KeyError:
            log.info('Data type {} not supported'.format(in_type))
            continue
        prop = graph.new_edge_property(dtype)
        prop.fa = edge_df[col]
        graph.edge_properties[col] = prop

    return graph
コード例 #16
0
ファイル: hdfgraph.py プロジェクト: DamCB/hdfgraph
def graph_from_dataframes(vertex_df, edge_df):
    '''Re-creates a Graph object with PropertyMaps taken
    from the vertex_df and edge_df DataFrames

    Paramters:
    ==========
    verex_df: a DataFrame with an index named 'vertex_index'
    edge_df: a DataFrame with a multi-index named ('source', 'target')

    Returns:
    ========
    graph: a grah-tool Graph with PropertyMaps copied
        from the columns of the input DataFrames
    '''

    graph = Graph(directed=True)

    vertex_index = vertex_df.index.get_level_values(level='vertex_index')
    vertices = graph.add_vertex(n=vertex_index.shape[0])
    for col in vertex_df.columns:
        in_type = vertex_df[col].dtype.name
        try:
            dtype = ALIASES[in_type]
        except KeyError:
            log.info('Data type {} not supported'.format(in_type))
            continue
        prop = graph.new_vertex_property(dtype)
        prop.fa = vertex_df[col]
        graph.vertex_properties[col] = prop

    src = edge_df.index.names.index('source')
    trgt = edge_df.index.names.index('target')
    ### TODO: use the list edge creation
    for tup in edge_df.index:
        source, target = tup[src], tup[trgt]
        try:
            edge = graph.add_edge(source, target)
        except ValueError:
            log.info('Invalid vertex in (source: {}, target: {})'.format(source, target))
    for col in edge_df.columns:
        in_type = edge_df[col].dtype.name
        try:
            dtype = ALIASES[in_type]
        except KeyError:
            log.info('Data type {} not supported'.format(in_type))
            continue
        prop = graph.new_edge_property(dtype)
        prop.fa = edge_df[col]
        graph.edge_properties[col] = prop

    return graph
コード例 #17
0
def basic_graph():
    """"""

    G = Graph()

    v0 = G.add_vertex()
    v1 = G.add_vertex()
    v2 = G.add_vertex()
    v3 = G.add_vertex()
    v4 = G.add_vertex()
    v5 = G.add_vertex()
    v6 = G.add_vertex()
    v7 = G.add_vertex()

    e0 = G.add_edge(v0, v1)
    e1 = G.add_edge(v0, v2)
    e2 = G.add_edge(v0, v3)
    e3 = G.add_edge(v0, v4)
    e4 = G.add_edge(v5, v4)
    e5 = G.add_edge(v6, v4)
    e6 = G.add_edge(v4, v7)

    prop_v = G.new_vertex_property('string')
    prop_e = G.new_edge_property('string')

    G.vertex_properties['name'] = prop_v
    G.edge_properties['c0'] = prop_e

    prop_v[v0] = '/John'
    prop_v[v1] = '*****@*****.**'
    prop_v[v2] = '*****@*****.**'
    prop_v[v3] = '/Researcher'
    prop_v[v4] = '/Rome'
    prop_v[v5] = '/Giacomo'
    prop_v[v6] = '/Piero'
    prop_v[v7] = '"Roma"@it'

    prop_e[e0] = 'foaf:mbox'
    prop_e[e1] = 'foaf:mbox'
    prop_e[e2] = 'rdf:type'
    prop_e[e3] = 'ex:birthPlace'
    prop_e[e4] = 'ex:areaOfWork'
    prop_e[e5] = 'ex:areaOfWork'
    prop_e[e6] = 'foaf:name'

    return G
コード例 #18
0
def load_graph(infile):
    inmatrix = np.loadtxt(infile, dtype=np.dtype('uint32'), delimiter=" ")
    numv = np.amax(inmatrix[:,0:2])

    #print numv, inmatrix[:,0:2]

    g = Graph(directed=False)
    edge_weights = g.new_edge_property("double")
    g.edge_properties["weights"] = edge_weights
    vlist = list(g.add_vertex(numv))

    for i in inmatrix:
        edge = g.add_edge(vlist[i[0]-1], vlist[i[1]-1]) # need to convert from 1-based index in file to 0-based
        edge_weights[edge] = i[2]

    remove_parallel_edges(g)
    return g
def g():
    g = Graph(directed=True)
    g.add_vertex(4)
    g.add_edge_list([(0, 1), (1, 0), (1, 3), (3, 1), (0, 2), (2, 0), (2, 3),
                     (3, 2)])
    weights = g.new_edge_property('float')
    weights[g.edge(0, 1)] = 0.9
    weights[g.edge(1, 0)] = 0.7

    weights[g.edge(1, 3)] = 0.8
    weights[g.edge(3, 1)] = 0.2

    weights[g.edge(2, 3)] = 0.4
    weights[g.edge(3, 2)] = 0.3

    weights[g.edge(0, 2)] = 0.1
    weights[g.edge(2, 0)] = 0.4
    g.edge_properties['weights'] = weights
    return g
コード例 #20
0
def build_closure(g, terminals, debug=False, verbose=False):
    """build the transitive closure on terminals"""
    def get_edges(dist, root, terminals):
        """get adjacent edges to root with weight"""
        return ((root, t, dist[t]) for t in terminals
                if dist[t] != -1 and t != root)

    terminals = list(terminals)
    gc = Graph(directed=False)

    gc.add_vertex(g.num_vertices())

    edges_with_weight = set()
    r2pred = {}  # root to predecessor map (from bfs)

    # bfs to all other nodes
    for r in terminals:
        if debug:
            print('root {}'.format(r))
        vis = init_visitor(g, r)
        bfs_search(g, source=r, visitor=vis)
        new_edges = set(get_edges(vis.dist, r, terminals))
        if debug:
            print('new edges {}'.format(new_edges))
        edges_with_weight |= new_edges
        r2pred[r] = vis.pred

    for u, v, c in edges_with_weight:
        gc.add_edge(u, v)

    # edge weights
    eweight = gc.new_edge_property('int')
    weights = np.array([c for _, _, c in edges_with_weight])
    eweight.set_2d_array(weights)

    #
    vfilt = gc.new_vertex_property('bool')
    vfilt.a = False
    for v in terminals:
        vfilt[v] = True
    gc.set_vertex_filter(vfilt)
    return gc, eweight, r2pred
コード例 #21
0
ファイル: _networks.py プロジェクト: harius/twitterology
def user_network(storage, track, session):
    g = Graph()
    users = defaultdict(g.add_vertex)

    g.graph_properties["track"] = g.new_graph_property("string", track)
    g.graph_properties["session"] = g.new_graph_property("string", session)

    g.edge_properties["created_at"] = g.new_edge_property("int64_t")

    for tweet in storage:
        tweeter_id = tweet["user__id_str"]
        origin_id = tweet["retweeted_status__user__id_str"]

        created_at = arrow.get(tweet["created_at"], DATE_FORMAT).timestamp

        if origin_id:
            edge = g.add_edge(users[tweeter_id], users[origin_id])
            g.edge_properties["created_at"][edge] = created_at

    return g
コード例 #22
0
ファイル: hdfgraph.py プロジェクト: glyg/hdfgraph
def graph_from_dataframes(vertex_df, edge_df):
    '''Re-creates a Graph object with PropertyMaps taken
    from the vertex_df and edge_df DataFrames

    Paramters:
    ==========
    verex_df: a DataFrame with an index named 'vertex_index'
    edge_df: a DataFrame with a multi-index named ('source', 'target')

    Returns:
    ========
    graph: a grah-tool Graph with PropertyMaps copied
        from the columns of the input DataFrames
    '''

    graph = Graph(directed=True)

    vertex_index = vertex_df.index.get_level_values(level='vertex_index')
    vertices = graph.add_vertex(n=vertex_index.shape[0])
    for col in vertex_df.columns:
        dtype = ALIASES[vertex_df[col].dtype.name]
        prop = graph.new_vertex_property(dtype)
        prop.a = vertex_df[col]
        graph.vertex_properties[col] = prop

    src = edge_df.index.names.index('source')
    trgt = edge_df.index.names.index('target')
    ### TODO: use the list edge creation
    for tup in edge_df.index:
        source, target = tup[src], tup[trgt]
        edge = graph.add_edge(source, target)

    for col in edge_df.columns:
        dtype = ALIASES[edge_df[col].dtype.name]
        prop = graph.new_edge_property(dtype)
        prop.a = edge_df[col]
        graph.edge_properties[col] = prop
    return graph
コード例 #23
0
def build_closure(g, terminals,
                  debug=False,
                  verbose=False):
    terminals = list(terminals)
    # build closure
    gc = Graph(directed=False)

    for _ in range(g.num_vertices()):
        gc.add_vertex()

    edges_with_weight = set()
    r2pred = {}

    for r in terminals:
        if debug:
            print('root {}'.format(r))
        vis = init_visitor(g, r)
        pbfs_search(g, source=r, terminals=terminals, visitor=vis)
        new_edges = set(get_edges(vis.dist, r, terminals))
        if debug:
            print('new edges {}'.format(new_edges))
        edges_with_weight |= new_edges
        r2pred[r] = vis.pred
    
    for u, v, c in edges_with_weight:
        gc.add_edge(u, v)
        
    eweight = gc.new_edge_property('int')
    weights = np.array([c for _, _, c in edges_with_weight])
    eweight.set_2d_array(weights)

    vfilt = gc.new_vertex_property('bool')
    vfilt.a = False
    for v in terminals:
        vfilt[v] = True
    gc.set_vertex_filter(vfilt)
    return gc, eweight, r2pred
コード例 #24
0
    def makeGraph(self, img, dia, xScale, yScale):
        print 'Building Graph Data Structure'
        start = time.time()
        G = Graph(directed=False)
        vprop = G.new_vertex_property('object')
        eprop = G.new_edge_property('object')
        epropW = G.new_edge_property("int32_t")
        avgScale = (xScale + yScale) / 2

        test = np.where(img == True)
        ss = np.shape(test)
        cccc = 0
        percentOld = 0.0
        print str(np.round(percentOld, 1)) + '%'
        for (i, j) in zip(test[1], test[0]):
            cccc += 1
            percent = (float(cccc) / float(ss[1])) * 100
            if percentOld + 10 < percent:
                print str(np.round(percent, 1)) + '%'
                percentOld = percent
            nodeNumber1 = (float(i) * yScale, float(j) * xScale)
            if gu.find_vertex(
                    G, vprop, {
                        'imgIdx': (j, i),
                        'coord': nodeNumber1,
                        'nrOfPaths': 0,
                        'diameter': float(dia[j][i]) * avgScale
                    }):
                v1 = gu.find_vertex(
                    G, vprop, {
                        'imgIdx': (j, i),
                        'coord': nodeNumber1,
                        'nrOfPaths': 0,
                        'diameter': float(dia[j][i]) * avgScale
                    })[0]
            else:
                v1 = G.add_vertex()
                vprop[G.vertex(v1)] = {
                    'imgIdx': (j, i),
                    'coord': nodeNumber1,
                    'nrOfPaths': 0,
                    'diameter': float(dia[j][i]) * avgScale
                }
            try:

                if img[j, i + 1] == True:
                    nodeNumber2 = (float(i + 1) * yScale, float(j) * xScale)
                    if gu.find_vertex(
                            G, vprop, {
                                'imgIdx': (j, i + 1),
                                'coord': nodeNumber2,
                                'nrOfPaths': 0,
                                'diameter': float(dia[j][i + 1]) * avgScale
                            }):
                        v2 = gu.find_vertex(
                            G, vprop, {
                                'imgIdx': (j, i + 1),
                                'coord': nodeNumber2,
                                'nrOfPaths': 0,
                                'diameter': float(dia[j][i + 1]) * avgScale
                            })[0]
                        if gu.find_edge(
                                G, eprop, {
                                    'coord1':
                                    vprop[v2]['coord'],
                                    'coord2':
                                    vprop[v1]['coord'],
                                    'weight': ((vprop[v1]['diameter'] +
                                                vprop[v2]['diameter']) / 2)**4,
                                    'RTP':
                                    False
                                }):
                            pass
                        else:
                            e = G.add_edge(v1, v2)
                            epropW[e] = (((vprop[v1]['diameter'] +
                                           vprop[v2]['diameter']) / 2) /
                                         avgScale)**4
                            eprop[e] = {
                                'coord1':
                                vprop[v1]['coord'],
                                'coord2':
                                vprop[v2]['coord'],
                                'weight': ((vprop[v1]['diameter'] +
                                            vprop[v2]['diameter']) / 2)**4,
                                'RTP':
                                False
                            }
                    else:
                        v2 = G.add_vertex()
                        vprop[G.vertex(v2)] = {
                            'imgIdx': (j, i + 1),
                            'coord': nodeNumber2,
                            'nrOfPaths': 0,
                            'diameter': float(dia[j][i + 1]) * avgScale
                        }
                        e = G.add_edge(v1, v2)
                        epropW[e] = (
                            ((vprop[v1]['diameter'] + vprop[v2]['diameter']) /
                             2) / avgScale)**4
                        eprop[e] = {
                            'coord1':
                            vprop[v1]['coord'],
                            'coord2':
                            vprop[v2]['coord'],
                            'weight':
                            ((vprop[v1]['diameter'] + vprop[v2]['diameter']) /
                             2)**4,
                            'RTP':
                            False
                        }
            except:
                pass
            try:
                if img[j, i - 1] == True:
                    nodeNumber2 = (float(i - 1) * yScale, float(j) * xScale)
                    if gu.find_vertex(
                            G, vprop, {
                                'imgIdx': (j, i - 1),
                                'coord': nodeNumber2,
                                'nrOfPaths': 0,
                                'diameter': float(dia[j][i - 1]) * avgScale
                            }):
                        v2 = gu.find_vertex(
                            G, vprop, {
                                'imgIdx': (j, i - 1),
                                'coord': nodeNumber2,
                                'nrOfPaths': 0,
                                'diameter': float(dia[j][i - 1]) * avgScale
                            })[0]
                        if gu.find_edge(
                                G, eprop, {
                                    'coord1':
                                    vprop[v2]['coord'],
                                    'coord2':
                                    vprop[v1]['coord'],
                                    'weight': ((vprop[v1]['diameter'] +
                                                vprop[v2]['diameter']) / 2)**4,
                                    'RTP':
                                    False
                                }):
                            pass
                        else:
                            e = G.add_edge(v1, v2)
                            epropW[e] = (((vprop[v1]['diameter'] +
                                           vprop[v2]['diameter']) / 2) /
                                         avgScale)**4
                            eprop[e] = {
                                'coord1':
                                vprop[v1]['coord'],
                                'coord2':
                                vprop[v2]['coord'],
                                'weight': ((vprop[v1]['diameter'] +
                                            vprop[v2]['diameter']) / 2)**4,
                                'RTP':
                                False
                            }
                    else:
                        v2 = G.add_vertex()
                        vprop[G.vertex(v2)] = {
                            'imgIdx': (j, i - 1),
                            'coord': nodeNumber2,
                            'nrOfPaths': 0,
                            'diameter': float(dia[j][i - 1]) * avgScale
                        }
                        e = G.add_edge(v1, v2)
                        epropW[e] = (
                            ((vprop[v1]['diameter'] + vprop[v2]['diameter']) /
                             2) / avgScale)**4
                        eprop[e] = {
                            'coord1':
                            vprop[v1]['coord'],
                            'coord2':
                            vprop[v2]['coord'],
                            'weight':
                            ((vprop[v1]['diameter'] + vprop[v2]['diameter']) /
                             2)**4,
                            'RTP':
                            False
                        }
            except:
                pass
            try:
                if img[j + 1, i] == True:
                    nodeNumber2 = (float(i) * yScale, float(j + 1) * xScale)
                    if gu.find_vertex(
                            G, vprop, {
                                'imgIdx': (j + 1, i),
                                'coord': nodeNumber2,
                                'nrOfPaths': 0,
                                'diameter': float(dia[j + 1][i]) * avgScale
                            }):
                        v2 = gu.find_vertex(
                            G, vprop, {
                                'imgIdx': (j + 1, i),
                                'coord': nodeNumber2,
                                'nrOfPaths': 0,
                                'diameter': float(dia[j + 1][i]) * avgScale
                            })[0]
                        if gu.find_edge(
                                G, eprop, {
                                    'coord1':
                                    vprop[v2]['coord'],
                                    'coord2':
                                    vprop[v1]['coord'],
                                    'weight': ((vprop[v1]['diameter'] +
                                                vprop[v2]['diameter']) / 2)**4,
                                    'RTP':
                                    False
                                }):
                            pass
                        else:
                            e = G.add_edge(v1, v2)
                            epropW[e] = (((vprop[v1]['diameter'] +
                                           vprop[v2]['diameter']) / 2) /
                                         avgScale)**4
                            eprop[e] = {
                                'coord1':
                                vprop[v1]['coord'],
                                'coord2':
                                vprop[v2]['coord'],
                                'weight': ((vprop[v1]['diameter'] +
                                            vprop[v2]['diameter']) / 2)**4,
                                'RTP':
                                False
                            }
                    else:
                        v2 = G.add_vertex()
                        vprop[G.vertex(v2)] = {
                            'imgIdx': (j + 1, i),
                            'coord': nodeNumber2,
                            'nrOfPaths': 0,
                            'diameter': float(dia[j + 1][i]) * avgScale
                        }
                        e = G.add_edge(v1, v2)
                        epropW[e] = (
                            ((vprop[v1]['diameter'] + vprop[v2]['diameter']) /
                             2) / avgScale)**4
                        eprop[e] = {
                            'coord1':
                            vprop[v1]['coord'],
                            'coord2':
                            vprop[v2]['coord'],
                            'weight':
                            ((vprop[v1]['diameter'] + vprop[v2]['diameter']) /
                             2)**4,
                            'RTP':
                            False
                        }
            except:
                pass
            try:
                if img[j - 1, i] == True:
                    nodeNumber2 = (float(i) * yScale, float(j - 1) * xScale)
                    if gu.find_vertex(
                            G, vprop, {
                                'imgIdx': (j - 1, i),
                                'coord': nodeNumber2,
                                'nrOfPaths': 0,
                                'diameter': float(dia[j - 1][i]) * avgScale
                            }):
                        v2 = gu.find_vertex(
                            G, vprop, {
                                'imgIdx': (j - 1, i),
                                'coord': nodeNumber2,
                                'nrOfPaths': 0,
                                'diameter': float(dia[j - 1][i]) * avgScale
                            })[0]
                        if gu.find_edge(
                                G, eprop, {
                                    'coord1':
                                    vprop[v2]['coord'],
                                    'coord2':
                                    vprop[v1]['coord'],
                                    'weight': ((vprop[v1]['diameter'] +
                                                vprop[v2]['diameter']) / 2)**4,
                                    'RTP':
                                    False
                                }):
                            pass
                        else:
                            e = G.add_edge(v1, v2)
                            epropW[e] = (((vprop[v1]['diameter'] +
                                           vprop[v2]['diameter']) / 2) /
                                         avgScale)**4
                            eprop[e] = {
                                'coord1':
                                vprop[v1]['coord'],
                                'coord2':
                                vprop[v2]['coord'],
                                'weight': ((vprop[v1]['diameter'] +
                                            vprop[v2]['diameter']) / 2)**4,
                                'RTP':
                                False
                            }
                    else:
                        v2 = G.add_vertex()
                        vprop[G.vertex(v2)] = {
                            'imgIdx': (j - 1, i),
                            'coord': nodeNumber2,
                            'nrOfPaths': 0,
                            'diameter': float(dia[j - 1][i]) * avgScale
                        }
                        e = G.add_edge(v1, v2)
                        epropW[e] = (
                            ((vprop[v1]['diameter'] + vprop[v2]['diameter']) /
                             2) / avgScale)**4
                        eprop[e] = {
                            'coord1':
                            vprop[v1]['coord'],
                            'coord2':
                            vprop[v2]['coord'],
                            'weight':
                            ((vprop[v1]['diameter'] + vprop[v2]['diameter']) /
                             2)**4,
                            'RTP':
                            False
                        }
            except:
                pass
#
        print '100.0%'
        print 'selecting largest connected component'
        G.edge_properties["ep"] = eprop
        G.edge_properties["w"] = epropW
        G.vertex_properties["vp"] = vprop
        l = gt.label_largest_component(G)
        print(l.a)
        u = gt.GraphView(G, vfilt=l)
        print '# vertices'
        print(u.num_vertices())
        print(G.num_vertices())
        print '# edges'
        print(u.num_edges())
        print 'building graph finished in: ' + str(time.time() - start) + 's'
        return u
コード例 #25
0
ファイル: buffer.py プロジェクト: yssource/obvz
class ob_viz(QWidget):
    def __init__(self, bg_color):
        QWidget.__init__(self)

        self.background_color = bg_color
        self.c = 0

        # K = 0.5
        # how many iterations the realignment is supposed to take
        self.step = 15
        self.rwr_c = 0

        # dumper([qt_coords])
        dumper(['obv viz init'])
        # self.show()

        # with open("/tmp/eaf3.csv", "a") as fo:
        #     wr = csv.writer(fo)
        #     wr.writerow([self.c, "runs4"])
        # dumper([self.c, "runs4"])

        # self.node_names [g_id[i] for i in g.vertices()]

    def init2(self, emacs_var_dict):
        self.emacs_var_dict = emacs_var_dict

        self.link_str = self.emacs_var_dict['links']
        self.g = Graph()
        self.label_ep = self.g.new_edge_property("string")
        self.links = self.link_str.split(";")

        link_tpls = [i.split(" -- ") for i in self.links]
        dumper([str(i) for i in link_tpls])

        self.g_id = self.g.add_edge_list(link_tpls,
                                         hashed=True,
                                         string_vals=True,
                                         eprops=[self.label_ep])

        self.adj = np.array([(int(i.source()), int(i.target()))
                             for i in self.g.edges()])
        self.node_names = [self.g_id[i] for i in self.g.vertices()]

        self.vd = {}
        for i in self.g.vertices():
            self.vd[self.g_id[i]] = int(i)

        # self.pos_vp = sfdp_layout(self.g, K=0.5)
        self.pos_vp = fruchterman_reingold_layout(self.g)
        self.base_pos_ar = self.pos_vp.get_2d_array((0, 1)).T
        self.qt_coords = self.nolz_pos_ar(self.base_pos_ar)

        dumper([str(self.qt_coords)])

        # dumper([link_str])

    def update_graph(self, emacs_var_dict):
        """set new links and nodes"""
        new_link_str = emacs_var_dict['links']
        new_links = new_link_str.split(";")
        new_link_tpls = [i.split(" -- ") for i in new_links]

        links_to_add = list(set(new_links) - set(self.links))
        links_to_del = list(set(self.links) - set(new_links))

        # setting new stuff
        self.links = new_links

        new_nodes = []
        for tpl in new_link_tpls:
            new_nodes.append(tpl[0])
            new_nodes.append(tpl[1])

        new_nodes_unique = list(set(new_nodes))

        nodes_to_del = list(set(self.node_names) - set(new_nodes_unique))
        nodes_to_add = list(set(new_nodes_unique) - set(self.node_names))

        dumper([
            "nodes_to_add: ", nodes_to_add, "nodes_to_del: ", nodes_to_del,
            "links_to_add: ", links_to_add, "links_to_del: ", links_to_del
        ])

        # first add nodes + index them, but not there yet (first links)

        for n in nodes_to_add:
            dumper(['adding node'])
            v = self.g.add_vertex()
            # how to new nodes pos to parents? separate loop afterwards
            self.vd[n] = int(v)
            self.g_id[v] = n

        del_node_ids = [self.vd[i] for i in nodes_to_del]
        self.g.remove_vertex(del_node_ids)

        # have to reindex after deletion
        self.vd = {}
        for i in self.g.vertices():
            self.vd[self.g_id[i]] = int(i)

        dumper(['node deleted'])
        # nodes_to_del_id =

        # dumper(['old nodes deleted, add new links'])

        for l in links_to_add:
            tpl = l.split(" -- ")
            n0, n1 = tpl[0], tpl[1]
            self.g.add_edge(self.vd[n0], self.vd[n1])

        # dumper(['new links added, delete old links'])

        for l in links_to_del:
            tpl = l.split(" -- ")
            n0 = tpl[0]
            n1 = tpl[1]
            dumper([list(self.vd.keys())])
            # only remove edge when neither of nodes removed
            if n0 in self.vd.keys() and n1 in self.vd.keys():
                self.g.remove_edge(self.g.edge(self.vd[n0], self.vd[n1]))

        # dumper(['graph modifications done'])

        # set positions of new nodes to parent nodes
        for n in nodes_to_add:
            v = self.g.vertex(self.vd[n])
            v_prnt = list(v.all_neighbors())[0]
            self.pos_vp[v] = self.pos_vp[v_prnt]

        # dumper(['node positions adjusted'])

        self.adj = np.array([(int(i.source()), int(i.target()))
                             for i in self.g.edges()])
        self.node_names = [self.g_id[i] for i in self.g.vertices()]

        # dumper(['storage objects updated'])

        # dumper(["nbr_edges new: ", str(len([i for i in self.g.edges()]))])
        # dumper(['nodes_to_add'] + nodes_to_add)
        # seems to work
        dumper(['to here'])

        self.recalculate_layout()
        dumper(['to here2'])

    def recalculate_layout(self):
        """calculate new change_array, set rwr_c counter"""
        dumper(['recalculating starting'])
        self.base_pos_ar = self.pos_vp.get_2d_array((0, 1)).T

        # set_dict = {'p': 2, 'max_level': 20, 'adaptive_cooling': False,
        #             'gamma': 1, 'theta': 1, 'cooling_step': 0.3, 'C': 0.6, 'mu_p': 1.2}

        # self.goal_vp = sfdp_layout(self.g, K=0.5, pos=self.pos_vp, **set_dict)
        self.goal_vp = fruchterman_reingold_layout(self.g, pos=self.pos_vp)

        goal_ar = self.goal_vp.get_2d_array([0, 1]).T
        self.chng_ar = (goal_ar - self.base_pos_ar) / self.step

        self.rwr_c = self.step
        dumper(["base_pos_ar: ", self.base_pos_ar])
        dumper(["goal_ar: ", goal_ar])
        dumper(["chng_ar: ", self.chng_ar])
        dumper(['recalculating done'])

    def redraw_layout(self):
        """actually do the drawing, run multiple (step (rwr_c)) times"""
        self.cur_pos_ar = np.round(
            self.base_pos_ar + self.chng_ar * (self.step - self.rwr_c), 3)
        self.qt_coords = self.nolz_pos_ar(self.cur_pos_ar)

        self.rwr_c -= 1
        self.update()
        # dumper(['redrawing'])

    # def draw_arrow(qp, p1x, p1y, p2x, p2y):
    def draw_arrow(self, qp, p1x, p1y, p2x, p2y, node_width):
        """draw arrow from p1 to rad units before p2"""
        # get arrow angle, counterclockwise from center -> east line

        # dumper(['painting time'])
        angle = degrees(atan2((p1y - p2y), (p1x - p2x)))

        # calculate attach point
        arw_goal_x = p2x + node_width * cos(radians(angle))
        arw_goal_y = p2y + node_width * sin(radians(angle))

        # calculate start point: idk how trig works but does
        start_px = p1x - node_width * cos(radians(angle))
        start_py = p1y - node_width * sin(radians(angle))

        # arrow stuff: +/- 30 deg
        ar1 = angle + 25
        ar2 = angle - 25

        arw_len = 10

        # need to focus on vector from p2 to p1
        ar1_x = arw_goal_x + arw_len * cos(radians(ar1))
        ar1_y = arw_goal_y + arw_len * sin(radians(ar1))

        ar2_x = arw_goal_x + arw_len * cos(radians(ar2))
        ar2_y = arw_goal_y + arw_len * sin(radians(ar2))

        # qp.drawLine(p1x, p1y, p2x, p2y)
        # qp.drawLine(p1x, p1y, arw_goal_x, arw_goal_y)
        qp.drawLine(start_px, start_py, arw_goal_x, arw_goal_y)
        qp.drawLine(ar1_x, ar1_y, arw_goal_x, arw_goal_y)
        qp.drawLine(ar2_x, ar2_y, arw_goal_x, arw_goal_y)

    def paintEvent(self, event):
        # dumper(['start painting'])
        node_width = 10
        qp = QPainter(self)
        edges = [(self.qt_coords[i[0]], self.qt_coords[i[1]])
                 for i in self.adj]
        # dumper([str(i) for i in edges])

        qp.setPen(QPen(Qt.green, 2, Qt.SolidLine))

        # [qp.drawLine(e[0][0], e[0][1], e[1][0], e[1][1]) for e in edges]
        [
            self.draw_arrow(qp, e[0][0], e[0][1], e[1][0], e[1][1],
                            (node_width / 2) + 5) for e in edges
        ]

        qp.setPen(QColor(168, 34, 3))
        # qp.setPen(Qt.green)
        qp.setFont(QFont('Decorative', 10))
        [
            qp.drawText(t[0][0] + node_width, t[0][1], t[1])
            for t in zip(self.qt_coords, self.node_names)
        ]
        # dumper(['done painting'])

        qp.setPen(QPen(Qt.black, 3, Qt.SolidLine))
        # qp.setBrush(QBrush(Qt.green, Qt.SolidPattern))

        dumper(['painting nodes'])

        for i in zip(self.qt_coords, self.node_names):
            if self.emacs_var_dict['cur_node'] == i[1]:
                qp.setPen(QPen(Qt.black, 4, Qt.SolidLine))
                qp.drawEllipse(i[0][0] - (node_width / 2),
                               i[0][1] - (node_width / 2), node_width,
                               node_width)
                qp.setPen(QPen(Qt.black, 3, Qt.SolidLine))

            else:
                qp.drawEllipse(i[0][0] - (node_width / 2),
                               i[0][1] - (node_width / 2), node_width,
                               node_width)

        # qp.drawEllipse(self.c, self.c, 7, 7)
        # qp.end()

    def nolz_pos_ar(self, pos_ar_org):
        """normalize pos ar to window limits"""

        # pos_ar_org = goal_ar

        size = self.size()

        limits = [[20, size.width() - 50], [20, size.height() - 20]]

        x_max = max(pos_ar_org[:, 0])
        x_min = min(pos_ar_org[:, 0])
        y_max = max(pos_ar_org[:, 1])
        y_min = min(pos_ar_org[:, 1])

        # need linear maping function again
        pos_ar2 = pos_ar_org

        pos_ar2[:, 0] = (((pos_ar2[:, 0] - x_min) / (x_max - x_min)) *
                         (limits[0][1] - limits[0][0])) + limits[0][0]
        pos_ar2[:, 1] = (((pos_ar2[:, 1] - y_min) / (y_max - y_min)) *
                         (limits[1][1] - limits[1][0])) + limits[1][0]

        return (pos_ar2)
コード例 #26
0
    for request_count in range(number_requests):
        request = []
        temp_source = randint(0,13)
        request.append(temp_source)
        while(1):
            temp_target = randint(0, 13)
            if(not(temp_target == temp_source)):
                request.append(temp_target)
                break
        if not(request in all_requests):
            all_requests.append(request)

    #print("Number of requests are " + str(len(all_requests)))

## Defining the graph properties ##
graph_weight = g.new_edge_property("float")
g.ep.weight = graph_weight

graph_pred_tree = g.new_vertex_property("int")
pred_tree = graph_pred_tree

edges_logger = {}

for e in g.edges():
    flags_of_edges = []
    # Temporary flag to ensure that alternative path is not on the primary path itself
    flags_of_edges.append(1)
    # Flags to see which channels are currently in use
    for i in range(number_frequency_bands):
        flags_of_edges.append(1)
    # Flags to keep record of the extent of the usage of a particular channel in a link
コード例 #27
0
def build_truncated_closure(g, cand_source, terminals, infection_times,
                            k=-1,
                            debug=False,
                            verbose=False,
                            **kawrgs):
    """
    build a clojure graph in which cand_source + terminals are all connected to each other.
    the number of neighbors of each node is determined by k

    the larger the k, the denser the graph"""
    r2pred = {}
    edges = {}
    terminals = list(terminals)

    # from cand_source to terminals
    vis = init_visitor(g, cand_source)

    cpbfs_search(g, source=cand_source, visitor=vis, terminals=terminals,
                 forbidden_nodes=terminals,
                 count_threshold=-1)  # k=-1 here because root connects to all other nodes
    r2pred[cand_source] = vis.pred
    for u, v, c in get_edges(vis.dist, cand_source, terminals):
        edges[(u, v)] = c
    if debug:
        print('cand_source: {}'.format(cand_source))
        print('#terminals: {}'.format(len(terminals)))
        print('edges from cand_source: {}'.format(edges))

    if verbose:
        terminals_iter = tqdm(terminals)
        print('building closure graph')
    else:
        terminals_iter = terminals

    # from terminal to other terminals
    # every temrinal should connetct to at least one earlier terminal
    # in this way, connectivity is ensured
    for root in terminals_iter:
        if root == cand_source:
            continue            
        # connect from some earlier node to root

        # if it's earliest, can only connect to peers
        early_terminals = [t for t in terminals
                           if infection_times[t] < infection_times[root]]
        same_time_terminals = [t for t in terminals
                               if infection_times[t] == infection_times[root] if t != root]
        late_time_terminals = [t for t in terminals
                               if infection_times[t] > infection_times[root]]
        if debug:
            print('root: {}'.format(root))
            print('early_terminals: {}'.format(early_terminals))
            print('same_time_terminals: {}'.format(same_time_terminals))
            print('late_time_terminals: {}'.format(late_time_terminals))

        if infection_times[root] == infection_times[terminals].min():
            targets = early_terminals + same_time_terminals
        else:
            targets = early_terminals

        targets = list(set(targets) - {cand_source})  # no one can connect to cand_source

        if debug:
            print('targets: {}'.format(targets))
            
        vis = init_visitor(g, root)
        cpbfs_search(g, source=root, visitor=vis,
                     terminals=targets,
                     forbidden_nodes=late_time_terminals,
                     count_threshold=k)
        r2pred[root] = vis.pred
        for root, v, c in get_edges(vis.dist, root, early_terminals):
            if debug:
                print('edge ({}, {})'.format(v, root))
            edges[(v, root)] = c  # from earlier node to root

    if verbose:
        print('returning closure graph')

    gc = Graph(directed=True)

    for _ in range(g.num_vertices()):
        gc.add_vertex()

    for (u, v) in edges:
        gc.add_edge(u, v)

    eweight = gc.new_edge_property('int')
    eweight.set_2d_array(np.array(list(edges.values())))

    return gc, eweight, r2pred
コード例 #28
0
ファイル: graph.py プロジェクト: lkopocinski/paintball
class BaseGraph(object):
    """
    Class representing a graph. We do not use pure graph_tool.Graph for we want
    to be able to easily change this library. Neither we use inheritance
    as graph_tool has inconvenient licence.
    """
    def __init__(self):
        self._g = None
        self._node_dict = {}
        self._syn_to_vertex_map = None
        self._lemma_to_nodes_dict = None
        self._lu_on_vertex_dict = None

    def use_graph_tool(self):
        """
        Returns underlying graph_tool.Graph. It should be avoided at all costs.
        """
        return self._g

    def get_node_for_synset_id(self, syn_id):
        """
        Lazy function to makes the map of synset identifiers to nodes into
        the graph. The building of map is made only on the first funcion call.
        The first and the next calls of this function will return the built map.
        """
        if not self._syn_to_vertex_map:
            self._syn_to_vertex_map = {}
            for node in self.all_nodes():
                if node.synset:
                    synset_id = node.synset.synset_id
                    self._syn_to_vertex_map[synset_id] = node
        return self._syn_to_vertex_map.get(syn_id, None)

    def pickle(self, filename):
        self._g.save(filename)

    def unpickle(self, filename):
        self._g = load_graph(filename)

    def init_graph(self, drctd=False):
        self._g = Graph(directed=drctd)

    def copy_graph_from(self, g):
        self._g = g._g.copy()

    def set_directed(self, drctd):
        self._g.set_directed(drctd)

    def is_directed(self):
        return self._g.is_directed()

    def merge_graphs(self, g1, g2):
        self._g = graph_union(g1._g, g2._g, internal_props=True)

    # Node operations:
    def all_nodes(self):
        for node in self._g.vertices():
            yield BaseNode(self._g, node)

    def create_node_attribute(self, name, kind, value=None):
        if not self.has_node_attribute(name):
            node_attr = self._g.new_vertex_property(kind, value)
            self._g.vertex_properties[name] = node_attr

    def create_node_attributes(self, node_attributes_list):
        for attr in node_attributes_list:
            if not self.has_node_attribute(attr[0]):
                node_attr = self._g.new_vertex_property(attr[1])
                self._g.vertex_properties[attr[0]] = node_attr

    def has_node_attribute(self, name):
        """ Checks if a node attribute already exists """
        return name in self._g.vertex_properties

    def delete_node_attribute(self, name):
        """ Delete node attribute """
        del self._g.vertex_properties[name]

    def add_node(self, name, node_attributes_list=None):
        if node_attributes_list is None:
            node_attributes_list = []

        if name not in self._node_dict:
            new_node = self._g.add_vertex()
            self._node_dict[name] = BaseNode(self._g, new_node)
            for attr in node_attributes_list:
                self._g.vertex_properties[attr[0]][new_node] = attr[1]
        return self._node_dict[name]

    def get_node(self, name):
        return self._node_dict[name]

    def remove_node(self, name):
        self._g.remove_vertex(self._node_dict[name]._node)
        del self._node_dict[name]

    def nodes_filter(self,
                     nodes_to_filter_set,
                     inverted=False,
                     replace=False,
                     soft=False):
        """
        Filters out nodes from set

        Args:
          nodes_to_filter_set (Iterable): Nodes which fill be filtered out.
          inverted (bool): If True, nodes NOT in set will be filtered out.
            Defaults to False.
          replace (bool): Replace current filter instead of combining the two.
            Defaults to False.
          soft (bool): Hide nodes without removing them so they can be restored
            with reset_nodes_filter. Defaults to False.
        """
        predicate = lambda node: node not in nodes_to_filter_set
        self.nodes_filter_conditional(predicate, inverted, replace, soft)

    def nodes_filter_conditional(self,
                                 predicate,
                                 inverted=False,
                                 replace=False,
                                 soft=False):
        """
        Filters node based on a predicate

        Args:
          predicate (Callable): Predicate returning False for nodes that should be
            filtered out.
          inverted (bool): Invert condition. Defaults to False.
          replace (bool): Replace current filter instead of combining the two.
            Defaults to False.
          soft (bool): Hide nodes without removing them so they can be restored
            with reset_nodes_filter. Defaults to False.
        """

        (old_filter, old_inverted) = self._g.get_vertex_filter()
        new_filter = self._g.new_vertex_property("bool")

        for node in self.all_nodes():
            kept = predicate(node) != inverted
            if not replace and old_filter:
                old_kept = bool(old_filter[node._node]) != old_inverted
                kept = kept and old_kept
            new_filter[node._node] = kept

        self._g.set_vertex_filter(new_filter, False)
        if not soft:
            self.apply_nodes_filter()

    def apply_nodes_filter(self):
        """ Removes nodes that are currently filtered out """
        self._g.purge_vertices()

    def reset_nodes_filter(self):
        """ Clears node filter """
        self._g.set_vertex_filter(None)

    # Edge operations:
    def num_edges(self):
        return self._g.num_edges()

    def all_edges(self):
        for e in self._g.edges():
            yield BaseEdge(self._g, e)

    def get_edges_between(self, source, target):
        """
        Return all edges between source and target. Source and target can be either
        BaseNode or integer.
        """
        if isinstance(source, BaseNode):
            source = source._node
        if isinstance(target, BaseNode):
            target = target._node
        for e in self._g.edge(source, target, all_edges=True):
            yield BaseEdge(self._g, e)

    def get_edge(self, source, target, add_missing=False):
        """
        Return some edge between source and target. Source and target can be either
        BaseNode or integer.
        """
        if isinstance(source, BaseNode):
            source = source._node
        if isinstance(target, BaseNode):
            target = target._node
        e = self._g.edge(source, target, add_missing)
        if e is not None:
            return BaseEdge(self._g, e)
        else:
            return None

    def create_edge_attribute(self, name, kind, value=None):
        if not self.has_edge_attribute(name):
            edge_attr = self._g.new_edge_property(kind, value)
            self._g.edge_properties[name] = edge_attr

    def alias_edge_attribute(self, name, alias):
        self._g.edge_properties[alias] = self._g.edge_properties[name]

    def create_edge_attributes(self, edge_attributes_list):
        for attr in edge_attributes_list:
            if not self.has_edge_attribute(attr[0]):
                edge_attr = self._g.new_edge_property(attr[1])
                self._g.edge_properties[attr[0]] = edge_attr

    def has_edge_attribute(self, name):
        """ Checks if an edge attribute already existst """
        return name in self._g.edge_properties

    def delete_edge_attribute(self, name):
        """ Delete edge attribute """
        del self._g.edge_properties[name]

    def add_edge(self, parent, child, edge_attributes_list=None):
        if edge_attributes_list is None:
            edge_attributes_list = []

        new_edge = self._g.add_edge(parent._node, child._node)
        for attr in edge_attributes_list:
            self._g.edge_properties[attr[0]][new_edge] = attr[1]

        return BaseEdge(self._g, new_edge)

    def edges_filter(self, edges_to_filter_set):
        edge_filter = self._g.new_edge_property("bool")

        for e in self.all_edges():
            if e in edges_to_filter_set:
                edge_filter[e._edge] = False
            else:
                edge_filter[e._edge] = True

        self._g.set_edge_filter(edge_filter)
        self._g.purge_edges()

    def ungraph_tool(self, thingy, lemma_on_only_synset_node_dict):
        """
        Converts given data structure so that it no longer have any graph_tool dependencies.
        """
        logger = logging.getLogger(__name__)

        if type(thingy) == dict:
            return {
                self.ungraph_tool(k, lemma_on_only_synset_node_dict):
                self.ungraph_tool(thingy[k], lemma_on_only_synset_node_dict)
                for k in thingy
            }

        nodes_to_translate = set()
        for vset in lemma_on_only_synset_node_dict.values():
            for v in vset:
                nodes_to_translate.add(v)

        if type(thingy) == gt.PropertyMap:
            dct = {}
            if thingy.key_type() == 'v':
                for node in nodes_to_translate:
                    dct[node] = thingy[node.use_graph_tool()]
            elif thingy.key_type() == 'e':
                for edge in self.all_edges():
                    dct[edge] = thingy[edge.use_graph_tool()]
            else:
                logger.error('Unknown property type %s', thingy.key_type())
                raise NotImplemented
            return dct

    def generate_lemma_to_nodes_dict_synsets(self):
        """
        This method generates a utility dictionary, which maps lemmas to
        corresponding node objects. It is expensive in menas of time
        needed to generate the dictionary. It should therefore be executed
        at the beginning of the runtime and later its results should be reused
        as many times as needed without re-executing the function.
        """
        lemma_to_nodes_dict = defaultdict(set)
        for node in self.all_nodes():
            try:
                lu_set = node.synset.lu_set
            except KeyError:
                continue

            for lu in lu_set:
                lemma = lu.lemma.lower()
                lemma_to_nodes_dict[lemma].add(node)

        self._lemma_to_nodes_dict = lemma_to_nodes_dict

    def generate_lemma_to_nodes_dict_lexical_units(self):
        """
        This method generates a utility dictionary, which maps lemmas to
        corresponding node objects. It is expensive in menas of time
        needed to generate the dictionary. It should therefore be executed
        at the beginning of the runtime and later its results should be reused
        as many times as needed without re-executing the function.
        """
        lemma_to_nodes_dict = defaultdict(set)

        for node in self.all_nodes():
            try:
                lemma = node.lu.lemma.lower()
                lemma_to_nodes_dict[lemma].add(node)
            except:
                continue

        self._lemma_to_nodes_dict = lemma_to_nodes_dict

    @property
    def lemma_to_nodes_dict(self):
        return self._lemma_to_nodes_dict

    def _make_lu_on_v_dict(self):
        """
        Makes dictionary lu on vertex
        """
        lu_on_vertex_dict = defaultdict(set)
        for node in self.all_nodes():
            try:
                nl = node.lu
            except Exception:
                continue

            if nl:
                lu_on_vertex_dict[node.lu.lu_id] = node

        self._lu_on_vertex_dict = lu_on_vertex_dict
コード例 #29
0
def build_truncated_closure(g,
                            cand_source,
                            terminals,
                            infection_times,
                            k=-1,
                            debug=False,
                            verbose=False,
                            **kawrgs):
    """
    build a clojure graph in which cand_source + terminals are all connected to each other.
    the number of neighbors of each node is determined by k

    the larger the k, the denser the graph"""
    r2pred = {}
    edges = {}
    terminals = list(terminals)

    # from cand_source to terminals
    vis = init_visitor(g, cand_source)

    cpbfs_search(g,
                 source=cand_source,
                 visitor=vis,
                 terminals=terminals,
                 forbidden_nodes=terminals,
                 count_threshold=-1
                 )  # k=-1 here because root connects to all other nodes
    r2pred[cand_source] = vis.pred
    for u, v, c in get_edges(vis.dist, cand_source, terminals):
        edges[(u, v)] = c
    if debug:
        print('cand_source: {}'.format(cand_source))
        print('#terminals: {}'.format(len(terminals)))
        print('edges from cand_source: {}'.format(edges))

    if verbose:
        terminals_iter = tqdm(terminals)
        print('building closure graph')
    else:
        terminals_iter = terminals

    # from terminal to other terminals
    # every temrinal should connetct to at least one earlier terminal
    # in this way, connectivity is ensured
    for root in terminals_iter:
        if root == cand_source:
            continue
        # connect from some earlier node to root

        # if it's earliest, can only connect to peers
        early_terminals = [
            t for t in terminals if infection_times[t] < infection_times[root]
        ]
        same_time_terminals = [
            t for t in terminals if infection_times[t] == infection_times[root]
            if t != root
        ]
        late_time_terminals = [
            t for t in terminals if infection_times[t] > infection_times[root]
        ]
        if debug:
            print('root: {}'.format(root))
            print('early_terminals: {}'.format(early_terminals))
            print('same_time_terminals: {}'.format(same_time_terminals))
            print('late_time_terminals: {}'.format(late_time_terminals))

        if infection_times[root] == infection_times[terminals].min():
            targets = early_terminals + same_time_terminals
        else:
            targets = early_terminals

        targets = list(set(targets) -
                       {cand_source})  # no one can connect to cand_source

        if debug:
            print('targets: {}'.format(targets))

        vis = init_visitor(g, root)
        cpbfs_search(g,
                     source=root,
                     visitor=vis,
                     terminals=targets,
                     forbidden_nodes=late_time_terminals,
                     count_threshold=k)
        r2pred[root] = vis.pred
        for root, v, c in get_edges(vis.dist, root, early_terminals):
            if debug:
                print('edge ({}, {})'.format(v, root))
            edges[(v, root)] = c  # from earlier node to root

    if verbose:
        print('returning closure graph')

    gc = Graph(directed=True)

    for _ in range(g.num_vertices()):
        gc.add_vertex()

    for (u, v) in edges:
        gc.add_edge(u, v)

    eweight = gc.new_edge_property('int')
    eweight.set_2d_array(np.array(list(edges.values())))

    return gc, eweight, r2pred
コード例 #30
0
ファイル: Segmentation.py プロジェクト: abucksch/DIRT
    def makeGraph(self,img,dia,xScale,yScale):
        print 'Building Graph Data Structure'
        start=time.time()
        G = Graph(directed=False)
        vprop=G.new_vertex_property('object')
        eprop=G.new_edge_property('object')
        epropW=G.new_edge_property("int32_t")
        avgScale=(xScale+yScale)/2

        test=np.where(img==True)
        ss = np.shape(test)
        cccc=0
        percentOld=0.0
        print str(np.round(percentOld,1))+'%'
        for (i,j) in zip(test[1],test[0]):
                cccc+=1
                percent=(float(cccc)/float(ss[1]))*100
                if percentOld+10< percent: 
                    print str(np.round(percent,1))+'%'
                    percentOld=percent
                nodeNumber1 = (float(i)*yScale,float(j)*xScale)
                if gu.find_vertex(G, vprop, {'imgIdx':(j,i),'coord':nodeNumber1, 'nrOfPaths':0, 'diameter':float(dia[j][i])*avgScale}):
                            v1=gu.find_vertex(G, vprop, {'imgIdx':(j,i),'coord':nodeNumber1, 'nrOfPaths':0, 'diameter':float(dia[j][i])*avgScale})[0]
                else:
                    v1=G.add_vertex()
                    vprop[G.vertex(v1)]={'imgIdx':(j,i),'coord':nodeNumber1, 'nrOfPaths':0, 'diameter':float(dia[j][i])*avgScale}
                try:
                    
                    if img[j,i+1] == True:
                        nodeNumber2 = (float(i+1)*yScale,float(j)*xScale)
                        if gu.find_vertex(G, vprop, {'imgIdx':(j,i+1),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j][i+1])*avgScale}):
                            v2=gu.find_vertex(G, vprop, {'imgIdx':(j,i+1),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j][i+1])*avgScale})[0]
                            if gu.find_edge(G, eprop, {'coord1':vprop[v2]['coord'], 'coord2':vprop[v1]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}):
                                pass
                            else:
                                e = G.add_edge(v1, v2)
                                epropW[e]=(((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)/avgScale)**4
                                eprop[e]={'coord1':vprop[v1]['coord'], 'coord2':vprop[v2]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}
                        else:
                            v2=G.add_vertex()
                            vprop[G.vertex(v2)]={'imgIdx':(j,i+1),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j][i+1])*avgScale}
                            e = G.add_edge(v1, v2)
                            epropW[e]=(((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)/avgScale)**4
                            eprop[e]={'coord1':vprop[v1]['coord'], 'coord2':vprop[v2]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}
                except:
                    pass
                try:
                    if img[j,i-1] == True:
                        nodeNumber2 = (float(i-1)*yScale,float(j)*xScale)
                        if gu.find_vertex(G, vprop, {'imgIdx':(j,i-1),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j][i-1])*avgScale}):
                            v2=gu.find_vertex(G, vprop, {'imgIdx':(j,i-1),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j][i-1])*avgScale})[0]
                            if gu.find_edge(G, eprop, {'coord1':vprop[v2]['coord'], 'coord2':vprop[v1]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}):
                                pass
                            else:
                                e = G.add_edge(v1, v2)
                                epropW[e]=(((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)/avgScale)**4
                                eprop[e]={'coord1':vprop[v1]['coord'], 'coord2':vprop[v2]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}
                        else:
                            v2=G.add_vertex()
                            vprop[G.vertex(v2)]={'imgIdx':(j,i-1),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j][i-1])*avgScale}
                            e = G.add_edge(v1, v2)
                            epropW[e]=(((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)/avgScale)**4
                            eprop[e]={'coord1':vprop[v1]['coord'], 'coord2':vprop[v2]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}
                except:pass
                try:
                    if img[j + 1,i] == True:
                        nodeNumber2 = (float(i)*yScale,float(j+1)*xScale)
                        if gu.find_vertex(G, vprop, {'imgIdx':(j+1,i),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j+1][i])*avgScale}):
                            v2=gu.find_vertex(G, vprop, {'imgIdx':(j+1,i),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j+1][i])*avgScale})[0]
                            if gu.find_edge(G, eprop, {'coord1':vprop[v2]['coord'], 'coord2':vprop[v1]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}):
                                pass
                            else:
                                e = G.add_edge(v1, v2)
                                epropW[e]=(((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)/avgScale)**4
                                eprop[e]={'coord1':vprop[v1]['coord'], 'coord2':vprop[v2]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}
                        else:
                            v2=G.add_vertex()
                            vprop[G.vertex(v2)]={'imgIdx':(j+1,i),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j+1][i])*avgScale}
                            e = G.add_edge(v1, v2)
                            epropW[e]=(((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)/avgScale)**4
                            eprop[e]={'coord1':vprop[v1]['coord'], 'coord2':vprop[v2]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}
                except:pass
                try:
                    if img[j - 1,i] == True:
                        nodeNumber2 = (float(i)*yScale,float(j-1)*xScale)
                        if gu.find_vertex(G, vprop, {'imgIdx':(j-1,i),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j-1][i])*avgScale}):
                            v2=gu.find_vertex(G, vprop, {'imgIdx':(j-1,i),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j-1][i])*avgScale})[0]
                            if gu.find_edge(G, eprop, {'coord1':vprop[v2]['coord'], 'coord2':vprop[v1]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}):
                                pass
                            else:
                                e = G.add_edge(v1, v2)
                                epropW[e]=(((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)/avgScale)**4
                                eprop[e]={'coord1':vprop[v1]['coord'], 'coord2':vprop[v2]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}
                        else:
                            v2=G.add_vertex()
                            vprop[G.vertex(v2)]={'imgIdx':(j-1,i),'coord':nodeNumber2, 'nrOfPaths':0, 'diameter':float(dia[j-1][i])*avgScale}
                            e = G.add_edge(v1, v2)
                            epropW[e]=(((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)/avgScale)**4
                            eprop[e]={'coord1':vprop[v1]['coord'], 'coord2':vprop[v2]['coord'],'weight':((vprop[v1]['diameter']+vprop[v2]['diameter'])/2)**4,'RTP':False}
                except: pass
#                    
        print '100.0%'
        print 'selecting largest connected component'
        G.edge_properties["ep"] = eprop
        G.edge_properties["w"] = epropW
        G.vertex_properties["vp"] = vprop
        l = gt.label_largest_component(G)
        print(l.a)
        u = gt.GraphView(G, vfilt=l)
        print '# vertices'
        print(u.num_vertices())
        print(G.num_vertices())
        print '# edges'
        print(u.num_edges())
        print 'building graph finished in: '+str(time.time()-start)+'s'
        return u 
コード例 #31
0
ファイル: network_tools.py プロジェクト: UWPRG/savvy
def build_graph(df_list, sens='ST', top=410, min_sens=0.01,
                edge_cutoff=0.0):
    """
    Initializes and constructs a graph where vertices are the parameters
    selected from the first dataframe in 'df_list', subject to the
    constraints set by 'sens', 'top', and 'min_sens'.  Edges are the second
    order sensitivities of the interactions between those vertices,
    with sensitivities greater than 'edge_cutoff'.

    Parameters
    -----------
    df_list     : list
                  A list of two dataframes.  The first dataframe should be
                  the first/total order sensitivities collected by the
                  function data_processing.get_sa_data().
    sens        : str, optional
                  A string with the name of the sensitivity that you would
                  like to use for the vertices ('ST' or 'S1').
    top         : int, optional
                  An integer specifying the number of vertices to display (
                  the top sensitivity values).
    min_sens    : float, optional
                  A float with the minimum sensitivity to allow in the graph.
    edge_cutoff : float, optional
                  A float specifying the minimum second order sensitivity to
                  show as an edge in the graph.

    Returns
    --------
    g : graph-tool object
        a graph-tool graph object of the network described above.  Each
        vertex has properties 'param', 'sensitivity', and 'confidence'
        corresponding to the name of the parameter, value of the sensitivity
        index, and it's confidence interval.  The only edge property is
        'second_sens', the second order sensitivity index for the
        interaction between the two vertices it connects.
    """

    # get the first/total index dataframe and second order dataframe
    df = df_list[0]
    df2 = df_list[1]

    # Make sure sens is ST or S1
    if sens not in set(['ST', 'S1']):
        raise ValueError('sens must be ST or S1')
    # Make sure that there is a second order index dataframe
    try:
        if not df2:
            raise Exception('Missing second order dataframe!')
    except:
        pass

    # slice the dataframes so the resulting graph will only include the top
    # 'top' values of 'sens' greater than 'min_sens'.
    df = df.sort_values(sens, ascending=False)
    df = df.ix[df[sens] > min_sens, :].head(top)
    df = df.reset_index()

    # initialize a graph
    g = Graph()

    vprop_sens = g.new_vertex_property('double')
    vprop_conf = g.new_vertex_property('double')
    vprop_name = g.new_vertex_property('string')
    eprop_sens = g.new_edge_property('double')

    g.vertex_properties['param'] = vprop_name
    g.vertex_properties['sensitivity'] = vprop_sens
    g.vertex_properties['confidence'] = vprop_conf
    g.edge_properties['second_sens'] = eprop_sens

    # keep a list of all the vertices
    v_list = []

    # Add the vertices to the graph
    for i, param in enumerate(df['Parameter']):
        v = g.add_vertex()
        vprop_sens[v] = df.ix[i, sens]
        vprop_conf[v] = 1 + df.ix[i, '%s_conf' % sens] / df.ix[i, sens]
        vprop_name[v] = param
        v_list.append(v)

    # Make two new columns in second order dataframe that point to the vertices
    # connected on each row.
    df2['vertex1'] = -999
    df2['vertex2'] = -999
    for vertex in v_list:
        param = g.vp.param[vertex]
        df2.ix[df2['Parameter_1'] == param, 'vertex1'] = vertex
        df2.ix[df2['Parameter_2'] == param, 'vertex2'] = vertex

    # Only allow edges for vertices that we've defined
    df_edges = df2[(df2['vertex1'] != -999) & (df2['vertex2'] != -999)]
    # eliminate edges below a certain cutoff value
    pruned = df_edges[df_edges['S2'] > edge_cutoff]
    pruned.reset_index(inplace=True)
    # Add the edges for the graph
    for i, sensitivity in enumerate(pruned['S2']):
        v1 = pruned.ix[i, 'vertex1']
        v2 = pruned.ix[i, 'vertex2']
        e = g.add_edge(v1, v2)
        # multiply by a number to make the lines visible on the plot
        eprop_sens[e] = sensitivity * 150

    # These are ways you can reference properties of vertices or edges
    # g.vp.param[g.vertex(77)]
    # g.vp.param[v_list[0]]

    print ('Created a graph with %s vertices and %s edges.\nVertices are the '
           'top %s %s values greater than %s.\nOnly S2 values (edges) '
           'greater than %s are included.' %
           (g.num_vertices(), g.num_edges(), top, sens, min_sens, edge_cutoff))

    return g
コード例 #32
0
    def makeGraphFast(self, img, dia, xScale, yScale):
        print('Building Graph Data Structure'),
        start = time.time()
        G = Graph(directed=False)
        sumAddVertices = 0

        vprop = G.new_vertex_property('object')
        eprop = G.new_edge_property('object')
        epropW = G.new_edge_property("float")
        h, w = np.shape(img)
        avgScale = (xScale + yScale) / 2

        addedVerticesLine2 = []
        vListLine2 = []
        percentOld = 0
        counter = 0
        '''
        Sweep over each line in the image except the last line
        '''
        for idx, i in enumerate(img[:len(img) - 2]):
            '''
            Get foreground indices in the current line of the image and make vertices
            '''
            counter += 1
            percent = (float(counter) / float(h)) * 100
            if percentOld + 10 < percent:
                print(str(np.round(percent, 1)) + '% '),
                percentOld = percent

            line1 = np.where(i == True)
            if len(line1[0]) > 0:
                line1 = set(line1[0]).difference(set(addedVerticesLine2))
                vL = G.add_vertex(len(list(line1)))

                if len(line1) > 1:
                    vList = vListLine2 + list(vL)
                else:
                    vList = vListLine2 + [vL]
                line1 = addedVerticesLine2 + list(line1)
                for jdx, j in enumerate(line1):
                    vprop[vList[jdx]] = {
                        'imgIdx': (j, idx),
                        'coord': (float(j) * xScale, float(idx) * yScale),
                        'nrOfPaths': 0,
                        'diameter': float(dia[idx][j]) * avgScale
                    }
                '''
                keep order of the inserted vertices
                '''
                sumAddVertices += len(line1)

                addedVerticesLine2 = []
                vListLine2 = []
                '''
                Connect foreground indices to neighbours in the next line
                '''
                for v1 in line1:
                    va = vList[line1.index(v1)]
                    diagonalLeft = diagonalRight = True
                    try:
                        if img[idx][v1 - 1] == True:
                            diagonalLeft = False
                            vb = vList[line1.index(v1 - 1)]
                            e = G.add_edge(va, vb)
                            eprop[e] = {
                                'coord1':
                                vprop[va]['coord'],
                                'coord2':
                                vprop[vb]['coord'],
                                'weight': ((vprop[va]['diameter'] +
                                            vprop[vb]['diameter']) / 2),
                                'RTP':
                                False
                            }
                            epropW[e] = 2. / (eprop[e]['weight']**2)
                    except:
                        print 'Boundary vertex at: ' + str(
                            [v1, idx - 1]) + ' image size: ' + str([w, h])
                        pass

                    try:
                        if img[idx][v1 + 1] == True:
                            diagonalRight = False
                            vb = vList[line1.index(v1 + 1)]
                            e = G.add_edge(va, vb)
                            eprop[e] = {
                                'coord1':
                                vprop[va]['coord'],
                                'coord2':
                                vprop[vb]['coord'],
                                'weight': ((vprop[va]['diameter'] +
                                            vprop[vb]['diameter']) / 2),
                                'RTP':
                                False
                            }
                            epropW[e] = 2. / (eprop[e]['weight']**2)
                    except:
                        print 'Boundary vertex at: ' + str(
                            [v1 + 1, idx]) + ' image size: ' + str([w, h])
                        pass  # just if we are out of bounds

                    try:
                        if img[idx + 1][v1] == True:
                            diagonalRight = False
                            diagonalLeft = False
                            vNew = G.add_vertex()
                            vprop[vNew] = {
                                'imgIdx': (v1, idx + 1),
                                'coord':
                                (float(v1) * xScale, float(idx + 1) * yScale),
                                'nrOfPaths':
                                0,
                                'diameter':
                                float(dia[idx + 1][v1]) * avgScale
                            }
                            vListLine2.append(vNew)
                            e = G.add_edge(vList[line1.index(v1)], vNew)
                            eprop[e] = {
                                'coord1':
                                vprop[va]['coord'],
                                'coord2':
                                vprop[vNew]['coord'],
                                'weight': ((vprop[va]['diameter'] +
                                            vprop[vNew]['diameter']) / 2),
                                'RTP':
                                False
                            }
                            epropW[e] = 1. / (eprop[e]['weight']**2)
                            if v1 not in addedVerticesLine2:
                                addedVerticesLine2.append(v1)
                    except:
                        print 'Boundary vertex at: ' + str(
                            [v1, idx + 1]) + ' image size: ' + str([w, h])
                        pass

                    try:
                        if diagonalRight == True and img[idx + 1][v1 +
                                                                  1] == True:
                            vNew = G.add_vertex()
                            vprop[vNew] = {
                                'imgIdx': (v1 + 1, idx + 1),
                                'coord': (float(v1 + 1) * xScale,
                                          float(idx + 1) * yScale),
                                'nrOfPaths':
                                0,
                                'diameter':
                                float(dia[idx + 1][v1 + 1]) * avgScale
                            }
                            vListLine2.append(vNew)
                            e = G.add_edge(vList[line1.index(v1)], vNew)
                            eprop[e] = {
                                'coord1':
                                vprop[va]['coord'],
                                'coord2':
                                vprop[vNew]['coord'],
                                'weight': ((vprop[va]['diameter'] +
                                            vprop[vNew]['diameter']) / 2),
                                'RTP':
                                False
                            }
                            epropW[e] = 1.41 / (eprop[e]['weight']**2)
                            if v1 + 1 not in addedVerticesLine2:
                                addedVerticesLine2.append(v1 + 1)
                    except:
                        print 'Boundary vertex at: ' + str(
                            [v1 + 1, idx + 1]) + ' image size: ' + str([w, h])
                        pass

                    try:
                        if diagonalLeft == True and img[idx + 1][v1 -
                                                                 1] == True:
                            vNew = G.add_vertex()
                            vprop[vNew] = {
                                'imgIdx': (v1 - 1, idx + 1),
                                'coord': (float(v1 - 1) * xScale,
                                          float(idx + 1) * yScale),
                                'nrOfPaths':
                                0,
                                'diameter':
                                float(dia[idx + 1][v1 - 1]) * avgScale
                            }
                            vListLine2.append(vNew)
                            e = G.add_edge(vList[line1.index(v1)], vNew)
                            eprop[e] = {
                                'coord1':
                                vprop[va]['coord'],
                                'coord2':
                                vprop[vNew]['coord'],
                                'weight': ((vprop[va]['diameter'] +
                                            vprop[vNew]['diameter']) / 2),
                                'RTP':
                                False
                            }
                            epropW[e] = 1.41 / (eprop[e]['weight']**2)
                            if v1 - 1 not in addedVerticesLine2:
                                addedVerticesLine2.append(v1 - 1)
                    except:
                        print 'Boundary vertex at: ' + str(
                            [v1 - 1, idx + 1]) + ' image size: ' + str([w, h])
                        pass
                    try:
                        if img[idx][v1 + 1] == False and img[idx][
                                v1 - 1] == False and img[idx + 1][
                                    v1] == False and diagonalLeft == False and diagonalRight == False:
                            print 'tip detected'
                            if img[idx - 1][v1 - 1] == False and img[idx - 1][
                                    v1 + 1] == False and img[idx -
                                                             1][v1] == False:
                                print 'floating pixel'
                    except:
                        pass

        print 'done!'
        G.edge_properties["ep"] = eprop
        G.edge_properties["w"] = epropW
        G.vertex_properties["vp"] = vprop
        print 'graph build in ' + str(time.time() - start)
        l = gt.label_largest_component(G)
        u = gt.GraphView(G, vfilt=l)
        print '# vertices'
        print(u.num_vertices())
        print(G.num_vertices())
        if u.num_vertices() != G.num_vertices():
            self.__fail = float((G.num_vertices() - u.num_vertices())) / float(
                G.num_vertices())
        return u, u.num_vertices()
コード例 #33
0
class BoardGraphGraphtool(BoardGraphBase):

    def __init__(self, number_of_vertices, graph_type):
        super().__init__(number_of_vertices, graph_type)
        # Graph tool creates directed multigraph by default.
        self._graph = Graph()
        self._graph.add_vertex(number_of_vertices)
        self._graph.vertex_properties["cell"] = self._graph.new_vertex_property(
            "object", number_of_vertices * [BoardCell()]
        )
        self._graph.edge_properties["direction"
                                   ] = self._graph.new_edge_property("object")
        self._graph.edge_properties["weight"
                                   ] = self._graph.new_edge_property("int")

    def __getitem__(self, position):
        return self._graph.vp.cell[self._graph.vertex(position)]

    def __setitem__(self, position, board_cell):
        self._graph.vp.cell[self._graph.vertex(position)] = board_cell

    def __contains__(self, position):
        return position in range(0, self.vertices_count())

    def vertices_count(self):
        return self._graph.num_vertices()

    def edges_count(self):
        return self._graph.num_edges()

    def has_edge(self, source_vertice, target_vertice, direction):
        for e in self._graph.vertex(source_vertice).out_edges():
            if (
                int(e.target()) == target_vertice and
                self._graph.ep.direction[e] == direction
            ):
                return True
        return False

    def out_edges_count(self, source_vertice, target_vertice):
        return len([
            1 for e in self._graph.vertex(source_vertice).out_edges()
            if int(e.target()) == target_vertice
        ])

    def reconfigure_edges(self, width, height, tessellation):
        """
        Uses tessellation object to create all edges in graph.
        """
        self._graph.clear_edges()
        for source_vertice in self._graph.vertices():
            for direction in tessellation.legal_directions:
                neighbor_vertice = tessellation.neighbor_position(
                    int(source_vertice),
                    direction,
                    board_width=width,
                    board_height=height
                )
                if neighbor_vertice is not None:
                    e = self._graph.add_edge(
                        source_vertice, neighbor_vertice, add_missing=False
                    )
                    self._graph.ep.direction[e] = direction

    # TODO: Faster version?
    # def reconfigure_edges(self, width, height, tessellation):
    #     """
    #     Uses tessellation object to create all edges in graph.
    #     """
    #     self._graph.clear_edges()
    #     edges_to_add = []
    #     directions_to_add = dict()
    #     for source_vertice in self._graph.vertices():
    #         for direction in tessellation.legal_directions:
    #             neighbor_vertice = tessellation.neighbor_position(
    #                 int(source_vertice), direction,
    #                 board_width=width, board_height=height
    #             )
    #             if neighbor_vertice is not None:
    #                 edge = (int(source_vertice), neighbor_vertice,)

    #                 edges_to_add.append(edge)

    #                 if edge not in directions_to_add:
    #                     directions_to_add[edge] = deque()

    #                 directions_to_add[edge].append(direction)

    #     self._graph.add_edge_list(edges_to_add) if edges_to_add else None

    #     for e in edges_to_add:
    #         e_descriptors = self._graph.edge(
    #             s = self._graph.vertex(e[0]),
    #             t = self._graph.vertex(e[1]),
    #             all_edges = True
    #         )

    #         for e_descriptor in e_descriptors:
    #             if len(directions_to_add[e]) > 0:
    #                 self._graph.ep.direction[e_descriptor] = directions_to_add[e][0]
    #                 directions_to_add[e].popleft()

    def calculate_edge_weights(self):
        for e in self._graph.edges():
            self._graph.ep.weight[e] = self.out_edge_weight(int(e.target()))

    def neighbor(self, from_position, direction):
        try:
            for e in self._graph.vertex(from_position).out_edges():
                if self._graph.ep.direction[e] == direction:
                    return int(e.target())
        except ValueError as e:
            raise IndexError(e.args)

        return None

    def wall_neighbors(self, from_position):
        return [
            int(n) for n in self._graph.vertex(from_position).out_neighbours()
            if self[int(n)].is_wall
        ]

    def all_neighbors(self, from_position):
        return [
            int(n) for n in self._graph.vertex(from_position).out_neighbours()
        ]

    def shortest_path(self, start_position, end_position):
        try:
            return [
                int(v)
                for v in shortest_path(
                    g=self._graph,
                    source=self._graph.vertex(start_position),
                    target=self._graph.vertex(end_position),
                )[0]
            ]
        except ValueError:
            return []

    def dijkstra_path(self, start_position, end_position):
        try:
            self.calculate_edge_weights()
            return [
                int(v)
                for v in shortest_path(
                    g=self._graph,
                    source=self._graph.vertex(start_position),
                    target=self._graph.vertex(end_position),
                    weights=self._graph.ep.weight,
                )[0]
            ]
        except ValueError:
            return []

    def position_path_to_direction_path(self, position_path):
        retv = []
        src_vertice_index = 0
        for target_vertice in position_path[1:]:
            source_vertice = position_path[src_vertice_index]
            src_vertice_index += 1

            for out_edge in self._graph.vertex(source_vertice).out_edges():
                if int(out_edge.target()) == target_vertice:
                    retv.append(self._graph.ep.direction[out_edge])

        return {
            'source_position': position_path[0] if position_path else None,
            'path': retv
        }
コード例 #34
0
class GraphDataset:
    """
    Class for managing datasets with graph data
    """
    def __init__(self, name, edges, object_ids, weights, hidden_graph=None):
        """
        Params:
            name (str): unique string to name this dataset (for pickling and
                unpickling)
            edges (numpy.ndarray): numpy array of shape [num_edges, 2]
                containing the indices of nodes in all edges
            objects (List[str]): string object ids for all nodes
            weights (numpy.ndarray): numpy array of shape [num_edges]
                containing edge weights
            hidden_graph (GraphDataset): Graph data that should be excluded
                but not considered as negative edges. (i.e. train
                edges should not be in eval dataset but they shouldn't be
                counted as negatives either)
        """

        self.name = name
        self.edges = edges
        self.object_ids = np.asarray(object_ids)
        self.weights = weights
        self.hidden_graph = hidden_graph

        self.graph = Graph(directed=False)
        self.graph.add_vertex(len(object_ids))
        edge_weights = [[edge[0], edge[1], weight]
                        for edge, weight in zip(self.edges, self.weights)]
        self.weight_property = self.graph.new_edge_property("float")
        eprops = [self.weight_property]
        self.graph.add_edge_list(edge_weights, eprops=eprops)
        self.manifold_nns = None

    def gen_neighbor_data(self, verbose=True) -> Dict:
        """
        Generates the graph data needed to run the cython iterator
        Returns a dict with the neighbor data which will have values

        - 'non_empty_vertices' the indices of vertices which have edges
           emanating from them
        - 'all_graph_neighbors' a list of lists of ints such that the list of
          edges emanating from the vertex with index non_empty_vertices[i] is
          stored in all_graph_neighbors[i]
        - 'all_graph_weights' a list of lists of ints such that
          all_graph_weights[i][j] represents the weight of the connection in
          all_graph_neighbors[i][j]
        - 'N' number of nodes in the graph

        Parameters:
            verbose (bool): should graph loading be printed out
        """

        all_graph_neighbors = []
        all_graph_weights = []
        non_empty_vertices = []
        empty_vertices = []
        if verbose:
            iterator = tqdm(range(self.n_nodes()),
                            desc="Generating Neighbor Data",
                            dynamic_ncols=True)
        else:
            iterator = range(self.n_nodes())

        for i in iterator:
            in_edges = self.graph.get_in_edges(i, [self.weight_property])
            out_edges = self.graph.get_out_edges(i, [self.weight_property])
            if in_edges.size + out_edges.size > 0:
                non_empty_vertices.append(i)
                if in_edges.size == 0:
                    all_graph_neighbors.append(out_edges[:,
                                                         1].astype(np.int64))
                    all_graph_weights.append(out_edges[:,
                                                       2].astype(np.float32))
                elif out_edges.size == 0:
                    all_graph_neighbors.append(in_edges[:, 1].astype(np.int64))
                    all_graph_weights.append(in_edges[:, 2].astype(np.float32))
                else:
                    all_graph_neighbors.append(
                        np.concatenate([in_edges[:, 0],
                                        out_edges[:, 1]]).astype(np.int64))
                    all_graph_weights.append(
                        np.concatenate([in_edges[:, 2],
                                        out_edges[:, 2]]).astype(np.float32))
            else:
                empty_vertices.append(i)

        # graph_neighbors = np.concatenate(all_graph_neighbors)
        # graph_neighbor_weights = np.concatenate(all_graph_weights)
        non_empty_vertices = np.array(non_empty_vertices, dtype=np.int64)
        empty_vertices = np.array(empty_vertices, dtype=np.int64)

        return {
            "all_graph_neighbors": all_graph_neighbors,
            "all_graph_weights": all_graph_weights,
            "non_empty_vertices": non_empty_vertices,
            "empty_vertices": empty_vertices,
            "N": self.n_nodes()
        }

    def add_manifold_nns(self, graph_embedder: GraphEmbedder):
        manifold = graph_embedder.get_manifold()
        data_points = graph_embedder.retrieve_nodes(self.n_nodes())
        self.manifold_nns = ManifoldNNS(data_points, manifold)

    def n_nodes(self) -> int:
        """
        Returns the number of nodes in the graph
        """
        return len(self.object_ids)

    def collapse_nodes(self, node_ids):
        all_new_edges = []
        for node_id in tqdm(node_ids,
                            desc="Collapsing Nodes",
                            dynamic_ncols=True):
            in_edges = self.graph.get_in_edges(node_id, [self.weight_property])
            out_edges = self.graph.get_out_edges(node_id,
                                                 [self.weight_property])
            neighbors = np.concatenate([out_edges[:, 1:3], in_edges[:, 0:3:2]])
            if neighbors.shape[0] > 1:
                neighbor_combos = \
                    neighbors[comb_index(neighbors.shape[0], 2)]
                neighbor_combos = \
                    neighbor_combos.reshape(neighbor_combos.shape[0], 4)
                new_edges = np.zeros((neighbor_combos.shape[0], 3))
                new_edges[:, :2] += neighbor_combos[:, 0:3:2]
                new_edges[:,2] += (neighbor_combos[:,1] + \
                                   neighbor_combos[:,3])/4
                all_new_edges.append(new_edges)

        self.graph.add_edge_list(np.concatenate(all_new_edges),
                                 eprops=[self.weight_property])

        self.object_ids = np.delete(self.object_ids, np.array(node_ids))
        self.graph.remove_vertex(node_ids)

        edges_weights = self.graph.get_edges(eprops=[self.weight_property])
        edges = edges_weights[:, 0:2]
        weights = edges_weights[:, 2]
        self.edges = edges
        self.weights = weights

    def get_neighbor_iterator(
        self,
        graph_sampling_config: GraphSamplingConfig,
        data_fraction: float = 1,
    ) -> Iterator[GraphDataBatch]:
        """
        Gets an efficient iterator of edge batches
        """
        neighbor_data = load_or_gen(f"GraphDataset.{self.name}",
                                    self.gen_neighbor_data)
        if self.hidden_graph is None:
            # GraphDataBatchIterator is defined in cython with these arguments.
            # noinspection PyArgumentList
            iterator = GraphDataBatchIterator(neighbor_data,
                                              graph_sampling_config)
            iterator.data_fraction = data_fraction

        else:
            hidden_neighbor_data = load_or_gen(
                f"GraphDataset.{self.hidden_graph.name}",
                self.hidden_graph.gen_neighbor_data)

            # GraphDataBatchIterator is defined in cython with these arguments.
            # noinspection PyArgumentList
            iterator = GraphDataBatchIterator(neighbor_data,
                                              graph_sampling_config,
                                              hidden_neighbor_data)
            iterator.data_fraction = data_fraction

        if self.manifold_nns is not None:
            sampling_config = get_config().sampling
            _, nns = \
                self.manifold_nns.knn_query_all(sampling_config.manifold_nn_k)

            all_manifold_neighbors = [
                nns[i][1:].astype(np.int64) for i in range(self.n_nodes())
            ]
            iterator.refresh_manifold_nn(all_manifold_neighbors)

        return iterator

    @classmethod
    def make_train_eval_split(cls, name, edges, object_ids, weights):
        """
        Returns a tuple of a train eval split of the graph as defined in the
        data config.
        """

        data_config = get_config().data
        np.random.seed(data_config.split_seed)
        if data_config.split_by_edges:
            # TODO Doesn't save to file in this mode
            shuffle_order = np.arange(edges.shape[0])
            np.random.shuffle(shuffle_order)
            num_eval = floor(edges.shape[0] * data_config.split_size)
            eval_indices = shuffle_order[:num_eval]
            train_indices = shuffle_order[num_eval:]
            train_edges = edges[train_indices]
            train_weights = weights[train_indices]
            eval_edges = edges[eval_indices]
            eval_weights = weights[eval_indices]
        else:
            shuffle_order = np.arange(len(object_ids))
            np.random.shuffle(shuffle_order)
            num_eval = floor(len(object_ids) * data_config.split_size)
            eval_indices = shuffle_order[:num_eval]

            test_set = data_config.generate_test_set
            if test_set:
                test_indices = shuffle_order[num_eval:2 * num_eval]
            train_indices = shuffle_order[2 * num_eval:] if test_set else \
                shuffle_order[num_eval:]

            train_edges = []
            eval_edges = []
            train_weights = []
            eval_weights = []
            if test_set:
                test_edges = []
                test_weights = []

            for edge, weight in zip(edges, weights):
                if test_set and (edge[0] in test_indices
                                 or edge[1] in test_indices):
                    test_edges.append(edge)
                    test_weights.append(weight)
                elif edge[0] in eval_indices or edge[1] in eval_indices:
                    eval_edges.append(edge)
                    eval_weights.append(weight)
                else:
                    train_edges.append(edge)
                    train_weights.append(weight)

            if test_set:
                save_graph_data(test_edges, test_weights, object_ids,
                                data_config.test_path)
            save_graph_data(train_edges, train_weights, object_ids,
                            data_config.train_path)
            save_graph_data(eval_edges, eval_weights, object_ids,
                            data_config.eval_path)

            train_edges = np.array(train_edges)
            eval_edges = np.array(eval_edges)
            train_weights = np.array(train_weights)
            eval_weights = np.array(eval_weights)

        train_data = GraphDataset(f"{name}_train", train_edges, object_ids,
                                  train_weights)

        eval_data = GraphDataset(f"{name}_eval",
                                 eval_edges,
                                 object_ids,
                                 eval_weights,
                                 hidden_graph=train_data)

        return train_data, eval_data
コード例 #35
0
def gen_fs(dicProperties):
	np.random.seed()
	graphFS = Graph()
	# on définit la fraction des arcs à utiliser la réciprocité
	f = dicProperties["Reciprocity"]
	rFracRecip =  f/(2.0-f)
	# on définit toutes les grandeurs de base
	rInDeg = dicProperties["InDeg"]
	rOutDeg = dicProperties["OutDeg"]
	nNodes = 0
	nEdges = 0
	rDens = 0.0
	if "Nodes" in dicProperties.keys():
		nNodes = dicProperties["Nodes"]
		graphFS.add_vertex(nNodes)
		if "Edges" in dicProperties.keys():
			nEdges = dicProperties["Edges"]
			rDens = nEdges / float(nNodes**2)
			dicProperties["Density"] = rDens
		else:
			rDens = dicProperties["Density"]
			nEdges = int(np.floor(rDens*nNodes**2))
			dicProperties["Edges"] = nEdges
	else:
		nEdges = dicProperties["Edges"]
		rDens = dicProperties["Density"]
		nNodes = int(np.floor(np.sqrt(nEdges/rDens)))
		graphFS.add_vertex(nNodes)
		dicProperties["Nodes"] = nNodes
	# on définit le nombre d'arcs à créer
	nArcs = int(np.floor(rDens*nNodes**2)/(1+rFracRecip))
	# on définit les paramètres fonctions de probabilité associées F(x) = A x^{-tau}
	Ai = nArcs*(rInDeg-1)/(nNodes)
	Ao = nArcs*(rOutDeg-1)/(nNodes)
	# on définit les moyennes des distributions de pareto 2 = lomax
	rMi = 1/(rInDeg-2.)
	rMo = 1/(rOutDeg-2.)
	# on définit les trois listes contenant les degrés sortant/entrant/bidirectionnels associés aux noeuds i in range(nNodes)
	lstInDeg = np.random.pareto(rInDeg,nNodes)+1
	lstOutDeg = np.random.pareto(rOutDeg,nNodes)+1
	lstInDeg = np.floor(np.multiply(Ai/np.mean(lstInDeg), lstInDeg)).astype(int)
	lstOutDeg = np.floor(np.multiply(Ao/np.mean(lstOutDeg), lstOutDeg)).astype(int)
	# on génère les stubs qui vont être nécessaires et on les compte
	nInStubs = int(np.sum(lstInDeg))
	nOutStubs = int(np.sum(lstOutDeg))
	lstInStubs = np.zeros(np.sum(lstInDeg))
	lstOutStubs = np.zeros(np.sum(lstOutDeg))
	nStartIn = 0
	nStartOut = 0
	for vert in range(nNodes):
		nInDegVert = lstInDeg[vert]
		nOutDegVert = lstOutDeg[vert]
		for j in range(np.max([nInDegVert,nOutDegVert])):
			if j < nInDegVert:
				lstInStubs[nStartIn+j] += vert
			if j < nOutDegVert:
				lstOutStubs[nStartOut+j] += vert
		nStartOut+=nOutDegVert
		nStartIn+=nInDegVert
	# on vérifie qu'on a à peu près le nombre voulu d'edges
	while nInStubs*(1+rFracRecip)/float(nArcs) < 0.95 :
		vert = np.random.randint(0,nNodes)
		nAddInStubs = int(np.floor(Ai/rMi*(np.random.pareto(rInDeg)+1)))
		lstInStubs = np.append(lstInStubs,np.repeat(vert,nAddInStubs)).astype(int)
		nInStubs+=nAddInStubs
	while nOutStubs*(1+rFracRecip)/float(nArcs) < 0.95 :
		nAddOutStubs = int(np.floor(Ao/rMo*(np.random.pareto(rOutDeg)+1)))
		lstOutStubs = np.append(lstOutStubs,np.repeat(vert,nAddOutStubs)).astype(int)
		nOutStubs+=nAddOutStubs
	# on s'assure d'avoir le même nombre de in et out stubs (1.13 is an experimental correction)
	nMaxStubs = int(1.13*(2.0*nArcs)/(2*(1+rFracRecip)))
	if nInStubs > nMaxStubs and nOutStubs > nMaxStubs:
		np.random.shuffle(lstInStubs)
		np.random.shuffle(lstOutStubs)
		lstOutStubs.resize(nMaxStubs)
		lstInStubs.resize(nMaxStubs)
		nOutStubs = nInStubs = nMaxStubs
	elif nInStubs < nOutStubs:
		np.random.shuffle(lstOutStubs)
		lstOutStubs.resize(nInStubs)
		nOutStubs = nInStubs
	else:
		np.random.shuffle(lstInStubs)
		lstInStubs.resize(nOutStubs)
		nInStubs = nOutStubs
	# on crée le graphe, les noeuds et les stubs
	nRecip = int(np.floor(nInStubs*rFracRecip))
	nEdges = nInStubs + nRecip +1
	# les stubs réciproques
	np.random.shuffle(lstInStubs)
	np.random.shuffle(lstOutStubs)
	lstInRecip = lstInStubs[0:nRecip]
	lstOutRecip = lstOutStubs[0:nRecip]
	lstEdges = np.array([np.concatenate((lstOutStubs,lstInRecip)),np.concatenate((lstInStubs,lstOutRecip))]).astype(int)
	# add edges
	graphFS.add_edge_list(np.transpose(lstEdges))
	remove_self_loops(graphFS)
	remove_parallel_edges(graphFS)
	lstIsolatedVert = find_vertex(graphFS, graphFS.degree_property_map("total"), 0)
	graphFS.remove_vertex(lstIsolatedVert)
	graphFS.reindex_edges()
	nNodes = graphFS.num_vertices()
	nEdges = graphFS.num_edges()
	rDens = nEdges / float(nNodes**2)
	# generate types
	rInhibFrac = dicProperties["InhibFrac"]
	lstTypesGen = np.random.uniform(0,1,nEdges)
	lstTypeLimit = np.full(nEdges,rInhibFrac)
	lstIsExcitatory = np.greater(lstTypesGen,lstTypeLimit)
	nExc = np.count_nonzero(lstIsExcitatory)
	epropType = graphFS.new_edge_property("int",np.multiply(2,lstIsExcitatory)-np.repeat(1,nEdges)) # excitatory (True) or inhibitory (False)
	graphFS.edge_properties["type"] = epropType
	# and weights
	if dicProperties["Weighted"]:
		lstWeights = dicGenWeights[dicProperties["Distribution"]](graphFS,dicProperties,nEdges,nExc) # generate the weights
		epropW = graphFS.new_edge_property("double",lstWeights) # crée la propriété pour stocker les poids
		graphFS.edge_properties["weight"] = epropW
	return graphFS
コード例 #36
0
ファイル: graphs.py プロジェクト: kalemaria/polyqIB
class SegmentationGraph(object):
    """
    Class defining the abstract SegmentationGraph object, its attributes and
    implements methods common to all derived graph classes.

    The constructor requires the following parameters of the underlying
    segmentation that will be used to build the graph.

    Args:
        scale_factor_to_nm (float): pixel size in nanometers for scaling the
            graph
        scale_x (int): x axis length in pixels of the segmentation
        scale_y (int): y axis length in pixels of the segmentation
        scale_z (int): z axis length in pixels of the segmentation
    """

    def __init__(self, scale_factor_to_nm, scale_x, scale_y, scale_z):
        """
        Constructor.

        Args:
            scale_factor_to_nm (float): pixel size in nanometers for scaling the
                graph
            scale_x (int): x axis length in pixels of the segmentation
            scale_y (int): y axis length in pixels of the segmentation
            scale_z (int): z axis length in pixels of the segmentation

        Returns:
            None
        """
        self.graph = Graph(directed=False)
        """graph_tool.Graph: a graph object storing the segmentation graph
        topology, geometry and properties.
        """
        self.scale_factor_to_nm = scale_factor_to_nm
        """float: pixel size in nanometers for scaling the coordinates and
        distances in the graph
        """
        self.scale_x = scale_x
        """int: x axis length in pixels of the segmentation"""
        self.scale_y = scale_y
        """int: y axis length in pixels of the segmentation"""
        self.scale_z = scale_z
        """int: z axis length in pixels of the segmentation"""

        # Add "internal property maps" to the graph.
        # vertex property for storing the xyz coordinates in nanometers of the
        # corresponding vertex:
        self.graph.vp.xyz = self.graph.new_vertex_property("vector<float>")
        # edge property for storing the distance in nanometers between the
        # connected vertices:
        self.graph.ep.distance = self.graph.new_edge_property("float")

        self.coordinates_to_vertex_index = {}
        """dist: a dictionary mapping the vertex coordinates in nanometers
        (x, y, z) to the vertex index.
        """
        self.coordinates_pair_connected = {}
        """dict: a dictionary storing pairs of vertex coordinates in nanometers
        that are connected by an edge as a key in a tuple form
        ((x1, y1, z1), (x2, y2, z2)) with value True.
        """

    @staticmethod
    def distance_between_voxels(voxel1, voxel2):
        """
        Calculates and returns the Euclidean distance between two voxels.

        Args:
            voxel1 (tuple): first voxel coordinates in form of a tuple of
                integers of length 3 (x1, y1, z1)
            voxel2 (tuple): second voxel coordinates in form of a tuple of
                integers of length 3 (x2, y2, z2)

        Returns:
            the Euclidean distance between two voxels (float)
        """
        if (isinstance(voxel1, tuple) and (len(voxel1) == 3) and
                isinstance(voxel2, tuple) and (len(voxel2) == 3)):
            sum_of_squared_differences = 0
            for i in range(3):  # for each dimension
                sum_of_squared_differences += (voxel1[i] - voxel2[i]) ** 2
            return math.sqrt(sum_of_squared_differences)
        else:
            error_msg = ('Tuples of integers of length 3 required as first and '
                         'second input.')
            raise pexceptions.PySegInputError(
                expr='distance_between_voxels (SegmentationGraph)',
                msg=error_msg
            )

    def update_coordinates_to_vertex_index(self):
        """
        Updates graph's dictionary coordinates_to_vertex_index.

        The dictionary maps the vertex coordinates (x, y, z) scaled in
        nanometers to the vertex index. It has to be updated after purging the
        graph, because vertices are renumbered, as well as after reading a graph
        from a file (e.g. before density calculation).

        Returns:
            None
        """
        self.coordinates_to_vertex_index = {}
        for vd in self.graph.vertices():
            [x, y, z] = self.graph.vp.xyz[vd]
            self.coordinates_to_vertex_index[
                (x, y, z)] = self.graph.vertex_index[vd]

    def calculate_density(self, mask=None, target_coordinates=None,
                          verbose=False):
        """
        Calculates ribosome density for each membrane graph vertex.

        Calculates shortest geodesic distances (d) for each vertex in the graph
        to each reachable ribosome center mapped on the membrane given by a
        binary mask with coordinates in pixels or an array of coordinates in nm.
        Then, calculates a density measure of ribosomes at each vertex or
        membrane voxel: D = sum {over all reachable ribosomes} (1 / (d + 1)).
        Adds the density as vertex PropertyMap to the graph. Returns an array
        with the same shape as the underlying segmentation with the densities
        plus 1, in order to distinguish membrane voxels with 0 density from the
        background.

        Args:
            mask (numpy.ndarray, optional): a binary mask of the ribosome
                centers as 3D array where indices are coordinates in pixels
                (default None)
            target_coordinates (numpy.ndarray, optional): the ribosome centers
                coordinates in nm as 2D array in format
                [[x1, y1, z1], [x2, y2, z2], ...] (default None)
            verbose (boolean, optional): if True (default False), some extra
                information will be printed out

        Returns:
            a 3D numpy ndarray with the densities + 1

        Note:
            One of the first two parameters, mask or target_coordinates, has to
            be given.
        """
        import ribosome_density as rd
        # If a mask is given, find the set of voxels of ribosome centers mapped
        # on the membrane, 'target_voxels', and rescale them to nm,
        # 'target_coordinates':
        if mask is not None:
            if mask.shape != (self.scale_x, self.scale_y, self.scale_z):
                error_msg = ("Scales of the input 'mask' have to be equal to "
                             "those set during the generation of the graph.")
                raise pexceptions.PySegInputError(
                    expr='calculate_density (SegmentationGraph)', msg=error_msg
                )
            # output as a list of tuples [(x1,y1,z1), (x2,y2,z2), ...] in pixels
            target_voxels = rd.get_foreground_voxels_from_mask(mask)
            # for rescaling have to convert to an ndarray
            target_ndarray_voxels = rd.tupel_list_to_ndarray_voxels(
                target_voxels
            )
            # rescale to nm, output an ndarray [[x1,y1,z1], [x2,y2,z2], ...]
            target_ndarray_coordinates = (target_ndarray_voxels
                                          * self.scale_factor_to_nm)
            # convert to a list of tuples, which are in nm now
            target_coordinates = rd.ndarray_voxels_to_tupel_list(
                target_ndarray_coordinates
            )
        # If target_coordinates are given (in nm), convert them from a numpy
        # ndarray to a list of tuples:
        elif target_coordinates is not None:
            target_coordinates = rd.ndarray_voxels_to_tupel_list(
                target_coordinates
            )
        # Exit if the target_voxels list is empty:
        if len(target_coordinates) == 0:
            error_msg = ("No target voxels were found! Check your input "
                         "('mask' or 'target_coordinates').")
            raise pexceptions.PySegInputError(
                expr='calculate_density (SegmentationGraph)', msg=error_msg
            )
        print '%s target voxels' % len(target_coordinates)
        if verbose:
            print target_coordinates

        # Pre-filter the target coordinates to those existing in the graph
        # (should already all be in the graph, but just in case):
        target_coordinates_in_graph = []
        for target_xyz in target_coordinates:
            if target_xyz in self.coordinates_to_vertex_index:
                target_coordinates_in_graph.append(target_xyz)
            else:
                error_msg = ('Target (%s, %s, %s) not inside the membrane!'
                             % (target_xyz[0], target_xyz[1], target_xyz[2]))
                raise pexceptions.PySegInputWarning(
                    expr='calculate_density (SegmentationGraph)', msg=error_msg
                )

        print '%s target coordinates in graph' % len(
            target_coordinates_in_graph)
        if verbose:
            print target_coordinates_in_graph

        # Get all indices of the target coordinates:
        target_vertices_indices = []
        for target_xyz in target_coordinates_in_graph:
            v_target_index = self.coordinates_to_vertex_index[target_xyz]
            target_vertices_indices.append(v_target_index)

        # Density calculation
        # Add a new vertex property to the graph, density:
        self.graph.vp.density = self.graph.new_vertex_property("float")
        # Dictionary mapping voxel coordinates (for the volume returned later)
        # to a list of density values falling within that voxel:
        voxel_to_densities = {}

        # For each vertex in the graph:
        for v_membrane in self.graph.vertices():
            # Get its coordinates:
            membrane_xyz = self.graph.vp.xyz[v_membrane]
            if verbose:
                print ('Membrane vertex (%s, %s, %s)'
                       % (membrane_xyz[0], membrane_xyz[1], membrane_xyz[2]))
            # Get a distance map with all pairs of distances between current
            # graph vertex (membrane_xyz) and target vertices (ribosome
            # coordinates):
            dist_map = shortest_distance(self.graph, source=v_membrane,
                                         target=target_vertices_indices,
                                         weights=self.graph.ep.distance)

            # Iterate over all shortest distances from the membrane vertex to
            # the target vertices, while calculating the density:
            # Initializing: membrane coordinates with no reachable ribosomes
            # will have a value of 0, those with reachable ribosomes > 0.
            density = 0
            # If there is only one target voxel, dist_map is a single value -
            # wrap it into a list.
            if len(target_coordinates_in_graph) == 1:
                dist_map = [dist_map]
            for d in dist_map:
                if verbose:
                    print '\tTarget vertex ...'
                # if unreachable, the maximum float64 is stored
                if d == np.finfo(np.float64).max:
                    if verbose:
                        print '\t\tunreachable'
                else:
                    if verbose:
                        print '\t\td = %s' % d
                    density += 1 / (d + 1)

            # Add the density of the membrane vertex as a property of the
            # current vertex in the graph:
            self.graph.vp.density[v_membrane] = density

            # Calculate the corresponding voxel of the vertex and add the
            # density to the list keyed by the voxel in the dictionary:
            # Scaling the coordinates back from nm to voxels. (Without round
            # float coordinates are truncated to the next lowest integer.)
            voxel_x = int(round(membrane_xyz[0] / self.scale_factor_to_nm))
            voxel_y = int(round(membrane_xyz[1] / self.scale_factor_to_nm))
            voxel_z = int(round(membrane_xyz[2] / self.scale_factor_to_nm))
            voxel = (voxel_x, voxel_y, voxel_z)
            if voxel in voxel_to_densities:
                voxel_to_densities[voxel].append(density)
            else:
                voxel_to_densities[voxel] = [density]

            if verbose:
                print '\tdensity = %s' % density
            if (self.graph.vertex_index[v_membrane] + 1) % 1000 == 0:
                now = datetime.now()
                print ('%s membrane vertices processed on: %s-%s-%s %s:%s:%s'
                       % (self.graph.vertex_index[v_membrane] + 1, now.year,
                          now.month, now.day, now.hour, now.minute, now.second))

        # Initialize an array scaled like the original segmentation, which will
        # hold in each membrane voxel the maximal density among the
        # corresponding vertex coordinates in the graph plus 1 and 0 in each
        # background (non-membrane) voxel:
        densities = np.zeros((self.scale_x, self.scale_y, self.scale_z),
                             dtype=np.float16)
        # The densities array membrane voxels are initialized with 1 in order to
        # distinguish membrane voxels from the background.
        for voxel in voxel_to_densities:
            densities[voxel[0], voxel[1], voxel[2]] = 1 + max(
                voxel_to_densities[voxel])
        if verbose:
            print 'densities:\n%s' % densities
        return densities

    def graph_to_points_and_lines_polys(self, vertices=True, edges=True,
                                        verbose=False):
        """
        Generates a VTK PolyData object from the graph with vertices as
        vertex-cells (containing 1 point) and edges as line-cells (containing 2
        points).

        Args:
            vertices (boolean, optional): if True (default) vertices are stored
                a VTK PolyData object as vertex-cells
            edges (boolean, optional): if True (default) edges are stored a VTK
                PolyData object as line-cells
            verbose (boolean, optional): if True (default False), some extra
                information will be printed out

        Returns:
            - vtk.vtkPolyData with vertex-cells
            - vtk.vtkPolyData with edges as line-cells
        """
        # Initialization
        poly_verts = vtk.vtkPolyData()
        poly_lines = vtk.vtkPolyData()
        points = vtk.vtkPoints()
        vertex_arrays = list()
        edge_arrays = list()
        # Vertex property arrays
        for prop_key in self.graph.vp.keys():
            data_type = self.graph.vp[prop_key].value_type()
            if (data_type != 'string' and data_type != 'python::object' and
                    prop_key != 'xyz'):
                if verbose:
                    print '\nvertex property key: %s' % prop_key
                    print 'value type: %s' % data_type
                if data_type[0:6] != 'vector':  # scalar
                    num_components = 1
                else:  # vector
                    num_components = len(
                        self.graph.vp[prop_key][self.graph.vertex(0)]
                    )
                array = TypesConverter().gt_to_vtk(data_type)
                array.SetName(prop_key)
                if verbose:
                    print 'number of components: %s' % num_components
                array.SetNumberOfComponents(num_components)
                vertex_arrays.append(array)
        # Edge property arrays
        for prop_key in self.graph.ep.keys():
            data_type = self.graph.ep[prop_key].value_type()
            if data_type != 'string' and data_type != 'python::object':
                if verbose:
                    print '\nedge property key: %s' % prop_key
                    print 'value type: %s' % data_type
                if data_type[0:6] != 'vector':  # scalar
                    num_components = 1
                else:  # vector (all edge properties so far are scalars)
                    # num_components = len(
                    #     self.graph.ep[prop_key][self.graph.edge(0, 1)]
                    # )
                    num_components = 3
                    if verbose:
                        print ('Sorry, not implemented yet, assuming a vector '
                               'with 3 components.')
                array = TypesConverter().gt_to_vtk(data_type)
                array.SetName(prop_key)
                if verbose:
                    print 'number of components: %s' % num_components
                array.SetNumberOfComponents(num_components)
                edge_arrays.append(array)
        if verbose:
            print '\nvertex arrays length: %s' % len(vertex_arrays)
            print 'edge arrays length: %s' % len(edge_arrays)

        # Geometry
        lut = np.zeros(shape=self.graph.num_vertices(), dtype=np.int)
        for i, vd in enumerate(self.graph.vertices()):
            [x, y, z] = self.graph.vp.xyz[vd]
            points.InsertPoint(i, x, y, z)
            lut[self.graph.vertex_index[vd]] = i
        if verbose:
            print 'number of points: %s' % points.GetNumberOfPoints()

        # Topology
        # Vertices
        verts = vtk.vtkCellArray()
        if vertices:
            for vd in self.graph.vertices():  # vd = vertex descriptor
                verts.InsertNextCell(1)
                verts.InsertCellPoint(lut[self.graph.vertex_index[vd]])
                for array in vertex_arrays:
                    prop_key = array.GetName()
                    n_comp = array.GetNumberOfComponents()
                    data_type = self.graph.vp[prop_key].value_type()
                    data_type = TypesConverter().gt_to_numpy(data_type)
                    array.InsertNextTuple(self.get_vertex_prop_entry(
                        prop_key, vd, n_comp, data_type))
            if verbose:
                print 'number of vertex cells: %s' % verts.GetNumberOfCells()
        # Edges
        lines = vtk.vtkCellArray()
        if edges:
            for ed in self.graph.edges():  # ed = edge descriptor
                lines.InsertNextCell(2)
                lines.InsertCellPoint(lut[self.graph.vertex_index[ed.source()]])
                lines.InsertCellPoint(lut[self.graph.vertex_index[ed.target()]])
                for array in edge_arrays:
                    prop_key = array.GetName()
                    n_comp = array.GetNumberOfComponents()
                    data_type = self.graph.ep[prop_key].value_type()
                    data_type = TypesConverter().gt_to_numpy(data_type)
                    array.InsertNextTuple(self.get_edge_prop_entry(
                        prop_key, ed, n_comp, data_type))
            if verbose:
                print 'number of line cells: %s' % lines.GetNumberOfCells()

        # vtkPolyData construction
        poly_verts.SetPoints(points)
        poly_lines.SetPoints(points)
        if vertices:
            poly_verts.SetVerts(verts)
        if edges:
            poly_lines.SetLines(lines)
        for array in vertex_arrays:
            poly_verts.GetCellData().AddArray(array)
        for array in edge_arrays:
            poly_lines.GetCellData().AddArray(array)

        return poly_verts, poly_lines

    def get_vertex_prop_entry(self, prop_key, vertex_descriptor, n_comp,
                              data_type):
        """
        Gets a property value of a vertex for inserting into a VTK vtkDataArray
        object.

        This private function is used by the methods
        graph_to_points_and_lines_polys and graph_to_triangle_poly (the latter
        of the derived class surface_graphs.TriangleGraph).

        Args:
            prop_key (str): name of the desired vertex property
            vertex_descriptor (graph_tool.Vertex): vertex descriptor of the
                current vertex
            n_comp (int): number of components of the array (length of the
                output tuple)
            data_type: numpy data type converted from a graph-tool property
                value type by TypesConverter().gt_to_numpy

        Returns:
            a tuple (with length like n_comp) with the property value of the
            vertex converted to a numpy data type
        """
        prop = list()
        if n_comp == 1:
            prop.append(data_type(self.graph.vp[prop_key][vertex_descriptor]))
        else:
            for i in range(n_comp):
                prop.append(data_type(
                            self.graph.vp[prop_key][vertex_descriptor][i]))
        return tuple(prop)

    def get_edge_prop_entry(self, prop_key, edge_descriptor, n_comp, data_type):
        """
        Gets a property value of an edge for inserting into a VTK vtkDataArray
        object.

        This private function is used by the method
        graph_to_points_and_lines_polys.

        Args:
            prop_key (str): name of the desired vertex property
            edge_descriptor (graph_tool.Edge): edge descriptor of the current
                edge
            n_comp (int): number of components of the array (length of the
                output tuple)
            data_type: numpy data type converted from a graph-tool property
                value type by TypesConverter().gt_to_numpy

        Returns:
            a tuple (with length like n_comp) with the property value of the
            edge converted to a numpy data type
        """
        prop = list()
        if n_comp == 1:
            prop.append(data_type(self.graph.ep[prop_key][edge_descriptor]))
        else:
            for i in range(n_comp):
                prop.append(data_type(
                            self.graph.ep[prop_key][edge_descriptor][i]))
        return tuple(prop)

    # * The following SegmentationGraph methods are needed for the normal vector
    # voting algorithm. *

    def calculate_average_edge_length(self, prop_e=None, value=1):
        """
        Calculates the average edge length in the graph.

        If a special edge property is specified, includes only the edges where
        this property equals the given value. If there are no edges in the
        graph, the given property does not exist or there are no edges with the
        given property equaling the given value, None is returned.

        Args:
            prop_e (str, optional): edge property, if specified only edges where
                this property equals the given value will be considered
            value (int, optional): value of the specified edge property an edge
                has to have in order to be considered (default 1)

        Returns:
            the average edge length in the graph (float) or None
        """
        total_edge_length = 0
        average_edge_length = None
        if prop_e is None:
            print "Considering all edges:"
            for ed in self.graph.edges():
                total_edge_length += self.graph.ep.distance[ed]
            if self.graph.num_edges() > 0:
                average_edge_length = total_edge_length / self.graph.num_edges()
            else:
                print "There are no edges in the graph!"
        elif prop_e in self.graph.edge_properties:
            print ("Considering only edges with property %s equaling value %s "
                   % (prop_e, value))
            num_special_edges = 0
            for ed in self.graph.edges():
                if self.graph.edge_properties[prop_e][ed] == value:
                    num_special_edges += 1
                    total_edge_length += self.graph.ep.distance[ed]
            if num_special_edges > 0:
                average_edge_length = total_edge_length / num_special_edges
            else:
                print ("There are no edges with the property %s equaling value "
                       "%s!" % (prop_e, value))
        print "Average length: %s" % average_edge_length
        return average_edge_length

    def find_geodesic_neighbors(self, v, g_max, verbose=False):
        """
        Finds geodesic neighbor vertices of a given vertex v in the graph that
        are within a given maximal geodesic distance g_max from it.

        Also finds the corresponding geodesic distances. All edges are
        considered.

        Args:
            v (graph_tool.Vertex): the source vertex
            g_max: maximal geodesic distance (in nanometers, if the graph was
                scaled)
            verbose (boolean, optional): if True (default False), some extra
                information will be printed out

        Returns:
            a dictionary mapping a neighbor vertex index to the geodesic
            distance from vertex v
        """
        dist_v = shortest_distance(self.graph, source=v, target=None,
                                   weights=self.graph.ep.distance,
                                   max_dist=g_max)
        dist_v = dist_v.get_array()

        neighbor_id_to_dist = dict()

        idxs = np.where(dist_v <= g_max)[0]
        for idx in idxs:
            dist = dist_v[idx]
            if dist != 0:  # ignore the source vertex itself
                neighbor_id_to_dist[idx] = dist

        if verbose:
            print "%s neighbors" % len(neighbor_id_to_dist)
        return neighbor_id_to_dist

    def get_vertex_property_array(self, property_name):
        """
        Gets a numpy array with all values of a vertex property of the graph,
        printing out the number of values, the minimal and the maximal value.

        Args:
            property_name (str): vertex property name

        Returns:
            an array (numpy.ndarray) with all values of the vertex property
        """
        if (isinstance(property_name, str) and
                property_name in self.graph.vertex_properties):
            values = self.graph.vertex_properties[property_name].get_array()
            print '%s "%s" values' % (len(values), property_name)
            print 'min = %s, max = %s' % (min(values), max(values))
            return values
        else:
            error_msg = ('The input "%s" is not a str object or is not found '
                         'in vertex properties of the graph.' % property_name)
            raise pexceptions.PySegInputError(
                expr='get_vertex_property_array (SegmentationGraph)',
                msg=error_msg)
コード例 #37
0
ファイル: Segmentation.py プロジェクト: abucksch/DIRT
    def makeGraphFast(self,img,dia,xScale,yScale):
        print('Building Graph Data Structure'),
        start=time.time()
        G = Graph(directed=False)
        sumAddVertices=0
        
        vprop=G.new_vertex_property('object')
        eprop=G.new_edge_property('object')
        epropW=G.new_edge_property("float")
        h, w = np.shape(img)
        if xScale>0 and yScale>0: avgScale=(xScale+yScale)/2
        else: 
            avgScale=1.
            xScale=1.
            yScale=1.
        addedVerticesLine2=[]
        vListLine2=[]
        percentOld=0
        counter=0
        '''
        Sweep over each line in the image except the last line
        '''
        for idx,i in enumerate(img[:len(img)-2]):
            '''
            Get foreground indices in the current line of the image and make vertices
            '''
            counter+=1
            percent=(float(counter)/float(h))*100
            if percentOld+10< percent: 
                print (str(np.round(percent,1))+'% '),
                percentOld=percent

            line1=np.where(i==True)
            if len(line1[0])>0:
                line1=set(line1[0]).difference(set(addedVerticesLine2))
                vL=G.add_vertex(len(list(line1)))
                
                
                if len(line1)>1 : 
                    vList=vListLine2+list(vL)
                else: vList=vListLine2+[vL]
                line1=addedVerticesLine2+list(line1)
                for jdx,j in enumerate(line1):
                    vprop[vList[jdx]]={'imgIdx':(j,idx),'coord': (float(j)*xScale,float(idx)*yScale), 'nrOfPaths':0, 'diameter':float(dia[idx][j])*avgScale}
                '''
                keep order of the inserted vertices
                '''
                sumAddVertices+=len(line1)
                
                addedVerticesLine2=[]
                vListLine2=[]
                '''
                Connect foreground indices to neighbours in the next line
                '''
                for v1 in line1:
                    va=vList[line1.index(v1)]
                    diagonalLeft = diagonalRight = True
                    try:
                        if img[idx][v1-1]==True:
                            diagonalLeft=False
                            vb=vList[line1.index(v1-1)]
                            e=G.add_edge(va,vb)
                            eprop[e]={'coord1':vprop[va]['coord'], 'coord2':vprop[vb]['coord'],'weight':((vprop[va]['diameter']+vprop[vb]['diameter'])/2),'RTP':False}
                            epropW[e]=2./(eprop[e]['weight']**2)
                    except:
                        print 'Boundary vertex at: '+str([v1,idx-1])+' image size: '+ str([w,h])
                        pass
                    
                    try:
                        if img[idx][v1+1]==True:
                            diagonalRight=False
                            vb=vList[line1.index(v1+1)]
                            e=G.add_edge(va,vb)
                            eprop[e]={'coord1':vprop[va]['coord'], 'coord2':vprop[vb]['coord'],'weight':((vprop[va]['diameter']+vprop[vb]['diameter'])/2),'RTP':False}
                            epropW[e]=2./(eprop[e]['weight']**2)
                    except:
                        print 'Boundary vertex at: '+str([v1+1,idx])+' image size: '+ str([w,h])
                        pass # just if we are out of bounds
                    
                    try:
                        if img[idx+1][v1]==True:
                            diagonalRight=False
                            diagonalLeft=False
                            vNew=G.add_vertex()
                            vprop[vNew]={'imgIdx':(v1,idx+1),'coord': (float(v1)*xScale,float(idx+1)*yScale), 'nrOfPaths':0, 'diameter':float(dia[idx+1][v1])*avgScale}
                            vListLine2.append(vNew)
                            e=G.add_edge(vList[line1.index(v1)],vNew)
                            eprop[e]={'coord1':vprop[va]['coord'], 'coord2':vprop[vNew]['coord'],'weight':((vprop[va]['diameter']+vprop[vNew]['diameter'])/2),'RTP':False}
                            epropW[e]=1./(eprop[e]['weight']**2)
                            if v1 not in addedVerticesLine2: addedVerticesLine2.append(v1)
                    except:
                        print 'Boundary vertex at: '+str([v1,idx+1])+' image size: '+ str([w,h])
                        pass
                    
                    try:    
                        if diagonalRight == True and img[idx+1][v1+1]==True:
                            vNew=G.add_vertex()
                            vprop[vNew]={'imgIdx':(v1+1,idx+1),'coord': (float(v1+1)*xScale,float(idx+1)*yScale), 'nrOfPaths':0, 'diameter':float(dia[idx+1][v1+1])*avgScale}
                            vListLine2.append(vNew)
                            e=G.add_edge(vList[line1.index(v1)],vNew)
                            eprop[e]={'coord1':vprop[va]['coord'], 'coord2':vprop[vNew]['coord'],'weight':((vprop[va]['diameter']+vprop[vNew]['diameter'])/2),'RTP':False}
                            epropW[e]=1.41/(eprop[e]['weight']**2)
                            if v1+1 not in addedVerticesLine2: addedVerticesLine2.append(v1+1)
                    except:
                        print 'Boundary vertex at: '+str([v1+1,idx+1])+' image size: '+ str([w,h])
                        pass
                    
                    try:
                        if diagonalLeft  == True and img[idx+1][v1-1]==True:
                            vNew=G.add_vertex()
                            vprop[vNew]={'imgIdx':(v1-1,idx+1),'coord': (float(v1-1)*xScale,float(idx+1)*yScale), 'nrOfPaths':0, 'diameter':float(dia[idx+1][v1-1])*avgScale}
                            vListLine2.append(vNew)
                            e=G.add_edge(vList[line1.index(v1)],vNew)
                            eprop[e]={'coord1':vprop[va]['coord'], 'coord2':vprop[vNew]['coord'],'weight':((vprop[va]['diameter']+vprop[vNew]['diameter'])/2),'RTP':False}
                            epropW[e]=1.41/(eprop[e]['weight']**2)
                            if v1-1 not in addedVerticesLine2: addedVerticesLine2.append(v1-1)
                    except:
                        print 'Boundary vertex at: '+str([v1-1,idx+1])+' image size: '+ str([w,h])
                        pass
                    try:
                        if img[idx][v1+1]==False and img[idx][v1-1]==False and img[idx+1][v1]==False and diagonalLeft==False and diagonalRight==False:
                            print 'tip detected'
                            if img[idx-1][v1-1]==False and img[idx-1][v1+1]==False and img[idx-1][v1]==False:
                                print 'floating pixel'
                    except:
                        pass
        
        print'done!'                               
        G.edge_properties["ep"] = eprop
        G.edge_properties["w"] = epropW
        G.vertex_properties["vp"] = vprop            
        print 'graph build in '+str(time.time()-start)
        l = gt.label_largest_component(G)
        u = gt.GraphView(G, vfilt=l)
        print '# vertices'
        print(u.num_vertices())
        print(G.num_vertices())
        if u.num_vertices()!=G.num_vertices(): self.__fail=float((G.num_vertices()-u.num_vertices()))/float(G.num_vertices())
        return u,u.num_vertices()
コード例 #38
0
def main():
    conn = serial_interface.connect()

    cur_track = track.init_tracka()
    g = Graph()
    g.add_vertex(len(cur_track))
    for (vi, node) in enumerate(cur_track):
        node.i = vi

    n_title = g.new_vertex_property("string")
    n_color = g.new_vertex_property("string")
    n_pos = g.new_vertex_property("vector<double>")
    e_title = g.new_edge_property("string")
    e_dist = g.new_edge_property("double")

    for node in cur_track:
        v = g.vertex(node.i)
        n_title[v] = node.name
        if node.typ == track.NODE_EXIT:
            # Invert points to match our ASCII display.
            n_pos[v] = (-node.reverse.coord_x, -node.reverse.coord_y)
        else:
            n_pos[v] = (-node.coord_x, -node.coord_y)
        e = g.add_edge(g.vertex(node.i), g.vertex(node.reverse.i))
        if node.typ == track.NODE_SENSOR: n_color[v] = "blue"
        elif node.typ == track.NODE_BRANCH: n_color[v] = "orange"
        elif node.typ == track.NODE_MERGE: n_color[v] = "yellow"
        elif node.typ == track.NODE_ENTER: n_color[v] = "green"
        elif node.typ == track.NODE_EXIT: n_color[v] = "red"
        else: n_color[v] = "white"
        for edge in node.edge:
            if edge.src is None: continue
            e = g.add_edge(g.vertex(edge.src.i), g.vertex(edge.dest.i))
            e_dist[e] = edge.dist
            e_title[e] = "%.2f" % (edge.dist)

    win = graph_tool.draw.GraphWindow(g,
                                      n_pos, (640, 480),
                                      edge_text=e_title,
                                      vertex_fill_color=n_color,
                                      vertex_text=n_title)
    win.show_all()

    def destroy_callback(*args, **kwargs):
        win.destroy()
        Gtk.main_quit()

    def set_switch(sw, d):
        for node in cur_track:
            if node.typ == track.NODE_BRANCH and node.num == sw:
                node.switch_direction = d
                return
        print "WARN: Could not find switch %d" % sw

    class Train():
        num = -1
        vel = 0.
        speed = 0.
        edge = cur_track[0].edge[0]
        edge_dist = 0
        SPEEDX = 1.

        def __init__(self, num):
            self.num = num

        def update(self):
            # Super shitty deacceleration model
            self.vel = self.vel + (0.018 / self.SPEEDX) * (self.speed -
                                                           self.vel)
            self.edge_dist += self.vel
            while True:
                e = self.e()
                if self.edge_dist < e_dist[e]: break
                if self.edge.dest.typ == track.NODE_SENSOR:
                    conn.set_sensor_tripped(self.edge.dest.num)
                self.edge = self.edge.dest.edge[
                    self.edge.dest.switch_direction]
                self.edge_dist -= e_dist[e]

        def draw(self, n_pos, da, cr):
            e = self.e()
            start, end = np.array(n_pos[e.source()]), np.array(
                n_pos[e.target()])
            alpha = self.edge_dist / e_dist[e]
            pos = start + alpha * (end - start)
            dp = win.graph.pos_to_device(pos)  # dp: device position
            cr.rectangle(dp[0] - 10, dp[1] - 10, 20, 20)
            cr.set_source_rgb(102. / 256, 102. / 256, 102. / 256)
            cr.fill()
            cr.move_to(dp[0] - 10, dp[1] + 10 - 12. / 2)
            cr.set_source_rgb(1., 1., 1.)
            cr.set_font_size(12)
            cr.show_text("%d" % self.num)
            cr.fill()

        def e(self):
            return g.edge(self.edge.src.i, self.edge.dest.i)

        def set_speed(self, speed):
            self.speed = speed / self.SPEEDX

        def toggle_reverse(self):
            self.edge = self.edge.reverse
            self.edge_dist = e_dist[self.e()] - self.edge_dist

    def find_train(train_number):
        for train in trains:
            if train.num == train_number:
                return train
        train = Train(train_number)
        trains.append(train)
        return train

    trains = [Train(12)]
    startup_time = time.time()
    accumulated_error = [0.]
    last_time = [time.time()]
    last_sensor_poll = [0]
    FPS = 30.

    def my_draw(da, cr):
        (typ, a1, a2) = conn.next_cmd()
        if typ is None: pass
        elif typ == 'set_speed': find_train(a1).set_speed(a2)
        elif typ == 'toggle_reverse': find_train(a1).toggle_reverse()
        elif typ == 'switch': set_switch(a1, a2)
        elif typ == 'sensor':
            last_sensor_poll[0] = round(
                (time.time() - startup_time) * 1000) / 1000
        else:
            print "Ignoring command %s" % typ
        cur_time = time.time()
        dt = cur_time - last_time[0] + accumulated_error[0]
        num_steps = int(dt * FPS)
        accumulated_error[0] = dt - num_steps / FPS
        for train in trains:
            for _ in range(0, num_steps):
                train.update()
            train.draw(n_pos, da, cr)
            cr.move_to(10., 10.)
            cr.set_source_rgb(0., 0., 0.)
            cr.set_font_size(12)
            cr.show_text("Last polled at %.3f" % last_sensor_poll[0])
        da.queue_draw()
        last_time[0] = cur_time

    win.connect("delete_event", destroy_callback)
    win.graph.connect("draw", my_draw)
    Gtk.main()
コード例 #39
0
class SegmentationGraph(object):
    """
    Class defining the abstract SegmentationGraph object, its attributes and
    implements methods common to all derived graph classes.

    The constructor requires the following parameters of the underlying
    segmentation that will be used to build the graph.
    """
    def __init__(self):
        """
        Constructor of the abstract SegmentationGraph object.

        Returns:
            None
        """
        self.graph = Graph(directed=False)
        """graph_tool.Graph: a graph object storing the segmentation graph
        topology, geometry and properties (initially empty).
        """

        # Add "internal property maps" to the graph.
        # vertex property for storing the xyz coordinates of the corresponding
        # vertex:
        self.graph.vp.xyz = self.graph.new_vertex_property("vector<float>")
        # edge property for storing the distance between the connected vertices:
        self.graph.ep.distance = self.graph.new_edge_property("float")

        self.coordinates_to_vertex_index = {}
        """dict: a dictionary mapping the vertex coordinates (x, y, z) to the
        vertex index.
        """
        self.coordinates_pair_connected = set()
        """set: a set storing pairs of vertex coordinates that are
        connected by an edge in a tuple form ((x1, y1, z1), (x2, y2, z2)).
        """

    @staticmethod
    def distance_between_voxels(voxel1, voxel2):
        """
        Calculates and returns the Euclidean distance between two voxels.

        Args:
            voxel1 (tuple): first voxel coordinates in form of a tuple of
                floats of length 3 (x1, y1, z1)
            voxel2 (tuple): second voxel coordinates in form of a tuple of
                floats of length 3 (x2, y2, z2)

        Returns:
            the Euclidean distance between two voxels (float)
        """
        if (isinstance(voxel1, tuple) and (len(voxel1) == 3)
                and isinstance(voxel2, tuple) and (len(voxel2) == 3)):
            sum_of_squared_differences = 0
            for i in range(3):  # for each dimension
                sum_of_squared_differences += (voxel1[i] - voxel2[i])**2
            return math.sqrt(sum_of_squared_differences)
        else:
            raise pexceptions.PySegInputError(
                expr='distance_between_voxels (SegmentationGraph)',
                msg=('Tuples of integers of length 3 required as first and '
                     'second input.'))

    def update_coordinates_to_vertex_index(self):
        """
        Updates graph's dictionary coordinates_to_vertex_index.

        The dictionary maps the vertex coordinates (x, y, z) to the vertex
        index. It has to be updated after purging the graph, because vertices
        are renumbered, as well as after reading a graph from a file (e.g.
        before density calculation).

        Returns:
            None
        """
        self.coordinates_to_vertex_index = {}
        for vd in self.graph.vertices():
            [x, y, z] = self.graph.vp.xyz[vd]
            self.coordinates_to_vertex_index[(x, y,
                                              z)] = self.graph.vertex_index[vd]

    def calculate_density(self,
                          size,
                          scale,
                          mask=None,
                          target_coordinates=None,
                          verbose=False):
        """
        Calculates ribosome density for each membrane graph vertex.

        Calculates shortest geodesic distances (d) for each vertex in the graph
        to each reachable ribosome center mapped on the membrane given by a
        binary mask with coordinates in pixels or an array of coordinates in
        given units.
        Then, calculates a density measure of ribosomes at each vertex or
        membrane voxel: D = sum {over all reachable ribosomes} (1 / (d + 1)).
        Adds the density as vertex PropertyMap to the graph. Returns an array
        with the same shape as the underlying segmentation with the densities
        plus 1, in order to distinguish membrane voxels with 0 density from the
        background.

        Args:
            size (tuple): size in voxels (X, Y, Z) of the original segmentation
            scale (tuple): pixel size (X, Y, Z) in given units of the original
                segmentation
            mask (numpy.ndarray, optional): a binary mask of the ribosome
                centers as 3D array where indices are coordinates in pixels
                (default None)
            target_coordinates (numpy.ndarray, optional): the ribosome centers
                coordinates in given units as 2D array in format
                [[x1, y1, z1], [x2, y2, z2], ...] (default None)
            verbose (boolean, optional): if True (default False), some extra
                information will be printed out

        Returns:
            a 3D numpy ndarray with the densities + 1

        Note:
            One of the two parameters, mask or target_coordinates, has to be
            given.
        """
        from . import ribosome_density as rd
        # If a mask is given, find the set of voxels of ribosome centers mapped
        # on the membrane, 'target_voxels', and rescale them to units,
        # 'target_coordinates':
        if mask is not None:
            if mask.shape != size:
                raise pexceptions.PySegInputError(
                    expr='calculate_density (SegmentationGraph)',
                    msg=("Size of the input 'mask' have to be equal to those "
                         "set during the generation of the graph."))
            # output as a list of tuples [(x1,y1,z1), (x2,y2,z2), ...] in pixels
            target_voxels = rd.get_foreground_voxels_from_mask(mask)
            # for rescaling have to convert to an ndarray
            target_ndarray_voxels = rd.tupel_list_to_ndarray_voxels(
                target_voxels)
            # rescale to units, output an ndarray [[x1,y1,z1], [x2,y2,z2], ...]
            target_ndarray_coordinates = (target_ndarray_voxels *
                                          np.asarray(scale))
            # convert to a list of tuples, which are in units now
            target_coordinates = rd.ndarray_voxels_to_tupel_list(
                target_ndarray_coordinates)
        # If target_coordinates are given (in units), convert them from a numpy
        # ndarray to a list of tuples:
        elif target_coordinates is not None:
            target_coordinates = rd.ndarray_voxels_to_tupel_list(
                target_coordinates)
        # Exit if the target_voxels list is empty:
        if len(target_coordinates) == 0:
            raise pexceptions.PySegInputError(
                expr='calculate_density (SegmentationGraph)',
                msg="No target voxels were found! Check your input ('mask' or "
                "'target_coordinates').")
        print('{} target voxels'.format(len(target_coordinates)))
        if verbose:
            print(target_coordinates)

        # Pre-filter the target coordinates to those existing in the graph
        # (should already all be in the graph, but just in case):
        target_coordinates_in_graph = []
        for target_xyz in target_coordinates:
            if target_xyz in self.coordinates_to_vertex_index:
                target_coordinates_in_graph.append(target_xyz)
            else:
                raise pexceptions.PySegInputWarning(
                    expr='calculate_density (SegmentationGraph)',
                    msg=('Target ({}, {}, {}) not inside the membrane!'.format(
                        target_xyz[0], target_xyz[1], target_xyz[2])))

        print('{} target coordinates in graph'.format(
            len(target_coordinates_in_graph)))
        if verbose:
            print(target_coordinates_in_graph)

        # Get all indices of the target coordinates:
        target_vertices_indices = []
        for target_xyz in target_coordinates_in_graph:
            v_target_index = self.coordinates_to_vertex_index[target_xyz]
            target_vertices_indices.append(v_target_index)

        # Density calculation
        # Add a new vertex property to the graph, density:
        self.graph.vp.density = self.graph.new_vertex_property("float")
        # Dictionary mapping voxel coordinates (for the volume returned later)
        # to a list of density values falling within that voxel:
        voxel_to_densities = {}

        # For each vertex in the graph:
        for v_membrane in self.graph.vertices():
            # Get its coordinates:
            membrane_xyz = self.graph.vp.xyz[v_membrane]
            if verbose:
                print('Membrane vertex ({}, {}, {})'.format(
                    membrane_xyz[0], membrane_xyz[1], membrane_xyz[2]))
            # Get a distance map with all pairs of distances between current
            # graph vertex (membrane_xyz) and target vertices (ribosome
            # coordinates):
            dist_map = shortest_distance(self.graph,
                                         source=v_membrane,
                                         target=target_vertices_indices,
                                         weights=self.graph.ep.distance)

            # Iterate over all shortest distances from the membrane vertex to
            # the target vertices, while calculating the density:
            # Initializing: membrane coordinates with no reachable ribosomes
            # will have a value of 0, those with reachable ribosomes > 0.
            density = 0
            # If there is only one target voxel, dist_map is a single value -
            # wrap it into a list.
            if len(target_coordinates_in_graph) == 1:
                dist_map = [dist_map]
            for d in dist_map:
                if verbose:
                    print('\tTarget vertex ...')
                # if unreachable, the maximum float64 is stored
                if d == np.finfo(np.float64).max:
                    if verbose:
                        print('\t\tunreachable')
                else:
                    if verbose:
                        print('\t\td = {}'.format(d))
                    density += 1 / (d + 1)

            # Add the density of the membrane vertex as a property of the
            # current vertex in the graph:
            self.graph.vp.density[v_membrane] = density

            # Calculate the corresponding voxel of the vertex and add the
            # density to the list keyed by the voxel in the dictionary:
            # Scaling the coordinates back from units to voxels. (Without round
            # float coordinates are truncated to the next lowest integer.)
            voxel_x = int(round(membrane_xyz[0] / scale[0]))
            voxel_y = int(round(membrane_xyz[1] / scale[1]))
            voxel_z = int(round(membrane_xyz[2] / scale[2]))
            voxel = (voxel_x, voxel_y, voxel_z)
            if voxel in voxel_to_densities:
                voxel_to_densities[voxel].append(density)
            else:
                voxel_to_densities[voxel] = [density]

            if verbose:
                print('\tdensity = {}'.format(density))
            if (self.graph.vertex_index[v_membrane] + 1) % 1000 == 0:
                now = datetime.now()
                print('{} membrane vertices processed on: {}-{}-{} {}:{}:{}'.
                      format(self.graph.vertex_index[v_membrane] + 1, now.year,
                             now.month, now.day, now.hour, now.minute,
                             now.second))

        # Initialize an array scaled like the original segmentation, which will
        # hold in each membrane voxel the maximal density among the
        # corresponding vertex coordinates in the graph plus 1 and 0 in each
        # background (non-membrane) voxel:
        densities = np.zeros(size, dtype=np.float16)
        # The densities array membrane voxels are initialized with 1 in order to
        # distinguish membrane voxels from the background.
        for voxel in voxel_to_densities:
            densities[voxel[0], voxel[1],
                      voxel[2]] = 1 + max(voxel_to_densities[voxel])
        if verbose:
            print('densities:\n{}'.format(densities))
        return densities

    def graph_to_points_and_lines_polys(self,
                                        vertices=True,
                                        edges=True,
                                        verbose=False):
        """
        Generates a VTK PolyData object from the graph with vertices as
        vertex-cells (containing 1 point) and edges as line-cells (containing 2
        points).

        Args:
            vertices (boolean, optional): if True (default) vertices are stored
                a VTK PolyData object as vertex-cells
            edges (boolean, optional): if True (default) edges are stored a VTK
                PolyData object as line-cells
            verbose (boolean, optional): if True (default False), some extra
                information will be printed out

        Returns:
            - vtk.vtkPolyData with vertex-cells
            - vtk.vtkPolyData with edges as line-cells
        """
        # Initialization
        poly_verts = vtk.vtkPolyData()
        poly_lines = vtk.vtkPolyData()
        points = vtk.vtkPoints()
        vertex_arrays = list()
        edge_arrays = list()
        # Vertex property arrays
        for prop_key in list(self.graph.vp.keys()):
            data_type = self.graph.vp[prop_key].value_type()
            if (data_type != 'string' and data_type != 'python::object'
                    and prop_key != 'xyz'):
                if verbose:
                    print('\nvertex property key: {}'.format(prop_key))
                    print('value type: {}'.format(data_type))
                if data_type[0:6] != 'vector':  # scalar
                    num_components = 1
                else:  # vector
                    num_components = len(
                        self.graph.vp[prop_key][self.graph.vertex(0)])
                array = TypesConverter().gt_to_vtk(data_type)
                array.SetName(prop_key)
                if verbose:
                    print('number of components: {}'.format(num_components))
                array.SetNumberOfComponents(num_components)
                vertex_arrays.append(array)
        # Edge property arrays
        for prop_key in list(self.graph.ep.keys()):
            data_type = self.graph.ep[prop_key].value_type()
            if data_type != 'string' and data_type != 'python::object':
                if verbose:
                    print('\nedge property key: {}'.format(prop_key))
                    print('value type: {}'.format(data_type))
                if data_type[0:6] != 'vector':  # scalar
                    num_components = 1
                else:  # vector (all edge properties so far are scalars)
                    # num_components = len(
                    #     self.graph.ep[prop_key][self.graph.edge(0, 1)])
                    num_components = 3
                    if verbose:
                        print('Sorry, not implemented yet, assuming a vector '
                              'with 3 components.')
                array = TypesConverter().gt_to_vtk(data_type)
                array.SetName(prop_key)
                if verbose:
                    print('number of components: {}'.format(num_components))
                array.SetNumberOfComponents(num_components)
                edge_arrays.append(array)
        if verbose:
            print('\nvertex arrays length: {}'.format(len(vertex_arrays)))
            print('edge arrays length: {}'.format(len(edge_arrays)))

        # Geometry
        lut = np.zeros(shape=self.graph.num_vertices(), dtype=np.int)
        for i, vd in enumerate(self.graph.vertices()):
            [x, y, z] = self.graph.vp.xyz[vd]
            points.InsertPoint(i, x, y, z)
            lut[self.graph.vertex_index[vd]] = i
        if verbose:
            print('number of points: {}'.format(points.GetNumberOfPoints()))

        # Topology
        # Vertices
        verts = vtk.vtkCellArray()
        if vertices:
            for vd in self.graph.vertices():  # vd = vertex descriptor
                verts.InsertNextCell(1)
                verts.InsertCellPoint(lut[self.graph.vertex_index[vd]])
                for array in vertex_arrays:
                    prop_key = array.GetName()
                    n_comp = array.GetNumberOfComponents()
                    data_type = self.graph.vp[prop_key].value_type()
                    data_type = TypesConverter().gt_to_numpy(data_type)
                    array.InsertNextTuple(
                        self.get_vertex_prop_entry(prop_key, vd, n_comp,
                                                   data_type))
            if verbose:
                print('number of vertex cells: {}'.format(
                    verts.GetNumberOfCells()))
        # Edges
        lines = vtk.vtkCellArray()
        if edges:
            for ed in self.graph.edges():  # ed = edge descriptor
                lines.InsertNextCell(2)
                lines.InsertCellPoint(
                    lut[self.graph.vertex_index[ed.source()]])
                lines.InsertCellPoint(
                    lut[self.graph.vertex_index[ed.target()]])
                for array in edge_arrays:
                    prop_key = array.GetName()
                    n_comp = array.GetNumberOfComponents()
                    data_type = self.graph.ep[prop_key].value_type()
                    data_type = TypesConverter().gt_to_numpy(data_type)
                    array.InsertNextTuple(
                        self.get_edge_prop_entry(prop_key, ed, n_comp,
                                                 data_type))
            if verbose:
                print('number of line cells: {}'.format(
                    lines.GetNumberOfCells()))

        # vtkPolyData construction
        poly_verts.SetPoints(points)
        poly_lines.SetPoints(points)
        if vertices:
            poly_verts.SetVerts(verts)
        if edges:
            poly_lines.SetLines(lines)
        for array in vertex_arrays:
            poly_verts.GetCellData().AddArray(array)
        for array in edge_arrays:
            poly_lines.GetCellData().AddArray(array)

        return poly_verts, poly_lines

    def get_vertex_prop_entry(self, prop_key, vertex_descriptor, n_comp,
                              data_type):
        """
        Gets a property value of a vertex for inserting into a VTK vtkDataArray
        object.

        This function is used by the methods graph_to_points_and_lines_polys and
        graph_to_triangle_poly (the latter of the derived classes PointGraph and
        TriangleGraph (in surface_graphs).

        Args:
            prop_key (str): name of the desired vertex property
            vertex_descriptor (graph_tool.Vertex): vertex descriptor of the
                current vertex
            n_comp (int): number of components of the array (length of the
                output tuple)
            data_type: numpy data type converted from a graph-tool property
                value type by TypesConverter().gt_to_numpy

        Returns:
            a tuple (with length like n_comp) with the property value of the
            vertex converted to a numpy data type
        """
        prop = list()
        if n_comp == 1:
            prop.append(data_type(self.graph.vp[prop_key][vertex_descriptor]))
        else:
            for i in range(n_comp):
                prop.append(
                    data_type(self.graph.vp[prop_key][vertex_descriptor][i]))
        return tuple(prop)

    def get_edge_prop_entry(self, prop_key, edge_descriptor, n_comp,
                            data_type):
        """
        Gets a property value of an edge for inserting into a VTK vtkDataArray
        object.

        This private function is used by the method
        graph_to_points_and_lines_polys.

        Args:
            prop_key (str): name of the desired vertex property
            edge_descriptor (graph_tool.Edge): edge descriptor of the current
                edge
            n_comp (int): number of components of the array (length of the
                output tuple)
            data_type: numpy data type converted from a graph-tool property
                value type by TypesConverter().gt_to_numpy

        Returns:
            a tuple (with length like n_comp) with the property value of the
            edge converted to a numpy data type
        """
        prop = list()
        if n_comp == 1:
            prop.append(data_type(self.graph.ep[prop_key][edge_descriptor]))
        else:
            for i in range(n_comp):
                prop.append(
                    data_type(self.graph.ep[prop_key][edge_descriptor][i]))
        return tuple(prop)

    # * The following SegmentationGraph methods are needed for the normal vector
    # voting algorithm. *

    def calculate_average_edge_length(self,
                                      prop_e=None,
                                      value=1,
                                      verbose=False):
        """
        Calculates the average edge length in the graph.

        If a special edge property is specified, includes only the edges where
        this property equals the given value. If there are no edges in the
        graph, the given property does not exist or there are no edges with the
        given property equaling the given value, None is returned.

        Args:
            prop_e (str, optional): edge property, if specified only edges where
                this property equals the given value will be considered
            value (int, optional): value of the specified edge property an edge
                has to have in order to be considered (default 1)
            verbose (boolean, optional): if True (default False), some extra
                information will be printed out

        Returns:
            the average edge length in the graph (float) or None
        """
        total_edge_length = 0
        average_edge_length = None
        if prop_e is None:
            if verbose:
                print("Considering all edges:")
            if self.graph.num_edges() > 0:
                if verbose:
                    print("{} edges".format(self.graph.num_edges()))
                average_edge_length = np.mean(self.graph.ep.distance.a)
            else:
                print("There are no edges in the graph!")
        elif prop_e in self.graph.edge_properties:
            if verbose:
                print("Considering only edges with property {} equaling value "
                      "{}!".format(prop_e, value))
            num_special_edges = 0
            for ed in self.graph.edges():
                if self.graph.edge_properties[prop_e][ed] == value:
                    num_special_edges += 1
                    total_edge_length += self.graph.ep.distance[ed]
            if num_special_edges > 0:
                if verbose:
                    print("{} such edges".format(num_special_edges))
                average_edge_length = total_edge_length / num_special_edges
            else:
                print("There are no edges with the property {} equaling value "
                      "{}!".format(prop_e, value))
        if verbose:
            print("Average length: {}".format(average_edge_length))
        return average_edge_length

    def find_geodesic_neighbors(self,
                                v,
                                g_max,
                                full_dist_map=None,
                                only_surface=False,
                                verbose=False):
        """
        Finds geodesic neighbor vertices of a given vertex v in the graph that
        are within a given maximal geodesic distance g_max from it.

        Also finds the corresponding geodesic distances. All edges are
        considered. The distances are calculated with Dijkstra's algorithm.

        Args:
            v (graph_tool.Vertex): the source vertex
            g_max: maximal geodesic distance (in the units of the graph)
            full_dist_map (graph_tool.PropertyMap, optional): the full distance
                map for the whole graph; if None, a local distance map is
                calculated for each vertex (default)
            only_surface (boolean, optional): if True (default False), only
                neighbors classified as surface patch (class 1) are considered
            verbose (boolean, optional): if True (default False), some extra
                information will be printed out

        Returns:
            a dictionary mapping a neighbor vertex index to the geodesic
            distance from vertex v
        """
        if full_dist_map is not None:
            dist_v = full_dist_map[v].get_array()
        else:
            dist_v = shortest_distance(self.graph,
                                       source=v,
                                       target=None,
                                       weights=self.graph.ep.distance,
                                       max_dist=g_max)
            dist_v = dist_v.get_array()
        # numpy array of distances from v to all vertices, in vertex index order

        vertex = self.graph.vertex
        orientation_class = self.graph.vp.orientation_class
        neighbor_id_to_dist = dict()

        idxs = np.where(dist_v <= g_max)[0]  # others are INF
        for idx in idxs:
            dist = dist_v[idx]
            if dist != 0:  # ignore the source vertex itself
                v_i = vertex(idx)
                if (not only_surface) or orientation_class[v_i] == 1:
                    neighbor_id_to_dist[idx] = dist

        if verbose:
            print("{} neighbors".format(len(neighbor_id_to_dist)))
        return neighbor_id_to_dist

    def find_geodesic_neighbors_exact(self,
                                      o,
                                      g_max,
                                      only_surface=False,
                                      verbose=False,
                                      debug=False):
        """
        Finds geodesic neighbor vertices of the origin vertex o in the graph
        that are within a given maximal geodesic distance g_max from it.

        Also finds the corresponding geodesic distances. All edges and faces are
        considered. The distances are calculated with Sun's and Abidi's
        algorithm, a simplification of Kimmels' and Sethian's fast marching
        algorithm.

        Args:
            o (graph_tool.Vertex): the source vertex
            g_max: maximal geodesic distance (in the units of the graph)
            only_surface (boolean, optional): if True (default False), only
                neighbors classified as surface patch (class 1) are considered
            verbose (boolean, optional): if True (default False), some extra
                information will be printed out
            debug (boolean, optional): if True (default False), some more extra
                information will be printed out

        Returns:
            a dictionary mapping a neighbor vertex index to the geodesic
            distance from vertex o
        """
        # Shortcuts
        xyz = self.graph.vp.xyz
        vertex = self.graph.vertex
        orientation_class = self.graph.vp.orientation_class
        distance_between_voxels = self.distance_between_voxels
        calculate_geodesic_distance = self._calculate_geodesic_distance
        insert_geo_dist_vertex_id = self._insert_geo_dist_vertex_id
        # Initialization
        geo_dist_heap = []  # heap has the smallest geodesic distance first
        # dictionaries to keep track which geodesic distance belongs to which
        # vertex or vertices and vice versa
        geo_dist_to_vertex_ids = {}
        vertex_id_to_geo_dist = {}
        neighbor_id_to_dist = {}  # output dictionary
        # Tag the center point (o) as Alive:
        self.graph.vp.tag = self.graph.new_vertex_property("string")
        tag = self.graph.vp.tag  # shortcut
        tag[o] = "Alive"
        if debug:
            print("Vertex o={}: Alive".format(int(o)))
        vertex_id_to_geo_dist[int(o)] = 0  # need it for geo. dist. calculation
        xyz_o = tuple(xyz[o])
        for n in o.all_neighbours():
            # Tag all neighboring points of the center point (n) as Close
            tag[n] = "Close"
            # Geodesic distance in this case = Euclidean between o and n
            xyz_n = tuple(xyz[n])
            on = distance_between_voxels(xyz_o, xyz_n)
            if debug:
                print("Vertex n={}: Close with distance {}".format(int(n), on))
            heappush(geo_dist_heap, on)
            insert_geo_dist_vertex_id(geo_dist_to_vertex_ids, on, int(n))
            vertex_id_to_geo_dist[int(n)] = on

        # Repeat while the smallest distance is <= g_max
        while len(geo_dist_heap) >= 1 and geo_dist_heap[0] <= g_max:
            if debug:
                print("\n{} distances in heap, first={}".format(
                    len(geo_dist_heap), geo_dist_heap[0]))
            # 1. Change the tag of the point in Close with the smallest
            # geodesic distance (a) from Close to Alive
            smallest_geo_dist = heappop(geo_dist_heap)
            closest_vertices_ids = geo_dist_to_vertex_ids[smallest_geo_dist]
            a = vertex(closest_vertices_ids[0])
            if len(closest_vertices_ids) > 1:  # move the first one (a) to the
                # back, so it's not taken again next time
                closest_vertices_ids.pop(0)
                closest_vertices_ids.append(int(a))
            tag[a] = "Alive"
            # only proceed if a is a surface patch:
            if only_surface and orientation_class[a] != 1:
                continue
            neighbor_id_to_dist[int(a)] = smallest_geo_dist  # add a to output
            if debug:
                print("Vertex a={}: Alive".format(int(a)))
            neighbors_a = set(a.all_neighbours())  # actually don't have
            # duplicates, but like this can use fast sets' intersection method
            for c in neighbors_a:
                # 2. Tag all neighboring points (c) of this point as Close,
                # but skip those which are Alive already
                if tag[c] == "Alive":
                    if debug:
                        print("Skipping Alive neighbor {}".format(int(c)))
                    continue
                tag[c] = "Close"
                if debug:
                    print("Vertex c={}: Close".format(int(c)))
                # 3. Recompute the geodesic distance of these neighboring
                # points, using only values of points that are Alive, and renew
                # it only if the recomputed result is smaller
                # Find Alive point b, belonging to the same triangle as a and c:
                # iterate over an intersection of the neighbors of a and c
                neighbors_c = set(c.all_neighbours())
                common_neighbors_a_c = neighbors_a.intersection(neighbors_c)
                for b in common_neighbors_a_c:
                    # check if b is tagged Alive
                    if tag[b] == "Alive":
                        if debug:
                            print("\tUsing vertex b={}".format(int(b)))
                        new_geo_dist_c = calculate_geodesic_distance(
                            a,
                            b,
                            xyz[c].a,
                            vertex_id_to_geo_dist,
                            verbose=verbose)
                        if int(c) not in vertex_id_to_geo_dist:  # add c
                            if debug:
                                print("\tadding new distance {}".format(
                                    new_geo_dist_c))
                            vertex_id_to_geo_dist[int(c)] = new_geo_dist_c
                            heappush(geo_dist_heap, new_geo_dist_c)
                            insert_geo_dist_vertex_id(geo_dist_to_vertex_ids,
                                                      new_geo_dist_c, int(c))
                        else:
                            old_geo_dist_c = vertex_id_to_geo_dist[int(c)]
                            if new_geo_dist_c < old_geo_dist_c:  # update c
                                if debug:
                                    print(
                                        "\tupdating distance {} to {}".format(
                                            old_geo_dist_c, new_geo_dist_c))
                                vertex_id_to_geo_dist[int(c)] = new_geo_dist_c
                                if old_geo_dist_c in geo_dist_heap:
                                    # check because it is sometimes not there
                                    geo_dist_heap.remove(old_geo_dist_c)
                                heappush(geo_dist_heap, new_geo_dist_c)
                                old_geo_dist_vertex_ids = geo_dist_to_vertex_ids[
                                    old_geo_dist_c]
                                if len(old_geo_dist_vertex_ids) == 1:
                                    del geo_dist_to_vertex_ids[old_geo_dist_c]
                                else:
                                    old_geo_dist_vertex_ids.remove(int(c))
                                insert_geo_dist_vertex_id(
                                    geo_dist_to_vertex_ids, new_geo_dist_c,
                                    int(c))
                            elif debug:
                                print("\tkeeping the old distance={}, because "
                                      "it's <= the new={}".format(
                                          old_geo_dist_c, new_geo_dist_c))
                        # if debug:
                        #     print(geo_dist_heap)
                        #     print(geo_dist_to_vertex_ids)
                        #     print(vertex_id_to_geo_dist)
                        #     print(neighbor_id_to_dist)
                        break  # one Alive b is expected, stop iteration
                else:
                    if debug:
                        print("\tNo common neighbors of a and c are Alive")

        del self.graph.vertex_properties["tag"]
        if debug:
            print("Vertex o={} has {} geodesic neighbors".format(
                int(o), len(neighbor_id_to_dist)))
        if verbose:
            print("{} neighbors".format(len(neighbor_id_to_dist)))
        return neighbor_id_to_dist

    def _calculate_geodesic_distance(self,
                                     a,
                                     b,
                                     xyz_c,
                                     vertex_id_to_geo_dist,
                                     verbose=False):
        geo_dist_a = vertex_id_to_geo_dist[int(a)]
        geo_dist_b = vertex_id_to_geo_dist[int(b)]
        xyz_a = self.graph.vp.xyz[a].a
        xyz_b = self.graph.vp.xyz[b].a
        ab = euclidean_distance(xyz_a, xyz_b)
        ac = euclidean_distance(xyz_a, xyz_c)
        bc = euclidean_distance(xyz_b, xyz_c)
        # maybe faster to use linalg.euclidean_distance directly on np.ndarrays
        alpha = nice_acos((ab**2 + ac**2 - bc**2) / (2 * ab * ac))
        beta = nice_acos((ab**2 + bc**2 - ac**2) / (2 * ab * bc))
        if alpha < (math.pi / 2) and beta < (math.pi / 2):
            if verbose:
                print("\ttriangle abc is acute")
            theta = nice_acos((geo_dist_a**2 + ab**2 - geo_dist_b**2) /
                              (2 * ab * geo_dist_a))
            geo_dist_c = math.sqrt(ac**2 + geo_dist_a**2 - 2 * ac *
                                   geo_dist_a * math.cos(alpha + theta))
        else:
            if verbose:
                print("\ttriangle abc is obtuse")
            geo_dist_c = min(geo_dist_a + ac, geo_dist_b + bc)
        return geo_dist_c

    @staticmethod
    def _insert_geo_dist_vertex_id(geo_dist_to_vertices, geo_dist, vertex_ind):
        if geo_dist in geo_dist_to_vertices:
            geo_dist_to_vertices[geo_dist].append(vertex_ind)
        else:
            geo_dist_to_vertices[geo_dist] = [vertex_ind]

    def get_vertex_property_array(self, property_name):
        """
        Gets a numpy array with all values of a vertex property of the graph,
        printing out the number of values, the minimal and the maximal value.

        Args:
            property_name (str): vertex property name

        Returns:
            an array (numpy.ndarray) with all values of the vertex property
        """
        if (isinstance(property_name, str)
                and property_name in self.graph.vertex_properties):
            values = np.array(
                self.graph.vertex_properties[property_name].get_array())
            print('{} "{}" values'.format(len(values), property_name))
            print('min = {}, max = {}, mean = {}'.format(
                min(values), max(values), np.mean(values)))
            return values
        else:
            raise pexceptions.PySegInputError(
                expr='get_vertex_property_array (SegmentationGraph)',
                msg=('The input "{}" is not a str object or is not found in '
                     'vertex properties of the graph.'.format(property_name)))
コード例 #40
0
        e2015 = child_graph.add_edge(child_graph.vertex_index[20], child_graph.vertex_index[15])
        e2115 = child_graph.add_edge(child_graph.vertex_index[21], child_graph.vertex_index[15])
        e1716 = child_graph.add_edge(child_graph.vertex_index[17], child_graph.vertex_index[16])
        e2116 = child_graph.add_edge(child_graph.vertex_index[21], child_graph.vertex_index[16])
        e2216 = child_graph.add_edge(child_graph.vertex_index[22], child_graph.vertex_index[16])
        e2317 = child_graph.add_edge(child_graph.vertex_index[23], child_graph.vertex_index[17])
        e1918 = child_graph.add_edge(child_graph.vertex_index[19], child_graph.vertex_index[18])
        e2019 = child_graph.add_edge(child_graph.vertex_index[20], child_graph.vertex_index[19])
        e2120 = child_graph.add_edge(child_graph.vertex_index[21], child_graph.vertex_index[20])
        e2221 = child_graph.add_edge(child_graph.vertex_index[22], child_graph.vertex_index[21])
        e2322 = child_graph.add_edge(child_graph.vertex_index[23], child_graph.vertex_index[22])


        ## Property definition
        graph_name = child_graph.new_graph_property("string")
        layer_capacities = child_graph.new_edge_property("int")
        layer_res_capacity = child_graph.new_edge_property("int")
        layer_flow = child_graph.new_edge_property("int")
        alternate_path = child_graph.new_edge_property("int")
        flag_path = child_graph.new_edge_property("int")

        ## Property Assignment
        child_graph.gp.layer_name = graph_name
        child_graph.ep.edge_capacity = layer_capacities
        child_graph.ep.residual_capacity = layer_res_capacity
        child_graph.ep.edge_flow = layer_flow
        child_graph.ep.shared_path = alternate_path
        child_graph.ep.path_flag = flag_path

        ## Setting the name of the graph
        child_graph.gp.layer_name = "Layer_" + str(i)
コード例 #41
0
    def draw_for(self, phase: Phase, model: GameModel):
        self.log.debug('drawing phase flow {0}'.format(phase.name))
        TMPUTILS.clear_container(self.main_panel)

        top = Gtk.HBox()

        name = Gtk.Label(phase.name)
        top.pack_start(name, True, True, 0)
        refresh_button = Gtk.Button('Refresh')
        refresh_button.connect('clicked', lambda w: self.draw_for(phase, model))
        top.pack_start(refresh_button, True, True, 0)
        self.main_panel.pack_start(top, False, False, 0)

        #TMPUTILS.start_rule_color = TMPUTILS.rule_color
        #start = phase.rules[0]
        #start = Rule('Początek {0}'.format(phase.name))
        start = Rule('Start {0}'.format(phase.name))
        start.next = phase.rules
        phase.rules = [start]

        rules_set = phase.all_rules_set()
        phase.rules = start.next

        graph = Graph()
        graph.vp.name = graph.new_vertex_property('string')
        graph.vp.fullname = graph.new_vertex_property('string')
        graph.vp.color = graph.new_vertex_property('string')
        graph.vp.shape = graph.new_vertex_property('string')
        graph.vp.rotation = graph.new_vertex_property('float')
        graph.vp.text_pos = graph.new_vertex_property('float')
        graph.vp.text_rotation = graph.new_vertex_property('float')

        graph.ep.text = graph.new_edge_property('string')
        graph.ep.text_color = graph.new_edge_property('string')

        rule_vertex = {}
        self.vertex_rule = {}

        for rule in rules_set:
            vertex = graph.add_vertex()
            rule_vertex[rule] = vertex
            self.vertex_rule[vertex] = rule
            graph.vp.name[vertex] = rule.verticle_name()
            graph.vp.fullname[vertex] = rule.name
            if rule is start:
                color = self.config.start_rule_color()
            elif issubclass(rule.__class__, ChangePhase):
                color = TMPUTILS.end_rule_color(rule, model)
            elif len([r for k, v in rule.rules_dict().items() for r in v]) == 0:
                color = self.config.wrong_rule_color()
            else:
                color = TMPUTILS.rule_color()
            graph.vp.color[vertex] = color
            #graph.vp.shape[vertex] = 'square' if issubclass(rule.__class__, If) else 'circle'
            graph.vp.shape[vertex] = self.config.rule_shape(rule)
            #graph.vp.rotation[vertex] = pi / 4 if issubclass(rule.__class__, If) else 0
            graph.vp.rotation[vertex] = self.config.rule_rotation(rule)
            graph.vp.text_pos[vertex] = 0
            #graph.vp.text_rotation[vertex] = - pi / 4 if issubclass(rule.__class__, If) else 0
            graph.vp.text_rotation[vertex] = self.config.rule_text_rotation(rule)

        for rule in rules_set:
            for next_text, next_rule_list in rule.rules_dict().items():
                for next_rule in next_rule_list:
                    edge = graph.add_edge(rule_vertex[rule], rule_vertex[next_rule])
                    #as_polish = {'No': "Nie", 'Yes': "Tak"}
                    #graph.ep.text[edge] = as_polish[next_text] if next_text in as_polish else next_text
                    graph.ep.text[edge] = next_text
                    graph.ep.text_color[edge] = TMPUTILS.text_color(next_text)

        pos = sfdp_layout(graph)

        vprops = {
            'text': graph.vp.name,
            'fill_color': graph.vp.color,
            'shape': graph.vp.shape,
            'rotation': graph.vp.rotation,
            'text_position': graph.vp.text_pos,
            'text_rotation': graph.vp.text_rotation
        }
        eprops = {
            'text': graph.ep.text,
            'text_color': graph.ep.text_color
        }
        self.graph_widget = GraphWidget(graph, pos, display_props=[graph.vp.fullname], vprops=vprops, eprops=eprops,
                                   vertex_size=50)
        #jest cos takiego jak GraphWidget.key_press_callback ale u mnie nie dziala...
        self.graph_widget.connect('button-release-event', self.on_vertex_clicked)

        self.main_panel.pack_start(self.graph_widget, True, True, 0)
        self.show_all()
def contract_graph_by_nodes(g, nodes, weights=None):
    """
    contract graph by nodes (only for undirected)

    note: the supernode is node 0 in the new graph

    Params:
    ----------
    g: Graph, undirected
    weights: edge_property_map
    nodes: list of ints

    Returns:
    ----------
    - Graph: a contracted graph where `nodes` are merged into a supernode
    - edge_property_map: new weight
    """
    if len(nodes) == 1:
        return g, weights

    nodes = set(nodes)

    # print('nodes:', nodes)

    # re-align the nodes
    # `v \in nodes` are considered node 0
    # get the old node to new node mapping
    o2n_map = {}
    c = 1
    for v in g.vertices():
        v = int(v)
        if v not in nodes:
            o2n_map[v] = c
            c += 1
        else:
            o2n_map[v] = 0
    # print('o2n_map:', o2n_map)

    # calculate new edges and new weights
    e2w = defaultdict(float)
    for e in g.edges():
        u, v = map(int, [e.source(), e.target()])
        nu, nv = sorted([o2n_map[u], o2n_map[v]])
        if weights:
            e2w[(nu, nv)] += weights[g.edge(u, v)]
        else:
            e2w[(nu, nv)] += 1

    # print('e2w:', e2w)

    # create the new graph
    new_g = Graph(directed=False)
    # for _ in range(g.num_vertices() - len(nodes) + 1):
    #     new_g.add_vertex()

    edges = []
    for u, v in e2w:
        e = new_g.add_edge(u, v)
        edges.append(e)

    new_weights = new_g.new_edge_property('float')
    for e, w in zip(edges, e2w.values()):
        new_weights[e] = w

    return new_g, new_weights
コード例 #43
0
ファイル: main.py プロジェクト: crazy2be/cs452
def main():
	conn = serial_interface.connect()

	cur_track = track.init_tracka()
	g = Graph()
	g.add_vertex(len(cur_track))
	for (vi, node) in enumerate(cur_track): node.i = vi

	n_title = g.new_vertex_property("string")
	n_color = g.new_vertex_property("string")
	n_pos = g.new_vertex_property("vector<double>")
	e_title = g.new_edge_property("string")
	e_dist = g.new_edge_property("double")

	for node in cur_track:
		v = g.vertex(node.i)
		n_title[v] = node.name
		if node.typ == track.NODE_EXIT:
			# Invert points to match our ASCII display.
			n_pos[v] = (-node.reverse.coord_x, -node.reverse.coord_y)
		else:
			n_pos[v] = (-node.coord_x, -node.coord_y)
		e = g.add_edge(g.vertex(node.i), g.vertex(node.reverse.i))
		if node.typ == track.NODE_SENSOR: n_color[v] = "blue"
		elif node.typ == track.NODE_BRANCH: n_color[v] = "orange"
		elif node.typ == track.NODE_MERGE: n_color[v] = "yellow"
		elif node.typ == track.NODE_ENTER: n_color[v] = "green"
		elif node.typ == track.NODE_EXIT: n_color[v] = "red"
		else: n_color[v] = "white"
		for edge in node.edge:
			if edge.src is None: continue
			e = g.add_edge(g.vertex(edge.src.i), g.vertex(edge.dest.i))
			e_dist[e] = edge.dist
			e_title[e] = "%.2f" % (edge.dist)

	win = graph_tool.draw.GraphWindow(g, n_pos, (640, 480), edge_text=e_title, vertex_fill_color=n_color, vertex_text=n_title)
	win.show_all()
	def destroy_callback(*args, **kwargs):
		win.destroy()
		Gtk.main_quit()

	def set_switch(sw, d):
		for node in cur_track:
			if node.typ == track.NODE_BRANCH and node.num == sw:
				node.switch_direction = d
				return
		print "WARN: Could not find switch %d" % sw

	class Train():
		num = -1
		vel = 0.
		speed = 0.
		edge = cur_track[0].edge[0]
		edge_dist = 0
		SPEEDX = 1.

		def __init__(self, num):
			self.num = num

		def update(self):
			# Super shitty deacceleration model
			self.vel = self.vel + (0.018/self.SPEEDX)*(self.speed - self.vel)
			self.edge_dist += self.vel
			while True:
				e = self.e()
				if self.edge_dist < e_dist[e]: break
				if self.edge.dest.typ == track.NODE_SENSOR:
					conn.set_sensor_tripped(self.edge.dest.num)
				self.edge = self.edge.dest.edge[self.edge.dest.switch_direction]
				self.edge_dist -= e_dist[e]

		def draw(self, n_pos, da, cr):
			e = self.e()
			start, end = np.array(n_pos[e.source()]), np.array(n_pos[e.target()])
			alpha = self.edge_dist / e_dist[e]
			pos = start + alpha*(end - start)
			dp = win.graph.pos_to_device(pos) # dp: device position
			cr.rectangle(dp[0]-10, dp[1]-10, 20, 20)
			cr.set_source_rgb(102. / 256, 102. / 256, 102. / 256)
			cr.fill()
			cr.move_to(dp[0]-10, dp[1] + 10 - 12./2)
			cr.set_source_rgb(1., 1., 1.)
			cr.set_font_size(12)
			cr.show_text("%d" % self.num)
			cr.fill()
		def e(self): return g.edge(self.edge.src.i, self.edge.dest.i)
		def set_speed(self, speed): self.speed = speed/self.SPEEDX
		def toggle_reverse(self):
			self.edge = self.edge.reverse
			self.edge_dist = e_dist[self.e()] - self.edge_dist

	def find_train(train_number):
		for train in trains:
			if train.num == train_number:
				return train
		train = Train(train_number)
		trains.append(train)
		return train

	trains = [Train(12)]
	startup_time = time.time()
	accumulated_error = [0.]
	last_time = [time.time()]
	last_sensor_poll = [0]
	FPS = 30.
	def my_draw(da, cr):
		(typ, a1, a2) = conn.next_cmd()
		if typ is None: pass
		elif typ == 'set_speed': find_train(a1).set_speed(a2)
		elif typ == 'toggle_reverse': find_train(a1).toggle_reverse()
		elif typ == 'switch': set_switch(a1, a2)
		elif typ == 'sensor': last_sensor_poll[0] = round((time.time() - startup_time) * 1000)/1000
		else: print "Ignoring command %s" % typ
		cur_time = time.time()
		dt = cur_time - last_time[0] + accumulated_error[0]
		num_steps = int(dt*FPS)
		accumulated_error[0] = dt - num_steps/FPS
		for train in trains:
			for _ in range(0, num_steps): train.update()
			train.draw(n_pos, da, cr)
			cr.move_to(10., 10.)
			cr.set_source_rgb(0., 0., 0.)
			cr.set_font_size(12)
			cr.show_text("Last polled at %.3f" % last_sensor_poll[0])
		da.queue_draw()
		last_time[0] = cur_time

	win.connect("delete_event", destroy_callback)
	win.graph.connect("draw", my_draw)
	Gtk.main()
コード例 #44
0
ファイル: cumulative.py プロジェクト: nestauk/rhodonite
def cumulative_cooccurrence_graph(steps, sequences, directed=False):
    '''cumulative_cooccurrence_graph
    Creates a cumulative cooccurrence graph.

    Parameters
    ----------
    steps : :obj:`iter` of :obj:`int` or :obj:`str` 
        A series that contains sequential labels for the nested groups.
    sequences : :obj:`iter` of :obj:`iter` of :obj:`int` 
        Nested iterable of integers representing vertices in the graph. Number 
        of nested iterables should be equal to `len(steps)`.
    directed : :obj:`bool` 
        Currently has no effect. In future this will determine whether to build 
        a bi-directional cooccurrence graph.

    Returns
    -------
    g : :obj:`graph_tool.Graph`
        A graph. Vertices are elements. Edges link terms that have cooccurred 
        at least once in the series.
    o_props : :obj:`dict` 
        Property maps with vertex occurrence values at each step.
    o_cumsum_props : :obj:`dict` 
        Property maps with cumulative vertex cooccurrence values at each step.
    co_props : :obj:`dict` 
        Property maps with edge cooccurrnce values at each step.
    co_cumsum_props : :obj:`dict`
        Property maps with cumulative edge cooccurrence values at each step.
    '''

    g = Graph(directed=directed)

    o_total = Counter(chain(*chain(*sequences)))
    n_vertices = len(o_total)
    g.add_vertex(n_vertices)
    o_max = dict_to_vertex_prop(g, o_total, 'int')

    co_total = cooccurrence_counts(chain(*sequences))
    edge_list = ((c[0], c[1], count) for c, count in co_total.items())
    co_max = g.new_edge_property('int')
    g.add_edge_list(edge_list, eprops=[co_max])

    edges = g.get_edges()
    edge_indices = dict(zip([(e[0], e[1]) for e in edges], edges[:, 2]))

    o_props = {}
    co_props = {}
    o_cumsum_props = {}
    co_cumsum_props = {}
    for i, (step, seq) in enumerate(zip(steps[:-1], sequences[:-1])):
        logging.info(f'Calculating cooccurrences at step {step}')
        o_step = Counter(chain(*seq))
        o_props[step] = dict_to_vertex_prop(g, o_step, 'int')

        combos = (combinations(sorted(ids), 2) for ids in seq)
        co_step = Counter(chain(*combos))
        co_props[step] = dict_to_edge_prop(g, co_step, 'int', edge_indices)

        o_cumsum = g.new_vertex_property('int')
        co_cumsum = g.new_edge_property('int')
        if i == 0:
            o_cumsum.a = o_cumsum.a + o_props[step].a
            co_cumsum.a = co_cumsum.a + co_props[step].a
        else:
            o_cumsum.a = o_cumsum_props[steps[i - 1]].a + o_props[step].a
            co_cumsum.a = co_cumsum_props[steps[i - 1]].a + co_props[step].a
        o_cumsum_props[step] = o_cumsum
        co_cumsum_props[step] = co_cumsum
    # fill in the last step without needing to count occurrences
    # or cooccurrences
    step_max = steps[-1]
    o = g.new_vertex_property('int')
    co = g.new_edge_property('int')
    o.a = o_max.a - o_cumsum.a
    co.a = co_max.a - co_cumsum.a
    o_props[step_max] = o
    co_props[step_max] = co

    o_cumsum_props[step_max] = o_max
    co_cumsum_props[step_max] = co_max

    steps_prop = g.new_graph_property('vector<int>')
    steps_prop.set_value(steps)
    g.gp['steps'] = steps_prop

    return g, o_props, o_cumsum_props, co_props, co_cumsum_props
コード例 #45
0
ファイル: network_tools.py プロジェクト: swapilpaliwal/savvy
def build_graph(df_list, sens='ST', top=410, min_sens=0.01, edge_cutoff=0.0):
    """
    Initializes and constructs a graph where vertices are the parameters
    selected from the first dataframe in 'df_list', subject to the
    constraints set by 'sens', 'top', and 'min_sens'.  Edges are the second
    order sensitivities of the interactions between those vertices,
    with sensitivities greater than 'edge_cutoff'.

    Parameters
    -----------
    df_list     : list
                  A list of two dataframes.  The first dataframe should be
                  the first/total order sensitivities collected by the
                  function data_processing.get_sa_data().
    sens        : str, optional
                  A string with the name of the sensitivity that you would
                  like to use for the vertices ('ST' or 'S1').
    top         : int, optional
                  An integer specifying the number of vertices to display (
                  the top sensitivity values).
    min_sens    : float, optional
                  A float with the minimum sensitivity to allow in the graph.
    edge_cutoff : float, optional
                  A float specifying the minimum second order sensitivity to
                  show as an edge in the graph.

    Returns
    --------
    g : graph-tool object
        a graph-tool graph object of the network described above.  Each
        vertex has properties 'param', 'sensitivity', and 'confidence'
        corresponding to the name of the parameter, value of the sensitivity
        index, and it's confidence interval.  The only edge property is
        'second_sens', the second order sensitivity index for the
        interaction between the two vertices it connects.
    """

    # get the first/total index dataframe and second order dataframe
    df = df_list[0]
    df2 = df_list[1]

    # Make sure sens is ST or S1
    if sens not in set(['ST', 'S1']):
        raise ValueError('sens must be ST or S1')
    # Make sure that there is a second order index dataframe
    try:
        if not df2:
            raise Exception('Missing second order dataframe!')
    except:
        pass

    # slice the dataframes so the resulting graph will only include the top
    # 'top' values of 'sens' greater than 'min_sens'.
    df = df.sort_values(sens, ascending=False)
    df = df.ix[df[sens] > min_sens, :].head(top)
    df = df.reset_index()

    # initialize a graph
    g = Graph()

    vprop_sens = g.new_vertex_property('double')
    vprop_conf = g.new_vertex_property('double')
    vprop_name = g.new_vertex_property('string')
    eprop_sens = g.new_edge_property('double')

    g.vertex_properties['param'] = vprop_name
    g.vertex_properties['sensitivity'] = vprop_sens
    g.vertex_properties['confidence'] = vprop_conf
    g.edge_properties['second_sens'] = eprop_sens

    # keep a list of all the vertices
    v_list = []

    # Add the vertices to the graph
    for i, param in enumerate(df['Parameter']):
        v = g.add_vertex()
        vprop_sens[v] = df.ix[i, sens]
        vprop_conf[v] = 1 + df.ix[i, '%s_conf' % sens] / df.ix[i, sens]
        vprop_name[v] = param
        v_list.append(v)

    # Make two new columns in second order dataframe that point to the vertices
    # connected on each row.
    df2['vertex1'] = -999
    df2['vertex2'] = -999
    for vertex in v_list:
        param = g.vp.param[vertex]
        df2.ix[df2['Parameter_1'] == param, 'vertex1'] = vertex
        df2.ix[df2['Parameter_2'] == param, 'vertex2'] = vertex

    # Only allow edges for vertices that we've defined
    df_edges = df2[(df2['vertex1'] != -999) & (df2['vertex2'] != -999)]
    # eliminate edges below a certain cutoff value
    pruned = df_edges[df_edges['S2'] > edge_cutoff]
    pruned.reset_index(inplace=True)
    # Add the edges for the graph
    for i, sensitivity in enumerate(pruned['S2']):
        v1 = pruned.ix[i, 'vertex1']
        v2 = pruned.ix[i, 'vertex2']
        e = g.add_edge(v1, v2)
        # multiply by a number to make the lines visible on the plot
        eprop_sens[e] = sensitivity * 150

    # These are ways you can reference properties of vertices or edges
    # g.vp.param[g.vertex(77)]
    # g.vp.param[v_list[0]]

    print('Created a graph with %s vertices and %s edges.\nVertices are the '
          'top %s %s values greater than %s.\nOnly S2 values (edges) '
          'greater than %s are included.' %
          (g.num_vertices(), g.num_edges(), top, sens, min_sens, edge_cutoff))

    return g
コード例 #46
0
def build_closure_with_order(g,
                             cand_source,
                             terminals,
                             infection_times,
                             k=-1,
                             strictly_smaller=True,
                             return_r2pred=False,
                             debug=False,
                             verbose=False):
    """
    build transitive closure with infection order constraint

    g: gt.Graph(directed=False)
    cand_source: int
    terminals: list of int
    infection_times: dict int -> float

    build a clojure graph in which cand_source + terminals are all connected to each other.
    the number of neighbors of each node is determined by k

    the larger the k, the denser the graph

    note that vertex ids are preserved (without re-mapping to consecutive integers)

    return:

    gt.Graph(directed=True)
    """
    if return_r2pred:
        r2pred = {}
    edges = {}
    terminals = list(terminals)

    # from cand_source to terminals
    vis = init_visitor(g, cand_source)
    cpbfs_search(g,
                 source=cand_source,
                 visitor=vis,
                 terminals=terminals,
                 forbidden_nodes=terminals,
                 count_threshold=k)
    if return_r2pred:
        r2pred[cand_source] = vis.pred
    for u, v, c in get_edges(vis.dist, cand_source, terminals):
        edges[(u, v)] = c

    if debug:
        print('cand_source: {}'.format(cand_source))
        print('#terminals: {}'.format(len(terminals)))
        print('edges from cand_source: {}'.format(edges))

    if verbose:
        terminals_iter = tqdm(terminals)
        print('building closure graph')
    else:
        terminals_iter = terminals

    # from terminal to other terminals
    for root in terminals_iter:

        if strictly_smaller:
            late_terminals = [
                t for t in terminals
                if infection_times[t] > infection_times[root]
            ]
        else:
            # respect what the paper presents
            late_terminals = [
                t for t in terminals
                if infection_times[t] >= infection_times[root]
            ]

        late_terminals = set(late_terminals) - {
            cand_source
        }  # no one can connect to cand_source
        if debug:
            print('root: {}'.format(root))
            print('late_terminals: {}'.format(late_terminals))
        vis = init_visitor(g, root)
        cpbfs_search(
            g,
            source=root,
            visitor=vis,
            terminals=list(late_terminals),
            forbidden_nodes=list(set(terminals) - set(late_terminals)),
            count_threshold=k)

        if return_r2pred:
            r2pred[root] = vis.pred

        for u, v, c in get_edges(vis.dist, root, late_terminals):
            if debug:
                print('edge ({}, {})'.format(u, v))
            edges[(u, v)] = c

    if verbose:
        print('returning closure graph')

    gc = Graph(directed=True)

    gc.add_vertex(g.num_vertices())

    vfilt = gc.new_vertex_property('bool')
    vfilt.a = False

    for (u, v) in edges:
        gc.add_edge(u, v)
        vfilt[u] = vfilt[v] = True

    eweight = gc.new_edge_property('int')
    eweight.set_2d_array(np.array(list(edges.values())))
    gc.set_vertex_filter(vfilt)

    rets = (gc, eweight)
    if return_r2pred:
        rets += (r2pred, )
    return rets
コード例 #47
0
ファイル: skeleton_data.py プロジェクト: bo-wu/skel_corres
class SkeletonData(object):
    """
    class to store and process skeleton data, like generated from starlab mean curvature skeleton
    """
    def __init__(self, fname=None, mesh_name=None, filter_sb=False):
        """
        @param filter_sb: if filter out Short Branch
        """
        if fname != None:
            self.skel_name = fname
            self.read_skel_file(fname)
            self._filter_short_branch(filter=filter_sb, short=10)
            self._parse_data()
            self.mesh_name = mesh_name
            self.vert_radius = None

    def calc_skel_properties(self):
        """
        calc all properties needed for matching
        """
        self.calc_node_centricity()
        self.calc_skel_radius()
        self.calc_path_length_ratio()
        self.calc_path_radius_ratio()
        self.normalize_skeleton()


    def read_skel_file(self, fname, dim=3):
        if fname == None:
            print 'please input skeleton file name'
            sys.exit(0)
        elif os.path.isfile(fname):
            self.verts_init = []
            self.edges_init = []
            with open(fname) as sf:
                for line in sf:
                    line = line.strip('\n')
                    line = line.split(' ')
                    if line[0] == '#':
                        continue
                    elif line[0] == 'v':
                        self.verts_init.append([x for x in line[1:(dim+1)]])
                    #### attention!! verts of edge start from 1 in files ####
                    elif line[0] == 'e':
                        self.edges_init.append([int(x)-1 for x in line[1:3]])
                    else:
                        print 'not support this format'
                        sys.exit(0)
        else:
            print 'no such flie', fname
            sys.exit(0)


    def _filter_short_branch(self, filter=False, short=30):
        """
        filter out very short branches: do this maybe not right for some models, for models with flat part, it is right
        I will test how this effect the final matching results
        need to delete nodes, switch with the last one then delete last
        """
        if filter == False:
            self.verts = self.verts_init
            self.edges = self.edges_init
        else:
            init_graph = Graph(directed=False)
            init_graph.add_vertex(len(self.verts_init))
            for edge in self.edges_init:
                init_graph.add_edge(init_graph.vertex(edge[0]), init_graph.vertex(edge[1]))

            terminal_node = []
            for v in init_graph.vertices():
                if v.out_degree() == 1:
                    terminal_node.append(v)

            visitor = DepthVisitor()
            short_nodes = []
            for tn in terminal_node:
                search.dfs_search(init_graph, tn, visitor)
                tmp_node = visitor.get_short_branch(min_length=short)
                visitor.reset()
                for n in tmp_node:
                    short_nodes.append(n)

            ## get edges on the short paths
            short_nodes = list(set(short_nodes))
            short_edges = []
            temp_verts = self.verts_init[:]
            v_num = len(self.verts_init)
            if len(short_nodes):
                for v in reversed(sorted(short_nodes)):
                    for ve in init_graph.vertex(v).out_edges():
                        short_edges.append(ve)

                ## delete edges first, then vertex
                short_edges = list(set(short_edges))
                for e in short_edges:
                    init_graph.remove_edge(e)

                print 'deleting vertex',
                for v in reversed(sorted(short_nodes)):
                    print v,
                    temp_verts[int(v)] = temp_verts[v_num-1]
                    init_graph.remove_vertex(v, fast=True)
                    v_num -= 1
                print '\ndeleting related edges' # already done above, just info user
            else:
                print 'no short branches'

            ######## new vertices and edges ########
            self.verts = temp_verts[:v_num]
            self.edges = []
            for e in init_graph.edges():
                self.edges.append([int(e.source()), int(e.target())])


    def create_virtual_node(self):
        """
        I am planning use this function to make virtual nodes for those feature nodes
        """
        pass


    def _parse_data(self):
        """
        extract interal points(degree>2) and endpoints(degree=1)
        extract segments
        """
        if self.verts == None or self.edges == None:
            print 'please first call read_skel_file function'
        else:
            self.verts = np.array(self.verts, dtype=np.float)
            self.edges = np.array(self.edges, dtype=np.int)
            terminal_index = []
            junction_index = []
            self.skel_graph = Graph(directed=False)
            self.skel_graph.add_vertex(len(self.verts))
            for edge in self.edges :
                self.skel_graph.add_edge(self.skel_graph.vertex(edge[0]), self.skel_graph.vertex(edge[1]))

            for v in self.skel_graph.vertices():
                if v.out_degree() == 2 :
                    continue
                elif v.out_degree() == 1 :
                    terminal_index.append(int(v))
                elif v.out_degree() > 2 :
                    junction_index.append(int(v))

            self.terminal = self.verts[terminal_index]
            self.junction = self.verts[junction_index]
            self.terminal_index = terminal_index
            self.junction_index = junction_index
            self.feature_node_index = junction_index + terminal_index 
            self.feature_node = self.verts[self.feature_node_index]

            """
            edge_vert_index = self.edges.flatten()
            print 'edge vertex index dtype', edge_vert_index.dtype
            if 0 in edge_vert_index:
                print 'vertex start from 0'
            else:
                print 'vertex start from 1'
            print 'skeleton vertex num', self.skel_graph.num_vertices()
            print 'skeleton edge num', self.skel_graph.num_edges()
            """
    
    def _calc_edge_length(self):
        """
        calc edge length and make it edge property map in graph-tool
        """
        vec = self.verts[self.edges[:,0]] - self.verts[self.edges[:,1]]
        edge_length = np.sqrt(np.sum(vec**2, axis=-1))
        self.edge_length_map = self.skel_graph.new_edge_property("double")
        self.edge_length_map.a = edge_length
    

    def calc_node_centricity(self):
        """
        calc node centricity of feature nodes(terminal and junction nodes)
        T1 in Oscar's EG 2010 paper
        """
        self._calc_edge_length()
        node_centricity = []
        for n_idx in self.feature_node_index:
            dist = topology.shortest_distance(self.skel_graph, source=self.skel_graph.vertex(n_idx), weights=self.edge_length_map)
            node_centricity.append(dist.a.mean())

        node_centricity = np.array(node_centricity)
        self.node_centricity = node_centricity / np.max(node_centricity)


    def calc_skel_radius(self, mesh_name=None, dim=3):
        """
        calc nearest mesh vertex of skeleton vertex
        """
        if mesh_name != None:
            self.mesh_name = mesh_name

        if self.mesh_name == None:
            print 'please set mesh_name before calc_skel_radius'
        elif os.path.isfile(self.mesh_name):
            mesh = om.TriMesh()
            assert om.read_mesh(mesh, self.mesh_name)
            mesh_vertices = np.zeros((mesh.n_vertices(), dim), dtype=float)
            for n, vh in enumerate(mesh.vertices()):
                for i in xrange(3):
                    mesh_vertices[n, i] = mesh.point(vh)[i]

            nbrs = NearestNeighbors(n_neighbors=1, algorithm='ball_tree').fit(mesh_vertices)
            self.vert_radius, indices = nbrs.kneighbors(self.verts)
        else:
            print 'cannot find mesh file', self.mesh_name                
            sys.exit(0)


    def calc_path_radius(self, start, end):
        """
        utile function for other function
        calc skeleton **mean** vertex radius along some segment
        """
        if self.vert_radius == None:
            print 'please call calc_skel_radius function first'
            return None
        elif start in self.feature_node_index and end in self.feature_node_index:
            v_list, e_list = topology.shortest_path(self.skel_graph, self.skel_graph.vertex(start), self.skel_graph.vertex(end), weights=self.edge_length_map)
            v_idx_list = []
            for v in v_list:
                v_idx_list.append(int(v))
            v_radius = self.vert_radius[v_idx_list]
            return v_radius.mean()
        else:
            print 'input vertex index is not feature node index'
            return None
    

    def calc_path_length_ratio(self):
        """
        for each feature node pair segment, calculate path length ratio
        normalized, to make it scale invariant
        """
        path_length = np.zeros((len(self.feature_node_index), len(self.feature_node_index)), dtype=float)
        for i, n_idx in enumerate(self.feature_node_index):
            for j, m_idx in enumerate(self.feature_node_index[i+1:], start=i+1):
                length = topology.shortest_distance(self.skel_graph, self.skel_graph.vertex(n_idx), self.skel_graph.vertex(m_idx), weights=self.edge_length_map)
                if length != None :
                    path_length[i,j] = path_length[j,i] = length
                else:
                    print 'compute path length ratio error'
                    return None

        ### extract path length from each feature node to junction nodes ###
        ### Careful!! path_length MUST start from junction node
        self.path_to_junction = path_length[:,:len(self.junction_index)]

        self.path_length_ratio = path_length / path_length.max()
        return self.path_length_ratio
    

    def calc_path_radius_ratio(self):
        """
        for each feature node pair segment, calculate path radius ratio   
        normalized, to make it scale invariant
        """
        path_radius = np.zeros((len(self.feature_node_index), len(self.feature_node_index)), dtype=float)
        for i, n_idx in enumerate(self.feature_node_index):
            for j, m_idx in enumerate(self.feature_node_index[i+1:], start=i+1):
                radius = self.calc_path_radius(n_idx, m_idx)
                if radius != None :
                    path_radius[i, j] = path_radius[j, i] = radius
                else:
                    print 'comptue path radius error'
                    return None

        self.path_radius_ratio = path_radius / path_radius.max()
        return self.path_radius_ratio


    def normalize_skeleton(self):
        """
        calc the pose-normalized skeleton to distinguish symmetric nodes
        using multidimensional scaling method(MDS)
        """
        v_num = len(self.verts)
        geodesic_dist = np.zeros((v_num, v_num))
        geodesic_dist_map = topology.shortest_distance(self.skel_graph, weights=self.edge_length_map)
        for i in xrange(v_num):
            geodesic_dist[i] = geodesic_dist_map[self.skel_graph.vertex(i)].a

        mds = manifold.MDS(n_components=3, max_iter=500, eps=1e-10, dissimilarity="precomputed", n_jobs=-2, n_init=1)
        verts_mean = self.verts - self.verts.mean(axis=0)
        normalized_verts = mds.fit(geodesic_dist, init=verts_mean).embedding_
        #scale = np.sqrt((verts_mean ** 2).sum()) / np.sqrt((normalized_verts ** 2).sum())
        #normalized_verts *= scale
        self.normalized_verts = normalized_verts
        self.normalized_feature_verts = normalized_verts[self.feature_node_index]
        return self.normalized_verts


    def write_file(self, file_path='./'):
        """
        maybe need to save file after filter
        same as starlab mean curvature skeleton
        """
        file_name = os.path.basename(self.skel_name)
        full_name = file_path + file_name
        v_num = len(self.verts)
        e_num = len(self.edges)
        first_line = '# D:3 ' + 'NV:' + str(v_num) + ' NE:' + str(e_num) + '\n'
        with open(full_name, 'w') as f:
            f.write(first_line)
            for v in self.verts:
                line = 'v ' + str(v[0]) + ' ' + str(v[1]) + ' ' + str(v[2]) + '\n'
                f.write(line)

            for e in self.edges:
                line = 'e ' + str(e[0]+1) + ' ' + str(e[1]+1) + '\n'
                f.write(line)
コード例 #48
0
ファイル: graph.py プロジェクト: elvis2els/map
class MapGraph(object):
    def __init__(self):
        self.g = Graph()
        self.dvertex_index = dict()
        self.vertex_label = self.g.new_vertex_property("string")
        self.g.vertex_properties["label"] = self.vertex_label
        self.edge_weight = self.g.new_edge_property("int")
        self.g.edge_properties["weight"] = self.edge_weight

    def has_vertex(self, label):
        """返回index"""
        return self.dvertex_index.get(label)

    def has_edge(self, s_label, e_label):
        s_vertex = self.dvertex_index.get(s_label)
        e_vertex = self.dvertex_index.get(e_label)
        if s_vertex and e_vertex:
            return self.g.edge(s_vertex, e_vertex)
        else:
            return None

    def add_edge(self, s_label, e_label):
        if self.has_edge(s_label, e_label):
            return self.g.edge(s_label, e_label)
        s_vertex = self.add_vertex(s_label)
        e_vertex = self.add_vertex(e_label)
        return self.g.add_edge(s_vertex, e_vertex)

    def add_vertex(self, label):
        """如果点存在则直接返回节点索引号"""
        if self.dvertex_index.get(label):
            return self.dvertex_index.get(label)
        v = self.g.add_vertex()
        self.vertex_label[v] = label
        self.dvertex_index[label] = v
        return v

    def add_edge_weight(self, s_label, e_label, weight):
        if self.has_edge(s_label, e_label):
            self.edge_weight[self.g.edge(s_label, e_label)] += weight
        else:
            edge = self.add_edge(s_label, e_label)
            self.edge_weight[edge] = weight

    @classmethod
    def networkx_to_graph_tool(cls, nx_g):
        gt_g = MapGraph()
        for e in nx_g.edges():
            gt_g.add_edge_weight(e[0], e[1], nx_g[e[0]][e[1]]["weight"])
        return gt_g

    def all_paths(self, s_label, e_label):
        if self.has_vertex(s_label) and self.has_vertex(e_label):
            time_s = time.time()
            s_vertex = self.dvertex_index.get(s_label)
            e_vertex = self.dvertex_index.get(e_label)
            for path in all_paths(
                    self.g,
                    s_vertex,
                    e_vertex,
                    cutoff=shortest_distance(self.g, s_vertex, e_vertex) *
                    1.5):
                if time.time() - time_s > 60 * 10:
                    break
                yield path