def test_from_components_no_copy(self): a = Component('ABCDE', id='a') f = Component('FGH') i = Component('IJKLMNOPQ', id='i') combined = Component.combine(a, f, i) self.assertEqual('ABCDEFGHIJKLMNOPQ', str(combined.seq)) qualifiers = {'mol_type': 'other DNA', 'organism': None} self.assertEqual([ Feature(a, FeatureLocation(0, 5), type='source', qualifiers=qualifiers, ref='a'), Feature( f, FeatureLocation(5, 8), type='source', qualifiers=qualifiers), Feature(i, FeatureLocation(8, 17), type='source', qualifiers=qualifiers, ref='i') ], list(combined.features))
def test_list_features(self): c1 = Component('A' * 10) c1.features.add(FeatureLocation(1, 10), type='repeat') c2 = Component('T' * 10) c2.features.add(FeatureLocation(1, 10), type='repeat') self.assertEqual([Feature(c1, FeatureLocation(1, 10), type='repeat')], list(c1.features)) self.assertEqual([Feature(c2, FeatureLocation(1, 10), type="repeat")], list(c2.features)) strain = HaploidOrganism(id='strain') strain.set('a', c1) strain.set('b', c2) strain.set('c', c2) self.assertEqual(2, len(strain.features)) self.assertEqual( { Feature(Component('AAAAAAAAAA'), FeatureLocation(1, 10), type="repeat"), Feature(Component('TTTTTTTTTT'), FeatureLocation(1, 10), type="repeat") }, set(strain.features))
def test_mutate_insert(self): self.assertEqual('99012345', str(Component('012345').mutate([INS(0, '99')]).seq)) self.assertEqual('09912345', str(Component('012345').mutate([INS(1, '99')]).seq)) self.assertEqual( '9912345', str(Component('012345').mutate([INS(0, '99', replace=True)]).seq))
def test_mutate_replace(self): self.assertEqual( '01ttf2345', str(Component('012345').mutate([Mutation(1, 1, '1ttf')]).seq)) self.assertEqual( '0ott45', str(Component('012345').mutate([Mutation(1, 3, 'ott')]).seq)) self.assertEqual('z12345', str(Component('012345').mutate([SNP(0, 'z')]).seq))
def test_mutate_delete(self): self.assertEqual('01234', str(Component('012345').mutate([DEL(5)]).seq)) self.assertEqual('01235', str(Component('012345').mutate([DEL(4)]).seq)) self.assertEqual('0123', str(Component('012345').mutate([DEL(4, 2)]).seq)) self.assertEqual('2345', str(Component('012345').mutate([DEL(0, 2)]).seq))
def test_inherit_feature_delete(self): orig = Component('TTACCCATT', features=[SeqFeature(FeatureLocation(0, 1), type='tt')]) f = orig.features.add(FeatureLocation(3, 6), type='ccc') self.assertEqual('CCC', str(f.seq)) mutated = orig.mutate([DEL(3, 3)]) self.assertEqual('TTAATT', str(mutated.seq)) self.assertEqual([Feature(mutated, FeatureLocation(0, 1), type='tt')], list(mutated.features))
def test_export_combined(self): c1 = Component(Seq('AGAGAGAGAGA', alphabet=DNAAlphabet()), annotations={'organism': 'Predator'}) c2 = Component(Seq('CGCGCGCCGCGCGCGCG', alphabet=DNAAlphabet()), annotations={'organism': 'Alien'}) c3 = Component(Seq('AAAAAAAAAAATTTTAA', alphabet=DNAAlphabet())) c123 = Component.combine(c1, c2, c3) record = GenbankConverter.to_seq_record(c123) self.assertEqual( open('fixtures/c123.gb').read(), record.format('genbank'))
def test_inherit_features(self): component = Component('ABCDEFGHIerrorJKLMNOPQRSTUVXYZ') component.features.add(FeatureLocation(0, 3), id='abc') # fine component.features.add(FeatureLocation(9, 14), id='error') # fine component.features.add(FeatureLocation(6, 12), id='GHI..err') component.features.add(FeatureLocation(11, 17), id='ror..JKL') component.features.add(FeatureLocation(8, 15), id='I..error..J') # fine component.features.add(FeatureLocation(29, 30), id='end') # fine mutated = component.mutate([DEL(9, 5)]) self.assertEqual({'JKL', 'Z', 'ABC', 'GHI', 'IJ'}, set(str(f.seq) for f in mutated.features))
def test_lineage_simple(self): generation1 = Component('Ax') generation2 = generation1.mutate([INS(1, 'B')]) generation3 = generation2.mutate([INS(2, 'C')]) other = Component('a') self.assertEqual('ABx', str(generation2.seq)) self.assertEqual(False, generation1.inherits_from(generation3)) self.assertEqual(True, generation3.inherits_from(generation1)) self.assertEqual(False, generation3.inherits_from(other)) self.assertEqual([generation2, generation1], list(generation3.get_lineage()))
def test_inherit_feature_delete(self): orig = Component( 'TTACCCATT', features=[SeqFeature(FeatureLocation(0, 1), type='tt')]) f = orig.features.add(FeatureLocation(3, 6), type='ccc') self.assertEqual('CCC', str(f.seq)) mutated = orig.mutate([DEL(3, 3)]) self.assertEqual('TTAATT', str(mutated.seq)) self.assertEqual([Feature(mutated, FeatureLocation(0, 1), type='tt')], list(mutated.features))
def test_inherited_search(self): letters = Component('AABBDDEE', features=[ SeqFeature(FeatureLocation(0, 1), type='vowel'), SeqFeature(FeatureLocation(2, 5), type='consonant'), SeqFeature(FeatureLocation(5, 6), type='vowel')]) letters = letters.mutate([INS(4, 'CC')]) self.assertEqual('AABBCCDDEE', str(letters.seq)) self.assertEqual([Feature(letters, FeatureLocation(0, 1), type='vowel'), Feature(letters, FeatureLocation(7, 8), type='vowel')], list(letters.features.find(type='vowel'))) self.assertEqual([], list(letters.features.find(type='consonant', between_end=1)))
def test_mutate_1(self): component = Component('ABCDEFGHIJKLMNOPQRSTUVWXYZ') # . . . . . . mutated = component.mutate( # 01234567 8901234567890 12345 [SNP(3, 'd'), # ABCdEFGH IJKLMNOPQRSTU VWXYZ DEL(1), # A-CdEFGH IJKLMNOPQRSTU VWXYZ INS(21, 'xx'), # A-CdEFGH IJKLMNOPQRSTUxxVWXYZ Mutation(10, 9, 'oops'), # A-CdEFGH IJoops-----TUxxVWXYZ SUB(4, 'ef'), # A-CdefGH IJoops-----TUxxVWXYZ Mutation(7, 1, 'Hh')], # A-CdefGHhIJoops-----TUxxVWXYZ strict=False) # 0 1234567890123 457890123 # . . . . . self.assertEqual('ACdefGHhIJoopsTUxxVWXYZ', str(mutated.seq))
def test_quickstart_feature_inherit(self): slogan = Component('CoPy is for DNA components', features=[ SeqFeature(FeatureLocation(0, 4), type='name'), SeqFeature(FeatureLocation(12, 15), id='DNA')]) self.assertEqual('components', str(slogan.features.add(FeatureLocation(16, 26)).seq)) self.assertEqual(['CoPy', 'DNA', 'components'], [str(f.seq) for f in slogan.features]) new_slogan = slogan.mutate([DEL(2, 2), DEL(12, 4)]) self.assertEqual('Co is for components', str(new_slogan.seq)) self.assertEqual([Feature(new_slogan, FeatureLocation(0, 2), type='name'), Feature(new_slogan, FeatureLocation(10, 20))], list(new_slogan.features)) self.assertEqual(['Co', 'components'], [str(f.seq) for f in new_slogan.features])
def test_mutate_1(self): component = Component('ABCDEFGHIJKLMNOPQRSTUVWXYZ') # . . . . . . mutated = component.mutate( # 01234567 8901234567890 12345 [ SNP(3, 'd'), # ABCdEFGH IJKLMNOPQRSTU VWXYZ DEL(1), # A-CdEFGH IJKLMNOPQRSTU VWXYZ INS(21, 'xx'), # A-CdEFGH IJKLMNOPQRSTUxxVWXYZ Mutation(10, 9, 'oops'), # A-CdEFGH IJoops-----TUxxVWXYZ SUB(4, 'ef'), # A-CdefGH IJoops-----TUxxVWXYZ Mutation(7, 1, 'Hh') ], # A-CdefGHhIJoops-----TUxxVWXYZ strict=False) # 0 1234567890123 457890123 # . . . . . self.assertEqual('ACdefGHhIJoopsTUxxVWXYZ', str(mutated.seq))
def test_export_combined(self): c1 = Component(Seq('AGAGAGAGAGA', alphabet=DNAAlphabet()), annotations={'organism': 'Predator'}) c2 = Component(Seq('CGCGCGCCGCGCGCGCG', alphabet=DNAAlphabet()), annotations={'organism': 'Alien'}) c3 = Component(Seq('AAAAAAAAAAATTTTAA', alphabet=DNAAlphabet())) c123 = Component.combine(c1, c2, c3) record = GenbankConverter.to_seq_record(c123) self.assertEqual(open('fixtures/c123.gb').read(), record.format('genbank'))
def test_from_components_copy(self): co_1 = Component(Seq('AAATTTAAA')) co_1.features.add(FeatureLocation(3, 6), type='repeat', qualifiers={'name': 'ts'}) co_2 = Component(Seq('G' * 10)) co_2.features.add(FeatureLocation(0, 10), type='repeat', qualifiers={'name': 'gs'}) combined = Component.combine(co_1, co_2, copy_features=True) self.assertEqual('AAATTTAAAGGGGGGGGGG', str(combined.seq)) self.assertEqual([Feature(combined, FeatureLocation(3, 6), type='repeat', qualifiers={'name': 'ts'}), Feature(combined, FeatureLocation(9, 19), type='repeat', qualifiers={'name': 'gs'})], list(combined.features))
def test_feature_non_strict_order(self): """ In non-strict mode, potentially ambiguous mutations are allowed where the order in which the order in which the mutations are applied is significant. """ component = Component('12345', feature_class=Feature) component.features.add(FeatureLocation(2, 4), type='34') # |████| |████| # 12|3 4|5 12|3 4|5 # 12|3xy4|5 12|3 -|5 # 12|3xy|-5 12|3 xy|5 mutated_1 = component.mutate([DEL(3), INS(3, 'xy')], strict=False) self.assertEqual('3xy', str(list(mutated_1.features)[0].seq)) # 3 would also be acceptable. self.assertEqual('123xy5', str(mutated_1.seq)) mutated_2 = component.mutate([INS(3, 'xy'), DEL(3)], strict=False) self.assertEqual('3xy', str(list(mutated_2.features)[0].seq)) self.assertEqual('123xy5', str(mutated_2.seq))
def test_feature_non_strict_order(self): """ In non-strict mode, potentially ambiguous mutations are allowed where the order in which the order in which the mutations are applied is significant. """ component = Component('12345', feature_class=Feature) component.features.add(FeatureLocation(2, 4), type='34') # |████| |████| # 12|3 4|5 12|3 4|5 # 12|3xy4|5 12|3 -|5 # 12|3xy|-5 12|3 xy|5 mutated_1 = component.mutate([DEL(3), INS(3, 'xy')], strict=False) self.assertEqual('3xy', str(list( mutated_1.features)[0].seq)) # 3 would also be acceptable. self.assertEqual('123xy5', str(mutated_1.seq)) mutated_2 = component.mutate([INS(3, 'xy'), DEL(3)], strict=False) self.assertEqual('3xy', str(list(mutated_2.features)[0].seq)) self.assertEqual('123xy5', str(mutated_2.seq))
def test_mutate_strain(self): strain = HaploidOrganism(id='strain-1') genome = Component('A' * 25 + 'C' * 25 + 'G' * 25 + 'T' * 25) genome.features.add(FeatureLocation(0, 25), type='a') genome.features.add(FeatureLocation(25, 49), type='c') feature_3 = genome.features.add(FeatureLocation(50, 74), type='g') feature_4 = genome.features.add(FeatureLocation( 75, 99), type='t') # FIXME 75 should be possible, no? strain.set('genome', genome) mutations = [ SNP(7, 'T'), SNP(30, 'G'), Mutation(31, 3, ''), Mutation(40, new_sequence='GATGA'), Mutation(feature_3.start, end=feature_3.end - 5), Mutation(feature_4.start, end=feature_4.end, new_sequence=Seq('GAGAGA')) ] new_genome = strain.components['genome'].mutate(mutations) new_strain = HaploidOrganism('strain-2', parent=strain) new_strain.set('genome', new_genome) # sets genome. self.assertEqual(False, feature_3 in new_strain.features) self.assertEqual(False, feature_4 in new_strain.features) self.assertEqual(1, len(new_strain.diff(strain))) # 'genome' changed self.assertEqual( 'AAAAAAATAAAAAAAAAAAAAAAAACCCCCGCCCCCCGATGACCCCCCCCCCGGGGGGAGAGA', str(new_genome.seq)) genome_fdiff = new_strain.components['genome'].fdiff( strain.components['genome']) self.assertEqual(set(genome.features), set( genome_fdiff.removed)) # all features removed/changed self.assertEqual(Diff(changed=['genome']), new_strain.diff(strain)) self.assertEqual( { Feature(new_genome, FeatureLocation(0, 25), type="a"), Feature(new_genome, FeatureLocation(52, 56), type="g"), Feature(new_genome, FeatureLocation(25, 50), type="c") }, set(genome_fdiff.added)) self.assertEqual( {('a', 'AAAAAAATAAAAAAAAAAAAAAAAA'), ('c', 'CCCCCGCCCCCCGATGACCCCCCCC'), ('g', 'GGGG')}, set((f.type, str(f.seq)) for f in genome_fdiff.added))
def test_add_features(self): component = Component('GAGAGAGATATAGAGAGA') component.features.add(FeatureLocation(8, 12), qualifiers={'name': 'tata'}) component.features.add(FeatureLocation(17, 18), qualifiers={'name': 'end'}) component.features.add(FeatureLocation(0, 1), qualifiers={'name': 'start'}) self.assertEqual( ['start', 'tata', 'end'], [f.qualifiers.get('name') for f in component.features])
def test_inherited_search(self): letters = Component('AABBDDEE', features=[ SeqFeature(FeatureLocation(0, 1), type='vowel'), SeqFeature(FeatureLocation(2, 5), type='consonant'), SeqFeature(FeatureLocation(5, 6), type='vowel') ]) letters = letters.mutate([INS(4, 'CC')]) self.assertEqual('AABBCCDDEE', str(letters.seq)) self.assertEqual([ Feature(letters, FeatureLocation(0, 1), type='vowel'), Feature(letters, FeatureLocation(7, 8), type='vowel') ], list(letters.features.find(type='vowel'))) self.assertEqual([], list( letters.features.find(type='consonant', between_end=1)))
def test_quickstart_feature_inherit(self): slogan = Component('CoPy is for DNA components', features=[ SeqFeature(FeatureLocation(0, 4), type='name'), SeqFeature(FeatureLocation(12, 15), id='DNA') ]) self.assertEqual('components', str(slogan.features.add(FeatureLocation(16, 26)).seq)) self.assertEqual(['CoPy', 'DNA', 'components'], [str(f.seq) for f in slogan.features]) new_slogan = slogan.mutate([DEL(2, 2), DEL(12, 4)]) self.assertEqual('Co is for components', str(new_slogan.seq)) self.assertEqual([ Feature(new_slogan, FeatureLocation(0, 2), type='name'), Feature(new_slogan, FeatureLocation(10, 20)) ], list(new_slogan.features)) self.assertEqual(['Co', 'components'], [str(f.seq) for f in new_slogan.features])
def test_from_components_no_copy(self): a = Component('ABCDE', id='a') f = Component('FGH') i = Component('IJKLMNOPQ', id='i') combined = Component.combine(a, f, i) self.assertEqual('ABCDEFGHIJKLMNOPQ', str(combined.seq)) qualifiers = {'mol_type': 'other DNA', 'organism': None} self.assertEqual([Feature(a, FeatureLocation(0, 5), type='source', qualifiers=qualifiers, ref='a'), Feature(f, FeatureLocation(5, 8), type='source', qualifiers=qualifiers), Feature(i, FeatureLocation(8, 17), type='source', qualifiers=qualifiers, ref='i')], list(combined.features))
def test_from_components_copy(self): co_1 = Component(Seq('AAATTTAAA')) co_1.features.add(FeatureLocation(3, 6), type='repeat', qualifiers={'name': 'ts'}) co_2 = Component(Seq('G' * 10)) co_2.features.add(FeatureLocation(0, 10), type='repeat', qualifiers={'name': 'gs'}) combined = Component.combine(co_1, co_2, copy_features=True) self.assertEqual('AAATTTAAAGGGGGGGGGG', str(combined.seq)) self.assertEqual([ Feature(combined, FeatureLocation(3, 6), type='repeat', qualifiers={'name': 'ts'}), Feature(combined, FeatureLocation(9, 19), type='repeat', qualifiers={'name': 'gs'}) ], list(combined.features))
def test_export(self): component = Component(Seq('TATAGAGACACA', alphabet=DNAAlphabet()), id='Magic_Brick', annotations={'accession': 'MB1'}) component.features.add(FeatureLocation(3, 7), type='-10_signal') component.features.add(FeatureLocation(7, 9), id='GA', type='CDS', qualifiers={'locus_id': 'b0001'}) # GenbankConverter.to_file(component, 'fixtures/MB_1.gb', 'Magic_Brick') record = GenbankConverter.to_seq_record(component) self.assertEqual( open('tests/fixtures/MB_1.gb').read(), record.format('genbank'))