Mercurial > repos > mahtabm > ensembl
diff variant_effect_predictor/Bio/EnsEMBL/Variation/StructuralVariationFeature.pm @ 0:1f6dce3d34e0
Uploaded
author | mahtabm |
---|---|
date | Thu, 11 Apr 2013 02:01:53 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/variant_effect_predictor/Bio/EnsEMBL/Variation/StructuralVariationFeature.pm Thu Apr 11 02:01:53 2013 -0400 @@ -0,0 +1,940 @@ +=head1 LICENSE + + Copyright (c) 1999-2012 The European Bioinformatics Institute and + Genome Research Limited. All rights reserved. + + This software is distributed under a modified Apache license. + For license details, please see + + http://www.ensembl.org/info/about/code_licence.html + +=head1 CONTACT + + Please email comments or questions to the public Ensembl + developers list at <dev@ensembl.org>. + + Questions may also be sent to the Ensembl help desk at + <helpdesk@ensembl.org>. + +=cut + +# Ensembl module for Bio::EnsEMBL::Variation::StructuralVariationFeature +# +# Copyright (c) 2011 Ensembl +# + + +=head1 NAME + +Bio::EnsEMBL::Variation::StructuralVariationFeature - A genomic position for a structural variation. + +=head1 SYNOPSIS + + # Structural variation feature representing a CNV + $svf = Bio::EnsEMBL::Variation::StructuralVariationFeature->new + (-start => 100, + -end => 200, + -strand => 1, + -slice => $slice, + -variation_name => 'esv1001', + -class_so_term => 'copy_number_variation', + -source => 'DGVa', + -source_description => 'Database of Genomic Variants Archive', + ); + + ... + + print $svf->start(), "-", $svf->end(), '(', $svf->strand(), ')', "\n"; + + print $svf->variation_name(), ":", $svf->var_class(); + +=head1 DESCRIPTION + +This is a class representing the genomic position of a structural variant +from the ensembl-variation database. A StructuralVariationFeature behaves as any other +Ensembl feature. See B<Bio::EnsEMBL::Feature> and +B<Bio::EnsEMBL::Variation::Variation>. + +=head1 METHODS + +=cut + +use strict; +use warnings; + +package Bio::EnsEMBL::Variation::StructuralVariationFeature; + +use Scalar::Util qw(weaken isweak); + +use Bio::EnsEMBL::Variation::BaseVariationFeature; +use Bio::EnsEMBL::Utils::Exception qw(throw warning deprecate); +use Bio::EnsEMBL::Utils::Argument qw(rearrange); +use Bio::EnsEMBL::Utils::Scalar qw(assert_ref); +use Bio::EnsEMBL::Slice; +use Bio::EnsEMBL::Variation::Utils::Constants qw(%VARIATION_CLASSES); +use Bio::EnsEMBL::Variation::Utils::VariationEffect qw(MAX_DISTANCE_FROM_TRANSCRIPT); +use Bio::EnsEMBL::Variation::StructuralVariationOverlap; +use Bio::EnsEMBL::Variation::TranscriptStructuralVariation; +use Bio::EnsEMBL::Variation::IntergenicStructuralVariation; + +our @ISA = ('Bio::EnsEMBL::Variation::BaseVariationFeature'); + +=head2 new + + Arg [-dbID] : + see superclass constructor + + Arg [-ADAPTOR] : + see superclass constructor + + Arg [-START] : + see superclass constructor + Arg [-END] : + see superclass constructor + + Arg [-STRAND] : + see superclass constructor + + Arg [-SLICE] : + see superclass constructor + + Arg [-INNER_START] : + int - the 5'-greater coordinate of the underlying structural variation + + Arg [-INNER_END] : + int - the 3'-less coordinate of the underlying structural variation + + Arg [-OUTER_START] : + int - the 5'-less coordinate of the underlying structural variation + + Arg [-OUTER_END] : + int - the 3'-greater coordinate of the underlying structural variation + + Arg [-VARIATION_NAME] : + string - the name of the variation this feature is for (denormalisation + from Variation object). + + Arg [-CLASS_SO_TERM] : + string - the sequence ontology term defining the class of the structural variation. + + Arg [-ALLELE_STRING] : + string - allele sequence of the structural variation. + + Arg [-SOURCE] : + string - the name of the source where the variation comes from + + Arg [-SOURCE_VERSION]: + string - version number of the source + + Arg [-IS_SOMATIC] : + int - flag to inform whether the structural variant is a somatic (1) or germline (0). + + Arg [-BREAKPOINT_ORDER] : + int - For a structural variant with multiple breakpoints, this gives the predicted order of the breakpoint event. + + Example : + $svf = Bio::EnsEMBL::Variation::StructuralVariationFeature->new + (-start => 100, + -end => 200, + -strand => 1, + -slice => $slice, + -variation_name => 'esv25480', + -class_so_term => 'structural_variant', + -source => 'DGVa'); + + Description: Constructor. Instantiates a new StructuralVariationFeature object. + Returntype : Bio::EnsEMBL::Variation::StructuralVariationFeature + Exceptions : none + Caller : general + Status : At Risk + +=cut + +sub new { + my $caller = shift; + my $class = ref($caller) || $caller; + + my $self = $class->SUPER::new(@_); + + my ( + $var_name, + $source, + $source_version, + $class_so_term, + $inner_start, + $inner_end, + $outer_start, + $outer_end, + $allele_string, + $is_somatic, + $breakpoint_order + ) = rearrange([qw( + VARIATION_NAME + SOURCE + SOURCE_VERSION + CLASS_SO_TERM + INNER_START + INNER_END + OUTER_START + INNER_START + ALLELE_STRING + IS_SOMATIC + BREAKPOINT_ORDER + )], @_); + + + $self->{'variation_name'} = $var_name; + $self->{'source'} = $source; + $self->{'source_version'} = $source_version; + $self->{'class_SO_term'} = $class_so_term; + $self->{'inner_start'} = $inner_start; + $self->{'inner_end'} = $inner_end; + $self->{'outer_start'} = $outer_start; + $self->{'outer_end'} = $outer_end; + $self->{'allele_string'} = $allele_string; + $self->{'is_somatic'} = $is_somatic || 0; + $self->{'breakpoint_order'} = $breakpoint_order; + + return $self; +} + + + +sub new_fast { + my $class = shift; + my $hashref = shift; + return bless $hashref, $class; +} + + +=head2 display_id + + Arg [1] : none + Example : print $svf->display_id(), "\n"; + Description: Returns the 'display' identifier for this feature. For + StructuralVariationFeatures this is simply the name of the structural variation + it is associated with. + Returntype : string + Exceptions : none + Caller : webcode + Status : At Risk + +=cut + +sub display_id { + my $self = shift; + return $self->{'variation_name'} || ''; +} + + + +=head2 variation_name + + Arg [1] : string $newval (optional) + The new value to set the variation_name attribute to + Example : $variation_name = $obj->variation_name() + Description: Getter/Setter for the variation_name attribute. This is the + name of the structural variant associated with this feature. + Returntype : string + Exceptions : none + Caller : general + Status : Stable + +=cut + +sub variation_name{ + my $self = shift; + return $self->{'variation_name'} = shift if(@_); + return $self->{'variation_name'}; +} + +=head2 allele_string + + Arg [1] : string $newval (optional) + The new value to set the allele_string attribute to + Example : $allele_string = $obj->allele_string() + Description: Getter/Setter for the allele_string attribute. This is the + genomic sequence represented by this feature. + Returntype : string + Exceptions : none + Caller : general + Status : Stable + +=cut + +sub allele_string{ + my $self = shift; + return $self->{'allele_string'} = shift if(@_); + return $self->{'allele_string'}; +} + + + +=head2 structural_variation + + Arg [1] : (optional) Bio::EnsEMBL::Variation::StructuralVariation or + Bio::EnsEMBL::Variation::SupportingStructuralVariation $structural_variation + Example : $sv = $svf->structural_variation(); + Description: Getter/Setter for the structural variant associated with this feature. + If not set, and this StructuralVariationFeature has an associated adaptor + an attempt will be made to lazy-load the structural variation from the + database. + Returntype : Bio::EnsEMBL::Variation::StructuralVariation or + Bio::EnsEMBL::Variation::SupportingStructuralVariation + Exceptions : throw on incorrect argument + Caller : general + Status : Stable + +=cut + +sub structural_variation { + my $self = shift; + + if(@_) { + if(!ref($_[0]) || (!$_[0]->isa('Bio::EnsEMBL::Variation::StructuralVariation') && + !$_[0]->isa('Bio::EnsEMBL::Variation::SupportingStructuralVariation') + )) { + throw("Bio::EnsEMBL::Variation::StructuralVariation or Bio::EnsEMBL::Variation::SupportingStructuralVariation argument expected"); + } + $self->{'structural_variation'} = shift; + } + elsif(!defined($self->{'structural_variation'}) && $self->{'adaptor'} && + defined($self->{'structural_variation_id'})) { + # lazy-load from database on demand + my $sva = $self->{'adaptor'}->db()->get_StructuralVariationAdaptor(); + $self->{'structural_variation'} = $sva->fetch_by_dbID($self->{'structural_variation_id'}); + if (!defined($self->{'structural_variation'})) { + $sva = $self->{'adaptor'}->db()->get_SupportingStructuralVariationAdaptor(); + $self->{'structural_variation'} = $sva->fetch_by_dbID($self->{'structural_variation_id'}); + } + } + + return $self->{'structural_variation'}; +} + + + + + +=head2 get_all_VariationSets + + Args : none + Example : my @vs = @{$svf->get_all_VariationSets()}; + Description : returns a reference to a list of all the VariationSets this + StructuralVariationFeature is a member of + ReturnType : reference to list of Bio::EnsEMBL::Variation::VariationSets + Exceptions : if no adaptor is attached to this object + Caller : general + Status : At Risk +=cut + +sub get_all_VariationSets { + my $self = shift; + + if (!$self->adaptor()) { + throw('An adaptor must be attached in order to get all variation sets'); + } + my $vs_adaptor = $self->adaptor()->db()->get_VariationSetAdaptor(); + my $variation_sets = $vs_adaptor->fetch_all_by_StructuralVariation($self->structural_variation()); + + return $variation_sets; +} + + +=head2 get_nearest_Gene + + Example : $svf->get_nearest_Gene($flanking_size); + Description : Getter a Gene which is associated to or nearest to the StructuralVariationFeature + Returntype : Listref of objects of Bio::EnsEMBL::Gene + Exceptions : None + Caller : general + Status : At Risk + +=cut + +sub get_nearest_Gene{ + + my $self = shift; + my $flanking_size = shift; #flanking size is optional + $flanking_size ||= 0; + my $sa = $self->{'adaptor'}->db()->dnadb->get_SliceAdaptor(); + my $slice = $sa->fetch_by_Feature($self,$flanking_size); + my @genes = @{$slice->get_all_Genes}; + return \@genes if @genes; #$svf is on the gene + + if (! @genes) { #if $svf is not on the gene, increase flanking size + warning("flanking_size $flanking_size is not big enough to overlap a gene, increase it by 1,000,000"); + $flanking_size += 1000000; + $slice = $sa->fetch_by_Feature($self,$flanking_size); + @genes = @{$slice->get_all_Genes}; + } + if (@genes) { + my %distances = (); + foreach my $g (@genes) { + if ($g->seq_region_start > $self->start) { + $distances{$g->seq_region_start-$self->start}=$g; + } + else { + $distances{$self->start-$g->seq_region_end}=$g; + } + } + my @distances = sort {$a<=>$b} keys %distances; + my $shortest_distance = $distances[0]; + if ($shortest_distance) { + my $nearest_gene = $distances{$shortest_distance}; + return [$nearest_gene]; + } + } + else { + throw("variation_feature with flanking_size $flanking_size is not overlap with a gene, try a bigger flanking_size"); + } +} + + +=head2 is_somatic + + Arg [1] : boolean $is_somatic (optional) + The new value to set the is_somatic flag to + Example : $is_somatic = $svf->is_somatic + Description: Getter/Setter for the is_somatic flag, which identifies this structural variation feature as either somatic or germline + Returntype : boolean + Exceptions : none + Caller : general + Status : Stable + +=cut + +sub is_somatic { + my ($self, $is_somatic) = @_; + $self->{'is_somatic'} = $is_somatic if defined $is_somatic; + return $self->{'is_somatic'}; +} + + +=head2 breakpoint_order + + Arg [1] : string $bp_order (optional) + The new value to set the breakpoint order to + Example : $bp_order = $svf->breakpoint_order() + Description: Getter/Setter for the breakpoint_order attribute + Returntype : string + Exceptions : none + Caller : general + Status : At Risk + +=cut + +sub breakpoint_order { + my $self = shift; + return $self->{'breakpoint_order'} = shift if(@_); + return $self->{'breakpoint_order'}; +} + +=head2 get_all_StructuralVariationOverlaps + + Description : Get all the StructuralVariationOverlaps associated with this StructuralVariation, this + includes TranscriptStructuralVariations and regulatory feature overlap object. + Returntype : listref of Bio::EnsEMBL::Variation::StructuralVariationOverlap objects + Exceptions : none + Status : At Risk + +=cut + +sub get_all_StructuralVariationOverlaps { + my $self = shift; + + my $vfos = [ + @{ $self->get_all_TranscriptStructuralVariations }, + @{ $self->get_all_RegulatoryFeatureStructuralVariations }, + @{ $self->get_all_MotifFeatureStructuralVariations }, + ]; + + if (my $iv = $self->get_IntergenicStructuralVariation) { + push @$vfos, $iv; + } + + return $vfos; +} + +=head2 get_all_TranscriptStructuralVariations + + Arg [1] : (optional) listref of Bio::EnsEMBL::Transcript objects + Example : $svf->get_all_TranscriptStructuralVariations; + Description : Get all the TranscriptStructuralVariations associated with this + StructuralVariationFeature. If the optional list of Transcripts + is supplied, get only TranscriptStructuralVariations + associated with those Transcripts. + Returntype : listref of Bio::EnsEMBL::Variation::TranscriptVariation objects + Exceptions : Thrown on wrong argument type + Caller : general + Status : At Risk + +=cut + +sub get_all_TranscriptStructuralVariations { + my ($self, $transcripts) = @_; + + if ($transcripts) { + assert_ref($transcripts, 'ARRAY'); + map { assert_ref($_, 'Bio::EnsEMBL::Transcript') } @$transcripts; + } + + elsif (not defined $self->{transcript_structural_variations}) { + # this VariationFeature is not in the database so we have to build the + # TranscriptVariations ourselves + + unless ($transcripts) { + # if the caller didn't supply some transcripts fetch those around this VariationFeature + # get a slice around this transcript including the maximum distance up and down-stream + # that we still call consequences for + my $slice = $self->feature_Slice->expand( + MAX_DISTANCE_FROM_TRANSCRIPT, + MAX_DISTANCE_FROM_TRANSCRIPT + ); + + # fetch all transcripts on this slice + $transcripts = $slice->get_all_Transcripts(1); + } + + my @unfetched_transcripts = grep { + not exists $self->{transcript_structural_variations}->{$_->stable_id} + } @$transcripts; + + for my $transcript (@unfetched_transcripts) { + $self->add_TranscriptStructuralVariation( + Bio::EnsEMBL::Variation::TranscriptStructuralVariation->new( + -structural_variation_feature => $self, + -transcript => $transcript, + -adaptor => undef, + ) + ); + } + } + + if ($transcripts) { + # just return TranscriptVariations for the requested Transcripts + return [ map { $self->{transcript_structural_variations}->{$_->stable_id} } @$transcripts ]; + } + else { + # return all TranscriptVariations + return [ values %{ $self->{transcript_structural_variations} } ]; + } +} + +=head2 get_all_RegulatoryFeatureStructuralVariations + + Description : Get all the RegulatoryFeatureStructuralVariations associated with this VariationFeature. + Returntype : listref of Bio::EnsEMBL::Variation::StructuralVariationOverlap objects + Exceptions : none + Status : At Risk + +=cut + +sub get_all_RegulatoryFeatureStructuralVariations { + my $self = shift; + return $self->_get_all_RegulationStructuralVariations('RegulatoryFeature', @_); +} + +=head2 get_all_MotifFeatureStructuralVariations + + Description : Get all the MotifFeatureStructuralVariations associated with this VariationFeature. + Returntype : listref of Bio::EnsEMBL::Variation::StructuralVariationOverlap objects + Exceptions : none + Status : At Risk + +=cut + +sub get_all_MotifFeatureStructuralVariations { + my $self = shift; + return $self->_get_all_RegulationStructuralVariations('MotifFeature', @_); +} + +=head2 get_all_ExternalFeatureStructuralVariations + + Description : Get all the ExternalFeatureStructuralVariations associated with this VariationFeature. + Returntype : listref of Bio::EnsEMBL::Variation::StructuralVariationOverlap objects + Exceptions : none + Status : At Risk + +=cut + +sub get_all_ExternalFeatureStructuralVariations { + my $self = shift; + return $self->_get_all_RegulationStructuralVariations('ExternalFeature', @_); +} + +sub _get_all_RegulationStructuralVariations { + my ($self, $type) = @_; + + unless ($type && ($type eq 'RegulatoryFeature' || $type eq 'MotifFeature' || $type eq 'ExternalFeature')) { + throw("Invalid Ensembl Regulation type '$type'"); + } + + unless ($self->{regulation_structural_variations}->{$type}) { + my $fg_adaptor; + + if (my $adap = $self->adaptor) { + if(my $db = $adap->db) { + $fg_adaptor = Bio::EnsEMBL::DBSQL::MergedAdaptor->new( + -species => $adap->db->species, + -type => $type, + ); + } + + unless ($fg_adaptor) { + warning("Failed to get adaptor for $type"); + return []; + } + } + else { + warning('Cannot get variation features without attached adaptor'); + return []; + } + + my $slice = $self->feature_Slice; + + my $constructor = 'Bio::EnsEMBL::Variation::StructuralVariationOverlap'; + + eval { + $self->{regulation_structural_variations}->{$type} = [ + map { + $constructor->new( + -structural_variation_feature => $self, + -feature => $_, + ); + } map { $_->transfer($self->slice) } @{ $fg_adaptor->fetch_all_by_Slice($slice) } + ]; + }; + + $self->{regulation_structural_variations}->{$type} ||= []; + } + + return $self->{regulation_structural_variations}->{$type}; +} + + +sub get_IntergenicStructuralVariation { + my $self = shift; + my $no_ref_check = shift; + + unless (exists $self->{intergenic_structural_variation}) { + if (scalar(@{ $self->get_all_TranscriptStructuralVariations }) == 0) { + $self->{intergenic_structural_variation} = Bio::EnsEMBL::Variation::IntergenicStructuralVariation->new( + -structural_variation_feature => $self, + -no_ref_check => $no_ref_check, + ); + } + else { + $self->{intergenic_structural_variation} = undef; + } + } + + return $self->{intergenic_structural_variation}; +} + + + +=head2 TranscriptStructuralVariation + + Arg [1] : Bio::EnsEMBL::Variation::TranscriptStructuralVariation + Example : $vf->add_TranscriptStructuralVariation($tsv); + Description : Adds a TranscriptStructuralVariation to the structural variation + feature object. + Exceptions : thrown on bad argument + Caller : Bio::EnsEMBL::Variation::StructuralVariationFeature, + Bio::EnsEMBL::Varaition::Utils::VEP + Status : Stable + +=cut + +sub add_TranscriptStructuralVariation { + my ($self, $tsv) = @_; + assert_ref($tsv, 'Bio::EnsEMBL::Variation::TranscriptStructuralVariation'); + # we need to weaken the reference back to us to avoid a circular reference + weaken($tsv->{base_variation_feature}); + $self->{transcript_structural_variations}->{$tsv->transcript_stable_id} = $tsv; +} + + +=head2 var_class + + Args : None + Example : my $sv_class = $svf->var_class() + Description : Getter for the class of structural variation + ReturnType : String + Exceptions : none + Caller : General + Status : At Risk + +=cut + +sub var_class { + my $self = shift; + + unless ($self->{class_display_term}) { + my $display_term = $VARIATION_CLASSES{$self->{class_SO_term}}->{display_term}; + + warn "No display term for SO term: ".$self->{class_SO_term} unless $display_term; + + $self->{class_display_term} = $display_term || $self->{class_SO_term}; + } + + return $self->{class_display_term}; +} + + +=head2 class_SO_term + + Args : None + Example : my $sv_so_term = $svf->class_SO_term() + Description : Getter for the class of structural variation, returning the SO term + ReturnType : String + Exceptions : none + Caller : General + Status : At Risk + +=cut + +sub class_SO_term { + my $self = shift; + + return $self->{class_SO_term}; +} + + +=head2 source + + Arg [1] : string $source (optional) + The new value to set the source attribute to + Example : $source = $svf->source() + Description: Getter/Setter for the source attribute + Returntype : string + Exceptions : none + Caller : general + Status : At Risk + +=cut + +sub source{ + my $self = shift; + return $self->{'source'} = shift if(@_); + return $self->{'source'}; +} + +=head2 source_version + + Arg [1] : string $source_version (optional) + The new value to set the source_version attribute to + Example : $source_version = $svf->source_version() + Description: Getter/Setter for the source_version attribute + Returntype : string + Exceptions : none + Caller : general + Status : At Risk + +=cut + +sub source_version { + my $self = shift; + return $self->{'source_version'} = shift if(@_); + return $self->{'source_version'}; +} + +=head2 bound_start + + Args : None + Example : my $bound_start = $svf->bound_start(); + Description : Getter/setter for the 5'-most coordinate defined for this StructuralVariationFeature (outer_start or start) + ReturnType : int + Exceptions : none + Caller : general + Status : At risk +=cut + +sub bound_start{ + my $self = shift; + return $self->{'outer_start'} if (defined($self->{'outer_start'})); + return $self->{'start'}; +} + + +=head2 bound_end + + Args : None + Example : my $bound_end = $svf->bound_end(); + Description : Getter/setter for the 3'-most coordinate defined for this StructuralVariationFeature (outer_end or end) + ReturnType : int + Exceptions : none + Caller : general + Status : At risk +=cut + +sub bound_end{ + my $self = shift; + return $self->{'outer_end'} if (defined($self->{'outer_end'})); + return $self->{'end'}; +} + + +=head2 outer_start + + Arg [1] : int $outer_start (optional) + The new value to set the outer_start attribute to + Example : my $outer_start = $svf->outer_start(); + Description : Getter/setter for the 5'-most coordinate defined for this StructuralVariationFeature + ReturnType : int + Exceptions : none + Caller : general + Status : At risk +=cut + +sub outer_start{ + my $self = shift; + return $self->{'outer_start'} = shift if(@_); + return $self->{'outer_start'}; +} + + +=head2 outer_end + + Arg [1] : int $outer_end (optional) + The new value to set the outer_end attribute to + Example : my $outer_end = $svf->outer_end(); + Description : Getter/setter for the 3'-most coordinate defined for this StructuralVariationFeature + ReturnType : int + Exceptions : none + Caller : general + Status : At risk +=cut + +sub outer_end{ + my $self = shift; + return $self->{'outer_end'} = shift if(@_); + return $self->{'outer_end'}; +} + + +=head2 inner_start + + Arg [1] : int $inner_start (optional) + The new value to set the inner_start attribute to + Example : my $inner_start = $svf->inner_start(); + Description : Getter/setter for the 5'-less coordinate defined for this StructuralVariationFeature + ReturnType : int + Exceptions : none + Caller : general + Status : At Risk +=cut + +sub inner_start{ + my $self = shift; + return $self->{'inner_start'} = shift if(@_); + return $self->{'inner_start'}; +} + + +=head2 inner_end + + Arg [1] : int $inner_end (optional) + The new value to set the inner_end attribute to + Example : my $inner_end = $svf->inner_end(); + Description : Getter/setter for the 3'-less coordinate defined for this StructuralVariationFeature + ReturnType : int + Exceptions : none + Caller : general + Status : At Risk +=cut + +sub inner_end{ + my $self = shift; + return $self->{'inner_end'} = shift if(@_); + return $self->{'inner_end'}; +} + + +=head2 get_reference_sequence + + Args : none + Example : my $seq = $svf->get_reference_sequence + Description : returns a string containing the reference sequence for the region + covered by this StructuralVariationFeature + ReturnType : string + Exceptions : none + Caller : general + Status : At Risk +=cut + +sub get_reference_sequence{ + my $self = shift; + + return $self->feature_Slice->seq(); +} + + +sub transform { + my $self = shift; + + # run the transform method from the parent class + my $transformed = $self->SUPER::transform(@_); + + if(defined $transformed) { + # fit the start and end coords to the new coords + $transformed->_fix_bounds($self); + } + + return $transformed; +} + + +sub transfer { + my $self = shift; + + # run the transfer method from the parent class + my $transferred = $self->SUPER::transfer(@_); + + if(defined $transferred) { + # fit the start and end coords to the new coords + $transferred->_fix_bounds($self); + } + + return $transferred; +} + + +sub _fix_bounds { + my $self = shift; + my $old = shift; + + if(defined $old->{'outer_start'}) { + $self->{'outer_start'} = $self->start - ($old->start - $old->{'outer_start'}); + } + + if(defined $old->{'outer_end'}) { + $self->{'outer_end'} = $self->end + ($old->{'outer_end'} - $old->end); + } +} + +sub _sort_svos { + my $self = shift; + + return unless defined $self->{structural_variation_overlaps}; + + my @svos = @{$self->{structural_variation_overlaps}}; + + # define a feature order for sorting + my %feature_order = ( + 'Bio::EnsEMBL::Gene' => 1, + 'Bio::EnsEMBL::Transcript' => 2, + 'Bio::EnsEMBL::Exon' => 3, + ); + + # sort them nicely by feature type and position + @svos = sort { + $feature_order{ref($a->feature)} <=> $feature_order{ref($b->feature)} || + $a->feature->start <=> $b->feature->start + } @svos; + + $self->{structural_variation_overlaps} = \@svos; +} + +1;