File Coverage

blib/lib/Bio/DB/BioFetch.pm
Criterion Covered Total %
statement 77 92 83.7
branch 24 42 57.1
condition 12 21 57.1
subroutine 17 19 89.4
pod 10 10 100.0
total 140 184 76.0


line stmt bran cond sub pod time code
1             #
2             # BioPerl module for Bio::DB::BioFetch
3             #
4             # Please direct questions and support issues to
5             #
6             # Cared for by Lincoln Stein
7             #
8             # Copyright Lincoln Stein
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              
15             package Bio::DB::BioFetch;
16             $Bio::DB::BioFetch::VERSION = '1.7.3';
17 1     1   75221 use strict;
  1         9  
  1         23  
18              
19 1     1   4 use Carp;
  1         2  
  1         40  
20              
21 1     1   387 use HTTP::Request::Common 'POST';
  1         19732  
  1         57  
22              
23             =head1 NAME
24              
25             Bio::DB::BioFetch - Database object interface to BioFetch retrieval
26              
27             =head1 SYNOPSIS
28              
29             use Bio::DB::BioFetch;
30              
31             $bf = Bio::DB::BioFetch->new();
32              
33             $seq = $bf->get_Seq_by_id('HSFOS'); # EMBL or SWALL ID
34              
35             # change formats, storage procedures
36             $bf = Bio::DB::BioFetch->new(-format => 'fasta',
37             -retrievaltype => 'tempfile',
38             -db => 'EMBL');
39              
40             $stream = $bf->get_Stream_by_id(['HSFOS','J00231']);
41             while (my $s = $stream->next_seq) {
42             print $s->seq,"\n";
43             }
44             # get a RefSeq entry
45             $bf->db('refseq');
46             eval {
47             $seq = $bf->get_Seq_by_version('NM_006732.1'); # RefSeq VERSION
48             };
49             print "accession is ", $seq->accession_number, "\n" unless $@;
50              
51              
52             =head1 DESCRIPTION
53              
54             Bio::DB::BioFetch is a guaranteed best effort sequence entry fetching
55             method. It goes to the Web-based dbfetch server located at the EBI
56             (http://www.ebi.ac.uk/Tools/dbfetch/dbfetch) to retrieve sequences in the
57             EMBL or GenBank sequence repositories.
58              
59             This module implements all the Bio::DB::RandomAccessI interface, plus
60             the get_Stream_by_id() and get_Stream_by_acc() methods that are found
61             in the Bio::DB::SwissProt interface.
62              
63             =head1 FEEDBACK
64              
65             =head2 Mailing Lists
66              
67             User feedback is an integral part of the evolution of this and other
68             Bioperl modules. Send your comments and suggestions preferably to one
69             of the Bioperl mailing lists. Your participation is much appreciated.
70              
71              
72             bioperl-l@bioperl.org - General discussion
73             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
74              
75             =head2 Support
76              
77             Please direct usage questions or support issues to the mailing list:
78              
79             I
80              
81             rather than to the module maintainer directly. Many experienced and
82             reponsive experts will be able look at the problem and quickly
83             address it. Please include a thorough description of the problem
84             with code and data examples if at all possible.
85              
86             =head2 Reporting Bugs
87              
88             Report bugs to the Bioperl bug tracking system to help us keep track
89             the bugs and their resolution. Bug reports can be submitted via the
90             web:
91              
92             https://github.com/bioperl/bioperl-live/issues
93              
94             =head1 AUTHOR - Lincoln Stein
95              
96             Email Lincoln Stein Elstein@cshl.orgE
97              
98             Also thanks to Heikki Lehvaslaiho Eheikki-at-bioperl-dot-orgE for the
99             BioFetch server and interface specification.
100              
101             =head1 APPENDIX
102              
103             The rest of the documentation details each of the object
104             methods. Internal methods are usually preceded with a _
105              
106             =cut
107              
108             # Let the code begin...
109 1     1   6 use vars qw(%FORMATMAP);
  1         2  
  1         51  
110 1     1   5 use base qw(Bio::DB::WebDBSeqI Bio::Root::Root);
  1         2  
  1         434  
111              
112             # warning: names used here must map into Bio::SeqIO::* space
113 1     1   89774 use constant DEFAULT_LOCATION => 'http://www.ebi.ac.uk/Tools/dbfetch/dbfetch';
  1         2  
  1         132  
114              
115             BEGIN {
116              
117 1     1   1079 %FORMATMAP = (
118             'embl' => {
119             default => 'embl', # default BioFetch format/SeqIOmodule pair
120             embl => 'embl', # alternative BioFetch format/module pair
121             fasta => 'fasta', # alternative BioFetch format/module pair
122             namespace => 'embl',
123             },
124             'swissprot' => {
125             default => 'swiss',
126             swissprot => 'swiss',
127             fasta => 'fasta',
128             namespace => 'uniprot',
129             },
130             'refseq' => {
131             default => 'genbank',
132             genbank => 'genbank',
133             fasta => 'fasta',
134             namespace => 'RefSeq',
135             },
136             'refseqn' => {
137             default => 'genbank',
138             genbank => 'genbank',
139             fasta => 'fasta',
140             namespace => 'refseqn',
141             },
142             'refseqp' => {
143             default => 'genbank',
144             genbank => 'genbank',
145             fasta => 'fasta',
146             namespace => 'refseqp',
147             },
148             'swall' => {
149             default => 'swiss',
150             swissprot => 'swiss',
151             fasta => 'fasta',
152             namespace => 'uniprot',
153             },
154             'uniprot' => {
155             default => 'swiss',
156             swissprot => 'swiss',
157             fasta => 'fasta',
158             namespace => 'uniprot',
159             },
160             'genbank' => {
161             default => 'genbank',
162             genbank => 'genbank',
163             namespace => 'genbank',
164             },
165             'genpep' => {
166             default => 'genbank',
167             genbank => 'genbank',
168             namespace => 'genpep',
169             },
170             'unisave' => {
171             default => 'swiss',
172             swissprot => 'swiss',
173             fasta => 'fasta',
174             namespace => 'unisave',
175             }
176             );
177             }
178              
179             =head2 new
180              
181             Title : new
182             Usage : $bf = Bio::DB::BioFetch->new(@args)
183             Function: Construct a new Bio::DB::BioFetch object
184             Returns : a Bio::DB::BioFetch object
185             Args : see below
186             Throws :
187              
188             @args are standard -name=Evalue options as listed in the following
189             table. If you do not provide any options, the module assumes reasonable
190             defaults.
191              
192             Option Value Default
193             ------ ----- -------
194              
195             -baseaddress location of dbfetch server http://www.ebi.ac.uk/Tools/dbfetch/dbfetch
196             -retrievaltype "tempfile" or "io_string" io_string
197             -format "embl", "fasta", "swissprot", embl
198             or "genbank"
199             -db "embl", "genbank" or "swissprot" embl
200              
201             =cut
202              
203             #'
204             sub new {
205 5     5 1 899399 my ($class,@args) = @_;
206 5         83 my $self = $class->SUPER::new(@args);
207 5         16577 my ($db) = $self->_rearrange([qw(DB)],@args);
208 5   66     146 $db ||= $self->default_db;
209 5         22 $self->db($db);
210 5 50       11 $self->url_base_address(DEFAULT_LOCATION) unless $self->url_base_address;
211 5         117 $self;
212             }
213              
214             =head2 new_from_registry
215              
216             Title : new_from_registry
217             Usage : $biofetch = $db->new_from_registry(%config)
218             Function: Creates a BioFetch object from the registry config hash
219             Returns : itself
220             Args : A configuration hash (see Registry.pm)
221             Throws :
222              
223              
224             =cut
225              
226             sub new_from_registry {
227 0     0 1 0 my ($class,%config)=@_;
228              
229             my $self = $class->SUPER::new(
230 0         0 -BASEADDRESS=>$config{'location'}
231             );
232 0 0       0 $self->db($config{'dbname'}) if $config{dbname};
233 0         0 return $self;
234             }
235              
236             # from Bio::DB::RandomAccessI
237              
238             =head2 get_Seq_by_id
239              
240             Title : get_Seq_by_id
241             Usage : $seq = $db->get_Seq_by_id('ROA1_HUMAN')
242             Function: Gets a Bio::Seq object by its name
243             Returns : a Bio::Seq object
244             Args : the id (as a string) of a sequence
245             Throws : "id does not exist" exception
246              
247              
248             =cut
249              
250             =head2 get_Seq_by_acc
251              
252             Title : get_Seq_by_acc
253             Usage : $seq = $db->get_Seq_by_acc('X77802');
254             Function: Gets a Bio::Seq object by accession number
255             Returns : A Bio::Seq object
256             Args : accession number (as a string)
257             Throws : "acc does not exist" exception
258              
259             =cut
260              
261             =head2 get_Seq_by_gi
262              
263             Title : get_Seq_by_gi
264             Usage : $seq = $db->get_Seq_by_gi('405830');
265             Function: Gets a Bio::Seq object by gi number
266             Returns : A Bio::Seq object
267             Args : gi number (as a string)
268             Throws : "gi does not exist" exception
269              
270             =cut
271              
272             =head2 get_Seq_by_version
273              
274             Title : get_Seq_by_version
275             Usage : $seq = $db->get_Seq_by_version('X77802.1');
276             Function: Gets a Bio::Seq object by sequence version
277             Returns : A Bio::Seq object
278             Args : accession.version (as a string)
279             Throws : "acc.version does not exist" exception
280              
281             =cut
282              
283             sub get_Seq_by_version {
284 0     0 1 0 my ($self,$seqid) = @_;
285 0         0 return $self->get_Seq_by_acc($seqid);
286             }
287              
288              
289             =head2 get_Stream_by_id
290              
291             Title : get_Stream_by_id
292             Usage : $stream = $db->get_Stream_by_id( [$uid1, $uid2] );
293             Function: Gets a series of Seq objects by unique identifiers
294             Returns : a Bio::SeqIO stream object
295             Args : $ref : a reference to an array of unique identifiers for
296             the desired sequence entries
297              
298             =cut
299              
300             =head2 get_Stream_by_gi
301              
302             Title : get_Stream_by_gi
303             Usage : $seq = $db->get_Seq_by_gi([$gi1, $gi2]);
304             Function: Gets a series of Seq objects by gi numbers
305             Returns : a Bio::SeqIO stream object
306             Args : $ref : a reference to an array of gi numbers for
307             the desired sequence entries
308             Note : For GenBank, this just calls the same code for get_Stream_by_id()
309              
310             =cut
311              
312             =head2 get_Stream_by_batch
313              
314             Title : get_Stream_by_batch
315             Usage : $seq = $db->get_Stream_by_batch($ref);
316             Function: Get a series of Seq objects by their IDs
317             Example :
318             Returns : a Bio::SeqIO stream object
319             Args : $ref : an array reference containing a list of unique
320             ids/accession numbers.
321              
322             In some of the Bio::DB::* moduels, get_Stream_by_id() is called
323             get_Stream_by_batch(). Since there seems to be no consensus, this
324             is provided as an alias.
325              
326             =cut
327              
328             *get_Stream_by_batch = \&Bio::DB::WebDBSeqI::get_Stream_by_id;
329              
330             =head1 The remainder of these methods are for internal use
331              
332             =head2 get_request
333              
334             Title : get_request
335             Usage : my $url = $self->get_request
336             Function: returns a HTTP::Request object
337             Returns :
338             Args : %qualifiers = a hash of qualifiers (ids, format, etc)
339              
340             =cut
341              
342              
343             sub get_request {
344 8     8 1 106 my ($self, @qualifiers) = @_;
345 8         773 my ($uids, $format) = $self->_rearrange([qw(UIDS FORMAT)],
346             @qualifiers);
347 8         271 my $db = $self->db;
348 8         17 my $namespace = $self->_namespace;
349              
350 8 50       17 $self->throw("Must specify a value for UIDs to fetch")
351             unless defined $uids;
352 8         11 my $tmp;
353 8         35 my $format_string = '';
354              
355 8   33     21 $format ||= $self->default_format;
356 8         22 ($format, $tmp) = $self->request_format($format);
357              
358 8         34 my $base = $self->url_base_address;
359 8 100       81 my $uid = join('+',ref $uids ? @$uids : $uids);
360 8         79 $self->debug("\n$base$format_string&id=$uid\n");
361 8 100       246 return POST($base,
362             [ db => $namespace,
363             id => join('+',ref $uids ? @$uids : $uids),
364             format => $format,
365             style => 'raw'
366             ]);
367             }
368              
369             =head2 default_format
370              
371             Title : default_format
372             Usage : $format = $self->default_format
373             Function: return the default format
374             Returns : a string
375             Args :
376              
377             =cut
378              
379             sub default_format {
380 4     4 1 209 return 'default';
381             }
382              
383             =head2 default_db
384              
385             Title : default_db
386             Usage : $db = $self->default_db
387             Function: return the default database
388             Returns : a string
389             Args :
390              
391             =cut
392              
393 6     6 1 29 sub default_db { 'embl' }
394              
395             =head2 db
396              
397             Title : db
398             Usage : $db = $self->db([$db])
399             Function: get/set the database
400             Returns : a string
401             Args : new database
402              
403             =cut
404              
405             sub db {
406 74     74 1 819503 my $self = shift;
407              
408 74 100       145 if (@_) {
409 12         23 my $db = lc shift;
410              
411             ## This is a special case error message because 'refseq' was
412             ## once a valid database. With time, remove this special error
413             ## handling. See issue #1.
414 12 50       27 if ($db eq 'refseq') {
415 0         0 croak "'refseq' is an invalid db. Try 'refseqn' or 'refseqn'";
416             }
417 12         48 my $base = $self->url_base_address;
418 12 50       100 $FORMATMAP{$db} or $self->throw("invalid db [$db] at [$base], must be one of [".
419             join(' ',keys %FORMATMAP). "]");
420 12         36 $self->{_db} = $db;
421             }
422 74   66     209 return $self->{_db} || $self->default_db ;
423             }
424              
425             sub _namespace {
426 30     30   43 my $self = shift;
427 30         43 my $db = $self->db;
428 30   33     102 return $FORMATMAP{$db}{namespace} || $db;
429             }
430              
431             =head2 postprocess_data
432              
433             Title : postprocess_data
434             Usage : $self->postprocess_data ( 'type' => 'string',
435             'location' => \$datastr);
436             Function: process downloaded data before loading into a Bio::SeqIO
437             Returns : void
438             Args : hash with two keys - 'type' can be 'string' or 'file'
439             - 'location' either file location or string
440             reference containing data
441              
442             =cut
443              
444             sub postprocess_data {
445 1     1 1 137270 my ($self,%args) = @_;
446              
447             # check for errors in the stream
448 1 50       7 if ($args{'type'} eq 'string') {
    50          
449 0         0 my $stringref = $args{'location'};
450 0 0       0 if ($$stringref =~ /^ERROR (\d+) (.+)/m) {
451 0         0 $self->throw("BioFetch Error $1: $2");
452             }
453             }
454              
455             elsif ($args{'type'} eq 'file') {
456 1 50       37 open my $F, '<', $args{'location'} or $self->throw("Could not read file '$args{location}': $!");
457             # this is dumb, but the error may be anywhere on the first three lines because the
458             # CGI headers are sometimes printed out by the server...
459 1         18 my @data = grep {defined $_} (scalar <$F>, scalar <$F>, scalar <$F>);
  3         8  
460 1         11 close $F;
461 1 50       17 if (join('',@data) =~ /^ERROR (\d+) (.+)/m) {
462 0         0 $self->throw("BioFetch Error $1: $2");
463             }
464             }
465              
466             else {
467 0         0 $self->throw("Don't know how to postprocess data of type $args{'type'}");
468             }
469             }
470              
471              
472             =head2 request_format
473              
474             Title : request_format
475             Usage : my ($req_format, $ioformat) = $self->request_format;
476             $self->request_format("genbank");
477             $self->request_format("fasta");
478             Function: Get/Set sequence format retrieval. The get-form will normally not
479             be used outside of this and derived modules.
480             Returns : Array of two strings, the first representing the format for
481             retrieval, and the second specifying the corresponding SeqIO format.
482             Args : $format = sequence format
483              
484             =cut
485              
486             sub request_format {
487 34     34 1 487501 my ($self, $value) = @_;
488 34 100       78 if ( defined $value ) {
489 22         67 my $db = $self->db;
490 22         54 my $namespace = $self->_namespace;
491 22         52 my $format = lc $value;
492 22 50       83 print "format:", $format, " module:", $FORMATMAP{$db}->{$format}, " ($namespace)\n"
493             if $self->verbose > 0;
494             $self->throw("Invalid format [$format], must be one of [".
495 0         0 join(' ',keys %{$FORMATMAP{$db}}). "]")
496 22 50 66     244 unless $format eq 'default' || $FORMATMAP{$db}->{$format};
497              
498 22         85 $self->{'_format'} = [ $format, $FORMATMAP{$db}->{$format}];
499             }
500 34         47 return @{$self->{'_format'}};
  34         98  
501             }
502              
503              
504             =head2 Bio::DB::WebDBSeqI methods
505              
506             Overriding WebDBSeqI method to help newbies to retrieve sequences.
507             EMBL database is all too often passed RefSeq accessions. This
508             redirects those calls. See L.
509              
510              
511             =head2 get_Stream_by_acc
512              
513             Title : get_Stream_by_acc
514             Usage : $seq = $db->get_Seq_by_acc([$acc1, $acc2]);
515             Function: Gets a series of Seq objects by accession numbers
516             Returns : a Bio::SeqIO stream object
517             Args : $ref : a reference to an array of accession numbers for
518             the desired sequence entries
519              
520             =cut
521              
522             sub get_Stream_by_acc {
523 6     6 1 2635 my ($self, $ids ) = @_;
524 6         18 $self->_check_id($ids);
525 5         20 return $self->get_seq_stream('-uids' => $ids, '-mode' => 'single');
526             }
527              
528              
529             =head2 _check_id
530              
531             Title : _check_id
532             Usage :
533             Function: Throw on whole chromosome NCBI sequences not in sequence databases
534             and redirect RefSeq accession requests sent to EMBL.
535             Returns :
536             Args : $id(s), $string
537             Throws : if accessionn number indicates whole chromosome NCBI sequence
538              
539             =cut
540              
541             sub _check_id {
542 6     6   11 my ($self, $id) = @_;
543              
544             # NT contigs can not be retrieved
545 6 100       54 $self->throw("NT_ contigs are whole chromosome files which are not part of regular ".
546             "database distributions. Go to ftp://ftp.ncbi.nih.gov/genomes/.")
547             if $id =~ /NT_/;
548              
549             ## Asking for a RefSeq from EMBL/GenBank
550 5 100 100     36 if ($id =~ /^(AC|NC|NG|NM|NR|NS)_/ && $self->db ne 'refseqn') {
    50 33        
551 1 50       10 carp "[$id] is a RefSeq (nucleotide) entry. Redirecting the request."
552             if $self->verbose >= 0;
553 1         737 $self->db('refseqn');
554             } elsif ($id =~ /^(AP|NP|XP|YP)_/ && $self->db ne 'refseqp') {
555 0 0         carp "[$id] is a RefSeq (protein) entry. Redirecting the request."
556             if $self->verbose >= 0;
557 0           $self->db('refseqp');
558             }
559             }
560              
561             1;