1=head1 NAME 2 3Bio::Tools::Run::Phylo::Hyphy::BatchFile - Wrapper for custom execution of Hyphy batch files 4 5=head1 SYNOPSIS 6 7my $aln = Bio::Align::AlignI->new(); 8my $treeio = Bio::TreeIO->new(-format => "nexus", -file => "$tree_file"); 9my $tree = $treeio->next_tree(); 10my $bf_exec = Bio::Tools::Run::Phylo::Hyphy::BatchFile->new(-params => {'bf' => "hyphybatchfile.bf", 'order' => ["Universal", "Custom", $aln, "001001", $tree]}); 11$bf_exec->set_parameter('3', "012012"); 12my ($rc,$parser) = $bf_exec->run(); 13 14=head1 DESCRIPTION 15 16This module creates a generic interface to processing of HBL files in HyPhy ([Hy]pothesis 17Testing Using [Phy]logenies), a package by Sergei Kosakowsky Pond, 18Spencer V. Muse, Simon D.W. Frost and Art Poon. See 19http://www.hyphy.org for more information. 20 21Instances of this module require only a link to the batch file and an ordered list of 22parameters, as described in the HyPhy documentation "SelectionAnalyses.pdf." 23 24 25=head1 FEEDBACK 26 27=head2 Mailing Lists 28 29User feedback is an integral part of the evolution of this and other 30Bioperl modules. Send your comments and suggestions preferably to 31the Bioperl mailing list. Your participation is much appreciated. 32 33 bioperl-l@bioperl.org - General discussion 34 http://bioperl.org/wiki/Mailing_lists - About the mailing lists 35 36=head2 Support 37 38Please direct usage questions or support issues to the mailing list: 39 40I<bioperl-l@bioperl.org> 41 42rather than to the module maintainer directly. Many experienced and 43reponsive experts will be able look at the problem and quickly 44address it. Please include a thorough description of the problem 45with code and data examples if at all possible. 46 47=head2 Reporting Bugs 48 49Report bugs to the Bioperl bug tracking system to help us keep track 50of the bugs and their resolution. Bug reports can be submitted via the 51web: 52 53 http://redmine.open-bio.org/projects/bioperl/ 54 55=head1 AUTHOR - Daisie Huang 56 57Email daisieh@zoology.ubc.ca 58 59=head1 CONTRIBUTORS 60 61Additional contributors names and emails here 62 63=cut 64 65package Bio::Tools::Run::Phylo::Hyphy::BatchFile; 66use strict; 67use Bio::Root::Root; 68use Bio::AlignIO; 69use Bio::TreeIO; 70use Bio::Tools::Run::Phylo::Hyphy::Base; 71use Bio::Tools::Run::WrapperBase; 72 73use base qw(Bio::Root::Root Bio::Tools::Run::Phylo::Hyphy::Base); 74 75=head2 valid_values 76 77 Title : valid_values 78 Usage : $factory->valid_values() 79 Function: returns the possible parameters 80 Returns: an array holding all possible parameters. The default 81values are always the first one listed. These descriptions are 82essentially lifted from the python wrapper or provided by the author. 83 Args : None 84 85=cut 86 87 88sub valid_values { 89 return ( 90 {'geneticCode' => [ "Universal","VertebratemtDNA","YeastmtDNA","Mold/ProtozoanmtDNA", 91 "InvertebratemtDNA","CiliateNuclear","EchinodermmtDNA","EuplotidNuclear", 92 "Alt.YeastNuclear","AscidianmtDNA","FlatwormmtDNA","BlepharismaNuclear"]}, 93 {'tempalnfile' => undef }, # aln file goes here 94 {'temptreefile' => undef }, # tree file goes here 95 ); 96} 97 98=head2 new 99 100 Title : new 101 Usage : my $obj = Bio::Tools::Run::Phylo::Hyphy::BatchFile->new(); 102 Function: Builds a new Bio::Tools::Run::Phylo::Hyphy::BatchFile object 103 Returns : Bio::Tools::Run::Phylo::Hyphy::BatchFile 104 Args : -alignment => the Bio::Align::AlignI object 105 -save_tempfiles => boolean to save the generated tempfiles and 106 NOT cleanup after onesself (default FALSE) 107 -tree => the Bio::Tree::TreeI object 108 -params => a hashref of parameters (all passed to set_parameter) 109 this hashref should include 'bf' => custombatchfile.bf 110 'order' => [array of ordered parameters] 111 -executable => where the hyphy executable resides 112 113See also: L<Bio::Tree::TreeI>, L<Bio::Align::AlignI> 114 115=cut 116 117sub new { 118 my($class,@args) = @_; 119 120 my $self = $class->SUPER::new(@args); 121 my ($aln, $tree, $st, $params, $exe) = $self->_rearrange([qw(ALIGNMENT TREE SAVE_TEMPFILES PARAMS EXECUTABLE)], @args); 122 defined $aln && $self->alignment($aln); 123 defined $tree && $self->tree($tree); 124 defined $st && $self->save_tempfiles($st); 125 defined $exe && $self->executable($exe); 126 127 $self->set_default_parameters(); 128 if( defined $params ) { 129 if( ref($params) !~ /HASH/i ) { 130 $self->warn("Must provide a valid hash ref for parameter -FLAGS"); 131 } else { 132 map { $self->set_parameter($_, $$params{$_}) } keys %$params; 133 } 134 } 135 return $self; 136} 137 138=head2 update_ordered_parameters 139 140 Title : update_ordered_parameters 141 Usage : $BatchFile->update_ordered_parameters(); 142 Function: updates all of the parameters needed for the ordered input redirect in HBL. 143 Returns : nothing 144 Args : none 145 146=cut 147 148sub update_ordered_parameters { 149 my ($self) = @_; 150 unless (defined ($self->{'_params'}{'order'})) { 151 $self->throw("No ordered parameters for HYPHY were defined."); 152 } 153 for (my $i=0; $i< scalar @{$self->{'_params'}{'order'}}; $i++) { 154 my $item = @{$self->{'_params'}{'order'}}[$i]; 155 #FIXME: update_ordered_parameters should be more flexible. It should be able to tell what type of object $item is and, if necessary, create a temp file for it. 156 if (ref ($item) =~ m/Bio::SimpleAlign/) { 157 $item = $self->{'_params'}{'tempalnfile'}; 158 } elsif (ref ($item) =~ m/Bio::Tree::Tree/) { 159 $item = $self->{'_params'}{'temptreefile'}; 160 } 161 $self->{'_orderedparams'}[$i] = {$i, $item}; 162 } 163 $self->SUPER::update_ordered_parameters(); 164} 165 166=head2 run 167 168 Title : run 169 Usage : my ($rc,$results) = $BatchFile->run(); 170 Function: run the Hyphy analysis using the specified batchfile and its ordered parameters 171 Returns : Return code, Hash 172 Args : none 173 174 175=cut 176 177sub run { 178 my $self = shift; 179 my ($rc, $results) = $self->SUPER::run(); 180 my $outfile = $self->outfile_name(); 181 open(OUTFILE, ">", $outfile) or $self->throw("cannot open $outfile for writing"); 182 print OUTFILE $results; 183 close(OUTFILE); 184 return ($rc,$results); 185} 186 187 188=head2 create_wrapper 189 190 Title : create_wrapper 191 Usage : $self->create_wrapper 192 Function: Creates the wrapper file for the batchfile specified in the hash, saves it to the hash as '_wrapper'. 193 Returns : nothing 194 Args : none 195 196 197=cut 198 199sub create_wrapper { 200 my $self = shift; 201 my $batchfile = $self->batchfile; 202 unless (defined($batchfile)) { 203 $self->throw("No batchfile specified, couldn't create wrapper."); 204 } 205 206 unless (-f $batchfile) { 207 # check to see if maybe this batchfile is a template batchfile 208 my $new_bf = $self->io->catfile($self->hyphy_lib_dir,"TemplateBatchFiles",$batchfile); 209 $new_bf =~ s/\"//g; 210 if (-f $new_bf) { 211 $self->batchfile($new_bf); 212 } else { 213 $self->throw ("Specified batchfile $batchfile not found."); 214 return; 215 } 216 } 217 $self->SUPER::create_wrapper('"' . $self->batchfile . '"'); 218} 219 220=head2 set_parameter 221 222Title : set_parameter 223Usage : $hyphy->set_parameter($param,$val); 224Function: Sets the named parameter $param to $val if it is a non-numeric parameter 225 If $param is a number, sets the corresponding value of the ordered redirect array (starts from 1). 226Returns : boolean if set was successful 227Args : $param => name of the parameter 228 $value => value to set the parameter to 229 230=cut 231 232 233sub set_parameter { 234 my ($self,$param,$value) = @_; 235 if ($param =~ /\d+/) { 236 $self->{'_params'}{'order'}[$param-1] = $value; 237 } else { 238 $self->{'_params'}{$param} = $value; 239 } 240 return 1; 241} 242 243=head2 batchfile 244 245Title : batchfile 246Usage : $hyphy->batchfile($bf_name); 247Function: Gets/sets the batchfile that is run by $hyphy. 248Returns : The batchfile path. 249Args : $bf_name => path of new batchfile 250 251=cut 252 253sub batchfile { 254 my ($self,$bf) = @_; 255 if (defined $bf) { 256 $self->set_parameter('bf', $bf); 257 } 258 259 if ($self->{'_params'}{'bf'}) { 260 return $self->{'_params'}{'bf'}; 261 } else { 262 $self->warn ("Batchfile was requested but no batchfile was found."); 263 } 264 return; 265} 266 267=head2 make_batchfile_with_contents 268 269Title : make_batchfile_with_contents 270Usage : $hyphy->make_batchfile_with_contents($bf_string); 271Function: Creates a temporary file with the specified string of contents for the batchfile. 272Returns : The batchfile path. 273Args : $bf_string => contents for the batchfile 274 275=cut 276 277sub make_batchfile_with_contents { 278 my ($self,$bf_string) = @_; 279 my $temp_bf = $self->io->catfile($self->tempdir,"temp.bf"); 280 open (BF, ">", $temp_bf) or $self->throw("cannot open $temp_bf for writing"); 281 print BF "$bf_string\n"; 282 close BF; 283 return $self->batchfile($temp_bf); 284} 285 286 287=head2 set_default_parameters 288 289 Title : set_default_parameters 290 Usage : $BatchFile->set_default_parameters(0); 291 Function: (Re)set the default parameters from the defaults 292 (the first value in each array in the 293 valid_values) 294 Returns : none 295 Args : boolean: keep existing parameter values 296 297 298=cut 299 300sub set_default_parameters { 301 my ($self,$keepold) = @_; 302 unless (defined $keepold) { 303 $keepold = 0; 304 } 305 my @validvals = $self->valid_values(); 306 for (my $i=0; $i< scalar (@validvals); $i++) { 307 my $elem = $validvals[$i]; 308 keys %$elem; #reset hash iterator 309 my ($param,$val) = each %$elem; 310 # skip if we want to keep old values and it is already set 311 if (ref($val)=~/ARRAY/i ) { 312 $self->{'_orderedparams'}[$i] = {$param, $val->[0]}; 313 } else { 314 $self->{'_orderedparams'}[$i] = {$param, $val}; 315 } 316 #FIXME: for alignment and treefile, this should default to the ones in params. 317 } 318} 319 3201; 321