def test_one_instance(self): H = nx.DiGraph() H.add_edge("x", "y", weight=1) H.add_edge("y", "z", weight=10) H.add_edge("z", "x", weight=5) motif = dotmotif.dotmotif().from_motif(""" A -> B [weight>=11] """.strip()) self.assertEqual(len(NetworkXExecutor(graph=H).find(motif)), 0)
def test_edge_attribute_equality(self): dm = dotmotif.dotmotif() dm.from_motif(""" A->B [weight==10, area==4] """) H = nx.DiGraph() H.add_edge("z", "x", weight=10, area=4) H.add_edge("x", "y") H.add_edge("y", "z", weight=5) self.assertEqual(len(NetworkXExecutor(graph=H).find(dm)), 1)
def test_edgecount_motif(self): dm = dotmotif.dotmotif() dm.from_motif("""A->B""") H = nx.DiGraph() H.add_edge("x", "y") self.assertEqual(len(NetworkXExecutor(graph=H).find(dm)), 1) H.add_edge("x", "y") self.assertEqual(len(NetworkXExecutor(graph=H).find(dm)), 1) H.add_edge("x", "z") self.assertEqual(len(NetworkXExecutor(graph=H).find(dm)), 2)
def test_wrong_args_macro(self): exp = """\ edge(A, B) { A -> B B -> A } edge(C, D, E) """ # with self.assertRaises(ValueError): with self.assertRaises(Exception): dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp)
def test_simple_macro_construction(self): exp = """\ edge(A, B) { A -> B } edge(C, D) """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) exp_edge = list(dm._g.edges(data=True))[0] self.assertEqual(exp_edge[0], "C") self.assertEqual(exp_edge[1], "D")
def test_undefined_macro(self): exp = """\ dualedge(A, B) { A -> B B -> A } foo(C, D) """ # with self.assertRaises(ValueError): with self.assertRaises(Exception): dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp)
def test_mini_example(self): H = nx.DiGraph() H.add_edge("y", "x", ATTRIBUTE=7) H.add_edge("y", "z", ATTRIBUTE=7) motif = dotmotif.dotmotif().from_motif( """ A -> B [ATTRIBUTE>=7] """.strip() ) self.assertEqual(len(GrandIsoExecutor(graph=H).find(motif)), 2)
def test_cypher_node_attributes(self): dm = dotmotif.dotmotif() dm.from_motif(""" A -> B A.size = "big" """) self.assertEqual( Neo4jExecutor.motif_to_cypher(dm).strip(), """MATCH (A:Neuron)-[A_B:SYN]->(B:Neuron)\nWHERE A.size = "big"\nRETURN DISTINCT A,B""" .strip(), )
def test_more_complex_macro(self): exp = """\ tri(A, B, C) { A -> B B -> C C -> A } tri(C, D, E) """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) edges = list(dm._g.edges(data=True)) self.assertEqual(len(edges), 3)
def test_edge_macro_attr(self): exp = """\ macro(Aa, Ba) { Aa -> Ba [type != 1, type != 12] } macro(X, Y) """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) self.assertEqual(len(dm._g.edges()), 1) u, v, d = list(dm._g.edges(data=True))[0] self.assertEqual(d["constraints"]["type"], {"!=": [1, 12]})
def test_cypher_node_same_node_many_attributes(self): dm = dotmotif.dotmotif() dm.from_motif(""" A -> B A.personality != "exciting" A.personality != "funny" """) self.assertEqual( Neo4jExecutor.motif_to_cypher(dm).strip(), """MATCH (A:Neuron)-[A_B:SYN]->(B:Neuron)\nWHERE A.personality <> "exciting" AND A.personality <> "funny"\nRETURN DISTINCT A,B""" .strip(), )
def test_automorphism_flag_triangle(self): G = nx.DiGraph() G.add_edge("A", "B") G.add_edge("B", "C") G.add_edge("C", "A") motif = dotmotif.dotmotif().from_motif(""" A -> B B -> C C -> A """) res = NetworkXExecutor(graph=G).find(motif) self.assertEqual(len(res), 3) motif = dotmotif.dotmotif(exclude_automorphisms=True).from_motif(""" A -> B B -> C C -> A """) res = NetworkXExecutor(graph=G).find(motif) self.assertEqual(len(res), 1)
def test_automorphism_notauto(self): G = nx.DiGraph() G.add_edge("X", "Z") G.add_edge("Y", "Z") motif = dotmotif.dotmotif().from_motif(""" A -> C B -> C """) res = NetworkXExecutor(graph=G).find(motif) self.assertEqual(len(res), 2)
def test_cypher_node_and_edge_attributes(self): dm = dotmotif.dotmotif() dm.from_motif(""" A -> B [area != 10] A.area <= 10 B.area <= 10 """) self.assertEqual( Neo4jExecutor.motif_to_cypher(dm).strip(), ("MATCH (A:Neuron)-[A_B:SYN]->(B:Neuron)\n" "WHERE A.area <= 10 AND B.area <= 10 AND A_B.area <> 10\n" "RETURN DISTINCT A,B").strip(), )
def test_node_multi_attr(self): exp = """\ Aa -> Ba Aa.type = "excitatory" Aa.size = 4.5 """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) self.assertEqual(len(dm.list_node_constraints()), 1) self.assertEqual(len(dm.list_node_constraints()["Aa"]), 2) self.assertEqual(dm.list_node_constraints()["Aa"]["type"]["="], ["excitatory"]) self.assertEqual(dm.list_node_constraints()["Aa"]["size"]["="], [4.5]) self.assertEqual(list(dm.list_node_constraints().keys()), ["Aa"])
def test_dynamic_constraints(self): """ Test that comparisons may be made between variables, e.g.: A.type != B.type """ exp = """\ A -> B A.radius < B.radius """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) self.assertEqual(len(dm.list_dynamic_node_constraints()), 1)
def test_cypher_negative_edge_and_inequality(self): dm = dotmotif.dotmotif(enforce_inequality=True) dm.from_motif(""" A -> B A -> C B !> C """) self.assertEqual( Neo4jExecutor.motif_to_cypher(dm).strip(), ("MATCH (A:Neuron)-[A_B:SYN]->(B:Neuron)\n" "MATCH (A:Neuron)-[A_C:SYN]->(C:Neuron)\n" "WHERE NOT (B:Neuron)-[:SYN]->(C:Neuron) AND A<>B AND A<>C AND B<>C\n" "RETURN DISTINCT A,B,C").strip(), )
def test_automorphism_auto(self): G = nx.DiGraph() G.add_edge("X", "Z") G.add_edge("Y", "Z") motif = dotmotif.dotmotif(exclude_automorphisms=True).from_motif( """ A -> C B -> C """ ) res = GrandIsoExecutor(graph=G).find(motif) self.assertEqual(len(res), 1)
def test_fullyconnected_triangle_motif(self): dm = dotmotif.dotmotif() dm.from_motif(""" A->B B->C C->A """) H = nx.DiGraph() H.add_edge("x", "y") self.assertEqual(len(NetworkXExecutor(graph=H).find(dm)), 0) H.add_edge("y", "z") self.assertEqual(len(NetworkXExecutor(graph=H).find(dm)), 0) H.add_edge("z", "x") self.assertEqual(len(NetworkXExecutor(graph=H).find(dm)), 3)
def test_two_instance(self): H = nx.DiGraph() H.add_edge("x", "y", weight=1) H.add_edge("y", "z", weight=10) H.add_edge("z", "x", weight=5) H.add_edge("z", "a", weight=5) H.add_edge("a", "b", weight=1) H.add_edge("b", "c", weight=10) H.add_edge("c", "a", weight=5) motif = dotmotif.dotmotif().from_motif( """ A -> B [weight>=7] """.strip() ) self.assertEqual(len(GrandIsoExecutor(graph=H).find(motif)), 2)
def test_nested_macros(self): exp = """\ dualedge(A, B) { A -> B B -> A } dualtri(A, B, C) { dualedge(A, B) dualedge(B, C) dualedge(C, A) } dualtri(foo, bar, baz) """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) edges = list(dm._g.edges(data=True)) self.assertEqual(len(edges), 6)
def test_dynamic_constraints_in_macro(self): """ Test that comparisons may be made between variables in a macro, e.g.: A.type != B.type """ exp = """\ macro(A, B) { A.radius > B.radius } macro(A, B) A -> B """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) self.assertEqual(len(dm.list_dynamic_node_constraints()), 1)
def test_combo_macro(self): exp = """\ edge(A, B) { A -> B } dualedge(A, B) { # Nested-inside comment! edge(A, B) B -> A } dualedge(foo, bar) """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) edges = list(dm._g.edges(data=True)) self.assertEqual(len(edges), 2)
def find_motif(self): # find motif and write out motif_df use dotmotif ''' dotmotif need to cite @article{matelsky_2020_dotmotif, doi = {10.1101/2020.06.08.140533}, url = {https://www.biorxiv.org/content/10.1101/2020.06.08.140533v1}, year = 2020, month = {june}, publisher = {BiorXiv}, author = {Matelsky, Jordan K. and Reilly, Elizabeth P. and Johnson,Erik C. and Wester, Brock A. and Gray-Roncal, William}, title = {{Connectome subgraph isomorphisms and graph queries with DotMotif}}, journal = {BiorXiv} } ''' if self.dataset == 'cn': G = self.cn_G() if self.dataset == 'mo': G = self.mo_G() if self.dataset == 'db': G = self.db_G() for root, _, files in os.walk('./data/' + self.dataset + '/motif'): for file in files: start = time.process_time() motif_file_name = root + '/' + file dm = dotmotif.dotmotif().from_motif(motif_file_name) tmp_df = pd.DataFrame() tmp_list = [] for i in NetworkXExecutor(graph=G).find(dm): tmp_list.append(i) if tmp_list: tmp_df = tmp_df.append(tmp_list, ignore_index=True) tmp_df = tmp_df.reindex(columns=['A', 'B', 'C' ]) # see floder '/motif' tmp_df.to_csv('./data/' + self.dataset + '/motif_unprocess/' + file, sep='\t', index=0, header=0) else: print(file, ' not exsit') elapsed = time.process_time() - start print(file, 'motif created. time cost:', elapsed) print(time.strftime('%y-%m-%d %I:%M:%S %p'))
def test_comment_macro_inline(self): exp = """\ edge(A, B) { A -> B } dualedge(A, B) { # Nested-inside comment! edge(A, B) # inline comment B -> A } dualedge(foo, bar) # inline comment # standalone comment foo -> bar # inline comment """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) edges = list(dm._g.edges(data=True)) self.assertEqual(len(edges), 2)
def test_dynamic_constraints_one_result(self): """ Test that comparisons may be made between variables, e.g.: A.type != B.type """ G = nx.DiGraph() G.add_edge("A", "B") G.add_edge("B", "C") G.add_edge("C", "A") G.add_node("A", radius=25) G.add_node("B", radius=10) exp = """\ A -> B A.radius > B.radius """ dm = dotmotif.dotmotif(parser=ParserV2) res = GrandIsoExecutor(graph=G).find(dm.from_motif(exp)) self.assertEqual(len(res), 1)
def test_conflicting_macro_invalid_edge_throws(self): exp = """\ tri(A, B, C) { A -> B B -> C C -> A } nontri(A, B, C) { A !> B B !> C C !> A } tri(C, D, E) nontri(D, E, F) """ # with self.assertRaises(dotmotif.validators.DisagreeingEdgesValidatorError): with self.assertRaises(Exception): dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp)
def test_dynamic_constraints_in_macros_zero_results(self): """ Test that comparisons may be made between variables, e.g.: A.type != B.type """ G = nx.DiGraph() G.add_edge("A", "B") G.add_edge("B", "C") G.add_edge("C", "A") G.add_node("A", radius=5) G.add_node("B", radius=10) exp = """\ macro(A, B) { A.radius > B.radius } macro(A, B) A -> B """ dm = dotmotif.dotmotif(parser=ParserV2) res = NetworkXExecutor(graph=G).find(dm.from_motif(exp)) self.assertEqual(len(res), 0)
def test_clustercuss_macros_no_repeats(self): exp = """\ edge(A, B) { A -> B } dualedge(A, B) { edge(A, B) edge(B, A) } dualtri(A, B, C) { dualedge(A, B) dualedge(B, C) dualedge(C, A) } dualtri(foo, bar, baz) dualtri(foo, bar, baf) """ dm = dotmotif.dotmotif(parser=ParserV2) dm.from_motif(exp) edges = list(dm._g.edges(data=True)) self.assertEqual(len(edges), 10)
def test_dm_parser_defaults(self): dm = dotmotif.dotmotif() dm.from_motif(_DEMO_G_MIN) self.assertEqual( Neo4jExecutor.motif_to_cypher(dm).strip(), _DEMO_G_MIN_CYPHER.strip())