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