def _match_disease(v: Vertex) -> bool: """Tests if a vertex name matches the regular expression for disease ids.""" try: disease_regex.match(v.attributes()["name"]) except TypeError: print(v.attributes()["name"]) print(type(v.attributes()["name"])) sys.exit() return bool(disease_regex.match(v.attributes()["name"]))
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 _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_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 is_loop(g: Graph, v: Vertex, e: Edge): """ Check if a vertex can reach itself again using the provided edge (check if the edge creates a loop)""" if not has_path_not_using_any_loop_edges(e.target_vertex, v): return False # Simulate deletion of edge and check if still loops e_orig_source = e.source e_orig_target = e.target e_orig_attr = e.attributes() g.delete_edges(e) has_any_loops = False for e in v.out_edges(): if has_path_not_using_any_loop_edges(e.target_vertex, v): has_any_loops = True break g.add_edge(e_orig_source, e_orig_target, **e_orig_attr) return not has_any_loops
def match(self, vertex: Vertex): if not vertex['morph_inf_list']: return False if self.grammemes and self.grammemes not in vertex['morph_info_list'][ 0].tag: return False if self.white_list and vertex['morph_info_list'].normal_form.lower( ) not in self.white_list: return False if self.black_list and vertex['morph_info_list'].normal_form.lower( ) in self.black_list: return False if not self._children: return True children = {e.graph.vs[e.target] for e in vertex.out_edges()} for child_pattern in self._children: for child in filter(child_pattern.match, children): children.discard(child) break else: return False return True
def get_for(cls, v: Vertex, decompiler: 'ExplorerScriptSsbDecompiler', parent: AbstractWriteHandler, vertex_that_started_block: Vertex, is_first_vertex_of_block: bool) -> AbstractWriteHandler: from explorerscript.ssb_converting.decompiler.write_handlers.foreign_label import ForeignLabelWriteHandler from explorerscript.ssb_converting.decompiler.write_handlers.label import LabelWriteHandler from explorerscript.ssb_converting.decompiler.write_handlers.label_jump import LabelJumpWriteHandler from explorerscript.ssb_converting.decompiler.write_handlers.simple_op import SimpleOperationWriteHandler if 'op' not in v.attributes(): raise ValueError(f"Invalid Ssb vertex: {v}") op: SsbOperation = v['op'] if isinstance(op, SsbLabel): return LabelWriteHandler(v, decompiler, parent, vertex_that_started_block, is_first_vertex_of_block) if isinstance(op, SsbForeignLabel): return ForeignLabelWriteHandler(v, decompiler, parent, vertex_that_started_block, is_first_vertex_of_block) if isinstance(op, SsbLabelJump): return LabelJumpWriteHandler(v, decompiler, parent) return SimpleOperationWriteHandler(v, decompiler, parent)
def is_disease(v: Vertex) -> bool: """Tests if a vertex is a disease node. """ return v.attributes()['type'] == 'disease'
def is_gene(v: Vertex) -> bool: """Tests if a vertex is a gene node. """ return v.attributes()['type'] == 'gene'
def is_drug(v: Vertex) -> bool: """Tests if a vertex is a drug node. """ return v.attributes()['type'] == 'drug'
def _is_downregulated_gene(self, v: Vertex) -> bool: return self._is_significantly_differentiated( v) and v.attributes()['l2fc'] < self.max_l2fc
def _is_significantly_differentiated(self, v: Vertex) -> bool: return v.attributes()['padj'] < self.max_adj_p
def _is_significantly_differentiated(self, v: Vertex) -> bool: """In a heterogeneous network, the vertex has to be tested if it is a gene before testing if it's up or down regulated.""" return self.is_gene(v) and v.attributes()['padj'] < self.max_adj_p
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 helper(v: Vertex): dv = v.degree() dv_1_squared = (dv + 1)**2 return dv / dv_1_squared
def compute_z(v: Vertex): return sum([compute_x_minus_1(n) for n in v.neighbors()]) + 1
def count_bags(vertex: ig.Vertex): return 1 + sum(edge['contains'] * count_bags(edge.target_vertex) for edge in list(vertex.out_edges()))
def compute_x_minus_1(v: Vertex): deg = v.degree() return (deg - 1) / deg
def compute_x(v: Vertex): deg = v.degree() return deg / (deg + 1)
def _match_drug(v: Vertex) -> bool: """Tests if a vertex name matches the regular expression for Drugbank ids. """ return bool(drugbank_regex.match(v.attributes()["name"]))
def remove_vertex_and_neighbors(graph: Graph, v: Vertex): graph.delete_vertices([v.index] + [ve.index for ve in v.neighbors()])
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)
def compute_y(v: Vertex): return sum([compute_x(n) for n in v.neighbors()]) + compute_x(v)
def compute_t(orig: Graph, vertex: Vertex): graph: Graph = orig.copy() how_many_neighbors = vertex.degree() remove_vertex_and_neighbors(graph, vertex) dv_dv_plus_1 = [(v.degree() / (v.degree() + 1)) for v in graph.vs] return sum(dv_dv_plus_1) + how_many_neighbors