-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathFeature_layout_organizer.pm
executable file
·93 lines (69 loc) · 2.07 KB
/
Feature_layout_organizer.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
#!/usr/local/bin/perl
package main;
our ($DEBUG);
package Feature_layout_organizer;
use strict;
## Each feature must be a hashref with keys (lend, rend) where lend <= rend
sub organize_features {
my @features = @_;
## First, sort the features so that the longer ones appear first:
@features = reverse sort { ($a->{rend} - $a->{lend})
<=>
($b->{rend} - $b->{lend}) } @features;
my @rows = ([]);
# each row contains an array-ref of sorted non-overlapping features
while (@features) {
my $curr_feature = shift @features;
my $added_flag = 0;
for (my $i=0; $i <= $#rows; $i++) {
my $curr_row = $rows[$i];
if (! &overlaps_existing_features($curr_row, $curr_feature)) {
# add feature to current row:
push (@$curr_row, $curr_feature);
@$curr_row = sort {$a->{lend}<=>$b->{lend}} @$curr_row; #maintain sortedness.
$added_flag = 1;
last;
}
}
unless ($added_flag) {
#must add another row:
push (@rows, [$curr_feature]);
}
}
return (@rows);
}
sub overlaps_existing_features {
my ($curr_row, $curr_feature) = @_;
## check for empty row:
unless (@$curr_row) {
return (0); #nothing yet to overlap.
}
## Do a binary search on the row to see if features overlap:
my $curr_lend = $curr_feature->{lend};
my $curr_rend = $curr_feature->{rend};
my $left_index = 0;
my $right_index = $#{$curr_row};
my $done = 0;
while (!$done) {
if ($left_index > $right_index) {
$done = 1;
} else {
my $search_index = int (($left_index + $right_index)/2 + 0.5);
my $check_feature = $curr_row->[$search_index];
my ($check_lend, $check_rend) = ($check_feature->{lend}, $check_feature->{rend});
if ($check_lend <= $curr_rend && $check_rend >= $curr_lend) {
# overlaps:
return (1);
} else {
# no overlap, reset search range and keep looking.
if ($curr_lend < $check_lend) {
$right_index = $search_index - 1;
} else {
$left_index = $search_index + 1;
}
}
}
}
return (0); # no apparent conflict
}
1; #EOM