3 # BioPerl module for Bio::SearchIO::hmmer
5 # Cared for by Jason Stajich <jason@bioperl.org>
7 # Copyright Jason Stajich
9 # You may distribute this module under the same terms as perl itself
11 # POD documentation - main docs before the code
15 Bio::SearchIO::hmmer - A parser for HMMER output (hmmpfam, hmmsearch)
19 # do not use this class directly it is available through Bio::SearchIO
21 my $in = Bio::SearchIO->new(-format => 'hmmer',
22 -file => 't/data/L77119.hmmer');
23 while( my $result = $in->next_result ) {
24 # this is a Bio::Search::Result::HMMERResult object
25 print $result->query_name(), " for HMM ", $result->hmm_name(), "\n";
26 while( my $hit = $result->next_hit ) {
27 print $hit->name(), "\n";
28 while( my $hsp = $hit->next_hsp ) {
29 print "length is ", $hsp->length(), "\n";
36 This object implements a parser for HMMER output.
42 User feedback is an integral part of the evolution of this and other
43 Bioperl modules. Send your comments and suggestions preferably to
44 the Bioperl mailing list. Your participation is much appreciated.
46 bioperl-l@bioperl.org - General discussion
47 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
51 Report bugs to the Bioperl bug tracking system to help us keep track
52 of the bugs and their resolution. Bug reports can be submitted via the
55 http://bugzilla.open-bio.org/
57 =head1 AUTHOR - Jason Stajich
59 Email jason-at-bioperl.org
63 The rest of the documentation details each of the object methods.
64 Internal methods are usually preceded with a _
68 # Let the code begin...
70 package Bio
::SearchIO
::hmmer
;
74 use Bio
::Factory
::ObjectFactory
;
76 use vars
qw(%MAPPING %MODEMAP
79 use base qw(Bio::SearchIO);
83 # mapping of HMMER items to Bioperl hash keys
85 'HMMER_Output' => 'result',
91 'Hsp_bit-score' => 'HSP-bits',
92 'Hsp_score' => 'HSP-score',
93 'Hsp_evalue' => 'HSP-evalue',
94 'Hsp_query-from' => 'HSP-query_start',
95 'Hsp_query-to' => 'HSP-query_end',
96 'Hsp_hit-from' => 'HSP-hit_start',
97 'Hsp_hit-to' => 'HSP-hit_end',
98 'Hsp_positive' => 'HSP-conserved',
99 'Hsp_identity' => 'HSP-identical',
100 'Hsp_gaps' => 'HSP-hsp_gaps',
101 'Hsp_hitgaps' => 'HSP-hit_gaps',
102 'Hsp_querygaps' => 'HSP-query_gaps',
103 'Hsp_qseq' => 'HSP-query_seq',
104 'Hsp_hseq' => 'HSP-hit_seq',
105 'Hsp_midline' => 'HSP-homology_seq',
106 'Hsp_align-len' => 'HSP-hsp_length',
107 'Hsp_query-frame' => 'HSP-query_frame',
108 'Hsp_hit-frame' => 'HSP-hit_frame',
110 'Hit_id' => 'HIT-name',
111 'Hit_len' => 'HIT-length',
112 'Hit_accession' => 'HIT-accession',
113 'Hit_desc' => 'HIT-description',
114 'Hit_signif' => 'HIT-significance',
115 'Hit_score' => 'HIT-score',
117 'HMMER_program' => 'RESULT-algorithm_name',
118 'HMMER_version' => 'RESULT-algorithm_version',
119 'HMMER_query-def' => 'RESULT-query_name',
120 'HMMER_query-len' => 'RESULT-query_length',
121 'HMMER_query-acc' => 'RESULT-query_accession',
122 'HMMER_querydesc' => 'RESULT-query_description',
123 'HMMER_hmm' => 'RESULT-hmm_name',
124 'HMMER_seqfile' => 'RESULT-sequence_file',
125 'HMMER_db' => 'RESULT-database_name',
132 Usage : my $obj = Bio::SearchIO::hmmer->new();
133 Function: Builds a new Bio::SearchIO::hmmer object
134 Returns : Bio::SearchIO::hmmer
135 Args : -fh/-file => HMMER filename
141 my ( $self, @args ) = @_;
142 $self->SUPER::_initialize
(@args);
143 my $handler = $self->_eventHandler;
144 $handler->register_factory(
146 Bio
::Factory
::ObjectFactory
->new(
147 -type
=> 'Bio::Search::Result::HMMERResult',
148 -interface
=> 'Bio::Search::Result::ResultI'
152 $handler->register_factory(
154 Bio
::Factory
::ObjectFactory
->new(
155 -type
=> 'Bio::Search::Hit::HMMERHit',
156 -interface
=> 'Bio::Search::Hit::HitI'
160 $handler->register_factory(
162 Bio
::Factory
::ObjectFactory
->new(
163 -type
=> 'Bio::Search::HSP::HMMERHSP',
164 -interface
=> 'Bio::Search::HSP::HSPI'
167 $self->{'_hmmidline'} = 'HMMER 2.2g (August 2001)';
173 Usage : my $hit = $searchio->next_result;
174 Function: Returns the next Result from a search
175 Returns : Bio::Search::Result::ResultI object
184 my ( $last, @hitinfo, @hspinfo, %hspinfo, %hitinfo );
188 my $verbose = $self->verbose; # cache for speed?
189 $self->start_document();
191 while ( defined( $_ = $self->_readline ) ) {
194 if (/^HMMER\s+(\S+)\s+\((.+)\)/o) {
195 my ( $prog, $version ) = split;
197 $self->_pushback($_);
198 $self->end_element( { 'Name' => 'HMMER_Output' } );
199 return $self->end_document();
201 $self->{'_hmmidline'} = $_;
202 $self->start_element( { 'Name' => 'HMMER_Output' } );
203 $self->{'_result_count'}++;
205 if ( defined $last ) {
206 ($reporttype) = split( /\s+/, $last );
209 'Name' => 'HMMER_program',
210 'Data' => uc($reporttype)
216 'Name' => 'HMMER_version',
221 elsif (s/^HMM file:\s+//o) {
222 $self->{'_hmmfileline'} = $lineorig;
225 'Name' => 'HMMER_hmm',
230 elsif (s/^Sequence\s+(file|database):\s+//o) {
231 $self->{'_hmmseqline'} = $lineorig;
232 if ( $1 eq 'database' ) {
235 'Name' => 'HMMER_db',
242 'Name' => 'HMMER_seqfile',
247 elsif (s/^Query(\s+(sequence|HMM))?(?:\s+\d+)?:\s+//o) {
250 # we're in a multi-query report
251 $self->_pushback( $self->{'_hmmidline'} );
252 $self->_pushback( $self->{'_hmmfileline'} );
253 $self->_pushback( $self->{'_hmmseqline'} );
254 $self->_pushback($lineorig);
260 'Name' => 'HMMER_query-def',
265 elsif (s/^Accession:\s+//o) {
269 'Name' => 'HMMER_query-acc',
274 elsif (s/^Description:\s+//o) {
278 'Name' => 'HMMER_querydesc',
283 elsif ( defined $self->{'_reporttype'}
284 && $self->{'_reporttype'} eq 'HMMSEARCH' )
287 # PROCESS HMMSEARCH RESULTS HERE
288 if (/^Scores for complete sequences/o) {
289 while ( defined( $_ = $self->_readline ) ) {
291 next if ( /^Sequence\s+Description/o || /^\-\-\-/o );
293 my ( $name, $n, $evalue, $score ) =
294 ( shift @line, pop @line, pop @line, pop @line );
295 my $desc = join( ' ', @line );
296 push @hitinfo, [ $name, $desc, $evalue, $score ];
297 $hitinfo{$name} = $#hitinfo;
300 elsif (/^Parsed for domains:/o) {
303 while ( defined( $_ = $self->_readline ) ) {
306 $self->_pushback($_);
309 next if ( /^(Model|Sequence)\s+Domain/ || /^\-\-\-/ );
313 my ( $n, $domainnum, $domainct, @vals ) = (
314 m
!^(\S
+)\s
+ # host name
315 (\d
+)/(\d+)\s+ # num/num
(ie
1 of
2)
316 (\d
+)\s
+(\d
+).+?
# sequence start and end
317 (\d
+)\s
+(\d
+)\s
+ # hmm start and end
326 # array lookup so that we can get rid of things
327 # when they've been processed
328 my $info = $hitinfo[ $hitinfo{$n} ];
329 if ( !defined $info ) {
331 "Incomplete Sequence information, can't find $n hitinfo says $hitinfo{$n}"
335 push @hspinfo, [ $n, @vals ];
339 elsif (/^Alignments of top/o) {
340 my ( $prelength, $lastdomain, $count, $width );
344 while ( defined( $_ = $self->_readline ) ) {
346 || /^\s+RF\s+[x\s]+$/o );
347 if ( /^Histogram/o || m!^//!o ) {
348 if ( $self->in_element('hsp') ) {
349 $self->end_element( { 'Name' => 'Hsp' } );
351 if ( $self->within_element('hit') ) {
352 $self->end_element( { 'Name' => 'Hit' } );
359 m
/^\s
*(.+):\s
+domain\s
+(\d
+)\s
+of\s
+(\d
+)\
,\s
+
360 from\s
+(\d
+)\s
+to\s
+(\d
+)/x
363 my ( $name, $domainct, $domaintotal, $from, $to ) =
364 ( $1, $2, $3, $4, $5 );
365 $domaincounter{$name}++;
366 if ( $self->within_element('hit') ) {
367 if ( $self->within_element('hsp') ) {
368 $self->end_element( { 'Name' => 'Hsp' } );
370 $self->end_element( { 'Name' => 'Hit' } );
373 $self->start_element( { 'Name' => 'Hit' } );
376 $hitinfo[ $hitinfo{$name} ] || $self->throw(
377 "Could not find hit info for $name: Insure that your database contains only unique sequence names"
381 if ( $info->[0] ne $name ) {
383 "Somehow the Model table order does not match the order in the domains (got "
385 . ", expected $name)" );
390 'Data' => shift @
{$info}
395 'Name' => 'Hit_desc',
396 'Data' => shift @
{$info}
401 'Name' => 'Hit_signif',
402 'Data' => shift @
{$info}
407 'Name' => 'Hit_score',
408 'Data' => shift @
{$info}
412 $self->start_element( { 'Name' => 'Hsp' } );
415 'Name' => 'Hsp_identity',
421 'Name' => 'Hsp_positive',
425 my $HSPinfo = shift @hspinfo;
426 my $id = shift @
$HSPinfo;
428 if ( $id ne $name ) {
430 "Somehow the domain list details do not match the table (got $id, expected $name)"
433 if ( $domaincounter{$name} == $domaintotal ) {
434 $hitinfo[ $hitinfo{$name} ] = undef;
438 'Name' => 'Hsp_hit-from',
439 'Data' => shift @
$HSPinfo
444 'Name' => 'Hsp_hit-to',
445 'Data' => shift @
$HSPinfo
450 'Name' => 'Hsp_query-from',
451 'Data' => shift @
$HSPinfo
456 'Name' => 'Hsp_query-to',
457 'Data' => shift @
$HSPinfo
462 'Name' => 'Hsp_score',
463 'Data' => shift @
$HSPinfo
468 'Name' => 'Hsp_evalue',
469 'Data' => shift @
$HSPinfo
476 # Might want to change this so that it
477 # accumulates all the of the alignment lines into
478 # three array slots and then tests for the
480 if (/^(\s+\*\-\>)(\S+)/o) { # start of domain
481 $prelength = CORE
::length($1);
484 # deal with fact that start en stop is on same line
486 if ($data =~ s/\<\-?\*?\s*$//)
488 $width = CORE
::length($data);
493 'Name' => 'Hsp_qseq',
500 elsif (/^(\s+)(\S+)\<\-\*\s*$/o) { #end of domain
503 'Name' => 'Hsp_qseq',
507 $width = CORE
::length($2);
510 elsif (( $count != 1 && /^\s+$/o )
511 || CORE
::length($_) == 0
516 elsif ( $count == 0 ) {
517 $prelength -= 3 unless ( $second_tier++ );
518 unless ( defined $prelength ) {
520 # $self->warn("prelength not set");
525 'Name' => 'Hsp_qseq',
526 'Data' => substr( $_, $prelength )
530 elsif ( $count == 1 ) {
531 if ( !defined $prelength ) {
532 $self->warn("prelength not set");
537 'Name' => 'Hsp_midline',
539 substr( $_, $prelength, $width )
544 $self->debug("midline is $_\n")
546 && CORE
::length($_) <= $prelength );
549 'Name' => 'Hsp_midline',
550 'Data' => substr( $_, $prelength )
555 elsif ( $count == 2 ) {
556 if (/^\s+(\S+)\s+(\d+|\-)\s+(\S*)\s+(\d+|\-)/o) {
559 'Name' => 'Hsp_hseq',
565 $self->warn("unrecognized line: $_\n");
568 $count = 0 if $count++ >= 2;
572 elsif ( /^Histogram/o || m!^//!o ) {
573 while ( my $HSPinfo = shift @hspinfo ) {
574 my $id = shift @
$HSPinfo;
575 my $info = [ @
{ $hitinfo[ $hitinfo{$id} ] } ];
576 next unless defined $info;
577 $self->start_element( { 'Name' => 'Hit' } );
581 'Data' => shift @
{$info}
586 'Name' => 'Hit_desc',
587 'Data' => shift @
{$info}
592 'Name' => 'Hit_signif',
593 'Data' => shift @
{$info}
598 'Name' => 'Hit_score',
599 'Data' => shift @
{$info}
602 $self->start_element( { 'Name' => 'Hsp' } );
605 'Name' => 'Hsp_query-from',
606 'Data' => shift @
$HSPinfo
611 'Name' => 'Hsp_query-to',
612 'Data' => shift @
$HSPinfo
617 'Name' => 'Hsp_hit-from',
618 'Data' => shift @
$HSPinfo
623 'Name' => 'Hsp_hit-to',
624 'Data' => shift @
$HSPinfo
629 'Name' => 'Hsp_score',
630 'Data' => shift @
$HSPinfo
635 'Name' => 'Hsp_evalue',
636 'Data' => shift @
$HSPinfo
641 'Name' => 'Hsp_identity',
647 'Name' => 'Hsp_positive',
653 'Name' => 'Hsp_positive',
657 $self->end_element( { 'Name' => 'Hsp' } );
658 $self->end_element( { 'Name' => 'Hit' } );
665 elsif ( defined $self->{'_reporttype'}
666 && $self->{'_reporttype'} eq 'HMMPFAM' )
668 # process HMMPFAM results here
669 if (/^Scores for sequence family/o) {
670 while ( defined( $_ = $self->_readline ) ) {
672 next if ( /^Model\s+Description/o || /^\-\-\-/o );
675 my ( $model, $n, $evalue, $score ) =
676 ( shift @line, pop @line, pop @line, pop @line );
677 my $desc = join( ' ', @line );
678 push @hitinfo, [ $model, $desc, $score, $evalue, $n ];
679 $hitinfo{$model} = $#hitinfo;
682 elsif (/^Parsed for domains:/o) {
684 while ( defined( $_ = $self->_readline ) ) {
687 $self->_pushback($_);
690 next if ( /^Model\s+Domain/o || /^\-\-\-/o );
693 my ( $n, $domainnum, $domainct, @vals ) = (
694 m
!^(\S
+)\s
+ # domain name
695 (\d
+)/(\d
+)\s
+ # domain num out of num
696 (\d
+)\s
+(\d
+).+?
# seq start, end
697 (\d
+)\s
+(\d
+)\s
+ # hmm start, end
705 my $hindex = $hitinfo{$n};
706 if ( !defined $hindex ) {
708 [ $n, '', $vals[5], $vals[6], $domainct ];
709 $hitinfo{$n} = $#hitinfo;
712 my $info = $hitinfo[$hindex];
713 if ( !defined $info ) {
715 "incomplete Domain information, can't find $n hitinfo says $hitinfo{$n}"
719 push @hspinfo, [ $n, @vals ];
723 elsif (/^Alignments of top/o) {
724 my ( $prelength, $lastdomain, $count, $width );
727 while ( defined( $_ = $self->_readline ) ) {
732 && /^\s+RF\s+[x\s]+$/o )
734 $self->debug("$count $_");
735 if ( /^Histogram/o || m!^//!o || /^Query sequence/o ) {
736 if ( $self->in_element('hsp') ) {
737 $self->end_element( { 'Name' => 'Hsp' } );
739 if ( $self->in_element('hit') ) {
740 $self->end_element( { 'Name' => 'Hit' } );
742 $self->_pushback($_);
746 if (m/(\S+):.*from\s+(\d+)\s+to\s+(\d+)/o) {
747 my ( $name, $from, $to ) = ( $1, $2, $3 );
749 if ( $self->within_element('hit') ) {
750 if ( $self->in_element('hsp') ) {
751 $self->end_element( { 'Name' => 'Hsp' } );
753 $self->end_element( { 'Name' => 'Hit' } );
755 my $info = [ @
{ $hitinfo[ $hitinfo{$name} ] } ];
757 || $info->[0] ne $name )
760 "Somehow the Model table order does not match the order in the domains (got "
762 . ", expected $name). We're back loading this from the alignment information instead"
766 /score\s+([^,\s]+),\s+E\s+=\s+(\S+)/ox
768 push @hitinfo, $info;
769 $hitinfo{$name} = $#hitinfo;
771 $self->start_element( { 'Name' => 'Hit' } );
776 'Data' => shift @
{$info}
781 'Name' => 'Hit_desc',
782 'Data' => shift @
{$info}
787 'Name' => 'Hit_score',
788 'Data' => shift @
{$info}
793 'Name' => 'Hit_signif',
794 'Data' => shift @
{$info}
798 $self->start_element( { 'Name' => 'Hsp' } );
801 'Name' => 'Hsp_identity',
807 'Name' => 'Hsp_positive',
811 my $HSPinfo = shift @hspinfo;
812 my $id = shift @
$HSPinfo;
814 if ( $id ne $name ) {
816 "Somehow the domain list details do not match the table (got $id, expected $name)"
821 'Name' => 'Hsp_query-from',
822 'Data' => shift @
$HSPinfo
827 'Name' => 'Hsp_query-to',
828 'Data' => shift @
$HSPinfo
833 'Name' => 'Hsp_hit-from',
834 'Data' => shift @
$HSPinfo
839 'Name' => 'Hsp_hit-to',
840 'Data' => shift @
$HSPinfo
845 'Name' => 'Hsp_score',
846 'Data' => shift @
$HSPinfo
851 'Name' => 'Hsp_evalue',
852 'Data' => shift @
$HSPinfo
858 if (/^(\s+\*\-\>)(\S+)/o) {
861 $prelength = CORE
::length($1);
864 # deal with fact that start en stop is on same line
866 if ($data =~ s/\<\-?\*?\s*$//)
868 $width = CORE
::length($data);
873 'Name' => 'Hsp_hseq',
881 elsif (/^(\s+)(\S+)\<\-?\*?\s*$/o) {
884 $prelength -= 3 unless ( $second_tier++ );
887 'Name' => 'Hsp_hseq',
891 $width = CORE
::length($2);
894 elsif (CORE
::length($_) == 0
895 || ( $count != 1 && /^\s+$/o )
900 elsif ( $count == 0 ) {
901 $prelength -= 3 unless ( $second_tier++ );
902 unless ( defined $prelength ) {
904 # $self->warn("prelength not set");
909 'Name' => 'Hsp_hseq',
910 'Data' => substr( $_, $prelength )
914 elsif ( $count == 1 ) {
915 if ( !defined $prelength ) {
916 $self->warn("prelength not set");
921 'Name' => 'Hsp_midline',
923 substr( $_, $prelength, $width )
930 'Name' => 'Hsp_midline',
931 'Data' => substr( $_, $prelength )
936 elsif ( $count == 2 ) {
937 if ( /^\s+(\S+)\s+(\d+)\s+(\S+)\s+(\d+)/o
938 || /^\s+(\S+)\s+(\-)\s+(\S*)\s+(\-)/o )
942 'Name' => 'Hsp_qseq',
949 "unrecognized line ($count): $_\n");
952 $count = 0 if $count++ >= 2;
956 elsif ( /^Histogram/o || m!^//!o ) {
958 while ( my $HSPinfo = shift @hspinfo ) {
959 my $id = shift @
$HSPinfo;
960 my $info = [ @
{ $hitinfo[ $hitinfo{$id} ] } ];
961 next unless defined $info;
962 $self->start_element( { 'Name' => 'Hit' } );
966 'Data' => shift @
{$info}
971 'Name' => 'Hit_desc',
972 'Data' => shift @
{$info}
977 'Name' => 'Hit_signif',
978 'Data' => shift @
{$info}
983 'Name' => 'Hit_score',
984 'Data' => shift @
{$info}
987 $self->start_element( { 'Name' => 'Hsp' } );
990 'Name' => 'Hsp_query-from',
991 'Data' => shift @
$HSPinfo
996 'Name' => 'Hsp_query-to',
997 'Data' => shift @
$HSPinfo
1002 'Name' => 'Hsp_hit-from',
1003 'Data' => shift @
$HSPinfo
1008 'Name' => 'Hsp_hit-to',
1009 'Data' => shift @
$HSPinfo
1014 'Name' => 'Hsp_score',
1015 'Data' => shift @
$HSPinfo
1020 'Name' => 'Hsp_evalue',
1021 'Data' => shift @
$HSPinfo
1026 'Name' => 'Hsp_identity',
1032 'Name' => 'Hsp_positive',
1038 'Name' => 'Hsp_positive',
1042 $self->end_element( { 'Name' => 'Hsp' } );
1043 $self->end_element( { 'Name' => 'Hit' } );
1055 $self->end_element( { 'Name' => 'HMMER_Output' } ) unless !$seentop;
1056 return $self->end_document();
1059 =head2 start_element
1061 Title : start_element
1062 Usage : $eventgenerator->start_element
1063 Function: Handles a start element event
1065 Args : hashref with at least 2 keys 'Data' and 'Name'
1071 my ( $self, $data ) = @_;
1073 # we currently don't care about attributes
1074 my $nm = $data->{'Name'};
1075 my $type = $MODEMAP{$nm};
1077 if ( $self->_eventHandler->will_handle($type) ) {
1078 my $func = sprintf( "start_%s", lc $type );
1079 $self->_eventHandler->$func( $data->{'Attributes'} );
1081 unshift @
{ $self->{'_elements'} }, $type;
1084 && $type eq 'result' )
1086 $self->{'_values'} = {};
1087 $self->{'_result'} = undef;
1093 Title : start_element
1094 Usage : $eventgenerator->end_element
1095 Function: Handles an end element event
1097 Args : hashref with at least 2 keys 'Data' and 'Name'
1103 my ( $self, $data ) = @_;
1104 my $nm = $data->{'Name'};
1105 my $type = $MODEMAP{$nm};
1108 if ( $nm eq 'HMMER_program' ) {
1109 if ( $self->{'_last_data'} =~ /(HMM\S+)/i ) {
1110 $self->{'_reporttype'} = uc $1;
1114 # Hsp are sort of weird, in that they end when another
1115 # object begins so have to detect this in end_element for now
1116 if ( $nm eq 'Hsp' ) {
1117 foreach (qw(Hsp_qseq Hsp_midline Hsp_hseq)) {
1118 my $data = $self->{'_last_hspdata'}->{$_};
1119 if ($data && $_ eq 'Hsp_hseq') {
1120 # replace hmm '.' gap symbol by '-'
1130 $self->{'_last_hspdata'} = {};
1133 if ( $self->_eventHandler->will_handle($type) ) {
1134 my $func = sprintf( "end_%s", lc $type );
1135 $rc = $self->_eventHandler->$func( $self->{'_reporttype'},
1136 $self->{'_values'} );
1138 my $lastelem = shift @
{ $self->{'_elements'} };
1140 elsif ( $MAPPING{$nm} ) {
1141 if ( ref( $MAPPING{$nm} ) =~ /hash/i ) {
1142 my $key = ( keys %{ $MAPPING{$nm} } )[0];
1143 $self->{'_values'}->{$key}->{ $MAPPING{$nm}->{$key} } =
1144 $self->{'_last_data'};
1147 $self->{'_values'}->{ $MAPPING{$nm} } = $self->{'_last_data'};
1151 $self->debug("unknown nm $nm, ignoring\n");
1153 $self->{'_last_data'} = ''; # remove read data if we are at
1155 $self->{'_result'} = $rc if ( defined $type && $type eq 'result' );
1162 Usage : $eventhandler->element({'Name' => $name, 'Data' => $str});
1163 Function: Convience method that calls start_element, characters, end_element
1165 Args : Hash ref with the keys 'Name' and 'Data'
1171 my ( $self, $data ) = @_;
1172 $self->start_element($data);
1173 $self->characters($data);
1174 $self->end_element($data);
1180 Usage : $eventgenerator->characters($str)
1181 Function: Send a character events
1189 my ( $self, $data ) = @_;
1191 if ( $self->in_element('hsp')
1192 && $data->{'Name'} =~ /Hsp\_(qseq|hseq|midline)/o
1193 && defined $data->{'Data'} )
1195 $self->{'_last_hspdata'}->{ $data->{'Name'} } .= $data->{'Data'};
1197 return unless ( defined $data->{'Data'} && $data->{'Data'} !~ /^\s+$/o );
1199 $self->{'_last_data'} = $data->{'Data'};
1202 =head2 within_element
1204 Title : within_element
1205 Usage : if( $eventgenerator->within_element($element) ) {}
1206 Function: Test if we are within a particular element
1207 This is different than 'in' because within can be tested
1210 Args : string element name
1215 sub within_element
{
1216 my ( $self, $name ) = @_;
1219 || !defined $self->{'_elements'}
1220 || scalar @
{ $self->{'_elements'} } == 0 );
1221 foreach ( @
{ $self->{'_elements'} } ) {
1222 return 1 if ( $_ eq $name );
1230 Usage : if( $eventgenerator->in_element($element) ) {}
1231 Function: Test if we are in a particular element
1232 This is different than 'within' because 'in' only
1233 tests its immediete parent.
1235 Args : string element name
1241 my ( $self, $name ) = @_;
1242 return 0 if !defined $self->{'_elements'}->[0];
1243 return ( $self->{'_elements'}->[0] eq $name );
1246 =head2 start_document
1248 Title : start_document
1249 Usage : $eventgenerator->start_document
1250 Function: Handle a start document event
1257 sub start_document
{
1259 $self->{'_lasttype'} = '';
1260 $self->{'_values'} = {};
1261 $self->{'_result'} = undef;
1262 $self->{'_elements'} = [];
1267 Title : end_document
1268 Usage : $eventgenerator->end_document
1269 Function: Handles an end document event
1270 Returns : Bio::Search::Result::ResultI object
1278 return $self->{'_result'};
1283 Title : result_count
1284 Usage : my $count = $searchio->result_count
1285 Function: Returns the number of results we have processed
1294 return $self->{'_result_count'};