ensembl-hive  2.7.0
PredictionExonAdaptor.pm
Go to the documentation of this file.
1 =head1 LICENSE
2 
3 See the NOTICE file distributed with this work for additional information
4 regarding copyright ownership.
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 =cut
19 
20 
21 =head1 CONTACT
22 
23  Please email comments or questions to the public Ensembl
24  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.
25 
26  Questions may also be sent to the Ensembl help desk at
27  <http://www.ensembl.org/Help/Contact>.
28 
29 =cut
30 
31 =head1 NAME
32 
33 Bio::EnsEMBL::DBSQL::PredictionExonAdaptor - Performs database interaction for
34 PredictionExons.
35 
36 =head1 SYNOPSIS
37 
38  $pea = $database_adaptor->get_PredictionExonAdaptor();
39  $pexon = $pea->fetch_by_dbID();
40 
41  my $slice =
42  $database_adaptor->get_SliceAdaptor->fetch_by_region( 'X', 1, 1e6 );
43 
44  my @pexons = @{ $pea->fetch_all_by_Slice($slice) };
45 
46 =head1 METHODS
47 
48 =cut
49 
50 package Bio::EnsEMBL::DBSQL::PredictionExonAdaptor;
51 
52 use vars qw( @ISA );
53 use strict;
54 
55 
58 use Bio::EnsEMBL::Utils::Exception qw( warning throw );
59 
60 
62 
63 
64 #_tables
65 #
66 # Arg [1] : none
67 # Example : none
68 # Description: PROTECTED implementation of superclass abstract method
69 # returns the names, aliases of the tables to use for queries
70 # Returntype : list of listrefs of strings
71 # Exceptions : none
72 # Caller : internal
73 #
74 
75 sub _tables {
76  return ([ 'prediction_exon', 'pe' ] );
77 }
78 
79 
80 
81 #_columns
82 #
83 # Arg [1] : none
84 # Example : none
85 # Description: PROTECTED implementation of superclass abstract method
86 # returns a list of columns to use for queries
87 # Returntype : list of strings
88 # Exceptions : none
89 # Caller : internal
90 
91 sub _columns {
92  my $self = shift;
93 
94  return qw( pe.prediction_exon_id
95  pe.seq_region_id
96  pe.seq_region_start
97  pe.seq_region_end
98  pe.seq_region_strand
99  pe.start_phase
100  pe.score
101  pe.p_value );
102 }
103 
104 
105 # _final_clause
106 #
107 # Arg [1] : none
108 # Example : none
109 # Description: PROTECTED implementation of superclass abstract method
110 # returns a default end for the SQL-query (ORDER BY)
111 # Returntype : string
112 # Exceptions : none
113 # Caller : internal
114 
115 sub _final_clause {
116  return "ORDER BY pe.prediction_transcript_id, pe.exon_rank";
117 }
118 
119 
120 =head2 fetch_all_by_PredictionTranscript
121 
122  Arg [1] : Bio::EnsEMBL::PredcitionTranscript $transcript
123  Example : none
124  Description: Retrieves all Exons for the Transcript in 5-3 order
125  Returntype : listref Bio::EnsEMBL::Exon on Transcript slice
126  Exceptions : throws if transcript does not have a slice
127  Caller : Transcript->get_all_Exons()
128  Status : Stable
129 
130 =cut
131 
132 sub fetch_all_by_PredictionTranscript {
133  my ( $self, $transcript ) = @_;
134  my $constraint = "pe.prediction_transcript_id = ".$transcript->dbID();
135 
136  # use 'keep_all' option to keep exons that are off end of slice
137 
138  my $tslice = $transcript->slice();
139  my $slice;
140 
141  if(!$tslice) {
142  throw("Transcript must have attached slice to retrieve exons.");
143  }
144 
145  # use a small slice the same size as the prediction transcript
146  $slice = $self->db->get_SliceAdaptor->fetch_by_Feature($transcript);
147 
148  my $exons = $self->fetch_all_by_Slice_constraint($slice, $constraint);
149 
150  # remap exon coordinates if necessary
151  if($slice->name() ne $tslice->name()) {
152  my @out;
153  foreach my $ex (@$exons) {
154  push @out, $ex->transfer($tslice);
155  }
156  $exons = \@out;
157  }
158 
159  return $exons;
160 }
161 
162 
163 
164 =head2 store
165 
166  Arg [1] : Bio::EnsEMBL::PredictionExon $exon
167  The exon to store in this database
168  Arg [2] : int $prediction_transcript_id
169  The internal identifier of the prediction exon that that this
170  exon is associated with.
171  Arg [3] : int $rank
172  The rank of the exon in the transcript (starting at 1)
173  Example : $pexon_adaptor->store($pexon, 1211, 2);
174  Description: Stores a PredictionExon in the database
175  Returntype : none
176  Exceptions : thrown if exon does not have a slice attached
177  or if $exon->start, $exon->end, $exon->strand, or $exon->phase
178  are not defined or if $exon is not a Bio::EnsEMBL::PredictionExon
179  Caller : general
180  Status : Stable
181 
182 =cut
183 
184 sub store {
185  my ( $self, $pexon, $pt_id, $rank ) = @_;
186 
187  if(!ref($pexon) || !$pexon->isa('Bio::EnsEMBL::PredictionExon') ) {
188  throw("Expected PredictionExon argument");
189  }
190 
191  throw("Expected PredictionTranscript id argument.") if(!$pt_id);
192  throw("Expected rank argument.") if(!$rank);
193 
194  my $db = $self->db();
195 
196  if($pexon->is_stored($db)) {
197  warning('PredictionExon is already stored in this DB.');
198  return $pexon->dbID();
199  }
200 
201  if( ! $pexon->start || ! $pexon->end ||
202  ! $pexon->strand || ! defined $pexon->phase ) {
203  throw("PredictionExon does not have all attributes to store.\n" .
204  "start, end, strand and phase attributes must be set.");
205  }
206 
207  #maintain reference to original passed-in prediction exon
208  my $original = $pexon;
209  my $seq_region_id;
210  ($pexon, $seq_region_id) = $self->_pre_store($pexon);
211 
212  my $sth = $db->dbc->prepare
213  ("INSERT into prediction_exon (prediction_transcript_id, exon_rank, " .
214  "seq_region_id, seq_region_start, seq_region_end, " .
215  "seq_region_strand, start_phase, score, p_value) " .
216  "VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? )");
217 
218  $sth->bind_param(1,$pt_id,SQL_INTEGER);
219  $sth->bind_param(2,$rank,SQL_SMALLINT);
220  $sth->bind_param(3,$seq_region_id,SQL_INTEGER);
221  $sth->bind_param(4,$pexon->start,SQL_INTEGER);
222  $sth->bind_param(5,$pexon->end,SQL_INTEGER);
223  $sth->bind_param(6,$pexon->strand,SQL_TINYINT);
224  $sth->bind_param(7,$pexon->phase,SQL_TINYINT);
225  $sth->bind_param(8,$pexon->score,SQL_DOUBLE);
226  $sth->bind_param(9,$pexon->p_value,SQL_DOUBLE);
227 
228  $sth->execute();
229 
230  my $dbID = $self->last_insert_id('prediction_transcript_id', undef, 'prediction_transcript');
231 
232  #set the adaptor and dbID of the object they passed in
233  $original->dbID($dbID);
234  $original->adaptor($self);
235 
236  return $dbID;
237 }
238 
239 
240 
241 =head2 remove
242 
243  Arg [1] : Bio::EnsEMBL::PredictionExon $exon
244  the exon to remove from the database
245  Example : $exon_adaptor->remove($exon);
246  Description: Removes an exon from the database
247  Returntype : none
248  Exceptions : none
249  Caller : general
250  Status : Stable
251 
252 =cut
253 
254 sub remove {
255  my $self = shift;
256  my $pexon = shift;
257 
258  my $db = $self->db();
259 
260  if(!$pexon->is_stored($db)) {
261  warning('PredictionExon is not in this DB - not removing');
262  return undef;
263  }
264 
265  my $sth = $self->prepare(
266  "DELETE FROM prediction_exon WHERE prediction_exon_id = ?");
267  $sth->bind_param( 1, $pexon->dbID, SQL_INTEGER );
268  $sth->execute();
269 
270  $pexon->dbID(undef);
271  $pexon->adaptor(undef);
272 }
273 
274 
275 
276 =head2 list_dbIDs
277 
278  Arg [1] : none
279  Example : @exon_ids = @{$exon_adaptor->list_dbIDs()};
280  Description: Gets an array of internal ids for all exons in the current db
281  Arg[1] : <optional> int. not 0 for the ids to be sorted by the seq_region.
282  Returntype : list of ints
283  Exceptions : none
284  Caller : ?
285  Status : Stable
286 
287 =cut
288 
289 sub list_dbIDs {
290  my ($self,$ordered) = @_;
291 
292  return $self->_list_dbIDs("prediction_exon",undef, $ordered);
293 }
294 
295 
296 
297 #_objs_from_sth
298 
299 # Arg [1] : Hashreference $hashref
300 # Example : none
301 # Description: PROTECTED implementation of abstract superclass method.
302 # responsible for the creation of Genes
303 # Returntype : listref of Bio::EnsEMBL::Genes in target coordinate system
304 # Exceptions : none
305 # Caller : internal
306 #
307 
308 sub _objs_from_sth {
309  my ($self, $sth, $mapper, $dest_slice) = @_;
310 
311  #
312  # This code is ugly because an attempt has been made to remove as many
313  # function calls as possible for speed purposes. Thus many caches and
314  # a fair bit of gymnastics is used.
315  #
316  my $sa = $self->db()->get_SliceAdaptor();
317 
318  my @exons;
319  my %slice_hash;
320  my %sr_name_hash;
321  my %sr_cs_hash;
322 
323  my(
324  $prediction_exon_id, $seq_region_id,
325  $seq_region_start, $seq_region_end, $seq_region_strand,
326  $start_phase, $score, $p_value);
327 
328  $sth->bind_columns(\(
329  $prediction_exon_id, $seq_region_id,
330  $seq_region_start, $seq_region_end, $seq_region_strand,
331  $start_phase, $score, $p_value));
332 
333  my $dest_slice_start;
334  my $dest_slice_end;
335  my $dest_slice_strand;
336  my $dest_slice_length;
337  my $dest_slice_cs;
338  my $dest_slice_sr_name;
339  my $dest_slice_sr_id;
340  my $asma;
341 
342  if ($dest_slice) {
343  $dest_slice_start = $dest_slice->start();
344  $dest_slice_end = $dest_slice->end();
345  $dest_slice_strand = $dest_slice->strand();
346  $dest_slice_length = $dest_slice->length();
347  $dest_slice_cs = $dest_slice->coord_system();
348  $dest_slice_sr_name = $dest_slice->seq_region_name();
349  $dest_slice_sr_id = $dest_slice->get_seq_region_id();
350  $asma = $self->db->get_AssemblyMapperAdaptor();
351  }
352 
353  FEATURE: while($sth->fetch()) {
354 
355  #need to get the internal_seq_region, if present
356  $seq_region_id = $self->get_seq_region_id_internal($seq_region_id);
357  my $slice = $slice_hash{"ID:".$seq_region_id};
358 
359  if (!$slice) {
360  $slice = $sa->fetch_by_seq_region_id($seq_region_id);
361  $slice_hash{"ID:".$seq_region_id} = $slice;
362  $sr_name_hash{$seq_region_id} = $slice->seq_region_name();
363  $sr_cs_hash{$seq_region_id} = $slice->coord_system();
364  }
365 
366  #obtain a mapper if none was defined, but a dest_seq_region was
367  if(!$mapper && $dest_slice && !$dest_slice_cs->equals($slice->coord_system)) {
368  $mapper = $asma->fetch_by_CoordSystems($dest_slice_cs, $slice->coord_system);
369  }
370 
371  my $sr_name = $sr_name_hash{$seq_region_id};
372  my $sr_cs = $sr_cs_hash{$seq_region_id};
373 
374  #
375  # remap the feature coordinates to another coord system
376  # if a mapper was provided
377  #
378 
379  if ($mapper) {
380 
381  if (defined $dest_slice && $mapper->isa('Bio::EnsEMBL::ChainedAssemblyMapper') ) {
382  ($seq_region_id, $seq_region_start, $seq_region_end, $seq_region_strand) =
383  $mapper->map($sr_name, $seq_region_start, $seq_region_end, $seq_region_strand, $sr_cs, 1, $dest_slice);
384 
385  } else {
386  ($seq_region_id, $seq_region_start, $seq_region_end, $seq_region_strand) =
387  $mapper->fastmap($sr_name, $seq_region_start, $seq_region_end, $seq_region_strand, $sr_cs);
388  }
389 
390  #skip features that map to gaps or coord system boundaries
391  next FEATURE if (!defined($seq_region_id));
392 
393  #get a slice in the coord system we just mapped to
394  $slice = $slice_hash{"ID:".$seq_region_id} ||= $sa->fetch_by_seq_region_id($seq_region_id);
395  }
396 
397  #
398  # If a destination slice was provided convert the coords.
399  #
400  if (defined($dest_slice)) {
401  my $seq_region_len = $dest_slice->seq_region_length();
402 
403  if ( $dest_slice_strand == 1 ) {
404  $seq_region_start = $seq_region_start - $dest_slice_start + 1;
405  $seq_region_end = $seq_region_end - $dest_slice_start + 1;
406 
407  if ( $dest_slice->is_circular ) {
408  # Handle circular chromosomes.
409 
410  if ( $seq_region_start > $seq_region_end ) {
411  # Looking at a feature overlapping the chromosome origin.
412 
413  if ( $seq_region_end > $dest_slice_start ) {
414  # Looking at the region in the beginning of the chromosome
415  $seq_region_start -= $seq_region_len;
416  }
417  if ( $seq_region_end < 0 ) {
418  $seq_region_end += $seq_region_len;
419  }
420  } else {
421  if ($dest_slice_start > $dest_slice_end && $seq_region_end < 0) {
422  # Looking at the region overlapping the chromosome
423  # origin and a feature which is at the beginning of the
424  # chromosome.
425  $seq_region_start += $seq_region_len;
426  $seq_region_end += $seq_region_len;
427  }
428  }
429  }
430  } else {
431 
432  my $start = $dest_slice_end - $seq_region_end + 1;
433  my $end = $dest_slice_end - $seq_region_start + 1;
434 
435  if ($dest_slice->is_circular()) {
436 
437  if ($dest_slice_start > $dest_slice_end) {
438  # slice spans origin or replication
439 
440  if ($seq_region_start >= $dest_slice_start) {
441  $end += $seq_region_len;
442  $start += $seq_region_len if $seq_region_end > $dest_slice_start;
443 
444  } elsif ($seq_region_start <= $dest_slice_end) {
445  # do nothing
446  } elsif ($seq_region_end >= $dest_slice_start) {
447  $start += $seq_region_len;
448  $end += $seq_region_len;
449 
450  } elsif ($seq_region_end <= $dest_slice_end) {
451  $end += $seq_region_len if $end < 0;
452 
453  } elsif ($seq_region_start > $seq_region_end) {
454  $end += $seq_region_len;
455  }
456 
457  } else {
458 
459  if ($seq_region_start <= $dest_slice_end and $seq_region_end >= $dest_slice_start) {
460  # do nothing
461  } elsif ($seq_region_start > $seq_region_end) {
462  if ($seq_region_start <= $dest_slice_end) {
463  $start -= $seq_region_len;
464  } elsif ($seq_region_end >= $dest_slice_start) {
465  $end += $seq_region_len;
466  }
467  }
468  }
469  }
470 
471  $seq_region_start = $start;
472  $seq_region_end = $end;
473  $seq_region_strand *= -1;
474 
475  } ## end else [ if ( $dest_slice_strand...)]
476 
477  # Throw away features off the end of the requested slice or on
478  # different seq_region.
479  if ($seq_region_end < 1
480  || $seq_region_start > $dest_slice_length
481  || ($dest_slice_sr_id != $seq_region_id)) {
482  next FEATURE;
483  }
484  $slice = $dest_slice;
485  }
486 
487  # Finally, create the new PredictionExon.
488  push( @exons,
489  $self->_create_feature( 'Bio::EnsEMBL::PredictionExon', {
490  '-start' => $seq_region_start,
491  '-end' => $seq_region_end,
492  '-strand' => $seq_region_strand,
493  '-adaptor' => $self,
494  '-slice' => $slice,
495  '-dbID' => $prediction_exon_id,
496  '-phase' => $start_phase,
497  '-score' => $score,
498  '-p_value' => $p_value
499  } ) );
500 
501  }
502 
503  return \@exons;
504 }
505 
506 
507 1;
transcript
public transcript()
Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor
Definition: BaseFeatureAdaptor.pm:24
Bio::EnsEMBL::DBSQL::BaseAdaptor::fetch_by_dbID
public Bio::EnsEMBL::Feature fetch_by_dbID()
exon
public exon()
Bio::EnsEMBL::Exon
Definition: Exon.pm:42
Bio::EnsEMBL::PredictionExon
Definition: PredictionExon.pm:38
Bio::EnsEMBL::DBSQL::PredictionExonAdaptor
Definition: PredictionExonAdaptor.pm:19
Bio::EnsEMBL::Utils::Exception
Definition: Exception.pm:68