def _neighborhood(self, node: Vertex) -> float: """Score a node based on its and its neighbours' log fold change. :param Vertex node: Node to be scored. :return float: Score of the node. """ node_fc = abs(node["l2fc"]) sum_fc = 0 for n in node.neighbors(): sum_fc += abs(n["l2fc"]) if len(node.neighbors()) > 0: return 0.5 * node_fc + 0.5 * sum_fc / len(node.neighbors()) else: return 0
def _search_continuous_edge( self, v: igraph.Vertex, visited_indices: Set[int] = None, ) -> Set[int]: """ Given a vertex, v, will find the continuous string of vertices v is part of. NOTE: Recursive function Args: v: current Vertex. If v has 2 neighbors, it's part of a continuous string. If not, recursion ends visited_indices: """ if visited_indices is None: #visited_indices = [] visited_indices = set() neighbors = v.neighbors() #visited_indices.append(v.index) visited_indices.add(v.index) if len(neighbors) != 2: return visited_indices else: for n in neighbors: if n.index not in visited_indices: path = self._search_continuous_edge(n, visited_indices) return visited_indices
def compare_vertices(v1: Vertex, v2: Vertex): v1d = v1.degree() v2d = v2.degree() if v1d < v2d: return v1 elif v1d > v2d: return v2 else: n: Vertex sum_neighbours_degree_v1 = sum([n.degree() for n in v1.neighbors()]) sum_neighbours_degree_v2 = sum([n.degree() for n in v2.neighbors()]) if sum_neighbours_degree_v1 > sum_neighbours_degree_v2: return v1 elif sum_neighbours_degree_v1 < sum_neighbours_degree_v2: return v2 else: random_number = random.randint(0, 1) return v1 if random_number == 0 else v2
def compute_g_of_v_for_testing(v: Vertex): degree = v.degree() if degree == 0: return 0, degree, (0 * degree) g_minus = 1 / (degree + 1) g_plus = np.array( [1 / (n.degree() * (n.degree() + 1)) for n in v.neighbors()]).sum() g = g_plus - g_minus return g, degree, g * degree
def compute_g_of_v(v: Vertex): degree = v.degree() if degree == 0: return 0 g_minus = 1 / (degree + 1) g_plus = np.array( [1 / (n.degree() * (n.degree() + 1)) for n in v.neighbors()]).sum() g = g_plus - g_minus return g
def compute_k(graph: Graph, vertex: Vertex): neighbors = vertex.neighbors() sum_x = 0 for v in graph.vs: if v == vertex: pass elif v in neighbors: x = (v.degree() - 1) / v.degree() sum_x = sum_x + x else: sum_x = sum_x + (v.degree() / (v.degree() + 1)) return sum_x + 1
def computeE_w(selected_vertex: Vertex, graph: Graph, C: Set[int], b: int) -> float: copy: Graph = graph.copy() C2 = C.union( [neighbor['orig_index'] for neighbor in selected_vertex.neighbors()]) copy.delete_vertices(selected_vertex.index) if b == 1: new_N = len(copy.vs) return new_N - len(C2) else: return sum([ computeE_w_helper(v.degree(), len(copy.vs), b - 1) for v in copy.vs if v['orig_index'] not in C2 ])
def _simplify_node(self, vertex: igraph.Vertex) -> None: """ If we simplify node B with connections A -- B -- C then we end up with (AB) -- C where the weight of the edge between (AB) and C equals the sum of the weights between A-B and B-C NOTE: this allows the graph to simplify long strings of nodes Args: vertex: node B in the description, to be merged with its neighbor Returns: Modifies graph in-place, no return value """ # Store the 2 neighbors of the node we are simplifying n0_vtx, n1_vtx = vertex.neighbors() n0_name = n0_vtx['name'] n1_name = n1_vtx['name'] n0_seq = self.vs.select(name=n0_vtx['name']) n1_seq = self.vs.select(name=n1_vtx['name']) v = self.vs.select(name=vertex['name']) # Grab each neighbor edge weight edge_n0 = self.es.select(_between=(n0_seq, v)) edge_n1 = self.es.select(_between=(n1_seq, v)) total_weight = edge_n0[0]['weight'] + edge_n1[0]['weight'] # Form a new edge between the two neighbors # The new_path must reflect the node that will be removed and the # 2 edges that will be removed new_path = edge_n0[0]['path'] + [vertex['name']] + edge_n1[0]['path'] super().add_edge(n0_seq[0], n1_seq[0], weight=total_weight, path=new_path) # Now we can delete the vertex and its 2 edges edge_n0 = self.es.select(_between=(n0_seq, v)) super().delete_edges(edge_n0) edge_n1 = self.es.select(_between=(n1_seq, v)) super().delete_edges(edge_n1) super().delete_vertices(v)
def get_igraph_walk(self, graph: igraph.Graph, vertex: igraph.Vertex) -> Walk: """Generate second-order random walks biased by edge weights.""" if self.parameters.max_path_length < 2: raise ValueError( "The path length for random walk is less than 2, which doesn't make sense" ) if self._check(vertex): return # Start walk yield vertex double_tail = vertex # Calculate walk length if vertex in self.sampling_strategy: walk_length = self.sampling_strategy[vertex].get( self.WALK_LENGTH_KEY, self.parameters.max_path_length) else: walk_length = self.parameters.max_path_length probabilities = vertex[self.FIRST_TRAVEL_KEY] tail = np.random.choice(vertex.neighbors(), p=probabilities) if not tail: return yield tail # Perform walk path_length = 2 while path_length < walk_length: neighbors = tail.neighbors() # Skip dead end nodes if not neighbors: break probabilities = tail[self.PROBABILITIES_KEY][double_tail['name']] double_tail, tail = tail, np.random.choice(neighbors, p=probabilities) yield tail path_length += 1
def any_neighbors_rank_1(v: Vertex): return any([n.degree() == 1 for n in v.neighbors()])
def remove_vertex_and_neighbors(graph: Graph, v: Vertex): graph.delete_vertices([v.index] + [ve.index for ve in v.neighbors()])
def is_neighbor_of_black(vertex: Vertex): neighbors = vertex.neighbors() for n in neighbors: if n['color'] == Color.BLACK: return True return False
def compute_neighbour_degree_frequency(degree_per_vector: List[int], vertex: Vertex): degree_vector_for_vertex = [ degree_per_vector[neighbour.index] for neighbour in vertex.neighbors() ] return Counter(degree_vector_for_vertex)
def compute_z(v: Vertex): return sum([compute_x_minus_1(n) for n in v.neighbors()]) + 1
def compute_y(v: Vertex): return sum([compute_x(n) for n in v.neighbors()]) + compute_x(v)
def isInA(v: Vertex): degree = v.degree() neighbors_with_lower_degree = [ n for n in v.neighbors() if n.degree() < degree ] return len(neighbors_with_lower_degree) > 0
def b_v(v: Vertex): degree = v.degree() neighbors_with_lower_degree = [ n for n in v.neighbors() if n.degree() == degree ] return len(neighbors_with_lower_degree)