예제 #1
0
    def path(
        self, node_a: str, node_b: str
    ) -> typing.Tuple[typing.Tuple[typing.Tuple[Node], ...], typing.Tuple[
            typing.Dict[str, typing.Any], ...]]:
        connected, src_edges = self.connected(node_a, node_b)
        if not connected:
            return tuple(), tuple()
        # Iterate through the possible paths; can be 1 or more.
        paths = []
        paths_meta = []
        for src_edge in src_edges:
            log.debug("Finding path between {} and {} with source edge {}"
                      "".format(node_a, node_b, src_edge))
            with self.g.transaction(write=False) as txn:
                # Find the last edge we're looking for.
                query = 'e(type="{}")->@n(value="{}")'.format(
                    src_edge.edge_type, node_b)
                log.debug("Using query {}".format(query))
                tgt_edges = tuple(txn.query(query))
                log.debug("Got tgt_edges {}".format(tgt_edges))
                # Unravel
                tgt_edges = tuple(LGGraph._parse_edge(e[0]) for e in tgt_edges)
                log.debug("tgt_edges after unraveling {}".format(tgt_edges))

                # There should be at least one connection, but can be more
                # if there are repeats.
                if len(tgt_edges) == 0:
                    raise GraphException(g=self)

                log.debug("Checking source edge {} for {} target edges".format(
                    src_edge, len(tgt_edges)))
                for tgt_edge in tgt_edges:
                    log.debug("Checking for target edge {}".format(tgt_edge))
                    if src_edge.edge_value > tgt_edge.edge_value:
                        log.debug("Skipping target edge {}".format(tgt_edge) +
                                  " with value {} because".format(src_edge) +
                                  "source edge has greater incr tag")
                        continue
                    path_nodes = self._find_path(src_edge, tgt_edge, txn)
                    if path_nodes == -1:
                        continue
                    if len(path_nodes) < 2:
                        raise GraphException(g=self)
                    log.debug("Found path of length {}".format(
                        len(path_nodes)))
                    log.debug("Got path {}".format(path_nodes))

                    # Append
                    paths.append(path_nodes)
                    if src_edge.labels is not None:
                        paths_meta.append({
                            'edge_type': src_edge.edge_type,
                            **src_edge.labels
                        })
                    else:
                        paths_meta.append({'edge_type': src_edge.edge_type})
        return tuple(paths), tuple(paths_meta)
예제 #2
0
def test_dgraph_edges_multiple_reverse(dg: Dgraph):
    _setup_connected_multiple(dg)
    edges = dg.find_edges_reverse("CDE")
    try:
        assert len(edges) == 2
    except:
        raise GraphException(dg)
예제 #3
0
def test_lemongraph_not_connected(prebuilt_graph: Graph):
    connected, starting_edges = prebuilt_graph.connected(
        'GCTGGATACGT', 'CGTCCGGACGT')
    if connected:
        raise GraphException(prebuilt_graph)
    else:
        assert True
    assert len(starting_edges) == 0
예제 #4
0
def test_lemongraph_connected_distant(prebuilt_graph: Graph):
    connected, starting_edges = prebuilt_graph.connected(
        'ATACGACGCCA', 'CGTCCGGACGT')
    if not connected:
        raise GraphException(prebuilt_graph)
    else:
        assert True
    assert len(starting_edges) == 1
    log.debug("Found starting_edges as {}".format(starting_edges[0]))
예제 #5
0
def test_graph_connected_no_node(g: Graph):
    _setup_connected_no_node(g)

    connected, starting_edges = g.connected('ABC', 'BCD')
    if connected:
        raise GraphException(g)
    else:
        assert True
    assert len(starting_edges) == 0
예제 #6
0
def test_graph_connected(g: Graph):
    _setup_connected(g)

    connected, starting_edges = g.connected('ABC', 'BCD')
    if not connected:
        raise GraphException(g)
    else:
        assert True
    assert len(starting_edges) == 1
    log.debug("Found starting_edges as {}".format(starting_edges[0]))
예제 #7
0
def test_graph_connected_shortcut(g: Graph):
    _setup_connected_shortcut(g)

    connected, starting_edges = g.connected('ABC', 'CDE')
    if not connected:
        raise GraphException(g)
    else:
        assert True
    assert len(starting_edges) == 2
    log.debug("Found starting_edges as:")
    for e in starting_edges:
        log.debug(e)
예제 #8
0
def test_graph_connected_path(g: Graph):
    _setup_connected(g)
    paths, _ = g.path("ABC", "BCD")
    # There should be 1 path in paths
    assert len(paths) == 1
    path = paths[0]
    if path[0].value != "ABC" or path[1].value != "BCD":
        raise GraphException(g=g)
    else:
        assert True

    joined = concat_values(path)
    assert joined == "ABCD"
예제 #9
0
def test_graph_basics_edges_dgraph(dg: Dgraph):
    g = dg
    expected = ["ABC", "BCE", "CEF"]
    expected = [Node(value=v) for v in expected]

    g.add_edge(Edge(src=expected[0].value, tgt=expected[1].value))
    g.add_edge(Edge(src=expected[1].value, tgt=expected[2].value))
    try:
        # In Dgraph we can retrieve the actual kmer value
        assert {(e.src, e.tgt) for e in g.edges} == {
            (expected[0].value, expected[1].value),
            (expected[1].value, expected[2].value)}
    except:
        raise GraphException(g)
예제 #10
0
def test_graph_connected_repeats_full_path(g: Graph):
    n1 = Node(value="ABC")
    n2 = Node(value="BCD")
    n3 = Node(value="CDE")
    g.upsert_node(n1)
    g.upsert_node(n2)
    g.upsert_node(n3)
    e1 = Edge(src="ABC", tgt="BCD", edge_value=0)
    g.add_edge(e1)
    e2 = Edge(src="BCD", tgt="CDE", edge_value=1)
    g.add_edge(e2)
    e3 = Edge(src="CDE", tgt="ABC", edge_value=2)
    g.add_edge(e3)
    e4 = Edge(src="ABC", tgt="BCD", edge_value=3)
    g.add_edge(e4)
    e5 = Edge(src="BCD", tgt="CDE", edge_value=4)
    g.add_edge(e5)
    g.save()

    try:
        paths, _ = g.path('ABC', 'CDE')
    except:
        raise GraphException(g)

    assert len(paths) == 3

    c = 0
    for path in paths:
        assert path[0].value == "ABC"
        assert path[-1].value == "CDE"
        if len(path) == 3:
            assert path[1].value == "BCD"
            # There are 2 copies of this
            c += 1
        elif len(path) == 6:
            assert path[1].value == "BCD"
            assert path[2].value == "CDE"
            assert path[3].value == "ABC"
            assert path[4].value == "BCD"
            assert path[5].value == "CDE"

    assert c == 2
예제 #11
0
def test_graph_basics_edges_lemongraph(lgr: LGGraph):
    g = lgr
    expected = ["ABC", "BCE", "CEF"]
    expected = [Node(value=v) for v in expected]

    nodes_with_ids = []
    for node in expected:
        # Returned the node with db_id set, these are required to check edges
        n = g.upsert_node(node)
        nodes_with_ids.append(n)

    g.add_edge(Edge(src=expected[0].value, tgt=expected[1].value))
    g.add_edge(Edge(src=expected[1].value, tgt=expected[2].value))
    try:
        # In lemongraph these are stored as numerical IDs
        assert {(e.src, e.tgt) for e in g.edges} == {
            (nodes_with_ids[0].db_id, nodes_with_ids[1].db_id),
            (nodes_with_ids[1].db_id, nodes_with_ids[2].db_id)}
    except:
        raise GraphException(g)