def test_expandAll(self): """StructureNode expandAll should act recursively""" r = StructureNode() r.append(StructureNode(Data=Stem(0, 6, 4))) r.append(StructureNode(Data=Stem(0, 6, 3))) r.append(StructureNode()) r[0].append(StructureNode()) r[0].append(StructureNode(Data=Stem(0, 6, 2))) r[0][-1].append(StructureNode()) r.renumber() self.assertEqual(str(r), '((((.((.))))))((())).') r.expandAll() self.assertEqual(str(r), '((((.((.))))))((())).') expected_nodes = [ (None, None, 0), (0, 13, 1), (1, 12, 1), (2, 11, 1), (3, 10, 1), (4, None, 0), (5, 9, 1), (6, 8, 1), (7, None, 0), (14, 19, 1), (15, 18, 1), (16, 17, 1), (20, None, 0), ] for obs, exp in zip(r.traverse(), expected_nodes): self.assertEqual((obs.Start, obs.End, obs.Length), exp)
def test_expand(self): """StructureNode expand should extend helices.""" s = StructureNode(Data=(Stem(1, 10, 3))) s.append(StructureNode()) #need to make a root node for consistency r = StructureNode() r.append(s) self.assertEqual(str(s), '(((.)))') s.expand() self.assertEqual(str(s), '(((.)))') self.assertEqual((s.Start, s.End, s.Length), (1, 10, 1)) n = s[0] self.assertEqual((n.Start, n.End, n.Length), (2, 9, 1)) n = s[0][0] self.assertEqual((n.Start, n.End, n.Length), (3, 8, 1)) n = s[0][0][0] self.assertEqual((n.Start, n.End, n.Length), (None, None, 0)) s.renumber() self.assertEqual((s.Start, s.End, s.Length), (0, 6, 1)) n = s[0] self.assertEqual((n.Start, n.End, n.Length), (1, 5, 1)) n = s[0][0] self.assertEqual((n.Start, n.End, n.Length), (2, 4, 1)) n = s[0][0][0] self.assertEqual((n.Start, n.End, n.Length), (3, None, 0)) #check that it's not recursive s[0][0].append(StructureNode(Data=Stem(20, 24, 2))) s.expand() n = s[0][0][-1] self.assertEqual((n.Start, n.End, n.Length), (20, 24, 2)) n.expand() self.assertEqual((n.Start, n.End, n.Length), (20, 24, 1)) n = n[0] self.assertEqual((n.Start, n.End, n.Length), (21, 23, 1))
def test_extract(self): """Stems extract should return a list of 'pairs' from a sequence""" seq = 'UGAGAUUUUCU' s = Stem(1, 10, 3) self.assertEqual(s.extract(seq), [('G', 'U'), ('A', 'C'), ('G', 'U')]) s = Stem(0, 1) self.assertEqual(s.extract(seq), [('U', 'G')]) #should put in None if either position hasn't been specified s = Stem(5) self.assertEqual(s.extract(seq), [('U', None)]) s = Stem() self.assertEqual(s.extract(seq), [(None, None)]) #should raise IndexError if the stem contains bases outside the seq s = Stem(50, 60, 5) self.assertRaises(IndexError, s.extract, seq)
def test_unpair(self): """StructureNode unpair should break a base pair and add correct nodes""" i = self.Internal self.assertEqual(i[0].unpair(), True) self.assertEqual(str(i), '.((...))...((.)).') e = self.Ends self.assertEqual(e[0].unpair(), False) self.assertEqual(str(e), self.EndsStr) o = self.OneHelix self.assertEqual(o[0].unpair(), True) self.assertEqual(str(o), '.(((()))).') self.assertEqual(o[1][0][0].unpair(), True) self.assertEqual(str(o), '.((.().)).') self.assertEqual(o[1].unpair(), True) self.assertEqual(str(o), '..(.().)..') self.assertEqual(o[2][1].unpair(), True) self.assertEqual(str(o), '..(....)..') self.assertEqual(o[2].unpair(), True) self.assertEqual(str(o), '..........') #test with multiple bases in helix r = StructureNode() r.append(StructureNode(Data=Stem(0, 0, 5))) r.renumber() self.assertEqual(str(r), '((((()))))') self.assertEqual(r[0].unpair(), True) self.assertEqual(str(r), '.(((()))).')
def test_extendHelix(self): """StructureNode extendHelix should extend the helix as far as possible """ #single paired node is root[4] op_str = ViennaStructure('....(......)...') op = op_str.toTree() #can't extend if base pairs not allowed op[4].extendHelix(Rna('AAAAAAAAAAAAAAA')) self.assertEqual(str(op), op_str) #should extend a pair 5' op[4].extendHelix(Rna('AAACCAAAAAAGGAA')) self.assertEqual(str(op), '...((......))..') #should extend multiple pairs 5' op = op_str.toTree() op[4].extendHelix(Rna('CCCCCUUUUUUGGGG')) self.assertEqual(str(op), '.((((......))))') #should extend a pair 3', but must leave > 2-base loop op = op_str.toTree() op[4].extendHelix(Rna('AAAACCCCGGGGAAA')) self.assertEqual(str(op), '....((....))...') op[4][0].insert(1, StructureNode(Data=Stem(Start=1, End=1, Length=1))) op.renumber() self.assertEqual(str(op), '....((.()...))...') op[4][0].extendHelix(Rna('AAAACCCUACGGGGAAA')) self.assertEqual(str(op), '....(((()..)))...') #should extend a pair in both directions if possible op = op_str.toTree() op[4].extendHelix(Rna('AAACCCAAAAGGGAA')) self.assertEqual(str(op), '...(((....)))..')
def test_len(self): """Stem len() should return self.Length""" s = Stem() self.assertEqual(len(s), 0) s.Length = 5 self.assertEqual(len(s), 5) s.Length = None self.assertRaises(TypeError, len, s)
def test_nonzero(self): """Stem nonzero should return True if paired (length > 0)""" assert not Stem() assert not Stem(1) assert Stem(7, 10) assert Stem(1, 7, 1) assert Stem(2, 8, 3) #go strictly by length; don't check if data is invalid assert Stem(0, 0) assert Stem(5, None, 10) assert not Stem(5, 7, -1)
def test_renumber(self): """ViennaNode renumber should assign correct numbers to nodes""" #should have no effect on empty structure se = self.Empty self.assertEqual(se.renumber(5), 5) self.assertEqual((se.Start, se.End, se.Length), (None, None, 0)) #with no pairs, should number consecutively sn = self.NoPairs self.assertEqual(sn.renumber(5), 10) self.assertEqual([i.Start for i in sn], [5, 6, 7, 8, 9]) self.assertEqual([i.End for i in sn], [None] * 5) self.assertEqual([i.Length for i in sn], [0] * 5) #spot checks on a complex structure sm = self.ManyHelices self.assertEqual(sm.renumber(5), 52) s0 = sm[0] self.assertEqual((s0.Start, s0.End, s0.Length), (5, 51, 1)) s5 = sm[0][2][2][0] self.assertEqual(len(s5), 2) self.assertEqual((s5.Start, s5.End, s5.Length), (18, 33, 1)) s6 = s5[0] self.assertEqual((s6.Start, s6.End, s6.Length), (19, None, 0)) #test with some helices of different lengths root = StructureNode() root.extend([StructureNode() for i in range(3)]) root.insert(1, StructureNode(Data=Stem(3, 7, 5))) root.insert(3, StructureNode(Data=Stem(6, 2, 2))) root.append(StructureNode()) self.assertEqual(root.renumber(0), 18) self.assertEqual(len(root), 6) curr = root[0] self.assertEqual((curr.Start, curr.End, curr.Length), (0, None, 0)) curr = root[1] self.assertEqual((curr.Start, curr.End, curr.Length), (1, 10, 5)) curr = root[2] self.assertEqual((curr.Start, curr.End, curr.Length), (11, None, 0)) curr = root[3] self.assertEqual((curr.Start, curr.End, curr.Length), (12, 15, 2)) curr = root[4] self.assertEqual((curr.Start, curr.End, curr.Length), (16, None, 0)) curr = root[5] self.assertEqual((curr.Start, curr.End, curr.Length), (17, None, 0))
def test_init(self): """Stem should init with Start, End, and Length""" s = Stem(Length=3) self.assertEqual((s.Start, s.End, s.Length), (None, None, 3)) #should set Length to 0 if not supplied and unpaired s = Stem(Start=3) self.assertEqual((s.Start, s.End, s.Length), (3, None, 0)) s = Stem(End=3) self.assertEqual((s.Start, s.End, s.Length), (None, 3, 0)) #should set Length to 1 if not supplied and paired s = Stem(Start=3, End=5) self.assertEqual((s.Start, s.End, s.Length), (3, 5, 1)) #parameters should be in order Start, End, Length #note that you're allowed to initialize an invalid stem, like the #following one (can't have 7 pairs between 3 and 5); this is often #useful when building up a tree that you plan to renumber(). s = Stem(3, 5, 7) self.assertEqual((s.Start, s.End, s.Length), (3, 5, 7)) #not allowed more than 3 parameters self.assertRaises(TypeError, Stem, 1, 2, 3, 4)
def test_getitem(self): """Stem getitem should return a Stem object for the ith pair in the stem""" s = Stem() self.assertRaises(IndexError, s.__getitem__, 0) s.Start = 5 s.End = 8 s.Length = 1 pairs = list(s) self.assertEqual(pairs, [Stem(5, 8, 1)]) s.Length = 2 pairs = list(s) self.assertEqual(pairs, [Stem(5, 8, 1), Stem(6, 7, 1)]) #WARNING: Stem will not complain when iterating over an invalid helix, #as per the one below s.Length = 5 pairs = list(s) self.assertEqual(pairs, [Stem(5,8,1),Stem(6,7,1),Stem(7,6,1),\ Stem(8,5,1), Stem(9,4,1)])
def test_cmp(self): """Stems should compare equal when the data is the same""" self.assertEqual(Stem(1, 2, 3), Stem(1, 2, 3)) self.assertNotEqual(Stem(1, 2, 5), Stem(1, 2, 3)) a = Stem(1, 10, 2) b = Stem(2, 8, 1) c = Stem(15, 20, 2) l = [c, b, a] l.sort() self.assertEqual(l, [a, b, c])
def test_str(self): """ViennaNode str should return Vienna-format string""" for s in [ self.EmptyStr, self.NoPairsStr, self.OneHelixStr, self.ManyHelicesStr, self.EndsStr, self.InternalStr ]: self.assertEqual(str(ViennaStructure(s).toTree()), s) #test with multiple-base helix in a node r = StructureNode() r.append(StructureNode()) r.append(StructureNode(Data=Stem(1, 7, 5))) r[1].append(StructureNode()) r.append(StructureNode()) r.append(StructureNode()) r.renumber() self.assertEqual(str(r), '.(((((.)))))..')
def test_hash(self): """Stems hash should allow use as dict keys if unchanged""" #WARNING: if you change the Stem after putting it in a dict, all bets #are off as to behavior. Don't do it! s = Stem(1, 5, 2) t = Stem(1, 5, 2) u = Stem(2, 4, 6) v = Stem(2, 4, 6) w = Stem(2, 4, 4) d = {} assert s is not t for i in (s, t, u, v, w): if i in d: d[i] += 1 else: d[i] = 1 self.assertEqual(len(d), 3) self.assertEqual(d[Stem(1, 5, 2)], 2) self.assertEqual(d[Stem(2, 4, 6)], 2) self.assertEqual(d[Stem(2, 4, 4)], 1) assert Stem(1, 5) not in d
def test_init_empty(self): """Stem should init ok with no parameters.""" s = Stem() self.assertEqual((s.Start, s.End, s.Length), (None, None, 0))
def test_str(self): """Stem str should print Start, End and Length as a tuple""" self.assertEqual(str(Stem()), '(None,None,0)') self.assertEqual(str(Stem(3)), '(3,None,0)') self.assertEqual(str(Stem(3, 4)), '(3,4,1)') self.assertEqual(str(Stem(3, 4, 5)), '(3,4,5)')