File Coverage

Bio/Search/Result/CrossMatchResult.pm
Criterion Covered Total %
statement 22 107 20.5
branch 2 36 5.5
condition 0 5 0.0
subroutine 5 20 25.0
pod 15 16 93.7
total 44 184 23.9


line stmt bran cond sub pod time code
1             package Bio::Search::Result::CrossMatchResult;
2             #
3             # BioPerl module for Bio::Search::Result::CrossMatchResult
4             #
5             # Please direct questions and support issues to
6             #
7             # Cared for by Shin Leong
8             #
9             # Copyright Shin Leong
10             #
11             # You may distribute this module under the same terms as perl itself
12              
13             # POD documentation - main docs before the code
14              
15             =head1 NAME
16              
17             Bio::Search::Result::CrossMatchResult - CrossMatch-specific subclass of Bio::Search::Result::GenericResult
18              
19             =head1 SYNOPSIS
20              
21             # Working with iterations (CrossMatch results)
22              
23             $result->next_iteration();
24             $result->num_iterations();
25             $result->iteration();
26             $result->iterations();
27              
28             # See Bio::Search::Result::GenericResult for information about working with Results.
29              
30             # See L
31             # for details about working with iterations.
32              
33             # TODO:
34             # * Show how to configure a SearchIO stream so that it generates
35             # CrossMatchResult objects.
36              
37              
38             =head1 DESCRIPTION
39              
40             This object is a subclass of Bio::Search::Result::GenericResult
41             and provides some operations that facilitate working with CrossMatch
42             and CrossMatch results.
43              
44             For general information about working with Results, see
45             Bio::Search::Result::GenericResult.
46              
47             =head1 FEEDBACK
48              
49             =head2 Mailing Lists
50              
51             User feedback is an integral part of the evolution of this and other
52             Bioperl modules. Send your comments and suggestions preferably to
53             the Bioperl mailing list. Your participation is much appreciated.
54              
55             bioperl-l@bioperl.org - General discussion
56             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
57              
58             =head2 Support
59              
60             Please direct usage questions or support issues to the mailing list:
61              
62             I
63              
64             rather than to the module maintainer directly. Many experienced and
65             reponsive experts will be able look at the problem and quickly
66             address it. Please include a thorough description of the problem
67             with code and data examples if at all possible.
68              
69             =head2 Reporting Bugs
70              
71             Report bugs to the Bioperl bug tracking system to help us keep track
72             of the bugs and their resolution. Bug reports can be submitted via the
73             web:
74              
75             https://github.com/bioperl/bioperl-live/issues
76              
77             =head1 AUTHOR - Shin Leong
78              
79             Email sleong@watson.wustl.edu
80              
81             =head1 CONTRIBUTORS
82              
83             Additional contributors names and emails here
84              
85             =head1 APPENDIX
86              
87             The rest of the documentation details each of the object methods.
88             Internal methods are usually preceded with a _
89              
90             =cut
91              
92              
93             # Let the code begin...
94              
95              
96             package Bio::Search::Result::CrossMatchResult;
97 1     1   5 use strict;
  1         2  
  1         25  
98              
99 1     1   267 use Bio::Search::Result::GenericResult;
  1         3  
  1         27  
100              
101 1     1   7 use base qw(Bio::Search::Result::GenericResult);
  1         1  
  1         947  
102              
103             =head2 new
104              
105             Title : new
106             Usage : my $obj = Bio::Search::Result::CrossMatchResult->new();
107             Function: Builds a new Bio::Search::Result::CrossMatchResult object
108             Returns : Bio::Search::Result::CrossMatchResult
109             Args : See Bio::Search::Result::GenericResult();
110             The following parameters are specific to CrossMatchResult:
111             -iterations => array ref of Bio::Search::Iteration::IterationI objects
112             -inclusion_threshold => e-value threshold for inclusion in the
113             CrossMatch score matrix model (blastpgp)
114              
115             =cut
116              
117             sub new {
118 1     1 1 6 my($class,@args) = @_;
119              
120 1         7 my $self = $class->SUPER::new(@args);
121              
122 1         3 $self->{'_iterations'} = [];
123 1         3 $self->{'_iteration_index'} = 0;
124 1         2 $self->{'_iteration_count'} = 0;
125              
126 1         3 my( $iters, $ithresh ) = $self->_rearrange([qw(ITERATIONS
127             INCLUSION_THRESHOLD)],@args);
128              
129 1         4 $self->{'_inclusion_threshold'} = $ithresh; # This is a read-only variable
130              
131 1 50       3 if( defined $iters ) {
132 0 0       0 $self->throw("Must define arrayref of Iterations when initializing a $class\n") unless ref($iters) =~ /array/i;
133              
134 0         0 foreach my $i ( @{$iters} ) {
  0         0  
135 0         0 $self->add_iteration($i);
136             }
137             }
138             else {
139             # This shouldn't get called with the new SearchIO::blast.
140             #print STDERR "CrossMatchResult::new(): Not adding iterations.\n";
141 1         3 $self->{'_no_iterations'} = 1;
142             }
143              
144             #$self->SUPER::algorithm('cross_match');
145 1         3 return $self;
146             }
147              
148              
149             =head2 hits
150              
151             This method overrides L to take
152             into account the possibility of multiple iterations, as occurs in CrossMatch reports.
153              
154             If there are multiple iterations, all 'new' hits for all iterations are returned.
155             These are the hits that did not occur in a previous iteration.
156              
157             See Also: L
158              
159             =cut
160              
161             sub hits {
162 0     0 1 0 my ($self) = shift;
163 0 0       0 if ($self->{'_no_iterations'}) {
164 0         0 return $self->SUPER::hits;
165             }
166 0         0 my @hits = ();
167 0         0 foreach my $it ($self->iterations) {
168 0         0 push @hits, $it->hits;
169             }
170 0         0 return @hits;
171             }
172              
173             =head2 next_hit
174              
175             This method overrides L to take
176             into account the possibility of multiple iterations, as occurs in CrossMatch reports.
177              
178             If there are multiple iterations, calling next_hit() traverses the
179             all of the hits, old and new, for each iteration, calling next_hit() on each iteration.
180              
181             See Also: L
182              
183             =cut
184              
185             sub next_hit {
186 2     2 1 437 my ($self,@args) = @_;
187 2 50       6 if ($self->{'_no_iterations'}) {
188 2         9 return $self->SUPER::next_hit(@args);
189             }
190              
191 0           my $iter_index;
192 0 0         if (not defined $self->{'_last_hit'}) {
193 0           $iter_index = $self->{'_iter_index'} = $self->_next_iteration_index;
194             } else {
195 0           $iter_index = $self->{'_iter_index'};
196             }
197              
198 0 0         return if $iter_index >= scalar @{$self->{'_iterations'}};
  0            
199              
200 0           my $it = $self->{'_iterations'}->[$iter_index];
201 0           my $hit = $self->{'_last_hit'} = $it->next_hit;
202              
203 0 0         return defined($hit) ? $hit : $self->next_hit;
204             }
205              
206              
207             =head2 num_hits
208              
209             This method overrides L to take
210             into account the possibility of multiple iterations, as occurs in CrossMatch reports.
211              
212             If there are multiple iterations, calling num_hits() returns the number of
213             'new' hits for each iteration. These are the hits that did not occur
214             in a previous iteration.
215              
216             See Also: L
217              
218             =cut
219              
220             sub num_hits{
221 0     0 1   my ($self) = shift;
222 0 0         if ($self->{'_no_iterations'}) {
223 0           return $self->SUPER::num_hits;
224             }
225 0 0         if (not defined $self->{'_iterations'}) {
226 0           $self->throw("Can't get Hits: data not collected.");
227             }
228 0           return scalar( $self->hits );
229             }
230              
231             =head2 add_iteration
232              
233             Title : add_iteration
234             Usage : $report->add_iteration($iteration)
235             Function: Adds a IterationI to the stored list of iterations
236             Returns : Number of IterationI currently stored
237             Args : Bio::Search::Iteration::IterationI
238              
239             =cut
240              
241             sub add_iteration {
242 0     0 1   my ($self,$i) = @_;
243 0 0         if( $i->isa('Bio::Search::Iteration::IterationI') ) {
244 0           push @{$self->{'_iterations'}}, $i;
  0            
245 0           $self->{'_iteration_count'}++;
246             } else {
247 0           $self->throw("Passed in a " .ref($i).
248             " as a Iteration which is not a Bio::Search::IterationI.");
249             }
250 0           return scalar @{$self->{'_iterations'}};
  0            
251             }
252              
253              
254             =head2 next_iteration
255              
256             Title : next_iteration
257             Usage : while( $it = $result->next_iteration()) { ... }
258             Function: Returns the next Iteration object, representing all hits
259             found within a given CrossMatch iteration.
260             Returns : a Bio::Search::Iteration::IterationI object or undef if there are no more.
261             Args : none
262              
263             =cut
264              
265             sub next_iteration {
266 0     0 1   my ($self) = @_;
267              
268 0 0         unless($self->{'_iter_queue_started'}) {
269 0           $self->{'_iter_queue'} = [$self->iterations()];
270 0           $self->{'_iter_queue_started'} = 1;
271             }
272 0           return shift @{$self->{'_iter_queue'}};
  0            
273             }
274              
275             =head2 iteration
276              
277             Usage : $iteration = $blast->iteration( $number );
278             Purpose : Get an IterationI object for the specified iteration
279             in the search result (CrossMatch).
280             Returns : Bio::Search::Iteration::IterationI object
281             Throws : Bio::Root::NoSuchThing exception if $number is not within
282             range of the number of iterations in this report.
283             Argument : integer (optional, if not specified get the last iteration)
284             First iteration = 1
285              
286             =cut
287              
288             sub iteration {
289 0     0 1   my ($self,$num) = @_;
290 0 0         $num = scalar @{$self->{'_iterations'}} unless defined $num;
  0            
291 0 0 0       unless ($num >= 1 and $num <= scalar $self->{'_iteration_count'}) {
292 0           $self->throw(-class=>'Bio::Root::NoSuchThing',
293             -text=>"No such iteration number: $num. Valid range=1-$self->{'_iteration_count'}",
294             -value=>$num);
295             }
296 0           return $self->{'_iterations'}->[$num-1];
297             }
298              
299             =head2 num_iterations
300              
301             Usage : $num_iterations = $blast->num_iterations;
302             Purpose : Get the number of iterations in the search result (CrossMatch).
303             Returns : Total number of iterations in the report
304             Argument : none (read-only)
305              
306             =cut
307              
308 0     0 1   sub num_iterations { shift->{'_iteration_count'} }
309              
310             # Methods provided for consistency with BPpsilite.pm (now deprecated);
311             # these are now merely synonyms
312              
313             =head2 number_of_iterations
314              
315             Same as L.
316              
317             =cut
318              
319 0     0 1   sub number_of_iterations { shift->num_iterations }
320              
321             =head2 round
322              
323             Same as L.
324              
325             =cut
326              
327 0     0 1   sub round { shift->iteration(@_) }
328              
329              
330             =head2 iterations
331              
332             Title : iterations
333             Usage : my @iterations = $result->iterations
334             Function: Returns the IterationI objects contained within this Result
335             Returns : Array of L objects
336             Args : none
337              
338             =cut
339              
340             sub iterations {
341 0     0 1   my $self = shift;
342 0           my @its = ();
343 0 0         if( ref($self->{'_iterations'}) =~ /ARRAY/i ) {
344 0           @its = @{$self->{'_iterations'}};
  0            
345             }
346 0           return @its;
347             }
348              
349             =head2 no_hits_found
350              
351             Usage : $nohits = $blast->no_hits_found( $iteration_number );
352             Purpose : Get boolean indicator indicating whether or not any hits
353             were present in the report.
354              
355             This is NOT the same as determining the number of hits via
356             the hits() method, which will return zero hits if there were no
357             hits in the report or if all hits were filtered out during the parse.
358              
359             Thus, this method can be used to distinguish these possibilities
360             for hitless reports generated when filtering.
361              
362             Returns : Boolean
363             Argument : (optional) integer indicating the iteration number (CrossMatch)
364             If iteration number is not specified and this is a CrossMatch result,
365             then this method will return true only if all iterations had
366             no hits found.
367              
368             =cut
369              
370             sub no_hits_found {
371 0     0 1   my ($self, $round) = @_;
372              
373 0           my $result = 0; # final return value of this method.
374             # Watch the double negative!
375             # result = 0 means "yes hits were found"
376             # result = 1 means "no hits were found" (for the indicated iteration or all iterations)
377              
378             # If a iteration was not specified and there were multiple iterations,
379             # this method should return true only if all iterations had no hits found.
380 0 0         if( not defined $round ) {
381 0 0         if( $self->{'_iterations'} > 1) {
382 0           $result = 1;
383 0           foreach my $i( 1..$self->{'_iterations'} ) {
384 0 0         if( not defined $self->{"_iteration_$i"}->{'_no_hits_found'} ) {
385 0           $result = 0;
386 0           last;
387             }
388             }
389             }
390             else {
391 0           $result = $self->{"_iteration_1"}->{'_no_hits_found'};
392             }
393             }
394             else {
395 0           $result = $self->{"_iteration_$round"}->{'_no_hits_found'};
396             }
397              
398 0           return $result;
399             }
400              
401              
402             =head2 set_no_hits_found
403              
404             Usage : $blast->set_no_hits_found( $iteration_number );
405             Purpose : Set boolean indicator indicating whether or not any hits
406             were present in the report.
407             Returns : n/a
408             Argument : (optional) integer indicating the iteration number (CrossMatch)
409              
410             =cut
411              
412             sub set_no_hits_found {
413 0     0 1   my ($self, $round) = @_;
414 0   0       $round ||= 1;
415 0           $self->{"_iteration_$round"}->{'_no_hits_found'} = 1;
416             }
417              
418             =head2 _next_iteration_index
419              
420             Title : _next_iteration_index
421             Usage : private
422              
423             =cut
424              
425             sub _next_iteration_index{
426 0     0     my ($self,@args) = @_;
427 0           return $self->{'_iteration_index'}++;
428             }
429              
430              
431             =head2 rewind
432              
433             Title : rewind
434             Usage : $result->rewind;
435             Function: Allow one to reset the Iteration iterator to the beginning
436             Since this is an in-memory implementation
437             Returns : none
438             Args : none
439              
440             =cut
441              
442             sub rewind {
443 0     0 1   my $self = shift;
444 0           $self->SUPER::rewind(@_);
445 0           $self->{'_iteration_index'} = 0;
446 0           foreach ($self->iterations) {
447 0           $_->rewind;
448             }
449             }
450              
451              
452             =head2 inclusion_threshold
453              
454             Title : inclusion_threshold
455             Usage : my $incl_thresh = $result->inclusion_threshold; (read-only)
456             Function: Gets the e-value threshold for inclusion in the CrossMatch
457             score matrix model (blastpgp) that was used for generating the report
458             being parsed.
459             Returns : number (real) or undef if not a CrossMatch report.
460             Args : none
461              
462             =cut
463              
464             sub inclusion_threshold {
465 0     0 1   my $self = shift;
466 0           return $self->{'_inclusion_threshold'};
467             }
468              
469              
470             sub algorithm_old {
471 0     0 0   my $self = shift;
472 0           my $value = shift;
473 0 0         if($value) {
474 0           print STDERR "Cannot set the algorightm on this class!\n";
475 0           return $self->SUPER::algorithm;
476             } else {
477 0           return $self->SUPER::algorithm;
478             }
479             }
480             1;
481              
482             #$Header$