File Coverage

blib/lib/Bio/PrimerDesigner/ispcr.pm
Criterion Covered Total %
statement 24 116 20.6
branch 0 36 0.0
condition 0 20 0.0
subroutine 8 14 57.1
pod 6 6 100.0
total 38 192 19.7


line stmt bran cond sub pod time code
1             package Bio::PrimerDesigner::ispcr;
2              
3             # $Id: ispcr.pm 9 2008-11-06 22:48:20Z kyclark $
4              
5             =head1 NAME
6              
7             Bio::PrimerDesigner::ispcr - A class for accessing the isPcr (in-silico PCR) binary
8              
9             =head1 SYNOPSIS
10              
11             use Bio::PrimerDesigner::ispcr;
12              
13             =head1 DESCRIPTION
14              
15             A low-level interface to the isPcr program. Uses supplied PCR primers,
16             DNA sequence and stringency parameters to predict both expected
17             and unexpected PCR products.
18              
19             =head1 METHODS
20              
21             =cut
22              
23 1     1   9646 use strict;
  1         2  
  1         40  
24 1     1   4 use warnings;
  1         3  
  1         38  
25 1     1   5 use File::Spec::Functions 'catfile';
  1         2  
  1         56  
26 1     1   5 use File::Temp 'tempfile';
  1         3  
  1         46  
27 1     1   5 use Bio::PrimerDesigner::Remote;
  1         2  
  1         26  
28 1     1   5 use Bio::PrimerDesigner::Result;
  1         3  
  1         21  
29 1     1   5 use Readonly;
  1         2  
  1         107  
30              
31             Readonly our
32             $VERSION => sprintf "%s", q$Revision: 24 $ =~ /(\d+)/;
33              
34 1     1   6 use base 'Class::Base';
  1         1  
  1         1229  
35              
36             # -------------------------------------------------------------------
37             sub run {
38              
39             =pod
40              
41             =head2 run
42              
43             Sets up the isPcr request for a single primer combination and returns
44             an Bio::PrimerDesigner::Result object
45              
46             If the permute flag is true, all three possible primer combinations
47             will be tested (ie: forward + reverse, forward + forward, reverse + reverse)
48              
49             =cut
50              
51 0     0 1   my $self = shift;
52 0           my @result = ();
53 0 0         my @params = @_ or return $self->error("No arguments for run method");
54 0           my $args = $_[2];
55 0 0         my $permute = $args->{'permute'} ? 1 : 0;
56 0 0         my $left = $args->{'left'} or $self->error("No left primer");
57 0 0         my $right = $args->{'right'} or $self->error("No right primer");
58            
59 0           $args->{'permute'} = 0;
60            
61 0 0         if ( $permute ) {
62 0           for my $combo ( 1 .. 3 ) {
63 0           my %seen = ();
64 0 0         local $args->{'right'} = $left if $combo == 2;
65 0 0         local $args->{'left'} = $right if $combo == 3;
66 0           $params[2] = $args;
67 0           my @pre_result = $self->request(@params);
68              
69             #
70             # same-primer comparisons give two identical
71             # results, we will ignore duplicates
72             #
73 0           for my $line (@pre_result) {
74 0 0         push @result, $line unless ++$seen{$line} > 1;
75             }
76             }
77             }
78             else {
79 0           @result = $self->request( @params );
80             }
81            
82             # first element will be empty
83 0           shift @result;
84              
85 0           my $out = Bio::PrimerDesigner::Result->new;
86            
87 0           $out->{1}->{'products'} = @result;
88 0           $out->{1}->{'raw_output'} = join('','>',@result);
89            
90 0           my $count = 0;
91              
92 0           for (@result) {
93 0           $count++;
94 0           s/>//;
95 0           my @lines = split "\n", $_;
96 0           chomp @lines;
97              
98 0           my $idline = shift @lines;
99 0           my ($location) = split /\s+/, $idline;
100 0           my ($start,$strand,$stop) = $location =~ /(\d+)([-+])(\d+)$/;
101 0           my $size = abs($stop - $start);
102              
103 0           $out->{$count}->{'start'} = $start;
104 0           $out->{$count}->{'stop'} = $out->{$count}->{'end'} = $stop;
105 0           $out->{$count}->{'size'} = $size;
106 0           $out->{$count}->{'amplicon'} = join '', @lines;
107             }
108            
109 0           return $out;
110             }
111              
112             # -------------------------------------------------------------------
113             sub request {
114              
115             =pod
116              
117             =head2 request
118              
119             Assembles the config file and command-line arguments and sends
120             the request to the local binary or remote server.
121              
122             =cut
123              
124 0     0 1   my $self = shift;
125 0           my ($method, $loc, $args) = @_;
126 0           my @data = ();
127 0   0       $method ||= 'remote';
128            
129 0 0         if ( $method eq 'remote' ) {
    0          
130 0 0         if ( ! defined $args->{'seq'} ) {
131 0           $self->error(
132             "A sequence must be supplied (not a file name) for remote ispcr"
133             );
134 0           return '';
135             }
136              
137 0           my $cgi = Bio::PrimerDesigner::Remote->new;
138 0           $cgi->{'program'} = 'ispcr';
139 0           $args->{'program'} = 'ispcr';
140            
141 0           @data = $cgi->CGI_request( $loc, $args );
142             }
143             elsif ( $method eq 'local') { # run ePCR locally
144             #
145             # required parameters
146             #
147 0   0       my $left = uc $args->{'left'} || $self->error("no left primer");
148 0   0       my $right = uc $args->{'right'} || $self->error("no right primer");
149 0   0       my $seq = $args->{'seq'} || '';
150 0   0       my $file = $args->{'seqfile'} || '';
151 0 0 0       $self->error("No sequence supplied") unless $seq || $file;
152              
153             #
154             # config file
155             #
156 0           my ( $temp_loc_fh, $temp_loc ) = tempfile;
157 0           print $temp_loc_fh "isPCR_test\t$left\t$right\n";
158 0           close $temp_loc_fh;
159            
160             #
161             # sequence file (fasta format)
162             #
163 0           my ($seq_loc_fh, $seq_loc, $seq_file, $seq_temp);
164 0 0         if ($seq) {
165 0           ( $seq_loc_fh, $seq_loc ) = tempfile;
166 0           $seq_temp = $seq_loc;
167 0           print $seq_loc_fh ">test\n$seq\n";
168 0           close $seq_loc_fh;
169             }
170             else {
171 0 0         $seq_loc = $file or $self->error('No sequence file');
172             }
173              
174             #
175             # command-line arguments
176             #
177 0           my $params = '';
178 0           for my $p (qw/tileSize stepSize maxSize minSize minPerfect minGood mask/) {
179 0 0         $params .= "-$p=$args->{$p}" if defined $args->{$p};
180             }
181              
182 0           $loc = catfile( $loc, $self->binary_name );
183            
184 0           local $/ = '>';
185 0           open ISPCR, "$loc $seq_loc $temp_loc $params stdout |";
186 0           @data = ();
187 0           close ISPCR;
188              
189              
190 0           unlink $temp_loc;
191 0 0 0       unlink $seq_temp if $seq_temp && -e $seq_temp;
192             }
193              
194 0           return @data;
195             }
196              
197             # -------------------------------------------------------------------
198             sub verify {
199              
200             =pod
201              
202             =head2 verify
203              
204             Check to make that the isPCR binary is installed and functioning
205             properly. Since ispcr returns nothing if no PCR product is found
206             in the sequence, we have to be able to distinguish between a valid,
207             undefined output from a functioning ispcr and an undefined output
208             for some other reason. verify uses sham ispcr data that is known
209             to produce a PCR product.
210              
211             =cut
212              
213 0     0 1   my $self = shift;
214 0 0         my ($method, $loc) = @_ or $self->error('No verify parameters');
215 0           my %param = ();
216 0           $param{'left'} = 'TTGCGCATTTACGATTACGA';
217 0           $param{'right'} = 'ATGCTGTAATCGGCTGTCCT';
218 0           $param{'seq'} = 'GCAGCGAGTTGCGCATTTACGATTACGACATACGACACGA' .
219             'TTACAGACAGGACAGCCGATTACAGCATATCGACAGCAT';
220            
221 0           my $result = $self->run( $method, $loc, \%param );
222 0   0       my $output = $result->raw_output || '';
223              
224 0 0         unless ( $output =~ />\S+\s+\S+\s+\S+\s+\S+/ ) {
225 0           return $self->error("ispcr did not verify!");
226             }
227             else {
228 0           return $result;
229             }
230             }
231              
232             # -------------------------------------------------------------------
233             sub binary_name {
234              
235             =pod
236              
237             =head2 binary_name
238              
239             Defines the binary's name on the system.
240              
241             =cut
242              
243 0     0 1   my $self = shift;
244 0           return 'isPcr';
245             }
246              
247             # -------------------------------------------------------------------
248             sub list_aliases {
249              
250             =pod
251              
252             =head2 list_aliases
253              
254             There are no aliases to list for ispcr.
255              
256             =cut
257              
258 0     0 1   my $self = shift;
259 0           return;
260             }
261              
262             # -------------------------------------------------------------------
263             sub list_params {
264              
265             =pod
266              
267             =head2 list_params
268              
269             Returns a list of ispcr configuration options. Required ispcr input is
270             a sequence string or file and the left and right primers. Default values
271             will be used for the remaining options if none are supplied.
272              
273              
274             =cut
275              
276 0     0 1   my $self = shift;
277              
278             return (
279 0           'REQUIRED:',
280             'seq (string) Raw DNA sequence to search for PCR products',
281             'OR',
282             'seqfile (string) Fasta file to search for PCR products',
283             '',
284             'left (string) Left primer sequence',
285             'right (string) Right primer sequence',
286             '', 'OPTIONAL:',
287             'tileSize (int) size of match that triggers alignment (default 11)',
288             'stepSize (int) spacing between tiles (default 5)',
289             'maxSize (int) max size of PCR product (default 4000)',
290             'minSize (int) min size of PCR product (default 0)',
291             'minPerfect (int) min size of perfect match at 3 prime end of primer (default 15)',
292             'minGood (int) min size where there must be 2 matches for each mismatch (default 15)',
293             'permute (true) Try all primer combinations (l/r, l/l, r/r)',
294             'mask (upper|lower) Mask out lower or upper-cased sequences'
295             );
296             }
297              
298             1;
299              
300             # -------------------------------------------------------------------
301              
302             =head1 AUTHOR
303              
304             Copyright (C) 2003-2009 Sheldon McKay Emckays@cshl.edu,
305             Ken Y. Clark Ekclark@cpan.orgE.
306              
307             =head1 LICENSE
308              
309             This program is free software; you can redistribute it and/or modify
310             it under the terms of the GNU General Public License as published by
311             the Free Software Foundation; version 3 or any later version.
312              
313             This program is distributed in the hope that it will be useful, but
314             WITHOUT ANY WARRANTY; without even the implied warranty of
315             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
316             General Public License for more details.
317              
318             You should have received a copy of the GNU General Public License
319             along with this program; if not, write to the Free Software
320             Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
321             USA.
322              
323             =head1 SEE ALSO
324              
325             Bio::PrimerDesigner::primer3.
326              
327             =cut