File Coverage

blib/lib/Bio/MUST/Apps/TwoScalp/Seq2Seq.pm
Criterion Covered Total %
statement 48 110 43.6
branch 0 22 0.0
condition 0 6 0.0
subroutine 16 20 80.0
pod 0 2 0.0
total 64 160 40.0


line stmt bran cond sub pod time code
1             package Bio::MUST::Apps::TwoScalp::Seq2Seq;
2             # ABSTRACT: internal class for two-scalp tool
3             $Bio::MUST::Apps::TwoScalp::Seq2Seq::VERSION = '0.211710';
4 1     1   10 use Moose;
  1         2  
  1         9  
5 1     1   7464 use namespace::autoclean;
  1         3  
  1         23  
6              
7 1     1   91 use autodie;
  1         3  
  1         11  
8 1     1   5808 use feature qw(say);
  1         4  
  1         97  
9              
10 1     1   12 use Smart::Comments -ENV;
  1         2  
  1         21  
11              
12 1     1   2049 use List::AllUtils qw(part);
  1         5  
  1         68  
13              
14 1     1   7 use Bio::MUST::Core;
  1         2  
  1         33  
15 1     1   15 use Bio::MUST::Core::Constants qw(:gaps);
  1         12  
  1         195  
16 1     1   7 use Bio::MUST::Core::Utils qw(secure_outfile);
  1         4  
  1         63  
17 1     1   639 use Bio::MUST::Drivers;
  1         2190244  
  1         103  
18 1     1   10 use aliased 'Bio::MUST::Core::Ali';
  1         3  
  1         4  
19 1     1   193 use aliased 'Bio::MUST::Core::Ali::Temporary';
  1         3  
  1         6  
20 1     1   184 use aliased 'Bio::MUST::Core::Seq';
  1         17  
  1         5  
21 1     1   202 use aliased 'Bio::MUST::Core::SeqId';
  1         3  
  1         4  
22 1     1   174 use aliased 'Bio::MUST::Core::SeqMask';
  1         3  
  1         4  
23 1     1   193 use aliased 'Bio::MUST::Apps::SlaveAligner::Local';
  1         2  
  1         4  
24              
25              
26             has 'coverage_mul' => (
27             is => 'ro',
28             isa => 'Num',
29             default => 1.1,
30             );
31              
32             has 'single_hsp' => (
33             is => 'ro',
34             isa => 'Bool',
35             default => 0,
36             );
37              
38             has 'out_suffix' => (
39             is => 'ro',
40             isa => 'Maybe[Str]',
41             default => '-ts',
42             );
43              
44             has 'ali' => (
45             is => 'ro',
46             isa => 'Bio::MUST::Core::Ali',
47             required => 1,
48             coerce => 1,
49             );
50              
51             has 'lookup' => (
52             is => 'ro',
53             isa => 'Bio::MUST::Core::IdList',
54             init_arg => undef,
55             writer => '_set_lookup',
56             );
57              
58             has 'new_ali' => (
59             is => 'ro',
60             isa => 'Bio::MUST::Core::Ali',
61             init_arg => undef,
62             writer => '_set_new_ali',
63             );
64              
65             has 'integrator' => (
66             is => 'ro',
67             isa => 'Bio::MUST::Apps::SlaveAligner::Local',
68             init_arg => undef,
69             writer => '_set_integrator',
70             );
71              
72             has 'blastdb' => (
73             is => 'ro',
74             isa => 'Bio::MUST::Drivers::Blast::Database::Temporary',
75             init_arg => undef,
76             writer => '_set_blastdb',
77             );
78              
79             has 'query_seqs' => (
80             is => 'ro',
81             isa => 'Bio::MUST::Core::Ali::Temporary',
82             init_arg => undef,
83             writer => '_set_query_seqs',
84             );
85              
86              
87             sub _align_seqs {
88 0     0     my $self = shift;
89              
90 0           my $args->{-outfmt} = 5;
91 0           $args->{-max_target_seqs} = 5;
92              
93 0           my $blastdb = $self->blastdb;
94 0           my $query_seqs = $self->query_seqs;
95 0           my $parser = $blastdb->blast($query_seqs, $args);
96             #### [S2S] XML BLASTP/N: $parser->filename
97              
98 0           my $bo = $parser->blast_output;
99 0 0         return unless $bo;
100              
101 0 0         my $sort_method = $self->single_hsp ? 'score' : 'hit_start';
102              
103             QUERY:
104 0           for my $query ( $bo->all_iterations ) {
105              
106 0           my $query_id = $query_seqs->long_id_for( $query->query_def );
107             ##### [S2S] Aligning: $query_id
108              
109 0           my @templates;
110             my @template_seqs;
111 0           my $best_coverage = 0;
112              
113             TEMPLATE:
114 0           for my $template ( $query->all_hits ) {
115              
116             # compute query coverage by template HSPs
117 0           my $mask = SeqMask->empty_mask( $query->query_len );
118             $mask->mark_block( $_->query_start, $_->query_end )
119 0           for $template->all_hsps;
120 0           my $coverage = $mask->coverage;
121              
122 0 0         last TEMPLATE if $coverage
123             < $best_coverage * $self->coverage_mul;
124 0           $best_coverage = $coverage;
125              
126             # fetch template full_id
127 0           my $template_id = SeqId->new(
128             full_id => $blastdb->long_id_for( $template->def )
129             );
130              
131             ###### [S2S] template: $template_id->full_id
132             ###### [S2S] coverage: $coverage
133              
134             # fetch and cache aligned template seq from Ali
135 0           push @templates, $template;
136 0           push @template_seqs, $self->ali->get_seq(
137             $self->lookup->index_for( $template_id->full_id )
138             );
139             }
140              
141 0 0         unless (@templates) {
142             ##### [S2S] skipped alignment due to lack of suitable template
143 0           next QUERY;
144             }
145              
146 0 0         @templates = ( $templates[-1] ) if $self->single_hsp;
147              
148             TEMPLATE:
149 0           for my $template (@templates) {
150              
151             # use each template in turn for BLAST alignment
152 0           my $template_seq = shift @template_seqs;
153 0 0         last TEMPLATE unless $template_seq;
154              
155             # sort HSPs by descending start coordinate on template or by
156             # descending score depending on --single-hsp option
157             my @hsps = sort {
158 0           $b->$sort_method <=> $a->$sort_method
  0            
159             } $template->all_hsps;
160              
161             HSP:
162 0           for my $hsp (@hsps) {
163              
164             # build HSP id from query id (and template/HSP ranks)
165 0           my $hsp_id = $query_seqs->long_id_for( $query->query_def );
166 0 0         $hsp_id .= '.H' . $template->num . '.' . $hsp->num
167             unless $self->single_hsp;
168 0           $hsp_id .= '#NEW#';
169              
170             # build HSP seq from BLASTX report
171 0           (my $hsp_seq = $hsp->qseq) =~ s{\*}{$FRAMESHIFT}xmsg;
172 0           my $new_seq = Seq->new(
173             seq_id => $hsp_id,
174             seq => $hsp_seq
175             );
176              
177             # fetch aligned template seq from HSP (= subject)
178 0           my $subject_seq = Seq->new(
179             seq_id => $template_seq->seq_id,
180             seq => $hsp->hseq
181             );
182              
183             # reverse complement seqs if template on reverse in BLASTN
184 0 0 0       if ($query_seqs->type eq 'nucl' && $blastdb->type eq 'nucl'
      0        
185             && $hsp->hit_strand == -1) {
186 0           $new_seq = $new_seq->reverse_complemented_seq;
187 0           $subject_seq = $subject_seq->reverse_complemented_seq;
188             }
189              
190             # align new_seq on template_seq using subject_seq as a guide
191             $self->new_ali->add_seq(
192 0           $self->integrator->align(
193             new_seq => $new_seq,
194             subject => $subject_seq,
195             template => $template_seq,
196             start => $hsp->hit_start,
197             )
198             );
199              
200 0 0         last HSP if $self->single_hsp;
201             }
202             }
203             }
204              
205 0           return;
206             }
207              
208              
209             sub display { ## no critic (RequireArgUnpacking)
210 0     0 0   return join "\n--- ", q{}, @_
211             }
212              
213              
214             sub BUILD {
215 0     0 0   my $self = shift;
216              
217 0           my $ali = $self->ali;
218             #### [ALI] #seqs: $ali->count_seqs
219 0 0         unless ($ali->count_seqs) {
220             #### [ALI] empty file; skipping!
221 0           return;
222             }
223              
224             # Note: this class maintains DRY through a single BUILD
225             # hence the writers instead of the usual builders
226              
227 0           $self->_set_lookup( $ali->new_lookup );
228              
229             # TODO: fix bug with 'aligned' seqs only composed of trailing spaces
230             my ($unaligned_seqs, $aligned_seqs)
231 0 0   0     = part { $_->is_aligned ? 1 : 0 } $ali->all_seqs;
  0            
232             #### [S2S] seqs to align: display( map { $_->full_id } @{$unaligned_seqs} )
233              
234 0           $self->_set_blastdb( Bio::MUST::Drivers::Blast::Database::Temporary->new(
235             seqs => $aligned_seqs )
236             );
237 0           $self->_set_query_seqs( Temporary->new( seqs => $unaligned_seqs ) );
238              
239 0           my $new_ali = Ali->new( seqs => $aligned_seqs );
240 0           $self->_set_new_ali($new_ali);
241              
242 0           my $integrator = Local->new( ali => $new_ali );
243 0           $self->_set_integrator($integrator);
244              
245 0           $self->_align_seqs;
246              
247             #### [S2S] Making delayed indels...
248 0           $integrator->make_indels;
249              
250             #### [S2S] Writing updated file...
251 0           my $outfile = secure_outfile($ali->filename, $self->out_suffix);
252 0           $new_ali->store($outfile);
253              
254 0           return;
255             }
256              
257              
258             __PACKAGE__->meta->make_immutable;
259             1;
260              
261             __END__
262              
263             =pod
264              
265             =head1 NAME
266              
267             Bio::MUST::Apps::TwoScalp::Seq2Seq - internal class for two-scalp tool
268              
269             =head1 VERSION
270              
271             version 0.211710
272              
273             =head1 AUTHOR
274              
275             Denis BAURAIN <denis.baurain@uliege.be>
276              
277             =head1 COPYRIGHT AND LICENSE
278              
279             This software is copyright (c) 2013 by University of Liege / Unit of Eukaryotic Phylogenomics / Denis BAURAIN.
280              
281             This is free software; you can redistribute it and/or modify it under
282             the same terms as the Perl 5 programming language system itself.
283              
284             =cut