# Copyright 2008 Michiel de Hoon. # Revisions copyright 2009 Leighton Pritchard. # Revisions copyright 2010 Peter Cock. # All rights reserved. # This code is part of the Biopython distribution and governed by its # license. Please see the LICENSE file that should have been included # as part of this package. """Code to parse output from the EMBOSS eprimer3 program. As elsewhere in Biopython there are two input functions, read and parse, for single record output and multi-record output. For primer3, a single record object is created for each target sequence and may contain multiple primers. i.e. If you ran eprimer3 with a single target sequence, use the read function. If you ran eprimer3 with multiple targets, use the parse function to iterate over the retsults. """ # --- primer3 class Record: """Represent information from a primer3 run finding primers. Members: primers - list of Primer objects describing primer pairs for this target sequence. comments - the comment line(s) for the record """ def __init__(self): self.comments = "" self.primers = [] class Primers: """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 def parse(handle): """Iterate over primer3 output as Bio.Emboss.Primer3.Record objects. """ # Skip blank lines at head of file while True: line = handle.readline() if line.strip(): break # Starting a record # Read each record record = None primer = None while True: if line.startswith('# EPRIMER3') or line.startswith('# PRIMER3'): # Record data if record is not None: yield record record = Record() record.comments += line primer = None elif line.startswith('#'): if line.strip() != '# Start Len Tm GC% Sequence': record.comments += line elif not line.strip(): pass elif line[5:19]=="PRODUCT SIZE: ": primer = Primers() primer.size = int(line[19:]) record.primers.append(primer) elif line[5:19]=="FORWARD PRIMER": words = line.split() if not primer or primer.size==0: primer = Primers() record.primers.append(primer) primer.forward_start = int(words[2]) primer.forward_length = int(words[3]) primer.forward_tm = float(words[4]) primer.forward_gc = float(words[5]) primer.forward_seq = words[6] elif line[5:19]=="REVERSE PRIMER": words = line.split() if not primer or primer.size==0: primer = Primers() record.primers.append(primer) primer.reverse_start = int(words[2]) primer.reverse_length = int(words[3]) primer.reverse_tm = float(words[4]) primer.reverse_gc = float(words[5]) primer.reverse_seq = words[6] elif line[5:19]=="INTERNAL OLIGO": words = line.split() if not primer or primer.size==0: primer = Primers() record.primers.append(primer) primer.internal_start = int(words[2]) primer.internal_length = int(words[3]) primer.internal_tm = float(words[4]) primer.internal_gc = float(words[5]) primer.internal_seq = words[6] try: line = next(handle) except StopIteration: break if record: yield record def read(handle): """Parse primer3 output into a Bio.Emboss.Primer3.Record object. This is for when there is one and only one target sequence. If designing primers for multiple sequences, use the parse function. """ iterator = parse(handle) try: first = next(iterator) except StopIteration: raise ValueError("No records found in handle") try: second = next(iterator) except StopIteration: second = None if second is not None: raise ValueError("More than one record found in handle") return first