comparison variant_effect_predictor/Bio/EnsEMBL/Variation/BaseVariationFeatureOverlap.pm @ 0:21066c0abaf5 draft

Uploaded
author willmclaren
date Fri, 03 Aug 2012 10:04:48 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:21066c0abaf5
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::Variation::BaseVariationFeatureOverlap
24
25 =head1 SYNOPSIS
26
27 use Bio::EnsEMBL::Variation::BaseVariationFeatureOverlap;
28
29 my $bvfo = Bio::EnsEMBL::Variation::BaseVariationFeatureOverlap->new(
30 -feature => $feature,
31 -base_variation_feature => $var_feat
32 );
33
34 print "consequence type: ", (join ",", @{ $bvfo->consequence_type }), "\n";
35 print "most severe consequence: ", $bvfo->display_consequence, "\n";
36
37 =head1 DESCRIPTION
38
39 A BaseVariationFeatureOverlap represents a BaseVariationFeature which is in close
40 proximity to another Ensembl Feature. It is the superclass of variation feature
41 specific classes such as VariationFeatureOverlap and StructuralVariationOverlap
42 and has methods common to all such objects. You will not normally instantiate this
43 class directly, instead instantiating one of the more specific subclasses.
44
45 =cut
46
47 package Bio::EnsEMBL::Variation::BaseVariationFeatureOverlap;
48
49 use strict;
50 use warnings;
51
52 use Bio::EnsEMBL::Utils::Argument qw(rearrange);
53 use Bio::EnsEMBL::Utils::Scalar qw(assert_ref);
54 use Bio::EnsEMBL::Utils::Exception qw(throw warning);
55 use Bio::EnsEMBL::Variation::Utils::VariationEffect qw(overlap within_cds);
56
57 sub new {
58 my $class = shift;
59
60 my (
61 $adaptor,
62 $base_variation_feature,
63 $feature,
64 $no_transfer
65 ) = rearrange([qw(
66 ADAPTOR
67 BASE_VARIATION_FEATURE
68 FEATURE
69 NO_TRANSFER
70 )], @_);
71
72 assert_ref($base_variation_feature, 'Bio::EnsEMBL::Variation::BaseVariationFeature');
73
74 if (defined $feature) {
75
76 assert_ref($feature, 'Bio::EnsEMBL::Feature');
77
78 # we need to ensure the Feature and the BaseVariationFeature live on the same slice
79 # so we explicitly transfer the Feature here
80 unless($no_transfer && $no_transfer == 1) {
81 $feature = $feature->transfer($base_variation_feature->slice)
82 or throw("Unable to transfer the supplied feature to the same slice as the base variation feature");
83 }
84 }
85
86 my $self = bless {
87 base_variation_feature => $base_variation_feature,
88 feature => $feature,
89 adaptor => $adaptor,
90 }, $class;
91
92 return $self;
93 }
94
95 sub new_fast {
96 my ($class, $hashref) = @_;
97 return bless $hashref, $class;
98 }
99
100 =head2 feature
101
102 Arg [1] : (optional) A Bio::EnsEMBL::Feature
103 Description: Get/set the associated Feature, lazy-loading it if required
104 Returntype : Bio::EnsEMBL::Feature
105 Exceptions : throws isf the argument is the wrong type
106 Status : At Risk
107
108 =cut
109
110 sub feature {
111 my ($self, $feature, $type) = @_;
112
113 if ($feature) {
114 assert_ref($feature, 'Bio::EnsEMBL::Feature');
115 $self->{feature} = $feature;
116 }
117
118 if ($type && !$self->{feature}) {
119
120 # try to lazy load the feature
121
122 if (my $adap = $self->{adaptor}) {
123
124 my $get_method = 'get_'.$type.'Adaptor';
125
126 # XXX: this can doesn't work because the method is AUTOLOADed, need to rethink this...
127 #if ($adap->db->dnadb->can($get_method)) {
128 if (my $fa = $adap->db->dnadb->$get_method) {
129
130 # if we have a stable id for the feature use that
131 if (my $feature_stable_id = $self->{_feature_stable_id}) {
132 if (my $f = $fa->fetch_by_stable_id($feature_stable_id)) {
133 $self->{feature} = $f;
134 delete $self->{_feature_stable_id};
135 }
136 }
137 elsif (my $feature_label = $self->{_feature_label}) {
138 # get a slice covering the vf
139
140 #for my $f ($fa->fetch_all_by_Slice_constraint)
141 }
142 }
143 #}
144 else {
145 warn "Cannot get an adaptor for type: $type";
146 }
147 }
148 }
149
150 return $self->{feature};
151 }
152
153 sub _fetch_feature_for_stable_id {
154
155 # we shouldn't actually need this method as there will apparently
156 # soon be core support for fetching any feature by its stable id,
157 # but I'm waiting for core to add this...
158
159 my ($self, $feature_stable_id) = @_;
160
161 my $type_lookup = {
162 G => { type => 'Gene', group => 'core' },
163 T => { type => 'Transcript', group => 'core' },
164 R => { type => 'RegulatoryFeature', group => 'funcgen' },
165 };
166
167 if ($feature_stable_id =~ /^ENS[A-Z]*([G|R|T])\d+$/) {
168
169 my $type = $type_lookup->{$1}->{type};
170 my $group = $type_lookup->{$1}->{group};
171
172 if (my $adap = $self->{adaptor}) {
173
174 my $get_method = 'get_'.$type.'Adaptor';
175
176 if ($adap->db->dnadb->can($get_method)) {
177 if (my $fa = $adap->db->dnadb->$get_method) {
178
179 # if we have a stable id for the feature use that
180 if (my $feature_stable_id = $self->{_feature_stable_id}) {
181 if (my $f = $fa->fetch_by_stable_id($feature_stable_id)) {
182 $self->{feature} = $f;
183 delete $self->{_feature_stable_id};
184 }
185 }
186 elsif (my $feature_label = $self->{_feature_label}) {
187 # get a slice covering the vf
188
189
190 #for my $f ($fa->fetch_all_by_Slice_constraint)
191 }
192 }
193 }
194 else {
195 warn "Cannot get an adaptor for type: $type";
196 }
197 }
198 }
199 }
200
201 sub _fetch_adaptor_for_group {
202 my ($self, $group) = @_;
203
204 }
205
206 sub _feature_stable_id {
207 my $self = shift;
208 if ($self->feature && $self->feature->can('stable_id')) {
209 return $self->feature->stable_id;
210 }
211 elsif (my $id = $self->{_feature_stable_id}) {
212 return $id;
213 }
214 else {
215 return undef;
216 }
217 }
218
219 =head2 base_variation_feature
220
221 Arg [1] : (optional) A Bio::EnsEMBL::Variation::BaseVariationFeature
222 Description: Get/set the associated BaseVariationFeature
223 Returntype : Bio::EnsEMBL::Variation::BaseVariationFeature
224 Exceptions : throws if the argument is the wrong type
225 Status : At Risk
226
227 =cut
228
229 sub base_variation_feature {
230 my ($self, $bvf) = @_;
231
232 if ($bvf) {
233 assert_ref($bvf, 'Bio::EnsEMBL::Variation::BaseVariationFeature');
234 $self->{base_variation_feature} = $bvf;
235 }
236
237 return $self->{base_variation_feature};
238 }
239
240 =head2 add_BaseVariationFeatureOverlapAllele
241
242 Arg [1] : A Bio::EnsEMBL::Variation::BaseVariationFeatureOverlapAllele instance
243 Description: Add an allele to this BaseVariationFeatureOverlap
244 Returntype : none
245 Exceptions : throws if the argument is not the expected type
246 Status : At Risk
247
248 =cut
249
250 sub add_BaseVariationFeatureOverlapAllele {
251 my ($self, $bvfoa) = @_;
252
253 assert_ref($bvfoa, 'Bio::EnsEMBL::Variation::BaseVariationFeatureOverlapAllele');
254
255 if ($bvfoa->is_reference) {
256 $self->{reference_allele} = $bvfoa;
257 }
258 else {
259 my $alt_alleles = $self->{alt_alleles} ||= [];
260 push @$alt_alleles, $bvfoa;
261 }
262 }
263
264 =head2 get_reference_BaseVariationFeatureOverlapAllele
265
266 Description: Get the object representing the reference allele of this BaseVariationFeatureOverlapAllele
267 Returntype : Bio::EnsEMBL::Variation::BaseVariationFeatureOverlapAllele instance
268 Exceptions : none
269 Status : At Risk
270
271 =cut
272
273 sub get_reference_BaseVariationFeatureOverlapAllele {
274 my $self = shift;
275 return $self->{reference_allele};
276 }
277
278 =head2 get_all_alternate_BaseVariationFeatureOverlapAlleles
279
280 Description: Get a list of the alternate alleles of this BaseVariationFeatureOverlapAllele
281 Returntype : listref of Bio::EnsEMBL::Variation::BaseVariationFeatureOverlapAllele objects
282 Exceptions : none
283 Status : At Risk
284
285 =cut
286
287 sub get_all_alternate_BaseVariationFeatureOverlapAlleles {
288 my $self = shift;
289
290 $self->{alt_alleles} ||= [];
291
292 return $self->{alt_alleles};
293 }
294
295 =head2 get_all_BaseVariationFeatureOverlapAlleles
296
297 Description: Get a list of the all the alleles, both reference and alternate, of this
298 BaseVariationFeatureOverlap
299 Returntype : listref of Bio::EnsEMBL::Variation::BaseVariationFeatureOverlapAllele objects
300 Exceptions : none
301 Status : At Risk
302
303 =cut
304
305 sub get_all_BaseVariationFeatureOverlapAlleles {
306 my $self = shift;
307
308 my @alleles = @{ $self->get_all_alternate_BaseVariationFeatureOverlapAlleles };
309
310 my $ref = $self->get_reference_BaseVariationFeatureOverlapAllele;
311
312 unshift @alleles, $ref if defined $ref;
313
314 return \@alleles;
315 }
316
317 =head2 consequence_type
318
319 Arg [1] : (optional) String $term_type
320 Description: Get a list of all the unique consequence terms of the alleles of this
321 BaseVariationFeatureOverlap. By default returns Ensembl display terms
322 (e.g. 'NON_SYNONYMOUS_CODING'). $term_type can also be 'label'
323 (e.g. 'Non-synonymous coding'), 'SO' (Sequence Ontology, e.g.
324 'non_synonymous_codon') or 'NCBI' (e.g. 'missense')
325 Returntype : listref of strings
326 Exceptions : none
327 Status : At Risk
328
329 =cut
330
331 sub consequence_type {
332 my $self = shift;
333 my $term_type = shift;
334
335 my $method_name;
336
337 # delete cached term
338 if(defined($term_type)) {
339 delete $self->{_consequence_type};
340 $method_name = $term_type.($term_type eq 'label' ? '' : '_term');
341 $method_name = 'SO_term' unless defined $self->most_severe_OverlapConsequence && $self->most_severe_OverlapConsequence->can($method_name);
342 }
343
344 $method_name ||= 'SO_term';
345
346 unless ($self->{_consequence_type}) {
347
348 # use a hash to ensure we don't include redundant terms (because more than one
349 # allele may have the same consequence SO_term)
350
351 my %cons_types;
352
353 for my $allele (@{ $self->get_all_alternate_BaseVariationFeatureOverlapAlleles }) {
354 for my $cons (@{ $allele->get_all_OverlapConsequences }) {
355 $cons_types{$cons->$method_name} = $cons->rank;
356 }
357 }
358
359 # sort the consequence types by rank such that the more severe terms are earlier in the list
360
361 $self->{_consequence_type} = [ sort { $cons_types{$a} <=> $cons_types{$b} } keys %cons_types ];
362 }
363
364 return $self->{_consequence_type};
365 }
366
367 =head2 most_severe_OverlapConsequence
368
369 Description: Get the OverlapConsequence considered (by Ensembl) to be the most severe
370 consequence of all the alleles of this VariationFeatureOverlap
371 Returntype : Bio::EnsEMBL::Variation::OverlapConsequence
372 Exceptions : none
373 Status : At Risk
374
375 =cut
376
377 sub most_severe_OverlapConsequence {
378 my $self = shift;
379
380 unless ($self->{_most_severe_consequence}) {
381
382 my $highest;
383
384 for my $allele (@{ $self->get_all_alternate_BaseVariationFeatureOverlapAlleles }) {
385 for my $cons (@{ $allele->get_all_OverlapConsequences }) {
386 $highest ||= $cons;
387 if ($cons->rank < $highest->rank) {
388 $highest = $cons;
389 }
390 }
391 }
392
393 $self->{_most_severe_consequence} = $highest;
394 }
395
396 return $self->{_most_severe_consequence};
397 }
398
399 =head2 display_consequence
400
401 Arg [1] : (optional) String $term_type
402 Description: Get the term for the most severe OverlapConsequence of this
403 VariationFeatureOverlap. By default returns Ensembl display terms
404 (e.g. 'NON_SYNONYMOUS_CODING'). $term_type can also be 'label'
405 (e.g. 'Non-synonymous coding'), 'SO' (Sequence Ontology, e.g.
406 'non_synonymous_codon') or 'NCBI' (e.g. 'missense')
407 Returntype : string
408 Exceptions : none
409 Status : At Risk
410
411 =cut
412
413 sub display_consequence {
414 my $self = shift;
415 my $term_type = shift;
416
417 my $method_name;
418
419 # delete cached term
420 if(defined($term_type)) {
421 $method_name = $term_type.($term_type eq 'label' ? '' : '_term');
422 $method_name = 'SO_term' unless @{$self->get_all_OverlapConsequences} && $self->get_all_OverlapConsequences->[0]->can($method_name);
423 }
424
425 $method_name ||= 'SO_term';
426
427 my $worst_conseq = $self->most_severe_OverlapConsequence;
428
429 return $worst_conseq ? $worst_conseq->$method_name : '';
430 }
431
432 sub adaptor {
433 my $self = shift;
434 $self->{adaptor} = shift if @_;
435
436 # make adaptor an anonymous hash in its absence
437 # this allows the VEP to cache OverlapConsequences in offline mode
438 $self->{adaptor} ||= {};
439
440 return $self->{adaptor};
441 }
442
443 1;
444