Skip to content

Commit 644cbdb

Browse files
committed
Add text parameter to init methods of vcf classes.
Also separate str() and repr() for those classes.
1 parent 516d100 commit 644cbdb

File tree

4 files changed

+455
-100
lines changed

4 files changed

+455
-100
lines changed

pyvdrm/asi2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def __init__(self, pos, label, args):
215215
"""
216216
if pos and label:
217217
pass
218-
self.mutations = MutationSet.from_string(''.join(args))
218+
self.mutations = MutationSet(''.join(args))
219219

220220
def __repr__(self):
221221
return str(self.mutations)

pyvdrm/tests/test_asi2.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def mus(mutations):
88
if mutations == '':
99
return set([])
1010
return reduce(lambda x, y: x.union(y),
11-
map(lambda x: set(MutationSet.from_string(x)), mutations.split()))
11+
map(lambda x: set(MutationSet(x)), mutations.split()))
1212

1313

1414
# noinspection SqlNoDataSourceInspection,SqlDialectInspection
@@ -19,9 +19,9 @@ def test_stanford_ex1(self):
1919

2020
def test_stanford_ex2(self):
2121
rule = ASI2("SELECT ATLEAST 2 FROM (41L, 67N, 70R, 210W, 215F, 219Q)")
22-
m1 = Mutation(41, 'L')
23-
m2 = Mutation(67, 'N')
24-
m3 = Mutation(70, 'N')
22+
m1 = Mutation('41L')
23+
m2 = Mutation('67N')
24+
m3 = Mutation('70N')
2525
self.assertTrue(rule([m1, m2]))
2626
self.assertFalse(rule([m1, m3]))
2727

pyvdrm/tests/test_vcf.py

Lines changed: 307 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,329 @@
11
import unittest
2-
from pyvdrm.vcf import Mutation, MutationSet, call_mutations
2+
from pyvdrm.vcf import Mutation, MutationSet, VariantCalls
33

44

5-
class TestMutationParser(unittest.TestCase):
5+
class TestMutation(unittest.TestCase):
6+
def test_init_text(self):
7+
expected_wildtype = 'Q'
8+
expected_position = 20
9+
expected_variant = 'A'
10+
m = Mutation('Q20A')
611

7-
def test_noWt(self):
8-
for residue in "20N 10NNN 1ASDF 0X".split():
9-
mutations = MutationSet.from_string(residue)
10-
self.assertIsNone(mutations.wildtype)
12+
self.assertEqual(expected_wildtype, m.wildtype)
13+
self.assertEqual(expected_position, m.pos)
14+
self.assertEqual(expected_variant, m.variant)
15+
16+
def test_init_details(self):
17+
expected_wildtype = 'Q'
18+
expected_position = 20
19+
expected_variant = 'A'
20+
m = Mutation(wildtype=expected_wildtype,
21+
pos=expected_position,
22+
variant=expected_variant)
23+
24+
self.assertEqual(expected_wildtype, m.wildtype)
25+
self.assertEqual(expected_position, m.pos)
26+
self.assertEqual(expected_variant, m.variant)
27+
28+
def test_init_bad_text(self):
29+
expected_message = \
30+
r'Mutation text expects wild type \(optional\), position, and one variant\.'
31+
with self.assertRaisesRegex(ValueError, expected_message):
32+
Mutation('!20A')
33+
34+
def test_init_multiple_variants(self):
35+
expected_message = \
36+
r'Mutation text only allows one variant\.'
37+
with self.assertRaisesRegex(ValueError, expected_message):
38+
Mutation('Q20AE')
39+
40+
def test_repr(self):
41+
m = Mutation('Q20A')
42+
r = repr(m)
43+
self.assertEqual("Mutation('Q20A')", r)
44+
45+
def test_str(self):
46+
m = Mutation('Q20A')
47+
s = str(m)
48+
self.assertEqual("Q20A", s)
49+
50+
def test_no_wildtype(self):
51+
m = Mutation('20A')
52+
r = repr(m)
53+
self.assertEqual("Mutation('20A')", r)
54+
self.assertIsNone(m.wildtype)
1155

1256
def test_eq(self):
13-
r1 = Mutation.from_string("20A")
14-
r2 = Mutation.from_string("20A")
57+
r1 = Mutation("20A")
58+
r2 = Mutation("20A")
1559
self.assertEqual(r2, r1)
1660

1761
def test_ineq_pos(self):
18-
r1 = Mutation.from_string("20A")
19-
r2 = Mutation.from_string("21A")
62+
r1 = Mutation("20A")
63+
r2 = Mutation("21A")
2064
self.assertNotEqual(r2, r1)
2165

2266
def test_ineq_aa(self):
23-
r1 = Mutation.from_string("20A")
24-
r2 = Mutation.from_string("20C")
67+
r1 = Mutation("20A")
68+
r2 = Mutation("20C")
2569
self.assertNotEqual(r2, r1)
2670

71+
def test_equal_with_wildtype_mismatch(self):
72+
set1 = Mutation('Q1A')
73+
set2 = Mutation('R1A')
74+
75+
expected_message = 'Wild type mismatch between Q1A and R1A'
76+
with self.assertRaisesRegex(ValueError, expected_message):
77+
if set1 == set2:
78+
pass
79+
80+
81+
class TestMutationSet(unittest.TestCase):
82+
def test_init_text(self):
83+
expected_wildtype = 'Q'
84+
expected_position = 1
85+
expected_mutations = {Mutation('Q1A'), Mutation('Q1C')}
86+
87+
ms = MutationSet('Q1AC')
88+
89+
self.assertEqual(expected_wildtype, ms.wildtype)
90+
self.assertEqual(expected_position, ms.pos)
91+
self.assertEqual(expected_mutations, ms.mutations)
92+
93+
def test_init_variants(self):
94+
expected_wildtype = 'Q'
95+
expected_position = 1
96+
expected_mutations = {Mutation('Q1A'), Mutation('Q1C')}
97+
98+
ms = MutationSet(wildtype=expected_wildtype,
99+
pos=expected_position,
100+
variants='AC')
101+
102+
self.assertEqual(expected_wildtype, ms.wildtype)
103+
self.assertEqual(expected_position, ms.pos)
104+
self.assertEqual(expected_mutations, ms.mutations)
105+
106+
def test_init_mutations(self):
107+
expected_wildtype = 'Q'
108+
expected_position = 1
109+
expected_mutations = {Mutation('Q1A'), Mutation('Q1C')}
110+
111+
ms = MutationSet(mutations=expected_mutations)
112+
113+
self.assertEqual(expected_wildtype, ms.wildtype)
114+
self.assertEqual(expected_position, ms.pos)
115+
self.assertEqual(expected_mutations, ms.mutations)
116+
117+
def test_init_mutations_some_without_wildtype(self):
118+
expected_wildtype = 'Q'
119+
expected_position = 1
120+
expected_mutations = {Mutation('Q1A'), Mutation('1C')}
121+
122+
ms = MutationSet(mutations=expected_mutations)
123+
124+
self.assertEqual(expected_wildtype, ms.wildtype)
125+
self.assertEqual(expected_position, ms.pos)
126+
self.assertEqual(expected_mutations, ms.mutations)
127+
128+
def test_init_no_mutations(self):
129+
expected_wildtype = 'Q'
130+
expected_position = 1
131+
expected_mutations = set()
132+
133+
ms = MutationSet(wildtype=expected_wildtype,
134+
pos=expected_position,
135+
mutations=expected_mutations)
136+
137+
self.assertEqual(expected_wildtype, ms.wildtype)
138+
self.assertEqual(expected_position, ms.pos)
139+
self.assertEqual(expected_mutations, ms.mutations)
140+
141+
def test_no_wildtypes(self):
142+
expected_position = 10
143+
expected_mutations = {Mutation('10C')}
144+
145+
ms = MutationSet(pos=expected_position,
146+
mutations=expected_mutations)
147+
148+
self.assertIsNone(ms.wildtype)
149+
self.assertEqual(expected_position, ms.pos)
150+
self.assertEqual(expected_mutations, ms.mutations)
151+
152+
def test_init_no_mutations_without_wildtype(self):
153+
position = 1
154+
mutations = set()
155+
156+
with self.assertRaisesRegex(ValueError,
157+
r'No wildtype and no variants\.'):
158+
MutationSet(pos=position, mutations=mutations)
159+
160+
def test_init_no_mutations_without_position(self):
161+
wildtype = 'Q'
162+
mutations = set()
163+
164+
with self.assertRaisesRegex(ValueError,
165+
r'No position and no variants\.'):
166+
MutationSet(wildtype=wildtype, mutations=mutations)
167+
168+
def test_init_position_mismatch(self):
169+
wildtype = 'Q'
170+
position = 2
171+
mutations = {Mutation('Q1A'), Mutation('Q1C')}
172+
173+
with self.assertRaisesRegex(ValueError,
174+
r'Multiple positions found: 1, 2\.'):
175+
MutationSet(wildtype=wildtype, pos=position, mutations=mutations)
176+
177+
def test_init_multiple_positions(self):
178+
mutations = {Mutation('Q3A'), Mutation('Q2C')}
179+
180+
with self.assertRaisesRegex(ValueError,
181+
r'Multiple positions found: 2, 3\.'):
182+
MutationSet(mutations=mutations)
183+
184+
def test_init_wildtype_mismatch(self):
185+
wildtype = 'R'
186+
position = 1
187+
mutations = {Mutation('Q1A'), Mutation('Q1C')}
188+
189+
with self.assertRaisesRegex(ValueError,
190+
r'Multiple wildtypes found: Q, R\.'):
191+
MutationSet(wildtype=wildtype, pos=position, mutations=mutations)
27192

28-
class TestCallMutations(unittest.TestCase):
29-
def test(self):
193+
def test_init_multiple_wildtypes(self):
194+
mutations = {Mutation('R1A'), Mutation('Q1C')}
195+
196+
with self.assertRaisesRegex(ValueError,
197+
r'Multiple wildtypes found: Q, R\.'):
198+
MutationSet(mutations=mutations)
199+
200+
def test_repr(self):
201+
expected_repr = "MutationSet('Q1AC')"
202+
ms = MutationSet('Q1AC')
203+
204+
r = repr(ms)
205+
206+
self.assertEqual(expected_repr, r)
207+
208+
def test_str(self):
209+
expected_str = 'Q1AC'
210+
ms = MutationSet(expected_str)
211+
212+
s = str(ms)
213+
214+
self.assertEqual(expected_str, s)
215+
216+
def test_equal(self):
217+
set1 = MutationSet('Q1AC')
218+
set2 = MutationSet('Q1CA')
219+
set3 = MutationSet('Q2AC')
220+
set4 = MutationSet('R2AC')
221+
set5 = MutationSet('Q1A')
222+
223+
self.assertEqual(set1, set2)
224+
self.assertNotEqual(set1, set3)
225+
self.assertNotEqual(set1, set4)
226+
self.assertNotEqual(set1, set5)
227+
228+
def test_equal_with_wildtype_mismatch(self):
229+
set1 = MutationSet('Q1AC')
230+
set2 = MutationSet('R1AC')
231+
232+
expected_message = 'Wild type mismatch between Q1AC and R1AC'
233+
with self.assertRaisesRegex(ValueError, expected_message):
234+
if set1 == set2:
235+
pass
236+
237+
def test_hash(self):
238+
hash1 = hash(MutationSet('Q1AC'))
239+
hash2 = hash(MutationSet('Q1CA'))
240+
hash3 = hash(MutationSet('Q2AC'))
241+
hash4 = hash(MutationSet('Q1A'))
242+
hash5 = hash(MutationSet('R1AC'))
243+
244+
self.assertEqual(hash1, hash2)
245+
self.assertNotEqual(hash1, hash3)
246+
self.assertNotEqual(hash1, hash4)
247+
self.assertEqual(hash1, hash5)
248+
249+
def test_no_wildtype(self):
250+
for text in "20N 10NNN 1ASDF 0X".split():
251+
mutations = MutationSet(text)
252+
self.assertIsNone(mutations.wildtype)
253+
254+
255+
class TestVariantCalls(unittest.TestCase):
256+
def test_init_text(self):
257+
expected_mutation_sets = {MutationSet('A1IL'), MutationSet('H3R')}
258+
259+
calls = VariantCalls('A1IL H3R')
260+
261+
self.assertIsNone(calls.reference)
262+
self.assertEqual(expected_mutation_sets, calls.mutation_sets)
263+
264+
def test_init_single_sequence(self):
30265
reference = 'ACHE'
31266
sample = 'ICRE'
32-
expected_mutations = [Mutation.from_string(residue)
33-
for residue in ('A1I', 'H3R')]
267+
expected_mutation_sets = {MutationSet('A1I'), MutationSet('H3R')}
268+
269+
calls = VariantCalls(reference=reference, sample=sample)
270+
271+
self.assertEqual(reference, calls.reference)
272+
self.assertEqual(expected_mutation_sets, calls.mutation_sets)
273+
274+
def test_init_multiple_sequences(self):
275+
reference = 'ACHE'
276+
sample = ['IN', 'C', 'HR', 'E']
277+
expected_mutation_sets = {MutationSet('A1IN'), MutationSet('H3HR')}
278+
279+
calls = VariantCalls(reference=reference, sample=sample)
280+
281+
self.assertEqual(reference, calls.reference)
282+
self.assertEqual(expected_mutation_sets, calls.mutation_sets)
283+
284+
def test_init_bad_length(self):
285+
reference = 'ACHE'
286+
sample = 'ICREL'
287+
288+
with self.assertRaisesRegex(
289+
ValueError, r'Reference length was 4 and sample length was 5\.'):
290+
VariantCalls(reference=reference, sample=sample)
291+
292+
def test_repr(self):
293+
expected_repr = "VariantCalls('A1IL H3R')"
294+
calls = VariantCalls('A1IL H3R')
295+
296+
r = repr(calls)
297+
298+
self.assertEqual(expected_repr, r)
299+
300+
def test_str(self):
301+
expected_str = 'A1IL H3R'
302+
calls = VariantCalls(expected_str)
303+
304+
s = str(calls)
305+
306+
self.assertEqual(expected_str, s)
307+
308+
def test_eq(self):
309+
calls1 = VariantCalls('A1IL H3R')
310+
calls2 = VariantCalls('H3R A1IL')
311+
calls3 = VariantCalls('A1IL H3Q')
312+
calls4 = VariantCalls('A1IL')
313+
314+
self.assertEqual(calls1, calls2)
315+
self.assertNotEqual(calls1, calls3)
316+
self.assertNotEqual(calls1, calls4)
34317

35-
mutations = call_mutations(reference, sample)
318+
def test_hash(self):
319+
hash1 = hash(VariantCalls('A1IL H3R'))
320+
hash2 = hash(VariantCalls('H3R A1IL'))
321+
hash3 = hash(VariantCalls('A1IL H3Q'))
322+
hash4 = hash(VariantCalls('A1IL'))
36323

37-
self.assertEqual(expected_mutations, mutations)
324+
self.assertEqual(hash1, hash2)
325+
self.assertNotEqual(hash1, hash3)
326+
self.assertNotEqual(hash1, hash4)
38327

39328

40329
if __name__ == '__main__':

0 commit comments

Comments
 (0)