File Coverage

blib/lib/GenOO/Region.pm
Criterion Covered Total %
statement 71 88 80.6
branch 36 46 78.2
condition 37 53 69.8
subroutine 20 24 83.3
pod 0 20 0.0
total 164 231 71.0


line stmt bran cond sub pod time code
1             # POD documentation - main docs before the code
2              
3             =head1 NAME
4              
5             GenOO::Region - Role that represents a region on a reference sequence
6              
7             =head1 SYNOPSIS
8              
9             This role when consumed requires specific attributes and provides
10             methods that correspond to a region on a reference sequence.
11              
12             =head1 DESCRIPTION
13              
14             A region object is an area on another reference sequence. It has a
15             specific start and stop position on the reference and a specific
16             direction (strand). It has methods that combine the direction with
17             the positional information a give positions for the head or the tail
18             of the region. It also offers methods that calculate distances or
19             overlaps with other object that also consume the role.
20              
21             =head1 EXAMPLES
22              
23             # Get the location information on the reference sequence
24             $obj_with_role->start; # 10
25             $obj_with_role->stop; # 20
26             $obj_with_role->strand; # -1
27            
28             # Get the head position on the reference sequence
29             $obj_with_role->head_position; # 20
30              
31             =cut
32              
33             # Let the code begin...
34              
35             package GenOO::Region;
36             $GenOO::Region::VERSION = '1.4.6';
37              
38             #######################################################################
39             ####################### Load External modules #####################
40             #######################################################################
41 2     2   1319 use Modern::Perl;
  2         4  
  2         15  
42 2     2   265 use Moose::Role;
  2         3  
  2         15  
43              
44              
45             #######################################################################
46             ####################### Required attributes #######################
47             #######################################################################
48             requires qw(strand rname start stop copy_number);
49              
50              
51             #######################################################################
52             ####################### Interface attributes ######################
53             #######################################################################
54             has 'length' => (
55             is => 'ro',
56             builder => '_calculate_length',
57             init_arg => undef,
58             lazy => 1,
59             );
60              
61              
62             #######################################################################
63             ######################## Interface Methods ########################
64             #######################################################################
65             sub location {
66 35     35 0 1244 my ($self) = @_;
67            
68 35         75 return $self->rname . ':' . $self->start . '-' . $self->stop . ':' . $self->strand;
69             }
70              
71             sub strand_symbol {
72 5     5 0 1834 my ($self) = @_;
73            
74 5 100       170 return undef if !defined $self->strand;
75            
76 4 100       94 if ($self->strand == 1) {
    50          
77 3         20 return '+';
78             }
79             elsif ($self->strand == -1) {
80 1         7 return '-';
81             }
82 0         0 return undef;
83             }
84              
85             sub head_position {
86 44     44 0 1187 my ($self) = @_;
87            
88 44 100       1048 if ($self->strand == 1) {
    50          
89 22         518 return $self->start;
90             }
91             elsif ($self->strand == -1) {
92 22         541 return $self->stop;
93             }
94             else {
95 0         0 return undef;
96             }
97             }
98              
99             sub tail_position {
100 36     36 0 1312 my ($self) = @_;
101            
102 36 100       847 if ($self->strand == 1) {
    50          
103 18         413 return $self->stop;
104             }
105             elsif ($self->strand == -1) {
106 18         408 return $self->start;
107             }
108             else {
109 0         0 return undef;
110             }
111             }
112              
113             sub mid_position {
114 33     33 0 1291 my ($self) = @_;
115            
116 33         908 return ($self->start + $self->stop)/2;
117             }
118              
119             sub mid_mid_distance_from {
120 10     10 0 1305 my ($self, $from_locus) = @_;
121            
122 10 100       27 die join(' ', 'Comparing relative position for regions on different reference (rname)',$self->rname,'ne',$from_locus->rname)."\n" if ($self->rname ne $from_locus->rname);
123 8         22 return ($self->mid_position - $from_locus->mid_position) * $self->strand;
124             }
125              
126             sub mid_head_distance_from {
127 10     10 0 1259 my ($self, $from_locus) = @_;
128            
129 10 100       31 die join(' ', 'Comparing relative position for regions on different reference (rname)',$self->rname,'ne',$from_locus->rname)."\n" if ($self->rname ne $from_locus->rname);
130 8         27 return ($self->mid_position - $from_locus->head_position) * $self->strand;
131             }
132              
133             sub mid_tail_distance_from {
134 0     0 0 0 my ($self, $from_locus) = @_;
135            
136 0 0       0 die join(' ', 'Comparing relative position for regions on different reference (rname)',$self->rname,'ne',$from_locus->rname)."\n" if ($self->rname ne $from_locus->rname);
137 0         0 return ($self->mid_position - $from_locus->tail_position) * $self->strand;
138             }
139              
140             sub head_mid_distance_from {
141 0     0 0 0 my ($self, $from_locus) = @_;
142            
143 0 0       0 die join(' ', 'Comparing relative position for regions on different reference (rname)',$self->rname,'ne',$from_locus->rname)."\n" if ($self->rname ne $from_locus->rname);
144 0         0 return ($self->head_position - $from_locus->mid_position) * $self->strand;
145             }
146              
147             sub head_head_distance_from {
148 10     10 0 1316 my ($self, $from_locus) = @_;
149            
150 10 100       32 die join(' ', 'Comparing relative position for regions on different reference (rname)',$self->rname,'ne',$from_locus->rname)."\n" if ($self->rname ne $from_locus->rname);
151 8         33 return ($self->head_position - $from_locus->head_position) * $self->strand;
152             }
153              
154             sub head_tail_distance_from {
155 10     10 0 1254 my ($self, $from_locus) = @_;
156            
157 10 100       42 die join(' ', 'Comparing relative position for regions on different reference (rname)',$self->rname,'ne',$from_locus->rname)."\n" if ($self->rname ne $from_locus->rname);
158 8         21 return ($self->head_position - $from_locus->tail_position) * $self->strand;
159             }
160              
161             sub tail_mid_distance_from {
162 0     0 0 0 my ($self, $from_locus) = @_;
163            
164 0 0       0 die join(' ', 'Comparing relative position for regions on different reference (rname)',$self->rname,'ne',$from_locus->rname)."\n" if ($self->rname ne $from_locus->rname);
165 0         0 return ($self->tail_position - $from_locus->mid_position) * $self->strand;
166             }
167              
168             sub tail_head_distance_from {
169 10     10 0 1397 my ($self, $from_locus) = @_;
170            
171 10 100       31 die join(' ', 'Comparing relative position for regions on different reference (rname)',$self->rname,'ne',$from_locus->rname)."\n" if ($self->rname ne $from_locus->rname);
172 8         21 return ($self->tail_position - $from_locus->head_position) * $self->strand;
173             }
174              
175             sub tail_tail_distance_from {
176 10     10 0 1499 my ($self, $from_locus) = @_;
177            
178 10 100       30 die join(' ', 'Comparing relative position for regions on different reference (rname)',$self->rname,'ne',$from_locus->rname)."\n" if ($self->rname ne $from_locus->rname);
179 8         19 return ($self->tail_position - $from_locus->tail_position) * $self->strand;
180             }
181              
182             sub to_string {
183 2     2 0 1401 my ($self, $params) = @_;
184            
185 2         12 return $self->location;
186             }
187              
188             sub overlaps_with_offset {
189 10     10 0 1192 my ($self, $region2, $use_strand, $offset) = @_;
190            
191 10   100     37 $offset //= 0;
192 10   100     26 $use_strand //= 1;
193            
194 10 100 100     289 if (($use_strand == 0 or $self->strand == $region2->strand) and ($self->rname eq $region2->rname) and (($self->start-$offset) <= $region2->stop) and ($region2->start <= ($self->stop+$offset))) {
      66        
      66        
      66        
195 6         24 return 1; #overlap
196             }
197             else {
198 4         17 return 0; #no overlap
199             }
200             }
201              
202             sub overlaps {
203 46     46 0 1310 my ($self, $region2, $use_strand) = @_;
204            
205 46   100     125 $use_strand //= 1;
206            
207 46 100 100     1300 if (($use_strand == 0 or $self->strand == $region2->strand) and ($self->rname eq $region2->rname) and ($self->start <= $region2->stop) and ($region2->start <= $self->stop)) {
      66        
      66        
      66        
208 33         111 return 1; #overlap
209             }
210             else {
211 13         44 return 0; #no overlap
212             }
213             }
214              
215             sub overlap_length {
216 8     8 0 1247 my ($self, $region2) = @_;
217            
218 8 100       21 if ($self->overlaps($region2)) {
219 4 100       89 my $max_start = $self->start > $region2->start ? $self->start : $region2->start;
220 4 50       85 my $min_stop = $self->stop < $region2->stop ? $self->stop : $region2->stop;
221 4         19 return $min_stop - $max_start + 1 ;
222             }
223             else {
224 4         16 return 0;
225             }
226             }
227              
228             sub contains {
229 12     12 0 1208 my ($self, $region2, $use_strand) = @_;
230            
231 12   50     48 $use_strand //= 1;
232            
233 12 100 66     434 if (($use_strand == 0 or $self->strand == $region2->strand) and ($self->rname eq $region2->rname) and ($self->start <= $region2->start) and ($region2->stop <= $self->stop)) {
      66        
      100        
      66        
234 4         13 return 1;
235             }
236             else {
237 8         32 return 0;
238             }
239             }
240              
241             sub contains_position {
242 214     214 0 1627 my ($self, $position) = @_;
243            
244 214 100 100     5442 if (($self->start <= $position) and ($position <= $self->stop)) {
245 199         803 return 1;
246             }
247             else {
248 15         46 return 0;
249             }
250             }
251              
252             #######################################################################
253             ######################### Private methods ##########################
254             #######################################################################
255             sub _calculate_length {
256 73     73   97 my ($self) = @_;
257            
258 73         1891 return $self->stop - $self->start + 1;
259             }
260              
261             sub _to_string_bed {
262 0     0     my ($self) = @_;
263            
264 0   0       my $strand_symbol = $self->strand_symbol || '.';
265 0   0       my $name = $self->name || '.';
266 0   0       my $score = $self->copy_number || 1;
267            
268 0           return $self->rname."\t".$self->start."\t".($self->stop+1)."\t".$name."\t".$score."\t".$strand_symbol;
269             }
270              
271             1;