File Coverage

blib/lib/Bio/Tools/Run/Phylo/PAML/Codeml.pm
Criterion Covered Total %
statement 122 179 68.1
branch 37 94 39.3
condition 6 32 18.7
subroutine 23 25 92.0
pod 13 13 100.0
total 201 343 58.6


line stmt bran cond sub pod time code
1             package Bio::Tools::Run::Phylo::PAML::Codeml;
2             $Bio::Tools::Run::Phylo::PAML::Codeml::VERSION = '1.7.2';
3 1     1   566 use utf8;
  1         4  
  1         8  
4 1     1   34 use strict;
  1         2  
  1         21  
5 1     1   5 use warnings;
  1         2  
  1         38  
6              
7 1     1   5 use vars qw(@ISA %VALIDVALUES $MINNAMELEN $PROGRAMNAME $PROGRAM);
  1         2  
  1         70  
8 1     1   5 use Bio::Root::Root;
  1         2  
  1         23  
9 1     1   5 use Bio::AlignIO;
  1         2  
  1         18  
10 1     1   4 use Bio::TreeIO;
  1         10  
  1         22  
11 1     1   326 use Bio::Tools::Run::WrapperBase;
  1         1315  
  1         27  
12 1     1   7 use Bio::Tools::Phylo::PAML;
  1         2  
  1         21  
13 1     1   8 use Cwd;
  1         2  
  1         296  
14              
15             @ISA = qw(Bio::Root::Root Bio::Tools::Run::WrapperBase);
16              
17             # ABSTRACT: Wrapper aroud the PAML program codeml
18             # AUTHOR: Jason Stajich
19             # OWNER: Jason Stajich
20             # LICENSE: Perl_5
21              
22              
23              
24             BEGIN {
25              
26 1     1   4 $MINNAMELEN = 25;
27 1 50       7 $PROGRAMNAME = 'codeml' . ($^O =~ /mswin/i ?'.exe':'');
28 1 50       5 if( defined $ENV{'PAMLDIR'} ) {
29 0 0       0 $PROGRAM = Bio::Root::IO->catfile($ENV{'PAMLDIR'},$PROGRAMNAME). ($^O =~ /mswin/i ?'.exe':'');;
30             }
31              
32             # valid values for parameters, the default one is always
33             # the first one in the array
34             # much of the documentation here is lifted directly from the codeml.ctl
35             # example file provided with the package
36             %VALIDVALUES = (
37 1         1482 'outfile' => 'mlc',
38             'noisy' => [ 0..3,9],
39             'verbose' => [ 1,0,2], # 0:concise, 1:detailed, 2:too much
40              
41             # (runmode) 0:user tree, 1:semi-autmatic, 2:automatic
42             # 3:stepwise addition, 4,5:PerturbationNNI
43             # -2:pairwise
44             'runmode' => [ -2, 0..5],
45              
46             'seqtype' => [ 1..3], # 1:codons, 2:AAs, 3:codons->AAs
47              
48             'CodonFreq' => [ 2, 0,1,3,4,5,6,7], # 0:1/61 each, 1:F1X4,
49             # 2:F3X4, 3:codon table
50              
51             # (aaDist) 0:equal, +:geometric, -:linear,
52             # 1-6:G1974,Miyata, c,p,v,a
53             'aaDist' => [ 0,'+','-', 1..6],
54              
55             # (aaRatefile) only used for aa seqs
56             # with model=empirical(_F)
57             # default is usually 'wag.dat', also
58             # dayhoff.dat, jones.dat, mtmam.dat, or your own
59             'aaRatefile' => 'wag.dat',
60              
61             # (model) models for codons
62             # 0: one, 1:b, 2:2 or more dN/dS ratios for branches
63             'model' => [0..3,7],
64              
65             # (NSsites) number of S sites
66             # 0: one w;1:neutral;2:selection; 3:discrete;4:freqs;
67             # 5:gamma;6:2gamma;7:beta;8:beta&w;9:betaγ
68             # 10:beta&gamma+1; 11:beta&normal>1; 12:0&2normal>1;
69             # 13:3normal>0
70             'NSsites' => [0..13],
71              
72             # (icode) genetic code
73             # 0:universal code
74             # 1:mamalian mt
75             # 2:yeast mt
76             # 3:mold mt,
77             # 4:invertebrate mt
78             # 5:ciliate nuclear
79             # 6:echinoderm mt
80             # 7:euplotid mt
81             # 8:alternative yeast nu.
82             # 9:ascidian mt
83             #10:blepharisma nu
84             # these correspond to 1-11 in the genbank transl table
85              
86             'icode' => [ 0..10],
87              
88             'Mgene' => [0,1], # 0:rates, 1:separate
89              
90             'fix_kappa'=> [0,1], # 0:estimate kappa, 1:fix kappa
91             'kappa' => '2', # initial or fixed kappa
92             'fix_omega'=> [0,1], # 0: estimate omega, 1: fix omega
93             'omega' => '1', # initial or fixed omega for
94             # codons or codon-base AAs
95             'fix_alpha'=> [1,0], # 0: estimate gamma shape param
96             # 1: fix it at alpha
97             'alpha' => '0.', # initial or fixed alpha
98             # 0: infinity (constant rate)
99             'Malpha' => [0,1], # different alphas for genes
100             'ncatG' => [1..10], # number of categories in
101             # dG of NSsites models
102              
103             # (clock)
104             # 0: no clock, 1: global clock, 2: local clock
105             # 3: TipDate
106             'clock' => [0..3],
107             # (getSE) Standard Error:
108             # 0:don't want them, 1: want S.E.
109             'getSE' => [0,1],
110             # (RateAncestor)
111             # 0,1,2 rates (alpha>0) or
112             # ancestral states (1 or 2)
113             'RateAncestor' => [1,0,2],
114             'Small_Diff' => '.5e-6',
115             # (cleandata) remove sites with ambiguity data
116             # 1: yes, 0:no
117             'cleandata' => [0,1],
118             # this is the number of datasets in
119             # the file - we would need to change
120             # our api to allow >1 alignment object
121             # to be referenced at time
122             'ndata' => 1,
123             # (method)
124             # 0: simultaneous,1: 1 branch at a time
125             'method' => [0,1],
126              
127             # allow branch lengths to be fixed
128             # 0 ignore
129             # -1 use random starting points
130             # 1 use the branch lengths in initial ML iteration
131             # 2 branch lengths are fixed
132             'fix_blength' => [0,-1,1,2],
133             );
134             }
135              
136              
137             sub program_name {
138 6     6 1 356 return 'codeml';
139             }
140              
141              
142             sub program_dir {
143 3 50   3 1 79 return Bio::Root::IO->catfile($ENV{PAMLDIR}) if $ENV{PAMLDIR};
144             }
145              
146              
147              
148             sub new {
149 1     1 1 472 my($class,@args) = @_;
150              
151 1         13 my $self = $class->SUPER::new(@args);
152 1         40 $self->{'_branchLengths'} = 0;
153 1         7 my ($aln, $tree, $st, $params, $exe,
154             $ubl) = $self->_rearrange([qw(ALIGNMENT TREE SAVE_TEMPFILES
155             PARAMS EXECUTABLE BRANCHLENGTHS)],
156             @args);
157 1 50       29 defined $aln && $self->alignment($aln);
158 1 50 0     5 defined $tree && $self->tree($tree, branchLengths => ($ubl || 0) );
159 1 50       3 defined $st && $self->save_tempfiles($st);
160 1 50       3 defined $exe && $self->executable($exe);
161              
162 1         6 $self->set_default_parameters();
163 1 50       7 if( defined $params ) {
164 1 50       7 if( ref($params) !~ /HASH/i ) {
165 0         0 $self->warn("Must provide a valid hash ref for parameter -FLAGS");
166             } else {
167 1         7 map { $self->set_parameter($_, $$params{$_}) } keys %$params;
  8         18  
168             }
169             }
170 1         3 return $self;
171             }
172              
173              
174              
175             sub prepare{
176 1     1 1 4 my ($self,$aln,$tree) = @_;
177 1 50       21 unless ( $self->save_tempfiles ) {
178             # brush so we don't get plaque buildup ;)
179 1         197 $self->cleanup();
180             }
181 1 50       42 $tree = $self->tree unless $tree;
182 1 50       4 $aln = $self->alignment unless $aln;
183 1 50       3 if( ! $aln ) {
184 0         0 $self->warn("must have supplied a valid alignment file in order to run codeml");
185 0         0 return 0;
186             }
187 1         8 my ($tempdir) = $self->tempdir();
188 1         559 my ($tempseqFH,$tempseqfile);
189 1 50 33     5 if( ! ref($aln) && -e $aln ) {
190 0         0 $tempseqfile = $aln;
191             } else {
192 1 50       3 ($tempseqFH,$tempseqfile) = $self->io->tempfile
193             ('-dir' => $tempdir,
194             UNLINK => ($self->save_tempfiles ? 0 : 1));
195 1 50       449 my $alnout = Bio::AlignIO->new('-format' => 'phylip',
196             '-fh' => $tempseqFH,
197             '-interleaved' => 0,
198             '-idlength' => $MINNAMELEN > $aln->maxdisplayname_length() ? $MINNAMELEN : $aln->maxdisplayname_length() +1);
199              
200 1         636 $alnout->write_aln($aln);
201 1         938 $alnout->close();
202 1         53 undef $alnout;
203 1         17 close($tempseqFH);
204             }
205             # now let's print the codeml.ctl file.
206             # many of the these programs are finicky about what the filename is
207             # and won't even run without the properly named file. Ack
208              
209 1         4 my $codeml_ctl = "$tempdir/codeml.ctl";
210 1 50       54 open(CODEML, ">$codeml_ctl") or $self->throw("cannot open $codeml_ctl for writing");
211 1         11 print CODEML "seqfile = $tempseqfile\n";
212 1         4 my $outfile = $self->outfile_name;
213 1         3 print CODEML "outfile = $outfile\n";
214              
215 1 50       4 if( $tree ) {
216 0         0 my ($temptreeFH,$temptreefile);
217 0 0 0     0 if( ! ref($tree) && -e $tree ) {
218 0         0 $temptreefile = $tree;
219             } else {
220 0 0       0 ($temptreeFH,$temptreefile) = $self->io->tempfile
221             ('-dir' => $tempdir,
222             UNLINK => ($self->save_tempfiles ? 0 : 1));
223              
224 0         0 my $treeout = Bio::TreeIO->new('-format' => 'newick',
225             '-fh' => $temptreeFH);
226 0         0 $treeout->write_tree($tree);
227 0         0 $treeout->close();
228 0         0 close($temptreeFH);
229             }
230 0         0 print CODEML "treefile = $temptreefile\n";
231             }
232              
233 1         4 my %params = $self->get_parameters;
234 1         8 while( my ($param,$val) = each %params ) {
235 28 100       76 next if $param eq 'outfile';
236 27         126 print CODEML "$param = $val\n";
237             }
238 1         30 close(CODEML);
239             # my ($rc,$parser) = (1);
240             # {
241             # my $cwd = cwd();
242             # my $exit_status;
243             # chdir($tempdir);
244             # }
245 1         7 return $tempdir;
246             }
247              
248              
249              
250              
251             sub run {
252 1     1 1 7 my ($self) = shift;;
253 1         4 my $outfile = $self->outfile_name;
254 1         10 my $tmpdir = $self->prepare(@_);
255              
256 1         3 my ($rc,$parser) = (1);
257             {
258 1         2 my $cwd = cwd();
  1         4011  
259 1         9 my $exit_status;
260 1         21 chdir($tmpdir);
261 1         38 my $codemlexe = $self->executable();
262 0 0 0     0 $self->throw("unable to find or run executable for 'codeml'") unless $codemlexe && -e $codemlexe && -x _;
      0        
263 0         0 my $run;
264 0 0       0 if( $self->{'_branchLengths'} ) {
265 0 0       0 open($run, "echo $self->{'_branchLengths'} | $codemlexe |") or $self->throw("Cannot open exe $codemlexe");
266             } else {
267 0 0       0 open($run, "$codemlexe |") or $self->throw("Cannot open exe $codemlexe");
268             }
269 0         0 my @output = <$run>;
270 0         0 $exit_status = close($run);
271 0         0 $self->error_string(join('',@output));
272 0 0 0     0 if( (grep { /\berr(or)?: /io } @output) || !$exit_status) {
  0         0  
273 0         0 $self->warn("There was an error - see error_string for the program output");
274 0         0 $rc = 0;
275             }
276 0         0 eval {
277 0         0 $parser = Bio::Tools::Phylo::PAML->new(-file => "$tmpdir/$outfile",
278             -verbose => $self->verbose,
279             -dir => "$tmpdir");
280             };
281 0 0       0 if( $@ ) {
282 0         0 $self->warn($self->error_string);
283             }
284 0         0 chdir($cwd);
285             }
286 0         0 return ($rc,$parser);
287             }
288              
289              
290             sub error_string{
291 0     0 1 0 my ($self,$value) = @_;
292 0 0       0 if( defined $value) {
293 0         0 $self->{'error_string'} = $value;
294             }
295 0         0 return $self->{'error_string'};
296              
297             }
298              
299              
300             sub alignment{
301 2     2 1 11500 my ($self,$aln) = @_;
302              
303 2 100       7 if( defined $aln ) {
304 1 50 33     48 if( -e $aln ) {
    50          
305 0         0 $self->{'_alignment'} = $aln;
306             } elsif( !ref($aln) || ! $aln->isa('Bio::Align::AlignI') ) {
307 0         0 $self->warn("Must specify a valid Bio::Align::AlignI object to the alignment function not $aln");
308 0         0 return undef;
309             } else {
310 1         4 $self->{'_alignment'} = $aln;
311             }
312             }
313 2         5 return $self->{'_alignment'};
314             }
315              
316              
317             sub tree {
318 1     1 1 3 my ($self, $tree, %params) = @_;
319 1 50       3 if( defined $tree ) {
320 0 0 0     0 if( ! ref($tree) || ! $tree->isa('Bio::Tree::TreeI') ) {
321 0         0 $self->warn("Must specify a valid Bio::Tree::TreeI object to the alignment function");
322             }
323 0         0 $self->{'_tree'} = $tree;
324 0 0       0 if ( defined $params{'_branchLengths'} ) {
325 0         0 my $ubl = $params{'_branchLengths'};
326 0 0       0 if ($ubl !~ m/^(0|1|2)$/) {
327 0         0 $self->throw("The branchLengths parameter to tree() must be 0 (ignore), 1 (initial values) or 2 (fixed values) only");
328             }
329 0         0 $self->{'_branchLengths'} = $ubl;
330             }
331             }
332 1         3 return $self->{'_tree'};
333             }
334              
335              
336             sub get_parameters{
337 1     1 1 3 my ($self) = @_;
338             # we're returning a copy of this
339 1         2 return %{ $self->{'_codemlparams'} };
  1         21  
340             }
341              
342              
343              
344             sub set_parameter{
345 8     8 1 16 my ($self,$param,$value) = @_;
346 8 50 33     17 unless (defined $self->{'no_param_checks'} && $self->{'no_param_checks'} == 1) {
347 8 50       17 if ( ! defined $VALIDVALUES{$param} ) {
348 0         0 $self->warn("unknown parameter $param will not be set unless you force by setting no_param_checks to true");
349 0         0 return 0;
350             }
351 8 100 66     20 if ( ref( $VALIDVALUES{$param}) =~ /ARRAY/i &&
352 5         16 scalar @{$VALIDVALUES{$param}} > 0 ) {
353              
354 5 50       8 unless ( grep { $value eq $_ } @{ $VALIDVALUES{$param} } ) {
  37         63  
  5         8  
355 0         0 $self->warn("parameter $param specified value $value is not recognized, please see the documentation and the code for this module or set the no_param_checks to a true value");
356 0         0 return 0;
357             }
358             }
359             }
360 8         13 $self->{'_codemlparams'}->{$param} = $value;
361 8         15 return 1;
362             }
363              
364              
365             sub set_default_parameters{
366 1     1 1 2 my ($self,$keepold) = @_;
367 1 50       4 $keepold = 0 unless defined $keepold;
368              
369 1         6 while( my ($param,$val) = each %VALIDVALUES ) {
370             # skip if we want to keep old values and it is already set
371 28 50 33     56 next if( defined $self->{'_codemlparams'}->{$param} && $keepold);
372 28 100       58 if(ref($val)=~/ARRAY/i ) {
373 21         66 $self->{'_codemlparams'}->{$param} = $val->[0];
374             } else {
375 7         21 $self->{'_codemlparams'}->{$param} = $val;
376             }
377             }
378             }
379              
380              
381              
382              
383             sub no_param_checks{
384 0     0 1 0 my ($self,$value) = @_;
385 0 0       0 if( defined $value) {
386 0         0 $self->{'no_param_checks'} = $value;
387             }
388 0         0 return $self->{'no_param_checks'};
389             }
390              
391              
392              
393              
394             sub outfile_name {
395 2     2 1 34 my $self = shift;
396 2 50       9 if( @_ ) {
397 0         0 return $self->{'_codemlparams'}->{'outfile'} = shift @_;
398             }
399 2 50       19 unless (defined $self->{'_codemlparams'}->{'outfile'}) {
400 0         0 $self->{'_codemlparams'}->{'outfile'} = 'mlc';
401             }
402 2         8 return $self->{'_codemlparams'}->{'outfile'};
403             }
404              
405              
406              
407              
408             sub DESTROY {
409 1     1   1110 my $self= shift;
410 1 50       8 unless ( $self->save_tempfiles ) {
411 1         27 $self->cleanup();
412             }
413 1         534 $self->SUPER::DESTROY();
414             }
415              
416             1;
417              
418             __END__