forked from PASApipeline/PASApipeline
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBinaryFeatureSearch.pm
executable file
·98 lines (66 loc) · 1.78 KB
/
BinaryFeatureSearch.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/env perl
package BinaryFeatureSearch;
use strict;
use warnings;
sub new {
my $packagename = shift;
my $chr_to_features_href = shift;
## Format should be:
# chr_to_features_href->{molecule} = [ a, b, c]
# where a = { acc => accession, lend => coord, rend => coord }
my $self = { chr_to_features_href => $chr_to_features_href };
bless ($self, $packagename);
$self->_sort_features_by_lend();
return($self);
}
####
sub _sort_features_by_lend {
my $self = shift;
my $chr_to_features_href = $self->{chr_to_features_href};
foreach my $molecule (keys %$chr_to_features_href) {
@{$chr_to_features_href->{$molecule}} = sort {$a->{lend}<=>$b->{lend}} @{$chr_to_features_href->{$molecule}};
}
return;
}
####
sub find_overlapping_feature {
my $self = shift;
my ($molecule, $pos_lend, $pos_rend) = @_;
my $feature_list_aref = $self->{chr_to_features_href}->{$molecule};
unless (ref $feature_list_aref) {
print STDERR "No features for $molecule\n";
return;
}
## perform binary search
my $i_left = 0;
my $i_right = $#$feature_list_aref;
while (1) {
if ($i_right < $i_left) {
last;
}
my $mid_index = int(($i_left+$i_right)/2 + 0.5);
my $feature = $feature_list_aref->[$mid_index];
my ($acc, $lend, $rend) = ($feature->{acc},
$feature->{lend},
$feature->{rend});
# print "Comparing [$i_left, $i_right, $mid_index] to $acc\t$lend\t$rend\n";
if ($pos_rend < $lend) {
# binary search left
$i_right = $mid_index - 1;
next;
}
elsif ($pos_lend > $rend) {
$i_left = $mid_index + 1;
next;
}
elsif ($lend <= $pos_rend && $rend >= $pos_lend) {
return($feature);
}
else {
# not sure what to do:
die "Error, doesn't overlap and isn't on either side";
}
}
return;
}
1; #EOM