Mercurial > repos > mahtabm > ensemb_rep_gvl
comparison variant_effect_predictor/Bio/EnsEMBL/Feature.pm @ 0:2bc9b66ada89 draft default tip
Uploaded
author | mahtabm |
---|---|
date | Thu, 11 Apr 2013 06:29:17 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:2bc9b66ada89 |
---|---|
1 =head1 LICENSE | |
2 | |
3 Copyright (c) 1999-2012 The European Bioinformatics Institute and | |
4 Genome Research Limited. All rights reserved. | |
5 | |
6 This software is distributed under a modified Apache license. | |
7 For license details, please see | |
8 | |
9 http://www.ensembl.org/info/about/code_licence.html | |
10 | |
11 =head1 CONTACT | |
12 | |
13 Please email comments or questions to the public Ensembl | |
14 developers list at <dev@ensembl.org>. | |
15 | |
16 Questions may also be sent to the Ensembl help desk at | |
17 <helpdesk@ensembl.org>. | |
18 | |
19 =cut | |
20 | |
21 =head1 NAME | |
22 | |
23 Bio::EnsEMBL::Feature - Ensembl specific sequence feature. | |
24 | |
25 =head1 SYNOPSIS | |
26 | |
27 my $feat = new Bio::EnsEMBL::Feature( | |
28 -start => 100, | |
29 -end => 220, | |
30 -strand => -1, | |
31 -slice => $slice -analysis => $analysis | |
32 ); | |
33 | |
34 my $start = $feat->start(); | |
35 my $end = $feat->end(); | |
36 my $strand = $feat->strand(); | |
37 | |
38 # Move the feature to the chromosomal coordinate system | |
39 $feature = $feature->transform('chromosome'); | |
40 | |
41 # Move the feature to a different slice (possibly on another coord | |
42 # system) | |
43 $feature = $feature->transfer($new_slice); | |
44 | |
45 # Project the feature onto another coordinate system possibly across | |
46 # boundaries: | |
47 @projection = @{ $feature->project('contig') }; | |
48 | |
49 # Change the start, end, and strand of the feature in place | |
50 $feature->move( $new_start, $new_end, $new_strand ); | |
51 | |
52 =head1 DESCRIPTION | |
53 | |
54 This is the Base feature class from which all Ensembl features inherit. | |
55 It provides a bare minimum functionality that all features require. It | |
56 basically describes a location on a sequence in an arbitrary coordinate | |
57 system. | |
58 | |
59 =head1 METHODS | |
60 | |
61 =cut | |
62 | |
63 | |
64 package Bio::EnsEMBL::Feature; | |
65 | |
66 use strict; | |
67 use warnings; | |
68 | |
69 use Bio::EnsEMBL::Storable; | |
70 use Bio::EnsEMBL::Utils::Argument qw(rearrange); | |
71 use Bio::EnsEMBL::Utils::Exception qw(throw deprecate warning); | |
72 use Bio::EnsEMBL::Utils::Scalar qw(check_ref assert_ref); | |
73 use Bio::EnsEMBL::Slice; | |
74 use Bio::EnsEMBL::StrainSlice; | |
75 use vars qw(@ISA); | |
76 | |
77 use Scalar::Util qw(weaken isweak); | |
78 | |
79 @ISA = qw(Bio::EnsEMBL::Storable); | |
80 | |
81 | |
82 =head2 new | |
83 | |
84 Arg [-SLICE]: Bio::EnsEMBL::SLice - Represents the sequence that this | |
85 feature is on. The coordinates of the created feature are | |
86 relative to the start of the slice. | |
87 Arg [-START]: The start coordinate of this feature relative to the start | |
88 of the slice it is sitting on. Coordinates start at 1 and | |
89 are inclusive. | |
90 Arg [-END] : The end coordinate of this feature relative to the start of | |
91 the slice it is sitting on. Coordinates start at 1 and are | |
92 inclusive. | |
93 Arg [-STRAND]: The orientation of this feature. Valid values are 1,-1,0. | |
94 Arg [-SEQNAME] : A seqname to be used instead of the default name of the | |
95 of the slice. Useful for features that do not have an | |
96 attached slice such as protein features. | |
97 Arg [-dbID] : (optional) internal database id | |
98 Arg [-ADAPTOR]: (optional) Bio::EnsEMBL::DBSQL::BaseAdaptor | |
99 Example : $feature = Bio::EnsEMBL::Feature->new(-start => 1, | |
100 -end => 100, | |
101 -strand => 1, | |
102 -slice => $slice, | |
103 -analysis => $analysis); | |
104 Description: Constructs a new Bio::EnsEMBL::Feature. Generally subclasses | |
105 of this method are instantiated, rather than this class itself. | |
106 Returntype : Bio::EnsEMBL::Feature | |
107 Exceptions : Thrown on invalid -SLICE, -ANALYSIS, -STRAND ,-ADAPTOR arguments | |
108 Caller : general, subclass constructors | |
109 Status : Stable | |
110 | |
111 =cut | |
112 | |
113 | |
114 sub new { | |
115 my $caller = shift; | |
116 | |
117 my $class = ref($caller) || $caller; | |
118 my ( $start, $end, $strand, $slice, $analysis,$seqname, $dbID, $adaptor ) = | |
119 rearrange(['START','END','STRAND','SLICE','ANALYSIS', 'SEQNAME', | |
120 'DBID', 'ADAPTOR'], @_); | |
121 if($slice) { | |
122 if(!ref($slice) || !($slice->isa('Bio::EnsEMBL::Slice') or $slice->isa('Bio::EnsEMBL::LRGSlice')) ) { | |
123 throw('-SLICE argument must be a Bio::EnsEMBL::Slice not '.$slice); | |
124 } | |
125 } | |
126 | |
127 if($analysis) { | |
128 if(!ref($analysis) || !$analysis->isa('Bio::EnsEMBL::Analysis')) { | |
129 throw('-ANALYSIS argument must be a Bio::EnsEMBL::Analysis not '. | |
130 $analysis); | |
131 } | |
132 } | |
133 | |
134 if(defined($strand)) { | |
135 if(!($strand == 1) && !($strand == -1) && !($strand == 0)) { | |
136 throw('-STRAND argument must be 1, -1, or 0'); | |
137 } | |
138 } | |
139 | |
140 if(defined($start) && defined($end)) { | |
141 if (($start =~ /\d+/) && ($end =~ /\d+/)) { | |
142 if($end+1 < $start) { | |
143 throw(sprintf('Start (%d) must be less than or equal to end+1 (%d)', $start, ($end+1))); | |
144 } | |
145 } else { | |
146 throw('Start and end must be integers'); | |
147 } | |
148 } | |
149 | |
150 my $self = bless({'start' => $start, | |
151 'end' => $end, | |
152 'strand' => $strand, | |
153 'slice' => $slice, | |
154 'analysis' => $analysis, | |
155 'seqname' => $seqname, | |
156 'dbID' => $dbID}, $class); | |
157 | |
158 $self->adaptor($adaptor); | |
159 return $self; | |
160 } | |
161 | |
162 | |
163 =head2 new_fast | |
164 | |
165 Arg [1] : hashref to be blessed | |
166 Description: Construct a new Bio::EnsEMBL::Feature using the hashref. | |
167 Exceptions : none | |
168 Returntype : Bio::EnsEMBL::Feature | |
169 Caller : general, subclass constructors | |
170 Status : Stable | |
171 | |
172 =cut | |
173 | |
174 | |
175 sub new_fast { | |
176 my $class = shift; | |
177 my $hashref = shift; | |
178 my $self = bless $hashref, $class; | |
179 weaken($self->{adaptor}) if ( ! isweak($self->{adaptor}) ); | |
180 return $self; | |
181 } | |
182 | |
183 =head2 start | |
184 | |
185 Arg [1] : (optional) int $start | |
186 The start of this feature relative to the start of the slice | |
187 that it is on. | |
188 Example : $start = $feat->start() | |
189 Description: Getter/Setter for the start of this feature relative to the | |
190 start of the slice it is on. Note that negative values, or | |
191 values exceeding the length of the slice are permitted. | |
192 Start must be less than or equal to the end regardless of the | |
193 strand. Coordinate values start at 1 and are inclusive. | |
194 Returntype : int | |
195 Exceptions : none | |
196 Caller : general | |
197 Status : Stable | |
198 | |
199 =cut | |
200 | |
201 sub start { | |
202 my ( $self, $value ) = @_; | |
203 | |
204 if ( defined($value) ) { | |
205 $self->{'start'} = $value; | |
206 } | |
207 | |
208 return $self->{'start'}; | |
209 } | |
210 | |
211 | |
212 | |
213 =head2 end | |
214 | |
215 Arg [1] : (optional) int $end | |
216 Example : $end = $feat->end(); | |
217 Description: Getter/Setter for the end of this feature relative to the | |
218 start of the slice that it is on. Note that negative values, | |
219 of values exceeding the length of the slice are permitted. End | |
220 must be greater than or equal to start regardless of the strand. | |
221 Coordinate values start at 1 and are inclusive. | |
222 Returntype : int | |
223 Exceptions : none | |
224 Caller : general | |
225 Status : Stable | |
226 | |
227 =cut | |
228 | |
229 sub end { | |
230 my ( $self, $value ) = @_; | |
231 | |
232 if ( defined($value) ) { | |
233 $self->{'end'} = $value; | |
234 } | |
235 | |
236 return $self->{'end'}; | |
237 } | |
238 | |
239 | |
240 | |
241 | |
242 =head2 strand | |
243 | |
244 Arg [1] : (optional) int $strand | |
245 Example : $feat->strand(-1); | |
246 Description: Getter/Setter for the strand of this feature relative to the | |
247 slice it is on. 0 is an unknown or non-applicable strand. | |
248 -1 is the reverse (negative) strand and 1 is the forward | |
249 (positive) strand. No other values are permitted. | |
250 Returntype : int | |
251 Exceptions : thrown if an invalid strand argument is passed | |
252 Caller : general | |
253 Status : Stable | |
254 | |
255 =cut | |
256 | |
257 sub strand { | |
258 my ( $self, $strand ) = @_; | |
259 | |
260 if ( defined($strand) ) { | |
261 if ( $strand != 0 && $strand != 1 && $strand != -1 ) { | |
262 throw('strand argument must be 0, -1 or 1'); | |
263 } | |
264 | |
265 $self->{'strand'} = $strand; | |
266 } | |
267 | |
268 return $self->{'strand'}; | |
269 } | |
270 | |
271 =head2 move | |
272 | |
273 Arg [1] : int start | |
274 Arg [2] : int end | |
275 Arg [3] : (optional) int strand | |
276 Example : None | |
277 Description: Sets the start, end and strand in one call rather than in | |
278 3 seperate calls to the start(), end() and strand() methods. | |
279 This is for convenience and for speed when this needs to be | |
280 done within a tight loop. | |
281 Returntype : none | |
282 Exceptions : Thrown is invalid arguments are provided | |
283 Caller : general | |
284 Status : Stable | |
285 | |
286 =cut | |
287 | |
288 sub move { | |
289 my $self = shift; | |
290 | |
291 throw('start and end arguments are required') if(@_ < 2); | |
292 | |
293 my $start = shift; | |
294 my $end = shift; | |
295 my $strand = shift; | |
296 | |
297 if(defined($start) && defined($end) && $end < $start) { | |
298 throw('start must be less than or equal to end'); | |
299 } | |
300 if(defined($strand) && $strand != 0 && $strand != -1 && $strand != 1) { | |
301 throw('strand must be 0, -1 or 1'); | |
302 } | |
303 | |
304 $self->{'start'} = $start; | |
305 $self->{'end'} = $end; | |
306 $self->{'strand'} = $strand if(defined($strand)); | |
307 } | |
308 | |
309 | |
310 | |
311 =head2 length | |
312 | |
313 Arg [1] : none | |
314 Example : $length = $feat->length(); | |
315 Description: Returns the length of this feature | |
316 Returntype : Integer | |
317 Exceptions : Throws if end < start and the feature is not on a | |
318 circular slice | |
319 Caller : general | |
320 Status : Stable | |
321 | |
322 =cut | |
323 | |
324 sub length { | |
325 my ($self) = @_; | |
326 | |
327 if ( $self->{'end'} < $self->{'start'} ) { | |
328 # if circular, we can work out the length of an origin-spanning | |
329 # feature using the size of the underlying region. | |
330 if ( $self->slice() && $self->slice()->is_circular() ) { | |
331 my $len = | |
332 $self->slice()->seq_region_length() - | |
333 ( $self->{'start'} - $self->{'end'} ) + 1; | |
334 return $len; | |
335 } else { | |
336 throw( "Cannot determine length of non-circular feature " | |
337 . "where start > end" ); | |
338 } | |
339 } | |
340 | |
341 return $self->{'end'} - $self->{'start'} + 1; | |
342 } | |
343 | |
344 =head2 analysis | |
345 | |
346 Arg [1] : (optional) Bio::EnsEMBL::Analysis $analysis | |
347 Example : $feature->analysis(new Bio::EnsEMBL::Analysis(...)) | |
348 Description: Getter/Setter for the analysis that is associated with | |
349 this feature. The analysis describes how this feature | |
350 was derived. | |
351 Returntype : Bio::EnsEMBL::Analysis | |
352 Exceptions : thrown if an invalid argument is passed | |
353 Caller : general | |
354 Status : Stable | |
355 | |
356 =cut | |
357 | |
358 sub analysis { | |
359 my $self = shift; | |
360 | |
361 if(@_) { | |
362 my $an = shift; | |
363 if(defined($an) && (!ref($an) || !$an->isa('Bio::EnsEMBL::Analysis'))) { | |
364 throw('analysis argument must be a Bio::EnsEMBL::Analysis'); | |
365 } | |
366 $self->{'analysis'} = $an; | |
367 } | |
368 | |
369 return $self->{'analysis'}; | |
370 } | |
371 | |
372 | |
373 | |
374 =head2 slice | |
375 | |
376 Arg [1] : (optional) Bio::EnsEMBL::Slice $slice | |
377 Example : $seqname = $feature->slice()->name(); | |
378 Description: Getter/Setter for the Slice that is associated with this | |
379 feature. The slice represents the underlying sequence that this | |
380 feature is on. Note that this method call is analagous to the | |
381 old SeqFeature methods contig(), entire_seq(), attach_seq(), | |
382 etc. | |
383 Returntype : Bio::EnsEMBL::Slice | |
384 Exceptions : thrown if an invalid argument is passed | |
385 Caller : general | |
386 Status : Stable | |
387 | |
388 =cut | |
389 | |
390 sub slice { | |
391 my ( $self, $slice ) = @_; | |
392 | |
393 if ( defined($slice) ) { | |
394 if ( !check_ref( $slice, 'Bio::EnsEMBL::Slice' ) | |
395 && !check_ref( $slice, 'Bio::EnsEMBL::LRGSlice' ) ) | |
396 { | |
397 throw('slice argument must be a Bio::EnsEMBL::Slice'); | |
398 } | |
399 | |
400 $self->{'slice'} = $slice; | |
401 } elsif ( @_ > 1 ) { | |
402 delete($self->{'slice'}); | |
403 } | |
404 | |
405 return $self->{'slice'}; | |
406 } | |
407 | |
408 =head2 equals | |
409 | |
410 Arg [1] : Bio::EnsEMBL::Feature object | |
411 Example : if ($featureA->equals($featureB)) { ... } | |
412 Description : Compares two features using various criteria. The | |
413 test for eqality goes through the following list and | |
414 terminates at the first true match: | |
415 | |
416 1. If the two features are the same object, they are | |
417 equal. | |
418 2. If they are of different types (e.g., transcript | |
419 and gene), they are *not* equal. | |
420 3. If they both have dbIDs: if these are the same, | |
421 then they are equal, otherwise not. | |
422 4. If they both have slices and analysis objects: | |
423 if the analysis dbIDs are the same and the | |
424 seq_region_id are the same, along with | |
425 seq_region_start and seq_region_end, then they are | |
426 equal, otherwise not. | |
427 | |
428 If none of the above is able to determine equality, | |
429 undef is returned. | |
430 | |
431 Return type : tri-Boolean (0, 1, undef = "unknown") | |
432 | |
433 Exceptions : Thrown if a non-feature is passed as the argument. | |
434 | |
435 =cut | |
436 | |
437 sub equals { | |
438 my ( $self, $feature ) = @_; | |
439 | |
440 # If the features are the same object, they are equal. | |
441 if ( !defined($feature) ) { return 0 } | |
442 if ( $self eq $feature ) { return 1 } | |
443 | |
444 assert_ref( $feature, 'Bio::EnsEMBL::Feature' ); | |
445 | |
446 # If the features have different types, they are *not* equal. | |
447 if ( ref($self) ne ref($feature) ) { | |
448 return 0; | |
449 } | |
450 | |
451 # If the features has the same dbID, they are equal. | |
452 if ( defined( $self->dbID() ) && defined( $feature->dbID() ) ) { | |
453 if ( $self->dbID() == $feature->dbID() ) { return 1 } | |
454 else { return 0 } | |
455 } | |
456 | |
457 # We now know that one of the features do not have a dbID. | |
458 | |
459 # If the features have the same start, end, strand and seq_region_id, | |
460 # and analysis_id, they are equal. | |
461 if ( | |
462 ( defined( $self->analysis() ) && defined( $feature->analysis() ) ) | |
463 && ( defined( $self->slice() ) && defined( $feature->slice() ) ) ) | |
464 { | |
465 if ( ( $self->start() == $feature->start() ) && | |
466 ( $self->end() == $feature->end() ) && | |
467 ( $self->strand() == $feature->strand() ) && | |
468 ( $self->slice()->get_seq_region_id() == | |
469 $feature->slice()->get_seq_region_id() ) && | |
470 ( $self->analysis()->dbID() == $feature->analysis()->dbID() ) ) | |
471 { | |
472 return 1; | |
473 } | |
474 else { return 0 } | |
475 } | |
476 | |
477 # We now know that one of the features does not have either analysis | |
478 # or slice. | |
479 | |
480 # We don't know if the features are equal. This happens if they are | |
481 # not the same object but are of the same type, and one of them lacks | |
482 # dbID, and if there aren't slice and analysis objects attached to | |
483 # them both. | |
484 return undef; | |
485 } ## end sub equals | |
486 | |
487 | |
488 =head2 transform | |
489 | |
490 Arg [1] : string $coord_system | |
491 The coord system to transform this feature to. | |
492 Arg [2] : string $version (optional) | |
493 The version of the coord system to transform this feature to. | |
494 Example : $feature = $feature->transform('contig'); | |
495 next if(!defined($feature)); | |
496 Description: Returns a copy of this feature, but converted to a different | |
497 coordinate system. The converted feature will be placed on a | |
498 slice which spans an entire sequence region of the new | |
499 coordinate system. If the requested coordinate system is the | |
500 same coordinate system it is simply placed on a slice which | |
501 spans the entire seq_region (as opposed to the original slice | |
502 which may have only partially covered the seq_region). | |
503 | |
504 If a feature spans a boundary in the new coordinate system, | |
505 undef is returned instead. | |
506 | |
507 For example, transforming an exon in contig coordinates to one | |
508 in chromosomal coodinates will place the exon on a slice of an | |
509 entire chromosome. | |
510 Returntype : Bio::EnsEMBL::Feature (or undef) | |
511 Exceptions : thrown if an invalid coordinate system is provided | |
512 warning if Feature is not attached to a slice | |
513 Caller : general, transfer() | |
514 Status : Stable | |
515 | |
516 =cut | |
517 | |
518 sub transform { | |
519 my $self = shift; | |
520 my $cs_name = shift; | |
521 my $cs_version = shift; | |
522 my $to_slice = shift; | |
523 | |
524 # | |
525 # For backwards compatibility check if the arguments are old style args | |
526 # | |
527 if(!$cs_name || ref($cs_name)) { | |
528 deprecate('Calling transform without a coord system name is deprecated.'); | |
529 return $self->_deprecated_transform($cs_name); | |
530 } | |
531 | |
532 my $slice = $self->{'slice'}; | |
533 | |
534 if(!$slice) { | |
535 warning("Feature cannot be transformed without attached slice."); | |
536 return undef; | |
537 } | |
538 | |
539 if(!$slice->adaptor()) { | |
540 warning("Feature cannot be transformed without adaptor on" . | |
541 " attached slice."); | |
542 return undef; | |
543 } | |
544 | |
545 #use db from slice since this feature may not yet be stored in a database | |
546 my $db = $slice->adaptor->db(); | |
547 my $cs = $db->get_CoordSystemAdaptor->fetch_by_name($cs_name, $cs_version); | |
548 my $current_cs = $slice->coord_system(); | |
549 | |
550 if(!$current_cs) { | |
551 warning("Feature cannot be transformed without CoordSystem on " . | |
552 "attached slice."); | |
553 return undef; | |
554 } | |
555 | |
556 if(!$cs) { | |
557 throw("Cannot transform to unknown coordinate system " . | |
558 "[$cs_name $cs_version]\n"); | |
559 } | |
560 | |
561 # if feature is already in the requested coordinate system, we can just | |
562 # return a copy | |
563 if( $cs->equals( $current_cs ) && $slice->start() == 1 && | |
564 $slice->strand() == 1 ) { | |
565 my $new_feature; | |
566 %$new_feature = %$self; | |
567 bless $new_feature, ref $self; | |
568 return $new_feature; | |
569 } | |
570 my $projection; | |
571 if(defined($to_slice)){ | |
572 $projection = $self->project_to_slice( $to_slice ); } | |
573 else{ | |
574 $projection = $self->project( $cs_name, $cs_version ); | |
575 } | |
576 | |
577 if(@$projection == 0){ | |
578 return undef; | |
579 } | |
580 if( @$projection != 1 and !defined($to_slice)) { | |
581 # warn "MORE than one projection and NO slice specified "; | |
582 # warn "from ".$self->slice->name." to $cs_name, $cs_version\n"; | |
583 return undef; | |
584 } | |
585 my $index = 0; | |
586 if(defined($to_slice)){ | |
587 my $found = 0; | |
588 my $i = 0; | |
589 foreach my $proj (@{$projection}) { | |
590 my $slice = $proj->[2]; | |
591 if($to_slice->get_seq_region_id eq $slice->get_seq_region_id){ | |
592 $found =1; | |
593 $index = $i; | |
594 } | |
595 $i++; | |
596 } | |
597 if(!$found){ | |
598 if(@$projection != 1){ | |
599 if(@$projection == 0){ | |
600 warn "number of mappings is ".@$projection."\n"; | |
601 warn "could not project feature ".ref($self)." from ".$self->slice->seq_region_name." to ".$to_slice->seq_region_name."\n"; | |
602 warn "In the region of ".$self->slice->start." <-> ".$self->slice->end."\n"; | |
603 warn "feat start=".($self->slice->start+$self->start)."\tend=".($self->slice->start+$self->end)."\n"; | |
604 } | |
605 else{ | |
606 foreach my $proj (@{$projection}) { | |
607 my $slice = $proj->[2]; | |
608 warn "available slice ".$slice->seq_regon_name."\n"; | |
609 } | |
610 warn "MORE than one projection and none to slice specified (".$to_slice->seq_region_name.")\n"; | |
611 } | |
612 } | |
613 else { | |
614 foreach my $proj (@{$projection}) { | |
615 warn "Mapping is to ".$proj->[2]->seq_region_name."\n"; | |
616 } | |
617 warn "One projection but none to slice specified\n"; | |
618 } | |
619 return undef; | |
620 } | |
621 } | |
622 | |
623 my $p_slice = $projection->[$index]->[2]; | |
624 my $slice_adaptor = $db->get_SliceAdaptor; | |
625 $slice = $slice_adaptor->fetch_by_region($p_slice->coord_system()->name(), | |
626 $p_slice->seq_region_name(), | |
627 undef, #start | |
628 undef, #end | |
629 1, #strand | |
630 $p_slice->coord_system()->version); | |
631 | |
632 my $new_feature; | |
633 %$new_feature = %$self; | |
634 bless $new_feature, ref $self; | |
635 $new_feature->{'start'} = $p_slice->start(); | |
636 $new_feature->{'end'} = $p_slice->end(); | |
637 $new_feature->{'strand'} = | |
638 ($self->{'strand'} == 0) ? 0 : $p_slice->strand(); | |
639 $new_feature->{'slice'} = $slice; | |
640 return $new_feature; | |
641 | |
642 } | |
643 | |
644 | |
645 | |
646 =head2 transfer | |
647 | |
648 Arg [1] : Bio::EnsEMBL::Slice $slice | |
649 The slice to transfer this feature to | |
650 Example : $feature = $feature->transfer($slice); | |
651 next if(!defined($feature)); | |
652 Description: Returns a copy of this feature which has been shifted onto | |
653 another slice. | |
654 | |
655 If the new slice is in a different coordinate system the | |
656 feature is transformed first and then placed on the slice. | |
657 If the feature would be split across a coordinate system | |
658 boundary or mapped to a gap undef is returned instead. | |
659 | |
660 If the feature cannot be placed on the provided slice because | |
661 it maps to an entirely different location, undef is returned | |
662 instead. | |
663 | |
664 Returntype : Bio::EnsEMBL::Feature (or undef) | |
665 Exceptions : throw on incorrect argument | |
666 throw if feature does not have attached slice | |
667 Caller : general, transform() | |
668 Status : Stable | |
669 | |
670 =cut | |
671 | |
672 | |
673 sub transfer { | |
674 my $self = shift; | |
675 my $slice = shift; | |
676 | |
677 if(!$slice || !ref($slice) || (!$slice->isa('Bio::EnsEMBL::Slice') && !$slice->isa('Bio::EnsEMBL::LRGSlice'))) { | |
678 throw('Slice argument is required'); | |
679 } | |
680 | |
681 #make a shallow copy of the feature to be transfered | |
682 my $feature; | |
683 %{$feature} = %{$self}; | |
684 bless $feature, ref($self); | |
685 weaken $feature->{adaptor}; | |
686 | |
687 my $current_slice = $self->{'slice'}; | |
688 | |
689 if(!$current_slice) { | |
690 warning("Feature cannot be transfered without attached slice."); | |
691 return undef; | |
692 } | |
693 | |
694 my $cur_cs = $current_slice->coord_system(); | |
695 my $dest_cs = $slice->coord_system(); | |
696 | |
697 #if we are not in the same coord system a transformation step is needed first | |
698 if(!$dest_cs->equals($cur_cs)) { | |
699 $feature = $feature->transform($dest_cs->name, $dest_cs->version, $slice); | |
700 return undef if(!defined($feature)); | |
701 $current_slice = $feature->{'slice'}; | |
702 } | |
703 | |
704 # feature went to entirely different seq_region | |
705 if($current_slice->seq_region_name() ne $slice->seq_region_name()) { | |
706 return undef; | |
707 } | |
708 | |
709 #if the current feature positions are not relative to the start of the | |
710 #seq region, convert them so they are | |
711 my $cur_slice_start = $current_slice->start(); | |
712 my $cur_slice_strand = $current_slice->strand(); | |
713 if($cur_slice_start != 1 || $cur_slice_strand != 1) { | |
714 my $fstart = $feature->{'start'}; | |
715 my $fend = $feature->{'end'}; | |
716 | |
717 if($cur_slice_strand == 1) { | |
718 $feature->{'start'} = $fstart + $cur_slice_start - 1; | |
719 $feature->{'end'} = $fend + $cur_slice_start - 1; | |
720 } else { | |
721 my $cur_slice_end = $current_slice->end(); | |
722 $feature->{'start'} = $cur_slice_end - $fend + 1; | |
723 $feature->{'end'} = $cur_slice_end - $fstart + 1; | |
724 $feature->{'strand'} *= -1; | |
725 } | |
726 } | |
727 | |
728 my $fstart = $feature->{'start'}; | |
729 my $fend = $feature->{'end'}; | |
730 | |
731 #convert to destination slice coords | |
732 if($slice->strand == 1) { | |
733 $feature->{'start'} = $fstart - $slice->start() + 1; | |
734 $feature->{'end'} = $fend - $slice->start() + 1; | |
735 } else { | |
736 $feature->{'start'} = $slice->end() - $fend + 1; | |
737 $feature->{'end'} = $slice->end() - $fstart + 1; | |
738 $feature->{'strand'} *= -1; | |
739 } | |
740 | |
741 $feature->{'slice'} = $slice; | |
742 | |
743 return $feature; | |
744 } | |
745 | |
746 =head2 project_to_slice | |
747 | |
748 Arg [1] : slice to project to | |
749 | |
750 | |
751 Example : | |
752 my $clone_projection = $feature->project_to_slice($slice); | |
753 | |
754 foreach my $seg (@$clone_projection) { | |
755 my $clone = $seg->to_Slice(); | |
756 print "Features current coords ", $seg->from_start, '-', | |
757 $seg->from_end, " project onto clone coords " . | |
758 $clone->seq_region_name, ':', $clone->start, '-', $clone->end, | |
759 $clone->strand, "\n"; | |
760 } | |
761 Description: Returns the results of 'projecting' this feature onto another | |
762 slice . This is useful to see where a feature | |
763 would lie in a coordinate system in which it | |
764 crosses a boundary. | |
765 | |
766 This method returns a reference to a list of | |
767 Bio::EnsEMBL::ProjectionSegment objects. | |
768 ProjectionSegments are blessed arrays and can also be used as | |
769 triplets [from_start,from_end,to_Slice]. The from_start and | |
770 from_end are the coordinates relative to the feature start. | |
771 For example, if a feature is current 100-200bp on a slice | |
772 then the triplets returned might be: | |
773 [1,50,$slice1], | |
774 [51,101,$slice2] | |
775 | |
776 The to_Slice is a slice spanning the region on the requested | |
777 coordinate system that this feature projected to. | |
778 | |
779 If the feature projects entirely into a gap then a reference to | |
780 an empty list is returned. | |
781 | |
782 Returntype : listref of Bio::EnsEMBL::ProjectionSegments | |
783 which can also be used as [$start,$end,$slice] triplets | |
784 Exceptions : slice does not have an adaptor | |
785 Caller : general | |
786 Status : At Risk | |
787 | |
788 =cut | |
789 | |
790 sub project_to_slice { | |
791 my $self = shift; | |
792 my $to_slice = shift; | |
793 my $slice = $self->{'slice'}; | |
794 | |
795 if(!$slice) { | |
796 warning("Feature cannot be projected without attached slice."); | |
797 return []; | |
798 } | |
799 | |
800 | |
801 #get an adaptor from the attached slice because this feature may not yet | |
802 #be stored and may not have its own adaptor | |
803 my $slice_adaptor = $slice->adaptor(); | |
804 | |
805 if(!$slice_adaptor) { | |
806 throw("Cannot project feature because associated slice does not have an " . | |
807 " adaptor"); | |
808 } | |
809 | |
810 my $strand = $self->strand() * $slice->strand(); | |
811 #fetch by feature always gives back forward strand slice: | |
812 $slice = $slice_adaptor->fetch_by_Feature($self); | |
813 $slice = $slice->invert if($strand == -1); | |
814 return $slice->project_to_slice($to_slice); | |
815 } | |
816 | |
817 | |
818 =head2 project | |
819 | |
820 Arg [1] : string $name | |
821 The name of the coordinate system to project this feature onto | |
822 Arg [2] : string $version (optional) | |
823 The version of the coordinate system (such as 'NCBI34') to | |
824 project this feature onto | |
825 Example : | |
826 my $clone_projection = $feature->project('clone'); | |
827 | |
828 foreach my $seg (@$clone_projection) { | |
829 my $clone = $seg->to_Slice(); | |
830 print "Features current coords ", $seg->from_start, '-', | |
831 $seg->from_end, " project onto clone coords " . | |
832 $clone->seq_region_name, ':', $clone->start, '-', $clone->end, | |
833 $clone->strand, "\n"; | |
834 } | |
835 Description: Returns the results of 'projecting' this feature onto another | |
836 coordinate system. This is useful to see where a feature | |
837 would lie in a coordinate system in which it | |
838 crosses a boundary. | |
839 | |
840 This method returns a reference to a list of | |
841 Bio::EnsEMBL::ProjectionSegment objects. | |
842 ProjectionSegments are blessed arrays and can also be used as | |
843 triplets [from_start,from_end,to_Slice]. The from_start and | |
844 from_end are the coordinates relative to the feature start. | |
845 For example, if a feature is current 100-200bp on a slice | |
846 then the triplets returned might be: | |
847 [1,50,$slice1], | |
848 [51,101,$slice2] | |
849 | |
850 The to_Slice is a slice spanning the region on the requested | |
851 coordinate system that this feature projected to. | |
852 | |
853 If the feature projects entirely into a gap then a reference to | |
854 an empty list is returned. | |
855 | |
856 Returntype : listref of Bio::EnsEMBL::ProjectionSegments | |
857 which can also be used as [$start,$end,$slice] triplets | |
858 Exceptions : slice does not have an adaptor | |
859 Caller : general | |
860 Status : Stable | |
861 | |
862 =cut | |
863 | |
864 sub project { | |
865 my $self = shift; | |
866 my $cs_name = shift; | |
867 my $cs_version = shift; | |
868 | |
869 my $slice = $self->{'slice'}; | |
870 | |
871 if(!$slice) { | |
872 warning("Feature cannot be projected without attached slice."); | |
873 return []; | |
874 } | |
875 | |
876 | |
877 #get an adaptor from the attached slice because this feature may not yet | |
878 #be stored and may not have its own adaptor | |
879 my $slice_adaptor = $slice->adaptor(); | |
880 | |
881 if(!$slice_adaptor) { | |
882 throw("Cannot project feature because associated slice does not have an " . | |
883 " adaptor"); | |
884 } | |
885 | |
886 my $strand = $self->strand() * $slice->strand(); | |
887 #fetch by feature always gives back forward strand slice: | |
888 $slice = $slice_adaptor->fetch_by_Feature($self); | |
889 $slice = $slice->invert if($strand == -1); | |
890 return $slice->project($cs_name, $cs_version); | |
891 } | |
892 | |
893 | |
894 | |
895 =head2 seqname | |
896 | |
897 Arg [1] : (optional) $seqname | |
898 Example : $seqname = $feat->seqname(); | |
899 Description: Getter/Setter for the name of the sequence that this feature | |
900 is on. Normally you can get away with not setting this value | |
901 and it will default to the name of the slice on which this | |
902 feature is on. It is useful to set this value on features which | |
903 do not ordinarily sit on features such as ProteinFeatures which | |
904 sit on peptides. | |
905 Returntype : string | |
906 Exceptions : none | |
907 Caller : general | |
908 Status : Stable | |
909 | |
910 =cut | |
911 | |
912 sub seqname { | |
913 my $self = shift; | |
914 | |
915 if(@_) { | |
916 $self->{'seqname'} = shift; | |
917 } | |
918 | |
919 if(!$self->{'seqname'} && $self->slice()) { | |
920 return $self->slice->name(); | |
921 } | |
922 | |
923 return $self->{'seqname'}; | |
924 } | |
925 | |
926 | |
927 | |
928 | |
929 =head2 display_id | |
930 | |
931 Arg [1] : none | |
932 Example : print $f->display_id(); | |
933 Description: This method returns a string that is considered to be | |
934 the 'display' identifier. It is overridden by subclasses to | |
935 return an appropriate value for objects of that particular | |
936 class. If no appropriate display id is available an empty | |
937 string is returned instead. | |
938 Returntype : string | |
939 Exceptions : none | |
940 Caller : web drawing code | |
941 Status : Stable | |
942 | |
943 =cut | |
944 | |
945 sub display_id { | |
946 my $self = shift; | |
947 return ''; | |
948 } | |
949 | |
950 | |
951 =head2 feature_Slice | |
952 | |
953 Args : none | |
954 Example : $slice = $feature->feature_Slice() | |
955 Description: This is a convenience method to return a slice that covers the | |
956 Area of this feature. The feature start will be at 1 on it, and | |
957 it will have the length of this feature. | |
958 Returntype : Bio::EnsEMBL::Slice or undef if this feature has no attached | |
959 Slice. | |
960 Exceptions : warning if Feature does not have attached slice. | |
961 Caller : web drawing code | |
962 Status : Stable | |
963 | |
964 =cut | |
965 | |
966 sub feature_Slice { | |
967 my $self = shift; | |
968 | |
969 my $slice = $self->slice(); | |
970 | |
971 if(!$slice) { | |
972 warning('Cannot obtain Feature_Slice for feature without attached slice'); | |
973 return undef; | |
974 } | |
975 | |
976 if($slice->isa("Bio::EnsEMBL::StrainSlice")){ | |
977 return Bio::EnsEMBL::StrainSlice->new | |
978 (-seq_region_name => $slice->seq_region_name, | |
979 -seq_region_length => $slice->seq_region_length, | |
980 -coord_system => $slice->coord_system, | |
981 -start => $self->seq_region_start(), | |
982 -end => $self->seq_region_end(), | |
983 -strand => $self->seq_region_strand(), | |
984 -adaptor => $slice->adaptor(), | |
985 -strain_name => $slice->strain_name()); | |
986 } | |
987 else{ | |
988 return Bio::EnsEMBL::Slice->new | |
989 (-seq_region_name => $slice->seq_region_name, | |
990 -seq_region_length => $slice->seq_region_length, | |
991 -coord_system => $slice->coord_system, | |
992 -start => $self->seq_region_start(), | |
993 -end => $self->seq_region_end(), | |
994 -strand => $self->seq_region_strand(), | |
995 -adaptor => $slice->adaptor()); | |
996 } | |
997 } | |
998 | |
999 | |
1000 =head2 seq_region_name | |
1001 | |
1002 Arg [1] : none | |
1003 Example : print $feature->seq_region_name(); | |
1004 Description: Gets the name of the seq_region which this feature is on. | |
1005 Returns undef if this Feature is not on a slice. | |
1006 Returntype : string or undef | |
1007 Exceptions : none | |
1008 Caller : general | |
1009 Status : Stable | |
1010 | |
1011 =cut | |
1012 | |
1013 sub seq_region_name { | |
1014 my $self = shift; | |
1015 my $slice = $self->{'slice'}; | |
1016 | |
1017 return ($slice) ? $slice->seq_region_name() : undef; | |
1018 } | |
1019 | |
1020 | |
1021 =head2 seq_region_length | |
1022 | |
1023 Arg [1] : none | |
1024 Example : print $feature->seq_region_length(); | |
1025 Description: Returns the length of the seq_region which this feature is on | |
1026 Returns undef if this Feature is not on a slice. | |
1027 Returntype : int (unsigned) or undef | |
1028 Exceptions : none | |
1029 Caller : general | |
1030 Status : Stable | |
1031 | |
1032 =cut | |
1033 | |
1034 | |
1035 sub seq_region_length { | |
1036 my $self = shift; | |
1037 my $slice = $self->{'slice'}; | |
1038 | |
1039 return ($slice) ? $slice->seq_region_length() : undef; | |
1040 } | |
1041 | |
1042 | |
1043 =head2 seq_region_strand | |
1044 | |
1045 Arg [1] : none | |
1046 Example : print $feature->seq_region_strand(); | |
1047 Description: Returns the strand of the seq_region which this feature is on | |
1048 (i.e. feature_strand * slice_strand) | |
1049 Returns undef if this Feature is not on a slice. | |
1050 Returntype : 1,0,-1 or undef | |
1051 Exceptions : none | |
1052 Caller : general | |
1053 Status : Stable | |
1054 | |
1055 =cut | |
1056 | |
1057 | |
1058 sub seq_region_strand { | |
1059 my $self = shift; | |
1060 my $slice = $self->{'slice'}; | |
1061 | |
1062 return ($slice) ? $slice->strand() * $self->{'strand'} : undef; | |
1063 } | |
1064 | |
1065 | |
1066 =head2 seq_region_start | |
1067 | |
1068 Arg [1] : none | |
1069 Example : print $feature->seq_region_start(); | |
1070 Description: Convenience method which returns the absolute start of this | |
1071 feature on the seq_region, as opposed to the relative (slice) | |
1072 position. | |
1073 | |
1074 Returns undef if this feature is not on a slice. | |
1075 Returntype : int or undef | |
1076 Exceptions : none | |
1077 Caller : general | |
1078 Status : Stable | |
1079 | |
1080 =cut | |
1081 | |
1082 sub seq_region_start { | |
1083 my ($self) = @_; | |
1084 | |
1085 my $slice = $self->slice(); | |
1086 | |
1087 if ( defined($slice) ) { | |
1088 my $start; | |
1089 | |
1090 if ( $slice->strand() == 1 ) { | |
1091 if ( defined( $self->start() ) ) { | |
1092 if ($self->start < 0 && $slice->is_circular) { | |
1093 $start = $slice->seq_region_length + $self->start; | |
1094 } else { | |
1095 $start = $slice->start() + $self->start() - 1; | |
1096 } | |
1097 } | |
1098 } else { | |
1099 if ( defined( $self->end() ) ) { | |
1100 $start = $slice->end() - $self->end() + 1; | |
1101 } | |
1102 } | |
1103 | |
1104 if ( defined($start) | |
1105 && $slice->is_circular() | |
1106 && $start > $slice->seq_region_length() ) | |
1107 { | |
1108 $start -= $slice->seq_region_length(); | |
1109 } | |
1110 | |
1111 return $start; | |
1112 } | |
1113 | |
1114 return undef; | |
1115 } ## end sub seq_region_start | |
1116 | |
1117 | |
1118 =head2 seq_region_end | |
1119 | |
1120 Arg [1] : none | |
1121 Example : print $feature->seq_region_end(); | |
1122 Description: Convenience method which returns the absolute end of this | |
1123 feature on the seq_region, as opposed to the relative (slice) | |
1124 position. | |
1125 | |
1126 Returns undef if this feature is not on a slice. | |
1127 Returntype : int or undef | |
1128 Exceptions : none | |
1129 Caller : general | |
1130 Status : Stable | |
1131 | |
1132 =cut | |
1133 | |
1134 sub seq_region_end { | |
1135 my ($self) = @_; | |
1136 | |
1137 my $slice = $self->slice(); | |
1138 | |
1139 if ( defined($slice) ) { | |
1140 my $end; | |
1141 | |
1142 if ( $slice->strand() == 1 ) { | |
1143 if ( defined( $self->end() ) ) { | |
1144 $end = $slice->start() + $self->end() - 1; | |
1145 } | |
1146 } else { | |
1147 if ( defined( $self->start() ) ) { | |
1148 $end = $slice->end() - $self->start() + 1; | |
1149 } | |
1150 } | |
1151 | |
1152 if ( defined($end) | |
1153 && $slice->is_circular() | |
1154 && $end > $slice->seq_region_length() ) | |
1155 { | |
1156 $end -= $slice->seq_region_length(); | |
1157 } | |
1158 | |
1159 return $end; | |
1160 } | |
1161 | |
1162 return undef; | |
1163 } ## end sub seq_region_end | |
1164 | |
1165 | |
1166 =head2 coord_system_name | |
1167 | |
1168 Arg [1] : none | |
1169 Example : print $feature->coord_system_name() | |
1170 Description: Gets the name of the coord_system which this feature is on. | |
1171 Returns undef if this Feature is not on a slice. | |
1172 Returntype : string or undef | |
1173 Exceptions : none | |
1174 Caller : general | |
1175 Status : Stable | |
1176 | |
1177 =cut | |
1178 | |
1179 sub coord_system_name { | |
1180 my $self = shift; | |
1181 my $slice = $self->{'slice'}; | |
1182 return ($slice) ? $slice->coord_system_name() : undef; | |
1183 } | |
1184 | |
1185 | |
1186 =head2 seq | |
1187 | |
1188 Args : none | |
1189 Example : my $dna_sequence = $simple_feature->seq(); | |
1190 Description: Returns the dna sequence from the attached slice and | |
1191 attached database that overlaps with this feature. | |
1192 Returns undef if there is no slice or no database. | |
1193 Returns undef if this feature is unstranded (i.e. strand=0). | |
1194 Returntype : undef or string | |
1195 Exceptions : warning if this feature is not stranded | |
1196 Caller : general | |
1197 Status : Stable | |
1198 | |
1199 =cut | |
1200 | |
1201 | |
1202 sub seq { | |
1203 my $self = shift; | |
1204 | |
1205 if( ! defined $self->{'slice'} ) { | |
1206 return undef; | |
1207 } | |
1208 | |
1209 if(!$self->strand()) { | |
1210 warning("Cannot retrieve sequence for unstranded feature."); | |
1211 return undef; | |
1212 } | |
1213 | |
1214 return $self->{'slice'}->subseq($self->start(), $self->end(), | |
1215 $self->strand()); | |
1216 | |
1217 } | |
1218 | |
1219 | |
1220 | |
1221 | |
1222 =head2 get_all_alt_locations | |
1223 | |
1224 Arg [1] : none | |
1225 Example : @features = @{$feature->get_all_alt_locations()}; | |
1226 foreach $f (@features) { | |
1227 print $f->slice->seq_region_name,' ',$f->start, $f->end,"\n"; | |
1228 } | |
1229 | |
1230 Description: Retrieves shallow copies of this feature in its alternate | |
1231 locations. A feature can be considered to have multiple | |
1232 locations when it sits on a alternative structural haplotype | |
1233 or when it is on a pseudo autosomal region. Most features will | |
1234 just return a reference to an empty list though. | |
1235 The features returned by this method will be on a slice which | |
1236 covers the entire alternate region. | |
1237 | |
1238 Currently this method does not take into account alternate | |
1239 locations on the alternate locations (e.g. a reference | |
1240 sequence may have multiple alternate haplotypes. Asking | |
1241 for alternate locations of a feature on one of the alternate | |
1242 haplotypes will give you back the reference location, but not | |
1243 locations on the other alternate haplotypes). | |
1244 | |
1245 Returntype : listref of features of the same type of this feature. | |
1246 Exceptions : none | |
1247 Caller : general | |
1248 Status : Stable | |
1249 | |
1250 =cut | |
1251 | |
1252 sub get_all_alt_locations { | |
1253 my $self = shift; | |
1254 my $return_all = shift || 0; | |
1255 | |
1256 my $slice = $self->{'slice'} or return []; | |
1257 my $sa = $slice->adaptor() or return []; | |
1258 | |
1259 # get slice of entire region | |
1260 $slice = $sa->fetch_by_seq_region_id($slice->get_seq_region_id); | |
1261 | |
1262 my $axfa = $sa->db->get_AssemblyExceptionFeatureAdaptor(); | |
1263 my $axfs = $axfa->fetch_all_by_Slice($slice); | |
1264 | |
1265 my (@haps, @alt); | |
1266 | |
1267 foreach my $axf (@$axfs) { | |
1268 if(uc($axf->type()) eq 'HAP') { | |
1269 push @haps, $axf; | |
1270 } elsif(uc($axf->type()) =~ 'PAR') { | |
1271 push @alt, $axf; | |
1272 } elsif( $axf->type() eq "PATCH_FIX"){ | |
1273 push @haps, $axf; | |
1274 } elsif( $axf->type() eq "PATCH_FIX REF"){ | |
1275 push @haps, $axf if $return_all > 0 ; | |
1276 } elsif( $axf->type() eq "HAP REF" ) { | |
1277 push @haps, $axf if $return_all > 0 ; | |
1278 # do nothing when you are on REF | |
1279 } elsif( $axf->type() eq "PATCH_NOVEL"){ | |
1280 push @haps, $axf; | |
1281 }elsif( $axf->type() eq "PATCH_NOVEL REF"){ | |
1282 push @haps, $axf if $return_all > 0 ; | |
1283 } else { | |
1284 warning("Unknown exception feature type ". $axf->type()."- ignoring."); | |
1285 } | |
1286 } | |
1287 | |
1288 # regions surrounding hap are those of interest, not hap itself | |
1289 # convert hap alt. exc. features to regions around haps instead | |
1290 foreach my $h (@haps) { | |
1291 my $haslice = $h->alternate_slice(); | |
1292 my $hacs = $haslice->coord_system(); | |
1293 | |
1294 if($h->start() > 1 && $haslice->start() > 1) { | |
1295 my $aslice = $sa->fetch_by_region($hacs->name(), | |
1296 $haslice->seq_region_name(), | |
1297 1, | |
1298 $haslice->start()-1, | |
1299 $haslice->strand(), | |
1300 $hacs->version()); | |
1301 | |
1302 push @alt, Bio::EnsEMBL::AssemblyExceptionFeature->new | |
1303 (-start => 1, | |
1304 -end => $h->start()-1, | |
1305 -alternate_slice => $aslice); | |
1306 } | |
1307 | |
1308 if($h->end() < $slice->seq_region_length() && | |
1309 $haslice->end < $haslice->seq_region_length()) { | |
1310 my $aslice = $sa->fetch_by_region($hacs->name(), | |
1311 $haslice->seq_region_name(), | |
1312 $haslice->end()+1, | |
1313 $haslice->seq_region_length(), | |
1314 $haslice->strand(), | |
1315 $hacs->version()); | |
1316 | |
1317 push @alt, Bio::EnsEMBL::AssemblyExceptionFeature->new | |
1318 (-start => $h->end() + 1, | |
1319 -end => $slice->seq_region_length(), | |
1320 -alternate_slice => $aslice); | |
1321 } | |
1322 } | |
1323 | |
1324 | |
1325 # check if exception regions contain our feature | |
1326 | |
1327 my @features; | |
1328 | |
1329 foreach my $axf (@alt) { | |
1330 # ignore other region if feature is not entirely on it | |
1331 next if($self->seq_region_start() < $axf->start() || | |
1332 $self->seq_region_end() > $axf->end()); | |
1333 | |
1334 # quick shallow copy of the feature | |
1335 my $f; | |
1336 %$f = %$self; | |
1337 bless $f, ref($self); | |
1338 | |
1339 my $aslice = $axf->alternate_slice(); | |
1340 | |
1341 # position feature on entire slice of other region | |
1342 $f->{'start'} = $f->seq_region_start() - $axf->start() + $aslice->start(); | |
1343 $f->{'end'} = $f->seq_region_end() - $axf->start() + $aslice->start(); | |
1344 $f->{'strand'} *= $aslice->strand(); | |
1345 | |
1346 $f->{'slice'} = $sa->fetch_by_seq_region_id($aslice->get_seq_region_id()); | |
1347 | |
1348 push @features, $f; | |
1349 } | |
1350 | |
1351 return \@features; | |
1352 } | |
1353 | |
1354 | |
1355 =head2 overlaps | |
1356 | |
1357 Arg [1] : Bio::EnsEMBL::Feature $f | |
1358 The other feature you want to check overlap with this feature | |
1359 for. | |
1360 Description: This method does a range comparison of this features start and | |
1361 end and compares it with another features start and end. It will | |
1362 return true if these ranges overlap and the features are on the | |
1363 same seq_region. | |
1364 Returntype : TRUE if features overlap, FALSE if they don't | |
1365 Exceptions : warning if features are on different seq_regions | |
1366 Caller : general | |
1367 Status : Stable | |
1368 | |
1369 =cut | |
1370 | |
1371 sub overlaps { | |
1372 my $self = shift; | |
1373 my $f = shift; | |
1374 | |
1375 my $sr1_name = $self->seq_region_name; | |
1376 my $sr2_name = $f->seq_region_name; | |
1377 | |
1378 if ($sr1_name and $sr2_name and ($sr1_name ne $sr2_name)) { | |
1379 warning("Bio::EnsEMBL::Feature->overlaps(): features are on different seq regions."); | |
1380 return undef; | |
1381 } | |
1382 | |
1383 return ($self->seq_region_end >= $f->seq_region_start and $self->seq_region_start <= $f->seq_region_end); | |
1384 } | |
1385 | |
1386 | |
1387 =head2 get_overlapping_Genes | |
1388 | |
1389 Description: Get all the genes that overlap this feature. | |
1390 Returntype : list ref of Bio::EnsEMBL::Gene | |
1391 Caller : general | |
1392 Status : UnStable | |
1393 | |
1394 =cut | |
1395 | |
1396 sub get_overlapping_Genes{ | |
1397 my $self = shift; | |
1398 | |
1399 my $slice = $self->feature_Slice; | |
1400 return $slice->get_all_Genes(); | |
1401 } | |
1402 | |
1403 # query for absolute nearest. | |
1404 # select x.display_label, g.gene_id, g.seq_region_start, ABS(cast((32921638 - g.seq_region_end) as signed)) as 'dist' from gene g, xref x where g.display_xref_id = x.xref_id and seq_region_id = 27513 order by ABS(cast((32921638 - g.seq_region_end) as signed)) limit 10; | |
1405 | |
1406 =head2 get_nearest_Gene | |
1407 | |
1408 Description: Get all the nearest gene to the feature | |
1409 Returntype : Bio::EnsEMBL::Gene | |
1410 Caller : general | |
1411 Status : UnStable | |
1412 | |
1413 =cut | |
1414 | |
1415 sub get_nearest_Gene { | |
1416 my $self = shift; | |
1417 my $stranded = shift; | |
1418 my $stream = shift; | |
1419 | |
1420 my $ga = Bio::EnsEMBL::Registry->get_adaptor($self->adaptor->db->species,"core","Gene"); | |
1421 | |
1422 return $ga->fetch_nearest_Gene_by_Feature($self, $stranded, $stream); | |
1423 | |
1424 } | |
1425 | |
1426 =head2 summary_as_hash | |
1427 | |
1428 Example : $feature_summary = $feature->summary_as_hash(); | |
1429 Description : Retrieves a textual summary of this Feature. | |
1430 Should be overidden by subclasses for specific tweaking | |
1431 Returns : hashref of arrays of descriptive strings | |
1432 Status : Intended for internal use | |
1433 =cut | |
1434 | |
1435 sub summary_as_hash { | |
1436 my $self = shift; | |
1437 my %summary; | |
1438 $summary{'ID'} = $self->display_id; | |
1439 $summary{'start'} = $self->seq_region_start; | |
1440 $summary{'end'} = $self->seq_region_end; | |
1441 $summary{'strand'} = $self->strand; | |
1442 $summary{'seq_region_name'} = $self->seq_region_name; | |
1443 return \%summary; | |
1444 } | |
1445 | |
1446 =head2 species | |
1447 | |
1448 Example : $feature->species(); | |
1449 Description : Shortcut to the feature's DBAdaptor and returns its species name | |
1450 Returntype : String the species name | |
1451 Exceptions : Thrown if there is no attached adaptor | |
1452 Caller : Webcode | |
1453 | |
1454 =cut | |
1455 | |
1456 sub species { | |
1457 my ($self) = @_; | |
1458 throw "Can only call this method if you have attached an adaptor" if ! $self->adaptor(); | |
1459 return $self->adaptor()->db()->species(); | |
1460 } | |
1461 | |
1462 | |
1463 ############################################## | |
1464 # Methods included for backwards compatibility | |
1465 ############################################## | |
1466 | |
1467 | |
1468 =head2 contig | |
1469 | |
1470 This method is deprecated and included for backwards compatibility only. | |
1471 Use slice() instead | |
1472 =cut | |
1473 sub contig { | |
1474 deprecate('Use slice() instead'); | |
1475 slice(@_); | |
1476 } | |
1477 | |
1478 | |
1479 | |
1480 =head2 sub_SeqFeature | |
1481 | |
1482 This method is deprecated and only for genebuild backwards compatibility. | |
1483 Avoid using it if possible | |
1484 =cut | |
1485 sub sub_SeqFeature{ | |
1486 my ($self) = @_; | |
1487 return @{$self->{'_gsf_sub_array'}} if($self->{'_gsf_sub_array'}); | |
1488 } | |
1489 | |
1490 =head2 add_sub_SeqFeature | |
1491 | |
1492 This method is deprecated and only for genebuild backwards compatibility. | |
1493 Avoid using it if possible | |
1494 =cut | |
1495 sub add_sub_SeqFeature{ | |
1496 my ($self,$feat,$expand) = @_; | |
1497 my ($p, $f, $l) = caller; | |
1498 if( $expand eq 'EXPAND' ) { | |
1499 # if this doesn't have start/end set - forget it! | |
1500 if( ! $self->start && ! $self->end ) { | |
1501 | |
1502 $self->start($feat->start()); | |
1503 $self->end($feat->end()); | |
1504 $self->strand($feat->strand); | |
1505 } else { | |
1506 if( $feat->start < $self->start ) { | |
1507 $self->start($feat->start); | |
1508 } | |
1509 | |
1510 if( $feat->end > $self->end ) { | |
1511 $self->end($feat->end); | |
1512 } | |
1513 } | |
1514 } else { | |
1515 if($self->start > $feat->start || $self->end < $feat->end) { | |
1516 throw("$feat is not contained within parent feature, " . | |
1517 "and expansion is not valid"); | |
1518 } | |
1519 } | |
1520 | |
1521 push(@{$self->{'_gsf_sub_array'}},$feat); | |
1522 } | |
1523 | |
1524 =head2 flush_sub_SeqFeature | |
1525 | |
1526 This method is deprecated and only for genebuild backwards compatibility. | |
1527 Avoid using it isf possible | |
1528 =cut | |
1529 sub flush_sub_SeqFeature { | |
1530 my ($self) = @_; | |
1531 $self->{'_gsf_sub_array'} = []; | |
1532 } | |
1533 | |
1534 | |
1535 sub _deprecated_transform { | |
1536 my $self = shift; | |
1537 my $arg = shift; | |
1538 | |
1539 if(!$arg) { | |
1540 warning("Calling transform() with no arguments is deprecated.\n". | |
1541 "A coordinate system name argument should be used instead.\n". | |
1542 "You probably wanted transform('seqlevel') or transform('contig')."); | |
1543 return $self->transform('seqlevel'); | |
1544 } | |
1545 | |
1546 if(ref($arg) eq 'Bio::EnsEMBL::Slice') { | |
1547 if($arg->{'empty'}) { | |
1548 warning("Calling transform with an empty slice is deprecated.\n" . | |
1549 "A coordinate system name argument should be used instead.\n". | |
1550 "You probably wanted transform('chromosome') or " . | |
1551 "transform('toplevel')"); | |
1552 return $self->transform('toplevel'); | |
1553 } | |
1554 warning("Calling transform with a slice is deprecated.\n" . | |
1555 "Use the transfer method instead"); | |
1556 return $self->transfer($arg); | |
1557 } | |
1558 | |
1559 warning("Calling transform with a [".ref($arg)."] arg is no longer " . | |
1560 "(or never was) supported. Doing nothing instead."); | |
1561 | |
1562 return $self; | |
1563 } | |
1564 | |
1565 | |
1566 =head2 id | |
1567 | |
1568 This method is deprecated and only included for backwards compatibility. | |
1569 Use display_id, hseqname, dbID or stable_id instead | |
1570 | |
1571 =cut | |
1572 | |
1573 sub id { | |
1574 my $self = shift; | |
1575 deprecate("id method is not used - use display_id instead"); | |
1576 return $self->{'stable_id'} if($self->{'stable_id'}); | |
1577 return $self->{'hseqname'} if($self->{'hseqname'}); | |
1578 return $self->{'seqname'} if($self->{'seqname'}); | |
1579 return $self->{'dbID'}; | |
1580 } | |
1581 | |
1582 1; |