File Coverage

Bio/SeqIO/bsml_sax.pm
Criterion Covered Total %
statement 123 127 96.8
branch 51 58 87.9
condition 4 6 66.6
subroutine 18 18 100.0
pod 6 6 100.0
total 202 215 93.9


line stmt bran cond sub pod time code
1             # BioPerl module for Bio::SeqIO::bsml_sax
2             #
3             # Please direct questions and support issues to
4             #
5             # Cared for by Jason Stajich
6             #
7              
8             =head1 NAME
9              
10             Bio::SeqIO::bsml_sax - BSML sequence input/output stream using SAX
11              
12             =head1 SYNOPSIS
13              
14             It is probably best not to use this object directly, but rather go
15             through the SeqIO handler system. To read a BSML file:
16              
17             $stream = Bio::SeqIO->new( -file => $filename, -format => 'bsml');
18              
19             while ( my $bioSeqObj = $stream->next_seq() ) {
20             # do something with $bioSeqObj
21             }
22              
23             To write a Seq object to the current file handle in BSML XML format:
24              
25             $stream->write_seq( -seq => $seqObj);
26              
27             If instead you would like a XML::DOM object containing the BSML, use:
28              
29             my $newXmlObject = $stream->to_bsml( -seq => $seqObj);
30              
31             =head1 DEPENDENCIES
32              
33             In addition to parts of the Bio:: hierarchy, this module uses:
34              
35             XML::SAX
36              
37             =head1 DESCRIPTION
38              
39             This object can transform Bio::Seq objects to and from BSML (XML)
40             flatfiles.
41              
42             =head1 FEEDBACK
43              
44             =head2 Mailing Lists
45              
46             User feedback is an integral part of the evolution of this and other
47             Bioperl modules. Send your comments and suggestions preferably to one
48             of the Bioperl mailing lists. Your participation is much appreciated.
49              
50             bioperl-l@bioperl.org - General discussion
51             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
52              
53             =head2 Support
54              
55             Please direct usage questions or support issues to the mailing list:
56              
57             I
58              
59             rather than to the module maintainer directly. Many experienced and
60             reponsive experts will be able look at the problem and quickly
61             address it. Please include a thorough description of the problem
62             with code and data examples if at all possible.
63              
64             =head2 Reporting Bugs
65              
66             Report bugs to the Bioperl bug tracking system to help us keep track
67             the bugs and their resolution. Bug reports can be submitted via the
68             web:
69              
70             https://github.com/bioperl/bioperl-live/issues
71              
72             =head1 AUTHOR - Jason Stajich
73              
74             Email jason-at-bioperl-dot-org
75              
76             =cut
77              
78             package Bio::SeqIO::bsml_sax;
79 1     1   5 use vars qw($Default_Source);
  1         1  
  1         55  
80 1     1   4 use strict;
  1         1  
  1         24  
81              
82 1     1   456 use Bio::SeqFeature::Generic;
  1         2  
  1         24  
83 1     1   289 use Bio::Species;
  1         2  
  1         22  
84 1     1   5 use XML::SAX;
  1         1  
  1         36  
85 1     1   3 use Bio::Seq::SeqFactory;
  1         2  
  1         14  
86 1     1   3 use Bio::Annotation::Collection;
  1         1  
  1         14  
87 1     1   264 use Bio::Annotation::Comment;
  1         1  
  1         20  
88 1     1   291 use Bio::Annotation::Reference;
  1         1  
  1         22  
89 1     1   4 use Bio::Annotation::DBLink;
  1         1  
  1         42  
90              
91 1     1   4 use base qw(Bio::SeqIO XML::SAX::Base);
  1         1  
  1         1040  
92              
93             $Default_Source = 'BSML';
94              
95             sub _initialize {
96 1     1   2 my ($self) = shift;
97 1         4 $self->SUPER::_initialize(@_);
98 1         7 $self->{'_parser'} = XML::SAX::ParserFactory->parser('Handler' => $self);
99 1 50       18433 if( ! defined $self->sequence_factory ) {
100 1         5 $self->sequence_factory(Bio::Seq::SeqFactory->new
101             (-verbose => $self->verbose(),
102             -type => 'Bio::Seq::RichSeq'));
103             }
104 1         1 return;
105             }
106              
107             =head1 METHODS
108              
109             =cut
110              
111             =head2 next_seq
112              
113             Title : next_seq
114             Usage : my $bioSeqObj = $stream->next_seq
115             Function: Retrieves the next sequence from a SeqIO::bsml stream.
116             Returns : A reference to a Bio::Seq::RichSeq object
117             Args :
118              
119             =cut
120              
121             sub next_seq {
122 1     1 1 6 my $self = shift;
123 1 50 33     1 if( @{$self->{'_seendata'}->{'_seqs'} || []} ||
  1 50       8  
124             eof($self->_fh)) {
125 0         0 return shift @{$self->{'_seendata'}->{'_seqs'}};
  0         0  
126             }
127 1         4 $self->{'_parser'}->parse_file($self->_fh);
128 1         35 return shift @{$self->{'_seendata'}->{'_seqs'}};
  1         6  
129             }
130              
131             # XML::SAX::Base methods
132              
133             sub start_document {
134 1     1 1 187 my ($self,$doc) = @_;
135 1         4 $self->{'_seendata'} = {'_seqs' => [],
136             '_authors' => [],
137             '_feats' => [] };
138 1         13 $self->SUPER::start_document($doc);
139             }
140              
141             sub end_document {
142 1     1 1 125 my ($self,$doc) = @_;
143 1         17 $self->SUPER::end_document($doc);
144             }
145              
146              
147             sub start_element {
148 36     36 1 26588 my ($self,$ele) = @_;
149 36         97 my $name = uc($ele->{'LocalName'});
150 36         34 my $attr = $ele->{'Attributes'};
151             my $seqid = defined $self->{'_seendata'}->{'_seqs'}->[-1] ?
152 36 100       116 $self->{'_seendata'}->{'_seqs'}->[-1]->display_id : undef;
153 36         78 for my $k ( keys %$attr ) {
154 59         98 $attr->{uc $k} = $attr->{$k};
155 59         80 delete $attr->{$k};
156             }
157 36 100       172 if( $name eq 'BSML' ) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
158              
159             } elsif( $name eq 'DEFINITIONS' ) {
160             } elsif( $name eq 'SEQUENCES' ) {
161              
162             } elsif( $name eq 'SEQUENCE' ) {
163             my ($id,$acc,$title,
164             $desc,$length,$topology,
165 1         3 $mol) = map { $attr->{'{}'.$_}->{'Value'} } qw(ID IC-ACCKEY
  7         11  
166             TITLE COMMENT
167             LENGTH
168             TOPOLOGY
169             MOLECULE);
170 1 50       2 push @{$self->{'_seendata'}->{'_seqs'}},
  1         5  
171             $self->sequence_factory->create
172             (
173             -display_id => $id,
174             -accession_number => $acc,
175             -description => $desc,
176             -length => $length,
177             -is_circular => ($topology =~ /^linear$/i) ? 0 : 1,
178             -molecule => $mol,
179             );
180              
181             } elsif( $name eq 'FEATURE-TABLES' ) {
182             } elsif( $name eq 'ATTRIBUTE' ) {
183 8         10 my $curseq = $self->{'_seendata'}->{'_seqs'}->[-1];
184 8         10 my ($name,$content) = map { $attr->{'{}'.$_}->{'Value'} } qw(NAME CONTENT);
  16         34  
185 8 100 100     47 if($name =~ /^version$/i ) {
    100          
    100          
    100          
    100          
186 1         2 my ($version);
187 1 50       7 if($content =~ /^[^\.]+\.(\d+)/) {
188 1         2 $version = $1;
189 0         0 } else { $version = $content }
190 1         3 $curseq->seq_version($version);
191             } elsif( $name eq 'organism-species') {
192 1         5 my ($genus,$species,$subsp) = split(/\s+/,$content,3);
193 1         10 $curseq->species(Bio::Species->new(-sub_species => $subsp,
194             -classification =>
195             [$species,$genus]));
196             } elsif( $name eq 'organism-classification' ) {
197 1         22 my (@class) =(split(/\s*;\s*/,$content),$curseq->species->species);
198 1         3 $curseq->species->classification([reverse @class]);
199             } elsif( $name eq 'database-xref' ) {
200 2         6 my ($db,$id) = split(/:/,$content);
201 2         6 $curseq->annotation->add_Annotation('dblink',
202             Bio::Annotation::DBLink->new
203             ( -database => $db,
204             -primary_id=> $id));
205             } elsif( $name eq 'date-created' ||
206             $name eq 'date-last-updated' ) {
207 2         6 $curseq->add_date($content);
208             }
209             } elsif( $name eq 'FEATURE' ) {
210             my ($id,$class,$type,$title,$display_auto)
211 2         3 = map { $attr->{'{}'.$_}->{'Value'} } qw(ID CLASS VALUE-TYPE
  10         17  
212             TITLE DISPLAY-AUTO);
213              
214 2         8 push @{$self->{'_seendata'}->{'_feats'}},
215             Bio::SeqFeature::Generic->new
216 2         3 ( -seq_id => $self->{'_seendata'}->{'_seqs'}->[-1]->display_id,
217             -source_tag => $Default_Source,
218             -primary_tag => $type,
219             -tag => {'ID' => $id,
220             });
221              
222             } elsif( $name eq 'QUALIFIER') {
223 10         12 my ($type,$value) = map { $attr->{'{}'.$_}->{'Value'} } qw(VALUE-TYPE
  20         37  
224             VALUE);
225 10         14 my $curfeat = $self->{'_seendata'}->{'_feats'}->[-1];
226 10         17 $curfeat->add_tag_value($type,$value);
227             } elsif( $name eq 'INTERVAL-LOC' ) {
228 2         3 my $curfeat = $self->{'_seendata'}->{'_feats'}->[-1];
229             my ($start,$end,$strand) =
230 2         3 map { $attr->{'{}'.$_}->{'Value'} } qw(STARTPOS
  6         13  
231             ENDPOS
232             COMPLEMENT);
233              
234 2         7 $curfeat->start($start);
235 2         5 $curfeat->end($end);
236 2 50       4 $curfeat->strand(-1) if($strand);
237             } elsif( $name eq 'REFERENCE' ) {
238 2         3 push @{$self->{'_seendata'}->{'_annot'}},
  2         10  
239             Bio::Annotation::Reference->new();
240             }
241              
242 36         32 push @{$self->{'_state'}}, $name;
  36         49  
243 36         75 $self->SUPER::start_element($ele);
244             }
245              
246             sub end_element {
247 36     36 1 6972 my ($self,$ele) = @_;
248 36         27 pop @{$self->{'_state'}};
  36         51  
249 36         60 my $name = uc $ele->{'LocalName'};
250 36         38 my $curseq = $self->{'_seendata'}->{'_seqs'}->[-1];
251 36 100       79 if( $name eq 'REFERENCE') {
    100          
252 2         1 my $ref = pop @{$self->{'_seendata'}->{'_annot'}};
  2         4  
253 2         5 $curseq->annotation->add_Annotation('reference',$ref);
254             } elsif( $name eq 'FEATURE' ) {
255 2         3 my $feat = pop @{$self->{'_seendata'}->{'_feats'}};
  2         3  
256 2         9 $curseq->add_SeqFeature($feat);
257             }
258 36         69 $self->SUPER::end_element($ele);
259             }
260              
261             sub characters {
262 52     52 1 3077 my ($self,$data) = @_;
263 52 50       46 if( ! @{$self->{'_state'}} ) {
  52         82  
264 0         0 $self->warn("Calling characters with no previous start_element call. Ignoring data");
265             } else {
266 52         47 my $curseq = $self->{'_seendata'}->{'_seqs'}->[-1];
267 52         49 my $curfeat = $self->{'_seendata'}->{'_feats'}->[-1];
268 52         41 my $curannot = $self->{'_seendata'}->{'_annot'}->[-1];
269 52         48 my $name = $self->{'_state'}->[-1];
270 52 100       166 if( $name eq 'REFAUTHORS' ) {
    100          
    100          
    100          
271 2         7 $curannot->authors($data->{'Data'});
272             } elsif( $name eq 'REFTITLE') {
273 1         4 $curannot->title($data->{'Data'});
274             } elsif( $name eq 'REFJOURNAL') {
275 2         6 $curannot->location($data->{'Data'});
276             } elsif( $name eq 'SEQ-DATA') {
277 2         27 $data->{'Data'} =~ s/\s+//g;
278 2         8 $curseq->seq($data->{'Data'});
279             }
280             }
281 52         91 $self->SUPER::characters($data);
282             }
283              
284             1;