File Coverage

blib/lib/Bio/Palantir/Refiner/GenePlus.pm
Criterion Covered Total %
statement 15 75 20.0
branch 0 18 0.0
condition 0 2 0.0
subroutine 5 8 62.5
pod 0 1 0.0
total 20 104 19.2


line stmt bran cond sub pod time code
1             package Bio::Palantir::Refiner::GenePlus;
2             # ABSTRACT: Refiner internal class for handling GenePlus objects
3             $Bio::Palantir::Refiner::GenePlus::VERSION = '0.200700';
4 1     1   504 use Moose;
  1         2  
  1         5  
5 1     1   5377 use namespace::autoclean;
  1         3  
  1         6  
6              
7 1     1   60 use Data::UUID;
  1         2  
  1         56  
8 1     1   7 use List::AllUtils qw(each_array);
  1         2  
  1         130  
9              
10 1     1   6 use aliased 'Bio::Palantir::Refiner::DomainPlus';
  1         2  
  1         12  
11              
12              
13             # private attributes
14              
15             has '_gene' => (
16             is => 'ro',
17             isa => 'Bio::Palantir::Parser::Gene',
18             handles => [qw(
19             name rank protein_sequence genomic_dna_begin
20             genomic_dna_end genomic_dna_coordinates
21             genomic_dna_size genomic_prot_begin genomic_prot_end
22             genomic_prot_coordinates genomic_prot_size
23             )],
24             );
25              
26             has 'from_seq' => (
27             is => 'ro',
28             isa => 'Bool',
29             default => 0,
30             );
31              
32             # public attributes
33              
34             has 'gap_filling' => (
35             is => 'ro',
36             isa => 'Bool',
37             default => 1,
38             );
39              
40             has 'undef_cleaning' => (
41             is => 'ro',
42             isa => 'Bool',
43             default => 1,
44             );
45              
46             has 'uui' => (
47             is => 'ro',
48             isa => 'Str',
49             init_arg => undef,
50             default => sub {
51             my $self = shift;
52             my $ug = Data::UUID->new;
53             my $uui = $ug->create_str();
54             return $uui;
55             }
56             );
57              
58             has 'gene_begin' => (
59             is => 'ro',
60             isa => 'Num',
61             init_arg => undef,
62             default => 1,
63             );
64              
65             has 'gene_end' => (
66             is => 'ro',
67             isa => 'Num',
68             init_arg => undef,
69             default => sub {
70             my $self = shift;
71             return $self->genomic_prot_size;
72             }
73             );
74              
75              
76             # public array(s) of composed objects
77              
78              
79             has 'domains' => (
80             traits => ['Array'],
81             is => 'ro',
82             isa => 'ArrayRef[Bio::Palantir::Refiner::DomainPlus]',
83             init_arg => undef,
84             default => sub { [] },
85             writer => '_set_domains',
86             handles => {
87             count_domains => 'count',
88             all_domains => 'elements',
89             get_domain => 'get',
90             next_domain => 'shift',
91             },
92             );
93              
94             with 'Bio::Palantir::Roles::Fillable',
95             'Bio::Palantir::Roles::Geneable';
96              
97              
98              
99             has 'exp_domains' => (
100             traits => ['Array'],
101             is => 'ro',
102             isa => 'ArrayRef[Bio::Palantir::Refiner::DomainPlus]',
103             init_arg => undef,
104             lazy => 1,
105             builder => '_build_exp_domains',
106             handles => {
107             count_exp_domains => 'count',
108             all_exp_domains => 'elements',
109             get_exp_domain => 'get',
110             next_exp_domain => 'shift',
111             },
112             );
113              
114             ## no critic (ProhibitUnusedPrivateSubroutines)
115              
116             sub _build_exp_domains {
117 0     0     my $self = shift;
118              
119 0           my ($seq) = $self->protein_sequence;
120 0           my $gene_pos = 0;
121              
122 0           my @domains = $self->detect_domains($seq, $gene_pos, undef, 1);
123            
124 0 0         unless (@domains) {
125 0           return [];
126             }
127              
128 0           return [ sort { $a->begin <=> $b->begin } @domains ];
  0            
129             }
130              
131             ## use critic
132              
133              
134             sub BUILD {
135             #TODO encapsulate the BUILD in Roles/Fillable.pm
136 0     0 0   my $self = shift;
137              
138 0 0         if ($self->from_seq == 1) {
139            
140 0           my ($seq) = $self->protein_sequence;
141 0           my $gene_pos = 0;
142              
143 0           my @domains = $self->detect_domains($seq, $gene_pos, undef, 1);
144              
145 0 0         unless (@domains) {
146 0           return;
147             }
148              
149 0           $self->_set_domains( [sort { $a->begin <=> $b->begin } @domains] );
  0            
150             }
151              
152             else {
153              
154             # based on Bio::Palantir::Parser::Gene
155 0           my @domains_plus;
156 0           for my $domain ($self->_gene->all_domains) {
157 0           push @domains_plus, DomainPlus->new(
158             protein_sequence => $domain->protein_sequence,
159             function => $domain->function,
160             base_uui => $domain->uui,
161             _domain => $domain,
162             begin => $domain->begin,
163             monomer => $domain->monomer,
164             );
165             }
166            
167 0 0         unless (@domains_plus) {
168 0           return;
169             }
170              
171             # get all domain properties
172 0           $self->_get_domain_features($_, $_->begin) for @domains_plus;
173            
174             # delete domains from antismash where we can't retrieve traces with all pHMMs (bugs ? -> P pisi Pren)
175 0 0         if ($self->undef_cleaning == 1 ) {
176 0           @domains_plus = grep { $_->function ne 'to_remove' } @domains_plus;
  0            
177             }
178            
179 0           $self->_set_domains(\@domains_plus);
180            
181             # elongate and refine domain coordinates
182 0           $self->_elongate_coordinates([$self->all_domains]);
183 0           $self->_refine_coordinates($self->all_domains);
184              
185             # subtype the domains
186 0           $self->_get_domain_subtype($_) for $self->all_domains;
187            
188             # fill gaps if needed (add domains)
189 0 0         unless ($self->gap_filling == 0) {
190 0           $self->_fill_gaps();
191             }
192              
193             #TODO $self->_get_docking_domains
194             }
195            
196 0           return;
197             }
198              
199             # public methods
200              
201              
202             # private methods
203              
204             sub _fill_gaps { # use gene protein sequence
205 0     0     my $self = shift;
206            
207 0   0       my $gap_cutoff = shift // 250;
208              
209             # point out gaps in the domain architecture
210 0           my %gap_for;
211 0           my $gap_corr = 1;
212              
213 0           my @domains = sort { $a->begin <=> $b->begin } $self->all_domains; # still no rank at this stage
  0            
214              
215 0           for (my $i = 0; $i <= (scalar @domains - 2); $i++) {
216            
217 0           my $gap_begin = $domains[$i]->end + $gap_corr;
218 0           my $gap_end = $domains[$i+1]->begin - $gap_corr;
219              
220 0 0         if ( ($gap_end - $gap_begin + 1) > $gap_cutoff ) {
221              
222 0           $gap_for{ $gap_begin . '-' . $gap_end } = {
223             start => $gap_begin,
224             end => $gap_end,
225             size => ($gap_end - $gap_begin + 1),
226             };
227             }
228              
229             #TODO if last domain before the end of the gene, maybe check it for undetected domains
230             }
231              
232 0           for my $gap (keys %gap_for) {
233              
234 0           my $perl_corr = 1;
235 0           my ($seq) = $self->protein_sequence;
236             $seq = substr($seq, $gap_for{$gap}{start} - $perl_corr,
237 0           $gap_for{$gap}{size});
238              
239             my @new_domains = $self->detect_domains($seq, $gap_for{$gap}{start},
240 0           [ $gap_for{$gap}{start}, $gap_for{$gap}{end} ]) ;
241              
242             # remove very truncated domains (to not overlap previous domain in upstream)
243 0           for my $i (0..@new_domains - 1) {
244              
245 0           my $match_length = $new_domains[$i]->size;
246 0           my $length_cutoff = $new_domains[$i]->tlen * 0.5;
247              
248 0 0         delete $new_domains[$i] if $match_length <= $length_cutoff;
249             }
250            
251 0           @new_domains = grep { defined } @new_domains;
  0            
252              
253 0 0         if (@new_domains) {
254             my @ordered_domains
255 0           = sort { $a->begin <=> $b->begin } (@domains, @new_domains);
  0            
256 0           $self->_set_domains(\@ordered_domains);
257             }
258             }
259              
260 0           return;
261             }
262              
263              
264             __PACKAGE__->meta->make_immutable;
265             1;
266              
267             __END__
268              
269             =pod
270              
271             =head1 NAME
272              
273             Bio::Palantir::Refiner::GenePlus - Refiner internal class for handling GenePlus objects
274              
275             =head1 VERSION
276              
277             version 0.200700
278              
279             =head1 SYNOPSIS
280              
281             # TODO
282              
283             =head1 DESCRIPTION
284              
285             # TODO
286              
287             =head1 ATTRIBUTES
288              
289             =head2 domains
290              
291             ArrayRef of L<Bio::Palantir::Refiner::Domain>
292              
293             =head2 exp_domains
294              
295             ArrayRef of L<Bio::Palantir::Refiner::Domain>
296              
297             =head1 METHODS
298              
299             =head2 count_domains
300              
301             Returns the number of Domains of the Gene.
302              
303             # $gene is a Bio::Palantir::Refiner::Gene
304             my $count = $gene->count_domains;
305              
306             This method does not accept any arguments.
307              
308             =head2 all_domains
309              
310             Returns all the Domains of the Gene (not an array reference).
311              
312             # $gene is a Bio::Palantir::Refiner::Gene
313             my @domains = $gene->all_domains;
314              
315             This method does not accept any arguments.
316              
317             =head2 get_domain
318              
319             # $gene is a Bio::Palantir::Refiner::Gene
320             my $domain = $gene->get_domain($index);
321             croak "Domain $index not found!" unless defined $domain;
322              
323             This method accepts just one argument (and not an array slice).
324              
325             =head2 next_domain
326              
327             Shifts the first Domain of the array off and returns it, shortening the
328             array by 1 and moving everything down. If there are no more Domains in
329             the array, returns C<undef>.
330              
331             # $gene is a Bio::Palantir::Refiner::Gene
332             while (my $domain = $gene->next_domain) {
333             # process $domain
334             # ...
335             }
336              
337             This method does not accept any arguments.
338              
339             =head2 count_exp_domains
340              
341             Returns the number of Domains of the Gene.
342              
343             # $gene is a Bio::Palantir::Refiner::Gene
344             my $count = $gene->count_exp_domains;
345              
346             This method does not accept any arguments.
347              
348             =head2 all_exp_domains
349              
350             Returns all the Domains of the Gene (not an array reference).
351              
352             # $gene is a Bio::Palantir::Refiner::Gene
353             my @exp_domains = $gene->all_exp_domains;
354              
355             This method does not accept any arguments.
356              
357             =head2 get_exp_domain
358              
359             # $gene is a Bio::Palantir::Refiner::Gene
360             my $exp_domain = $gene->get_exp_domain($index);
361             croak "Domain $index not found!" unless defined $exp_domain;
362              
363             This method accepts just one argument (and not an array slice).
364              
365             =head2 next_exp_domain
366              
367             Shifts the first Domain of the array off and returns it, shortening the
368             array by 1 and moving everything down. If there are no more Domains in
369             the array, returns C<undef>.
370              
371             # $gene is a Bio::Palantir::Refiner::Gene
372             while (my $exp_domain = $gene->next_exp_domain) {
373             # process $exp_domain
374             # ...
375             }
376              
377             This method does not accept any arguments.
378              
379             =head1 AUTHOR
380              
381             Loic MEUNIER <lmeunier@uliege.be>
382              
383             =head1 COPYRIGHT AND LICENSE
384              
385             This software is copyright (c) 2019 by University of Liege / Unit of Eukaryotic Phylogenomics / Loic MEUNIER and Denis BAURAIN.
386              
387             This is free software; you can redistribute it and/or modify it under
388             the same terms as the Perl 5 programming language system itself.
389              
390             =cut