File Coverage

blib/lib/Bio/MUST/Drivers/Exonerate.pm
Criterion Covered Total %
statement 45 89 50.5
branch 0 10 0.0
condition n/a
subroutine 15 21 71.4
pod 0 6 0.0
total 60 126 47.6


line stmt bran cond sub pod time code
1             package Bio::MUST::Drivers::Exonerate;
2             # ABSTRACT: Bio::MUST driver for running the Exonerate alignment program
3             $Bio::MUST::Drivers::Exonerate::VERSION = '0.210160';
4 5     5   64 use Moose;
  5         11  
  5         45  
5 5     5   37598 use namespace::autoclean;
  5         13  
  5         57  
6              
7 5     5   517 use autodie;
  5         13  
  5         52  
8 5     5   29003 use feature qw(say);
  5         14  
  5         554  
9              
10 5     5   40 use Carp;
  5         22  
  5         450  
11 5     5   40 use Const::Fast;
  5         11  
  5         69  
12 5     5   438 use IPC::System::Simple qw(system);
  5         12  
  5         313  
13 5     5   38 use List::AllUtils qw(mesh);
  5         12  
  5         330  
14 5     5   65 use Module::Runtime qw(use_module);
  5         12  
  5         39  
15 5     5   493 use Path::Class qw(file);
  5         11  
  5         302  
16              
17 5     5   35 use Bio::MUST::Core;
  5         23  
  5         178  
18 5     5   34 use aliased 'Bio::MUST::Core::Ali';
  5         12  
  5         45  
19 5     5   1229 use aliased 'Bio::MUST::Core::GeneticCode';
  5         14  
  5         19  
20 5     5   1084 use aliased 'Bio::MUST::Core::Seq';
  5         18  
  5         21  
21 5     5   1062 use aliased 'Bio::MUST::Drivers::Exonerate::Sugar';
  5         14  
  5         21  
22              
23              
24             has 'dna_seq' => (
25             is => 'ro',
26             isa => 'Bio::MUST::Core::Seq',
27             required => 1,
28             );
29              
30             has 'pep_seq' => (
31             is => 'ro',
32             isa => 'Bio::MUST::Core::Seq',
33             required => 1,
34             );
35              
36             has 'genetic_code' => (
37             is => 'ro',
38             isa => 'Bio::MUST::Core::GeneticCode',
39             required => 1,
40             );
41              
42             has '_ali' => (
43             is => 'ro',
44             isa => 'Bio::MUST::Core::Ali',
45             init_arg => undef,
46             writer => '_set_ali',
47             handles => {
48             all_cds => 'all_seqs',
49             count_cds => 'count_seqs',
50             },
51             );
52              
53             has '_sugars' => (
54             traits => ['Array'],
55             is => 'ro',
56             isa => 'ArrayRef[Bio::MUST::Drivers::Exonerate::Sugar]',
57             default => sub { [] },
58             handles => {
59             add_sugar => 'push',
60             get_sugar => 'get',
61             },
62             );
63              
64              
65             const my @attrs => qw(
66             query_id query_start query_end query_strand
67             target_id target_start target_end target_strand
68             score
69             );
70              
71             sub BUILD {
72 0     0 0   my $self = shift;
73              
74             # provision executable
75 0           my $app = use_module('Bio::MUST::Provision::Exonerate')->new;
76 0           $app->meet();
77              
78             # build temp Ali file for input DNA seq
79 0           my $dna = Ali->new(
80             seqs => [ $self->dna_seq ],
81             guessing => 0,
82             );
83 0           my $dnafile = $dna->temp_fasta;
84              
85             # build temp Ali file for input PEP seq
86 0           my $pep = Ali->new(
87             seqs => [ $self->pep_seq ],
88             guessing => 0,
89             );
90 0           my $pepfile = $pep->temp_fasta;
91              
92             # setup output file
93 0           my $outfile = $dnafile . '.exonerate.out';
94             # TODO: make outfile name more robust using File::Temp
95              
96             # create exonerate command
97 0           my $pgm = 'exonerate';
98 0           my $code = $self->genetic_code->ncbi_id;
99 0           my $cmd = qq{$pgm --ryo ">%S\\n%tcs" --showvulgar no}
100             . " --showalignment no --verbose 0 --geneticcode $code"
101             . " --model protein2genome --query $pepfile --target $dnafile"
102             . " > $outfile 2> /dev/null"
103             ;
104              
105             # try to robustly execute exonerate
106 0           my $ret_code = system( [ 0, 127 ], $cmd);
107 0 0         if ($ret_code == 127) {
108 0           carp "[BMD] Warning: Cannot execute $pgm command; returning nothing!";
109 0           return;
110             }
111             # TODO: try to bypass shell (need for absolute path to executable then)
112              
113             # read output file (FASTA format with special defline)
114 0           my $ali = Ali->load($outfile);
115 0           $self->_set_ali($ali);
116              
117             # parse deflines and store them as Sugar objects
118             # TODO: fix coordinates for consistency with Aligned? (beware of rev_comp)
119 0           for my $id ($ali->all_seq_ids) {
120 0           my @fields = split /\s+/xms, $id->full_id;
121 0           $fields[0] = $self->pep_seq->seq_id->full_id;
122 0           $fields[4] = $self->dna_seq->seq_id->full_id;
123             @fields[3,7] = map {
124 0 0         $_ eq '-' ? -1 : # reverse
  0 0          
    0          
125             $_ eq '+' ? 1 : # forward
126             $_ eq '.' ? 1 : # unknown
127             $_
128             } @fields[3,7];
129 0           $self->add_sugar( Sugar->new( { mesh @attrs, @fields } ) );
130             }
131             # TODO: check value of strands / gene orientation
132              
133             # unlink temp files
134 0           file($_)->remove for ($dnafile, $pepfile, $outfile);
135              
136 0           return;
137             }
138              
139              
140             sub cds_order {
141 0     0 0   my $self = shift;
142              
143             # return exon indices according to start pos in protein coordinates
144             my @order = sort {
145 0           $self->get_sugar($a)->query_start <=> $self->get_sugar($b)->query_start
  0            
146             } 0..$self->count_cds-1;
147              
148 0           return @order;
149             }
150              
151              
152             sub all_exons_in_order {
153 0     0 0   my $self = shift;
154 0           return @{ $self->_ali->seqs }[ $self->cds_order ];
  0            
155             }
156              
157              
158             sub complete_cds {
159 0     0 0   my $self = shift;
160              
161             # splice CDS from sorted exons
162 0           my $full_id = $self->dna_seq->full_id;
163 0           my $new_seq = join q{}, map { $_->seq } $self->all_exons_in_order;
  0            
164              
165             # warn of unexpected CDS length
166 0 0         carp "[BMD] Warning: spliced CDS length not a multiple of 3 for $full_id!"
167             unless length($new_seq) % 3 == 0;
168              
169 0           return Seq->new(seq_id => $full_id, seq => $new_seq);
170             }
171              
172              
173             sub translation {
174 0     0 0   my $self = shift;
175              
176             # return translated protein from spliced CDS
177 0           return $self->genetic_code->translate($self->complete_cds);
178             }
179              
180              
181             sub all_sugars_in_order {
182 0     0 0   my $self = shift;
183 0           return @{ $self->_sugars }[ $self->cds_order ];
  0            
184             }
185              
186             __PACKAGE__->meta->make_immutable;
187             1;
188              
189             __END__
190              
191             =pod
192              
193             =head1 NAME
194              
195             Bio::MUST::Drivers::Exonerate - Bio::MUST driver for running the Exonerate alignment program
196              
197             =head1 VERSION
198              
199             version 0.210160
200              
201             =head1 SYNOPSIS
202              
203             # TODO
204              
205             =head1 DESCRIPTION
206              
207             # TODO
208              
209             =head1 AUTHOR
210              
211             Denis BAURAIN <denis.baurain@uliege.be>
212              
213             =head1 COPYRIGHT AND LICENSE
214              
215             This software is copyright (c) 2013 by University of Liege / Unit of Eukaryotic Phylogenomics / Denis BAURAIN.
216              
217             This is free software; you can redistribute it and/or modify it under
218             the same terms as the Perl 5 programming language system itself.
219              
220             =cut