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