Beispiel #1
0
 def test_read(self):
     s1 = BytesIO(b'@r1\nACG\n+\nHHH\n')
     s2 = BytesIO(b'@r2\nGTT\n+\n858\n')
     with PairedSequenceReader(s1, s2) as psr:
         assert [
             (Sequence("r1", "ACG", "HHH"), Sequence("r2", "GTT", "858")),
         ] == list(psr)
Beispiel #2
0
 def test_write_sequence_object(self):
     with FastaWriter(self.path) as fw:
         fw.write(Sequence("name", "CCATA"))
         fw.write(Sequence("name2", "HELLO"))
     assert fw._file.closed
     with open(self.path) as t:
         assert t.read() == '>name\nCCATA\n>name2\nHELLO\n'
Beispiel #3
0
def test_end_trim_with_mismatch():
    """
    Test the not-so-obvious case where an adapter of length 13 is trimmed from
    the end of a sequence with overlap 9 and there is one deletion.
    In this case the algorithm starts with 10 bases of the adapter to get
    the hit and so the match is considered good. An insertion or substitution
    at the same spot is not a match.
    """
    adapter = Adapter('TCGATCGATCGAT', BACK, max_error_rate=0.1)

    read = Sequence('foo1', 'AAAAAAAAAAATCGTCGATC')
    cutter = AdapterCutter([adapter], times=1)
    trimmed_read = cutter(read, [])

    assert trimmed_read.sequence == 'AAAAAAAAAAA'
    assert cutter.adapter_statistics[adapter].back.lengths == {9: 1}
    # We see 1 error at length 9 even though the number of allowed mismatches at
    # length 9 is 0.
    assert cutter.adapter_statistics[adapter].back.errors[9][1] == 1

    read = Sequence('foo2', 'AAAAAAAAAAATCGAACGA')
    cutter = AdapterCutter([adapter], times=1)
    trimmed_read = cutter(read, [])

    assert trimmed_read.sequence == read.sequence
    assert cutter.adapter_statistics[adapter].back.lengths == {}
Beispiel #4
0
    def __call__(self, read1: DnaSequence, read2: DnaSequence,
                 info1: ModificationInfo,
                 info2: ModificationInfo) -> Tuple[DnaSequence, DnaSequence]:

        id1, comment1 = Renamer.parse_name(read1.name)
        id2, comment2 = Renamer.parse_name(read2.name)
        if not record_names_match(read1.name, read2.name):
            raise ValueError(
                "Input read IDs not identical: '{}' != '{}'".format(id1, id2))
        name1, name2 = self.get_new_headers(
            id1=id1,
            id2=id2,
            comment1=comment1,
            comment2=comment2,
            header1=read1.name,
            header2=read2.name,
            info1=info1,
            info2=info2,
        )
        new_id1 = Renamer.parse_name(name1)[0]
        new_id2 = Renamer.parse_name(name2)[0]
        if not record_names_match(name1, name2):
            raise InvalidTemplate(
                "After renaming R1 and R2, their IDs are no longer identical: "
                "'{}' != '{}'. Original read ID: '{}'. ".format(
                    new_id1, new_id2, id1))
        read1.name = name1
        read2.name = name2
        return read1, read2
Beispiel #5
0
def test_nextseq_trim():
    s = Sequence('n', '', '')
    assert nextseq_trim_index(s, cutoff=22) == 0
    s = Sequence(
        'n',
        'TCTCGTATGCCGTCTTATGCTTGAAAAAAAAAAGGGGGGGGGGGGGGGGGNNNNNNNNNNNGGNGG',
        'AA//EAEE//A6///E//A//EA/EEEEEEAEA//EEEEEEEEEEEEEEE###########EE#EA')
    assert nextseq_trim_index(s, cutoff=22) == 33
Beispiel #6
0
 def test_twoheaders(self):
     with FastqWriter(self.path, two_headers=True) as fq:
         fq.write(Sequence("name", "CCATA", "!#!#!"))
         fq.write(Sequence("name2", "HELLO", "&&&!&"))
     assert fq._file.closed
     with open(self.path) as t:
         assert t.read(
         ) == '@name\nCCATA\n+name\n!#!#!\n@name2\nHELLO\n+name2\n&&&!&\n'
Beispiel #7
0
def test_nend_trimmer():
    trimmer = NEndTrimmer()
    seqs = ['NNNNAAACCTTGGNNN', 'NNNNAAACNNNCTTGGNNN', 'NNNNNN']
    trims = ['AAACCTTGG', 'AAACNNNCTTGG', '']
    for seq, trimmed in zip(seqs, trims):
        _seq = Sequence('read1', seq, qualities='#' * len(seq))
        _trimmed = Sequence('read1', trimmed, qualities='#' * len(trimmed))
        assert trimmer(_seq, ModificationInfo(_seq)) == _trimmed
Beispiel #8
0
 def test_write_to_file_like_object(self):
     bio = BytesIO()
     with FastaWriter(bio) as fw:
         fw.write(Sequence("name", "CCATA"))
         fw.write(Sequence("name2", "HELLO"))
     assert bio.getvalue() == b'>name\nCCATA\n>name2\nHELLO\n'
     assert not bio.closed
     assert not fw._file.closed
Beispiel #9
0
 def test_ids_not_identical(self):
     renamer = PairedEndRenamer("{id} abc {comment} xyz")
     r1 = Sequence("theid_a cmtx", "ACGT")
     r2 = Sequence("theid_b cmty", "ACGT")
     info1 = ModificationInfo(r1)
     info2 = ModificationInfo(r2)
     with pytest.raises(ValueError) as e:
         renamer(r1, r2, info1, info2)
     assert "not identical" in e.value.args[0]
Beispiel #10
0
    def test_rc_template_varialbe(self):
        renamer = Renamer("{id} rc={rc} {comment}")
        read = Sequence("theid thecomment", "ACGT")
        info = ModificationInfo(read)
        assert renamer(read, info).name == "theid rc= thecomment"

        read = Sequence("theid thecomment", "ACGT")
        info.is_rc = True
        assert renamer(read, info).name == "theid rc=rc thecomment"
Beispiel #11
0
 def test_read_number(self):
     renamer = PairedEndRenamer("{id} read no. is: {rn}")
     r1 = Sequence("theid cmtx", "ACGT")
     r2 = Sequence("theid cmty", "ACGT")
     info1 = ModificationInfo(r1)
     info2 = ModificationInfo(r2)
     renamed1, renamed2 = renamer(r1, r2, info1, info2)
     assert renamed1.name == "theid read no. is: 1"
     assert renamed2.name == "theid read no. is: 2"
Beispiel #12
0
def test_ncontentfilter_paired(seq1, seq2, count, expected):
    filter_ = NContentFilter(count=count)
    filter_legacy = PairedRedirector(None, filter_, filter_, pair_filter_mode='first')
    filter_any = PairedRedirector(None, filter_, filter_, pair_filter_mode='any')
    read1 = Sequence('read1', seq1, qualities='#'*len(seq1))
    read2 = Sequence('read1', seq2, qualities='#'*len(seq2))
    assert filter_legacy(read1, read2, [], []) == filter_(read1, [])
    # discard entire pair if one of the reads fulfills criteria
    assert filter_any(read1, read2, [], []) == expected
Beispiel #13
0
 def test_r2_comment(self):
     renamer = PairedEndRenamer("{id} abc {r2.comment} xyz")
     r1 = Sequence("theid cmtx", "ACGT")
     r2 = Sequence("theid cmty", "ACGT")
     info1 = ModificationInfo(r1)
     info2 = ModificationInfo(r2)
     renamed1, renamed2 = renamer(r1, r2, info1, info2)
     assert renamed1.name == "theid abc cmty xyz"
     assert renamed2.name == "theid abc cmty xyz"
Beispiel #14
0
def test_quality_trimmer():
    read = Sequence('read1', 'ACGTTTACGTA', '##456789###')

    qt = QualityTrimmer(10, 10, 33)
    assert qt(read, []) == Sequence('read1', 'GTTTAC', '456789')

    qt = QualityTrimmer(0, 10, 33)
    assert qt(read, []) == Sequence('read1', 'ACGTTTAC', '##456789')

    qt = QualityTrimmer(10, 0, 33)
    assert qt(read, []) == Sequence('read1', 'GTTTACGTA', '456789###')
Beispiel #15
0
def test_paired_adapter_cutter_actions(action, expected_trimmed1,
                                       expected_trimmed2):
    a1 = BackAdapter("GGTTAA")
    a2 = BackAdapter("AACCGG")
    s1 = Sequence("name", "CCCCGGTTAACCCC")
    s2 = Sequence("name", "TTTTAACCGGTTTT")
    pac = PairedAdapterCutter([a1], [a2], action=action)
    info1 = ModificationInfo(s1)
    info2 = ModificationInfo(s2)
    trimmed1, trimmed2 = pac(s1, s2, info1, info2)
    assert expected_trimmed1 == trimmed1.sequence
    assert expected_trimmed2 == trimmed2.sequence
Beispiel #16
0
def test_paired_adapter_cutter_actions(action, expected_trimmed1,
                                       expected_trimmed2):
    from cutadapt.adapters import SingleAdapter, Where
    a1 = SingleAdapter("GGTTAA", where=Where.BACK)
    a2 = SingleAdapter("AACCGG", where=Where.BACK)
    s1 = Sequence("name", "CCCCGGTTAACCCC")
    s2 = Sequence("name", "TTTTAACCGGTTTT")
    pac = PairedAdapterCutter([a1], [a2], action=action)
    info1 = ModificationInfo()
    info2 = ModificationInfo()
    trimmed1, trimmed2 = pac(s1, s2, info1, info2)
    assert expected_trimmed1 == trimmed1.sequence
    assert expected_trimmed2 == trimmed2.sequence
Beispiel #17
0
 def test(self):
     reads = [
         (Sequence('A/1 comment', 'TTA',
                   '##H'), Sequence('A/2 comment', 'GCT', 'HH#')),
         (Sequence('B/1', 'CC', 'HH'), Sequence('B/2', 'TG', '#H')),
     ]
     bio = BytesIO()
     with InterleavedSequenceWriter(bio) as writer:
         for read1, read2 in reads:
             writer.write(read1, read2)
     assert bio.getvalue() == (b'@A/1 comment\nTTA\n+\n##H\n'
                               b'@A/2 comment\nGCT\n+\nHH#\n'
                               b'@B/1\nCC\n+\nHH\n'
                               b'@B/2\nTG\n+\n#H\n')
Beispiel #18
0
def test_shortener():
    read = Sequence('read1', 'ACGTTTACGTA', '##456789###')

    shortener = Shortener(0)
    assert shortener(read, []) == Sequence('read1', '', '')

    shortener = Shortener(1)
    assert shortener(read, []) == Sequence('read1', 'A', '#')

    shortener = Shortener(5)
    assert shortener(read, []) == Sequence('read1', 'ACGTT', '##456')

    shortener = Shortener(100)
    assert shortener(read, []) == read
Beispiel #19
0
def test_action_retain():
    back = BackAdapter("AACCGG")
    ac = AdapterCutter([back], action="retain")
    seq = Sequence("r1", "ATTGCCAACCGGTATATAT")
    info = ModificationInfo(seq)
    trimmed = ac(seq, info)
    assert "ATTGCCAACCGG" == trimmed.sequence
Beispiel #20
0
def test_adapter_cutter():
    from cutadapt.adapters import SingleAdapter, Where
    a1 = SingleAdapter('GTAGTCCCGC', where=Where.BACK)
    a2 = SingleAdapter('GTAGTCCCCC', where=Where.BACK)
    match = AdapterCutter.best_match([a1, a2],
                                     Sequence("name", "ATACCCCTGTAGTCCCC"))
    assert match.adapter is a2
Beispiel #21
0
def test_issue_80():
    # This issue turned out to not be an actual issue with the alignment
    # algorithm. The following alignment is found because it has more matches
    # than the 'obvious' one:
    #
    # TCGTATGCCGTCTTC
    # =========X==XX=
    # TCGTATGCCCTC--C
    #
    # This is correct, albeit a little surprising, since an alignment without
    # indels would have only two errors.

    adapter = SingleAdapter(
        sequence="TCGTATGCCGTCTTC",
        where=Where.BACK,
        remove=WhereToRemove.SUFFIX,
        max_error_rate=0.2,
        min_overlap=3,
        read_wildcards=False,
        adapter_wildcards=False)
    read = Sequence(name="seq2", sequence="TCGTATGCCCTCC")
    result = adapter.match_to(read)
    assert result.errors == 3, result
    assert result.astart == 0, result
    assert result.astop == 15, result
Beispiel #22
0
def test_info_record():
    adapter = Adapter(sequence='GAACTCCAGTCACNNNNN',
                      where=Where.BACK,
                      max_error_rate=0.12,
                      min_overlap=5,
                      read_wildcards=False,
                      adapter_wildcards=True,
                      name="Foo")
    read = Sequence(name="abc", sequence='CCCCAGAACTACAGTCCCGGC')
    am = Match(astart=0,
               astop=17,
               rstart=5,
               rstop=21,
               matches=15,
               errors=2,
               remove_before=False,
               adapter=adapter,
               read=read)
    assert am.get_info_record() == (
        "abc",
        2,
        5,
        21,
        'CCCCA',
        'GAACTACAGTCCCGGC',
        '',
        'Foo',
        '',
        '',
        '',
    )
Beispiel #23
0
def test_issue_265():
    """Crash when accessing the matches property of non-anchored linked adapters"""
    s = Sequence('name', 'AAAATTTT')
    front_adapter = SingleAdapter('GGG', where=Where.FRONT)
    back_adapter = SingleAdapter('TTT', where=Where.BACK)
    la = LinkedAdapter(front_adapter, back_adapter, front_required=False, back_required=False, name='name')
    assert la.match_to(s).matches == 3
def test_info_record():
    adapter = BackAdapter(sequence='GAACTCCAGTCACNNNNN',
                          max_errors=0.12,
                          min_overlap=5,
                          read_wildcards=False,
                          adapter_wildcards=True,
                          name="Foo")
    read = Sequence(name="abc", sequence='CCCCAGAACTACAGTCCCGGC')
    am = RemoveAfterMatch(astart=0,
                          astop=17,
                          rstart=5,
                          rstop=21,
                          matches=15,
                          errors=2,
                          adapter=adapter,
                          sequence=read.sequence)
    assert am.get_info_records(read) == [[
        "",
        2,
        5,
        21,
        'CCCCA',
        'GAACTACAGTCCCGGC',
        '',
        'Foo',
        '',
        '',
        '',
    ]]
Beispiel #25
0
def test_adapter_cutter():
    from cutadapt.adapters import BackAdapter
    a1 = BackAdapter("GTAGTCCCGC")
    a2 = BackAdapter("GTAGTCCCCC")
    match = AdapterCutter.best_match([a1, a2],
                                     Sequence("name", "ATACCCCTGTAGTCCCC"))
    assert match.adapter is a2
Beispiel #26
0
def test_unconditional_cutter():
    UnconditionalCutter(length=5)
    read = Sequence('r1', 'abcdefg')
    info = ModificationInfo(read)
    assert UnconditionalCutter(length=2)(read, info).sequence == 'cdefg'
    assert UnconditionalCutter(length=-2)(read, info).sequence == 'abcde'
    assert UnconditionalCutter(length=100)(read, info).sequence == ''
    assert UnconditionalCutter(length=-100)(read, info).sequence == ''
Beispiel #27
0
    def test(self):
        expected = [
            (Sequence('read1/1 some text', 'TTATTTGTCTCCAGC',
                      '##HHHHHHHHHHHHH'),
             Sequence('read1/2 other text', 'GCTGGAGACAAATAA',
                      'HHHHHHHHHHHHHHH')),
            (Sequence('read3/1', 'CCAACTTGATATTAATAACA',
                      'HHHHHHHHHHHHHHHHHHHH'),
             Sequence('read3/2', 'TGTTATTAATATCAAGTTGG',
                      '#HHHHHHHHHHHHHHHHHHH')),
        ]
        with InterleavedSequenceReader("tests/data/interleaved.fastq") as isr:
            reads = list(isr)

        assert reads == expected
        with dnaio.open("tests/data/interleaved.fastq", interleaved=True) as f:
            reads = list(f)
        assert reads == expected
Beispiel #28
0
def test_reverse_complementer():
    adapters = [
        PrefixAdapter("TTATTTGTCT"),
        PrefixAdapter("TCCGCACTGG"),
    ]
    adapter_cutter = AdapterCutter(adapters, index=False)
    reverse_complementer = ReverseComplementer(adapter_cutter)

    read = Sequence("r", "ttatttgtctCCAGCTTAGACATATCGCCT")
    info = ModificationInfo(read)
    trimmed = reverse_complementer(read, info)
    assert trimmed.sequence == "CCAGCTTAGACATATCGCCT"
    assert not info.is_rc

    read = Sequence("r", "CAACAGGCCACATTAGACATATCGGATGGTagacaaataa")
    info = ModificationInfo(read)
    trimmed = reverse_complementer(read, info)
    assert trimmed.sequence == "ACCATCCGATATGTCTAATGTGGCCTGTTG"
    assert info.is_rc
Beispiel #29
0
def test_statistics():
    read = Sequence('name', 'AAAACCCCAAAA')
    adapters = [Adapter('CCCC', BACK, max_error_rate=0.1)]
    cutter = AdapterCutter(adapters, times=3)
    trimmed_read = cutter(read, [])
    # TODO make this a lot simpler
    trimmed_bp = 0
    for adapter in adapters:
        for d in (cutter.adapter_statistics[adapter].front.lengths,
                  cutter.adapter_statistics[adapter].back.lengths):
            trimmed_bp += sum(seqlen * count for (seqlen, count) in d.items())
    assert trimmed_bp <= len(read), trimmed_bp
Beispiel #30
0
 def __call__(self, read: DnaSequence, info: ModificationInfo) -> DnaSequence:
     id_, comment = self.parse_name(read.name)
     read.name = self._template.format(
         header=read.name,
         id=id_,
         comment=comment,
         cut_prefix=info.cut_prefix if info.cut_prefix else "",
         cut_suffix=info.cut_suffix if info.cut_suffix else "",
         adapter_name=info.matches[-1].adapter.name if info.matches else "no_adapter",
         rc="rc" if info.is_rc else "",
     )
     return read