Archive Ensembl HomeArchive Ensembl Home
PredictionExonAdaptor.pm
Go to the documentation of this file.
00001 =head1 LICENSE
00002 
00003   Copyright (c) 1999-2012 The European Bioinformatics Institute and
00004   Genome Research Limited.  All rights reserved.
00005 
00006   This software is distributed under a modified Apache license.
00007   For license details, please see
00008 
00009     http://www.ensembl.org/info/about/code_licence.html
00010 
00011 =head1 CONTACT
00012 
00013   Please email comments or questions to the public Ensembl
00014   developers list at <dev@ensembl.org>.
00015 
00016   Questions may also be sent to the Ensembl help desk at
00017   <helpdesk@ensembl.org>.
00018 
00019 =cut
00020 
00021 =head1 NAME
00022 
00023 Bio::EnsEMBL::DBSQL::PredictionExonAdaptor - Performs database interaction for
00024 PredictionExons.
00025 
00026 =head1 SYNOPSIS
00027 
00028   $pea   = $database_adaptor->get_PredictionExonAdaptor();
00029   $pexon = $pea->fetch_by_dbID();
00030 
00031   my $slice =
00032     $database_adaptor->get_SliceAdaptor->fetch_by_region( 'X', 1, 1e6 );
00033 
00034   my @pexons = @{ $pea->fetch_all_by_Slice($slice) };
00035 
00036 =head1 METHODS
00037 
00038 =cut
00039 
00040 package Bio::EnsEMBL::DBSQL::PredictionExonAdaptor;
00041 
00042 use vars qw( @ISA );
00043 use strict;
00044 
00045 
00046 use Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor;
00047 use Bio::EnsEMBL::PredictionExon;
00048 use Bio::EnsEMBL::Utils::Exception qw( warning throw deprecate );
00049 
00050 
00051 @ISA = qw( Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor );
00052 
00053 
00054 #_tables
00055 #
00056 #  Arg [1]    : none
00057 #  Example    : none
00058 #  Description: PROTECTED implementation of superclass abstract method
00059 #               returns the names, aliases of the tables to use for queries
00060 #  Returntype : list of listrefs of strings
00061 #  Exceptions : none
00062 #  Caller     : internal
00063 #
00064 
00065 sub _tables {
00066   return ([ 'prediction_exon', 'pe' ] );
00067 }
00068 
00069 
00070 
00071 #_columns
00072 #
00073 #  Arg [1]    : none
00074 #  Example    : none
00075 #  Description: PROTECTED implementation of superclass abstract method
00076 #               returns a list of columns to use for queries
00077 #  Returntype : list of strings
00078 #  Exceptions : none
00079 #  Caller     : internal
00080 
00081 sub _columns {
00082   my $self = shift;
00083 
00084   return qw( pe.prediction_exon_id
00085              pe.seq_region_id
00086              pe.seq_region_start
00087              pe.seq_region_end
00088              pe.seq_region_strand
00089              pe.start_phase
00090              pe.score
00091              pe.p_value );
00092 }
00093 
00094 
00095 # _final_clause
00096 #
00097 #  Arg [1]    : none
00098 #  Example    : none
00099 #  Description: PROTECTED implementation of superclass abstract method
00100 #               returns a default end for the SQL-query (ORDER BY)
00101 #  Returntype : string
00102 #  Exceptions : none
00103 #  Caller     : internal
00104 
00105 sub _final_clause {
00106   return "ORDER BY pe.prediction_transcript_id, pe.exon_rank";
00107 }
00108 
00109 
00110 =head2 fetch_all_by_PredictionTranscript
00111 
00112   Arg [1]    : Bio::EnsEMBL::PredcitionTranscript $transcript
00113   Example    : none
00114   Description: Retrieves all Exons for the Transcript in 5-3 order
00115   Returntype : listref Bio::EnsEMBL::Exon on Transcript slice 
00116   Exceptions : throws if transcript does not have a slice
00117   Caller     : Transcript->get_all_Exons()
00118   Status     : Stable
00119 
00120 =cut
00121 
00122 sub fetch_all_by_PredictionTranscript {
00123   my ( $self, $transcript ) = @_;
00124   my $constraint = "pe.prediction_transcript_id = ".$transcript->dbID();
00125 
00126   # use 'keep_all' option to keep exons that are off end of slice
00127 
00128   my $tslice = $transcript->slice();
00129   my $slice;
00130 
00131   if(!$tslice) {
00132     throw("Transcript must have attached slice to retrieve exons.");
00133   }
00134 
00135   # use a small slice the same size as the prediction transcript
00136   $slice = $self->db->get_SliceAdaptor->fetch_by_Feature($transcript);
00137 
00138   my $exons = $self->fetch_all_by_Slice_constraint($slice, $constraint);
00139 
00140   # remap exon coordinates if necessary
00141   if($slice->name() ne $tslice->name()) {
00142     my @out;
00143     foreach my $ex (@$exons) {
00144       push @out, $ex->transfer($tslice);
00145     }
00146     $exons = \@out;
00147   }
00148 
00149   return $exons;
00150 }
00151 
00152 
00153 
00154 =head2 store
00155 
00156   Arg [1]    : Bio::EnsEMBL::PredictionExon $exon
00157                The exon to store in this database
00158   Arg [2]    : int $prediction_transcript_id
00159                The internal identifier of the prediction exon that that this
00160                exon is associated with.
00161   Arg [3]    : int $rank
00162                The rank of the exon in the transcript (starting at 1)
00163   Example    : $pexon_adaptor->store($pexon, 1211, 2);
00164   Description: Stores a PredictionExon in the database
00165   Returntype : none
00166   Exceptions : thrown if exon does not have a slice attached
00167                or if $exon->start, $exon->end, $exon->strand, or $exon->phase 
00168                are not defined or if $exon is not a Bio::EnsEMBL::PredictionExon 
00169   Caller     : general
00170   Status     : Stable
00171 
00172 =cut
00173 
00174 sub store {
00175   my ( $self, $pexon, $pt_id, $rank ) = @_;
00176 
00177   if(!ref($pexon) || !$pexon->isa('Bio::EnsEMBL::PredictionExon') ) {
00178     throw("Expected PredictionExon argument");
00179   }
00180 
00181   throw("Expected PredictionTranscript id argument.") if(!$pt_id);
00182   throw("Expected rank argument.") if(!$rank);
00183 
00184   my $db = $self->db();
00185 
00186   if($pexon->is_stored($db)) {
00187     warning('PredictionExon is already stored in this DB.');
00188     return $pexon->dbID();
00189   }
00190 
00191   if( ! $pexon->start || ! $pexon->end ||
00192       ! $pexon->strand || ! defined $pexon->phase ) {
00193     throw("PredictionExon does not have all attributes to store.\n" .
00194          "start, end, strand and phase attributes must be set.");
00195   }
00196 
00197   #maintain reference to original passed-in prediction exon
00198   my $original = $pexon;
00199   my $seq_region_id;
00200   ($pexon, $seq_region_id) = $self->_pre_store($pexon);
00201 
00202   my $sth = $db->dbc->prepare
00203     ("INSERT into prediction_exon (prediction_transcript_id, exon_rank, " .
00204                        "seq_region_id, seq_region_start, seq_region_end, " .
00205                        "seq_region_strand, start_phase, score, p_value) " .
00206       "VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? )");
00207 
00208   $sth->bind_param(1,$pt_id,SQL_INTEGER);
00209   $sth->bind_param(2,$rank,SQL_SMALLINT);
00210   $sth->bind_param(3,$seq_region_id,SQL_INTEGER);
00211   $sth->bind_param(4,$pexon->start,SQL_INTEGER);
00212   $sth->bind_param(5,$pexon->end,SQL_INTEGER);
00213   $sth->bind_param(6,$pexon->strand,SQL_TINYINT);
00214   $sth->bind_param(7,$pexon->phase,SQL_TINYINT);
00215   $sth->bind_param(8,$pexon->score,SQL_DOUBLE);
00216   $sth->bind_param(9,$pexon->p_value,SQL_DOUBLE);
00217 
00218   $sth->execute();
00219 
00220   my $dbID = $sth->{'mysql_insertid'};
00221 
00222   #set the adaptor and dbID of the object they passed in
00223   $original->dbID($dbID);
00224   $original->adaptor($self);
00225 
00226   return $dbID;
00227 }
00228 
00229 
00230 
00231 =head2 remove
00232 
00233   Arg [1]    : Bio::EnsEMBL::PredictionExon $exon
00234                the exon to remove from the database 
00235   Example    : $exon_adaptor->remove($exon);
00236   Description: Removes an exon from the database
00237   Returntype : none
00238   Exceptions : none
00239   Caller     : general
00240   Status     : Stable
00241 
00242 =cut
00243 
00244 sub remove {
00245   my $self = shift;
00246   my $pexon = shift;
00247 
00248   my $db = $self->db();
00249 
00250   if(!$pexon->is_stored($db)) {
00251     warning('PredictionExon is not in this DB - not removing');
00252     return undef;
00253   }
00254 
00255   my $sth = $self->prepare(
00256             "DELETE FROM prediction_exon WHERE prediction_exon_id = ?");
00257   $sth->bind_param( 1, $pexon->dbID, SQL_INTEGER );
00258   $sth->execute();
00259 
00260   $pexon->dbID(undef);
00261   $pexon->adaptor(undef);
00262 }
00263 
00264 
00265 
00266 =head2 list_dbIDs
00267 
00268   Arg [1]    : none
00269   Example    : @exon_ids = @{$exon_adaptor->list_dbIDs()};
00270   Description: Gets an array of internal ids for all exons in the current db
00271   Arg[1]     : <optional> int. not 0 for the ids to be sorted by the seq_region.
00272   Returntype : list of ints
00273   Exceptions : none
00274   Caller     : ?
00275   Status     : Stable
00276 
00277 =cut
00278 
00279 sub list_dbIDs {
00280    my ($self,$ordered) = @_;
00281 
00282    return $self->_list_dbIDs("prediction_exon",undef, $ordered);
00283 }
00284 
00285 
00286 
00287 #_objs_from_sth
00288 
00289 #  Arg [1]    : Hashreference $hashref
00290 #  Example    : none 
00291 #  Description: PROTECTED implementation of abstract superclass method.
00292 #               responsible for the creation of Genes 
00293 #  Returntype : listref of Bio::EnsEMBL::Genes in target coordinate system
00294 #  Exceptions : none
00295 #  Caller     : internal
00296 #
00297 
00298 sub _objs_from_sth {
00299   my ($self, $sth, $mapper, $dest_slice) = @_;
00300 
00301   #
00302   # This code is ugly because an attempt has been made to remove as many
00303   # function calls as possible for speed purposes.  Thus many caches and
00304   # a fair bit of gymnastics is used.
00305   #
00306   my $sa = $self->db()->get_SliceAdaptor();
00307 
00308   my @exons;
00309   my %slice_hash;
00310   my %sr_name_hash;
00311   my %sr_cs_hash;
00312 
00313   my($prediction_exon_id,$seq_region_id,
00314      $seq_region_start, $seq_region_end, $seq_region_strand,
00315      $start_phase, $score, $p_value);
00316 
00317   $sth->bind_columns(\$prediction_exon_id,\$seq_region_id,
00318      \$seq_region_start, \$seq_region_end, \$seq_region_strand,
00319      \$start_phase, \$score, \$p_value);
00320 
00321   my $asm_cs;
00322   my $cmp_cs;
00323   my $asm_cs_vers;
00324   my $asm_cs_name;
00325   my $cmp_cs_vers;
00326   my $cmp_cs_name;
00327   if($mapper) {
00328     $asm_cs = $mapper->assembled_CoordSystem();
00329     $cmp_cs = $mapper->component_CoordSystem();
00330     $asm_cs_name = $asm_cs->name();
00331     $asm_cs_vers = $asm_cs->version();
00332     $cmp_cs_name = $cmp_cs->name();
00333     $cmp_cs_vers = $cmp_cs->version();
00334   }
00335 
00336   my $dest_slice_start;
00337   my $dest_slice_end;
00338   my $dest_slice_strand;
00339   my $dest_slice_length;
00340   my $dest_slice_cs;
00341   my $asma;
00342   my $dest_slice_sr_name;
00343   my $dest_slice_sr_id;
00344  
00345   if($dest_slice) {
00346     $dest_slice_start  = $dest_slice->start();
00347     $dest_slice_end    = $dest_slice->end();
00348     $dest_slice_strand = $dest_slice->strand();
00349     $dest_slice_length = $dest_slice->length();
00350     $dest_slice_cs = $dest_slice->coord_system;
00351     $dest_slice_sr_name = $dest_slice->seq_region_name();
00352     $dest_slice_sr_id =  $dest_slice->get_seq_region_id();
00353     $asma = $self->db->get_AssemblyMapperAdaptor();
00354   }
00355 
00356   FEATURE: while($sth->fetch()) {
00357     #need to get the internal_seq_region, if present
00358     $seq_region_id = $self->get_seq_region_id_internal($seq_region_id);
00359     my $slice = $slice_hash{"ID:".$seq_region_id};
00360     my $dest_mapper = $mapper;
00361 
00362 
00363     if(!$slice) {
00364       $slice = $sa->fetch_by_seq_region_id($seq_region_id);
00365       $slice_hash{"ID:".$seq_region_id} = $slice;
00366       $sr_name_hash{$seq_region_id} = $slice->seq_region_name();
00367       $sr_cs_hash{$seq_region_id} = $slice->coord_system();
00368     }
00369 
00370     #obtain a mapper if none was defined, but a dest_seq_region was
00371     if(!$dest_mapper && $dest_slice && 
00372        !$dest_slice_cs->equals($slice->coord_system)) {
00373       $dest_mapper = $asma->fetch_by_CoordSystems($dest_slice_cs,
00374                                                  $slice->coord_system);
00375       $asm_cs = $dest_mapper->assembled_CoordSystem();
00376       $cmp_cs = $dest_mapper->component_CoordSystem();
00377       $asm_cs_name = $asm_cs->name();
00378       $asm_cs_vers = $asm_cs->version();
00379       $cmp_cs_name = $cmp_cs->name();
00380       $cmp_cs_vers = $cmp_cs->version();
00381     }
00382 
00383     my $sr_name = $sr_name_hash{$seq_region_id};
00384     my $sr_cs   = $sr_cs_hash{$seq_region_id};
00385   
00386     #
00387     # remap the feature coordinates to another coord system 
00388     # if a mapper was provided
00389     #
00390     if($dest_mapper) {
00391 
00392       ($seq_region_id,$seq_region_start,$seq_region_end,$seq_region_strand) =
00393         $dest_mapper->fastmap($sr_name, $seq_region_start, $seq_region_end,
00394                               $seq_region_strand, $sr_cs);
00395 
00396       #skip features that map to gaps or coord system boundaries
00397       next FEATURE if(!defined($seq_region_id));
00398 
00399       #get a slice in the coord system we just mapped to
00400 #      if($asm_cs == $sr_cs || ($cmp_cs != $sr_cs && $asm_cs->equals($sr_cs))) {
00401         $slice = $slice_hash{"ID:".$seq_region_id} ||=
00402           $sa->fetch_by_seq_region_id($seq_region_id);
00403 #      } else {
00404 #        $slice = $slice_hash{"NAME:$sr_name:$asm_cs_name:$asm_cs_vers"} ||=
00405 #          $sa->fetch_by_region($asm_cs_name, $sr_name, undef, undef, undef,
00406 #                               $asm_cs_vers);
00407 #      }
00408     } 
00409 
00410     #
00411     # If a destination slice was provided convert the coords
00412     # If the dest_slice starts at 1 and is foward strand, nothing needs doing
00413     #
00414     if($dest_slice) {
00415       if($dest_slice_start != 1 || $dest_slice_strand != 1) {
00416     if($dest_slice_strand == 1) {
00417       $seq_region_start = $seq_region_start - $dest_slice_start + 1;
00418       $seq_region_end   = $seq_region_end   - $dest_slice_start + 1;
00419     } else {
00420       my $tmp_seq_region_start = $seq_region_start;
00421       $seq_region_start = $dest_slice_end - $seq_region_end + 1;
00422       $seq_region_end   = $dest_slice_end - $tmp_seq_region_start + 1;
00423       $seq_region_strand *= -1;
00424     }
00425       }
00426 
00427       #throw away features off the end of the requested slice
00428       if($seq_region_end < 1 || $seq_region_start > $dest_slice_length ||
00429      ( $dest_slice_sr_id ne $seq_region_id )) {
00430     next FEATURE;
00431       }
00432       
00433       $slice = $dest_slice;
00434     }
00435 
00436     # Finally, create the new PredictionExon.
00437     push( @exons,
00438           $self->_create_feature( 'Bio::EnsEMBL::PredictionExon', {
00439                                     '-start'   => $seq_region_start,
00440                                     '-end'     => $seq_region_end,
00441                                     '-strand'  => $seq_region_strand,
00442                                     '-adaptor' => $self,
00443                                     '-slice'   => $slice,
00444                                     '-dbID'    => $prediction_exon_id,
00445                                     '-phase'   => $start_phase,
00446                                     '-score'   => $score,
00447                                     '-p_value' => $p_value
00448                                   } ) );
00449 
00450   }
00451 
00452   return \@exons;
00453 }
00454 
00455 
00456 1;