rework to optimize a bit, again for bug #3172
[bioperl-live.git] / scripts / utilities / search2alnblocks.PLS
blobf58f0b525c99e1363bb2850e47e6917456c89167
1 #!perl -w
2 # Author:      Jason Stajich <jason-at-bioperl-dot-org>
3 # Description: Turn SearchIO parseable report(s) into a set of Aligned blocks
6 =head1 NAME
8 search2alnblocks - Turn SearchIO parseable reports(s) into a set of aligned blocks
10 =head1 SYNOPSIS
12   search2alnblocks --minid PERCENTID --minlen LEN --minevalue EVALUE file1.
13   blast file2.blast ...> out.fas
15 =head1 DESCRIPTION
17 This script will parse and filter BLAST (or other formats
18 L<Bio::SearchIO> can parse) output and format the alignment as blocks
19 of alignments based on the HSPs.  Note this can only work if the input
20 file parsed contains the necessary.
22 Typically this can be used to turn BLAST output into a FASTA alignment format for input into the QRNA comparative gene finder for RNA genes (E.Rivas).
24 =head1 OPTIONS
26  --maxevalue   Maximum E-value for an HSP
27  --minevalue   Minimum E-value for an HSP 
28  --minlen      Minimum length of an HSP [default 0] 
29  --maxid       Maximum Percent Id [default 100]
30                (to help remove sequences which are really close)
31  --minid       Minimum Percent Identity for an HSP [default 0]
32  -i/--input    An optional input filename (expects input on STDIN by default)
33  -o/--output   An optional output filename (exports to STDOUT by default)
34  -f/--format   Specify a different Search Alignment format- 
35                {fasta, axt, waba, blast, blastxml} are all permitted
36                although the format must have actual alignment 
37                sequence for this script to work
38                See L<Bio::SearchIO> for more information.
39  -of/--outformat Output format for the alignment blocks, anything
40                L<Bio::AlignIO> supports.
41  -v/--verbose  Turn on debugging
43 =head1 AUTHOR - Jason Stajich
45 Jason Stajich, jason-at-bioperl-dot-org.
47 =cut
50 use strict;
52 use Bio::SearchIO;
53 use Bio::AlignIO;
54 use Math::BigFloat;
55 use Getopt::Long;
57 my $Usage = 'search2alnblocks --minid PERCENTID --minlen LEN --maxevalue EVALUE file1.blast file2.blast ... > blocks.fas';
59 my ($min_id,$min_len,$max_id,$max_len,$max_evalue,$min_evalue,$format,
60     $outformat,$verbose,$input,$output);
61 $min_id  = 0;
62 $max_evalue = 0;
63 $min_evalue = undef;
64 $min_len = 0;
65 $format = 'blast';
66 $outformat= 'fasta';
67 GetOptions(
68            'minid:s'      => \$min_id,
69            'maxid:s'      => \$max_id,
70            'minlen:s'     => \$min_len,
71            'maxlen:s'     => \$max_len,
72            'minevalue:s'  => \$min_evalue,
73            'maxevalue:s'  => \$max_evalue,
74            'f|format:s'   => \$format,
75            'i|input:s'    => \$input,
76            'o|output:s'   => \$output,
77            'of|oformat:s' => \$outformat,
78            'v|verbose'    => \$verbose,
79            'h|help'       => sub { system('perldoc', $0);
80                                    exit(0) },
81            );
82 $max_evalue =~ s/^e/1e/;
84 # if $input is undef then will read from STDIN
85 my $parser =  new Bio::SearchIO(-format => $format,
86                                 -file   => $input,
87                                 -verbose=> $verbose);
88 my $out;
90 if( $output ) {
91     $out = new Bio::AlignIO(-format => $outformat,
92                             -file   => ">$output");
93 } else { 
94     $out = new Bio::AlignIO(-format => $outformat);
97 my $id = 1;
98 while( my $r = $parser->next_result ) {
99     while( my $hit = $r->next_hit ) {
100         while( my $hsp = $hit->next_hsp ) {
101             my $hsplen = $hsp->length('total');
102             next if( $min_len && $hsplen < $min_len);
103             my $pid = $hsp->percent_identity;
104             next if( ($min_id && $pid < $min_id) || 
105                      ($max_id && $pid > $max_id ) );
106             next if( defined $min_evalue && 
107                      $hsp->evalue > $min_evalue ); 
108             next if( $max_evalue && 
109                      $hsp->evalue < $max_evalue);           
110             $verbose && $hsp->verbose($verbose);            
111             my $aln = $hsp->get_aln();
112             my @seqs;
113             foreach my $seq ( $aln->each_seq ) {
114                 if( $seq->display_id =~ /(\S+)[\/\_](\d+)\-(\d+)/ ) {
115                     $seq->display_id($1);
116                     $seq->start($seq->start + $2 - 1);
117                     $seq->end($seq->end + $2 - 1);
118                 }
119                 $seq->description(sprintf("PID=%.2f LEN=%d HSP=%d",
120                                           $pid,$hsplen,$id));
121                 push @seqs, $seq;
122             }
123             $aln = new Bio::SimpleAlign();
124             $aln->add_seq(shift @seqs);
125             $aln->add_seq(shift @seqs);
126             
127             $id++;
128             $out->write_aln($aln);
129         }
130     }