Bio::DB::TFBS namespace has been moved to its own distribution named after itself
[bioperl-live.git] / Bio / Tools / HMMER / Results.pm
blob7beb1b3637225ce79c411f01204573df3ef4f81b
2 # Perl Module for HMMResults
4 # Please direct questions and support issues to <bioperl-l@bioperl.org>
6 # Cared for by Ewan Birney <birney@sanger.ac.uk>
8 #Copyright Genome Research Limited (1997).
10 =head1 NAME
12 Bio::Tools::HMMER::Results - Object representing HMMER output results
14 =head1 SYNOPSIS
16 # parse a hmmsearch file (can also parse a hmmpfam file)
17 $res = Bio::Tools::HMMER::Results->new( -file => 'output.hmm' ,
18 -type => 'hmmsearch');
20 # print out the results for each sequence
21 foreach $seq ( $res->each_Set ) {
22 print "Sequence bit score is",$seq->bits,"\n";
23 foreach $domain ( $seq->each_Domain ) {
24 print " Domain start ",$domain->start," end ",$domain->end,
25 " score ",$domain->bits,"\n";
29 # new result object on a sequence/domain cutoff of
30 # 25 bits sequence, 15 bits domain
31 $newresult = $res->filter_on_cutoff(25,15);
33 # alternative way of getting out all domains directly
34 foreach $domain ( $res->each_Domain ) {
35 print "Domain on ",$domain->seq_id," with score ",
36 $domain->bits," evalue ",$domain->evalue,"\n";
39 =head1 DESCRIPTION
41 This object represents HMMER output, either from hmmsearch or
42 hmmpfam. For hmmsearch, a series of HMMER::Set objects are made, one
43 for each sequence, which have the the bits score for the object. For
44 hmmpfam searches, only one Set object is made.
47 These objects come from the original HMMResults modules used
48 internally in Pfam, written by Ewan Birney. Ewan then converted them to
49 BioPerl objects in 1999. That conversion is meant to be backwardly
50 compatible, but may not be (caveat emptor).
52 =head1 FEEDBACK
54 =head2 Mailing Lists
56 User feedback is an integral part of the evolution of this and other
57 Bioperl modules. Send your comments and suggestions preferably to one
58 of the Bioperl mailing lists. Your participation is much appreciated.
60 bioperl-l@bioperl.org - General discussion
61 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
63 =head2 Support
65 Please direct usage questions or support issues to the mailing list:
67 I<bioperl-l@bioperl.org>
69 rather than to the module maintainer directly. Many experienced and
70 reponsive experts will be able look at the problem and quickly
71 address it. Please include a thorough description of the problem
72 with code and data examples if at all possible.
74 =head2 Reporting Bugs
76 Report bugs to the Bioperl bug tracking system to help us keep track
77 the bugs and their resolution. Bug reports can be submitted via the
78 web:
80 https://github.com/bioperl/bioperl-live/issues
82 =head1 AUTHOR - Ewan Birney
84 Email birney@ebi.ac.uk
86 =head1 CONTRIBUTORS
88 Jason Stajich, jason-at-bioperl.org
90 =head1 APPENDIX
92 The rest of the documentation details each of the object
93 methods. Internal methods are usually preceded with a _
95 =cut
97 package Bio::Tools::HMMER::Results;
99 use strict;
101 use Bio::Tools::HMMER::Domain;
102 use Bio::Tools::HMMER::Set;
103 use Symbol;
105 use base qw(Bio::Root::Root Bio::Root::IO Bio::SeqAnalysisParserI);
107 sub new {
108 my($class,@args) = @_;
110 my $self = $class->SUPER::new(@args);
112 $self->{'domain'} = []; # array of HMMUnits
113 $self->{'seq'} = {};
115 my ($parsetype) = $self->_rearrange([qw(TYPE)],@args);
116 $self->_initialize_io(@args);
117 if( !defined $parsetype ) {
118 $self->throw("No parse type provided. should be hmmsearch or hmmpfam");
120 $self->parsetype($parsetype);
121 if( defined $self->_fh() ) {
122 if( $parsetype eq 'hmmsearch' ) {
123 $self->_parse_hmmsearch($self->_fh());
124 } elsif ( $parsetype eq 'hmmpfam' ) {
125 $self->_parse_hmmpfam($self->_fh());
126 } else {
127 $self->throw("Did not recoginise type $parsetype");
131 return $self; # success - we hope!
135 =head2 next_feature
137 Title : next_feature
138 Usage : while( my $feat = $res->next_feature ) { # do something }
139 Function: SeqAnalysisParserI implementing function
140 Example :
141 Returns : A Bio::SeqFeatureI compliant object, in this case,
142 each DomainUnit object, ie, flattening the Sequence
143 aspect of this.
144 Args : None
147 =cut
149 sub next_feature{
150 my ($self) = @_;
152 if( $self->{'_started_next_feature'} == 1 ) {
153 return shift @{$self->{'_next_feature_array'}};
154 } else {
155 $self->{'_started_next_feature'} = 1;
156 my @array;
157 foreach my $seq ( $self->each_Set() ) {
158 foreach my $unit ( $seq->each_Domain() ) {
159 push(@array,$unit);
162 my $res = shift @array;
163 $self->{'_next_feature_array'} = \@array;
164 return $res;
167 $self->throw("Should not reach here! Error!");
171 =head2 number
173 Title : number
174 Usage : print "There are ",$res->number," domains hit\n";
175 Function: provides the number of domains in the HMMER report
177 =cut
179 sub number {
180 my $self = shift;
181 my @val;
182 my $ref;
183 $ref = $self->{'domain'};
186 @val = @{$self->{'domain'}};
187 return scalar @val;
190 =head2 seqfile
192 Title : seqfile
193 Usage : $obj->seqfile($newval)
194 Function:
195 Example :
196 Returns : value of seqfile
197 Args : newvalue (optional)
200 =cut
202 sub seqfile{
203 my ($self,$value) = @_;
204 if( defined $value) {
205 $self->{'seqfile'} = $value;
207 return $self->{'seqfile'};
211 =head2 hmmfile
213 Title : hmmfile
214 Usage : $obj->hmmfile($newval)
215 Function:
216 Example :
217 Returns : value of hmmfile
218 Args : newvalue (optional)
221 =cut
223 sub hmmfile{
224 my ($self,$value) = @_;
225 if( defined $value) {
226 $self->{'hmmfile'} = $value;
228 return $self->{'hmmfile'};
232 =head2 add_Domain
234 Title : add_Domain
235 Usage : $res->add_Domain($unit)
236 Function: adds a domain to the results array. Mainly used internally.
237 Args : A Bio::Tools::HMMER::Domain
240 =cut
242 sub add_Domain {
243 my $self = shift;
244 my $unit = shift;
245 my $name;
247 $name = $unit->seq_id();
249 if( ! exists $self->{'seq'}->{$name} ) {
250 $self->warn("Adding a domain of $name but with no HMMSequence. Will be kept in domain array but not added to a HMMSequence");
251 } else {
252 $self->{'seq'}->{$name}->add_Domain($unit);
254 push(@{$self->{'domain'}},$unit);
258 =head2 each_Domain
260 Title : each_Domain
261 Usage : foreach $domain ( $res->each_Domain() )
262 Function: array of Domain units which are held in this report
263 Returns : array
264 Args : none
267 =cut
269 sub each_Domain {
270 my $self = shift;
271 my (@arr,$u);
273 foreach $u ( @{$self->{'domain'}} ) {
274 push(@arr,$u);
277 return @arr;
281 =head2 domain_bits_cutoff_from_evalue
283 Title : domain_bits_cutoff_from_evalue
284 Usage : $cutoff = domain_bits_cutoff_from_evalue(0.01);
285 Function: return a bits cutoff from an evalue using the
286 scores here. Somewhat interesting logic:
287 Find the two bit score which straddle the evalue
288 if( 25 is between these two points) return 25
289 else return the midpoint.
291 This logic tries to ensure that with large signal to
292 noise separation one still has sensible 25 bit cutoff
293 Returns :
294 Args :
296 =cut
298 sub domain_bits_cutoff_from_evalue {
299 my $self = shift;
300 my $eval = shift;
301 my ($dom,$prev,@doms,$cutoff,$sep,$seen);
303 @doms = $self->each_Domain;
306 @doms = map { $_->[0] }
307 sort { $b->[1] <=> $a->[1] }
308 map { [ $_, $_->bits] } @doms;
309 $seen = 0;
310 foreach $_ ( @doms ) {
311 if( $_->evalue > $eval ) {
312 $seen = 1;
313 $dom = $_;
314 last;
316 $prev = $_;
319 if( ! defined $prev || $seen == 0) {
320 $self->throw("Evalue is either above or below the list...");
321 return;
324 $sep = $prev->bits - $dom->bits ;
326 if( $sep < 1 ) {
327 return $prev->bits();
329 if( $dom->bits < 25 && $prev->bits > 25 ) {
330 return 25;
333 return int( $dom->bits + $sep/2 ) ;
338 sub dictate_hmm_acc {
339 my $self = shift;
340 my $acc = shift;
341 my ($unit);
344 foreach $unit ( $self->eachHMMUnit() ) {
345 $unit->hmmacc($acc);
349 =head2 write_FT_output
351 Title : write_FT_output
352 Usage : $res->write_FT_output(\*STDOUT,'DOMAIN')
353 Function: writes feature table output ala swissprot
354 Returns :
355 Args :
358 =cut
360 sub write_FT_output {
361 my $self = shift;
362 my $file = shift;
363 my $idt = shift;
364 my ($seq,$unit);
366 if( !defined $idt ) {
367 $idt = "DOMAIN";
370 foreach $seq ( $self->each_Set() ) {
371 print $file sprintf("ID %s\n",$seq->name());
372 foreach $unit ( $seq->each_Domain() ) {
373 print $file sprintf("FT %s %d %d %s\n",$idt,
374 $unit->start,$unit->end,$unit->hmmname);
376 print $file "//\n";
380 =head2 filter_on_cutoff
382 Title : filter_on_cutoff
383 Usage : $newresults = $results->filter_on_cutoff(25,15);
384 Function: Produces a new HMMER::Results module which has
385 been trimmed at the cutoff.
386 Returns : a Bio::Tools::HMMER::Results module
387 Args : sequence cutoff and domain cutoff. in bits score
388 if you want one cutoff, simply use same number both places
390 =cut
392 sub filter_on_cutoff {
393 my $self = shift;
394 my $seqthr = shift;
395 my $domthr = shift;
396 my ($new,$seq,$unit,@array,@narray);
398 if( !defined $domthr ) {
399 $self->throw("hmmresults filter on cutoff needs two arguments");
402 $new = Bio::Tools::HMMER::Results->new(-type => $self->parsetype);
404 foreach $seq ( $self->each_Set()) {
405 next if( $seq->bits() < $seqthr );
406 $new->add_Set($seq);
407 foreach $unit ( $seq->each_Domain() ) {
408 next if( $unit->bits() < $domthr );
409 $new->add_Domain($unit);
412 $new;
415 =head2 write_ascii_out
417 Title : write_ascii_out
418 Usage : $res->write_ascii_out(\*STDOUT)
419 Function: writes as
420 seq seq_start seq_end model-acc model_start model_end model_name
421 Returns :
422 Args :
424 FIXME: Now that we have no modelacc, this is probably a bad thing.
426 =cut
428 # writes as seq sstart send modelacc hstart hend modelname
430 sub write_ascii_out {
431 my $self = shift;
432 my $fh = shift;
433 my ($unit,$seq);
435 if( !defined $fh) {
436 $fh = \*STDOUT;
440 foreach $seq ( $self->each_Set()) {
441 foreach $unit ( $seq->each_Domain()) {
442 print $fh sprintf("%s %4d %4d %s %4d %4d %4.2f %4.2g %s\n",
443 $unit->seq_id(),$unit->start(),$unit->end(),
444 $unit->hmmacc,$unit->hstart,$unit->hend,
445 $unit->bits,$unit->evalue,$unit->hmmname);
451 =head2 write_GDF_bits
453 Title : write_GDF_bits
454 Usage : $res->write_GDF_bits(25,15,\*STDOUT)
455 Function: writes GDF format with a sequence,domain threshold
456 Returns :
457 Args :
459 =cut
461 sub write_GDF_bits {
462 my $self = shift;
463 my $seqt = shift;
464 my $domt = shift;
465 my $file = shift;
466 my $seq;
467 my $unit;
468 my (@array,@narray);
470 if( !defined $file ) {
471 $self->throw("Attempting to use write_GDF_bits without passing in correct arguments!");
472 return;
475 foreach $seq ( $self->each_Set()) {
477 if( $seq->bits() < $seqt ) {
478 next;
481 foreach $unit ( $seq->each_Domain() ) {
482 if( $unit->bits() < $domt ) {
483 next;
485 push(@array,$unit);
490 @narray = sort { my ($aa,$bb,$st_a,$st_b);
491 $aa = $a->seq_id();
492 $bb = $b->seq_id();
493 if ( $aa eq $bb) {
494 $st_a = $a->start();
495 $st_b = $b->start();
496 return $st_a <=> $st_b;
498 else {
499 return $aa cmp $bb;
500 } } @array;
502 foreach $unit ( @narray ) {
503 print $file sprintf("%-24s\t%6d\t%6d\t%15s\t%.1f\t%g\n",$unit->get_nse(),$unit->start(),$unit->end(),$unit->seq_id(),$unit->bits(),$unit->evalue);
508 sub write_scores_bits {
509 my $self = shift;
510 my $seqt = shift;
511 my $domt = shift;
512 my $file = shift;
513 my $seq;
514 my $unit;
515 my (@array,@narray);
517 if( !defined $file ) {
518 $self->warn("Attempting to use write_scores_bits without passing in correct arguments!");
519 return;
522 foreach $seq ( $self->eachHMMSequence()) {
524 if( $seq->bits() < $seqt ) {
525 next;
528 foreach $unit ( $seq->eachHMMUnit() ) {
529 if( $unit->bits() < $domt ) {
530 next;
532 push(@array,$unit);
537 @narray = sort { my ($aa,$bb,$st_a,$st_b);
538 $aa = $a->bits();
539 $bb = $b->bits();
540 return $aa <=> $bb;
541 } @array;
543 foreach $unit ( @narray ) {
544 print $file sprintf("%4.2f %s\n",$unit->bits(),$unit->get_nse());
549 sub write_GDF {
550 my $self = shift;
551 my $file = shift;
552 my $unit;
554 if( !defined $file ) {
555 $file = \*STDOUT;
559 foreach $unit ( $self->eachHMMUnit() ) {
560 print $file sprintf("%-24s\t%6d\t%6d\t%15s\t%.1f\t%g\n",$unit->get_nse(),$unit->start(),$unit->end(),$unit->seq_id(),$unit->bits(),$unit->evalue);
565 sub highest_noise {
566 my $self = shift;
567 my $seqt = shift;
568 my $domt = shift;
569 my ($seq,$unit,$hseq,$hdom,$noiseseq,$noisedom);
571 $hseq = $hdom = -100000;
573 foreach $seq ( $self->eachHMMSequence()) {
574 if( $seq->bits() < $seqt && $seq->bits() > $hseq ) {
575 $hseq = $seq->bits();
576 $noiseseq = $seq;
578 foreach $unit ( $seq->eachHMMUnit() ) {
579 if( (($seq->bits() < $seqt) || ($seq->bits() > $seqt && $unit->bits < $domt)) && $unit->bits() > $hdom ) {
580 $hdom = $unit->bits();
581 $noisedom = $unit;
587 return ($noiseseq,$noisedom);
592 sub lowest_true {
593 my $self = shift;
594 my $seqt = shift;
595 my $domt = shift;
596 my ($seq,$unit,$lowseq,$lowdom,$trueseq,$truedom);
598 if( ! defined $domt ) {
599 $self->warn("lowest true needs at least a domain threshold cut-off");
600 return (0,0);
603 $lowseq = $lowdom = 100000;
605 foreach $seq ( $self->eachHMMSequence()) {
607 if( $seq->bits() >= $seqt && $seq->bits() < $lowseq ) {
608 $lowseq = $seq->bits();
609 $trueseq = $seq;
611 if( $seq->bits() < $seqt ) {
612 next;
615 foreach $unit ( $seq->eachHMMUnit() ) {
616 if( $unit->bits() >= $domt && $unit->bits() < $lowdom ) {
617 $lowdom = $unit->bits();
618 $truedom = $unit;
624 return ($trueseq,$truedom);
630 =head2 add_Set
632 Title : add_Set
633 Usage : Mainly internal function
634 Function:
635 Returns :
636 Args :
639 =cut
641 sub add_Set {
642 my $self = shift;
643 my $seq = shift;
644 my $name;
646 $name = $seq->name();
648 if( exists $self->{'seq'}->{$name} ) {
649 $self->throw("You alredy have $name in HMMResults!");
651 $self->{'seq'}->{$name} = $seq;
655 =head2 each_Set
657 Title : each_Set
658 Usage :
659 Function:
660 Returns :
661 Args :
664 =cut
666 sub each_Set {
667 my $self = shift;
668 my (@array,$name);
671 foreach $name ( keys %{$self->{'seq'}} ) {
672 push(@array,$self->{'seq'}->{$name});
674 return @array;
678 =head2 get_Set
680 Title : get_Set
681 Usage : $set = $res->get_Set('sequence-name');
682 Function: returns the Set for a particular sequence
683 Returns : a HMMER::Set object
684 Args : name of the sequence
687 =cut
689 sub get_Set {
690 my $self = shift;
691 my $name = shift;
693 return $self->{'seq'}->{$name};
697 =head2 _parse_hmmpfam
699 Title : _parse_hmmpfam
700 Usage : $res->_parse_hmmpfam($filehandle)
701 Function:
702 Returns :
703 Args :
706 =cut
708 sub _parse_hmmpfam {
709 my $self = shift;
710 my $file = shift;
712 my ($id,$sqfrom,$sqto,$hmmf,$hmmt,$sc,$ev,
713 $unit,$nd,$seq,$name,$seqname,$from,
714 $to,%hash,%acc,$acc);
715 my $count = 0;
717 while(<$file>) {
718 if( /^HMM file:\s+(\S+)/ ) { $self->hmmfile($1); next; }
719 elsif( /^Sequence file:\s+(\S+)/ ) { $self->seqfile($1); next }
720 elsif( /^Query(\s+sequence)?:\s+(\S+)/ ) {
722 $seqname = $2;
724 $seq = Bio::Tools::HMMER::Set->new();
726 $seq ->name($seqname);
727 $self->add_Set($seq);
728 %hash = ();
730 while(<$file>){
732 if( /Accession:\s+(\S+)/ ) { $seq->accession($1); next }
733 elsif( s/^Description:\s+// ) { chomp; $seq->desc($_); next }
734 /^Parsed for domains/ && last;
736 # This is to parse out the accession numbers in old Pfam format.
737 # now not support due to changes in HMMER.
739 if( (($id,$acc, $sc, $ev, $nd) = /^\s*(\S+)\s+(\S+).+?\s(\S+)\s+(\S+)\s+(\d+)\s*$/)) {
740 $hash{$id} = $sc; # we need this for the sequence
741 # core of the domains below!
742 $acc {$id} = $acc;
744 # this is the more common parsing routine
745 } elsif ( (($id,$sc, $ev, $nd) =
746 /^\s*(\S+).+?\s(\S+)\s+(\S+)\s+(\d+)\s*$/) ) {
748 $hash{$id} = $sc; # we need this for the
749 # sequence score of hte domains below!
754 while(<$file>) {
755 /^Align/ && last;
756 m{^//} && last;
757 # this is meant to match
759 #Sequence Domain seq-f seq-t hmm-f hmm-t score E-value
760 #-------- ------- ----- ----- ----- ----- ----- -------
761 #PF00621 1/1 198 372 .. 1 207 [] 281.6 1e-80
763 if( (($id, $sqfrom, $sqto, $hmmf,$hmmt,$sc, $ev) =
764 /(\S+)\s+\S+\s+(\d+)\s+(\d+).+?(\d+)\s+(\d+)\s+\S+\s+(\S+)\s+(\S+)\s*$/)) {
765 $unit = Bio::Tools::HMMER::Domain->new();
766 $unit->seq_id ($seqname);
767 $unit->hmmname ($id);
768 $unit->start ($sqfrom);
769 $unit->end ($sqto);
770 $unit->hstart($hmmf);
771 $unit->hend ($hmmt);
772 $unit->bits ($sc);
773 $unit->evalue ($ev);
775 if( !exists($hash{$id}) ) {
776 $self->throw("HMMResults parsing error in hmmpfam for $id - can't find sequecne score");
779 $unit->seqbits($hash{$id});
781 if( defined $acc{$id} ) {
782 $unit->hmmacc($acc{$id});
785 # this should find it's own sequence!
786 $self->add_Domain($unit);
789 if( m{^//} ) { next; }
791 $_ = <$file>;
792 # parses alignment lines. Icky as we have to break on the same line
793 # that we need to read to place the alignment lines with the unit.
795 while(1) {
796 (!defined $_ || m{^//}) && last;
798 # matches:
799 # PF00621: domain 1 of 1, from 198 to 372
800 if( /^\s*(\S+):.*from\s+(\d+)\s+to\s+(\d+)/ ) {
802 $name = $1;
803 $from = $2;
804 $to = $3;
806 # find the HMMUnit which this alignment is from
808 $unit = $self->get_unit_nse($seqname,$name,$from,$to);
809 if( !defined $unit ) {
810 $self->warn("Could not find $name $from $to unit even though I am reading it in. ugh!");
811 $_ = <$file>;
812 next;
814 while(<$file>) {
815 m{^//} && last;
816 /^\s*\S+:.*from\s+\d+\s+to\s+\d+/ && last;
817 $unit->add_alignment_line($_);
819 } else {
820 $_ = <$file>;
824 # back to main 'Query:' loop
829 # mainly internal function
831 sub get_unit_nse {
832 my $self = shift;
833 my $seqname = shift;
834 my $domname = shift;
835 my $start = shift;
836 my $end = shift;
838 my($seq,$unit);
840 $seq = $self->get_Set($seqname);
842 if( !defined $seq ) {
843 $self->throw("Could not get sequence name $seqname - so can't get its unit");
846 foreach $unit ( $seq->each_Domain() ) {
847 if( $unit->hmmname() eq $domname && $unit->start() == $start && $unit->end() == $end ) {
848 return $unit;
852 return;
856 =head2 _parse_hmmsearch
858 Title : _parse_hmmsearch
859 Usage : $res->_parse_hmmsearch($filehandle)
860 Function:
861 Returns :
862 Args :
865 =cut
867 sub _parse_hmmsearch {
868 my $self = shift;
869 my $file = shift;
870 my ($id,$sqfrom,$sqto,$sc,$ev,$unit,$nd,$seq,$hmmf,$hmmt,
871 $hmmfname,$hmmacc, $hmmid, %seqh);
872 my $count = 0;
874 while(<$file>) {
875 /^HMM file:\s+(\S+)/ and do { $self->hmmfile($1); $hmmfname = $1 };
876 /^Accession:\s+(\S+)/ and do { $hmmacc = $1 };
877 /^Query HMM:\s+(\S+)/ and do { $hmmid = $1 };
878 /^Sequence database:\s+(\S+)/ and do { $self->seqfile($1) };
879 /^Scores for complete sequences/ && last;
882 $hmmfname = "given" if not $hmmfname;
884 while(<$file>) {
885 /^Parsed for domains/ && last;
886 if( (($id, $sc, $ev, $nd) = /(\S+).+?\s(\S+)\s+(\S+)\s+(\d+)\s*$/)) {
887 $seq = Bio::Tools::HMMER::Set->new();
888 $seq->name($id);
889 $seq->bits($sc);
890 $seqh{$id} = $sc;
891 $seq->evalue($ev);
892 $self->add_Set($seq);
893 $seq->accession($hmmacc);
897 while(<$file>) {
898 /^Alignments of top-scoring domains/ && last;
899 if( (($id, $sqfrom, $sqto, $hmmf, $hmmt, $sc, $ev) = /(\S+)\s+\S+\s+(\d+)\s+(\d+).+?(\d+)\s+(\d+)\s+\S+\s+(\S+)\s+(\S+)\s*$/)) {
900 $unit = Bio::Tools::HMMER::Domain->new();
902 $unit->seq_id($id);
903 $unit->hmmname($hmmfname);
904 $unit->start($sqfrom);
905 $unit->end($sqto);
906 $unit->bits($sc);
907 $unit->hstart($hmmf);
908 $unit->hend($hmmt);
909 $unit->evalue($ev);
910 $unit->seqbits($seqh{$id});
911 $self->add_Domain($unit);
912 $count++;
916 $_ = <$file>;
918 ## Recognize and store domain alignments
920 while(1) {
921 if( !defined $_ ) {
922 last;
924 /^Histogram of all scores/ && last;
926 # matches:
927 # PF00621: domain 1 of 1, from 198 to 372
928 if( /^\s*(\S+):.*from\s+(\d+)\s+to\s+(\d+)/ ) {
929 my $name = $1;
930 my $from = $2;
931 my $to = $3;
933 # find the HMMUnit which this alignment is from
934 $unit = $self->get_unit_nse($name,$hmmfname,$from,$to);
936 if( !defined $unit ) {
937 $self->warn("Could not find $name $from $to unit even though I am reading it in. ugh!");
938 next;
940 while(<$file>) {
941 /^Histogram of all scores/ && last;
942 /^\s*\S+:.*from\s+\d+\s+to\s+\d+/ && last;
943 $unit->add_alignment_line($_);
946 else {
947 $_ = <$file>;
951 return $count;
954 =head2 parsetype
956 Title : parsetype
957 Usage : $obj->parsetype($newval)
958 Function:
959 Returns : value of parsetype
960 Args : newvalue (optional)
963 =cut
965 sub parsetype{
966 my ($self,$value) = @_;
967 if( defined $value) {
968 $self->{'_parsetype'} = $value;
970 return $self->{'_parsetype'};
973 1; # says use was ok
974 __END__