File: test_maps.py

package info (click to toggle)
python-cogent 2023.2.12a1%2Bdfsg-2%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 12,416 kB
  • sloc: python: 89,165; makefile: 117; sh: 16
file content (147 lines) | stat: -rw-r--r-- 4,844 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python

import unittest

from cogent3 import DNA, make_aligned_seqs
from cogent3.core.annotation import Feature, _Feature
from cogent3.core.location import Map, Span


__author__ = "Peter Maxwell"
__copyright__ = "Copyright 2007-2022, The Cogent Project"
__credits__ = ["Peter Maxwell", "Gavin Huttley", "Rob Knight", "Matthew Wakefield"]
__license__ = "BSD-3"
__version__ = "2023.2.12a1"
__maintainer__ = "Gavin Huttley"
__email__ = "gavin.huttley@anu.edu.au"
__status__ = "Production"


def SimpleAnnotation(parent, locations, name):
    return Feature(parent, "", name, locations)


def annotate(parent, start, end, name):
    annot = parent.add_annotation(SimpleAnnotation, locations=[(start, end)], name=name)
    return annot


def structure(a, depth=0):
    annots = [structure(annot, depth + 1) for annot in a.annotations]
    if not isinstance(a, _Feature):
        return ("seq", len(a), annots)
    elif annots:
        return (a.name, repr(a.map), annots)
    else:
        return (a.name, repr(a.map))


class MapTest(unittest.TestCase):
    """Testing annotation of and by maps"""

    def test_spans(self):
        # a simple two part map of length 10
        map = Map([(0, 5), (5, 10)], parent_length=10)
        # try different spans on the above map
        for ((start, end), expected) in [
            ((0, 4), "[0:4]"),
            ((0, 5), "[0:5]"),
            ((0, 6), "[0:5, 5:6]"),
            ((5, 10), "[5:10]"),
            ((-1, 10), "[-1-, 0:5, 5:10]"),
            ((5, 11), "[5:10, -1-]"),
            ((0, 10), "[0:5, 5:10]"),
            ((10, 0), "[10:5, 5:0]"),
        ]:
            r = repr(Span(start, end, reverse=start > end).remap_with(map))
            # print (start, end), r,
            if r != expected:
                self.fail(repr((r, expected)))

    def test_maps_on_maps(self):
        seq = DNA.make_seq("ATCGATCGAT" * 5, name="base")
        feat1 = annotate(seq, 10, 20, "fake")
        annotate(feat1, 3, 5, "fake2")
        annotate(seq, 1, 3, "left")

        seq2 = seq[5:]
        self.assertEqual(
            structure(seq),
            (
                "seq",
                50,
                [("fake", "[10:20]/50", [("fake2", "[3:5]/10")]), ("left", "[1:3]/50")],
            ),
        )
        self.assertEqual(
            structure(seq2),
            ("seq", 45, [("fake", "[5:15]/45", [("fake2", "[3:5]/10")])]),
        )

    def test_get_by_annotation(self):
        seq = DNA.make_seq("ATCGATCGAT" * 5, name="base")
        seq.add_annotation(Feature, "test_type", "test_label", [(5, 10)])
        seq.add_annotation(Feature, "test_type", "test_label2", [(15, 18)])

        answer = list(seq.get_by_annotation("test_type"))
        self.assertEqual(len(answer), 2)
        self.assertEqual(str(answer[0]), "TCGAT")
        self.assertEqual(str(answer[1]), "TCG")

        answer = list(seq.get_by_annotation("test_type", "test_label"))
        self.assertEqual(len(answer), 1)
        self.assertEqual(str(answer[0]), "TCGAT")

        # test ignoring of a partial annotation
        sliced_seq = seq[:17]
        answer = list(sliced_seq.get_by_annotation("test_type", ignore_partial=True))
        self.assertEqual(len(answer), 1)
        self.assertEqual(str(answer[0]), "TCGAT")

    def test_get_by_seq_annotation(self):
        aln = make_aligned_seqs(
            data={"a": "ATCGAAATCGAT", "b": "ATCGA--TCGAT"}, array_align=False
        )
        b = aln.get_seq("b")
        b.add_annotation(Feature, "test_type", "test_label", [(4, 6)])

        answer = aln.get_by_seq_annotation("b", "test_type")[0].to_dict()
        self.assertEqual(answer, {"b": "A--T", "a": "AAAT"})


if 0:  # old, needs fixes
    # Maps
    a = Map([(10, 20)], parent_length=100)

    for (desc, map, expected) in [
        ("a ", a, "Map([10:20] on base)"),
        ("i ", a.inverse(), "Map([-10-, 0:10, -80-] on Map([10:20] on base))"),
        ("1 ", a[5:], "Map([5:10] on Map([10:20] on base))"),
        ("1r", a[5:].relative_to(b), "Map([15:20] on base)"),
        ("2 ", a[:5], "Map([0:5] on Map([10:20] on base))"),
        ("2r", a[:5].relative_to(b), "Map([10:15] on base)"),
        (
            "r ",
            a.relative_to(a[5:]),
            "Map([-5-, 0:5] on Map([5:10] on Map([10:20] on base)))",
        ),
        (
            "r ",
            a[2:4].relative_to(a[2:6]),
            "Map([0:2] on Map([2:6] on Map([10:20] on base)))",
        ),
        (
            "r ",
            a[2:4].relative_to(a[2:6][0:3]),
            "Map([0:2] on Map([0:3] on Map([2:6] on Map([10:20] on base))))",
        ),
    ]:
        print(desc, repr(map), end=" ")
        if repr(map) == expected:
            print()
        else:
            print(" <--- ", expected)
            bad = True

if __name__ == "__main__":
    unittest.main()