File Coverage

blib/lib/Bio/Coordinate/Pair.pm
Criterion Covered Total %
statement 151 152 99.3
branch 40 54 74.0
condition 21 28 75.0
subroutine 15 15 100.0
pod 7 7 100.0
total 234 256 91.4


line stmt bran cond sub pod time code
1             package Bio::Coordinate::Pair;
2             our $AUTHORITY = 'cpan:BIOPERLML';
3             $Bio::Coordinate::Pair::VERSION = '1.007001';
4 3     3   471895 use utf8;
  3         28  
  3         14  
5 3     3   84 use strict;
  3         5  
  3         52  
6 3     3   13 use warnings;
  3         4  
  3         77  
7 3     3   1206 use Bio::Coordinate::Result;
  3         6  
  3         96  
8 3     3   1273 use Bio::Coordinate::Result::Match;
  3         7  
  3         88  
9 3     3   1245 use Bio::Coordinate::Result::Gap;
  3         7  
  3         92  
10 3     3   12 use parent qw(Bio::Root::Root Bio::Coordinate::MapperI);
  3         3  
  3         11  
11              
12             # ABSTRACT: Continuous match between two coordinate sets.
13             # AUTHOR: Heikki Lehvaslaiho
14             # OWNER: Heikki Lehvaslaiho
15             # LICENSE: Perl_5
16              
17              
18              
19             sub new {
20 245     245 1 55902 my($class,@args) = @_;
21 245         636 my $self = $class->SUPER::new(@args);
22              
23 245         4092 my($in, $out) =
24             $self->_rearrange([qw(IN
25             OUT
26             )],
27             @args);
28              
29 245 50       4115 $in && $self->in($in);
30 245 50       566 $out && $self->out($out);
31 245         599 return $self; # success - we hope!
32             }
33              
34              
35             sub in {
36 2182     2182 1 10773 my ($self,$value) = @_;
37 2182 100       3214 if( defined $value) {
38 245 50       677 $self->throw("Not a valid input Bio::Location [$value] ")
39             unless $value->isa('Bio::LocationI');
40 245         292 $self->{'_in'} = $value;
41             }
42 2182         3974 return $self->{'_in'};
43             }
44              
45              
46             sub out {
47 2362     2362 1 17167 my ($self,$value) = @_;
48 2362 100       3488 if( defined $value) {
49 245 50       544 $self->throw("Not a valid output coordinate Bio::Location [$value] ")
50             unless $value->isa('Bio::LocationI');
51 245         275 $self->{'_out'} = $value;
52             }
53 2362         4422 return $self->{'_out'};
54             }
55              
56              
57             sub swap {
58 147     147 1 678 my ($self) = @_;
59 147         210 ($self->{'_in'}, $self->{'_out'}) = ($self->{'_out'}, $self->{'_in'});
60 147         214 return 1;
61             }
62              
63              
64             sub strand {
65 220     220 1 1220 my ($self) = @_;
66 220 50       313 $self->warn("Outgoing coordinates are not defined")
67             unless $self->out;
68 220 50       311 $self->warn("Incoming coordinates are not defined")
69             unless $self->in;
70              
71 220   100     316 return ($self->in->strand || 0) * ($self->out->strand || 0);
      100        
72             }
73              
74              
75             sub test {
76 208     208 1 1264 my ($self) = @_;
77 208 50       299 $self->warn("Outgoing coordinates are not defined")
78             unless $self->out;
79 208 50       310 $self->warn("Incoming coordinates are not defined")
80             unless $self->in;
81 208         294 return ($self->in->end - $self->in->start) == ($self->out->end - $self->out->start);
82             }
83              
84              
85             sub map {
86 73     73 1 22855 my ($self,$value) = @_;
87              
88 73 50       170 $self->throw("Need to pass me a value.")
89             unless defined $value;
90 73 50       232 $self->throw("I need a Bio::Location, not [$value]")
91             unless $value->isa('Bio::LocationI');
92 73 50       117 $self->throw("Input coordinate system not set")
93             unless $self->in;
94 73 50       122 $self->throw("Output coordinate system not set")
95             unless $self->out;
96              
97 73 100       273 if ($value->isa("Bio::Location::SplitLocationI")) {
98              
99 2         7 my $result = Bio::Coordinate::Result->new();
100 2         221 foreach my $loc ( $value->sub_Location(1) ) {
101 4         225 my $res = $self->_map($loc);
102 4         11 map { $result->add_sub_Location($_) } $res->each_Location;
  4         75  
103             }
104 2         42 return $result;
105             } else {
106 71         135 return $self->_map($value);
107             }
108             }
109              
110              
111             sub _map {
112 75     75   87 my ($self,$value) = @_;
113              
114 75         214 my $result = Bio::Coordinate::Result->new();
115              
116 75         6001 my $offset = $self->in->start - $self->out->start;
117 75         686 my $start = $value->start - $offset;
118 75         705 my $end = $value->end - $offset;
119              
120 75         753 my $match = Bio::Location::Simple->new;
121 75         2187 $match->location_type($value->location_type);
122 75         987 $match->strand($self->strand);
123              
124             #within
125             # |-------------------------|
126             # |-|
127 75 100 100     1072 if ($start >= $self->out->start and $end <= $self->out->end) {
    100 100        
    100 33        
    100 66        
    50 66        
      100        
      66        
      33        
128              
129 29         356 $match->seq_id($self->out->seq_id);
130 29         218 $result->seq_id($self->out->seq_id);
131              
132 29 100       58 if ($self->strand >= 0) {
133 19         139 $match->start($start);
134 19         117 $match->end($end);
135             } else {
136 10         69 $match->start($self->out->end - $end + $self->out->start);
137 10         137 $match->end($self->out->end - $start + $self->out->start);
138             }
139 29 100       398 if ($value->strand) {
140 27         164 $match->strand($match->strand * $value->strand);
141 27         370 $result->strand($match->strand);
142             }
143 29         525 bless $match, 'Bio::Coordinate::Result::Match';
144 29         86 $result->add_sub_Location($match);
145             }
146             #out
147             # |-------------------------|
148             # |-| or |-|
149             elsif ( ($end < $self->out->start or $start > $self->out->end ) or
150             #insertions just outside the range need special settings
151             ($value->location_type eq 'IN-BETWEEN' and
152             ($end = $self->out->start or $start = $self->out->end))) {
153              
154 6         66 $match->seq_id($self->in->seq_id);
155 6         44 $result->seq_id($self->in->seq_id);
156 6         16 $match->start($value->start);
157 6         92 $match->end($value->end);
158 6         131 $match->strand($value->strand);
159              
160 6         59 bless $match, 'Bio::Coordinate::Result::Gap';
161 6         17 $result->add_sub_Location($match);
162             }
163             #partial I
164             # |-------------------------|
165             # |-----|
166             elsif ($start < $self->out->start and $end <= $self->out->end ) {
167              
168 13         143 $result->seq_id($self->out->seq_id);
169 13 100       32 if ($value->strand) {
170 10         71 $match->strand($match->strand * $value->strand);
171 10         142 $result->strand($match->strand);
172             }
173 13         199 my $gap = Bio::Location::Simple->new;
174 13         361 $gap->start($value->start);
175 13         170 $gap->end($self->in->start - 1);
176 13         269 $gap->strand($value->strand);
177 13         129 $gap->seq_id($self->in->seq_id);
178              
179 13         97 bless $gap, 'Bio::Coordinate::Result::Gap';
180 13         35 $result->add_sub_Location($gap);
181              
182             # match
183 13         134 $match->seq_id($self->out->seq_id);
184              
185 13 100       93 if ($self->strand >= 0) {
186 12         84 $match->start($self->out->start);
187 12         153 $match->end($end);
188             } else {
189 1         8 $match->start($self->out->end - $end + $self->out->start);
190 1         14 $match->end($self->out->end);
191             }
192 13         135 bless $match, 'Bio::Coordinate::Result::Match';
193 13         37 $result->add_sub_Location($match);
194             }
195             #partial II
196             # |-------------------------|
197             # |------|
198             elsif ($start >= $self->out->start and $end > $self->out->end ) {
199              
200 21         243 $match->seq_id($self->out->seq_id);
201 21         158 $result->seq_id($self->out->seq_id);
202 21 100       50 if ($value->strand) {
203 18         110 $match->strand($match->strand * $value->strand);
204 18         243 $result->strand($match->strand);
205             }
206 21 100       346 if ($self->strand >= 0) {
207 15         110 $match->start($start);
208 15         88 $match->end($self->out->end);
209             } else {
210 6         45 $match->start($self->out->start);
211 6         84 $match->end($self->out->end - $start + $self->out->start);
212             }
213 21         373 bless $match, 'Bio::Coordinate::Result::Match';
214 21         60 $result->add_sub_Location($match);
215              
216 21         271 my $gap = Bio::Location::Simple->new;
217 21         627 $gap->start($self->in->end + 1);
218 21         356 $gap->end($value->end);
219 21         431 $gap->strand($value->strand);
220 21         221 $gap->seq_id($self->in->seq_id);
221 21         151 bless $gap, 'Bio::Coordinate::Result::Gap';
222 21         52 $result->add_sub_Location($gap);
223              
224             }
225             #enveloping
226             # |-------------------------|
227             # |---------------------------------|
228             elsif ($start < $self->out->start and $end > $self->out->end ) {
229              
230 6         69 $result->seq_id($self->out->seq_id);
231 6 50       20 if ($value->strand) {
232 6         39 $match->strand($match->strand * $value->strand);
233 6         89 $result->strand($match->strand);
234             }
235             # gap1
236 6         106 my $gap1 = Bio::Location::Simple->new;
237 6         174 $gap1->start($value->start);
238 6         79 $gap1->end($self->in->start - 1);
239 6         133 $gap1->strand($value->strand);
240 6         73 $gap1->seq_id($self->in->seq_id);
241 6         50 bless $gap1, 'Bio::Coordinate::Result::Gap';
242 6         22 $result->add_sub_Location($gap1);
243              
244             # match
245 6         70 $match->seq_id($self->out->seq_id);
246              
247 6         46 $match->start($self->out->start);
248 6         77 $match->end($self->out->end);
249 6         110 bless $match, 'Bio::Coordinate::Result::Match';
250 6         16 $result->add_sub_Location($match);
251              
252             # gap2
253 6         57 my $gap2 = Bio::Location::Simple->new;
254 6         165 $gap2->start($self->in->end + 1);
255 6         92 $gap2->end($value->end);
256 6         124 $gap2->strand($value->strand);
257 6         64 $gap2->seq_id($self->in->seq_id);
258 6         45 bless $gap2, 'Bio::Coordinate::Result::Gap';
259 6         23 $result->add_sub_Location($gap2);
260              
261             } else {
262 0         0 $self->throw("Should not be here!");
263             }
264 75         938 return $result;
265             }
266              
267             1;
268              
269             __END__