Source code for cactis.Digraph

import numpy as np
import networkx as nx


[docs] class Digraph(nx.DiGraph): """ A wrapper for networkx.DiGraph with custom edge weighting and distance matrix methods. Each node stores two attributes: - bin: the corresponding bin/vertex label - count: an integer count associated with that bin """
[docs] def __init__(self, adjacency_matrix, vertices, counts, loops: bool): """ Initialize a directed graph from an adjacency matrix. Parameters ---------- adjacency_matrix : ndarray of shape (n, n) Binary or weighted adjacency matrix describing directed edges. vertices : list of length n Labels for the vertices (e.g., bin indices). counts : list of length n Associated counts for each vertex. loops : bool Whether to keep self-loops (True) or remove them (False). Notes ----- - If 'loops' is False, the diagonal of the adjacency matrix is zeroed out before graph construction. - Node attributes 'bin' and 'count' are set from 'vertices' and 'counts' respectively. """ if loops == False: np.fill_diagonal(adjacency_matrix,0) super().__init__(adjacency_matrix) elif loops == True: super().__init__(adjacency_matrix) for i in range(len(self.nodes)): self.nodes[i]['bin'] = vertices[i] self.nodes[i]['count'] = counts[i]
[docs] def distance_matrix(self, method = 'unweighted_shortest_path'): """ Compute a pairwise distance matrix between all nodes. Parameters ---------- method : {`unweighted_shortest_path`, `weighted_shortest_path`, `probabilistic`} Returns ------- D : ndarray of shape (n, n) Distance matrix, where `D[i, j]` is the distance from node `i` to node `j`. Unreachable pairs are assigned a large value (1000). Notes ----- - The distance matrix is also stored as self.D. """ if method == 'unweighted_shortest_path': lengths = dict(nx.all_pairs_shortest_path_length(self)) D = np.full((len(lengths),len(lengths)),1000,dtype=float) # was -1 default for key in lengths: for item in lengths[key]: D[key,item] = lengths[key][item] if method == 'probabilistic': #since I doubt we are doing this in this paper, I haven't checked exactly if this is right w = nx.get_edge_attributes(self,'weight') for key in w: w[key] = 1/w[key] nx.set_edge_attributes(self,w,name='weight') lengths = dict(nx.all_pairs_dijkstra_path_length(self)) D = np.full((len(lengths),len(lengths)),1000,dtype=float) # was -1 default for key in lengths: for item in lengths[key]: if lengths[key][item] != 0: D[key,item] = lengths[key][item] elif lengths[key][item] == 0: D[key,item] = 0 if method == 'weighted_shortest_path': lengths = dict(nx.all_pairs_dijkstra_path_length(self)) D = np.full((len(lengths),len(lengths)),1000,dtype=float) # was -1 default for key in lengths: for item in lengths[key]: if lengths[key][item] != 0: D[key,item] = lengths[key][item] elif lengths[key][item] == 0: D[key,item] = 0 self.D = D return D
[docs] def weight_graph(self, weights, smallest, biggest): """ Assign edge weights to the graph. Parameters ---------- weights : callable Function of the form weights(smallest, biggest) that returns a weight for an edge. This is applied to every edge. For example, numpy.random.randint smallest : number Smallest number in the weight range biggest : number Biggest number in the weight range """ for e in self.edges: source = e[0] target = e[1] self[source][target]['weight'] = weights(smallest, biggest)
[docs] def get_weights(self): """ Retrieve all edge weights. Returns ------- weights : dict Dictionary mapping edges '(u, v)' to their 'weight' attribute. """ return nx.get_edge_attributes(self, "weight")