File Coverage

blib/lib/GenOO/RegionCollection/Type/DoubleHashArray.pm
Criterion Covered Total %
statement 83 89 93.2
branch 10 14 71.4
condition n/a
subroutine 30 32 93.7
pod 0 15 0.0
total 123 150 82.0


line stmt bran cond sub pod time code
1             # POD documentation - main docs before the code
2              
3             =head1 NAME
4              
5             GenOO::RegionCollection::Type::DoubleHashArray - Object for a collection of GenOO::Region objects, with features
6              
7             =head1 SYNOPSIS
8              
9             # Object that manages a collection of GenOO::Region objects.
10              
11             # To initialize
12             my $locus_collection = GenOO::RegionCollection::DoubleHashArray->new({
13             name => undef,
14             species => undef,
15             description => undef,
16             extra => undef,
17             });
18              
19              
20             =head1 DESCRIPTION
21              
22             The primary data structure of this object is a 2D hash whose primary key is the strand
23             and its secondary key is the reference sequence name. Each such pair of keys correspond to an
24             array reference which stores objects of the class L<GenOO::Region> sorted by start position.
25              
26             =head1 EXAMPLES
27              
28             # Print records in FASTA format
29             $locus_collection->print("FASTA",'STDOUT',"/data1/data/UCSC/hg19/chromosomes/");
30            
31             # ditto
32             $locus_collection->print_in_fasta_format('STDOUT',"/data1/data/UCSC/hg19/chromosomes/");
33              
34             =cut
35              
36             # Let the code begin...
37              
38             package GenOO::RegionCollection::Type::DoubleHashArray;
39             $GenOO::RegionCollection::Type::DoubleHashArray::VERSION = '1.4.6';
40              
41             #######################################################################
42             ####################### Load External modules #####################
43             #######################################################################
44 1     1   6 use Modern::Perl;
  1         1  
  1         16  
45 1     1   199 use autodie;
  1         3  
  1         11  
46 1     1   3498 use Moose;
  1         2  
  1         5  
47 1     1   5021 use namespace::autoclean;
  1         2  
  1         9  
48              
49              
50             #######################################################################
51             ######################### Load GenOO modules ######################
52             #######################################################################
53 1     1   66 use GenOO::Module::Search::Binary;
  1         2  
  1         24  
54 1     1   497 use GenOO::Data::Structure::DoubleHashArray;
  1         3  
  1         1081  
55              
56              
57             #######################################################################
58             ####################### Interface attributes ######################
59             #######################################################################
60             has 'name' => (
61             isa => 'Str',
62             is => 'rw'
63             );
64              
65             has 'species' => (
66             isa => 'Str',
67             is => 'rw'
68             );
69              
70             has 'description' => (
71             isa => 'Str',
72             is => 'rw'
73             );
74              
75             has 'longest_record' => (
76             is => 'ro',
77             builder => '_find_longest_record',
78             clearer => '_clear_longest_record',
79             init_arg => undef,
80             lazy => 1,
81             );
82              
83             has 'extra' => (
84             is => 'rw'
85             );
86              
87              
88             #######################################################################
89             ######################## Private attributes #######################
90             #######################################################################
91             has '_container' => (
92             is => 'ro',
93             builder => '_build_container',
94             init_arg => undef,
95             lazy => 1
96             );
97              
98             #######################################################################
99             ########################## Consumed Roles #########################
100             #######################################################################
101             with 'GenOO::RegionCollection';
102              
103              
104             #######################################################################
105             ######################## Interface Methods ########################
106             #######################################################################
107             sub add_record {
108 1768     1768 0 2511 my ($self, $record) = @_;
109 1768         53655 $self->_container->add_entry($record->strand, $record->rname, $record);
110 1768         3474 $self->_reset;
111             }
112              
113             sub all_records {
114 6     6 0 1756 my ($self) = @_;
115            
116 6         15 my @all_records;
117             $self->foreach_record_do(sub {
118 158     158   238 push @all_records, $_[0];
119 6         47 });
120            
121 6 100       70 return wantarray ? @all_records : \@all_records;
122             }
123              
124             sub foreach_record_do {
125 14     14 0 1128 my ($self, $block) = @_;
126 14         534 $self->_container->foreach_entry_do($block);
127             }
128              
129             sub foreach_record_on_rname_do {
130 1     1 0 1074 my ($self, $rname, $block) = @_;
131 1         45 $self->_container->foreach_entry_on_secondary_key_do($rname, $block);
132             }
133              
134             sub records_count {
135 14     14 0 8520 my ($self) = @_;
136 14         567 return $self->_container->entries_count;
137             }
138              
139             sub strands {
140 1     1 0 1100 my ($self) = @_;
141 1         61 return $self->_container->primary_keys();
142             }
143              
144             sub rnames_for_strand {
145 2     2 0 1409 my ($self, $strand) = @_;
146 2         84 return $self->_container->secondary_keys_for_primary_key($strand);
147             }
148              
149             sub rnames_for_all_strands {
150 1     1 0 894 my ($self) = @_;
151 1         42 return $self->_container->secondary_keys_for_all_primary_keys();
152             }
153              
154             sub longest_record_length {
155 1     1 0 1155 my ($self) = @_;
156 1         45 return $self->longest_record->length;
157             }
158              
159             sub is_empty {
160 1     1 0 966 my ($self) = @_;
161 1         44 return $self->_container->is_empty;
162             }
163              
164             sub is_not_empty {
165 1     1 0 958 my ($self) = @_;
166 1         42 return $self->_container->is_not_empty;
167             }
168              
169             sub foreach_overlapping_record_do {
170 3     3 0 1424 my ($self, $strand, $chr, $start, $stop, $block) = @_;
171            
172 3         149 $self->_container->sort_entries;
173            
174             # Get a reference on the array containing the records of the specified strand and rname
175 3 50       16 my $records_ref = $self->_records_ref_for_strand_and_rname($strand, $chr) or return ();
176            
177             # Find the closest but greater value to a target value. Target value is defined such that
178             # any records with smaller values are impossible to overlap with the requested region
179             # This allows us to search only from that point onwards for overlap
180 3         126 my $target_value = $start - $self->longest_record->length;
181             my $index = GenOO::Module::Search::Binary->binary_search_for_value_greater_or_equal(
182             $target_value, $records_ref,
183             sub {
184 15     15   338 return $_[0]->start
185             }
186 3         35 );
187            
188             # If a value close and greater than the target value exists scan downstream for overlaps
189 3 50       15 if (defined $index) {
190 3         11 while ($index < @$records_ref) {
191 9         10 my $record = $records_ref->[$index];
192 9 50       230 if ($record->start <= $stop) {
193 9 100       231 if ($start <= $record->stop) {
194 8 50       25 last if $block->($record) eq 'break_loop';
195             }
196             }
197             else {
198 0         0 last; # No chance to find overlap from now on
199             }
200 9         35 $index++;
201             }
202             }
203             }
204              
205             sub records_overlapping_region {
206 2     2 0 2089 my ($self, $strand, $chr, $start, $stop) = @_;
207            
208 2         10 my @overlapping_records;
209             $self->foreach_overlapping_record_do($strand, $chr, $start, $stop,
210             sub {
211 5     5   5 my ($record) = @_;
212 5         17 push @overlapping_records, $record;
213             }
214 2         16 );
215            
216 2         12 return @overlapping_records;
217             }
218              
219             sub total_copy_number {
220 1     1 0 945 my ($self, $block) = @_;
221            
222 1         3 my $total_copy_number = 0;
223 1     12   13 $self->foreach_record_do( sub {$total_copy_number += $_[0]->copy_number} );
  12         308  
224            
225 1         7 return $total_copy_number;
226             }
227              
228             sub total_copy_number_for_records_contained_in_region {
229 0     0 0 0 my ($self, $strand, $rname, $start, $stop) = @_;
230            
231 0         0 my $total_copy_number = 0;
232 0     0   0 $self->foreach_overlapping_record_do( $strand, $rname, $start, $stop, sub {$total_copy_number += $_[0]->copy_number} );
  0         0  
233            
234 0         0 return $total_copy_number;
235             }
236              
237             #######################################################################
238             ######################### Private methods ##########################
239             #######################################################################
240             sub _build_container {
241 22     22   704 return GenOO::Data::Structure::DoubleHashArray->new(
242             sorting_code_block => sub {return $_[0]->start <=> $_[1]->start}
243 43     43   1916 );
244             }
245              
246             sub _find_longest_record {
247 5     5   8 my ($self) = @_;
248            
249 5         9 my $longest_record;
250 5         7 my $longest_record_length = 0;
251             $self->foreach_record_do(
252             sub {
253 61     61   67 my ($record) = @_;
254            
255 61 100       1353 if ($record->length > $longest_record_length) {
256 8         187 $longest_record_length = $record->length;
257 8         36 $longest_record = $record;
258             }
259             }
260 5         41 );
261            
262 5         213 return $longest_record;
263             }
264              
265             sub _records_ref_for_strand_and_rname {
266 4     4   886 my ($self, $strand, $chr) = @_;
267 4         155 return $self->_container->entries_ref_for_keys($strand, $chr);
268             }
269              
270             sub _reset {
271 1768     1768   1734 my ($self) = @_;
272 1768         63782 $self->_clear_longest_record;
273             }
274              
275              
276             #######################################################################
277             ############################ Finalize #############################
278             #######################################################################
279             __PACKAGE__->meta->make_immutable;
280             1;