1 """PrimerDesign script using Primer3 by yong27, 2005-05-17
2
3 priming conditions refer to http://www.rfcgr.mrc.ac.uk/Software/EMBOSS/Apps/eprimer3.html
4 """
5 import unittest, os, glob
6 from cStringIO import StringIO
7 from Bio import Fasta
8 from Bio.Emboss import Primer
9
10 class PrimerDesigner:
11 temp_dir = 'temp'
12 def __init__(self, ifile):
13 self.fi = Fasta.Iterator(ifile, Fasta.RecordParser())
14 self.pg = None
15
16 def getNextFasta(self):
17 return self.fi.next()
18
19 def saveAllFastas(self):
20 self.cleanUp()
21 os.mkdir(self.temp_dir)
22 for fasta in self.fi:
23 fasta.title = fasta.title.replace(':','-')
24 besid = '__'.join(fasta.title.split())
25 file(os.path.join(self.temp_dir, besid), 'w').write(str(fasta))
26
27 def cleanUp(self):
28 if os.path.exists(self.temp_dir):
29 for fname in os.listdir(self.temp_dir):
30 os.remove(os.path.join(self.temp_dir, fname))
31 os.rmdir(self.temp_dir)
32
33 def doPrimer3(self, **keywds):
34 self.saveAllFastas()
35 for fname in os.listdir(self.temp_dir):
36 fname = os.path.join(self.temp_dir, fname)
37 cmds = ['eprimer3']
38 cmds.extend(['-sequence', fname])
39 cmds.extend(['-outfile', fname+'.eprimer3'])
40 for k,v in keywds.iteritems():
41 cmds.extend(['-'+k, v])
42 os.system(' '.join(cmds))
43 self.pg = self.primerGenerator()
44
45 def getNextPrimer(self):
46 return self.pg.next()
47
48 def primerGenerator(self):
49 ppser = Primer.Primer3Parser()
50 for fname in glob.glob(os.path.join(self.temp_dir, '*.eprimer3')):
51 try:
52 primer = ppser.parse(file(fname)).primers[0]
53 except IndexError:
54 continue
55 yield (os.path.splitext(os.path.split(fname)[1])[0], primer)
56
57 def getPrimerInfos(self, primer, direction):
58 seq = getattr(primer, direction+'_seq')
59 tm = getattr(primer, direction+'_tm')
60 return [direction, seq, str(tm), str(primer.size)]
61
62 def writeXls(self, xfile):
63 for fname, primer in self.pg:
64 words = fname.split('__')
65 xfile.write('\t'.join(words+self.getPrimerInfos(primer, 'forward'))+'\n')
66 xfile.write('\t'.join(words+self.getPrimerInfos(primer, 'reverse'))+'\n')
67
68
69 class BreakPrimerDesigner(PrimerDesigner):
70 def __init__(self, ifile):
71 PrimerDesigner.__init__(self, ifile)
72 def writeXls(self, xfile):
73 xfile.write('\t'.join([
74 'BAC', 'BES', 'FPC start', 'FPC end', 'Human match',
75 'Direction', 'Primer sequence', 'Primer TM', 'Product size'
76 ])+'\n')
77 for fname, primer in self.pg:
78 besid, bacid, start, end, humanMatch = fname.split('__')
79 xfile.write('\t'.join([
80 bacid, besid, start, end, humanMatch,
81 ]+self.getPrimerInfos(primer, 'forward'))+'\n')
82 xfile.write('\t'.join([
83 bacid, besid, start, end, humanMatch,
84 ]+self.getPrimerInfos(primer, 'reverse'))+'\n')
85
86
87 class ByunsBreakPrimerDesigner:
88 def __init__(self, ifile):
89 self.pd = BreakPrimerDesigner(ifile)
90 self.pd.doPrimer3(otm='55', mintm='53')
91 def write(self, wfile):
92 self.pd.writeXls(wfile)
93
94
95 class TestPrimerDesigner(unittest.TestCase):
96 def setUp(self):
97 inputFile = StringIO("""\
98 >bE78F16SP6 CH242-78F16 46 72 18:11487196-11487708
99 GGTTGATGGTTCCCTGGTTTCATAAAACCTCTCAGGAACATTAGACTATGTCCGTGGAGA
100 GAAGTAAAACCCAATTATCCTCAGTGCCAGTAGTTTTTATGTCTCAGAAGAGATTCTGCT
101 GGAAGGATCACTGGGCATTTCAAGATGTTTGGAAACACTGCACTGATGGAGTTATCCTCA
102 GAGGGGTGTCATTAAATGTTTGTTTACGATTGTTGGTGGGTCTATCAAACCCACTTATTT
103 CTGCCAGCGTTAGATTTTTGACTCAATTAGGAAAAAAAAAGTATTAGAGGGAACTAACTT
104 TGCAGCAAAGGGCAGATACTCTTAGGTACTGAAAACTTGCTGAATTCTGTAGGAATAGGA
105 ACCTTGGGAATTATGCTTCCGTAGGAGAAATAATCAGAAAGGTCATTTTAGTCACTTAGG
106 AGTCTGTGGTGCCACTGGAATAATTAAAAACATGATAATTTAAACTGACTGTAGAGGTAA
107 TGGAAGAAACATGAAATTTAGTTAGACTAGGGTAGTTGAGTTTGTTCAAAAATCAAATGG
108 AAATCTTAGGGCACTACGGGAGCAGTTGAGAGTTGATCACAGCTGAGCAAGGCTGGTCTT
109 CTTCCTGCAGGTCCCGGCACCTTTGAGGATCTGACAAAGGCTGGCTGTCTTCTCTCAAGA
110 CAAGGGGCACGGGACCCCCAGTG
111 >bE78F16T7 CH242-78F16 46 72 18:11085776-11086061
112 TTGCTCTAACAGCCCTGAAATCCCCTGCAGCAGATTACTCTGATATAGGANGAANNGGCC
113 CCCNTTNCCNTTCACTGCTCTTTTTGACTTCCAAAAATAATATTCTGGCCCAGCTGTTCG
114 GTCAGGGCCTCGGTTTATTTGTAGTTAGCCAGAGAGGGGACCATAAATGAAATTCAGATG
115 CCGGGAGGGAGGAATGTCAGTCCTTCCAAATCCAACACTGAAAAGCCTTTCTTGTTTTTG
116 AGCTGAATAAAGAACGTCGGGCAATGGAACTTTGACCCAACATGCCATCCAGTCCAAAGA
117 GGAACGGCCAGAAAAAAGTGGACTTGTCTGGAGATGGTTCTCAGCCTCTAAGCCAGCCAG
118 CTCAGTCCCTTGTTTTAGCCCCCAGGGTATCTGGGCAGCCACAGGTCTGAGACACCCTTG
119 GTAGCTGAGGGCTCCCCTGGGCGCACAGGGCATGAGGGTGCCACCACGAAGAGGGGCCAC
120 AGGGCCCTTTTGTCAGCAAACAGAGCCTGGGCTCCAGGCTCCAGGTCTTGCAACAAATCC
121 CACCTCACC
122 """)
123 self.pd = PrimerDesigner(inputFile)
124
125 def testGetNextFasta(self):
126 expected = "bE78F16SP6 CH242-78F16 46 72 18:11487196-11487708"
127 self.assertEquals(expected, self.pd.getNextFasta().title)
128 expected = "bE78F16T7 CH242-78F16 46 72 18:11085776-11086061"
129 self.assertEquals(expected, self.pd.getNextFasta().title)
130
131 def testSaveAllFastas(self):
132 self.pd.saveAllFastas()
133 expected = ['bE78F16SP6__CH242-78F16__46__72__18-11487196-11487708',
134 'bE78F16T7__CH242-78F16__46__72__18-11085776-11086061',
135 ]
136 self.assertEquals(expected, os.listdir('temp'))
137
138 def testDoPrimer3(self):
139 self.pd.doPrimer3()
140 expected = ['bE78F16SP6__CH242-78F16__46__72__18-11487196-11487708',
141 'bE78F16T7__CH242-78F16__46__72__18-11085776-11086061',
142 'bE78F16SP6__CH242-78F16__46__72__18-11487196-11487708.eprimer3',
143 'bE78F16T7__CH242-78F16__46__72__18-11085776-11086061.eprimer3',
144 ]
145 expected.sort()
146 self.assertEquals(expected, sorted(os.listdir('temp')))
147
148 def testGetNextPrimer(self):
149 self.pd.doPrimer3()
150 fname, primer = self.pd.getNextPrimer()
151 self.assertEquals('TCTGTGGTGCCACTGGAATA', primer.forward_seq)
152 self.assertEquals('bE78F16SP6__CH242-78F16__46__72__18-11487196-11487708',fname)
153
154 def testWriteXls(self):
155 self.pd.doPrimer3()
156 xfile = StringIO()
157 self.pd.writeXls(xfile)
158 self.assertEquals('bE78F16SP6', xfile.getvalue().splitlines()[1].split('\t')[0])
159
160 if __name__=='__main__':
161 unittest.main()