Spaces:
No application file
No application file
# Copyright 2008 Michiel de Hoon. | |
# Revisions copyright 2009 Leighton Pritchard. | |
# Revisions copyright 2010 Peter Cock. | |
# All rights reserved. | |
# | |
# This file is part of the Biopython distribution and governed by your | |
# choice of the "Biopython License Agreement" or the "BSD 3-Clause 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): | |
"""Initialize the class.""" | |
self.comments = "" | |
self.primers = [] | |
class Primers: | |
"""A primer set designed by Primer3. | |
Members: | |
- size - length of product, note you can use len(primer) as an | |
alternative to primer.size | |
- forward_seq | |
- forward_start | |
- forward_length | |
- forward_tm | |
- forward_gc | |
- reverse_seq | |
- reverse_start | |
- reverse_length | |
- reverse_tm | |
- reverse_gc | |
- internal_seq | |
- internal_start | |
- internal_length | |
- internal_tm | |
- internal_gc | |
""" | |
def __init__(self): | |
"""Initialize the class.""" | |
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 | |
self.internal_seq = "" | |
self.internal_start = 0 | |
self.internal_length = 0 | |
self.internal_tm = 0.0 | |
self.internal_gc = 0.0 | |
def __len__(self): | |
"""Length of the primer product (i.e. product size).""" | |
return self.size | |
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]) | |
try: | |
primer.internal_seq = words[6] | |
except IndexError: # eprimer3 reports oligo without sequence | |
primer.internal_seq = "" | |
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: | |
record = next(iterator) | |
except StopIteration: | |
raise ValueError("No records found in handle") from None | |
try: | |
next(iterator) | |
raise ValueError("More than one record found in handle") | |
except StopIteration: | |
pass | |
return record | |