Commit d36d1cd9 authored by Graham McVicker's avatar Graham McVicker
Browse files

ExternalFeatureAdaptor now integrated into API

old ExternalFeatureFactoryI now magically behaves as an ExternalFeatureAdaptor for backwards compatibility
parent 6c556588
......@@ -12,8 +12,7 @@
=head1 NAME
Bio::EnsEMBL::DB::ExternalFeatureFactoryI - Abstract interface for
External Feature Factories
Bio::EnsEMBL::DB::ExternalFeatureFactoryI - Legacy Abstract interface for External Feature Factories. Bio::EnsEMBL::External::ExternalFeatureAdaptor should be used instead if possible.
=head1 SYNOPSIS
......@@ -41,15 +40,11 @@ External Feature Factories
=head1 DESCRIPTION
Currently this is included for legacy purposes. Presumably numerous
external installations use external feature factories as a method
of adding features to ensembl. The rest of the DB directory has
been removed from the main trunk but this files remains to allow
external feature factories to continue to work.
If you are an internal EnsEMBL developer you should probably think twice
before using this modules since there is probably a better alternative.
This is a legacy class. It is included only for backwards compatibility with
ExternalFeatureFactories which are presumably still used to place data into
ensembl. It is recommended that if you wish to create EnsEMBL features
externally that you use the Bio::EnsEMBL::External::ExternalFeatureAdaptor
instead.
This object defines the abstract interface for External Database
access inside Ensembl. The aim is that one can attach an External
......@@ -120,50 +115,108 @@ using unique internal identifiers in that database. The method is:
It should return exactly one Sequence Feature object of the same type
as above.
=head1 AUTHOR - Ewan Birney
=head1 FEEDBACK
Email birney@ebi.ac.uk
=head2 Mailing Lists
=head1 CONTACT
User feedback is an integral part of the evolution of this
and other Bioperl modules. Send your comments and suggestions preferably
to one of the Bioperl mailing lists.
Your participation is much appreciated.
Email questions to the EnsEMBL developer list: <ensembl-dev@ebi.ac.uk>
vsns-bcd-perl@lists.uni-bielefeld.de - General discussion
vsns-bcd-perl-guts@lists.uni-bielefeld.de - Technically-oriented discussion
http://bio.perl.org/MailList.html - About the mailing lists
=head1 APPENDIX
=head2 Reporting Bugs
The rest of the documentation details each of the object methods. Internal methods are usually preceded with a _
Report bugs to the Bioperl bug tracking system to help us keep track
the bugs and their resolution.
Bug reports can be submitted via email or the web:
=cut
bioperl-bugs@bio.perl.org
http://bio.perl.org/bioperl-bugs/
=head1 AUTHOR - Ewan Birney
# Let the code begin...
Email birney@ebi.ac.uk
package Bio::EnsEMBL::DB::ExternalFeatureFactoryI;
use Bio::EnsEMBL::External::ExternalFeatureAdaptor;
use vars qw(@ISA);
Describe contact details here
@ISA = ( 'Bio::EnsEMBL::External::ExternalFeatureAdaptor' );
=head1 APPENDIX
The rest of the documentation details each of the object methods. Internal methods are usually preceded with a _
=head2 coordinate_systems
Arg [1] : none
Example : none
Description: This method is present to make the ExternalFeatureFactory
interface behave as an ExternalFeatureAdaptor. It is for
backwards compatibility.
Returntype : none
Exceptions : none
Caller : internal
=cut
sub coordinate_systems {
my $self = shift;
return qw(CONTIG);
}
# Let the code begin...
=head2 fetch_all_by_contig_name
package Bio::EnsEMBL::DB::ExternalFeatureFactoryI;
use Bio::EnsEMBL::Root;
use vars qw(@ISA);
Arg [1] : none
Example : none
Description: This method is present to make the ExternalFeatureFactory
interface behave as an ExternalFeatureAdaptor. It is for
backwards compatibility.
Returntype : none
Exceptions : none
Caller : internal
@ISA = ( 'Bio::EnsEMBL::Root');
=cut
sub fetch_all_by_contig_name {
my ($self, $contig_name) = @_;
unless($self->db) {
$self->throw('DB attribute not set. This value must be set for the ' .
'ExternalFeatureFactory to function correctly');
}
my @features = ();
my $ctg = $self->db->get_RawContigAdaptor->fetch_by_name($contig_name);
my $clone = $ctg->clone;
my $version = $clone->version;
my $ctg_length = $ctg->length;
#get contig features
push @features, $self->get_Ensembl_SeqFeatures_contig($ctg->name,
$version,
1,
$ctg_length);
#get clone features
my $clone_start = $ctg->embl_offset;
my $clone_end = $clone_start + $ctg_length - 1;
my @clone_features = $self->get_Ensembl_SeqFeatures_clone($clone->id,
$version,
$clone_start,
$clone_end);
#change clone coordinates to contig coordinates
my ($start, $end);
foreach my $f (@clone_features) {
$start = $f->start - $clone_start + 1;
$end = $f->end - $clone_start + 1;
#skip features outside the contig
next if($end < 1 || $start > $ctg_length);
$f->start($start);
$f->end($end);
push @features, $f;
}
return \@features;
}
=head2 get_Ensembl_SeqFeatures_contig
......
......@@ -829,53 +829,115 @@ sub _each_DASFeatureFactory{
##################################################################
=head2 add_ExternalFeatureFactory
Arg [1] : Bio::EnsEMBL::DB::ExternalFeatureFactoryI $value
Example : $db_adaptor->add_ExternalFeatureFactory
Description: Adds an external feature factory to the core database
so that features from external sources can be displayed in
ensembl. This method is still available mainly for legacy
support for external EnsEMBL installations. It should
probably not be used by internal EnsEMBL developers as
there is likely a better way to integrate your data with
the system.
=head2 add_ExternalFeatureAdaptor
Arg [1] : Bio::EnsEMBL::External::ExternalFeatureAdaptor
Example : $db_adaptor->add_ExternalFeatureAdaptor($xfa);
Description: Adds an external feature adaptor to this database adaptor.
Adding the external adaptor in this way allows external
features to be obtained from Slices and from RawContigs.
The external feature adaptor which is passed to this method
will have its db attribuite set to this DBAdaptor object via
the db accessor method.
ExternalFeatureAdaptors passed to this method are stored
internally in a hash keyed on the string returned by the
ExternalFeatureAdaptors track_name method.
If the track name method is not implemented then the
a default key named 'External features' is assigned. In the
event of duplicate key names, a number is appended to the
key name, and incremented for each subsequent adaptor with the
same track name. For example, if no track_names are specified
then the the external feature adaptors will be stored under the
keys 'External features', 'External features2'
'External features3' etc.
Returntype : none
Exceptions : none
Caller : external
Caller : general
=cut
sub add_ExternalFeatureFactory{
my ($self,$value) = @_;
unless( ref $value &&
$value->isa('Bio::EnsEMBL::DB::ExternalFeatureFactoryI') ) {
$self->throw("[$value] is not a " .
"Bio::EnsEMBL::DB::ExternalFeatureFactoryI " .
"but it should be!");
}
sub add_ExternalFeatureAdaptor {
my ($self, $adaptor) = @_;
unless($adaptor && ref $adaptor &&
$adaptor->isa('Bio::EnsEMBL::External::ExternalFeatureAdaptor')) {
$self->throw("[$adaptor] is not a " .
"Bio::EnsEMBL::External::ExternalFeatureAdaptor");
}
unless(exists $self->{'_xf_adaptors'}) {
$self->{'_xf_adaptors'} = {};
}
my $track_name = $adaptor->{'_track_name'};
#use a generic track name if one hasn't been defined
unless(defined $track_name) {
$track_name = "External features";
}
#if the track name exists add numbers to the end until a free name is found
if(exists $self->{'_xf_adaptor'}->{"$track_name"}) {
my $num = 2;
$num++ while(exists $self->{'_xf_adaptor'}->{"$track_name$num"});
$self->{'_xf_adaptors'}->{"$track_name$num"} = $adaptor;
} else {
$self->{'_xf_adaptors'}->{"$track_name"} = $adaptor;
}
push(@{$self->{'_external_ff'}},$value);
$adaptor->db($self);
}
=head2 _each_ExternalFeatureFactory
=head2 get_ExternalFeatureAdaptors
Arg [1] : none
Example : none
Description: PRIVATE included for support of ExternalFeature Factories.
Returns list of external feature factories currently attached.
Returntype : list of Bio::EnsEMBL::DB::ExternalFeatureFactory objects
Example : @xfas = values %{$db_adaptor->get_ExternalFeatureAdaptors};
Description: Retrieves all of the ExternalFeatureAdaptors which have been
added to this DBAdaptor. The ExternalFeatureAdaptors are
returned in a reference to a hash keyed on the track names
of the external adaptors
Returntype : Reference to a hash of ExternalFeatureAdaptors keyed on
their track names.
Exceptions : none
Caller : internal
Caller : general
=cut
sub _each_ExternalFeatureFactory{
my ($self) = @_;
sub get_ExternalFeatureAdaptors {
my $self = shift;
return $self->{'_xf_adaptors'};
}
=head2 add_ExternalFeatureFactory
Arg [1] : Bio::EnsEMBL::DB::ExternalFeatureFactoryI $value
Example : $db_adaptor->add_ExternalFeatureFactory
Description: It is recommended that add_ExternalFeatureAdaptor be used
instead. See documentation for
Bio::EnsEMBL::External::ExternalFeatureAdaptor
Adds an external feature factory to the core database
so that features from external sources can be displayed in
ensembl. This method is still available mainly for legacy
support for external EnsEMBL installations.
Returntype : none
Exceptions : none
Caller : external
=cut
sub add_ExternalFeatureFactory{
my ($self,$value) = @_;
return @{$self->{'_external_ff'}}
$self->add_ExternalFeatureAdaptor($value);
}
......
......@@ -7,7 +7,7 @@
=head1 NAME
Bio::EnsEMBL::External::ExternalFeatureAdaptor - Allows features created externally from EnsEMBL in a single coordinate system to be retrieved in several other (EnsEMBL-style) coordinate systems.
Bio::EnsEMBL::External::ExternalFeatureAdaptor - Allows features created externally from EnsEMBL in a single coordinate system to be retrieved in several other (EnsEMBL-style) coordinate systems. This is intended to be a replacement for the old Bio::EnsEMBL::DB::ExternalFeatureFactoryI interface.
=head1 SYNOPSIS
......@@ -16,7 +16,10 @@ Bio::EnsEMBL::External::ExternalFeatureAdaptor - Allows features created externa
-dbname => 'homo_sapiens_core_9_30',
-pass => 'anonymous' );
$xf_adaptor = new ExternalFeatureAdaptorSubClass($database_adaptor);
$xf_adaptor = new ExternalFeatureAdaptorSubClass;
#explicitly add db, (can be done automatically by add_ExternalFeatureAdaptor)
$xf_adaptor->db($database_adaptor);
#get some features in RawContig coords
@feats = @{$xf_adaptor->fetch_all_by_contig_name('AC000087.2.1.42071')};
......@@ -42,6 +45,15 @@ Bio::EnsEMBL::External::ExternalFeatureAdaptor - Allows features created externa
$slice = $slice_adaptor->fetch_by_chr_start_end(1,100000,200000);
@feats = @{$xf_adaptor->fetch_all_by_Slice($slice)};
#Add the external adaptor to the EnsEMBL system
#this also implicitly adds the dbadaptor so you don't have to call 'db'
$database_adaptor->add_ExternalFeatureAdaptor($xf_adaptor);
#now features can be retrieved directly from slice or RawContig
@feats = @{$slice->get_all_ExternalFeatures};
@feats = @{$contig->get_all_ExternalFeatures};
=head1 DESCRIPTION
This class is intended to be used as a method of getting external features into
......@@ -73,6 +85,20 @@ internal dependencies the fetch_all_by_contig_name and
fetch_all_by_clone_accession must also be overridden if these methods are
altered. See the method descriptions for more detail.
The objects returned by the fetch methods should be Bio::SeqFeature object,
though only the start, end, strand and attach_seq methods are actually used
by the ExternalFeatureAdaptor. The objects which are returned by the
ExternalFeature adaptor will be altered by the functions called.
Before the non-overridden ExternalFeatureAdaptor fetch methods may be called
an EnsEMBL core database adaptor must be attached to the ExternalFeatureAdaptor
. This database adaptor is required to perform the remappings between various
coordinate system. This may be done explicitly through a call to the db
accessor method, or implicitly by adding the ExternalFeatureAdaptor to the
database adaptor through a call to the DBAdaptor add_ExternalFeatureAdaptor
method.
=head1 CONTACT
Post questions to the EnsEMBL developer list: <ensembl-dev@ebi.ac.uk>
......@@ -94,9 +120,56 @@ package Bio::EnsEMBL::External::ExternalFeatureAdaptor;
use vars qw(@ISA);
use Bio::EnsEMBL::DBSQL::BaseAdaptor;
use Bio::EnsEMBL::Root;
@ISA = qw(Bio::EnsEMBL::Root);
=head2 new
Arg [1] : none
Example : $xfa = new Bio::EnsEMBL::External::ExternalFeatureAdaptor;
Description: Creates a new ExternalFeatureAdaptor object. You may wish to
extend this constructor and provide your own set of paremeters.
Returntype : Bio::EnsEMBL::External::ExternalFeatureAdaptor
Exceptions : none
Caller : general
=cut
sub new {
my $class = shift;
if(ref $class) {
return bless {}, ref $class;
}
return bless {}, $class;
}
=head2 db
Arg [1] : (optional) Bio::EnsEMBL::DBSQL::DBAdaptor
Example : $external_feature_adaptor->db($new_val);
Description: none
Returntype : Bio::EnsEMBL::DBSQL::DBAdaptor
Exceptions : none
Caller : internal
=cut
sub db {
my ($self, $value) = @_;
if($value) {
$self->{'db'} = $value;
}
return $self->{'db'};
}
@ISA = qw(Bio::EnsEMBL::DBSQL::BaseAdaptor);
=head2 coordinate_systems
......@@ -124,6 +197,56 @@ sub coordinate_systems {
}
=head2 track_name
Arg [1] : none
Example : $track_name = $xf_adaptor->track_name;
Description: Currently this is not really used. In the future it may be
possible to have ExternalFeatures automatically displayed by
the EnsEMBL web code. By default this method returns
'External features' but you are encouraged to override this
method and provide your own meaningful name for the features
your adaptor provides. This also allows you to distinguish the
type of features retrieved from RawContigs or Slices. See
the PODs for Bio::EnsEMBL::Slice::get_all_ExternalFeatures and
Bio::EnsEMBL::DBSQL::DBAdaptor::add_ExternalFeatureAdaptor
methods.
Returntype : string
Exceptions : none
Caller : Bio::EnsEMBL::DBSQL::DBAdaptor::add_ExternalFeatureAdaptor
=cut
sub track_name {
my $self = shift;
return 'External features';
}
=head2 feature_type
Arg [1] : none
Example : $feature_type = $xf_adaptor->track_name
Description: Currently this is not used. In the future it may be possible
to have ExternalFeatures automatically displayed by the EnsEMBL
web code. This method would then be used do determine the
type of glyphs used to draw the features which are returned
from this external adaptor.
Returntype : string
Exceptions : none
Caller : none
=cut
sub feature_type {
my $self = shift;
return qw(SIMPLE);
}
=head2 fetch_all_by_Slice
......@@ -258,6 +381,10 @@ sub fetch_all_by_RawContig {
$self->_no_valid_coord_system;
}
unless($self->db) {
$self->throw('DB attribute not set. This value must be set for the ' .
'ExternalFeatureAdaptor to function correctly');
}
my $asma = $self->db->get_AssemblyMapperAdaptor;
my $mapper = $asma->fetch_by_type($self->db->assembly_type);
......@@ -343,9 +470,21 @@ sub fetch_all_by_contig_name {
" but fetch_all_by_contig_name is not implemented");
}
unless($self->db) {
$self->throw('DB attribute not set. This value must be set for the ' .
'ExternalFeatureAdaptor to function correctly');
}
my $contig_adaptor = $self->db->get_RawContigAdaptor;
my $contig = $contig_adaptor->fetch_by_name($contig_name);
unless($contig) {
$self->warn("ExternalFeatureAdaptor::fetch_all_by_contig_name: Contig " .
"[$contig_name] not found\n");
return [];
}
return $self->fetch_all_by_RawContig($contig);
}
......@@ -407,6 +546,7 @@ sub fetch_all_by_Clone {
#convert each feature to clone coordinates
$f->start($f->start - $offset + 1);
$f->end($f->end - $offset + 1);
#$f->attach_seq($clone); #this might work in future...
push @$out, $f;
}
}
......@@ -457,9 +597,23 @@ sub fetch_all_by_clone_accession {
'but does not implement fetch_all_by_clone_accession');
}
unless($self->db) {
$self->throw('DB attribute not set. This value must be set for the ' .
'ExternalFeatureAdaptor to function correctly');
}
my $clone_adaptor = $self->db->get_CloneAdaptor;
my $clone = $clone_adaptor->fetch_by_accession($acc);
unless($clone) {
$self->warn("ExternalFeatureAdaptor::fetch_all_by_clone_accession: Clone "
. "[$acc] not found\n");
return [];
}
return $self->fetch_all_by_Clone($clone);
}
......@@ -499,6 +653,11 @@ sub fetch_all_by_chr_start_end {
$self->throw("Incorrect start [$start] end [$end] or chr [$chr_name] arg");
}
unless($self->db) {
$self->throw('DB attribute not set. This value must be set for the ' .
'ExternalFeatureAdaptor to function correctly');
}
my $out = [];
my $asma = $self->db->get_AssemblyMapperAdaptor;
......@@ -511,15 +670,20 @@ sub fetch_all_by_chr_start_end {
}
my $slice_adaptor = $self->db->get_SliceAdaptor;
#get a slice of the whole chromosome
my $chrom_slice = $slice_adaptor->fetch_by_chr_name($chr_name);
if($self->_supported('SLICE')) {
#fetch by slice and convert to assembly coords
my $slice_adaptor = $self->db->get_SliceAdaptor;
my $slice = $slice_adaptor->fetch_by_chr_start_end($chr_name,$start,$end);
$out = $self->fetch_all_by_Slice($slice);
foreach my $f (@$out) {
$f->start($start + $f->start - 1);
$f->end ($start + $f->end - 1);
$f->attach_seq($chrom_slice);
}
return $out;
......@@ -558,6 +722,7 @@ sub fetch_all_by_chr_start_end {
$f->start($m_start);
$f->end($m_end);
$f->strand($m_strand);
$f->attach_seq($chrom_slice);
push @$out, $f;
}
......
......@@ -571,78 +571,47 @@ sub _clone_id {
=head2 get_all_ExternalFeatures
Arg [1] : none
Example : @external = $contig->get_all_ExternalFeatures
Description: retrieves features generated by external feature factories
attached to this database which are on this Contig.
See Bio::EnsEMBL::DB::ExternalFeatureFactoryI for details.
Returntype : list of Bio::SeqFeatureI implementing objects
Arg [1] : (optional) string $track_name
If specified only features from ExternalFeatureAdaptors with
the track name $track_name are retrieved. If not set, all
features from every ExternalFeatureAdaptor are retrieved.
Example : @xfeatures = @{$contig->get_all_ExternalFeatures};
Description: Retrieves features on this contig from external feature adaptors
Returntype : listref of Bio::SeqFeatureI implementing objects in contig
coordinates
Exceptions : none
Caller : external
Caller : general
=cut
sub get_all_ExternalFeatures {
my ($self) = @_;
my ($self, $track_name) = @_;