File: Primer.py

package info (click to toggle)
python-biopython 1.42-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 17,584 kB
  • ctags: 12,272
  • sloc: python: 80,461; xml: 13,834; ansic: 7,902; cpp: 1,855; sql: 1,144; makefile: 203
file content (281 lines) | stat: -rw-r--r-- 8,654 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
"""Code to interact with various Primer-related programs from EMBOSS.
"""
# standard library
import string
from xml.sax import handler

# Martel
import Martel
from Martel import RecordReader

# biopython stuff
from Bio.ParserSupport import AbstractConsumer
from Bio.ParserSupport import EventGenerator

import primersearch_format
import primer3_format

# --- primersearch

class PrimerSearchInputRecord:
    """Represent the input file into the primersearch program.

    This makes it easy to add primer information and write it out to the
    simple primer file format.
    """ 
    def __init__(self):
        self.primer_info = []

    def __str__(self):
        output = ""
        for name, primer1, primer2 in self.primer_info:
            output += "%s %s %s\n" % (name, primer1, primer2)
        return output

    def add_primer_set(self, primer_name, first_primer_seq, 
                       second_primer_seq):
        """Add primer information to the record.
        """
        self.primer_info.append((primer_name, first_primer_seq,
                                 second_primer_seq))
           
class PrimerSearchParser:
    """Parse primersearch output into a PrimerSearchOutputRecord.
    """
    def __init__(self, debug_level = 0):
        self._scanner = _PrimerSearchScanner(debug_level)

    def parse(self, handle):
        self._consumer = _PrimerSearchRecordConsumer()
        self._scanner.feed(handle, self._consumer)
        return self._consumer.data

class PrimerSearchOutputRecord:
    """Represent the information from a primersearch job.

    amplifiers is a dictionary where the keys are the primer names and
    the values are a list of PrimerSearchAmplifier objects.
    """
    def __init__(self):
        self.amplifiers = {}

class PrimerSearchAmplifier:
    """Represent a single amplification from a primer.
    """
    def __init__(self):
        self.hit_info = ""
        self.length = 0

class _PrimerSearchRecordConsumer(AbstractConsumer):
    """Get output from primersearch into a PrimerSearchOutputRecord
    """
    def __init__(self):
        self.data = PrimerSearchOutputRecord()
        self._cur_primer = None
        self._cur_amplifier = None

    def _add_last_amplifier(self):
        # add on the last amplifier
        if self._cur_primer is not None and self._cur_amplifier is not None:
            self.data.amplifiers[self._cur_primer].append(self._cur_amplifier)

    def primer_name(self, name):
        self._add_last_amplifier() 
        self.data.amplifiers[name] = []
        self._cur_primer = name

    def amplifier(self, amplifier_num):
        self._add_last_amplifier()
        self._cur_amplifier = PrimerSearchAmplifier()

    def amplifier_sequence(self, sequence_info):
        self._cur_amplifier.hit_info = sequence_info

    def amplifier_length(self, amplifier_info):
        self._cur_amplifier.length = int(amplifier_info)

    def end_record(self):
        self._add_last_amplifier()

class _PrimerSearchScanner:
    """Scan output from the primersearch program.
    """
    def __init__(self, debug = 0):
        self.interest_tags = ["primer_name", "amplifier", 
                              "amplifier_sequence", "amplifier_length",
                              "end_record"]

        expression = Martel.select_names(primersearch_format.record,
                                            self.interest_tags)
        self._parser = expression.make_parser(debug_level = debug)

    def feed(self, handle, consumer):
        self._parser.setContentHandler(EventGenerator(consumer,
                                                      self.interest_tags,
                                                      _strip_and_combine))
        self._parser.setErrorHandler(handler.ErrorHandler())
        self._parser.parseFile(handle)

        consumer.end_record()

# --- primer3

class Primer3Record:
    """Represent information from a primer3 run finding primers.

    Members:

    primers   A list of primers that are generated (usually 5)
    """
    def __init__(self):
        self.comments = ""
        self.primers = []

class Primer3Primers:
    """A primer set designed by Primer3.

    Members:

    size
    forward_seq
    forward_start
    forward_length
    forward_tm
    forward_gc
    reverse_seq
    reverse_start
    reverse_length
    reverse_tm
    reverse_gc
    """
    def __init__(self):
        self.size = 0
        self.forward_seq = ""
        self.forward_start = 0
        self.forward_length = 0
        self.forward_tm = 0.0
        self.forward_gc = 0.0
        self.reverse_seq = ""
        self.reverse_start = 0
        self.reverse_length = 0
        self.reverse_tm = 0.0
        self.reverse_gc = 0.0

class Primer3Parser:
    """Parse primer3 output into a Primer3Record.
    """
    def __init__(self, debug_level = 0):
        self._scanner = _Primer3Scanner(debug_level)

    def parse(self, handle):
        self._consumer = _Primer3RecordConsumer()
        self._scanner.feed(handle, self._consumer)
        return self._consumer.data

class _Primer3RecordConsumer(AbstractConsumer):
    """Get output from prime3 into a Primer3Record
    """
    def __init__(self):
        self.data = Primer3Record()
        self._cur_primer = None

    def _add_last_primer(self):
        # add on the last amplifier
        if self._cur_primer is not None:
            self.data.primers.append(self._cur_primer)

    def comments(self, comment):
        self.data.comments = comment

    def start_primer(self, junk):
        self._add_last_primer()
        self._cur_primer = Primer3Primers()

    def single_primer_line(self, junk):
        self.start_primer(junk)

    def product_size(self, size):
        self._cur_primer.size = int(size)

    def forward_start(self, start):
        self._cur_primer.forward_start = int(start)

    def forward_length(self, length):
        self._cur_primer.forward_length = int(length)

    def forward_tm(self, tm):
        self._cur_primer.forward_tm = float(tm)

    def forward_gc(self, gc):
        self._cur_primer.forward_gc = float(gc)

    def forward_seq(self, seq):
        self._cur_primer.forward_seq = seq

    def reverse_start(self, start):
        self._cur_primer.reverse_start = int(start)

    def reverse_length(self, length):
        self._cur_primer.reverse_length = int(length)

    def reverse_tm(self, tm):
        self._cur_primer.reverse_tm = float(tm)

    def reverse_gc(self, gc):
        self._cur_primer.reverse_gc = float(gc)

    def reverse_seq(self, seq):
        self._cur_primer.reverse_seq = seq

    def internal_start(self, start):
        self._cur_primer.internal_start = int(start)

    def internal_length(self, length):
        self._cur_primer.internal_length = int(length)

    def internal_tm(self, tm):
        self._cur_primer.internal_tm = float(tm)

    def internal_gc(self, gc):
        self._cur_primer.internal_gc = float(gc)

    def internal_seq(self, seq):
        self._cur_primer.internal_seq = seq

    def end_record(self):
        self._add_last_primer()

class _Primer3Scanner:
    """Scan output from the primer3 program.
    """
    def __init__(self, debug = 0):
        self.interest_tags = ["comments", "single_primer_line",
                              "start_primer", "product_size",
                              "forward_start", "forward_length",
                              "forward_tm", "forward_gc", "forward_seq",
                              "reverse_start", "reverse_length",
                              "reverse_tm", "reverse_gc", "reverse_seq",
                              "internal_start", "internal_length",
                              "internal_tm", "internal_gc", "internal_seq",
                              "end_record"]

        expression = Martel.select_names(primer3_format.record,
                                         self.interest_tags)
        self._parser = expression.make_parser(debug_level = debug)

    def feed(self, handle, consumer):
        self._parser.setContentHandler(EventGenerator(consumer,
                                                      self.interest_tags,
                                                      _strip_and_combine))
        self._parser.setErrorHandler(handler.ErrorHandler())
        self._parser.parseFile(handle)

        consumer.end_record()

def _strip_and_combine(line_list):
    """Combine multiple lines of content separated by spaces.
    """
    # first strip out extra whitespace
    stripped_line_list = map(string.strip, line_list)
    # now combine everything with spaces
    return string.join(stripped_line_list, ' ')