File Coverage

blib/lib/Bio/Coordinate/Collection.pm
Criterion Covered Total %
statement 88 110 80.0
branch 28 52 53.8
condition 9 18 50.0
subroutine 15 17 88.2
pod 9 9 100.0
total 149 206 72.3


line stmt bran cond sub pod time code
1             package Bio::Coordinate::Collection;
2             our $AUTHORITY = 'cpan:BIOPERLML';
3             $Bio::Coordinate::Collection::VERSION = '1.007001';
4 2     2   460 use utf8;
  2         3  
  2         9  
5 2     2   51 use strict;
  2         4  
  2         30  
6 2     2   7 use warnings;
  2         2  
  2         45  
7 2     2   8 use Bio::Coordinate::Result;
  2         2  
  2         47  
8 2     2   21 use Bio::Coordinate::Result::Gap;
  2         4  
  2         55  
9 2     2   8 use parent qw(Bio::Root::Root Bio::Coordinate::MapperI);
  2         1  
  2         8  
10              
11             # ABSTRACT: Noncontinuous match between two coordinate sets.
12             # AUTHOR: Heikki Lehvaslaiho
13             # OWNER: Heikki Lehvaslaiho
14             # LICENSE: Perl_5
15              
16             # CONTRIBUTOR: Ewan Birney
17              
18              
19              
20             sub new {
21 35     35 1 403 my($class,@args) = @_;
22 35         73 my $self = $class->SUPER::new(@args);
23              
24 35         215 $self->{'_mappers'} = [];
25              
26 35         100 my($in, $out, $strict, $mappers, $return_match) =
27             $self->_rearrange([qw(IN
28             OUT
29             STRICT
30             MAPPERS
31             RETURN_MATCH
32             )],
33             @args);
34              
35 35 50       163 $in && $self->in($in);
36 35 50       58 $out && $self->out($out);
37 35 50       54 $mappers && $self->mappers($mappers);
38 35 100       61 $return_match && $self->return_match('return_match');
39 35         64 return $self; # success - we hope!
40             }
41              
42              
43             sub add_mapper {
44 199     199 1 386 my ($self,$value) = @_;
45              
46 199 50 33     923 $self->throw("Is not a Bio::Coordinate::MapperI but a [$self]")
47             unless defined $value && $value->isa('Bio::Coordinate::MapperI');
48              
49             # test pair range lengths
50 199 50       414 $self->warn("Coordinates in pair [". $value . ":" .
51             $value->in->seq_id . "/". $value->out->seq_id .
52             "] are not right.")
53             unless $value->test;
54              
55 199         1977 $self->_is_sorted(0);
56 199         161 push(@{$self->{'_mappers'}},$value);
  199         607  
57             }
58              
59              
60             sub mappers{
61 0     0 1 0 my ($self,@args) = @_;
62              
63 0 0       0 if (@args) {
64 0 0 0     0 if (@args == 1 && ref $args[0] eq 'ARRAY') {
65 0         0 @args = @{$args[0]};
  0         0  
66             }
67 0 0 0     0 $self->throw("Is not a Bio::Coordinate::MapperI but a [$self]")
68             unless defined $args[0] && $args[0]->isa('Bio::Coordinate::MapperI');
69 0         0 push(@{$self->{'_mappers'}}, @args);
  0         0  
70             }
71              
72 0         0 return @{$self->{'_mappers'}};
  0         0  
73             }
74              
75              
76             sub each_mapper{
77 72     72 1 77 my ($self) = @_;
78 72         58 return @{$self->{'_mappers'}};
  72         190  
79             }
80              
81              
82             sub mapper_count{
83 1     1 1 2 my $self = shift;
84 1 50       2 return scalar @{$self->{'_mappers'} || []};
  1         6  
85             }
86              
87              
88             sub swap {
89 19     19 1 4195 my ($self) = @_;
90              
91 19 100       31 $self->sort unless $self->_is_sorted;
92 19         20 map {$_->swap;} @{$self->{'_mappers'}};
  140         219  
  19         29  
93             ($self->{'_in_ids'}, $self->{'_out_ids'}) =
94 19         29 ($self->{'_out_ids'}, $self->{'_in_ids'});
95 19         32 1;
96             }
97              
98              
99             sub test {
100 0     0 1 0 my ($self) = @_;
101              
102 0         0 my $res = 1;
103              
104 0         0 foreach my $mapper ($self->each_mapper) {
105 0 0       0 unless( $mapper->test ) {
106 0         0 $self->warn("Coordinates in pair [". $mapper . ":" .
107             $mapper->in->seq_id . "/". $mapper->out->seq_id .
108             "] are not right.");
109 0         0 $res = 0;
110             }
111             }
112 0         0 $res;
113             }
114              
115              
116             sub map {
117 23     23 1 9657 my ($self,$value) = @_;
118              
119 23 50       57 $self->throw("Need to pass me a value.")
120             unless defined $value;
121 23 50       71 $self->throw("I need a Bio::Location, not [$value]")
122             unless $value->isa('Bio::LocationI');
123 23 50       49 $self->throw("No coordinate mappers!")
124             unless $self->each_mapper;
125              
126 23 100       57 $self->sort unless $self->_is_sorted;
127              
128 23 100       91 if ($value->isa("Bio::Location::SplitLocationI")) {
129              
130 3         9 my $result = Bio::Coordinate::Result->new();
131 3         220 foreach my $loc ( $value->sub_Location(1) ) {
132              
133 5         231 my $res = $self->_map($loc);
134 5         10 map { $result->add_sub_Location($_) } $res->each_Location;
  5         77  
135              
136             }
137 3         54 return $result;
138              
139             } else {
140 20         49 return $self->_map($value);
141             }
142              
143             }
144              
145              
146             sub _map {
147 25     25   26 my ($self,$value) = @_;
148              
149 25         116 my $result = Bio::Coordinate::Result->new(-is_remote=>1);
150              
151             IDMATCH: {
152              
153             # bail out now we if are forcing the use of an ID
154             # and it is not in this collection
155 25         2604 last IDMATCH if defined $value->seq_id &&
156 25 50 66     58 ! $self->{'_in_ids'}->{$value->seq_id};
157              
158 25         248 foreach my $pair ($self->each_mapper) {
159              
160             # if we are limiting input to a certain ID
161 167 100 100     1405 next if defined $value->seq_id && $value->seq_id ne $pair->in->seq_id;
162              
163             # if we haven't even reached the start, move on
164 67 100       448 next if $pair->in->end < $value->start;
165             # if we have over run, break
166 49 100       874 last if $pair->in->start > $value->end;
167              
168 36         590 my $subres = $pair->map($value);
169 36         84 $result->add_result($subres);
170             }
171             }
172              
173 25 50       447 $result->seq_id($result->match->seq_id) if $result->match;
174 25 50       155 unless ($result->each_Location) {
175             #build one gap;
176 0         0 my $gap = Bio::Location::Simple->new(-start => $value->start,
177             -end => $value->end,
178             -strand => $value->strand,
179             -location_type => $value->location_type
180             );
181 0 0       0 $gap->seq_id($value->seq_id) if defined $value->seq_id;
182 0         0 bless $gap, 'Bio::Coordinate::Result::Gap';
183 0 0       0 $result->seq_id($value->seq_id) if defined $value->seq_id;
184 0         0 $result->add_sub_Location($gap);
185             }
186 25         519 return $result;
187             }
188              
189              
190             sub sort{
191 17     17 1 17 my ($self) = @_;
192              
193 17         50 @{$self->{'_mappers'}} = map { $_->[0] }
  139         146  
194 132         269 sort { $a->[1] <=> $b->[1] }
195 139         1138 map { [ $_, $_->in->start] }
196 17         33 @{$self->{'_mappers'}};
  17         28  
197              
198             #create hashes for sequence ids
199 17         41 $self->{'_in_ids'} = ();
200 17         22 $self->{'_out_ids'} = ();
201 17         25 foreach ($self->each_mapper) {
202 139         628 $self->{'_in_ids'}->{$_->in->seq_id} = 1;
203 139         607 $self->{'_out_ids'}->{$_->out->seq_id} = 1;
204             }
205              
206 17         81 $self->_is_sorted(1);
207             }
208              
209              
210             sub _is_sorted{
211 258     258   252 my ($self,$value) = @_;
212              
213 258 100 100     847 $self->{'_is_sorted'} = 1 if defined $value && $value;
214 258         334 return $self->{'_is_sorted'};
215             }
216              
217             1;
218              
219             __END__