File Coverage

blib/lib/CracTools/Interval/Query.pm
Criterion Covered Total %
statement 86 92 93.4
branch 17 28 60.7
condition 1 3 33.3
subroutine 18 18 100.0
pod 8 8 100.0
total 130 149 87.2


line stmt bran cond sub pod time code
1             package CracTools::Interval::Query;
2             {
3             $CracTools::Interval::Query::DIST = 'CracTools';
4             }
5             # ABSTRACT: Store and query genomics intervals.
6             #
7             $CracTools::Interval::Query::VERSION = '1.22';
8 4     4   22056 use strict;
  4         8  
  4         104  
9 4     4   20 use warnings;
  4         6  
  4         99  
10              
11 4     4   1314 use CracTools::Utils;
  4         9  
  4         140  
12 4     4   3045 use Set::IntervalTree 0.10;
  4         45056  
  4         319  
13 4     4   40 use Carp;
  4         9  
  4         5590  
14              
15              
16             sub new {
17 4     4 1 20 my $class = shift;
18              
19 4         13 my %args = @_;
20              
21 4         15 my $self = bless {
22             interval_trees => {},
23             }, $class;
24              
25 4         15 return $self;
26             }
27              
28              
29             sub addInterval {
30 48     48 1 73 my $self = shift;
31 48         80 my ($chr,$start,$end,$strand,$value) = @_;
32              
33 48         95 my $interval_tree = $self->_getIntervalTree($chr,$strand);
34             # If there is no already existing IntervalTree for this ("chr","strand") pair
35 48 100       126 if(!defined $interval_tree) {
36             # We create a new one
37 11         107 $interval_tree = Set::IntervalTree->new;
38             # We add this new interval tree with the others
39 11         36 $self->_addIntervalTree($chr,$strand,$interval_tree);
40             }
41              
42             # We insert the given interval in the IntervalTree
43             # pos_end +1 because Interval tree use [a,b) intervals
44             #$interval_tree->insert($value,$start,$end+1);
45 48         364 $interval_tree->insert({value => $value, start => $start, end => $end},$start,$end+1);
46             }
47              
48              
49             sub fetchByRegion {
50 31     31 1 55 my ($self,$chr,$pos_start,$pos_end,$strand,$windowed) = @_;
51              
52 31         67 my $interval_tree = $self->_getIntervalTree($chr,$strand);
53            
54 31 50       107 if(defined $interval_tree) {
55 31 50 33     103 if(defined $windowed && $windowed) {
56             # pos_end +1 because Interval tree use [a,b) intervals
57 0         0 return $self->_processReturnValues($interval_tree->fetch_window($pos_start,$pos_end+1));
58             } else {
59             # pos_end +1 because Interval tree use [a,b) intervals
60 31         191 return $self->_processReturnValues($interval_tree->fetch($pos_start,$pos_end+1));
61             }
62             }
63 0         0 return [];
64             }
65              
66              
67             sub fetchByLocation {
68 19     19 1 1888 my ($self,$chr,$position,$strand) = @_;
69 19         45 return $self->fetchByRegion($chr,$position,$position,$strand);
70             }
71              
72              
73             sub fetchNearestDown {
74 5     5 1 8 my ($self,$chr,$position,$strand) = @_;
75              
76 5         13 my $interval_tree = $self->_getIntervalTree($chr,$strand);
77            
78 5 50       18 if(defined $interval_tree) {
79 5         19 my $nearest_down = $interval_tree->fetch_nearest_down($position);
80 5 50       15 if(defined $nearest_down) {
81             return ({start => $nearest_down->{start}, end => $nearest_down->{end}},
82             $self->_processReturnValue($nearest_down->{value})
83 5         67 );
84             }
85             }
86 0         0 return [];
87             }
88              
89              
90             sub fetchNearestUp {
91 4     4 1 7 my ($self,$chr,$position,$strand) = @_;
92              
93 4         12 my $interval_tree = $self->_getIntervalTree($chr,$strand);
94            
95 4 50       14 if(defined $interval_tree) {
96 4         14 my $nearest_up = $interval_tree->fetch_nearest_up($position);
97 4 50       11 if(defined $nearest_up) {
98             return ({start => $nearest_up->{start}, end => $nearest_up->{end}},
99             $self->_processReturnValue($nearest_up->{value})
100 4         23 );
101             }
102             }
103 0         0 return [];
104             }
105              
106              
107             sub fetchAllNearestDown {
108 5     5 1 10 my ($self,$chr,$position,$strand) = @_;
109              
110 5         18 my ($nearest_down_interval,$nearest_down) = $self->fetchNearestDown($chr,$position,$strand);
111 5 50       15 if(defined $nearest_down) {
112             # We return all lines that belong to this
113 5         17 my ($hits_interval,$hits) = $self->fetchByLocation($chr,$nearest_down_interval->{end},$strand);
114 5         10 my @valid_hits;
115             my @valid_hits_interval;
116 5         18 for (my $i = 0; $i < @$hits; $i++) {
117             # if this inteval as the same "end" boudaries as the nearest down interval
118 15 100       84 if($hits_interval->[$i]->{end} == $nearest_down_interval->{end}) {
119 10         17 push @valid_hits, $hits->[$i];
120 10         28 push @valid_hits_interval, $hits_interval->[$i];
121             }
122             }
123 5         41 return (\@valid_hits_interval,\@valid_hits);
124             }
125 0         0 return [];
126             }
127              
128              
129             sub fetchAllNearestUp {
130 4     4 1 8 my ($self,$chr,$position,$strand) = @_;
131              
132 4         14 my ($nearest_up_interval,$nearest_up) = $self->fetchNearestUp($chr,$position,$strand);
133              
134 4 50       13 if(defined $nearest_up) {
135             # We return all lines that belong to this
136 4         14 my ($hits_interval,$hits) = $self->fetchByLocation($chr,$nearest_up_interval->{start},$strand);
137 4         9 my @valid_hits;
138             my @valid_hits_interval;
139 4         16 for (my $i = 0; $i < @$hits; $i++) {
140             # if this inteval as the same "end" boudaries as the nearest down interval
141 9 100       27 if($hits_interval->[$i]->{start} == $nearest_up_interval->{start}) {
142 7         11 push @valid_hits, $hits->[$i];
143 7         22 push @valid_hits_interval, $hits_interval->[$i];
144             }
145             }
146 4         28 return (\@valid_hits_interval,\@valid_hits);
147             }
148              
149 0         0 return [];
150             }
151              
152              
153             sub _getIntervalTree {
154 88     88   126 my ($self,$chr,$strand) = @_;
155 88 50       178 $strand = 1 if !defined $strand;
156 88         189 return $self->{interval_trees}{_getIntervalTreeKey($chr,$strand)};
157             }
158              
159              
160             sub _addIntervalTree {
161 11     11   21 my ($self,$chr,$strand,$interval_tree) = @_;
162 11 50       29 $strand = 1 if !defined $strand;
163 11         25 $self->{interval_trees}{_getIntervalTreeKey($chr,$strand)} = $interval_tree;
164             }
165              
166              
167             sub _getIntervalTreeKey {
168 99     99   129 my ($chr,$strand) = @_;
169 99 50       179 $strand = 1 if !defined $strand;
170 99         342 return "$chr"."@"."$strand";
171             }
172              
173              
174             sub _processReturnValues {
175 31     31   44 my $self = shift;
176 31         39 my $return_values = shift;
177 31         46 my @processed_return_values = ();
178 31         41 my @processed_return_intervals = ();
179 31         34 foreach (@{$return_values}) {
  31         75  
180 78         197 push(@processed_return_values, $self->_processReturnValue($_->{value}));
181             push(@processed_return_intervals, {
182             start => $_->{start},
183             end => $_->{end}
184             }
185 78         285 );
186             }
187 31         133 return (\@processed_return_intervals,\@processed_return_values);
188             }
189              
190              
191             sub _processReturnValue {
192 51     51   60 my $self = shift;
193 51         58 my $val = shift;
194 51         80 return $val;
195             }
196              
197             1;
198              
199             __END__