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         47  
80 1     1   5 use strict;
  1         1  
  1         19  
81              
82 1     1   280 use Bio::SeqFeature::Generic;
  1         3  
  1         29  
83 1     1   271 use Bio::Species;
  1         2  
  1         26  
84 1     1   6 use XML::SAX;
  1         2  
  1         41  
85 1     1   4 use Bio::Seq::SeqFactory;
  1         2  
  1         18  
86 1     1   3 use Bio::Annotation::Collection;
  1         2  
  1         17  
87 1     1   243 use Bio::Annotation::Comment;
  1         2  
  1         23  
88 1     1   241 use Bio::Annotation::Reference;
  1         2  
  1         24  
89 1     1   5 use Bio::Annotation::DBLink;
  1         2  
  1         47  
90              
91 1     1   5 use base qw(Bio::SeqIO XML::SAX::Base);
  1         1  
  1         1229  
92              
93             $Default_Source = 'BSML';
94              
95             sub _initialize {
96 1     1   3 my ($self) = shift;
97 1         5 $self->SUPER::_initialize(@_);
98 1         7 $self->{'_parser'} = XML::SAX::ParserFactory->parser('Handler' => $self);
99 1 50       17379 if( ! defined $self->sequence_factory ) {
100 1         4 $self->sequence_factory(Bio::Seq::SeqFactory->new
101             (-verbose => $self->verbose(),
102             -type => 'Bio::Seq::RichSeq'));
103             }
104 1         2 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 5 my $self = shift;
123 1 50 33     1 if( @{$self->{'_seendata'}->{'_seqs'} || []} ||
  1 50       9  
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         31 return shift @{$self->{'_seendata'}->{'_seqs'}};
  1         5  
129             }
130              
131             # XML::SAX::Base methods
132              
133             sub start_document {
134 1     1 1 235 my ($self,$doc) = @_;
135 1         3 $self->{'_seendata'} = {'_seqs' => [],
136             '_authors' => [],
137             '_feats' => [] };
138 1         10 $self->SUPER::start_document($doc);
139             }
140              
141             sub end_document {
142 1     1 1 165 my ($self,$doc) = @_;
143 1         14 $self->SUPER::end_document($doc);
144             }
145              
146              
147             sub start_element {
148 36     36 1 34389 my ($self,$ele) = @_;
149 36         68 my $name = uc($ele->{'LocalName'});
150 36         42 my $attr = $ele->{'Attributes'};
151             my $seqid = defined $self->{'_seendata'}->{'_seqs'}->[-1] ?
152 36 100       123 $self->{'_seendata'}->{'_seqs'}->[-1]->display_id : undef;
153 36         85 for my $k ( keys %$attr ) {
154 59         123 $attr->{uc $k} = $attr->{$k};
155 59         89 delete $attr->{$k};
156             }
157 36 100       155 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         18  
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         12 my $curseq = $self->{'_seendata'}->{'_seqs'}->[-1];
184 8         9 my ($name,$content) = map { $attr->{'{}'.$_}->{'Value'} } qw(NAME CONTENT);
  16         41  
185 8 100 100     40 if($name =~ /^version$/i ) {
    100          
    100          
    100          
    100          
186 1         2 my ($version);
187 1 50       5 if($content =~ /^[^\.]+\.(\d+)/) {
188 1         3 $version = $1;
189 0         0 } else { $version = $content }
190 1         3 $curseq->seq_version($version);
191             } elsif( $name eq 'organism-species') {
192 1         7 my ($genus,$species,$subsp) = split(/\s+/,$content,3);
193 1         8 $curseq->species(Bio::Species->new(-sub_species => $subsp,
194             -classification =>
195             [$species,$genus]));
196             } elsif( $name eq 'organism-classification' ) {
197 1         15 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         7 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         5 $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         23  
212             TITLE DISPLAY-AUTO);
213              
214 2         6 push @{$self->{'_seendata'}->{'_feats'}},
215             Bio::SeqFeature::Generic->new
216 2         4 ( -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         15 my ($type,$value) = map { $attr->{'{}'.$_}->{'Value'} } qw(VALUE-TYPE
  20         61  
224             VALUE);
225 10         17 my $curfeat = $self->{'_seendata'}->{'_feats'}->[-1];
226 10         24 $curfeat->add_tag_value($type,$value);
227             } elsif( $name eq 'INTERVAL-LOC' ) {
228 2         4 my $curfeat = $self->{'_seendata'}->{'_feats'}->[-1];
229             my ($start,$end,$strand) =
230 2         3 map { $attr->{'{}'.$_}->{'Value'} } qw(STARTPOS
  6         16  
231             ENDPOS
232             COMPLEMENT);
233              
234 2         8 $curfeat->start($start);
235 2         6 $curfeat->end($end);
236 2 50       14 $curfeat->strand(-1) if($strand);
237             } elsif( $name eq 'REFERENCE' ) {
238 2         2 push @{$self->{'_seendata'}->{'_annot'}},
  2         11  
239             Bio::Annotation::Reference->new();
240             }
241              
242 36         40 push @{$self->{'_state'}}, $name;
  36         59  
243 36         92 $self->SUPER::start_element($ele);
244             }
245              
246             sub end_element {
247 36     36 1 2780 my ($self,$ele) = @_;
248 36         29 pop @{$self->{'_state'}};
  36         50  
249 36         68 my $name = uc $ele->{'LocalName'};
250 36         47 my $curseq = $self->{'_seendata'}->{'_seqs'}->[-1];
251 36 100       71 if( $name eq 'REFERENCE') {
    100          
252 2         3 my $ref = pop @{$self->{'_seendata'}->{'_annot'}};
  2         3  
253 2         5 $curseq->annotation->add_Annotation('reference',$ref);
254             } elsif( $name eq 'FEATURE' ) {
255 2         3 my $feat = pop @{$self->{'_seendata'}->{'_feats'}};
  2         4  
256 2         8 $curseq->add_SeqFeature($feat);
257             }
258 36         95 $self->SUPER::end_element($ele);
259             }
260              
261             sub characters {
262 52     52 1 4015 my ($self,$data) = @_;
263 52 50       47 if( ! @{$self->{'_state'}} ) {
  52         83  
264 0         0 $self->warn("Calling characters with no previous start_element call. Ignoring data");
265             } else {
266 52         57 my $curseq = $self->{'_seendata'}->{'_seqs'}->[-1];
267 52         63 my $curfeat = $self->{'_seendata'}->{'_feats'}->[-1];
268 52         78 my $curannot = $self->{'_seendata'}->{'_annot'}->[-1];
269 52         55 my $name = $self->{'_state'}->[-1];
270 52 100       148 if( $name eq 'REFAUTHORS' ) {
    100          
    100          
    100          
271 2         6 $curannot->authors($data->{'Data'});
272             } elsif( $name eq 'REFTITLE') {
273 1         4 $curannot->title($data->{'Data'});
274             } elsif( $name eq 'REFJOURNAL') {
275 2         5 $curannot->location($data->{'Data'});
276             } elsif( $name eq 'SEQ-DATA') {
277 2         26 $data->{'Data'} =~ s/\s+//g;
278 2         12 $curseq->seq($data->{'Data'});
279             }
280             }
281 52         113 $self->SUPER::characters($data);
282             }
283              
284             1;