File Coverage

blib/lib/Bio/JBrowse/Store/NCList/NCList.pm
Criterion Covered Total %
statement 41 41 100.0
branch 13 14 92.8
condition n/a
subroutine 8 8 100.0
pod 1 4 25.0
total 63 67 94.0


line stmt bran cond sub pod time code
1             #After
2             #Alekseyenko, A., and Lee, C. (2007).
3             #Nested Containment List (NCList): A new algorithm for accelerating
4             # interval query of genome alignment and interval databases.
5             #Bioinformatics, doi:10.1093/bioinformatics/btl647
6             #http://bioinformatics.oxfordjournals.org/cgi/content/abstract/btl647v1
7              
8             package Bio::JBrowse::Store::NCList::NCList;
9             BEGIN {
10 3     3   893 $Bio::JBrowse::Store::NCList::NCList::AUTHORITY = 'cpan:RBUELS';
11             }
12             {
13             $Bio::JBrowse::Store::NCList::NCList::VERSION = '0.1';
14             }
15              
16 3     3   17 use strict;
  3         7  
  3         73  
17 3     3   15 use warnings;
  3         4  
  3         79  
18 3     3   14 use List::Util qw(max);
  3         5  
  3         1506  
19              
20              
21             sub new {
22 25     25 1 424 my ($class, $start, $end, $setSublist, $featList) = @_;
23              
24 2560 50       5784 my @features = sort {
25 25         154 $start->($a) <=> $start->($b) || $end->($b) <=> $end->($a)
26             } @$featList;
27              
28             #@sublistStack is a list of all the currently relevant sublists
29             #(one for each level of nesting)
30 25         49 my @sublistStack;
31             #$curlist is the currently active sublist
32 25         51 my $curList = [];
33              
34 25 100       106 my $self = { 'topList' => $curList,
35             'setSublist' => $setSublist,
36             'count' => scalar( @features ),
37             'minStart' => ( @features ? $start->($features[0]) : undef ),
38             };
39 25         110 bless $self, $class;
40              
41 25 100       77 push @$curList, $features[0] if @features;
42              
43 25 100       112 my $maxEnd = @features ? $end->($features[0]) : undef;
44              
45 25         38 my $topSublist;
46 25         71 for (my $i = 1; $i < @features; $i++) {
47 2560         6366 $maxEnd = max( $maxEnd, $end->( $features[$i] ));
48             #if this interval is contained in the previous interval,
49 2560 100       6245 if ($end->($features[$i]) < $end->($features[$i - 1])) {
50             #create a new sublist starting with this interval
51 14         27 push @sublistStack, $curList;
52 14         32 $curList = [$features[$i]];
53 14         50 $setSublist->($features[$i - 1], $curList);
54             } else {
55             #find the right sublist for this interval
56 2546         2645 while (1) {
57             #if we're at the top level list,
58 2559 100       4212 if ($#sublistStack < 0) {
59             #just add the current feature
60 2532         3828 push @$curList, $features[$i];
61 2532         6756 last;
62             } else {
63 27         38 $topSublist = $sublistStack[$#sublistStack];
64             #if the last interval in the top sublist ends
65             #after the end of the current interval,
66 27 100       40 if ($end->($topSublist->[$#{$topSublist}])
  27         78  
67             > $end->($features[$i]) ) {
68             #then curList is the first (deepest) sublist
69             #that the current feature fits into, and
70             #we add the current feature to curList
71 14         28 push @$curList, $features[$i];
72 14         43 last;
73             } else {
74             #move on to the next shallower sublist
75 13         31 $curList = pop @sublistStack;
76             }
77             }
78             }
79             }
80             }
81              
82 25         66 $self->{maxEnd} = $maxEnd;
83              
84 25         183 return $self;
85             }
86              
87             sub maxEnd {
88 46     46 0 163 return shift->{maxEnd};
89             }
90              
91             sub minStart {
92 22     22 0 51 return shift->{minStart};
93             }
94              
95             sub nestedList {
96 25     25 0 115 return shift->{topList};
97             }
98              
99             1;
100              
101             __END__