Raw content of Bio::EnsEMBL::Funcgen::RegulatoryFeature
#
# Ensembl module for Bio::EnsEMBL::Funcgen::RegulatoryFeature
#
# You may distribute this module under the same terms as Perl itself
=head1 NAME
Bio::EnsEMBL::RegulatoryFeature - A module to represent a regulatory feature
mapping as generated by the eFG regulatory build pipeline.
=head1 SYNOPSIS
use Bio::EnsEMBL::Funcgen::RegulatoryFeature;
my $feature = Bio::EnsEMBL::Funcgen::RegulatoryFeature->new(
-SLICE => $chr_1_slice,
-START => 1_000_000,
-END => 1_000_024,
-STRAND => -1,
-DISPLAY_LABEL => $text,
-FEATURE_SET => $fset,
-FEATURE_TYPE => $reg_feat_type,
);
=head1 DESCRIPTION
A RegulatoryFeature object represents the genomic placement of a combined regulatory
feature generated by the eFG analysis pipeline, which may have originated from one or
many separate annotated or supporting features.
=head1 AUTHOR
This module was created by Nathan Johnson.
This module is part of the Ensembl project: /
=head1 CONTACT
Post comments or questions to the Ensembl development list: ensembl-dev@ebi.ac.uk
=head1 METHODS
=cut
use strict;
use warnings;
package Bio::EnsEMBL::Funcgen::RegulatoryFeature;
use Bio::EnsEMBL::Utils::Argument qw( rearrange );
use Bio::EnsEMBL::Utils::Exception qw( throw );
use Bio::EnsEMBL::Funcgen::SetFeature;
use vars qw(@ISA);
@ISA = qw(Bio::EnsEMBL::Funcgen::SetFeature);
=head2 new
Arg [-SCORE]: (optional) int - Score assigned by analysis pipeline
Arg [-ANALYSIS] : Bio::EnsEMBL::Analysis
Arg [-SLICE] : Bio::EnsEMBL::Slice - The slice on which this feature is.
Arg [-START] : int - The start coordinate of this feature relative to the start of the slice
it is sitting on. Coordinates start at 1 and are inclusive.
Arg [-END] : int -The end coordinate of this feature relative to the start of the slice
it is sitting on. Coordinates start at 1 and are inclusive.
Arg [-DISPLAY_LABEL]: string - Display label for this feature
Arg [-STRAND] : int - The orientation of this feature. Valid values are 1, -1 and 0.
Arg [-FEATURE_SET] : Bio::EnsEMBL::Funcgen::FeatureSet - Regulatory Feature set
Arg [-FEATURE_TYPE] : Bio::EnsEMBL::Funcgen::FeatureType - Regulatory Feature sub type
Arg [-ATTRIBUTES] : ARRAYREF of attribute features e.g. Annotated or ? Features
Arg [-dbID] : (optional) int - Internal database ID.
Arg [-ADAPTOR] : (optional) Bio::EnsEMBL::DBSQL::BaseAdaptor - Database adaptor.
Example : my $feature = Bio::EnsEMBL::Funcgen::RegulatoryFeature->new(
-SLICE => $chr_1_slice,
-START => 1_000_000,
-END => 1_000_024,
-STRAND => -1,
-DISPLAY_LABEL => $text,
-FEATURE_SET => $fset,
-FEATURE_TYPE => $reg_ftype,
-REGULATORY_ATTRIBUTES => \@features,
-_ATTRIBUTE_CACHE => \%attr_cache,
);
Description: Constructor for RegulatoryFeature objects.
Returntype : Bio::EnsEMBL::Funcgen::RegulatoryFeature
Exceptions : None
Caller : General
Status : At Risk
=cut
sub new {
my $caller = shift;
my $class = ref($caller) || $caller;
my $self = $class->SUPER::new(@_);
my ($stable_id, $reg_attrs, $attr_cache)
= rearrange(['STABLE_ID', 'REGULATORY_ATTRIBUTES', '_ATTRIBUTE_CACHE'], @_);
#moved to set feature, but not mandatory?
#throw("Must provide a FeatureType") if ! $reg_type;
$self->stable_id($stable_id) if $stable_id;
$self->regulatory_attributes($reg_attrs) if $reg_attrs;
$self->_attribute_cache($attr_cache) if $attr_cache;
return $self;
}
=head2 display_label
Arg [1] : string - display label
Example : my $label = $feature->display_label();
Description: Getter and setter for the display label of this feature.
Returntype : String
Exceptions : None
Caller : General
Status : Medium Risk
=cut
#this will over ride individual display_label for annotated features.
#set label could be used as track name and feature label used in zmenu?
#These should therefore be called track_label and display_label
sub display_label {
my $self = shift;
$self->{'display_label'} = shift if @_;
#auto generate here if not set in table
#need to go with one or other, or can we have both, split into diplay_name and display_label?
#HACK to hide binary string and siplay something more meaningful
#if(! $self->{'display_label'} && $self->adaptor()){
#hardcoded for RegulatoryF Feature here instead of accessing feature_set
#$self->{'display_label'} = $self->feature_type->name()." Regulatory Feature";
#$self->{'display_label'} .= " - ".$self->cell_type->name() if $self->cell_type->display_name();#?
#}
my $tmp = $self->feature_type->name()." Regulatory Feature";
$tmp .= " - ".$self->cell_type->name() if defined $self->cell_type();#?
return $tmp;
}
=head2 stable_id
Arg [1] : (optional) string - stable_id e.g ENSR00000000001
Example : my $stable_id = $feature->stable_id();
Description: Getter and setter for the stable_id attribute for this feature.
Returntype : string
Exceptions : None
Caller : General
Status : At Risk
=cut
sub stable_id {
my $self = shift;
$self->{'stable_id'} = shift if @_;
return (defined $self->{'stable_id'}) ? sprintf("ENSR%011d", $self->{'stable_id'}) : undef;
}
=head2 regulatory_attributes
Arg [1] : (optional) list of constituent features
Example : print "Regulatory Attributes:\n\t".join("\n\t", @{$feature->regulatory_attributes()})."\n";
Description: Getter and setter for the regulatory_attributes for this feature.
Returntype : ARRAYREF
Exceptions : None
Caller : General
Status : At Risk
=cut
#change to store attrs in type hash?
sub regulatory_attributes {
my ($self, $attrs) = @_;
my $table;
#This is causing errors when we have not yet set the adaptor
my %adaptors = (
'annotated_feature' => $self->adaptor->db->get_AnnotatedFeatureAdaptor(),
# #'external_feature' => $self->adaptor->db->get_ExternalFeatureAdaptor(),
);
#my %attr_class_tables = (
#'Bio::EnsEMBL::Funcgen::AnnotatedFeature' => 'annotated',
# 'Bio::EnsEMBL::Funcgen::CuratedFeature' => 'curated',
#mm, get from adaptor instead? attrs should always have an adaptor set as they should be stored by now
#change this to a dbID key'd hash to allow storage of only dbIDs during reg build
#deref here for safety??
#$self->{'regulatory_attributes'} = [@$attrs] if $attrs;
if(defined $attrs){# && @$attrs){
my @attrs = @$attrs;
foreach my $attr(@attrs){
$table = $attr->adaptor->_main_table->[0];
#check for isa Feature here?
$self->{'regulatory_attributes'}{$table}{$attr->dbID()} = $attr;
}
}
else{
#do we need this block if we are not using the id approach outside of the reg_build script?
#temporarily yes!!
#Until we pass the actual features in the attr cache from build_regulatory_features.pl
foreach my $table(keys %{$self->{'regulatory_attributes'}}){
foreach my $dbID(keys %{$self->{'regulatory_attributes'}{$table}}){
if(! defined $self->{'regulatory_attributes'}{$table}{$dbID}){
$self->{'regulatory_attributes'}{$table}{$dbID} = $adaptors{$table}->fetch_by_dbID($dbID);
}
}
}
}
return [ map values %{$self->{'regulatory_attributes'}{$_}}, keys %{$self->{'regulatory_attributes'}} ];
}
=head2 _attribute_cache
Arg [1] : (optional) hash of attribute table keys with dbID list vakues for regulatory attributes
Example : $feature->_attribute_cache(%attribute_table_ids);
Description: Setter for the regulatory_attributes dbIDs for this feature. This is a short cut method used by the
regulatory build and the webcode to avoid having to query the DB for the underlying attribute features
Returntype : Hasref of table keys and hash values with dbID keys
Exceptions : None?? check for enum'd types?
Caller : RegulatoryFeatureAdaptor.pm and build_regulatory_features.pl
Status : At Risk
=cut
sub _attribute_cache{
my ($self, $attr_table_ids) = @_;
foreach my $table(keys %{$attr_table_ids}){
foreach my $dbID(keys %{$attr_table_ids->{$table}}){
if(exists $self->{'regulatory_attributes'}{$table}{$dbID}){
warn "You are trying to overwrite a pre-existing regulatory atribute cache entry for $table dbID $dbID\n";
}
else{
#why are we setting this to undef?
$self->{'regulatory_attributes'}{$table}{$dbID} = undef;
}
}
}
return $self->{'regulatory_attributes'};
}
=head2 bound_start
Example : my $bound_start = $feature->bound_start();
Description: Getter for the bound_start attribute for this feature.
Gives the 5' most start value of the underlying attribute
features.
Returntype : string
Exceptions : None
Caller : General
Status : At Risk
=cut
sub bound_start {
my $self = shift;
$self->_generate_underlying_structure() if(! defined $self->{'bound_start'});
return $self->{'bound_start'};
}
=head2 bound_end
Example : my $bound_end = $feature->bound_start();
Description: Getter for the bound_end attribute for this feature.
Gives the 3' most end value of the underlying attribute
features.
Returntype : string
Exceptions : None
Caller : General
Status : At Risk
=cut
sub bound_end {
my $self = shift;
$self->_generate_underlying_structure() if(! defined $self->{'bound_end'});
#This should return the attr name to?
return $self->{'bound_end'};
}
=head2 _generate_underlying_structure
Example : $self->_generate_underlying_structure() if(! exists $self->{'bound_end'});
Description: Getter for the bound_end attribute for this feature.
Gives the 3' most end value of the underlying attribute
features.
Returntype : string
Exceptions : None
Caller : General
Status : At Risk
=cut
sub _generate_underlying_structure{
my $self = shift;
my @attrs = @{$self->regulatory_attributes()};
if(! @attrs){
warn "No underlying regulatory_attribute features to generate comples structure from";
#This should never happen
#set to undef so we don't cause too many errors
#set these to start and end instead?
$self->{'bound_end'} = undef;
$self->{'bound_end'} = undef;
}
else{
my (@start_ends);
map {push @start_ends, ($_->start, $_->end)} @attrs;
@start_ends = sort { $a <=> $b } @start_ends;
$self->{'bound_end'} = pop @start_ends;
$self->{'bound_start'} = shift @start_ends;
}
return;
}
#other methods
#type!! Add to BaseFeature? Hard code val in oligo_feature
#analysis? Use AnalsisAdapter here, or leave to caller?
#sources/experiments
#target, tar
1;