Back to index

python-biopython  1.60
Primer3.py
Go to the documentation of this file.
00001 # Copyright 2008 Michiel de Hoon.
00002 # Revisions copyright 2009 Leighton Pritchard.
00003 # Revisions copyright 2010 Peter Cock.
00004 # All rights reserved.
00005 # This code is part of the Biopython distribution and governed by its
00006 # license.  Please see the LICENSE file that should have been included
00007 # as part of this package.
00008 """Code to parse output from the EMBOSS eprimer3 program.
00009 
00010 As elsewhere in Biopython there are two input functions, read and parse,
00011 for single record output and multi-record output. For primer3, a single
00012 record object is created for each target sequence and may contain
00013 multiple primers.
00014 
00015 i.e. If you ran eprimer3 with a single target sequence, use the read
00016 function. If you ran eprimer3 with multiple targets, use the parse
00017 function to iterate over the retsults.
00018 """
00019 
00020 # --- primer3
00021 
00022 class Record(object):
00023     """Represent information from a primer3 run finding primers.
00024 
00025     Members:
00026 
00027     primers  - list of Primer objects describing primer pairs for
00028                this target sequence.
00029     comments - the comment line(s) for the record
00030     """
00031     def __init__(self):
00032         self.comments = ""
00033         self.primers = []
00034 
00035 class Primers(object):
00036     """A primer set designed by Primer3.
00037 
00038     Members:
00039 
00040     size - length of product, note you can use len(primer) as an
00041            alternative to primer.size
00042 
00043     forward_seq
00044     forward_start
00045     forward_length
00046     forward_tm
00047     forward_gc
00048 
00049     reverse_seq
00050     reverse_start
00051     reverse_length
00052     reverse_tm
00053     reverse_gc
00054 
00055     internal_seq
00056     internal_start
00057     internal_length
00058     internal_tm
00059     internal_gc
00060     """
00061     def __init__(self):
00062         self.size = 0
00063         self.forward_seq = ""
00064         self.forward_start = 0
00065         self.forward_length = 0
00066         self.forward_tm = 0.0
00067         self.forward_gc = 0.0
00068         self.reverse_seq = ""
00069         self.reverse_start = 0
00070         self.reverse_length = 0
00071         self.reverse_tm = 0.0
00072         self.reverse_gc = 0.0
00073         self.internal_seq = ""
00074         self.internal_start = 0
00075         self.internal_length = 0
00076         self.internal_tm = 0.0
00077         self.internal_gc = 0.0
00078 
00079     def __len__(self):
00080         """Length of the primer product (i.e. product size)."""
00081         return self.size
00082 
00083 
00084 def parse(handle):
00085     """Iterate over primer3 output as Bio.Emboss.Primer3.Record objects.
00086     """
00087     # Skip blank lines at head of file
00088     while True:
00089         line = handle.readline()
00090         if line.strip():
00091             break # Starting a record
00092 
00093     # Read each record
00094     record = None
00095     primer = None
00096     while True:
00097         if line.startswith('# EPRIMER3') or line.startswith('# PRIMER3'):
00098             # Record data
00099             if record is not None:
00100                 yield record
00101             record = Record()
00102             record.comments += line
00103             primer = None
00104         elif line.startswith('#'):
00105             if line.strip() != '#                      Start  Len   Tm     GC%   Sequence':
00106                 record.comments += line
00107         elif not line.strip():
00108             pass
00109         elif line[5:19]=="PRODUCT SIZE: ":
00110             primer = Primers()
00111             primer.size = int(line[19:])
00112             record.primers.append(primer)
00113         elif line[5:19]=="FORWARD PRIMER":
00114             words = line.split()
00115             if not primer or primer.size==0:
00116                 primer = Primers()
00117                 record.primers.append(primer)
00118             primer.forward_start = int(words[2])
00119             primer.forward_length = int(words[3])
00120             primer.forward_tm = float(words[4])
00121             primer.forward_gc = float(words[5])
00122             primer.forward_seq = words[6]
00123         elif line[5:19]=="REVERSE PRIMER":
00124             words = line.split()
00125             if not primer or primer.size==0:
00126                 primer = Primers()
00127                 record.primers.append(primer)
00128             primer.reverse_start = int(words[2])
00129             primer.reverse_length = int(words[3])
00130             primer.reverse_tm = float(words[4])
00131             primer.reverse_gc = float(words[5])
00132             primer.reverse_seq = words[6]
00133         elif line[5:19]=="INTERNAL OLIGO":
00134             words = line.split()
00135             if not primer or primer.size==0:
00136                 primer = Primers()
00137                 record.primers.append(primer)
00138             primer.internal_start = int(words[2])
00139             primer.internal_length = int(words[3])
00140             primer.internal_tm = float(words[4])
00141             primer.internal_gc = float(words[5])
00142             primer.internal_seq = words[6]
00143         try:
00144             line = handle.next()
00145         except StopIteration:
00146             break
00147     if record:
00148         yield record
00149 
00150 
00151 def read(handle):
00152     """Parse primer3 output into a Bio.Emboss.Primer3.Record object.
00153 
00154     This is for when there is one and only one target sequence. If
00155     designing primers for multiple sequences, use the parse function.
00156     """
00157     iterator = parse(handle)
00158     try:
00159         first = iterator.next()
00160     except StopIteration:
00161         raise ValueError("No records found in handle")
00162     try:
00163         second = iterator.next()
00164     except StopIteration:
00165         second = None
00166     if second is not None:
00167         raise ValueError("More than one record found in handle")
00168     return first