File Coverage

blib/lib/Bio/Tools/Run/StandAloneBlastPlus.pm
Criterion Covered Total %
statement 27 418 6.4
branch 0 192 0.0
condition 0 68 0.0
subroutine 9 44 20.4
pod 13 32 40.6
total 49 754 6.5


line stmt bran cond sub pod time code
1             #
2             # BioPerl module for Bio::Tools::Run::StandAloneBlastPlus
3             #
4             # Please direct questions and support issues to
5             #
6             # Cared for by Mark A. Jensen
7             #
8             # Copyright Mark A. Jensen
9             #
10             # You may distribute this module under the same terms as perl itself
11              
12             # POD documentation - main docs before the code
13              
14             =head1 NAME
15              
16             Bio::Tools::Run::StandAloneBlastPlus - Compute with NCBI's blast+ suite *ALPHA*
17              
18             =head1 SYNOPSIS
19              
20             B: This module is related to the
21             L system in name (and inspiration)
22             only. You must use this module directly.
23              
24             # existing blastdb:
25             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
26             -db_name => 'mydb'
27             );
28            
29             # create blastdb from fasta file and attach
30             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
31             -db_name => 'mydb',
32             -db_data => 'myseqs.fas',
33             -create => 1
34             );
35            
36             # create blastdb from BioPerl sequence collection objects
37             $alnio = Bio::AlignIO->new( -file => 'alignment.msf' );
38             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
39             -db_name => 'mydb',
40             -db_data => $alnio,
41             -create => 1
42             );
43              
44             @seqs = $alnio->next_aln->each_seq;
45             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
46             -db_name => 'mydb',
47             -db_data => \@seqs,
48             -create => 1
49             );
50              
51             # create database with masks
52              
53             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
54             -db_name => 'my_masked_db',
55             -db_data => 'myseqs.fas',
56             -masker => 'dustmasker',
57             -mask_data => 'maskseqs.fas',
58             -create => 1
59             );
60              
61             # create a mask datafile separately
62             $mask_file = $fac->make_mask(
63             -data => 'maskseqs.fas',
64             -masker => 'dustmasker'
65             );
66              
67             # query database for metadata
68             $info_hash = $fac->db_info;
69             $num_seq = $fac->db_num_sequences;
70             @mask_metadata = @{ $fac->db_filter_algorithms };
71              
72             # perform blast methods
73             $result = $fac->tblastn( -query => $seqio );
74             # see Bio::Tools::Run::StandAloneBlastPlus::BlastMethods
75             # for many more details
76              
77             =head1 DESCRIPTION
78              
79             B This module requires BLAST+ v. 2.2.24+ and higher. Until the API
80             stabilizes for BLAST+, consider this module highly experimental.
81              
82             This module along with
83             L allows the user
84             to perform BLAST functions using the external program suite C
85             (available at
86             L), using
87             BioPerl objects and L facilities. This wrapper can
88             prepare BLAST databases as well as run BLAST searches. It can also be
89             used to run C programs independently.
90              
91             This module encapsulates object construction and production of
92             databases and masks. Blast analysis methods (C,
93             etc>) are contained in
94             L.
95              
96             =head1 USAGE
97              
98             The basic mantra is to (1) create a BlastPlus factory using the
99             C constructor, and (2) perform BLAST analyses by calling the
100             desired BLAST program by name off the factory object. The blast
101             database itself and any masking data are attached to the factory
102             object (step 1). Query sequences and any parameters associated with
103             particular programs are provided to the blast method call (step 2),
104             and are run against the attached database.
105              
106             =head2 Factory construction/initialization
107              
108             The factory needs to be told where the blast+ programs live. The
109             C environment variable will be checked for the default
110             executable directory. The program directory can be set for individual
111             factory instances with the C parameter. All the blast+
112             programs must be accessible from that directory (i.e., as executable
113             files or symlinks).
114              
115             Either the database or BLAST subject data must be specified at object
116             construction. Databases can be pre-existing formatted BLAST dbs, or
117             can be built directly from fasta sequence files or BioPerl sequence
118             object collections of several kinds. The key constructor parameters
119             are C, C, C.
120              
121             To specify a pre-existing BLAST database, use C alone:
122              
123             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
124             -DB_NAME => 'mydb'
125             );
126              
127             The directory can be specified along with the basename, or separately
128             with C:
129            
130             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
131             -DB_NAME => '~/home/blast/mydb'
132             );
133              
134             #same as
135              
136             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
137             -DB_NAME => 'mydb', -DB_DIR => '~/home/blast'
138             );
139              
140             To create a BLAST database de novo, see L.
141              
142             If you wish to apply pre-existing mask data (i.e., the final ASN1
143             output from one of the blast+ masker programs), to the database before
144             querying, specify it with C:
145              
146             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
147             -DB_NAME => 'mydb', -MASK_FILE => 'mymaskdata.asn'
148             );
149              
150             =head2 Creating a BLAST database
151              
152             There are several options for creating the database de novo using
153             attached data, both before and after factory construction. If a
154             temporary database (one that can be deleted by the C
155             method) is desired, leave out the C<-db_name> parameter. If
156             C<-db_name> is specified, the database will be preserved with the
157             basename specified.
158              
159             Use C<-create => 1> to create a new database (otherwise the factory
160             will look for an existing database). Use C<-overwrite => 1> to create
161             and overwrite an existing database.
162              
163             Note that the database is not created immediately on factory
164             construction. It will be created if necessary on the first use of a
165             factory BLAST method, or you can force database creation by executing
166              
167             $fac->make_db();
168              
169             =over
170              
171             =item * Specify data during construction
172              
173             With a FASTA file:
174              
175             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
176             -db_name => 'mydb',
177             -db_data => 'myseqs.fas',
178             -create => 1
179             );
180              
181             With another BioPerl object collection:
182              
183             $alnio = Bio::AlignIO->new( -file => 'alignment.msf' );
184             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
185             -db_name => 'mydb',
186             -db_data => $alnio,
187             -create => 1
188             );
189             @seqs = $alnio->next_aln->each_seq;
190             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
191             -db_name => 'mydb',
192             -db_data => \@seqs,
193             -create => 1
194             );
195              
196             Other collections (e.g., L) are valid. If a certain type
197             does not work, please submit an enhancement request.
198              
199             To create temporary databases, leave out the C<-db_name>, e.g.
200              
201             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
202             -db_data => 'myseqs.fas',
203             -create => 1
204             );
205              
206             To get the tempfile basename, do:
207              
208             $dbname = $fac->db;
209              
210             =item * Specify data post-construction
211              
212             Use the explicit attribute setters:
213              
214             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
215             -create => 1
216             );
217              
218             $fac->set_db_data('myseqs.fas');
219             $fac->make_db;
220              
221             =back
222              
223             =head2 Creating and using mask data
224              
225             The blast+ mask utilities C, C, and
226             C are available. Masking can be rolled into database
227             creation, or can be executed later. If your mask data is already
228             created and in ASN1 format, set the C<-mask_file> attribute on
229             construction (see L).
230              
231             To create a mask from raw data or an existing database and apply the
232             mask upon database creation, construct the factory like so:
233              
234             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
235             -db_name => 'my_masked_db',
236             -db_data => 'myseqs.fas',
237             -masker => 'dustmasker',
238             -mask_data => 'maskseqs.fas',
239             -create => 1
240             );
241              
242             The masked database will be created during C.
243              
244             The C<-mask_data> parameter can be a FASTA filename or any BioPerl
245             sequence object collection. If the datatype ('nucl' or 'prot') of the
246             mask data is not compatible with the selected masker, an exception
247             will be thrown with a message to that effect.
248              
249             To create a mask ASN1 file that can be used in the C<-mask_file>
250             parameter separately from the attached database, use the
251             C method directly:
252              
253             $mask_file = $fac->make_mask(-data => 'maskseqs.fas',
254             -masker => 'dustmasker');
255             # segmasker can use a blastdb as input
256             $mask_file = $fac->make_mask(-mask_db => 'mydb',
257             -masker => 'segmasker')
258              
259             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
260             -db_name => 'my_masked_db',
261             -db_data => 'myseqs.fas',
262             -mask_file => $mask_file
263             -create => 1
264             );
265              
266             =head2 Getting database information
267              
268             To get a hash containing useful metadata on an existing database
269             (obtained by running C, use C:
270            
271             # get info on the attached database..
272             $info = $fac->db_info;
273             # get info on another database
274             $info = $fac->db_info('~/home/blastdbs/another');
275              
276             To get a particular info element for the attached database, just call
277             the element name off the factory:
278              
279             $num_seqs = $fac->db_num_sequences;
280             # info on all the masks applied to the db, if any:
281             @masking_info = @{ $fac->db_filter_algorithms };
282              
283             =head2 Accessing the L factory
284              
285             The blast+ programs are actually executed by a
286             L wrapper instance. This instance is
287             available for peeking and poking in the L
288             C attribute. For convenience, C methods can be
289             run from the C object, and are delegated to the
290             C attribute. For example, to get the blast+ program to be
291             executed, examine either
292              
293             $fac->factory->command
294              
295             or
296              
297             $fac->command
298              
299             Similarly, the current parameters for the C factory are
300              
301             @parameters = $fac->get_parameters
302              
303             =head2 Cleaning up temp files
304              
305             Temporary analysis files produced under a single factory instances can
306             be unlinked by running
307              
308             $fac->cleanup;
309              
310             Tempfiles are generally not removed unless this method is explicitly
311             called. C only unlinks "registered" files and
312             databases. All temporary files are automatically registered; in
313             particular, "anonymous" databases (such as
314              
315             $fac->Bio::Tools::Run::StandAloneBlastPlus->new(
316             -db_data => 'myseqs.fas',
317             -create => 1
318             );
319              
320             without a C<-db_name> specification) are registered for cleanup. Any
321             file or database can be registered with an internal method:
322              
323             $fac->_register_temp_for_cleanup('testdb');
324              
325             =head2 Other Goodies
326              
327             =over
328              
329             =item
330              
331             You can check whether a given basename points to a properly formatted
332             BLAST database by doing
333              
334             $is_good = $fac->check_db('putative_db');
335              
336             =item
337              
338             User parameters can be passed to the underlying blast+ programs (if
339             you know what you're doing) with C and C:
340              
341             $fac = Bio::Tools::Run::StandAloneBlastPlus->new(
342             -db_name => 'customdb',
343             -db_data => 'myseqs.fas',
344             -db_make_args => [ '-taxid_map' => 'seq_to_taxa.txt' ],
345             -masker => 'windowmasker',
346             -mask_data => 'myseqs.fas',
347             -mask_make_args => [ '-dust' => 'T' ],
348             -create => 1
349             );
350              
351             =item
352              
353             You can prevent exceptions from being thrown by failed blast+ program
354             executions by setting C. Examine the error with
355             C:
356              
357             $fac->no_throw_on_crash(1);
358             $fac->make_db;
359             if ($fac->stderr =~ /Error:/) {
360             #handle error
361             ...
362             }
363              
364             =back
365              
366             =head1 SEE ALSO
367              
368             L,
369             L
370              
371             =head1 FEEDBACK
372              
373             =head2 Mailing Lists
374              
375             User feedback is an integral part of the evolution of this and other
376             Bioperl modules. Send your comments and suggestions preferably to
377             the Bioperl mailing list. Your participation is much appreciated.
378              
379             bioperl-l@bioperl.org - General discussion
380             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
381              
382             =head2 Support
383              
384             Please direct usage questions or support issues to the mailing list:
385              
386             L
387              
388             rather than to the module maintainer directly. Many experienced and
389             reponsive experts will be able look at the problem and quickly
390             address it. Please include a thorough description of the problem
391             with code and data examples if at all possible.
392              
393             =head2 Reporting Bugs
394              
395             Report bugs to the Bioperl bug tracking system to help us keep track
396             of the bugs and their resolution. Bug reports can be submitted via
397             the web:
398              
399             http://redmine.open-bio.org/projects/bioperl/
400              
401             =head1 AUTHOR - Mark A. Jensen
402              
403             Email maj -at- fortinbras -dot- us
404              
405             =head1 CONTRIBUTORS
406              
407             =head1 APPENDIX
408              
409             The rest of the documentation details each of the object methods.
410             Internal methods are usually preceded with a _
411              
412             =cut
413              
414             # Let the code begin...
415              
416              
417             package Bio::Tools::Run::StandAloneBlastPlus;
418 1     1   776 use strict;
  1         2  
  1         38  
419             our $AUTOLOAD;
420              
421             # Object preamble - inherits from Bio::Root::Root
422              
423 1     1   5 use lib '../../..';
  1         2  
  1         3  
424 1     1   98 use Bio::Root::Root;
  1         2  
  1         21  
425 1     1   4 use Bio::SeqIO;
  1         1  
  1         19  
426 1     1   4 use Bio::Tools::GuessSeqFormat;
  1         1  
  1         16  
427 1     1   426 use Bio::Tools::Run::StandAloneBlastPlus::BlastMethods;
  1         3  
  1         27  
428 1     1   6 use File::Temp 0.22;
  1         23  
  1         51  
429 1     1   387 use IO::String;
  1         1868  
  1         33  
430              
431 1     1   6 use base qw(Bio::Root::Root);
  1         3  
  1         3517  
432             unless ( eval "require Bio::Tools::Run::BlastPlus" ) {
433             Bio::Root::Root->throw("This module requires 'Bio::Tools::Run::BlastPlus'");
434             }
435              
436             my %AVAILABLE_MASKERS = (
437             'windowmasker' => 'nucl',
438             'dustmasker' => 'nucl',
439             'segmasker' => 'prot'
440             );
441              
442             # NOTE: After testing all possible output formats, only 'maskinfo_asn1_text'
443             # is currently working correctly as input for makeblastdb '-mask_data' argument,
444             # the others return an 'Unknown encoding for mask data' error
445             my %MASKER_ENCODING = (
446             'windowmasker' => 'maskinfo_asn1_text',
447             'dustmasker' => 'maskinfo_asn1_text',
448             'segmasker' => 'maskinfo_asn1_text'
449             );
450            
451             my $bp_class = 'Bio::Tools::Run::BlastPlus';
452              
453             # what's the desire here?
454             #
455             # * factory object (created by new())
456             # - points to some blast db entity, so all functions run off the
457             # the factory (except bl2seq?) use the associated db
458             #
459             # * create a blast formatted database:
460             # - specify a file, or an AlignI object
461             # - store for later, or store in a tempfile to throw away
462             # - object should store its own database pointer
463             # - provide masking options based on the maskers provided
464             #
465             # * perform database actions via db-oriented blast+ commands
466             # via the object
467             #
468             # * perform blast searches against the database
469             # - blastx, blastp, blastn, tblastx, tblastn
470             # - specify Bio::Seq objects or files as queries
471             # - output the results as a file or as a Bio::Search::Result::BlastResult
472             # * perform 'special' (i.e., ones I don't know) searches
473             # - psiblast, megablast, rpsblast, rpstblastn
474             # some of these are "tasks" under particular programs
475             # check out psiblast, why special (special 'iteration' handling in
476             # ...::BlastResult)
477             # check out rpsblast, megablast
478             #
479             # * perform bl2seq
480             # - return the alignment directly as a convenience, using Bio::Search
481             # functions
482              
483             # lazy db formatting: makeblastdb only on first blast request...
484             # ParameterBaseI delegation : use AUTOLOAD
485             #
486             #
487              
488             =head2 new
489              
490             Title : new
491             Usage : my $obj = new Bio::Tools::Run::StandAloneBlastPlus();
492             Function: Builds a new Bio::Tools::Run::StandAloneBlastPlus object
493             Returns : an instance of Bio::Tools::Run::StandAloneBlastPlus
494             Args : named argument (key => value) pairs:
495             -db : blastdb name
496              
497             =cut
498              
499             sub new {
500 0     0 1   my ($class,@args) = @_;
501 0           my $self = $class->SUPER::new(@args);
502 0           my ($db_name, $db_data, $db_dir, $db_make_args,
503             $mask_file, $mask_data, $mask_make_args, $masker,
504             $create, $overwrite, $is_remote, $prog_dir, $program_dir)
505             = $self->_rearrange([qw(
506             DB_NAME
507             DB_DATA
508             DB_DIR
509             DB_MAKE_ARGS
510             MASK_FILE
511             MASK_DATA
512             MASK_MAKE_ARGS
513             MASKER
514             CREATE
515             OVERWRITE
516             REMOTE
517             PROG_DIR
518             PROGRAM_DIR
519             )], @args);
520              
521             # parm taint checks
522 0 0         if ($db_name) {
523 0 0         $self->throw("DB name contains invalid characters") unless $db_name =~ m{^[a-z0-9_/:.+-]+$}i;
524             }
525              
526 0 0         if ( $db_dir ) {
527 0 0         $self->throw("DB directory (DB_DIR) not found") unless (-d $db_dir);
528 0           $self->{'_db_dir'} = $db_dir;
529             }
530             else {
531 0           $self->{'_db_dir'} = '.';
532             }
533 0   0       $program_dir ||= $prog_dir; # alias
534             # now handle these systematically (bug #3003)
535             # allow db_name to include path info
536             # let db_dir act as root if present and db_name is a relative path
537             # db property contains the pathless name only
538 0 0         if ($db_name) {
539 0           my ($v,$d,$f) = File::Spec->splitpath($db_name);
540 0 0         $self->throw("No DB name at the end of path '$db_name'") unless $f;
541 0           $f =~ s/\..*$//; # tolerant of extensions, but ignore them
542 0           $self->{_db} = $f;
543             # now establish db_path property as the internal authority on
544             # db location...
545 0 0         if ( File::Spec->file_name_is_absolute($db_name) ) {
546 0 0 0       $self->throw("Path specified in DB name ('$d') does not exist") unless !$d || (-d $d);
547 0           $self->{_db_path} = File::Spec->catfile($d,$f);
548 0           $self->{_db_dir} = $d;
549             # ignore $db_dir, give heads-up
550 0 0         $self->warn("DB name is an absolute path; setting db_dir to '".$self->db_dir."'") if $db_dir;
551             }
552             else {
553 0           $d = File::Spec->catdir($self->db_dir, $d);
554 0 0 0       $self->throw("Path specified by DB_DIR+DB_NAME ('$d') does not exist") unless !$d || (-d $d);
555 0           $self->{_db_path} = File::Spec->catfile($d,$f);
556             }
557             }
558            
559 0 0         if ($masker) {
560 0 0         $self->throw("Masker '$masker' not available") unless
561             grep /^$masker$/, keys %AVAILABLE_MASKERS;
562 0           $self->{_masker} = $masker;
563             }
564            
565 0 0         if ($program_dir) {
    0          
566 0 0         $self->throw("Can't find program directory '$program_dir'") unless
567             -d $program_dir;
568 0           $self->{_program_dir} = $program_dir;
569             }
570             elsif ($ENV{BLASTPLUSDIR}) {
571 0           $self->{_program_dir} = $ENV{BLASTPLUSDIR};
572             }
573             $Bio::Tools::Run::BlastPlus::program_dir = $self->{_program_dir} ||
574 0   0       $Bio::Tools::Run::BlastPlus::program_dir;
575            
576              
577 0 0         $self->set_db_make_args( $db_make_args) if ( $db_make_args );
578 0 0         $self->set_mask_make_args( $mask_make_args) if ($mask_make_args);
579 0           $self->{'_create'} = $create;
580 0           $self->{'_overwrite'} = $overwrite;
581 0           $self->{'_is_remote'} = $is_remote;
582 0           $self->{'_db_data'} = $db_data;
583            
584 0           $self->{'_mask_file'} = $mask_file;
585 0           $self->{'_mask_data'} = $mask_data;
586              
587              
588             # check db
589 0 0 0       if (defined $self->check_db and $self->check_db == 0 and !$self->is_remote) {
      0        
590 0 0 0       $self->throw("DB '".$self->db."' can't be found. To create, set -create => 1.") unless ($create || $overwrite);
591             }
592 0 0         if (!$self->db) {
593             # allow this to pass; catch lazily at make_db...
594 0 0         if (!$self->db_data) {
595 0           $self->debug('No database or db data specified. '.
596             'To create a new database, provide '.
597             '-db_data => [fasta|\@seqs|$seqio_object]')
598             }
599              
600             # no db specified; create temp db
601 0           $self->{_create} = 1;
602 0 0         if ($self->db_dir) {
603 0           my $fh = File::Temp->new(TEMPLATE => 'DBXXXXX',
604             DIR => $self->db_dir,
605             UNLINK => 1);
606 0           my ($v,$d,$f) = File::Spec->splitpath($fh->filename);
607 0           $self->{_db} = $f;
608 0           $self->{_db_path} = $fh->filename;
609 0           $self->_register_temp_for_cleanup($self->db_path);
610 0           $fh->close;
611             }
612             else {
613 0           $self->{_db_dir} = File::Temp->newdir('DBDXXXXX');
614 0           $self->{_db} = 'DBTEMP';
615 0           $self->{_db_path} = File::Spec->catfile($self->db_dir,
616             $self->db);
617             }
618             }
619              
620 0           return $self;
621             }
622              
623             =head2 db()
624              
625             Title : db
626             Usage : $obj->db($newval)
627             Function: contains the basename of the local blast database
628             Example :
629             Returns : value of db (a scalar string)
630             Args : readonly
631              
632             =cut
633              
634 0     0 1   sub db { shift->{_db} }
635 0     0 0   sub db_name { shift->{_db} }
636 0     0 0   sub set_db_name { shift->{_db} = shift }
637 0     0 0   sub db_dir { shift->{_db_dir} }
638 0     0 0   sub set_db_dir { shift->{_db_dir} = shift }
639 0     0 0   sub db_path { shift->{_db_path} }
640 0     0 0   sub db_data { shift->{_db_data} }
641 0     0 0   sub set_db_data { shift->{_db_data} = shift }
642 0     0 0   sub db_type { shift->{_db_type} }
643 0     0 0   sub masker { shift->{_masker} }
644 0     0 0   sub set_masker { shift->{_masker} = shift }
645 0     0 0   sub mask_file { shift->{_mask_file} }
646 0     0 0   sub set_mask_file { shift->{_mask_file} = shift }
647 0     0 0   sub mask_data { shift->{_mask_data} }
648 0     0 0   sub set_mask_data { shift->{_mask_data} = shift }
649              
650             =head2 factory()
651              
652             Title : factory
653             Usage : $obj->factory($newval)
654             Function: attribute containing the Bio::Tools::Run::BlastPlus
655             factory
656             Example :
657             Returns : value of factory (Bio::Tools::Run::BlastPlus object)
658             Args : readonly
659              
660             =cut
661              
662 0     0 1   sub factory { shift->{_factory} }
663 0     0 0   sub create { shift->{_create} }
664 0     0 0   sub overwrite { shift->{_overwrite} }
665 0     0 0   sub is_remote { shift->{_is_remote} }
666              
667             =head2 program_version()
668              
669             Title : program_version
670             Usage : $version = $bedtools_fac->program_version()
671             Function: Returns the program version (if available)
672             Returns : string representing location and version of the program
673             Note : this works around the WrapperBase::version() method conflicting with
674             the -version parameter for SABlast (good argument for not having
675             getter/setters for these)
676              
677             =cut
678              
679             =head2 package_version()
680              
681             Title : package_version
682             Usage : $version = $bedtools_fac->package_version()
683             Function: Returns the BLAST+ package version (if available)
684             Returns : string representing BLAST+ package version (may differ from version())
685              
686             =cut
687              
688             sub program_version {
689 0     0 1   my $self = shift;
690 0           my $fac = $self->factory;
691 0 0         $fac->program_version(@_) if $fac;
692             }
693              
694             sub package_version {
695 0     0 1   my $self = shift;
696 0           my $fac = $self->factory;
697 0 0         $fac->package_version(@_) if $fac;
698             }
699              
700             =head1 DB methods
701              
702             =head2 make_db()
703              
704             Title : make_db
705             Usage :
706             Function: create the blast database (if necessary),
707             imposing masking if specified
708             Returns : true on success
709             Args :
710              
711             =cut
712              
713             # should also provide facility for creating subdatabases from
714             # existing databases (i.e., another format for $data: the name of an
715             # existing blastdb...)
716             sub make_db {
717 0     0 1   my $self = shift;
718 0           my @args = @_;
719 0 0 0       return 1 if ( $self->check_db && !$self->overwrite ); # already there or force make
720              
721 0 0         $self->throw('No database or db data specified. '.
722             'To create a new database, provide '.
723             '-db_data => [fasta|\@seqs|$seqio_object]')
724             unless $self->db_data;
725             # db_data can be: fasta file, array of seqs, Bio::SeqIO object
726 0           my $data = $self->db_data;
727 0           $data = $self->_fastize($data);
728 0           my $testio = Bio::SeqIO->new(-file=>$data, -format=>'fasta');
729 0 0         $self->{_db_type} = ($testio->next_seq->alphabet =~ /.na/) ? 'nucl' : 'prot';
730 0           $testio->close;
731              
732 0           my ($v,$d,$name) = File::Spec->splitpath($data);
733 0           $name =~ s/\.fas$//;
734 0   0       $self->{_db} ||= $name;
735 0           $self->{_db_path} = File::Spec->catfile($self->db_dir,$self->db);
736             # <#######[
737             # deal with creating masks here,
738             # and provide correct parameters to the
739             # makeblastdb ...
740            
741             # accomodate $self->db_make_args here -- allow them
742             # to override defaults, or allow only those args
743             # that are not specified here?
744 0   0       my $usr_db_args ||= $self->db_make_args;
745 0 0         my %usr_args = @$usr_db_args if $usr_db_args;
746              
747 0           my %db_args = (
748             -in => $data,
749             -dbtype => $self->db_type,
750             -out => $self->db_path,
751             -title => $self->db,
752             -parse_seqids => 1 # necessary for masking
753             );
754             # usr arg override
755 0 0         if (%usr_args) {
756 0           $db_args{$_} = $usr_args{$_} for keys %usr_args;
757             }
758              
759             # do masking if requested
760             # if the (masker and mask_data) OR mask_file attributes of this
761             # object are set, assume that masking is desired
762             #
763 0 0 0       if ($self->mask_file) { # the actual masking data is provided
    0          
764 0           $db_args{'-mask_data'} = $self->mask_file;
765             }
766             elsif ($self->masker && $self->mask_data) { # build the mask
767 0           $db_args{'-mask_data'} = $self->make_mask(-data => $self->mask_data);
768             $self->throw("Masker error: message is '".$self->stderr."'") unless
769 0 0         $db_args{'-mask_data'};
770 0           $self->{_mask_data} = $db_args{'-mask_data'};
771             }
772              
773 0           $self->{_factory} = $bp_class->new(
774             -command => 'makeblastdb',
775             %db_args
776             );
777 0           $self->factory->no_throw_on_crash($self->no_throw_on_crash);
778 0           return $self->factory->_run;
779             }
780              
781             =head2 make_mask()
782              
783             Title : make_mask
784             Usage :
785             Function: create masking data based on specified parameters
786             Returns : mask data filename (scalar string)
787             Args :
788              
789             =cut
790              
791             # mask program usage (based on blast+ manual)
792             #
793             # program dbtype opn
794             # windowmasker nucl mask overrep data, low-complexity (optional)
795             # dustmasker nucl mask low-complexity
796             # segmasker prot
797              
798             sub make_mask {
799 0     0 1   my $self = shift;
800 0           my @args = @_;
801 0           my ($data, $mask_db, $make_args, $masker) = $self->_rearrange([qw(
802             DATA
803             MASK_DB
804             MAKE_ARGS
805             MASKER)], @args);
806 0           my (%mask_args,%usr_args,$db_type);
807 0           my $infmt = 'fasta';
808 0 0         $self->throw("make_mask requires -data argument") unless $data;
809 0   0       $masker ||= $self->masker;
810 0 0         $self->throw("no masker specified and no masker default set in object")
811             unless $masker;
812 0   0       my $usr_make_args ||= $self->mask_make_args;
813 0 0         %usr_args = @$usr_make_args if $usr_make_args;
814 0 0         unless (grep /^$masker$/, keys %AVAILABLE_MASKERS) {
815 0           $self->throw("Masker '$masker' not available");
816             }
817 0 0         if ($self->check_db($data)) {
818 0 0         unless ($masker eq 'segmasker') {
819 0           $self->throw("Masker '$masker' can't use a blastdb as primary input");
820             }
821 0 0         unless ($self->db_info($data)->{_db_type} eq
822             $AVAILABLE_MASKERS{$masker}) {
823 0           $self->throw("Masker '$masker' is incompatible with input db sequence type");
824             }
825 0           $infmt = 'blastdb';
826             }
827             else {
828 0           $data = $self->_fastize($data);
829 0           my $sio = Bio::SeqIO->new(-file=>$data);
830 0           my $s = $sio->next_seq;
831 0           my $type;
832 0 0         if ($s->alphabet =~ /.na/) {
    0          
833 0           $type = 'nucl';
834             }
835             elsif ($s->alphabet =~ /protein/) {
836 0           $type = 'prot';
837             }
838             else {
839 0           $type = 'UNK';
840             }
841 0 0         unless ($type eq $AVAILABLE_MASKERS{$masker}) {
842 0           $self->throw("Masker '$masker' is incompatible with sequence type '$type'");
843             }
844             }
845            
846             # check that sequence type and masker program match:
847            
848             # now, need to provide reasonable default masker arg settings,
849             # and override these with $usr_make_args as necessary and appropriate
850 0           my $mh = File::Temp->new(TEMPLATE=>'MSKXXXXX',
851             UNLINK => 0,
852             DIR => $self->db_dir);
853 0           my $mask_outfile = $mh->filename;
854 0           $mh->close;
855 0           $self->_register_temp_for_cleanup(File::Spec->catfile($self->db_dir,$mask_outfile));
856              
857             # NOTE: '-outfmt' argument must not be included in the default args because
858             # it conflicts with windowmasker '-mk_counts' argument
859 0           %mask_args = (
860             -in => $data,
861             -parse_seqids => 1,
862             );
863             # usr arg override
864 0 0         if (%usr_args) {
865 0           $mask_args{$_} = $usr_args{$_} for keys %usr_args;
866             }
867             # masker-specific pipelines
868 0           my $status;
869 0           for ($masker) {
870 0 0         m/dustmasker/ && do {
871 0           $mask_args{'-out'} = $mask_outfile;
872 0           $mask_args{'-outfmt'} = $MASKER_ENCODING{$masker};
873 0           $self->{_factory} = $bp_class->new(-command => $masker,
874             %mask_args);
875 0           $self->factory->no_throw_on_crash($self->no_throw_on_crash);
876 0           $status = $self->factory->_run;
877 0           last;
878             };
879 0 0         m/windowmasker/ && do {
880             # check mask_db if present
881 0 0         if ($mask_db) {
882 0 0         unless ($self->check_db($mask_db)) {
883 0           $self->throw("Mask database '$mask_db' is not present or valid");
884             }
885             }
886 0           my $cth = File::Temp->new(TEMPLATE=>'MCTXXXXX',
887             DIR => $self->db_dir);
888 0           my $ct_file = $cth->filename;
889 0           $cth->close;
890 0           $mask_args{'-out'} = $ct_file;
891 0           $mask_args{'-mk_counts'} = 'true';
892 0           $self->{_factory} = $bp_class->new(-command => $masker,
893             %mask_args);
894 0           $self->factory->no_throw_on_crash($self->no_throw_on_crash);
895 0           $status = $self->factory->_run;
896 0 0         last unless $status;
897 0           delete $mask_args{'-mk_counts'};
898 0           $mask_args{'-ustat'} = $ct_file;
899 0           $mask_args{'-out'} = $mask_outfile;
900 0           $mask_args{'-outfmt'} = $MASKER_ENCODING{$masker};
901 0 0         if ($mask_db) {
902 0           $mask_args{'-in'} = $mask_db;
903 0           $mask_args{'-infmt'} = 'blastdb';
904             }
905 0           $self->factory->reset_parameters(%mask_args);
906 0           $self->factory->no_throw_on_crash($self->no_throw_on_crash);
907 0           $status = $self->factory->_run;
908 0           last;
909             };
910 0 0         m/segmasker/ && do {
911 0           $mask_args{'-infmt'} = $infmt;
912 0           $mask_args{'-out'} = $mask_outfile;
913 0           $mask_args{'-outfmt'} = $MASKER_ENCODING{$masker};
914 0           $self->{_factory} = $bp_class->new(-command => $masker,
915             %mask_args);
916 0           $self->factory->no_throw_on_crash($self->no_throw_on_crash);
917 0           $status = $self->factory->_run;
918 0           last;
919             };
920 0           do {
921 0           $self->throw("Masker program '$masker' not recognized");
922             };
923             }
924 0 0         return $status ? $mask_outfile : $status;
925             }
926              
927             =head2 db_info()
928              
929             Title : db_info
930             Usage :
931             Function: get info for database
932             (via blastdbcmd -info); add factory attributes
933             Returns : hash of database attributes
934             Args : [optional] db name (scalar string) (default: currently attached db)
935              
936             =cut
937              
938             sub db_info {
939 0     0 1   my $self = shift;
940 0           my $db = shift;
941 0   0       $db ||= $self->db_path;
942 0 0         unless ($db) {
943 0           $self->warn("db_info: db not specified and no db attached");
944 0           return;
945             }
946 0 0         if ($self->is_remote) {
947 0           $self->warn("db_info: sorry, can't get info for remote database (complain to NCBI)");
948 0           return;
949             }
950 0 0 0       if ($db eq $self->db and $self->{_db_info}) {
951 0           return $self->{_db_info}; # memoized
952             }
953 0           my $db_info_text;
954 0           $self->{_factory} = $bp_class->new( -command => 'blastdbcmd',
955             -info => 1,
956             -db => $db );
957 0           $self->factory->no_throw_on_crash(1);
958 0           $self->factory->_run();
959 0           $self->factory->no_throw_on_crash(0);
960 0 0         if ($self->factory->stderr =~ /No alias or index file found/) {
961 0           $self->warn("db_info: Couldn't find database ".$self->db."; make with make_db()");
962 0           return;
963             }
964 0           $db_info_text = $self->factory->stdout;
965             # parse info into attributes
966 0           my $infh = IO::String->new($db_info_text);
967 0           my %attr;
968 0           while (<$infh>) {
969 0 0         /Database: (.*)/ && do {
970 0           $attr{db_info_name} = $1;
971 0           next;
972             };
973 0 0         /([0-9,]+) sequences; ([0-9,]+) total/ && do {
974 0           $attr{db_num_sequences} = $1;
975 0           $attr{db_total_bases} = $2;
976 0           $attr{db_num_sequences} =~ s/,//g;
977 0           $attr{db_total_bases} =~ s/,//g;
978 0           next;
979             };
980 0 0         /Date: (.*?)\s+Longest sequence: ([0-9,]+)/ && do {
981 0           $attr{db_date} = $1; # convert to more usable date object
982 0           $attr{db_longest_sequence} = $2;
983 0           $attr{db_longest_sequence} =~ s/,//g;
984 0           next;
985             };
986 0 0         /Algorithm ID/ && do {
987 0           my $alg = $attr{db_filter_algorithms} = [];
988 0           while (<$infh>) {
989 0 0         if (/\s*([0-9]+)\s+([a-z0-9_]+)\s+(.*)/i) {
990 0           my ($alg_id, $alg_name, $alg_opts) = ($1, $2, $3);
991 0           $alg_opts =~ s/\s+$//;
992 0           push @$alg, { algorithm_id => $alg_id,
993             algorithm_name => $alg_name,
994             algorithm_opts => $alg_opts };
995             }
996             else {
997 0           last;
998             }
999             }
1000 0           next;
1001             };
1002             }
1003             # get db type
1004 0 0         if ( -e $db.'.psq' ) {
    0          
1005 0           $attr{_db_type} = 'prot';
1006             }
1007             elsif (-e $db.'.nsq') {
1008 0           $attr{_db_type} = 'nucl';
1009             }
1010             else {
1011 0           $attr{_db_type} = 'UNK'; # bork
1012             }
1013 0 0         if ($db eq $self->db) {
1014 0           $self->{_db_type} = $attr{_db_type};
1015 0           $self->{_db_info_text} = $db_info_text;
1016 0           $self->{_db_info} = \%attr;
1017             }
1018 0           return \%attr;
1019             }
1020              
1021             =head2 set_db_make_args()
1022              
1023             Title : set_db_make_args
1024             Usage :
1025             Function: set the DB make arguments attribute
1026             with checking
1027             Returns : true on success
1028             Args : arrayref or hashref of named arguments
1029              
1030             =cut
1031              
1032             sub set_db_make_args {
1033 0     0 1   my $self = shift;
1034 0           my $args = shift;
1035 0 0         $self->throw("Arrayref or hashref required at DB_MAKE_ARGS") unless
1036             ref($args) =~ /^ARRAY|HASH$/;
1037 0 0         if (ref($args) eq 'HASH') {
1038 0           my @a = %$args;
1039 0           $args = \@a;
1040             }
1041 0 0         $self->throw("Named args required for DB_MAKE_ARGS") unless !(@$args % 2);
1042 0           $self->{'_db_make_args'} = $args;
1043 0           return 1;
1044             }
1045              
1046 0     0 0   sub db_make_args { shift->{_db_make_args} }
1047              
1048             =head2 set_mask_make_args()
1049              
1050             Title : set_mask_make_args
1051             Usage :
1052             Function: set the masker make arguments attribute
1053             with checking
1054             Returns : true on success
1055             Args : arrayref or hasref of named arguments
1056              
1057             =cut
1058              
1059             sub set_mask_make_args {
1060 0     0 1   my $self = shift;
1061 0           my $args = shift;
1062 0 0         $self->throw("Arrayref or hashref required at MASK_MAKE_ARGS") unless
1063             ref($args) =~ /^ARRAY|HASH$/;
1064 0 0         if (ref($args) eq 'HASH') {
1065 0           my @a = %$args;
1066 0           $args = \@a;
1067             }
1068 0 0         $self->throw("Named args required at MASK_MAKE_ARGS") unless !(@$args % 2);
1069 0           $self->{'_mask_make_args'} = $args;
1070 0           return 1;
1071             }
1072              
1073 0     0 0   sub mask_make_args { shift->{_mask_make_args} }
1074              
1075             =head2 check_db()
1076              
1077             Title : check_db
1078             Usage :
1079             Function: determine if database with registered name and dir
1080             exists
1081             Returns : 1 if db present, 0 if not present, undef if name/dir not
1082             set
1083             Args : [optional] db name (default is 'registered' name in $self->db)
1084             [optional] db directory (default is 'registered' dir in
1085             $self->db_dir)
1086              
1087             =cut
1088              
1089             sub check_db {
1090 0     0 1   my $self = shift;
1091 0           my ($db) = @_;
1092 0           my $db_path;
1093 0 0         if ($db) {
1094 0           my ($v,$d,$f) = File::Spec->splitpath($db);
1095 0           $f =~ s/\..*$//; # ignore extensions
1096 0   0       $db_path = File::Spec->catfile($d||'.',$f);
1097             }
1098             else {
1099 0           $db_path = $self->db_path;
1100             }
1101 0 0         if ( $db_path ) {
1102 0           $self->{_factory} = $bp_class->new( -command => 'blastdbcmd',
1103             -info => 1,
1104             -db => $db_path );
1105             # $DB::single=1;
1106 0           $self->factory->no_throw_on_crash(1);
1107 0           $self->factory->_run();
1108 0           $self->factory->no_throw_on_crash(0);
1109 0 0         return 0 if ($self->factory->stderr =~ /No alias or index file found/);
1110 0           return 1;
1111             }
1112 0           return;
1113             }
1114              
1115             =head2 no_throw_on_crash()
1116              
1117             Title : no_throw_on_crash
1118             Usage : $fac->no_throw_on_crash($newval)
1119             Function: set to prevent an exeception throw on a failed
1120             blast program execution
1121             Example :
1122             Returns : value of no_throw_on_crash (boolean)
1123             Args : on set, new value (boolean)
1124              
1125             =cut
1126              
1127             sub no_throw_on_crash {
1128 0     0 1   my $self = shift;
1129            
1130 0 0         return $self->{'no_throw_on_crash'} = shift if @_;
1131 0           return $self->{'no_throw_on_crash'};
1132             }
1133              
1134              
1135             =head1 Internals
1136              
1137             =head2 _fastize()
1138              
1139             Title : _fastize
1140             Usage :
1141             Function: convert a sequence collection to a temporary
1142             fasta file (sans gaps)
1143             Returns : fasta filename (scalar string)
1144             Args : sequence collection
1145              
1146             =cut
1147              
1148             sub _fastize {
1149 0     0     my $self = shift;
1150 0           my $data = shift;
1151 0           for ($data) {
1152 0 0         !ref && do {
1153             # suppose a fasta file name
1154 0 0         $self->throw('Sequence file not found') unless -e $data;
1155 0           my $guesser = Bio::Tools::GuessSeqFormat->new(-file => $data);
1156 0 0         $self->throw('Sequence file not in FASTA format') unless
1157             $guesser->guess eq 'fasta';
1158 0           last;
1159             };
1160             (ref eq 'ARRAY') && (ref $$data[0]) &&
1161             ($$data[0]->isa('Bio::Seq') || $$data[0]->isa('Bio::PrimarySeq'))
1162 0 0 0       && do {
      0        
      0        
1163 0           my $fh = File::Temp->new(TEMPLATE => 'DBDXXXXX',
1164             UNLINK => 0,
1165             DIR => $self->db_dir,
1166             SUFFIX => '.fas');
1167 0           my $fname = $fh->filename;
1168 0           $fh->close;
1169 0           $self->_register_temp_for_cleanup($fname);
1170 0 0         my $fasio = Bio::SeqIO->new(-file=>">$fname", -format=>"fasta")
1171             or $self->throw("Can't create temp fasta file");
1172 0           for (@$data) {
1173 0           my $s = $_->seq;
1174 0           my $a = $_->alphabet;
1175 0           $s =~ s/[$Bio::PrimarySeq::GAP_SYMBOLS]//g;
1176 0           $_->seq( $s );
1177 0           $_->alphabet($a);
1178 0           $fasio->write_seq($_);
1179             }
1180 0           $fasio->close;
1181 0           $data = $fname;
1182 0           last;
1183             };
1184 0 0         ref && do { # some kind of object
1185 0           my ($fmt) = ref($data) =~ /.*::(.*)/;
1186 0 0         if ($fmt eq 'fasta') {
1187 0           $data = $data->file; # use the fasta file directly
1188             }
1189             else {
1190             # convert
1191 0           my $fh = File::Temp->new(TEMPLATE => 'DBDXXXXX',
1192             UNLINK => 0,
1193             DIR => $self->db_dir,
1194             SUFFIX => '.fas');
1195 0           my $fname = $fh->filename;
1196 0           $fh->close;
1197 0           $self->_register_temp_for_cleanup($fname);
1198 0 0         my $fasio = Bio::SeqIO->new(-file=>">$fname", -format=>"fasta")
1199             or $self->throw("Can't create temp fasta file");
1200 0           require Bio::PrimarySeq;
1201 0 0 0       if ($data->isa('Bio::AlignIO')) {
    0          
    0          
    0          
1202 0           my $aln = $data->next_aln;
1203 0           for ($aln->each_seq) {
1204             # must de-gap
1205 0           my $s = $_->seq;
1206 0           my $a = $_->alphabet;
1207 0           $s =~ s/[$Bio::PrimarySeq::GAP_SYMBOLS]//g;
1208 0           $_->seq( $s );
1209 0           $_->alphabet($a);
1210 0           $fasio->write_seq($_)
1211             }
1212             }
1213             elsif ($data->isa('Bio::SeqIO')) {
1214 0           while (local $_ = $data->next_seq) {
1215 0           my $s = $_->seq;
1216 0           my $a = $_->alphabet;
1217 0           $s =~ s/[$Bio::PrimarySeq::GAP_SYMBOLS]//g;
1218 0           $_->seq( $s );
1219 0           $_->alphabet($a);
1220 0           $fasio->write_seq($_);
1221             }
1222             }
1223             elsif ($data->isa('Bio::Align::AlignI')) {
1224 0           for( $data->each_seq) {
1225 0           my $s = $_->seq;
1226 0           my $a = $_->alphabet;
1227 0           $s =~ s/[$Bio::PrimarySeq::GAP_SYMBOLS]//g;
1228 0           $_->seq( $s );
1229 0           $_->alphabet($a);
1230 0           $fasio->write_seq($_)
1231             }
1232             }
1233             elsif ($data->isa('Bio::Seq') || $data->isa('Bio::PrimarySeq')) {
1234 0           my $s = $data->seq;
1235 0           my $a = $data->alphabet;
1236 0           $s =~ s/[$Bio::PrimarySeq::GAP_SYMBOLS]//g;
1237 0           $data->seq($s);
1238 0           $data->alphabet($a);
1239 0           $fasio->write_seq($data);
1240             }
1241             else {
1242 0           $self->throw("Can't handle sequence container object ".
1243             "of type '".ref($data)."'");
1244             }
1245 0           $fasio->close;
1246 0           $data = $fname;
1247             }
1248 0           last;
1249             };
1250             }
1251 0           return $data;
1252             }
1253              
1254             =head2 _register_temp_for_cleanup()
1255              
1256             Title : _register_temp_for_cleanup
1257             Usage :
1258             Function: register a file for cleanup with
1259             cleanup() method
1260             Returns : true on success
1261             Args : a file name or a blastdb basename
1262             (scalar string)
1263              
1264             =cut
1265              
1266             sub _register_temp_for_cleanup {
1267 0     0     my $self = shift;
1268 0           my @files = @_;
1269              
1270 0           for (@files) {
1271 0           my ($v, $d, $n) = File::Spec->splitpath($_);
1272 0 0         $_ = File::Spec->catfile($self->db_dir, $n) unless length($d);
1273 0           push @{$self->{_cleanup_list}}, File::Spec->rel2abs($_);
  0            
1274             }
1275 0           return 1;
1276             }
1277              
1278             =head2 cleanup()
1279              
1280             Title : cleanup
1281             Usage :
1282             Function: unlink files registered for cleanup
1283             Returns : true on success
1284             Args :
1285              
1286             =cut
1287              
1288             sub cleanup {
1289 0     0 1   my $self = shift;
1290 0 0         return unless $self->{_cleanup_list};
1291              
1292 0           my $self_file = '';
1293 0 0         if (exists $self->{_results}->{_file}) {
1294 0           $self_file = $self->{_results}->{_file};
1295             }
1296 0           for (@{$self->{_cleanup_list}}) {
  0            
1297             # Close $self_file filehandle if it appears on the cleanup list,
1298             # to avoid 'permission denied' errors when unlinking
1299 0 0 0       if ($self_file ne '' and $_ =~ m/$self_file$/) {
1300 0           close $self->{_results}->_fh;
1301             }
1302              
1303 0 0         m/(\.[a-z0-9_]+)+$/i && do {
1304 0           unlink $_;
1305 0           next;
1306             };
1307 0           do { # catch all index files
1308 0 0         if ( -e $_.".psq" ) {
    0          
1309 0           unlink glob($_.".p*");
1310 0           unlink glob($_.".??.p*");
1311             }
1312             elsif ( -e $_.".nsq" ) {
1313 0           unlink glob($_.".n*");
1314 0           unlink glob($_.".??.n*");
1315             }
1316             else {
1317 0           unlink $_;
1318             }
1319 0           next;
1320             };
1321             }
1322 0           return 1;
1323             }
1324              
1325             =head2 AUTOLOAD
1326              
1327             In this module, C delegates L and
1328             L methods (including those
1329             of L) to the C attribute:
1330              
1331             $fac->stderr
1332              
1333             gives you
1334              
1335             $fac->factory->stderr
1336              
1337             If $AUTOLOAD isn't pointing to a WrapperBase method, then AUTOLOAD attempts to return a C attribute: e.g.
1338              
1339             $fac->db_num_sequences
1340              
1341             works by looking in the $fac->db_info() hash.
1342              
1343             Finally, if $AUTOLOAD is pointing to a blast query method, AUTOLOAD
1344             runs C with the C<-method> parameter appropriately set.
1345              
1346             =cut
1347              
1348             sub AUTOLOAD {
1349 0     0     my $self = shift;
1350 0           my @args = @_;
1351 0           my $method = $AUTOLOAD;
1352 0           $method =~ s/.*:://;
1353 0           my @ret;
1354 0 0         if (grep /^$method$/, @Bio::Tools::Run::StandAloneBlastPlus::BlastMethods) {
1355 0 0         push @args, ('-method_args' => ['-remote' => 1] ) if ($self->is_remote);
1356 0           return $self->run( -method => $method, @args );
1357             }
1358 0 0 0       if ($self->factory and $self->factory->can($method)) { # factory method
1359 0           return $self->factory->$method(@args);
1360             }
1361 0 0 0       if ($self->db_info and grep /^$method$/, keys %{$self->db_info}) {
  0            
1362 0           return $self->db_info->{$method};
1363             }
1364             # else, fail
1365 0           $self->throw("Can't locate method '$method' in class ".ref($self));
1366              
1367             }
1368              
1369              
1370             1;