Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/SearchIO/blast.pm @ 0:1f6dce3d34e0
Uploaded
| author | mahtabm |
|---|---|
| date | Thu, 11 Apr 2013 02:01:53 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:1f6dce3d34e0 |
|---|---|
| 1 # $Id: blast.pm,v 1.42.2.14 2003/09/15 16:19:01 jason Exp $ | |
| 2 # | |
| 3 # BioPerl module for Bio::SearchIO::blast | |
| 4 # | |
| 5 # Cared for by Jason Stajich <jason@bioperl.org> | |
| 6 # | |
| 7 # Copyright Jason Stajich | |
| 8 # | |
| 9 # You may distribute this module under the same terms as perl itself | |
| 10 | |
| 11 # POD documentation - main docs before the code | |
| 12 | |
| 13 =head1 NAME | |
| 14 | |
| 15 Bio::SearchIO::blast - Event generator for event based parsing of blast reports | |
| 16 | |
| 17 =head1 SYNOPSIS | |
| 18 | |
| 19 # Do not use this object directly - it is used as part of the | |
| 20 # Bio::SearchIO system. | |
| 21 | |
| 22 use Bio::SearchIO; | |
| 23 my $searchio = new Bio::SearchIO(-format => 'blast', | |
| 24 -file => 't/data/ecolitst.bls'); | |
| 25 while( my $result = $searchio->next_result ) { | |
| 26 while( my $hit = $result->next_hit ) { | |
| 27 while( my $hsp = $hit->next_hsp ) { | |
| 28 # ... | |
| 29 } | |
| 30 } | |
| 31 } | |
| 32 | |
| 33 =head1 DESCRIPTION | |
| 34 | |
| 35 This object encapsulated the necessary methods for generating events | |
| 36 suitable for building Bio::Search objects from a BLAST report file. | |
| 37 Read the L<Bio::SearchIO> for more information about how to use this. | |
| 38 | |
| 39 =head1 FEEDBACK | |
| 40 | |
| 41 =head2 Mailing Lists | |
| 42 | |
| 43 User feedback is an integral part of the evolution of this and other | |
| 44 Bioperl modules. Send your comments and suggestions preferably to | |
| 45 the Bioperl mailing list. Your participation is much appreciated. | |
| 46 | |
| 47 bioperl-l@bioperl.org - General discussion | |
| 48 http://bioperl.org/MailList.shtml - About the mailing lists | |
| 49 | |
| 50 =head2 Reporting Bugs | |
| 51 | |
| 52 Report bugs to the Bioperl bug tracking system to help us keep track | |
| 53 of the bugs and their resolution. Bug reports can be submitted via | |
| 54 email or the web: | |
| 55 | |
| 56 bioperl-bugs@bioperl.org | |
| 57 http://bugzilla.bioperl.org/ | |
| 58 | |
| 59 =head1 AUTHOR - Jason Stajich | |
| 60 | |
| 61 Email jason@bioperl.org | |
| 62 | |
| 63 Describe contact details here | |
| 64 | |
| 65 =head1 CONTRIBUTORS | |
| 66 | |
| 67 Additional contributors names and emails here | |
| 68 | |
| 69 =head1 APPENDIX | |
| 70 | |
| 71 The rest of the documentation details each of the object methods. | |
| 72 Internal methods are usually preceded with a _ | |
| 73 | |
| 74 =cut | |
| 75 | |
| 76 | |
| 77 # Let the code begin... | |
| 78 | |
| 79 | |
| 80 | |
| 81 package Bio::SearchIO::blast; | |
| 82 use strict; | |
| 83 use vars qw(@ISA %MAPPING %MODEMAP $DEFAULT_BLAST_WRITER_CLASS); | |
| 84 use Bio::SearchIO; | |
| 85 | |
| 86 @ISA = qw(Bio::SearchIO ); | |
| 87 | |
| 88 BEGIN { | |
| 89 # mapping of NCBI Blast terms to Bioperl hash keys | |
| 90 %MODEMAP = ('BlastOutput' => 'result', | |
| 91 'Hit' => 'hit', | |
| 92 'Hsp' => 'hsp' | |
| 93 ); | |
| 94 | |
| 95 # This should really be done more intelligently, like with | |
| 96 # XSLT | |
| 97 | |
| 98 %MAPPING = | |
| 99 ( | |
| 100 'Hsp_bit-score' => 'HSP-bits', | |
| 101 'Hsp_score' => 'HSP-score', | |
| 102 'Hsp_evalue' => 'HSP-evalue', | |
| 103 'Hsp_pvalue' => 'HSP-pvalue', | |
| 104 'Hsp_query-from' => 'HSP-query_start', | |
| 105 'Hsp_query-to' => 'HSP-query_end', | |
| 106 'Hsp_hit-from' => 'HSP-hit_start', | |
| 107 'Hsp_hit-to' => 'HSP-hit_end', | |
| 108 'Hsp_positive' => 'HSP-conserved', | |
| 109 'Hsp_identity' => 'HSP-identical', | |
| 110 'Hsp_gaps' => 'HSP-hsp_gaps', | |
| 111 'Hsp_hitgaps' => 'HSP-hit_gaps', | |
| 112 'Hsp_querygaps' => 'HSP-query_gaps', | |
| 113 'Hsp_qseq' => 'HSP-query_seq', | |
| 114 'Hsp_hseq' => 'HSP-hit_seq', | |
| 115 'Hsp_midline' => 'HSP-homology_seq', | |
| 116 'Hsp_align-len' => 'HSP-hsp_length', | |
| 117 'Hsp_query-frame'=> 'HSP-query_frame', | |
| 118 'Hsp_hit-frame' => 'HSP-hit_frame', | |
| 119 | |
| 120 'Hit_id' => 'HIT-name', | |
| 121 'Hit_len' => 'HIT-length', | |
| 122 'Hit_accession' => 'HIT-accession', | |
| 123 'Hit_def' => 'HIT-description', | |
| 124 'Hit_signif' => 'HIT-significance', | |
| 125 'Hit_score' => 'HIT-score', | |
| 126 'Iteration_iter-num' => 'HIT-iteration', | |
| 127 | |
| 128 'BlastOutput_program' => 'RESULT-algorithm_name', | |
| 129 'BlastOutput_version' => 'RESULT-algorithm_version', | |
| 130 'BlastOutput_query-def'=> 'RESULT-query_name', | |
| 131 'BlastOutput_query-len'=> 'RESULT-query_length', | |
| 132 'BlastOutput_query-acc'=> 'RESULT-query_accession', | |
| 133 'BlastOutput_querydesc'=> 'RESULT-query_description', | |
| 134 'BlastOutput_db' => 'RESULT-database_name', | |
| 135 'BlastOutput_db-len' => 'RESULT-database_entries', | |
| 136 'BlastOutput_db-let' => 'RESULT-database_letters', | |
| 137 | |
| 138 'Parameters_matrix' => { 'RESULT-parameters' => 'matrix'}, | |
| 139 'Parameters_expect' => { 'RESULT-parameters' => 'expect'}, | |
| 140 'Parameters_include' => { 'RESULT-parameters' => 'include'}, | |
| 141 'Parameters_sc-match' => { 'RESULT-parameters' => 'match'}, | |
| 142 'Parameters_sc-mismatch' => { 'RESULT-parameters' => 'mismatch'}, | |
| 143 'Parameters_gap-open' => { 'RESULT-parameters' => 'gapopen'}, | |
| 144 'Parameters_gap-extend'=> { 'RESULT-parameters' => 'gapext'}, | |
| 145 'Parameters_filter' => {'RESULT-parameters' => 'filter'}, | |
| 146 'Parameters_allowgaps' => { 'RESULT-parameters' => 'allowgaps'}, | |
| 147 | |
| 148 'Statistics_db-len' => {'RESULT-statistics' => 'dbentries'}, | |
| 149 'Statistics_db-let' => { 'RESULT-statistics' => 'dbletters'}, | |
| 150 'Statistics_hsp-len' => { 'RESULT-statistics' => 'effective_hsplength'}, | |
| 151 'Statistics_query-len' => { 'RESULT-statistics' => 'querylength'}, | |
| 152 'Statistics_eff-space' => { 'RESULT-statistics' => 'effectivespace'}, | |
| 153 'Statistics_eff-spaceused' => { 'RESULT-statistics' => 'effectivespaceused'}, | |
| 154 'Statistics_eff-dblen' => { 'RESULT-statistics' => 'effectivedblength'}, | |
| 155 'Statistics_kappa' => { 'RESULT-statistics' => 'kappa' }, | |
| 156 'Statistics_lambda' => { 'RESULT-statistics' => 'lambda' }, | |
| 157 'Statistics_entropy' => { 'RESULT-statistics' => 'entropy'}, | |
| 158 'Statistics_framewindow'=> { 'RESULT-statistics' => 'frameshiftwindow'}, | |
| 159 'Statistics_decay'=> { 'RESULT-statistics' => 'decayconst'}, | |
| 160 | |
| 161 'Statistics_T'=> { 'RESULT-statistics' => 'T'}, | |
| 162 'Statistics_A'=> { 'RESULT-statistics' => 'A'}, | |
| 163 'Statistics_X1'=> { 'RESULT-statistics' => 'X1'}, | |
| 164 'Statistics_X2'=> { 'RESULT-statistics' => 'X2'}, | |
| 165 'Statistics_S1'=> { 'RESULT-statistics' => 'S1'}, | |
| 166 'Statistics_S2'=> { 'RESULT-statistics' => 'S2'}, | |
| 167 'Statistics_hit_to_db' => { 'RESULT-statistics' => 'Hits_to_DB'}, | |
| 168 'Statistics_num_extensions' => { 'RESULT-statistics' => 'num_extensions'}, | |
| 169 'Statistics_num_extensions' => { 'RESULT-statistics' => 'num_extensions'}, | |
| 170 'Statistics_num_suc_extensions' => { 'RESULT-statistics' => 'num_successful_extensions'}, | |
| 171 'Statistics_seqs_better_than_cutoff' => { 'RESULT-statistics' => 'seqs_better_than_cutoff'}, | |
| 172 'Statistics_posted_date' => { 'RESULT-statistics' => 'posted_date'}, | |
| 173 | |
| 174 # WU-BLAST stats | |
| 175 'Statistics_DFA_states'=> { 'RESULT-statistics' => 'num_dfa_states'}, | |
| 176 'Statistics_DFA_size'=> { 'RESULT-statistics' => 'dfa_size'}, | |
| 177 | |
| 178 'Statistics_search_cputime' => { 'RESULT-statistics' => 'search_cputime'}, | |
| 179 'Statistics_total_cputime' => { 'RESULT-statistics' => 'total_cputime'}, | |
| 180 'Statistics_search_actualtime' => { 'RESULT-statistics' => 'search_actualtime'}, | |
| 181 'Statistics_total_actualtime' => { 'RESULT-statistics' => 'total_actualtime'}, | |
| 182 | |
| 183 'Statistics_noprocessors' => { 'RESULT-statistics' => 'no_of_processors'}, | |
| 184 'Statistics_neighbortime' => { 'RESULT-statistics' => 'neighborhood_generate_time'}, | |
| 185 'Statistics_starttime' => { 'RESULT-statistics' => 'start_time'}, | |
| 186 'Statistics_endtime' => { 'RESULT-statistics' => 'end_time'}, | |
| 187 ); | |
| 188 | |
| 189 $DEFAULT_BLAST_WRITER_CLASS = 'Bio::Search::Writer::HitTableWriter'; | |
| 190 } | |
| 191 | |
| 192 | |
| 193 =head2 new | |
| 194 | |
| 195 Title : new | |
| 196 Usage : my $obj = new Bio::SearchIO::blast(); | |
| 197 Function: Builds a new Bio::SearchIO::blast object | |
| 198 Returns : Bio::SearchIO::blast | |
| 199 Args : -fh/-file => filehandle/filename to BLAST file | |
| 200 -format => 'blast' | |
| 201 | |
| 202 =cut | |
| 203 | |
| 204 =head2 next_result | |
| 205 | |
| 206 Title : next_result | |
| 207 Usage : my $hit = $searchio->next_result; | |
| 208 Function: Returns the next Result from a search | |
| 209 Returns : Bio::Search::Result::ResultI object | |
| 210 Args : none | |
| 211 | |
| 212 =cut | |
| 213 | |
| 214 sub next_result{ | |
| 215 my ($self) = @_; | |
| 216 | |
| 217 my $data = ''; | |
| 218 my $seentop = 0; | |
| 219 my ($reporttype,$seenquery,$reportline); | |
| 220 $self->start_document(); | |
| 221 my @hit_signifs; | |
| 222 | |
| 223 while( defined ($_ = $self->_readline )) { | |
| 224 next if( /^\s+$/); # skip empty lines | |
| 225 next if( /CPU time:/); | |
| 226 next if( /^>\s*$/); | |
| 227 | |
| 228 if( /^([T]?BLAST[NPX])\s*(.+)$/i || | |
| 229 /^(PSITBLASTN)\s+(.+)$/i || | |
| 230 /^(RPS-BLAST)\s*(.+)$/i || | |
| 231 /^(MEGABLAST)\s*(.+)$/i | |
| 232 ) { | |
| 233 if( $seentop ) { | |
| 234 $self->_pushback($_); | |
| 235 $self->in_element('hsp') && | |
| 236 $self->end_element({ 'Name' => 'Hsp'}); | |
| 237 $self->in_element('hit') && | |
| 238 $self->end_element({ 'Name' => 'Hit'}); | |
| 239 $self->end_element({ 'Name' => 'BlastOutput'}); | |
| 240 return $self->end_document(); | |
| 241 } | |
| 242 $self->start_element({ 'Name' => 'BlastOutput' } ); | |
| 243 $self->{'_result_count'}++; | |
| 244 $seentop = 1; | |
| 245 $reporttype = $1; | |
| 246 $reportline = $_; # to fix the fact that RPS-BLAST output is wrong | |
| 247 $self->element({ 'Name' => 'BlastOutput_program', | |
| 248 'Data' => $reporttype}); | |
| 249 | |
| 250 $self->element({ 'Name' => 'BlastOutput_version', | |
| 251 'Data' => $2}); | |
| 252 } elsif ( /^Query=\s*(.+)$/ ) { | |
| 253 my $q = $1; | |
| 254 my $size = 0; | |
| 255 if( defined $seenquery ) { | |
| 256 $self->_pushback($reportline); | |
| 257 $self->_pushback($_); | |
| 258 $self->in_element('hsp') && | |
| 259 $self->end_element({'Name'=> 'Hsp'}); | |
| 260 $self->in_element('hit') && | |
| 261 $self->end_element({'Name'=> 'Hit'}); | |
| 262 $self->end_element({'Name' => 'BlastOutput'}); | |
| 263 return $self->end_document(); | |
| 264 } else { | |
| 265 if( ! defined $reporttype ) { | |
| 266 $self->start_element({'Name' => 'BlastOutput'}); | |
| 267 $seentop = 1; | |
| 268 $self->{'_result_count'}++; | |
| 269 } | |
| 270 } | |
| 271 $seenquery = $q; | |
| 272 $_ = $self->_readline; | |
| 273 while( defined ($_) ) { | |
| 274 if( /^Database:/ ) { | |
| 275 $self->_pushback($_); | |
| 276 last; | |
| 277 } | |
| 278 chomp; | |
| 279 if( /\((\-?[\d,]+)\s+letters.*\)/ ) { | |
| 280 $size = $1; | |
| 281 $size =~ s/,//g; | |
| 282 last; | |
| 283 } else { | |
| 284 $q .= " $_"; | |
| 285 $q =~ s/ +/ /g; | |
| 286 $q =~ s/^ | $//g; | |
| 287 } | |
| 288 | |
| 289 $_ = $self->_readline; | |
| 290 } | |
| 291 chomp($q); | |
| 292 my ($nm,$desc) = split(/\s+/,$q,2); | |
| 293 $self->element({ 'Name' => 'BlastOutput_query-def', | |
| 294 'Data' => $nm}); | |
| 295 $self->element({ 'Name' => 'BlastOutput_query-len', | |
| 296 'Data' => $size}); | |
| 297 defined $desc && $desc =~ s/\s+$//; | |
| 298 $self->element({ 'Name' => 'BlastOutput_querydesc', | |
| 299 'Data' => $desc}); | |
| 300 | |
| 301 if( my @pieces = split(/\|/,$nm) ) { | |
| 302 my $acc = pop @pieces; | |
| 303 $acc = pop @pieces if( ! defined $acc || $acc =~ /^\s+$/); | |
| 304 $self->element({ 'Name' => 'BlastOutput_query-acc', | |
| 305 'Data' => $acc}); | |
| 306 } | |
| 307 | |
| 308 } elsif( /Sequences producing significant alignments:/ ) { | |
| 309 descline: | |
| 310 while( defined ($_ = $self->_readline() )) { | |
| 311 if( /^>/ ) { | |
| 312 $self->_pushback($_); | |
| 313 last descline; | |
| 314 } elsif( /(\d+)\s+([\d\.\-eE]+)(\s+\d+)?\s*$/) { | |
| 315 # the last match is for gapped BLAST output | |
| 316 # which will report the number of HSPs for the Hit | |
| 317 my ($score, $evalue) = ($1, $2); | |
| 318 # Some data clean-up so e-value will appear numeric to perl | |
| 319 $evalue =~ s/^e/1e/i; | |
| 320 push @hit_signifs, [ $evalue, $score ]; | |
| 321 } | |
| 322 } | |
| 323 } elsif( /Sequences producing High-scoring Segment Pairs:/ ) { | |
| 324 # skip the next line | |
| 325 $_ = $self->_readline(); | |
| 326 | |
| 327 while( defined ($_ = $self->_readline() ) && | |
| 328 ! /^\s+$/ ) { | |
| 329 my @line = split; | |
| 330 pop @line; # throw away first number which is for 'N'col | |
| 331 push @hit_signifs, [ pop @line, pop @line]; | |
| 332 } | |
| 333 } elsif ( /^Database:\s*(.+)$/ ) { | |
| 334 my $db = $1; | |
| 335 | |
| 336 while( defined($_ = $self->_readline) ) { | |
| 337 if( /^\s+(\-?[\d\,]+)\s+sequences\;\s+(\-?[\d,]+)\s+total\s+letters/){ | |
| 338 my ($s,$l) = ($1,$2); | |
| 339 $s =~ s/,//g; | |
| 340 $l =~ s/,//g; | |
| 341 $self->element({'Name' => 'BlastOutput_db-len', | |
| 342 'Data' => $s}); | |
| 343 $self->element({'Name' => 'BlastOutput_db-let', | |
| 344 'Data' => $l}); | |
| 345 last; | |
| 346 } else { | |
| 347 chomp; | |
| 348 $db .= $_; | |
| 349 } | |
| 350 } | |
| 351 $self->element({'Name' => 'BlastOutput_db', | |
| 352 'Data' => $db}); | |
| 353 } elsif( /^>(\S+)\s*(.*)?/ ) { | |
| 354 chomp; | |
| 355 | |
| 356 $self->in_element('hsp') && $self->end_element({ 'Name' => 'Hsp'}); | |
| 357 $self->in_element('hit') && $self->end_element({ 'Name' => 'Hit'}); | |
| 358 | |
| 359 $self->start_element({ 'Name' => 'Hit'}); | |
| 360 my $id = $1; | |
| 361 my $restofline = $2; | |
| 362 $self->element({ 'Name' => 'Hit_id', | |
| 363 'Data' => $id}); | |
| 364 my ($acc, $version); | |
| 365 if ($id =~ /(gb|emb|dbj|sp|pdb|bbs|ref|lcl)\|(.*)\|(.*)/) { | |
| 366 ($acc, $version) = split /\./, $2; | |
| 367 } elsif ($id =~ /(pir|prf|pat|gnl)\|(.*)\|(.*)/) { | |
| 368 ($acc, $version) = split /\./, $3; | |
| 369 } else { | |
| 370 #punt, not matching the db's at ftp://ftp.ncbi.nih.gov/blast/db/README | |
| 371 #Database Name Identifier Syntax | |
| 372 #============================ ======================== | |
| 373 #GenBank gb|accession|locus | |
| 374 #EMBL Data Library emb|accession|locus | |
| 375 #DDBJ, DNA Database of Japan dbj|accession|locus | |
| 376 #NBRF PIR pir||entry | |
| 377 #Protein Research Foundation prf||name | |
| 378 #SWISS-PROT sp|accession|entry name | |
| 379 #Brookhaven Protein Data Bank pdb|entry|chain | |
| 380 #Patents pat|country|number | |
| 381 #GenInfo Backbone Id bbs|number | |
| 382 #General database identifier gnl|database|identifier | |
| 383 #NCBI Reference Sequence ref|accession|locus | |
| 384 #Local Sequence identifier lcl|identifier | |
| 385 $acc=$id; | |
| 386 } | |
| 387 $self->element({ 'Name' => 'Hit_accession', | |
| 388 'Data' => $acc}); | |
| 389 | |
| 390 my $v = shift @hit_signifs; | |
| 391 if( defined $v ) { | |
| 392 $self->element({'Name' => 'Hit_signif', | |
| 393 'Data' => $v->[0]}); | |
| 394 $self->element({'Name' => 'Hit_score', | |
| 395 'Data' => $v->[1]}); | |
| 396 } | |
| 397 while(defined($_ = $self->_readline()) ) { | |
| 398 next if( /^\s+$/ ); | |
| 399 chomp; | |
| 400 if( /Length\s*=\s*([\d,]+)/ ) { | |
| 401 my $l = $1; | |
| 402 $l =~ s/\,//g; | |
| 403 $self->element({ 'Name' => 'Hit_len', | |
| 404 'Data' => $l }); | |
| 405 last; | |
| 406 } else { | |
| 407 $restofline .= $_; | |
| 408 } | |
| 409 } | |
| 410 $restofline =~ s/\s+/ /g; | |
| 411 $self->element({ 'Name' => 'Hit_def', | |
| 412 'Data' => $restofline}); | |
| 413 } elsif( /\s+(Plus|Minus) Strand HSPs:/i ) { | |
| 414 next; | |
| 415 } elsif( ($self->in_element('hit') || | |
| 416 $self->in_element('hsp')) && # wublast | |
| 417 m/Score\s*=\s*(\S+)\s* # Bit score | |
| 418 \(([\d\.]+)\s*bits\), # Raw score | |
| 419 \s*Expect\s*=\s*([^,\s]+), # E-value | |
| 420 \s*(?:Sum)?\s* # SUM | |
| 421 P(?:\(\d+\))?\s*=\s*([^,\s]+) # P-value | |
| 422 /ox | |
| 423 ) { | |
| 424 my ($score, $bits,$evalue,$pvalue) = ($1,$2,$3,$4); | |
| 425 $evalue =~ s/^e/1e/i; | |
| 426 $pvalue =~ s/^e/1e/i; | |
| 427 $self->in_element('hsp') && $self->end_element({'Name' => 'Hsp'}); | |
| 428 $self->start_element({'Name' => 'Hsp'}); | |
| 429 $self->element( { 'Name' => 'Hsp_score', | |
| 430 'Data' => $score}); | |
| 431 $self->element( { 'Name' => 'Hsp_bit-score', | |
| 432 'Data' => $bits}); | |
| 433 $self->element( { 'Name' => 'Hsp_evalue', | |
| 434 'Data' => $evalue}); | |
| 435 $self->element( {'Name' => 'Hsp_pvalue', | |
| 436 'Data' => $pvalue}); | |
| 437 } elsif( ($self->in_element('hit') || | |
| 438 $self->in_element('hsp')) && # ncbi blast | |
| 439 m/Score\s*=\s*(\S+)\s*bits\s* # Bit score | |
| 440 (?:\((\d+)\))?, # Missing for BLAT pseudo-BLAST fmt | |
| 441 \s*Expect(?:\(\d+\))?\s*=\s*(\S+) # E-value | |
| 442 /ox) { | |
| 443 my ($bits,$score,$evalue) = ($1,$2,$3); | |
| 444 $evalue =~ s/^e/1e/i; | |
| 445 $self->in_element('hsp') && $self->end_element({ 'Name' => 'Hsp'}); | |
| 446 | |
| 447 $self->start_element({'Name' => 'Hsp'}); | |
| 448 $self->element( { 'Name' => 'Hsp_score', | |
| 449 'Data' => $score}); | |
| 450 $self->element( { 'Name' => 'Hsp_bit-score', | |
| 451 'Data' => $bits}); | |
| 452 $self->element( { 'Name' => 'Hsp_evalue', | |
| 453 'Data' => $evalue}); | |
| 454 } elsif( $self->in_element('hsp') && | |
| 455 m/Identities\s*=\s*(\d+)\s*\/\s*(\d+)\s*[\d\%\(\)]+\s* | |
| 456 (?:,\s*Positives\s*=\s*(\d+)\/(\d+)\s*[\d\%\(\)]+\s*)? # pos only valid for Protein alignments | |
| 457 (?:\,\s*Gaps\s*=\s*(\d+)\/(\d+))? # Gaps | |
| 458 /oxi | |
| 459 ) { | |
| 460 $self->element( { 'Name' => 'Hsp_identity', | |
| 461 'Data' => $1}); | |
| 462 $self->element( {'Name' => 'Hsp_align-len', | |
| 463 'Data' => $2}); | |
| 464 if( defined $3 ) { | |
| 465 $self->element( { 'Name' => 'Hsp_positive', | |
| 466 'Data' => $3}); | |
| 467 } else { | |
| 468 $self->element( { 'Name' => 'Hsp_positive', | |
| 469 'Data' => $1}); | |
| 470 } | |
| 471 if( defined $6 ) { | |
| 472 $self->element( { 'Name' => 'Hsp_gaps', | |
| 473 'Data' => $5}); | |
| 474 } | |
| 475 | |
| 476 $self->{'_Query'} = { 'begin' => 0, 'end' => 0}; | |
| 477 $self->{'_Sbjct'} = { 'begin' => 0, 'end' => 0}; | |
| 478 | |
| 479 if( /(Frame\s*=\s*.+)$/ ) { | |
| 480 # handle wu-blast Frame listing on same line | |
| 481 $self->_pushback($1); | |
| 482 } | |
| 483 } elsif( $self->in_element('hsp') && | |
| 484 /Strand\s*=\s*(Plus|Minus)\s*\/\s*(Plus|Minus)/i ) { | |
| 485 # consume this event ( we infer strand from start/end) | |
| 486 next; | |
| 487 } elsif( $self->in_element('hsp') && | |
| 488 /Frame\s*=\s*([\+\-][1-3])\s*(\/\s*([\+\-][1-3]))?/ ){ | |
| 489 my ($one,$two)= ($1,$2); | |
| 490 my ($queryframe,$hitframe); | |
| 491 if( $reporttype eq 'TBLASTX' ) { | |
| 492 ($queryframe,$hitframe) = ($one,$two); | |
| 493 $hitframe =~ s/\/\s*//g; | |
| 494 } elsif( $reporttype =~ /^(PSI)?TBLASTN/oi ) { | |
| 495 ($hitframe,$queryframe) = ($one,0); | |
| 496 } elsif( $reporttype eq 'BLASTX' ) { | |
| 497 ($queryframe,$hitframe) = ($one,0); | |
| 498 } | |
| 499 $self->element({'Name' => 'Hsp_query-frame', | |
| 500 'Data' => $queryframe}); | |
| 501 | |
| 502 $self->element({'Name' => 'Hsp_hit-frame', | |
| 503 'Data' => $hitframe}); | |
| 504 } elsif( /^Parameters:/ || /^\s+Database:\s+?/ || /^\s+Subset/ || | |
| 505 /^\s+Subset/ || /^\s*Lambda/ || /^\s*Histogram/ || | |
| 506 ( $self->in_element('hsp') && /WARNING|NOTE/ ) ) { | |
| 507 $self->in_element('hsp') && $self->end_element({'Name' => 'Hsp'}); | |
| 508 $self->in_element('hit') && $self->end_element({'Name' => 'Hit'}); | |
| 509 next if /^\s+Subset/; | |
| 510 my $blast = ( /^(\s+Database\:)|(\s*Lambda)/ ) ? 'ncbi' : 'wublast'; | |
| 511 if( /^\s*Histogram/ ) { | |
| 512 $blast = 'btk'; | |
| 513 } | |
| 514 my $last = ''; | |
| 515 # default is that gaps are allowed | |
| 516 $self->element({'Name' => 'Parameters_allowgaps', | |
| 517 'Data' => 'yes'}); | |
| 518 while( defined ($_ = $self->_readline ) ) { | |
| 519 if( /^(PSI)?([T]?BLAST[NPX])\s*(.+)$/i || | |
| 520 /^(RPS-BLAST)\s*(.+)$/i || | |
| 521 /^(MEGABLAST)\s*(.+)$/i ) { | |
| 522 $self->_pushback($_); | |
| 523 # let's handle this in the loop | |
| 524 last; | |
| 525 } elsif( /^Query=/ ) { | |
| 526 $self->_pushback($reportline); | |
| 527 $self->_pushback($_); | |
| 528 # -- Superfluous I think | |
| 529 $self->in_element('hsp') && | |
| 530 $self->end_element({'Name' => 'Hsp'}); | |
| 531 $self->in_element('hit') && | |
| 532 $self->end_element({'Name' => 'Hit'}); | |
| 533 # -- | |
| 534 $self->end_element({ 'Name' => 'BlastOutput'}); | |
| 535 return $self->end_document(); | |
| 536 } | |
| 537 | |
| 538 # here is where difference between wublast and ncbiblast | |
| 539 # is better handled by different logic | |
| 540 if( /Number of Sequences:\s+([\d\,]+)/i || | |
| 541 /of sequences in database:\s+([\d,]+)/i) { | |
| 542 my $c = $1; | |
| 543 $c =~ s/\,//g; | |
| 544 $self->element({'Name' => 'Statistics_db-len', | |
| 545 'Data' => $c}); | |
| 546 } elsif ( /letters in database:\s+(\-?[\d,]+)/i) { | |
| 547 my $s = $1; | |
| 548 $s =~ s/,//g; | |
| 549 $self->element({'Name' => 'Statistics_db-let', | |
| 550 'Data' => $s}); | |
| 551 } elsif( $blast eq 'btk' ) { | |
| 552 next; | |
| 553 } elsif( $blast eq 'wublast' ) { | |
| 554 if( /E=(\S+)/ ) { | |
| 555 $self->element({'Name' => 'Parameters_expect', | |
| 556 'Data' => $1}); | |
| 557 } elsif( /nogaps/ ) { | |
| 558 $self->element({'Name' => 'Parameters_allowgaps', | |
| 559 'Data' => 'no'}); | |
| 560 } elsif( $last =~ /(Frame|Strand)\s+MatID\s+Matrix name/i ){ | |
| 561 s/^\s+//; | |
| 562 #throw away first two slots | |
| 563 my @vals = split; | |
| 564 splice(@vals, 0,2); | |
| 565 my ($matrix,$lambda,$kappa,$entropy) = @vals; | |
| 566 $self->element({'Name' => 'Parameters_matrix', | |
| 567 'Data' => $matrix}); | |
| 568 $self->element({'Name' => 'Statistics_lambda', | |
| 569 'Data' => $lambda}); | |
| 570 $self->element({'Name' => 'Statistics_kappa', | |
| 571 'Data' => $kappa}); | |
| 572 $self->element({'Name' => 'Statistics_entropy', | |
| 573 'Data' => $entropy}); | |
| 574 } elsif( m/^\s+Q=(\d+),R=(\d+)\s+/ox ) { | |
| 575 $self->element({'Name' => 'Parameters_gap-open', | |
| 576 'Data' => $1}); | |
| 577 $self->element({'Name' => 'Parameters_gap-extend', | |
| 578 'Data' => $2}); | |
| 579 } elsif( /(\S+\s+\S+)\s+DFA:\s+(\S+)\s+\((.+)\)/ ) { | |
| 580 if( $1 eq 'states in') { | |
| 581 $self->element({'Name' => 'Statistics_DFA_states', | |
| 582 'Data' => "$2 $3"}); | |
| 583 } elsif( $1 eq 'size of') { | |
| 584 $self->element({'Name' => 'Statistics_DFA_size', | |
| 585 'Data' => "$2 $3"}); | |
| 586 } | |
| 587 } elsif( /^\s+Time to generate neighborhood:\s+(\S+\s+\S+\s+\S+)/ ) { | |
| 588 $self->element({'Name' => 'Statistics_neighbortime', | |
| 589 'Data' => $1}); | |
| 590 } elsif( /processors\s+used:\s+(\d+)/ ) { | |
| 591 $self->element({'Name' => 'Statistics_noprocessors', | |
| 592 'Data' => $1}); | |
| 593 } elsif( m/^\s+(\S+)\s+cpu\s+time:\s+(\S+\s+\S+\s+\S+)\s+ | |
| 594 Elapsed:\s+(\S+)/ox ) { | |
| 595 my $cputype = lc($1); | |
| 596 $self->element({'Name' => "Statistics_$cputype\_cputime", | |
| 597 'Data' => $2}); | |
| 598 $self->element({'Name' => "Statistics_$cputype\_actualtime", | |
| 599 'Data' => $3}); | |
| 600 } elsif( /^\s+Start:/ ) { | |
| 601 my ($junk,$start,$stime,$end,$etime) = | |
| 602 split(/\s+(Start|End)\:\s+/,$_); | |
| 603 chomp($stime); | |
| 604 $self->element({'Name' => 'Statistics_starttime', | |
| 605 'Data' => $stime}); | |
| 606 chomp($etime); | |
| 607 $self->element({'Name' => 'Statistics_endtime', | |
| 608 'Data' => $etime}); | |
| 609 } elsif( !/^\s+$/ ) { | |
| 610 $self->debug( "unmatched stat $_"); | |
| 611 } | |
| 612 | |
| 613 } elsif ( $blast eq 'ncbi' ) { | |
| 614 if( m/^Matrix:\s+(\S+)/oxi ) { | |
| 615 $self->element({'Name' => 'Parameters_matrix', | |
| 616 'Data' => $1}); | |
| 617 } elsif( /Lambda/ ) { | |
| 618 $_ = $self->_readline; | |
| 619 s/^\s+//; | |
| 620 my ($lambda, $kappa, $entropy) = split; | |
| 621 $self->element({'Name' => 'Statistics_lambda', | |
| 622 'Data' => $lambda}); | |
| 623 $self->element({'Name' => 'Statistics_kappa', | |
| 624 'Data' => $kappa}); | |
| 625 $self->element({'Name' => 'Statistics_entropy', | |
| 626 'Data' => $entropy}); | |
| 627 } elsif( m/effective\s+search\s+space\s+used:\s+(\d+)/ox ) { | |
| 628 $self->element({'Name' => 'Statistics_eff-spaceused', | |
| 629 'Data' => $1}); | |
| 630 } elsif( m/effective\s+search\s+space:\s+(\d+)/ox ) { | |
| 631 $self->element({'Name' => 'Statistics_eff-space', | |
| 632 'Data' => $1}); | |
| 633 } elsif( m/Gap\s+Penalties:\s+Existence:\s+(\d+)\, | |
| 634 \s+Extension:\s+(\d+)/ox) { | |
| 635 $self->element({'Name' => 'Parameters_gap-open', | |
| 636 'Data' => $1}); | |
| 637 $self->element({'Name' => 'Parameters_gap-extend', | |
| 638 'Data' => $2}); | |
| 639 } elsif( /effective\s+HSP\s+length:\s+(\d+)/ ) { | |
| 640 $self->element({'Name' => 'Statistics_hsp-len', | |
| 641 'Data' => $1}); | |
| 642 } elsif( /effective\s+length\s+of\s+query:\s+([\d\,]+)/ ) { | |
| 643 my $c = $1; | |
| 644 $c =~ s/\,//g; | |
| 645 $self->element({'Name' => 'Statistics_query-len', | |
| 646 'Data' => $c}); | |
| 647 } elsif( m/effective\s+length\s+of\s+database:\s+ | |
| 648 ([\d\,]+)/ox){ | |
| 649 my $c = $1; | |
| 650 $c =~ s/\,//g; | |
| 651 $self->element({'Name' => 'Statistics_eff-dblen', | |
| 652 'Data' => $c}); | |
| 653 } elsif( m/^(T|A|X1|X2|S1|S2):\s+(.+)/ox ) { | |
| 654 my $v = $2; | |
| 655 chomp($v); | |
| 656 $self->element({'Name' => "Statistics_$1", | |
| 657 'Data' => $v}); | |
| 658 } elsif( m/frameshift\s+window\,\s+decay\s+const:\s+ | |
| 659 (\d+)\,\s+([\.\d]+)/ox ) { | |
| 660 $self->element({'Name'=> 'Statistics_framewindow', | |
| 661 'Data' => $1}); | |
| 662 $self->element({'Name'=> 'Statistics_decay', | |
| 663 'Data' => $2}); | |
| 664 } elsif( m/^Number\s+of\s+Hits\s+to\s+DB:\s+(\S+)/ox ) { | |
| 665 $self->element({'Name' => 'Statistics_hit_to_db', | |
| 666 'Data' => $1}); | |
| 667 } elsif( m/^Number\s+of\s+extensions:\s+(\S+)/ox ) { | |
| 668 $self->element({'Name' => 'Statistics_num_extensions', | |
| 669 'Data' => $1}); | |
| 670 } elsif( m/^Number\s+of\s+successful\s+extensions:\s+ | |
| 671 (\S+)/ox ) { | |
| 672 $self->element({'Name' => 'Statistics_num_suc_extensions', | |
| 673 'Data' => $1}); | |
| 674 } elsif( m/^Number\s+of\s+sequences\s+better\s+than\s+ | |
| 675 (\S+):\s+(\d+)/ox ) { | |
| 676 $self->element({'Name' => 'Parameters_expect', | |
| 677 'Data' => $1}); | |
| 678 $self->element({'Name' => 'Statistics_seqs_better_than_cutoff', | |
| 679 'Data' => $2}); | |
| 680 } elsif( /^\s+Posted\s+date:\s+(.+)/ ) { | |
| 681 my $d = $1; | |
| 682 chomp($d); | |
| 683 $self->element({'Name' => 'Statistics_posted_date', | |
| 684 'Data' => $d}); | |
| 685 } elsif( ! /^\s+$/ ) { | |
| 686 $self->debug( "unmatched stat $_"); | |
| 687 } | |
| 688 } | |
| 689 $last = $_; | |
| 690 } | |
| 691 } elsif( $self->in_element('hsp') ) { | |
| 692 # let's read 3 lines at a time; | |
| 693 my %data = ( 'Query' => '', | |
| 694 'Mid' => '', | |
| 695 'Hit' => '' ); | |
| 696 my ($l,$len); | |
| 697 for( my $i = 0; | |
| 698 defined($_) && $i < 3; | |
| 699 $i++ ){ | |
| 700 chomp; | |
| 701 if( ($i == 0 && /^\s+$/) || ($l = /^\s*Lambda/i) ) { | |
| 702 $self->_pushback($_) if defined $_; | |
| 703 # this fixes bug #1443 | |
| 704 $self->end_element({'Name' => 'Hsp'}); | |
| 705 $self->end_element({'Name' => 'Hit'}) if $l; | |
| 706 last; | |
| 707 } | |
| 708 if( /^((Query|Sbjct):\s+(\d+)\s*)(\S+)\s+(\d+)/ ) { | |
| 709 $data{$2} = $4; | |
| 710 $len = length($1); | |
| 711 $self->{"\_$2"}->{'begin'} = $3 unless $self->{"_$2"}->{'begin'}; | |
| 712 $self->{"\_$2"}->{'end'} = $5; | |
| 713 } else { | |
| 714 $self->throw("no data for midline $_") | |
| 715 unless (defined $_ && defined $len); | |
| 716 $data{'Mid'} = substr($_,$len); | |
| 717 } | |
| 718 $_ = $self->_readline(); | |
| 719 } | |
| 720 $self->characters({'Name' => 'Hsp_qseq', | |
| 721 'Data' => $data{'Query'} }); | |
| 722 $self->characters({'Name' => 'Hsp_hseq', | |
| 723 'Data' => $data{'Sbjct'}}); | |
| 724 $self->characters({'Name' => 'Hsp_midline', | |
| 725 'Data' => $data{'Mid'} }); | |
| 726 } else { | |
| 727 $self->debug( "unrecognized line $_"); | |
| 728 } | |
| 729 } | |
| 730 | |
| 731 if( $seentop ) { | |
| 732 # double back check that hits and hsps are closed | |
| 733 # this in response to bug #1443 (may be uncessary due to fix | |
| 734 # above, but making double sure) | |
| 735 $self->in_element('hsp') && | |
| 736 $self->end_element({'Name' => 'Hsp'}); | |
| 737 $self->in_element('hit') && | |
| 738 $self->end_element({'Name' => 'Hit'}); | |
| 739 $self->end_element({'Name' => 'BlastOutput'}); | |
| 740 } | |
| 741 # $self->end_element({'Name' => 'BlastOutput'}) unless ! $seentop; | |
| 742 return $self->end_document(); | |
| 743 } | |
| 744 | |
| 745 =head2 start_element | |
| 746 | |
| 747 Title : start_element | |
| 748 Usage : $eventgenerator->start_element | |
| 749 Function: Handles a start element event | |
| 750 Returns : none | |
| 751 Args : hashref with at least 2 keys 'Data' and 'Name' | |
| 752 | |
| 753 | |
| 754 =cut | |
| 755 | |
| 756 sub start_element{ | |
| 757 my ($self,$data) = @_; | |
| 758 # we currently don't care about attributes | |
| 759 my $nm = $data->{'Name'}; | |
| 760 my $type = $MODEMAP{$nm}; | |
| 761 if( $type ) { | |
| 762 if( $self->_eventHandler->will_handle($type) ) { | |
| 763 my $func = sprintf("start_%s",lc $type); | |
| 764 $self->_eventHandler->$func($data->{'Attributes'}); | |
| 765 } | |
| 766 unshift @{$self->{'_elements'}}, $type; | |
| 767 if( $type eq 'result') { | |
| 768 $self->{'_values'} = {}; | |
| 769 $self->{'_result'}= undef; | |
| 770 } else { | |
| 771 # cleanup some things | |
| 772 if( defined $self->{'_values'} ) { | |
| 773 foreach my $k ( grep { /^\U$type\-/ } | |
| 774 keys %{$self->{'_values'}} ) { | |
| 775 delete $self->{'_values'}->{$k}; | |
| 776 } | |
| 777 } | |
| 778 } | |
| 779 } | |
| 780 } | |
| 781 | |
| 782 =head2 end_element | |
| 783 | |
| 784 Title : start_element | |
| 785 Usage : $eventgenerator->end_element | |
| 786 Function: Handles an end element event | |
| 787 Returns : none | |
| 788 Args : hashref with at least 2 keys 'Data' and 'Name' | |
| 789 | |
| 790 | |
| 791 =cut | |
| 792 | |
| 793 sub end_element { | |
| 794 my ($self,$data) = @_; | |
| 795 my $nm = $data->{'Name'}; | |
| 796 my $type = $MODEMAP{$nm}; | |
| 797 my $rc; | |
| 798 if($nm eq 'BlastOutput_program' && | |
| 799 $self->{'_last_data'} =~ /(t?blast[npx])/i ) { | |
| 800 $self->{'_reporttype'} = uc $1; | |
| 801 } | |
| 802 | |
| 803 # Hsp are sort of weird, in that they end when another | |
| 804 # object begins so have to detect this in end_element for now | |
| 805 if( $nm eq 'Hsp' ) { | |
| 806 foreach ( qw(Hsp_qseq Hsp_midline Hsp_hseq) ) { | |
| 807 $self->element({'Name' => $_, | |
| 808 'Data' => $self->{'_last_hspdata'}->{$_}}); | |
| 809 } | |
| 810 $self->{'_last_hspdata'} = {}; | |
| 811 $self->element({'Name' => 'Hsp_query-from', | |
| 812 'Data' => $self->{'_Query'}->{'begin'}}); | |
| 813 $self->element({'Name' => 'Hsp_query-to', | |
| 814 'Data' => $self->{'_Query'}->{'end'}}); | |
| 815 | |
| 816 $self->element({'Name' => 'Hsp_hit-from', | |
| 817 'Data' => $self->{'_Sbjct'}->{'begin'}}); | |
| 818 $self->element({'Name' => 'Hsp_hit-to', | |
| 819 'Data' => $self->{'_Sbjct'}->{'end'}}); | |
| 820 } | |
| 821 if( $type = $MODEMAP{$nm} ) { | |
| 822 if( $self->_eventHandler->will_handle($type) ) { | |
| 823 my $func = sprintf("end_%s",lc $type); | |
| 824 $rc = $self->_eventHandler->$func($self->{'_reporttype'}, | |
| 825 $self->{'_values'}); | |
| 826 } | |
| 827 shift @{$self->{'_elements'}}; | |
| 828 | |
| 829 } elsif( $MAPPING{$nm} ) { | |
| 830 | |
| 831 if ( ref($MAPPING{$nm}) =~ /hash/i ) { | |
| 832 # this is where we shove in the data from the | |
| 833 # hashref info about params or statistics | |
| 834 my $key = (keys %{$MAPPING{$nm}})[0]; | |
| 835 $self->{'_values'}->{$key}->{$MAPPING{$nm}->{$key}} = $self->{'_last_data'}; | |
| 836 } else { | |
| 837 $self->{'_values'}->{$MAPPING{$nm}} = $self->{'_last_data'}; | |
| 838 } | |
| 839 } else { | |
| 840 $self->debug( "unknown nm $nm, ignoring\n"); | |
| 841 } | |
| 842 $self->{'_last_data'} = ''; # remove read data if we are at | |
| 843 # end of an element | |
| 844 $self->{'_result'} = $rc if( defined $type && $type eq 'result' ); | |
| 845 return $rc; | |
| 846 | |
| 847 } | |
| 848 | |
| 849 =head2 element | |
| 850 | |
| 851 Title : element | |
| 852 Usage : $eventhandler->element({'Name' => $name, 'Data' => $str}); | |
| 853 Function: Convience method that calls start_element, characters, end_element | |
| 854 Returns : none | |
| 855 Args : Hash ref with the keys 'Name' and 'Data' | |
| 856 | |
| 857 | |
| 858 =cut | |
| 859 | |
| 860 sub element{ | |
| 861 my ($self,$data) = @_; | |
| 862 $self->start_element($data); | |
| 863 $self->characters($data); | |
| 864 $self->end_element($data); | |
| 865 } | |
| 866 | |
| 867 =head2 characters | |
| 868 | |
| 869 Title : characters | |
| 870 Usage : $eventgenerator->characters($str) | |
| 871 Function: Send a character events | |
| 872 Returns : none | |
| 873 Args : string | |
| 874 | |
| 875 | |
| 876 =cut | |
| 877 | |
| 878 sub characters{ | |
| 879 my ($self,$data) = @_; | |
| 880 return unless ( defined $data->{'Data'} && $data->{'Data'} !~ /^\s+$/ ); | |
| 881 | |
| 882 if( $self->in_element('hsp') && | |
| 883 $data->{'Name'} =~ /Hsp\_(qseq|hseq|midline)/ ) { | |
| 884 $self->{'_last_hspdata'}->{$data->{'Name'}} .= $data->{'Data'}; | |
| 885 } | |
| 886 $self->{'_last_data'} = $data->{'Data'}; | |
| 887 } | |
| 888 | |
| 889 =head2 within_element | |
| 890 | |
| 891 Title : within_element | |
| 892 Usage : if( $eventgenerator->within_element($element) ) {} | |
| 893 Function: Test if we are within a particular element | |
| 894 This is different than 'in' because within can be tested | |
| 895 for a whole block. | |
| 896 Returns : boolean | |
| 897 Args : string element name | |
| 898 | |
| 899 | |
| 900 =cut | |
| 901 | |
| 902 sub within_element{ | |
| 903 my ($self,$name) = @_; | |
| 904 return 0 if ( ! defined $name && | |
| 905 ! defined $self->{'_elements'} || | |
| 906 scalar @{$self->{'_elements'}} == 0) ; | |
| 907 foreach ( @{$self->{'_elements'}} ) { | |
| 908 if( $_ eq $name ) { | |
| 909 return 1; | |
| 910 } | |
| 911 } | |
| 912 return 0; | |
| 913 } | |
| 914 | |
| 915 | |
| 916 =head2 in_element | |
| 917 | |
| 918 Title : in_element | |
| 919 Usage : if( $eventgenerator->in_element($element) ) {} | |
| 920 Function: Test if we are in a particular element | |
| 921 This is different than 'in' because within can be tested | |
| 922 for a whole block. | |
| 923 Returns : boolean | |
| 924 Args : string element name | |
| 925 | |
| 926 | |
| 927 =cut | |
| 928 | |
| 929 sub in_element{ | |
| 930 my ($self,$name) = @_; | |
| 931 return 0 if ! defined $self->{'_elements'}->[0]; | |
| 932 return ( $self->{'_elements'}->[0] eq $name) | |
| 933 } | |
| 934 | |
| 935 =head2 start_document | |
| 936 | |
| 937 Title : start_document | |
| 938 Usage : $eventgenerator->start_document | |
| 939 Function: Handle a start document event | |
| 940 Returns : none | |
| 941 Args : none | |
| 942 | |
| 943 | |
| 944 =cut | |
| 945 | |
| 946 sub start_document{ | |
| 947 my ($self) = @_; | |
| 948 $self->{'_lasttype'} = ''; | |
| 949 $self->{'_values'} = {}; | |
| 950 $self->{'_result'}= undef; | |
| 951 $self->{'_elements'} = []; | |
| 952 } | |
| 953 | |
| 954 =head2 end_document | |
| 955 | |
| 956 Title : end_document | |
| 957 Usage : $eventgenerator->end_document | |
| 958 Function: Handles an end document event | |
| 959 Returns : Bio::Search::Result::ResultI object | |
| 960 Args : none | |
| 961 | |
| 962 | |
| 963 =cut | |
| 964 | |
| 965 sub end_document{ | |
| 966 my ($self,@args) = @_; | |
| 967 return $self->{'_result'}; | |
| 968 } | |
| 969 | |
| 970 | |
| 971 sub write_result { | |
| 972 my ($self, $blast, @args) = @_; | |
| 973 | |
| 974 if( not defined($self->writer) ) { | |
| 975 $self->warn("Writer not defined. Using a $DEFAULT_BLAST_WRITER_CLASS"); | |
| 976 $self->writer( $DEFAULT_BLAST_WRITER_CLASS->new() ); | |
| 977 } | |
| 978 $self->SUPER::write_result( $blast, @args ); | |
| 979 } | |
| 980 | |
| 981 sub result_count { | |
| 982 my $self = shift; | |
| 983 return $self->{'_result_count'}; | |
| 984 } | |
| 985 | |
| 986 sub report_count { shift->result_count } | |
| 987 | |
| 988 1; |
