diff variant_effect_predictor/Bio/EnsEMBL/DBSQL/OperonTranscriptAdaptor.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/DBSQL/OperonTranscriptAdaptor.pm	Thu Apr 11 02:01:53 2013 -0400
@@ -0,0 +1,876 @@
+
+=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
+
+=head1 NAME
+
+Bio::EnsEMBL::DBSQL::OperonAdaptor - Database adaptor for the retrieval and
+storage of OperonTranscript objects
+
+=head1 SYNOPSIS
+
+
+my $operon_transcript_adaptor =  Bio::EnsEMBL::DBSQL::OperonTranscriptAdaptor->new($dba);
+$operon_transcript_adaptor->store($operon_transcript);
+my $operon_transcript2 = $operon_transcript_adaptor->fetch_by_dbID( $operon->dbID() );
+my $operon_transcripts = $operon_transcript_adaptor->fetch_all_by_gene( $gene );
+
+=head1 DESCRIPTION
+
+This is a database aware adaptor for the retrieval and storage of operon
+transcript objects.
+
+=head1 METHODS
+
+=cut
+
+package Bio::EnsEMBL::DBSQL::OperonTranscriptAdaptor;
+
+use strict;
+
+use Bio::EnsEMBL::Utils::Exception qw( deprecate throw warning );
+use Bio::EnsEMBL::Utils::Scalar qw( assert_ref );
+use Bio::EnsEMBL::DBSQL::SliceAdaptor;
+use Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor;
+use Bio::EnsEMBL::DBSQL::DBAdaptor;
+use Bio::EnsEMBL::Operon;
+use Bio::EnsEMBL::OperonTranscript;
+use Bio::EnsEMBL::Utils::SqlHelper;
+
+use vars '@ISA';
+@ISA = qw(Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor);
+
+# _tables
+#  Arg [1]    : none
+#  Description: PROTECTED implementation of superclass abstract method.
+#               Returns the names, aliases of the tables to use for queries.
+#  Returntype : list of listrefs of strings
+#  Exceptions : none
+#  Caller     : interna
+#  Status     : Stable
+
+sub _tables {
+	return ( [ 'operon_transcript', 'o' ] );
+}
+
+# _columns
+#  Arg [1]    : none
+#  Example    : none
+#  Description: PROTECTED implementation of superclass abstract method.
+#               Returns a list of columns to use for queries.
+#  Returntype : list of strings
+#  Exceptions : none
+#  Caller     : internal
+#  Status     : Stable
+
+sub _columns {
+	my ($self) = @_;
+
+	my $created_date =
+	  $self->db()->dbc()->from_date_to_seconds("o.created_date");
+	my $modified_date =
+	  $self->db()->dbc()->from_date_to_seconds("o.modified_date");
+
+	return ( 'o.operon_transcript_id', 'o.seq_region_id',
+			 'o.seq_region_start',     'o.seq_region_end',
+			 'o.seq_region_strand',    'o.display_label',
+			 'o.analysis_id',          'o.stable_id',
+			 'o.version',            $created_date,
+			 $modified_date );
+}
+
+=head2 list_dbIDs
+
+  Example    : @ot_ids = @{$ot_adaptor->list_dbIDs()};
+  Description: Gets an array of internal ids for all operon_transcripts in the current db
+  Arg[1]     : <optional> int. not 0 for the ids to be sorted by the seq_region.
+  Returntype : Listref of Ints
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub list_dbIDs {
+	my ( $self, $ordered ) = @_;
+
+	return $self->_list_dbIDs( "operon_transcript", undef, $ordered );
+}
+
+=head2 list_stable_ids
+
+  Example    : @stable_ot_ids = @{$ot_adaptor->list_stable_ids()};
+  Description: Gets an listref of stable ids for all operon_transcripts in the current db
+  Returntype : reference to a list of strings
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub list_stable_ids {
+	my ($self) = @_;
+
+	return $self->_list_dbIDs( "operon_transcript", "stable_id" );
+}
+
+sub list_seq_region_ids {
+	my $self = shift;
+
+	return $self->_list_seq_region_ids('operon');
+}
+
+=head2 fetch_by_stable_id
+
+  Arg [1]    : String $id 
+               The stable ID of the operon_transcript to retrieve
+  Example    : $operon_transcript = $operon_transcript_adaptor->fetch_by_stable_id('ENSG00000148944');
+  Description: Retrieves a operon_transcript object from the database via its stable id.
+               The operon_transcript will be retrieved in its native coordinate system (i.e.
+               in the coordinate system it is stored in the database). It may
+               be converted to a different coordinate system through a call to
+               transform() or transfer(). If the operon_transcript or exon is not found
+               undef is returned instead.
+  Returntype : Bio::EnsEMBL::OperonTranscript or undef
+  Exceptions : if we cant get the operon_transcript in given coord system
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub fetch_by_stable_id {
+	my ( $self, $stable_id ) = @_;
+
+	my $constraint = "o.stable_id = ?";
+	$self->bind_param_generic_fetch( $stable_id, SQL_VARCHAR );
+	my ($operon_transcript) = @{ $self->generic_fetch($constraint) };
+
+	return $operon_transcript;
+}
+
+=head2 fetch_by_name
+
+  Arg [1]    : String $label - name of operon transcript to fetch
+  Example    : my $operon_transcript = $operonAdaptor->fetch_by_name("ECK0012121342");
+  Description: Returns the operon transcript which has the given display label or undef if
+               there is none. If there are more than 1, only the first is
+               reported.
+  Returntype : Bio::EnsEMBL::OperonTranscript
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub fetch_by_name {
+	my $self  = shift;
+	my $label = shift;
+
+	my $constraint = "o.display_label = ?";
+	$self->bind_param_generic_fetch( $label, SQL_VARCHAR );
+	my ($operon) = @{ $self->generic_fetch($constraint) };
+
+	return $operon;
+}
+
+=head2 fetch_all
+
+  Example     : $operon_transcripts = $operon_adaptor->fetch_all();
+  Description : Retrieves all operon transcripts stored in the database.
+  Returntype  : listref of Bio::EnsEMBL::OperonTranscript
+  Caller      : general
+  Status      : At Risk
+
+=cut
+
+sub fetch_all {
+	my ($self) = @_;
+
+	my $constraint         = '';
+	my @operon_transcripts = @{ $self->generic_fetch($constraint) };
+	return \@operon_transcripts;
+}
+
+=head2 fetch_all_versions_by_stable_id 
+
+  Arg [1]     : String $stable_id 
+                The stable ID of the operon_transcript to retrieve
+  Example     : $operon_transcript = $operon_transcript_adaptor->fetch_all_versions_by_stable_id
+                  ('ENSG00000148944');
+  Description : Similar to fetch_by_stable_id, but retrieves all versions of a
+                operon_transcript stored in the database.
+  Returntype  : listref of Bio::EnsEMBL::OperonTranscript
+  Exceptions  : if we cant get the operon_transcript in given coord system
+  Caller      : general
+  Status      : At Risk
+
+=cut
+
+sub fetch_all_versions_by_stable_id {
+	my ( $self, $stable_id ) = @_;
+
+	my $constraint = "o.stable_id = ?";
+	$self->bind_param_generic_fetch( $stable_id, SQL_VARCHAR );
+	return $self->generic_fetch($constraint);
+}
+
+=head2 fetch_all_by_Slice
+
+  Arg [1]    : Bio::EnsEMBL::Slice $slice
+               The slice to fetch operon_transcripts on.
+  Arg [2]    : (optional) string $logic_name
+               the logic name of the type of features to obtain
+  Arg [3]    : (optional) boolean $load_transcripts
+               if true, transcripts will be loaded immediately rather than
+               lazy loaded later.
+  Arg [4]    : (optional) string $source
+               the source name of the features to obtain.
+  Arg [5]    : (optional) string biotype
+                the biotype of the features to obtain.
+  Example    : @operon_transcripts = @{$operon_transcript_adaptor->fetch_all_by_Slice()};
+  Description: Overrides superclass method to optionally load transcripts
+               immediately rather than lazy-loading them later.  This
+               is more efficient when there are a lot of operon_transcripts whose
+               transcripts are going to be used.
+  Returntype : reference to list of operon_transcripts 
+  Exceptions : thrown if exon cannot be placed on transcript slice
+  Caller     : Slice::get_all_OperonTranscripts
+  Status     : Stable
+
+=cut
+
+sub fetch_all_by_Slice {
+	my ( $self, $slice, $logic_name, $load_transcripts ) = @_;
+
+	my $constraint = '';
+
+	my $operons =
+	  $self->SUPER::fetch_all_by_Slice_constraint( $slice, $constraint,
+												   $logic_name );
+
+	# If there are less than two operons, still do lazy-loading.
+	if ( !$load_transcripts || @$operons < 2 ) {
+		return $operons;
+	}
+
+	# Preload all of the transcripts now, instead of lazy loading later,
+	# faster than one query per transcript.
+
+	# First check if transcripts are already preloaded.
+	# FIXME: Should check all transcripts.
+	if ( exists( $operons->[0]->{'_operon_transcript_array'} ) ) {
+		return $operons;
+	}
+
+	# Get extent of region spanned by transcripts.
+	my ( $min_start, $max_end );
+	foreach my $o (@$operons) {
+		if ( !defined($min_start) || $o->seq_region_start() < $min_start ) {
+			$min_start = $o->seq_region_start();
+		}
+		if ( !defined($max_end) || $o->seq_region_end() > $max_end ) {
+			$max_end = $o->seq_region_end();
+		}
+	}
+
+	my $ext_slice;
+
+	if ( $min_start >= $slice->start() && $max_end <= $slice->end() ) {
+		$ext_slice = $slice;
+	} else {
+		my $sa = $self->db()->get_SliceAdaptor();
+		$ext_slice =
+		  $sa->fetch_by_region( $slice->coord_system->name(),
+								$slice->seq_region_name(),
+								$min_start,
+								$max_end,
+								$slice->strand(),
+								$slice->coord_system->version() );
+	}
+
+	# Associate transcript identifiers with operon_transcripts.
+
+	my %o_hash = map { $_->dbID => $_ } @{$operons};
+
+	my $o_id_str = join( ',', keys(%o_hash) );
+
+	my $sth =
+	  $self->prepare(   "SELECT operon_id, operon_transcript_id "
+					  . "FROM   operon_transcript "
+					  . "WHERE  operon_id IN ($o_id_str)" );
+
+	$sth->execute();
+
+	my ( $o_id, $tr_id );
+	$sth->bind_columns( \( $o_id, $tr_id ) );
+
+	my %tr_o_hash;
+
+	while ( $sth->fetch() ) {
+		$tr_o_hash{$tr_id} = $o_hash{$o_id};
+	}
+
+	my $ta = $self->db()->get_OperonTranscriptAdaptor();
+	my $transcripts =
+	  $ta->fetch_all_by_Slice( $ext_slice,
+							   1, undef,
+							   sprintf( "ot.operon_transcript_id IN (%s)",
+										join( ',',
+											  sort { $a <=> $b }
+												keys(%tr_o_hash) ) ) );
+
+# Move transcripts onto operon_transcript slice, and add them to operon_transcripts.
+	foreach my $tr ( @{$transcripts} ) {
+		if ( !exists( $tr_o_hash{ $tr->dbID() } ) ) { next }
+
+		my $new_tr;
+		if ( $slice != $ext_slice ) {
+			$new_tr = $tr->transfer($slice);
+			if ( !defined($new_tr) ) {
+				throw("Unexpected. "
+					. "Transcript could not be transfered onto OperonTranscript slice."
+				);
+			}
+		} else {
+			$new_tr = $tr;
+		}
+
+		$tr_o_hash{ $tr->dbID() }->add_OperonTranscript($new_tr);
+	}
+
+	return $operons;
+} ## end sub fetch_all_by_Slice
+
+=head2 fetch_by_Operon
+
+  Arg [1]    : Bio::EnsEMBL::Operon
+  Example    : $ot = $ot_adaptor->fetch_by_Operon($operon);
+  Description: Retrieves all operon transcripts belonging to an operon
+  Returntype : arrayref of Bio::EnsEMBL::OperonTranscript
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub fetch_all_by_Operon {
+	my ( $self, $operon ) = @_;
+	return $self->fetch_by_operon_id( $operon->dbID() );
+}
+
+=head2 fetch_by_operon_id
+
+  Arg [1]    : Int id
+  Example    : $ot = $ot_adaptor->fetch_by_operon_transcript($operon);
+  Description: Retrieves all operon transcripts belonging to an operon
+  Returntype : arrayref of Bio::EnsEMBL::OperonTranscript
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub fetch_by_operon_id {
+	my ( $self, $operon_id ) = @_;
+
+	my $constraint = "o.operon_id = ?";
+	$self->bind_param_generic_fetch( $operon_id, SQL_INTEGER );
+	return $self->generic_fetch($constraint);
+}
+
+=head2 fetch_genes_by_operon_transcript
+
+  Arg [1]    : Bio::EnsEMBL::OperonTranscript
+  Example    : $ot = $ot_adaptor->fetch_genes_by_operon_transcript($operon_transcript);
+  Description: Retrieves all genes attached to an operon transcript
+  Returntype : arrayref of Bio::EnsEMBL::Gene
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub fetch_genes_by_operon_transcript {
+	my ( $self, $operon_transcript ) = @_;
+	assert_ref( $operon_transcript, 'Bio::EnsEMBL::OperonTranscript' );
+	return $self->fetch_genes_by_operon_transcript_id(
+												   $operon_transcript->dbID() );
+}
+
+=head2 fetch_genes_by_operon_transcript_id
+
+  Arg [1]    : Int id
+  Example    : $ot = $ot_adaptor->fetch_genes_by_operon_transcript($operon_transcript_id);
+  Description: Retrieves all genes attached to an operon transcript
+  Returntype : arrayref of Bio::EnsEMBL::Gene
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub fetch_genes_by_operon_transcript_id {
+	my ( $self, $operon_transcript_id ) = @_;
+	my $helper =
+	  Bio::EnsEMBL::Utils::SqlHelper->new( -DB_CONNECTION => $self->db->dbc() );
+
+	my $gene_ids =
+	  $helper->execute_simple(
+		-SQL =>
+'SELECT  gene_id FROM operon_transcript_gene tr WHERE  operon_transcript_id =?',
+		-PARAMS => [$operon_transcript_id] );
+
+	my $genes        = [];
+	my $gene_adaptor = $self->db()->get_GeneAdaptor();
+	for my $gene_id (@$gene_ids) {
+		push @$genes, $gene_adaptor->fetch_by_dbID($gene_id);
+	}
+	return $genes;
+}
+
+=head2 fetch_all_by_gene
+
+  Arg [1]    : Bio::EnsEMBL::Gene
+  Example    : $ots = $ot_adaptor->fetch_all_by_gene($gene);
+  Description: Retrieves all operon transcripts attached to a given gene
+  Returntype : arrayref of Bio::EnsEMBL::OperonTranscript
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub fetch_all_by_gene {
+	my ( $self, $gene ) = @_;
+	assert_ref( $gene, 'Bio::EnsEMBL::Gene' );
+	return $self->fetch_all_by_gene_id( $gene->dbID() );
+}
+
+=head2 fetch_all_by_gene_id
+
+  Arg [1]    : Int id of Bio::EnsEMBL::Gene
+  Example    : $ots = $ot_adaptor->fetch_all_by_gene($gene);
+  Description: Retrieves all operon transcripts attached to a given gene
+  Returntype : arrayref of Bio::EnsEMBL::OperonTranscript
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub fetch_all_by_gene_id {
+	my ( $self, $gene_id ) = @_;
+	my $helper =
+	  Bio::EnsEMBL::Utils::SqlHelper->new( -DB_CONNECTION => $self->db->dbc() );
+
+	my $ot_ids = $helper->execute_simple(
+		-SQL =>
+'SELECT operon_transcript_id FROM operon_transcript_gene tr WHERE gene_id =?',
+		-PARAMS => [$gene_id] );
+
+	my $ots = [];
+	for my $ot_id (@$ot_ids) {
+		push @$ots, $self->fetch_by_dbID($ot_id);
+	}
+	return $ots;
+}
+
+=head2 store
+
+  Arg [1]    : Bio::EnsEMBL::OperonTranscript $gene
+               The gene to store in the database
+  Arg [2]    : ignore_release in xrefs [default 1] set to 0 to use release info 
+               in external database references
+  Example    : $gene_adaptor->store($gene);
+  Description: Stores a gene in the database.
+  Returntype : the database identifier (dbID) of the newly stored gene
+  Exceptions : thrown if the $gene is not a Bio::EnsEMBL::OperonTranscript or if 
+               $gene does not have an analysis object
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub store {
+	my ( $self, $operon_transcript, $operon_id ) = @_;
+
+	assert_ref( $operon_transcript, 'Bio::EnsEMBL::OperonTranscript' );
+
+	my $db = $self->db();
+
+	if ( $operon_transcript->is_stored($db) ) {
+		return $operon_transcript->dbID();
+	}
+
+	# ensure coords are correct before storing
+	#$operon->recalculate_coordinates();
+
+	my $seq_region_id;
+
+	( $operon_transcript, $seq_region_id ) =
+	  $self->_pre_store($operon_transcript);
+	my $analysis = $operon_transcript->analysis();
+	throw("OperonTranscripts must have an analysis object.")
+	  if ( !defined($analysis) );
+	my $analysis_id;
+	if ( $analysis->is_stored($db) ) {
+		$analysis_id = $analysis->dbID();
+	} else {
+		$analysis_id = $db->get_AnalysisAdaptor->store($analysis);
+	}
+	my $store_operon_transcript_sql = qq(
+        INSERT INTO operon_transcript
+           SET seq_region_id = ?,
+               seq_region_start = ?,
+               seq_region_end = ?,
+               seq_region_strand = ?,
+               display_label = ?,
+               operon_id = ?,
+               analysis_id =?
+  );
+
+	if ( defined($operon_transcript->stable_id()) ) {
+	    my $created = $self->db->dbc->from_seconds_to_date($operon_transcript->created_date());
+	    my $modified = $self->db->dbc->from_seconds_to_date($operon_transcript->modified_date());
+	    $store_operon_transcript_sql .= ", stable_id = ?, version = ?, created_date = " . $created . ",modified_date = " . $modified;
+	}
+	
+
+	# column status is used from schema version 34 onwards (before it was
+	# confidence)
+
+	my $sth = $self->prepare($store_operon_transcript_sql);
+	$sth->bind_param( 1, $seq_region_id,                      SQL_INTEGER );
+	$sth->bind_param( 2, $operon_transcript->start(),         SQL_INTEGER );
+	$sth->bind_param( 3, $operon_transcript->end(),           SQL_INTEGER );
+	$sth->bind_param( 4, $operon_transcript->strand(),        SQL_TINYINT );
+	$sth->bind_param( 5, $operon_transcript->display_label(), SQL_VARCHAR );
+	$sth->bind_param( 6, $operon_id,                          SQL_INTEGER );
+	$sth->bind_param( 7, $analysis_id,                        SQL_INTEGER );
+
+	if ( defined($operon_transcript->stable_id()) ) {
+	    $sth->bind_param( 8, $operon_transcript->stable_id(), SQL_VARCHAR );
+	    my $version = ($operon_transcript->version()) ? $operon_transcript->version() : 1;
+	    $sth->bind_param( 9, $version, SQL_INTEGER ); 
+	}
+
+	$sth->execute();
+	$sth->finish();
+
+	my $operon_transcript_dbID = $sth->{'mysql_insertid'};
+
+	# store the dbentries associated with this gene
+	my $dbEntryAdaptor = $db->get_DBEntryAdaptor();
+
+	foreach my $dbe ( @{ $operon_transcript->get_all_DBEntries } ) {
+		$dbEntryAdaptor->store( $dbe, $operon_transcript_dbID,
+								"OperonTranscript" );
+	}
+
+	# store operon attributes if there are any
+	my $attrs = $operon_transcript->get_all_Attributes();
+	if ( $attrs && scalar @$attrs ) {
+		my $attr_adaptor = $db->get_AttributeAdaptor();
+		$attr_adaptor->store_on_OperonTranscript( $operon_transcript, $attrs );
+	}
+
+	# set the adaptor and dbID on the original passed in gene not the
+	# transfered copy
+	$operon_transcript->adaptor($self);
+	$operon_transcript->dbID($operon_transcript_dbID);
+
+	if ( defined $operon_transcript->{_gene_array} ) {
+		$self->store_genes_on_OperonTranscript( $operon_transcript,
+											$operon_transcript->{_gene_array} );
+	}
+
+	return $operon_transcript_dbID;
+} ## end sub store
+
+=head2 store_genes_on_OperonTranscript
+
+  Arg [1]    : Bio::EnsEMBL::OperonTranscript $ot
+               the operon_transcript to store genes on
+  Arg [2]    : arrayref of Bio::EnsEMBL::Gene $gene
+               the genes to store on operon transcript
+  Example    : $ot_adaptor->store_genes_on_OperonTranscript(\@genes);
+  Description: Associates genes with operon transcript
+  Returntype : none
+  Exceptions : throw on incorrect arguments 
+               warning if operon_transcript is not stored in this database
+  Caller     : general, store
+  Status     : Stable
+
+=cut
+
+sub store_genes_on_OperonTranscript {
+	my ( $self, $operon_transcript, $genes ) = @_;
+	assert_ref( $operon_transcript, "Bio::EnsEMBL::OperonTranscript" );
+	my $sth = $self->prepare(
+'insert into operon_transcript_gene(operon_transcript_id,gene_id) values('
+		  . $operon_transcript->dbID()
+		  . ',?)' );
+	for my $gene ( @{$genes} ) {
+		assert_ref( $gene, "Bio::EnsEMBL::Gene" );
+		$sth->bind_param( 1, $gene->dbID(), SQL_INTEGER );
+		$sth->execute();
+	}
+	$sth->finish();
+	return;
+}
+
+=head2 remove
+
+  Arg [1]    : Bio::EnsEMBL::OperonTranscript $ot
+               the operon_transcript to remove from the database
+  Example    : $ot_adaptor->remove($ot);
+  Description: Removes a operon transcript completely from the database.
+  Returntype : none
+  Exceptions : throw on incorrect arguments 
+               warning if operon_transcript is not stored in this database
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub remove {
+	my $self              = shift;
+	my $operon_transcript = shift;
+
+	assert_ref( $operon_transcript, 'Bio::EnsEMBL::OperonTranscript' );
+
+	if ( !$operon_transcript->is_stored( $self->db() ) ) {
+		warning(   "Cannot remove operon transcript "
+				 . $operon_transcript->dbID()
+				 . ". Is not stored in "
+				 . "this database." );
+		return;
+	}
+
+	# remove all object xrefs associated with this gene
+
+	my $dbe_adaptor = $self->db()->get_DBEntryAdaptor();
+	foreach my $dbe ( @{ $operon_transcript->get_all_DBEntries() } ) {
+		$dbe_adaptor->remove_from_object( $dbe, $operon_transcript,
+										  'OperonTranscript' );
+	}
+
+	#	# remove the attributes associated with this transcript
+	#	my $attrib_adaptor = $self->db->get_AttributeAdaptor;
+	#	$attrib_adaptor->remove_from_OperonTranscript($operon_transcript);
+
+	# remove from the database
+	my $sth = $self->prepare(
+			   "DELETE FROM operon_transcript WHERE operon_transcript_id = ? ");
+	$sth->bind_param( 1, $operon_transcript->dbID, SQL_INTEGER );
+	$sth->execute();
+	$sth->finish();
+
+	# unset the gene identifier and adaptor thereby flagging it as unstored
+
+	$operon_transcript->dbID(undef);
+	$operon_transcript->adaptor(undef);
+
+	return;
+} ## end sub remove
+
+# _objs_from_sth
+
+#  Arg [1]    : StatementHandle $sth
+#  Arg [2]    : Bio::EnsEMBL::AssemblyMapper $mapper
+#  Arg [3]    : Bio::EnsEMBL::Slice $dest_slice
+#  Description: PROTECTED implementation of abstract superclass method.
+#               responsible for the creation of OperonTranscripts
+#  Returntype : listref of Bio::EnsEMBL::OperonTranscripts in target coordinate system
+#  Exceptions : none
+#  Caller     : internal
+#  Status     : Stable
+
+sub _objs_from_sth {
+	my ( $self, $sth, $mapper, $dest_slice ) = @_;
+
+	#
+	# This code is ugly because an attempt has been made to remove as many
+	# function calls as possible for speed purposes.  Thus many caches and
+	# a fair bit of gymnastics is used.
+	#
+
+	my $sa = $self->db()->get_SliceAdaptor();
+	my $aa = $self->db->get_AnalysisAdaptor();
+
+	my @operons;
+	my %analysis_hash;
+	my %slice_hash;
+	my %sr_name_hash;
+	my %sr_cs_hash;
+	my ( $stable_id, $version, $created_date, $modified_date );
+
+	my ( $operon_transcript_id, $seq_region_id,     $seq_region_start,
+		 $seq_region_end,       $seq_region_strand, $display_label,
+		 $analysis_id );
+
+	$sth->bind_columns( \$operon_transcript_id, \$seq_region_id,
+						\$seq_region_start,     \$seq_region_end,
+						\$seq_region_strand,    \$display_label,
+						\$analysis_id,          \$stable_id,
+						\$version,              \$created_date,
+						\$modified_date );
+
+	my $asm_cs;
+	my $cmp_cs;
+	my $asm_cs_vers;
+	my $asm_cs_name;
+	my $cmp_cs_vers;
+	my $cmp_cs_name;
+	if ($mapper) {
+		$asm_cs      = $mapper->assembled_CoordSystem();
+		$cmp_cs      = $mapper->component_CoordSystem();
+		$asm_cs_name = $asm_cs->name();
+		$asm_cs_vers = $asm_cs->version();
+		$cmp_cs_name = $cmp_cs->name();
+		$cmp_cs_vers = $cmp_cs->version();
+	}
+
+	my $dest_slice_start;
+	my $dest_slice_end;
+	my $dest_slice_strand;
+	my $dest_slice_length;
+	my $dest_slice_sr_name;
+	my $dest_slice_seq_region_id;
+	if ($dest_slice) {
+		$dest_slice_start         = $dest_slice->start();
+		$dest_slice_end           = $dest_slice->end();
+		$dest_slice_strand        = $dest_slice->strand();
+		$dest_slice_length        = $dest_slice->length();
+		$dest_slice_sr_name       = $dest_slice->seq_region_name();
+		$dest_slice_seq_region_id = $dest_slice->get_seq_region_id();
+	}
+
+	my $count = 0;
+  OPERON: while ( $sth->fetch() ) {
+		$count++;
+		#    #get the analysis object
+		my $analysis = $analysis_hash{$analysis_id} ||=
+		  $aa->fetch_by_dbID($analysis_id);
+		$analysis_hash{$analysis_id} = $analysis;
+		#need to get the internal_seq_region, if present
+		$seq_region_id = $self->get_seq_region_id_internal($seq_region_id);
+		#get the slice object
+		my $slice = $slice_hash{ "ID:" . $seq_region_id };
+
+		if ( !$slice ) {
+			$slice = $sa->fetch_by_seq_region_id($seq_region_id);
+			$slice_hash{ "ID:" . $seq_region_id } = $slice;
+			$sr_name_hash{$seq_region_id}         = $slice->seq_region_name();
+			$sr_cs_hash{$seq_region_id}           = $slice->coord_system();
+		}
+
+		my $sr_name = $sr_name_hash{$seq_region_id};
+		my $sr_cs   = $sr_cs_hash{$seq_region_id};
+		#
+		# remap the feature coordinates to another coord system
+		# if a mapper was provided
+		#
+		if ($mapper) {
+
+		    if (defined $dest_slice && $mapper->isa('Bio::EnsEMBL::ChainedAssemblyMapper')  ) {
+			( $seq_region_id,  $seq_region_start,
+			  $seq_region_end, $seq_region_strand )
+			    =
+			    $mapper->map( $sr_name, $seq_region_start, $seq_region_end,
+					  $seq_region_strand, $sr_cs, 1, $dest_slice);
+
+		    } else {
+
+			( $seq_region_id,  $seq_region_start,
+			  $seq_region_end, $seq_region_strand )
+			    =
+			    $mapper->fastmap( $sr_name, $seq_region_start, $seq_region_end,
+					      $seq_region_strand, $sr_cs );
+		    }
+
+		
+			#skip features that map to gaps or coord system boundaries
+			next OPERON if ( !defined($seq_region_id) );
+
+			#get a slice in the coord system we just mapped to
+			if ( $asm_cs == $sr_cs
+				 || ( $cmp_cs != $sr_cs && $asm_cs->equals($sr_cs) ) )
+			{
+				$slice = $slice_hash{ "ID:" . $seq_region_id } ||=
+				  $sa->fetch_by_seq_region_id($seq_region_id);
+			} else {
+				$slice = $slice_hash{ "ID:" . $seq_region_id } ||=
+				  $sa->fetch_by_seq_region_id($seq_region_id);
+			}
+		}
+
+	   #
+	   # If a destination slice was provided convert the coords
+	   # If the dest_slice starts at 1 and is foward strand, nothing needs doing
+	   #
+		if ($dest_slice) {
+			if ( $dest_slice_start != 1 || $dest_slice_strand != 1 ) {
+				if ( $dest_slice_strand == 1 ) {
+					$seq_region_start =
+					  $seq_region_start - $dest_slice_start + 1;
+					$seq_region_end = $seq_region_end - $dest_slice_start + 1;
+				} else {
+					my $tmp_seq_region_start = $seq_region_start;
+					$seq_region_start = $dest_slice_end - $seq_region_end + 1;
+					$seq_region_end =
+					  $dest_slice_end - $tmp_seq_region_start + 1;
+					$seq_region_strand *= -1;
+				}
+			}
+
+			#throw away features off the end of the requested slice
+			if (    $seq_region_end < 1
+				 || $seq_region_start > $dest_slice_length
+				 || ( $dest_slice_seq_region_id != $seq_region_id ) )
+			{
+#	print STDERR "IGNORED DUE TO CUTOFF  $dest_slice_seq_region_id ne $seq_region_id . $sr_name\n";
+				next OPERON;
+			}
+			$slice = $dest_slice;
+		} ## end if ($dest_slice)
+
+		push( @operons,
+			  Bio::EnsEMBL::OperonTranscript->new(
+									  -START         => $seq_region_start,
+									  -END           => $seq_region_end,
+									  -STRAND        => $seq_region_strand,
+									  -SLICE         => $slice,
+									  -DISPLAY_LABEL => $display_label,
+									  -ADAPTOR       => $self,
+									  -DBID          => $operon_transcript_id,
+									  -STABLE_ID     => $stable_id,
+									  -VERSION       => $version,
+									  -CREATED_DATE  => $created_date || undef,
+									  -MODIFIED_DATE => $modified_date || undef,
+									  -ANALYSIS      => $analysis ) );
+
+	} ## end while ( $sth->fetch() )
+
+	return \@operons;
+} ## end sub _objs_from_sth
+
+1;
+