ensembl-hive  2.8.1
TranscriptAdaptor.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::TranscriptAdaptor - An adaptor which performs database
34 interaction relating to the storage and retrieval of Transcripts
35 
36 =head1 SYNOPSIS
37 
39 
41  -host => 'ensembldb.ensembl.org',
42  -user => 'anonymous'
43  );
44 
45  $transcript_adaptor =
46  Bio::EnsEMBL::Registry->get_adaptor( 'Human', 'Core',
47  'Transcript' );
48 
49  $transcript = $transcript_adaptor->fetch_by_dbID(1234);
50 
51  $transcript =
52  $transcript_adaptor->fetch_by_stable_id('ENST00000201961');
53 
54  $slice =
55  $slice_adaptor->fetch_by_region( 'Chromosome', '3', 1, 1000000 );
56  @transcripts = @{ $transcript_adaptor->fetch_all_by_Slice($slice) };
57 
58  ($transcript) =
59  @{ $transcript_adaptor->fetch_all_by_external_name('NP_065811.1') };
60 
61 =head1 DESCRIPTION
62 
63 This adaptor provides a means to retrieve and store information related
64 to Transcripts. Primarily this involves the retrieval or storage of
65 Bio::EnsEMBL::Transcript objects from a database.
66 
67 See Bio::EnsEMBL::Transcript for details of the Transcript class.
68 
69 =cut
70 
71 package Bio::EnsEMBL::DBSQL::TranscriptAdaptor;
72 
73 use strict;
74 
80 use Bio::EnsEMBL::Utils::Exception qw( throw warning );
81 use Bio::EnsEMBL::Utils::Scalar qw( assert_ref );
82 
83 use vars qw(@ISA);
85 
86 
87 # _tables
88 #
89 # Description: PROTECTED implementation of superclass abstract method.
90 # Returns the names, aliases of the tables to use for queries.
91 # Returntype : list of listrefs of strings
92 # Exceptions : none
93 # Caller : internal
94 # Status : Stable
95 
96 sub _tables {
97  return (
98  [ 'transcript', 't' ],
99  [ 'xref', 'x' ],
100  [ 'external_db', 'exdb' ] );
101 }
102 
103 
104 #_columns
105 #
106 # Description: PROTECTED implementation of superclass abstract method.
107 # Returns a list of columns to use for queries.
108 # Returntype : list of strings
109 # Exceptions : none
110 # Caller : internal
111 # Status : Stable
112 
113 sub _columns {
114  my ($self) = @_;
115 
116  my $created_date =
117  $self->db()->dbc()->from_date_to_seconds("created_date");
118  my $modified_date =
119  $self->db()->dbc()->from_date_to_seconds("modified_date");
120 
121  my @columns =
122  (
123  't.transcript_id', 't.seq_region_id',
124  't.seq_region_start', 't.seq_region_end',
125  't.seq_region_strand', 't.analysis_id',
126  't.gene_id', 't.is_current',
127  't.stable_id', 't.version',
128  $created_date, $modified_date,
129  't.description', 't.biotype',
130  'exdb.db_name',
131  'exdb.status', 'exdb.db_display_name',
132  'x.xref_id', 'x.display_label',
133  'x.dbprimary_acc', 'x.version',
134  'x.description', 'x.info_type',
135  'x.info_text', 'exdb.db_release'
136  );
137 
138  $self->schema_version > 74 and push @columns, 't.source';
139 
140  return @columns;
141 }
142 
143 sub _left_join {
144  return (
145  [ 'xref', "x.xref_id = t.display_xref_id" ],
146  [ 'external_db', "exdb.external_db_id = x.external_db_id" ]
147  );
148 }
149 
150 
151 =head2 fetch_by_stable_id
152 
153  Arg [1] : String $stable_id
154  The stable id of the transcript to retrieve
155  Example : my $tr = $tr_adaptor->fetch_by_stable_id('ENST00000309301');
156  Description: Retrieves a transcript via its stable id.
157  Returntype : Bio::EnsEMBL::Transcript
158  Exceptions : none
159  Caller : general
160  Status : Stable
161 
162 =cut
163 
164 sub fetch_by_stable_id {
165  my ($self, $stable_id) = @_;
166 
167  my $constraint = "t.stable_id = ? AND t.is_current = 1";
168 
169  $self->bind_param_generic_fetch($stable_id,SQL_VARCHAR);
170 
171  my ($transcript) = @{ $self->generic_fetch($constraint) };
172 
173  # If we didn't get anything back, desperately try to see if there's
174  # a version number in the stable_id
175  if(!defined($transcript) && (my $vindex = rindex($stable_id, '.'))) {
176  $transcript = $self->fetch_by_stable_id_version(substr($stable_id,0,$vindex),
177  substr($stable_id,$vindex+1));
178  }
179 
180  return $transcript;
181 }
182 
183 
184 =head2 fetch_by_stable_id_version
185 
186  Arg [1] : String $id
187  The stable ID of the transcript to retrieve
188  Arg [2] : Integer $version
189  The version of the stable_id to retrieve
190  Example : $tr = $tr_adaptor->fetch_by_stable_id('ENST00000309301', 3);
191  Description: Retrieves a transcript object from the database via its
192  stable id and version.
193  The transcript will be retrieved in its native coordinate system (i.e.
194  in the coordinate system it is stored in the database). It may
195  be converted to a different coordinate system through a call to
196  transform() or transfer(). If the transcript is not found
197  undef is returned instead.
198  Returntype : Bio::EnsEMBL::Transcript or undef
199  Exceptions : if we cant get the transcript in given coord system
200  Caller : general
201  Status : Stable
202 
203 =cut
204 
205 sub fetch_by_stable_id_version {
206  my ($self, $stable_id, $version) = @_;
207 
208  # Enforce that version be numeric
209  return unless($version =~ /^\d+$/);
210 
211  my $constraint = "t.stable_id = ? AND t.version = ? AND t.is_current = 1";
212  $self->bind_param_generic_fetch($stable_id, SQL_VARCHAR);
213  $self->bind_param_generic_fetch($version, SQL_INTEGER);
214  my ($transcript) = @{$self->generic_fetch($constraint)};
215 
216  return $transcript;
217 }
218 
219 sub fetch_all {
220  my ($self) = @_;
221 
222  my $constraint = 't.biotype != "LRG_gene" and t.is_current = 1';
223  my @trans = @{ $self->generic_fetch($constraint) };
224  return \@trans ;
225 }
226 
227 =head2 fetch_all_versions_by_stable_id
228 
229  Arg [1] : String $stable_id
230  The stable ID of the transcript to retrieve
231  Example : my $tr = $tr_adaptor->fetch_all_version_by_stable_id
232  ('ENST00000309301');
233  Description : Similar to fetch_by_stable_id, but retrieves all versions of a
234  transcript stored in the database.
235  Returntype : listref of Bio::EnsEMBL::Transcript objects
236  Exceptions : if we cant get the gene in given coord system
237  Caller : general
238  Status : At Risk
239 
240 =cut
241 
242 sub fetch_all_versions_by_stable_id {
243  my ($self, $stable_id) = @_;
244 
245  my $constraint = "t.stable_id = ?";
246 
247  $self->bind_param_generic_fetch($stable_id,SQL_VARCHAR);
248 
249  return $self->generic_fetch($constraint);
250 }
251 
252 
253 =head2 fetch_by_rnaproduct_id
254 
255  Arg [1] : Int $id
256  The internal identifier of the RNAProduct whose transcript
257  is to be retrieved
258  Example : my $tr = $tr_adaptor->fetch_by_rnaproduct_id($rnap->dbID);
259  Description: Given the internal identifier of a RNAProduct this method
260  retrieves the transcript associated with that RNAProduct.
261  If the transcript cannot be found undef is returned instead.
262  Returntype : Bio::EnsEMBL::Transcript or undef
263  Exceptions : none
264  Caller : general
265  Status : Stable
266 
267 =cut
268 
269 sub fetch_by_rnaproduct_id {
270  my ($self, $p_dbID) = @_;
271 
272  throw("dbID argument is required") unless defined($p_dbID);
273 
274  my $sth = $self->prepare(
275  "SELECT transcript_id FROM rnaproduct WHERE rnaproduct_id = ?"
276  );
277  $sth->bind_param(1, $p_dbID, SQL_INTEGER);
278  $sth->execute();
279 
280  my ($dbID) = $sth->fetchrow_array();
281  $sth->finish();
282 
283  if ($dbID) {
284  return $self->fetch_by_dbID($dbID);
285  }
286 
287  return;
288 }
289 
290 
291 =head2 fetch_by_translation_stable_id
292 
293  Arg [1] : String $transl_stable_id
294  The stable identifier of the translation of the transcript to
295  retrieve
296  Example : my $tr = $tr_adaptor->fetch_by_translation_stable_id
297  ('ENSP00000311007');
298  Description: Retrieves a Transcript object using the stable identifier of
299  its translation.
300  Returntype : Bio::EnsEMBL::Transcript or undef
301  Exceptions : none
302  Caller : general
303  Status : Stable
304 
305 =cut
306 
307 sub fetch_by_translation_stable_id {
308  my ($self, $transl_stable_id ) = @_;
309 
310  my $sth = $self->prepare(qq(
311  SELECT t.transcript_id
312  FROM translation tl,
313  transcript t
314  WHERE tl.stable_id = ?
315  AND tl.transcript_id = t.transcript_id
316  AND t.is_current = 1
317  ));
318 
319  $sth->bind_param(1, $transl_stable_id, SQL_VARCHAR);
320  $sth->execute();
321 
322  my ($id) = $sth->fetchrow_array;
323  $sth->finish;
324  if ($id){
325  return $self->fetch_by_dbID($id);
326  } elsif(my $vindex = rindex($transl_stable_id, '.')) {
327  return $self->fetch_by_translation_stable_id_version(substr($transl_stable_id,0,$vindex),
328  substr($transl_stable_id,$vindex+1));
329  } else {
330  return undef;
331  }
332 }
333 
334 =head2 fetch_by_translation_stable_id_version
335 
336  Arg [1] : String $transl_stable_id
337  The stable identifier of the translation of the transcript to
338  retrieve
339  Arg [2] : Integer $version
340  The version of the translation of the transcript to retrieve
341  Example : my $tr = $tr_adaptor->fetch_by_translation_stable_id_version
342  ('ENSP00000311007', 2);
343  Description: Retrieves a Transcript object using the stable identifier and
344  version of its translation.
345  Returntype : Bio::EnsEMBL::Transcript or undef
346  Exceptions : none
347  Caller : general
348  Status : Stable
349 
350 =cut
351 
352 sub fetch_by_translation_stable_id_version {
353  my ($self, $transl_stable_id, $transl_version ) = @_;
354 
355  # Enforce that version be numeric
356  return unless($transl_version =~ /^\d+$/);
357 
358  my $sth = $self->prepare(qq(
359  SELECT t.transcript_id
360  FROM translation tl,
361  transcript t
362  WHERE tl.stable_id = ?
363  AND tl.version = ?
364  AND tl.transcript_id = t.transcript_id
365  AND t.is_current = 1
366  ));
367 
368  $sth->bind_param(1, $transl_stable_id, SQL_VARCHAR);
369  $sth->bind_param(2, $transl_version, SQL_INTEGER);
370  $sth->execute();
371 
372  my ($id) = $sth->fetchrow_array;
373  $sth->finish;
374  if ($id){
375  return $self->fetch_by_dbID($id);
376  } else {
377  return undef;
378  }
379 }
380 
381 =head2 fetch_by_translation_id
382 
383  Arg [1] : Int $id
384  The internal identifier of the translation whose transcript
385  is to be retrieved
386  Example : my $tr = $tr_adaptor->fetch_by_translation_id($transl->dbID);
387  Description: Given the internal identifier of a translation this method
388  retrieves the transcript associated with that translation.
389  If the transcript cannot be found undef is returned instead.
390  Returntype : Bio::EnsEMBL::Transcript or undef
391  Exceptions : none
392  Caller : general
393  Status : Stable
394 
395 =cut
396 
397 sub fetch_by_translation_id {
398  my ( $self, $p_dbID ) = @_;
399 
400  if ( !defined($p_dbID) ) {
401  throw("dbID argument is required");
402  }
403 
404  my $sth =
405  $self->prepare( "SELECT transcript_id "
406  . "FROM translation "
407  . "WHERE translation_id = ?" );
408 
409  $sth->bind_param( 1, $p_dbID, SQL_INTEGER );
410  $sth->execute();
411 
412  my ($dbID) = $sth->fetchrow_array();
413  $sth->finish();
414 
415  if ($dbID) {
416  return $self->fetch_by_dbID($dbID);
417  }
418 
419  return undef;
420 }
421 
422 =head2 fetch_all_by_Gene
423 
424  Arg [1] : Bio::EnsEMBL::Gene $gene
425  The gene to fetch transcripts of
426  Example : my $gene = $gene_adaptor->fetch_by_stable_id('ENSG0000123');
427  my @transcripts = { $tr_adaptor->fetch_all_by_Gene($gene) };
428  Description: Retrieves Transcript objects for given gene. Puts Genes slice
429  in each Transcript.
430  Returntype : Listref of Bio::EnsEMBL::Transcript objects
431  Exceptions : none
432  Caller : Gene->get_all_Transcripts()
433  Status : Stable
434 
435 =cut
436 
437 sub fetch_all_by_Gene {
438  my ( $self, $gene ) = @_;
439 
440  my $constraint = "t.gene_id = " . $gene->dbID();
441 
442  # Use the fetch_all_by_Slice_constraint method because it handles the
443  # difficult Haps/PARs and coordinate remapping.
444 
445  # Get a slice that entirely overlaps the gene. This is because we
446  # want all transcripts to be retrieved, not just ones overlapping
447  # the slice the gene is on (the gene may only partially overlap the
448  # slice). For speed reasons, only use a different slice if necessary
449  # though.
450 
451  my $gslice = $gene->slice();
452 
453  if ( !defined($gslice) ) {
454  throw("Gene must have attached slice to retrieve transcripts.");
455  }
456 
457  my $slice;
458 
459  if ( $gene->start() < 1 || $gene->end() > $gslice->length() ) {
460  if ( $gslice->is_circular() ) {
461  $slice = $gslice;
462  } else {
463  $slice = $self->db->get_SliceAdaptor->fetch_by_Feature($gene);
464  }
465  } else {
466  $slice = $gslice;
467  }
468 
469  my $transcripts =
470  $self->fetch_all_by_Slice_constraint( $slice, $constraint );
471 
472  if ( $slice != $gslice ) {
473  my @out;
474  foreach my $tr ( @{$transcripts} ) {
475  push( @out, $tr->transfer($gslice) );
476  }
477  $transcripts = \@out;
478  }
479 
480  my $canonical_t = $gene->canonical_transcript();
481 
482  foreach my $t ( @{$transcripts} ) {
483  if ( $t->equals($canonical_t) ) {
484  $t->is_canonical(1);
485  last;
486  }
487  }
488 
489  return $transcripts;
490 } ## end sub fetch_all_by_Gene
491 
492 
493 =head2 fetch_all_by_Slice
494 
495  Arg [1] : Bio::EnsEMBL::Slice $slice
496  The slice to fetch transcripts on
497  Arg [2] : (optional) Boolean $load_exons
498  If true, exons will be loaded immediately rather than
499  lazy loaded later
500  Arg [3] : (optional) String $logic_name
501  The logic name of the type of features to obtain
502  ARG [4] : (optional) String $constraint
503  An extra contraint.
504  Example : my @transcripts = @{ $tr_adaptor->fetch_all_by_Slice($slice) };
505  Description: Overrides superclass method to optionally load exons
506  immediately rather than lazy-loading them later. This
507  is more efficient when there are a lot of transcripts whose
508  exons are going to be used.
509  Returntype : Listref of Bio::EnsEMBL::Transcript objects
510  Exceptions : thrown if exon cannot be placed on transcript slice
511  Caller : Slice::get_all_Transcripts
512  Status : Stable
513 
514 =cut
515 
516 sub fetch_all_by_Slice {
517  my ( $self, $slice, $load_exons, $logic_name, $constraint, $source, $biotype ) = @_;
518 
519  if (defined $constraint and $constraint ne '') {
520  $constraint .= ' AND t.is_current = 1';
521  } else {
522  $constraint .= 't.is_current = 1';
523  }
524  if (defined($source)) {
525  $constraint .= " and t.source = '$source'";
526  }
527  if (defined($biotype)) {
528  my $inline_variables = 1;
529  $constraint .= " and ".$self->generate_in_constraint($biotype, 't.biotype', SQL_VARCHAR, $inline_variables);
530  }
531 
532  my $transcripts = $self->SUPER::fetch_all_by_Slice_constraint( $slice, $constraint, $logic_name);
533 
534  # if there are 0 transcripts still do lazy-loading
535  if ( !$load_exons || @$transcripts < 1 ) {
536  return $transcripts;
537  }
538 
539  # preload all of the exons now, instead of lazy loading later
540  # faster than 1 query per transcript
541 
542  # first check if the exons are already preloaded
543  # @todo FIXME: Should test all exons.
544  if ( exists( $transcripts->[0]->{'_trans_exon_array'} ) ) {
545  return $transcripts;
546  }
547 
548  # get extent of region spanned by transcripts
549  my ($min_start, $max_end);
550  my $ext_slice;
551 
552  unless ($slice->is_circular()) {
553  foreach my $t (@$transcripts) {
554  if (!defined($min_start) || $t->seq_region_start() < $min_start) {
555  $min_start = $t->seq_region_start();
556  }
557  if (!defined($max_end) || $t->seq_region_end() > $max_end) {
558  $max_end = $t->seq_region_end();
559  }
560  }
561 
562  if ($min_start >= $slice->start() && $max_end <= $slice->end()) {
563  $ext_slice = $slice;
564  } else {
565  my $sa = $self->db()->get_SliceAdaptor();
566  $ext_slice = $sa->fetch_by_region($slice->coord_system->name(), $slice->seq_region_name(), $min_start, $max_end, $slice->strand(), $slice->coord_system->version());
567  }
568 
569  } else {
570  # feature might be crossing the origin of replication (i.e. seq_region_start > seq_region_end)
571  # the computation of min_start|end based on seq_region_start|end is not safe
572  # use feature start/end relative to the slice instead
573  my ($min_start_feature, $max_end_feature);
574  foreach my $t (@$transcripts) {
575  if (!defined($min_start) || ($t->start >= 0 && $t->start() < $min_start)) {
576  $min_start = $t->start();
577  $min_start_feature = $t;
578  }
579  if (!defined($max_end) || ($t->end() >= 0 && $t->end() > $max_end)) {
580  $max_end = $t->end();
581  $max_end_feature = $t;
582  }
583  }
584 
585  # now we can reassign min_start|end to seq_region_start|end of
586  # the feature which spans the largest region
587  $min_start = $min_start_feature->seq_region_start();
588  $max_end = $max_end_feature->seq_region_end();
589 
590  my $sa = $self->db()->get_SliceAdaptor();
591  $ext_slice =
592  $sa->fetch_by_region($slice->coord_system->name(),
593  $slice->seq_region_name(),
594  $min_start,
595  $max_end,
596  $slice->strand(),
597  $slice->coord_system->version());
598  }
599 
600 
601 
602  # associate exon identifiers with transcripts
603 
604  my %tr_hash = map { $_->dbID => $_ } @{$transcripts};
605 
606  my $tr_id_str = join( ',', keys(%tr_hash) );
607 
608  my $sth =
609  $self->prepare( "SELECT `transcript_id`, `exon_id`, `rank` "
610  . "FROM exon_transcript "
611  . "WHERE transcript_id IN ($tr_id_str)" );
612 
613  $sth->execute();
614 
615  my ( $tr_id, $ex_id, $rank );
616  $sth->bind_columns( \( $tr_id, $ex_id, $rank ) );
617 
618  my %ex_tr_hash;
619 
620  while ( $sth->fetch() ) {
621  $ex_tr_hash{$ex_id} ||= [];
622  push( @{ $ex_tr_hash{$ex_id} }, [ $tr_hash{$tr_id}, $rank ] );
623  }
624 
625  my $ea = $self->db()->get_ExonAdaptor();
626  my $exons = $ea->fetch_all_by_Slice_constraint(
627  $ext_slice,
628  sprintf( "e.exon_id IN (%s)",
629  join( ',', sort { $a <=> $b } keys(%ex_tr_hash) ) ) );
630 
631  # move exons onto transcript slice, and add them to transcripts
632  foreach my $ex ( @{$exons} ) {
633  my $new_ex;
634  if ( $slice != $ext_slice ) {
635  $new_ex = $ex->transfer($slice);
636  if ( !defined($new_ex) ) {
637  throw("Unexpected. "
638  . "Exon could not be transfered onto Transcript slice." );
639  }
640  } else {
641  $new_ex = $ex;
642  }
643 
644  foreach my $row ( @{ $ex_tr_hash{ $new_ex->dbID() } } ) {
645  my ( $tr, $rank ) = @{$row};
646  $tr->add_Exon( $new_ex, $rank );
647  }
648  }
649 
650  my $tla = $self->db()->get_TranslationAdaptor();
651 
652  # load all of the translations at once
653  $tla->fetch_all_by_Transcript_list($transcripts);
654 
655  return $transcripts;
656 } ## end sub fetch_all_by_Slice
657 
658 
659 =head2 fetch_all_by_external_name
660 
661  Arg [1] : String $external_name
662  An external identifier of the transcript to be obtained
663  Arg [2] : (optional) String $external_db_name
664  The name of the external database from which the
665  identifier originates.
666  Arg [3] : Boolean override. Force SQL regex matching for users
667  who really do want to find all 'NM%'
668  Example : my @transcripts =
669  @{ $tr_adaptor->fetch_all_by_external_name( 'NP_065811.1') };
670  my @more_transcripts =
671  @{$tr_adaptor->fetch_all_by_external_name( 'NP_0658__._')};
672  Description: Retrieves all transcripts which are associated with
673  an external identifier such as a GO term, Swissprot
674  identifer, etc. Usually there will only be a single
675  transcript returned in the list reference, but not
676  always. Transcripts are returned in their native
677  coordinate system, i.e. the coordinate system in which
678  they are stored in the database. If they are required
679  in another coordinate system the Transcript::transfer or
680  Transcript::transform method can be used to convert them.
681  If no transcripts with the external identifier are found,
682  a reference to an empty list is returned.
683  SQL wildcards % and _ are supported in the $external_name
684  but their use is somewhat restricted for performance reasons.
685  Users that really do want % and _ in the first three characters
686  should use argument 3 to prevent optimisations
687  Returntype : listref of Bio::EnsEMBL::Transcript
688  Exceptions : none
689  Caller : general
690  Status : Stable
691 
692 =cut
693 
694 sub fetch_all_by_external_name {
695  my ( $self, $external_name, $external_db_name, $override) = @_;
696 
697  my $entryAdaptor = $self->db->get_DBEntryAdaptor();
698 
699  my @ids =
700  $entryAdaptor->list_transcript_ids_by_extids( $external_name,
701  $external_db_name, $override );
702 
703  my @features = @{ $self->fetch_all_by_dbID_list( \@ids ) };
704  my @reference = grep { $_->slice()->is_reference() } @features;
705  my @non_reference = grep { ! $_->slice()->is_reference() } @features;
706  return [ @reference, @non_reference ];
707 }
708 
709 =head2 fetch_all_by_GOTerm
710 
712  The GO term for which transcripts should be fetched.
713 
714  Example: @transcripts = @{
715  $transcript_adaptor->fetch_all_by_GOTerm(
716  $go_adaptor->fetch_by_accession('GO:0030326') ) };
717 
718  Description : Retrieves a list of transcripts that are
719  associated with the given GO term, or with any of
720  its descendent GO terms. The transcripts returned
721  are in their native coordinate system, i.e. in
722  the coordinate system in which they are stored
723  in the database. If another coordinate system
724  is required then the Transcript::transfer or
725  Transcript::transform method can be used.
726 
727  Return type : listref of Bio::EnsEMBL::Transcript
728  Exceptions : Throws of argument is not a GO term
729  Caller : general
730  Status : Stable
731 
732 =cut
733 
734 sub fetch_all_by_GOTerm {
735  my ( $self, $term ) = @_;
736 
737  assert_ref( $term, 'Bio::EnsEMBL::OntologyTerm' );
738  if ( $term->ontology() ne 'GO' ) {
739  throw('Argument is not a GO term');
740  }
741 
742  my $entryAdaptor = $self->db->get_DBEntryAdaptor();
743 
744  my %unique_dbIDs;
745  foreach my $accession ( map { $_->accession() }
746  ( $term, @{ $term->descendants() } ) )
747  {
748  my @ids =
749  $entryAdaptor->list_transcript_ids_by_extids( $accession, 'GO' );
750  foreach my $dbID (@ids) { $unique_dbIDs{$dbID} = 1 }
751  }
752 
753  my @result = @{
754  $self->fetch_all_by_dbID_list(
755  [ sort { $a <=> $b } keys(%unique_dbIDs) ]
756  ) };
757 
758  return \@result;
759 } ## end sub fetch_all_by_GOTerm
760 
761 =head2 fetch_all_by_GOTerm_accession
762 
763  Arg [1] : String
764  The GO term accession for which genes should be
765  fetched.
766 
767  Example :
768 
769  @genes =
770  @{ $gene_adaptor->fetch_all_by_GOTerm_accession(
771  'GO:0030326') };
772 
773  Description : Retrieves a list of genes that are associated with
774  the given GO term, or with any of its descendent
775  GO terms. The genes returned are in their native
776  coordinate system, i.e. in the coordinate system
777  in which they are stored in the database. If
778  another coordinate system is required then the
779  Gene::transfer or Gene::transform method can be
780  used.
781 
782  Return type : listref of Bio::EnsEMBL::Gene
783  Exceptions : Throws of argument is not a GO term accession
784  Caller : general
785  Status : Stable
786 
787 =cut
788 
789 sub fetch_all_by_GOTerm_accession {
790  my ( $self, $accession ) = @_;
791 
792  if ( $accession !~ /^GO:/ ) {
793  throw('Argument is not a GO term accession');
794  }
795 
796  my $goAdaptor =
797  Bio::EnsEMBL::Registry->get_adaptor( 'Multi', 'Ontology',
798  'OntologyTerm' );
799 
800  my $term = $goAdaptor->fetch_by_accession($accession);
801 
802  return $self->fetch_all_by_GOTerm($term);
803 }
804 
805 =head2 fetch_by_display_label
806 
807  Arg [1] : String $label - display label of transcript to fetch
808  Example : my $tr = $tr_adaptor->fetch_by_display_label("BRCA2");
809  Description: Returns the transcript which has the given display label or
810  undef if there is none. If there are more than 1, only the first
811  is reported.
812  Returntype : Bio::EnsEMBL::Transcript
813  Exceptions : none
814  Caller : general
815  Status : Stable
816 
817 =cut
818 
819 sub fetch_by_display_label {
820  my $self = shift;
821  my $label = shift;
822 
823  my $constraint = "x.display_label = ? AND t.is_current = 1";
824 
825  $self->bind_param_generic_fetch($label,SQL_VARCHAR);
826 
827  my ($transcript) = @{ $self->generic_fetch($constraint) };
828 
829  return $transcript;
830 }
831 
832 
833 =head2 fetch_all_by_exon_stable_id
834 
835  Arg [1] : String $stable_id
836  The stable id of an exon in a transcript
837  Example : my $tr = $tr_adaptor->fetch_all_by_exon_stable_id
838  ('ENSE00000309301');
839  Description: Retrieves a list of transcripts via an exon stable id.
840  Returntype : Listref of Bio::EnsEMBL::Transcript objects
841  Exceptions : none
842  Caller : general
843  Status : Stable
844 
845 =cut
846 
847 sub fetch_all_by_exon_stable_id {
848  my ($self, $stable_id) = @_;
849 
850  my @trans ;
851 
852  my $sth = $self->prepare(qq(
853  SELECT t.transcript_id
854  FROM exon_transcript et, exon e, transcript t
855  WHERE e.exon_id = et.exon_id
856  AND et.transcript_id = t.transcript_id
857  AND e.stable_id = ?
858  AND t.is_current = 1
859  ));
860 
861  $sth->bind_param(1, $stable_id, SQL_VARCHAR);
862  $sth->execute();
863 
864  while( my $id = $sth->fetchrow_array ) {
865  my $transcript = $self->fetch_by_dbID($id);
866  push(@trans, $transcript) if $transcript;
867  }
868 
869  if (!@trans) {
870  return undef;
871  }
872 
873  return \@trans;
874 }
875 
876 =head2 fetch_all_by_source
877 
878  Arg [1] : String $source
879  listref of $sources
880  The source of the transcript to retrieve. You can have as an argument a reference
881  to a list of sources
882  Example : $transcripts = $transcript_adaptor->fetch_all_by_source('havana');
883  $transcripts = $transcript_adaptor->fetch_all_by_source(['ensembl', 'vega']);
884  Description: Retrieves an array reference of transcript objects from the database via its source or sources.
885  The transcript will be retrieved in its native coordinate system (i.e.
886  in the coordinate system it is stored in the database). It may
887  be converted to a different coordinate system through a call to
888  transform() or transfer(). If the gene or exon is not found
889  undef is returned instead.
890  Returntype : listref of Bio::EnsEMBL::Transcript
891  Exceptions : if we cant get the gene in given coord system
892  Caller : general
893  Status : Stable
894 
895 =cut
896 
897 sub fetch_all_by_source {
898  my ($self, $source) = @_;
899  my @transcripts = @{$self->generic_fetch($self->source_constraint($source))};
900  return \@transcripts;
901 }
902 
903 =head2 source_constraint
904 
905  Arg [1] : String $source
906  listref of $sources
907  The source of the transcript to retrieve. You can have as an argument a reference
908  to a list of sources
909  Description: Used internally to generate a SQL constraint to restrict a transcript query by source
910  Returntype : String
911  Exceptions : If source is not supplied
912  Caller : general
913  Status : Stable
914 
915 =cut
916 
917 sub source_constraint {
918  my ($self, $sources, $inline_variables) = @_;
919  my $constraint = "t.is_current = 1";
920  my $in_statement = $self->generate_in_constraint($sources, 't.source', SQL_VARCHAR, $inline_variables);
921  $constraint .= " and $in_statement";
922  return $constraint;
923 }
924 
925 =head2 count_all_by_source
926 
927  Arg [1] : String $source
928  listref of $source
929  The source of the transcript to retrieve. You can have as an argument a reference
930  to a list of sources
931  Example : $cnt = $transcript_adaptor->count_all_by_source('ensembl');
932  $cnt = $transcript_adaptor->count_all_by_source(['havana', 'vega']);
933  Description : Retrieves count of transcript objects from the database via its source or sources.
934  Returntype : integer
935  Caller : general
936  Status : Stable
937 
938 =cut
939 
940 sub count_all_by_source {
941  my ($self, $source) = @_;
942  return $self->generic_count($self->source_constraint($source));
943 }
944 
945 =head2 count_all_by_Slice
946 
947  Arg [1] : Bio::EnsEMBL::Slice $slice
948  The slice to count transcripts on.
949  Arg [2] : (optional) biotype(s) string or arrayref of strings
950  the biotype of the features to count.
951  Arg [1] : (optional) string $source
952  the source name of the features to count.
953  Example : $cnt = $transcript_adaptor->count_all_by_Slice();
954  Description: Method to count transcripts on a given slice, filtering by biotype and source
955  Returntype : integer
956  Exceptions : thrown if exon cannot be placed on transcript slice
957  Status : Stable
958  Caller : general
959 =cut
960 
961 sub count_all_by_Slice {
962  my ($self, $slice, $biotype, $source) = @_;
963 
964  my $constraint = 't.is_current = 1';
965  if (defined($source)) {
966  $constraint .= " and t.source = '$source'";
967  }
968  if (defined($biotype)) {
969  $constraint .= " and " . $self->biotype_constraint($biotype);
970  }
971 
972  return $self->count_by_Slice_constraint($slice, $constraint);
973 }
974 
975 =head2 fetch_all_by_biotype
976 
977  Arg [1] : String $biotype
978  listref of $biotypes
979  The biotype of the transcript to retrieve. You can have as an argument a reference
980  to a list of biotypes
981  Example : $gene = $transcript_adaptor->fetch_all_by_biotype('protein_coding');
982  $gene = $transcript_adaptor->fetch_all_by_biotypes(['protein_coding', 'sRNA', 'miRNA']);
983  Description: Retrieves an array reference of transcript objects from the database via its biotype or biotypes.
984  The transcript will be retrieved in its native coordinate system (i.e.
985  in the coordinate system it is stored in the database). It may
986  be converted to a different coordinate system through a call to
987  transform() or transfer(). If the gene or exon is not found
988  undef is returned instead.
989  Returntype : listref of Bio::EnsEMBL::Transcript
990  Exceptions : if we cant get the gene in given coord system
991  Caller : general
992  Status : Stable
993 
994 =cut
995 
996 sub fetch_all_by_biotype {
997  my ($self, $biotype) = @_;
998  my @transcripts = @{$self->generic_fetch($self->biotype_constraint($biotype))};
999  return \@transcripts;
1000 }
1001 
1002 =head2 biotype_constraint
1003 
1004  Arg [1] : String $biotypes
1005  listref of $biotypes
1006  The biotype of the transcript to retrieve. You can have as an argument a reference
1007  to a list of biotypes
1008  Description: Used internally to generate a SQL constraint to restrict a transcript query by biotype
1009  Returntype : String
1010  Exceptions : If biotype is not supplied
1011  Caller : general
1012  Status : Stable
1013 
1014 =cut
1015 
1016 sub biotype_constraint {
1017  my ($self, $biotypes, $inline_variables) = @_;
1018  my $constraint = "t.is_current = 1";
1019  my $in_statement = $self->generate_in_constraint($biotypes, 't.biotype', SQL_VARCHAR, $inline_variables);
1020  $constraint .= " and $in_statement";
1021  return $constraint;
1022 }
1023 
1024 =head2 count_all_by_biotype
1025 
1026  Arg [1] : String $biotype
1027  listref of $biotypes
1028  The biotype of the transcript to retrieve. You can have as an argument a reference
1029  to a list of biotypes
1030  Example : $cnt = $transcript_adaptor->count_all_by_biotype('protein_coding');
1031  $cnt = $transcript_adaptor->count_all_by_biotypes(['protein_coding', 'sRNA', 'miRNA']);
1032  Description : Retrieves count of transcript objects from the database via its biotype or biotypes.
1033  Returntype : integer
1034  Caller : general
1035  Status : Stable
1036 
1037 =cut
1038 
1039 sub count_all_by_biotype {
1040  my ($self, $biotype) = @_;
1041  return $self->generic_count($self->biotype_constraint($biotype));
1042 }
1043 
1044 =head2 store
1045 
1046  Arg [1] : Bio::EnsEMBL::Transcript $transcript
1047  The transcript to be written to the database
1048  Arg [2] : Int $gene_dbID
1049  The identifier of the gene that this transcript is associated
1050  with
1051  Arg [3] : DEPRECATED (optional) Int $analysis_id
1052  The analysis_id to use when storing this gene. This is for
1053  backward compatibility only and used to fall back to the gene
1054  analysis_id if no analysis object is attached to the transcript
1055  (which you should do for new code).
1056  Arg [4] : prevent coordinate recalculation if you are persisting
1057  transcripts with this gene
1058  Example : $transID = $tr_adaptor->store($transcript, $gene->dbID);
1059  Description: Stores a transcript in the database and returns the new
1060  internal identifier for the stored transcript.
1061  Returntype : Int
1062  Exceptions : none
1063  Caller : general
1064  Status : Stable
1065 
1066 =cut
1067 
1068 sub store {
1069  my ( $self, $transcript, $gene_dbID, $analysis_id, $skip_recalculating_coordinates ) = @_;
1070 
1071  if ( !ref($transcript)
1072  || !$transcript->isa('Bio::EnsEMBL::Transcript') )
1073  {
1074  throw("$transcript is not a EnsEMBL transcript - not storing");
1075  }
1076 
1077  my $db = $self->db();
1078 
1079  if ( $transcript->is_stored($db) ) {
1080  return $transcript->dbID();
1081  }
1082 
1083  # Force lazy-loading of exons and ensure coords are correct.
1084  # If we have been told not to do this then skip doing this
1085  # and we assume the user knows what they are doing. You have been
1086  # warned
1087  if(! $skip_recalculating_coordinates) {
1088  $transcript->recalculate_coordinates();
1089  }
1090 
1091  my $is_current = ( defined( $transcript->is_current() )
1092  ? $transcript->is_current()
1093  : 1 );
1094 
1095  # store analysis
1096  my $analysis = $transcript->analysis();
1097  my $new_analysis_id;
1098 
1099  if ($analysis) {
1100  if ( $analysis->is_stored($db) ) {
1101  $new_analysis_id = $analysis->dbID;
1102  } else {
1103  $new_analysis_id = $db->get_AnalysisAdaptor->store($analysis);
1104  }
1105  } else {
1106  throw("Need an analysis_id to store the Transcript.");
1107  }
1108 
1109  #
1110  # Store exons - this needs to be done before the possible transfer
1111  # of the transcript to another slice (in _prestore()). Transfering
1112  # results in copies being made of the exons and we need to preserve
1113  # the object identity of the exons so that they are not stored twice
1114  # by different transcripts.
1115  #
1116  my $exons = $transcript->get_all_Exons();
1117  my $exonAdaptor = $db->get_ExonAdaptor();
1118  foreach my $exon ( @{$exons} ) {
1119  $exonAdaptor->store($exon);
1120  }
1121 
1122  my $original_translation = $transcript->translation();
1123  my $original = $transcript;
1124  my $seq_region_id;
1125  ( $transcript, $seq_region_id ) = $self->_pre_store($transcript);
1126 
1127  # First store the transcript without a display xref. The display xref
1128  # needs to be set after xrefs are stored which needs to happen after
1129  # transcript is stored.
1130 
1131  #
1132  # Store transcript
1133  #
1134 
1135 # my $store_transcript_sql =
1136 # sprintf "INSERT INTO transcript SET gene_id = ?, analysis_id = ?, seq_region_id = ?, seq_region_start = ?, seq_region_end = ?, seq_region_strand = ?,%s biotype = ?, description = ?, is_current = ?, canonical_translation_id = ?", ($self->schema_version > 74)?" source = ?,":'';
1137 
1138  my @columns = qw(
1139  gene_id
1140  analysis_id
1141  seq_region_id
1142  seq_region_start
1143  seq_region_end
1144  seq_region_strand
1145  );
1146 
1147  push @columns, 'source' if ($self->schema_version > 74);
1148 
1149  push @columns, qw(
1150  biotype
1151  description
1152  is_current
1153  canonical_translation_id
1154  );
1155 
1156  my @canned_columns;
1157  my @canned_values;
1158 
1159  if ( defined( $transcript->stable_id() ) ) {
1160  push @columns, 'stable_id', 'version';
1161 
1162  my $created = $self->db->dbc->from_seconds_to_date($transcript->created_date());
1163  my $modified = $self->db->dbc->from_seconds_to_date($transcript->modified_date());
1164 
1165  if ($created) {
1166  push @canned_columns, 'created_date';
1167  push @canned_values, $created;
1168  }
1169  if ($modified) {
1170  push @canned_columns, 'modified_date';
1171  push @canned_values, $modified;
1172  }
1173 
1174  }
1175 
1176  my $columns = join(', ', @columns, @canned_columns);
1177  my $values = join(', ', ('?') x @columns, @canned_values);
1178  my $store_transcript_sql = qq(
1179  INSERT INTO transcript ( $columns ) VALUES ( $values )
1180  );
1181 
1182  my $tst = $self->prepare($store_transcript_sql);
1183  my $i = 0;
1184  $tst->bind_param( ++$i, $gene_dbID, SQL_INTEGER );
1185  $tst->bind_param( ++$i, $new_analysis_id, SQL_INTEGER );
1186  $tst->bind_param( ++$i, $seq_region_id, SQL_INTEGER );
1187  $tst->bind_param( ++$i, $transcript->start(), SQL_INTEGER );
1188  $tst->bind_param( ++$i, $transcript->end(), SQL_INTEGER );
1189  $tst->bind_param( ++$i, $transcript->strand(), SQL_TINYINT );
1190 
1191  $self->schema_version > 74 and
1192  $tst->bind_param( ++$i, $transcript->source(), SQL_VARCHAR );
1193 
1194  $tst->bind_param( ++$i, $transcript->get_Biotype->name, SQL_VARCHAR );
1195  $tst->bind_param( ++$i, $transcript->description(), SQL_LONGVARCHAR );
1196  $tst->bind_param( ++$i, $is_current, SQL_TINYINT );
1197 
1198  # If the transcript has a translation, this is updated later:
1199  $tst->bind_param( ++$i, undef, SQL_INTEGER );
1200 
1201  if ( defined( $transcript->stable_id() ) ) {
1202 
1203  $tst->bind_param( ++$i, $transcript->stable_id(), SQL_VARCHAR );
1204  $tst->bind_param( ++$i, $transcript->version(), SQL_INTEGER );
1205  }
1206 
1207  $tst->execute();
1208  $tst->finish();
1209 
1210  my $transc_dbID = $self->last_insert_id('transcript_id', undef, 'transcript');
1211 
1212  #
1213  # Store translation
1214  #
1215 
1216  my $alt_translations =
1217  $transcript->get_all_alternative_translations();
1218  my $translation = $transcript->translation();
1219 
1220  if ( defined($translation) ) {
1221  # Make sure that the start and end exon are set correctly.
1222  my $start_exon = $translation->start_Exon();
1223  my $end_exon = $translation->end_Exon();
1224 
1225  if ( !defined($start_exon) ) {
1226  throw("Translation does not define a start exon.");
1227  }
1228 
1229  if ( !defined($end_exon) ) {
1230  throw("Translation does not defined an end exon.");
1231  }
1232 
1233  # If the dbID is not set, this means the exon must have been a
1234  # different object in memory than the the exons of the transcript.
1235  # Try to find the matching exon in all of the exons we just stored.
1236  if ( !defined( $start_exon->dbID() ) ) {
1237  my $key = $start_exon->hashkey();
1238  ($start_exon) = grep { $_->hashkey() eq $key } @$exons;
1239 
1240  if ( defined($start_exon) ) {
1241  $translation->start_Exon($start_exon);
1242  } else {
1243  throw( "Translation's start_Exon does not appear "
1244  . "to be one of the exons in "
1245  . "its associated Transcript" );
1246  }
1247  }
1248 
1249  if ( !defined( $end_exon->dbID() ) ) {
1250  my $key = $end_exon->hashkey();
1251  ($end_exon) = grep { $_->hashkey() eq $key } @$exons;
1252 
1253  if ( defined($end_exon) ) {
1254  $translation->end_Exon($end_exon);
1255  } else {
1256  throw( "Translation's end_Exon does not appear "
1257  . "to be one of the exons in "
1258  . "its associated Transcript." );
1259  }
1260  }
1261 
1262  my $old_dbid = $translation->dbID();
1263  $db->get_TranslationAdaptor()->store( $translation, $transc_dbID );
1264 
1265  # Need to update the canonical_translation_id for this transcript.
1266 
1267  my $sth = $self->prepare(
1268  q(
1269  UPDATE transcript
1270  SET canonical_translation_id = ?
1271  WHERE transcript_id = ?)
1272  );
1273 
1274  $sth->bind_param( 1, $translation->dbID(), SQL_INTEGER );
1275  $sth->bind_param( 2, $transc_dbID, SQL_INTEGER );
1276 
1277  $sth->execute();
1278 
1279  # Set values of the original translation, we may have copied it when
1280  # we transformed the transcript.
1281  $original_translation->dbID( $translation->dbID() );
1282  $original_translation->adaptor( $translation->adaptor() );
1283  } ## end if ( defined($translation...))
1284 
1285  #
1286  # Store the alternative translations, if there are any.
1287  #
1288 
1289  if ( defined($alt_translations)
1290  && scalar( @{$alt_translations} ) > 0 )
1291  {
1292  foreach my $alt_translation ( @{$alt_translations} ) {
1293  my $start_exon = $alt_translation->start_Exon();
1294  my $end_exon = $alt_translation->end_Exon();
1295 
1296  if ( !defined($start_exon) ) {
1297  throw("Translation does not define a start exon.");
1298  } elsif ( !defined($end_exon) ) {
1299  throw("Translation does not defined an end exon.");
1300  }
1301 
1302  if ( !defined( $start_exon->dbID() ) ) {
1303  my $key = $start_exon->hashkey();
1304  ($start_exon) = grep { $_->hashkey() eq $key } @{$exons};
1305 
1306  if ( defined($start_exon) ) {
1307  $alt_translation->start_Exon($start_exon);
1308  } else {
1309  throw( "Translation's start_Exon does not appear "
1310  . "to be one of the exon in"
1311  . "its associated Transcript" );
1312  }
1313  }
1314  if ( !defined( $end_exon->dbID() ) ) {
1315  my $key = $end_exon->hashkey();
1316  ($end_exon) = grep { $_->hashkey() eq $key } @$exons;
1317 
1318  if ( defined($end_exon) ) {
1319  $alt_translation->end_Exon($end_exon);
1320  } else {
1321  throw( "Translation's end_Exon does not appear "
1322  . "to be one of the exons in "
1323  . "its associated Transcript." );
1324  }
1325  }
1326 
1327  $db->get_TranslationAdaptor()
1328  ->store( $alt_translation, $transc_dbID );
1329  } ## end foreach my $alt_translation...
1330  } ## end if ( defined($alt_translations...))
1331 
1332  #
1333  # Store the xrefs/object xref mapping.
1334  #
1335  my $dbEntryAdaptor = $db->get_DBEntryAdaptor();
1336 
1337  foreach my $dbe ( @{ $transcript->get_all_DBEntries() } ) {
1338  $dbEntryAdaptor->store( $dbe, $transc_dbID, "Transcript", 1 );
1339  }
1340 
1341  #
1342  # Update transcript to point to display xref if it is set.
1343  #
1344  if ( my $dxref = $transcript->display_xref() ) {
1345  my $dxref_id;
1346 
1347  if ( $dxref->is_stored($db) ) {
1348  $dxref_id = $dxref->dbID();
1349  } else {
1350  $dxref_id = $dbEntryAdaptor->exists($dxref);
1351  }
1352 
1353  if ( defined($dxref_id) ) {
1354  my $sth =
1355  $self->prepare( "UPDATE transcript "
1356  . "SET display_xref_id = ? "
1357  . "WHERE transcript_id = ?" );
1358  $sth->bind_param( 1, $dxref_id, SQL_INTEGER );
1359  $sth->bind_param( 2, $transc_dbID, SQL_INTEGER );
1360  $sth->execute();
1361  $dxref->dbID($dxref_id);
1362  $dxref->adaptor($dbEntryAdaptor);
1363  $sth->finish();
1364  } else {
1365  warning(sprintf(
1366  "Display_xref %s:%s is not stored in database.\n"
1367  . "Not storing relationship to this transcript.",
1368  $dxref->dbname(), $dxref->display_id() ) );
1369  $dxref->dbID(undef);
1370  $dxref->adaptor(undef);
1371  }
1372  } ## end if ( my $dxref = $transcript...)
1373 
1374  #
1375  # Link transcript to exons in exon_transcript table
1376  #
1377  my $etst = $self->prepare(
1378  "INSERT INTO exon_transcript (`exon_id`,`transcript_id`,`rank`) "
1379  . "VALUES (?,?,?)" );
1380  my $rank = 1;
1381  foreach my $exon ( @{ $transcript->get_all_Exons } ) {
1382  $etst->bind_param( 1, $exon->dbID, SQL_INTEGER );
1383  $etst->bind_param( 2, $transc_dbID, SQL_INTEGER );
1384  $etst->bind_param( 3, $rank, SQL_INTEGER );
1385  $etst->execute();
1386  $rank++;
1387  }
1388 
1389  $etst->finish();
1390 
1391  # Now the supporting evidence
1392  my $tsf_adaptor = $db->get_TranscriptSupportingFeatureAdaptor();
1393  $tsf_adaptor->store( $transc_dbID,
1394  $transcript->get_all_supporting_features() );
1395 
1396  # store transcript attributes if there are any
1397  my $attr_adaptor = $db->get_AttributeAdaptor();
1398 
1399  $attr_adaptor->store_on_Transcript( $transc_dbID,
1400  $transcript->get_all_Attributes() );
1401 
1402  # Check if transcript is canonical
1403  if ($transcript->is_canonical()) {
1404  my $gene_adaptor = $self->db()->get_GeneAdaptor();
1405  my $gene = $gene_adaptor->fetch_by_dbID($gene_dbID);
1406  $transcript->dbID($transc_dbID);
1407  $gene->canonical_transcript($transcript);
1408  $gene_adaptor->update($gene);
1409  }
1410 
1411  # store the IntronSupportingEvidence features
1412  my $ise_adaptor = $db->get_IntronSupportingEvidenceAdaptor();
1413  my $intron_supporting_evidence = $transcript->get_all_IntronSupportingEvidence();
1414  foreach my $ise (@{$intron_supporting_evidence}) {
1415  $ise_adaptor->store($ise);
1416  $ise_adaptor->store_transcript_linkage($ise, $transcript, $transc_dbID);
1417  }
1418 
1419  # Update the original transcript object - not the transfered copy that
1420  # we might have created.
1421  $original->dbID($transc_dbID);
1422  $original->adaptor($self);
1423 
1424  return $transc_dbID;
1425 } ## end sub store
1426 
1427 
1428 =head2 get_Interpro_by_transid
1429 
1430  Arg [1] : String $trans_stable_id
1431  The stable if of the transcript to obtain
1432  Example : @i = $tr_adaptor->get_Interpro_by_transid($trans->stable_id());
1433  Description: Gets interpro accession numbers by transcript stable id.
1434  A hack really - we should have a much more structured
1435  system than this.
1436  Returntype : listref of strings (Interpro_acc:description)
1437  Exceptions : none
1438  Caller : domainview? , GeneView
1439  Status : Stable
1440 
1441 =cut
1442 
1443 sub get_Interpro_by_transid {
1444  my ($self,$trans_stable_id) = @_;
1445 
1446  my $straight_join = $self->_can_straight_join ? 'STRAIGHT_JOIN' : '';
1447  my $sth = $self->prepare(qq(
1448  SELECT ${straight_join} i.interpro_ac, x.description
1449  FROM transcript t,
1450  translation tl,
1451  protein_feature pf,
1452  interpro i,
1453  xref x
1454  WHERE t.stable_id = ?
1455  AND tl.transcript_id = t.transcript_id
1456  AND tl.translation_id = pf.translation_id
1457  AND i.id = pf.hit_name
1458  AND i.interpro_ac = x.dbprimary_acc
1459  AND t.is_current = 1
1460  ));
1461 
1462  $sth->bind_param(1, $trans_stable_id, SQL_VARCHAR);
1463  $sth->execute();
1464 
1465  my @out;
1466  my %h;
1467  while( (my $arr = $sth->fetchrow_arrayref()) ) {
1468  if( $h{$arr->[0]} ) { next; }
1469  $h{$arr->[0]}=1;
1470  my $string = $arr->[0] .":".$arr->[1];
1471  push(@out,$string);
1472  }
1473 
1474  return \@out;
1475 }
1476 
1477 =head2 is_Transcript_canonical()
1478 
1479  Arg [1] : Bio::EnsEMBL::Transcript $transcript
1480  The transcript to query with
1481  Example : $tr_adaptor->is_Transcript_canonical($transcript);
1482  Description : Returns a boolean if the given transcript is considered
1483  canonical with respect to a gene
1484  Returntype : Boolean
1485  Exceptions : None
1486  Caller : Bio::EnsEMBL::Transcript
1487  Status : Beta
1488 
1489 
1490 =cut
1491 
1492 sub is_Transcript_canonical {
1493  my ($self, $transcript) = @_;
1494  return $self->dbc()->sql_helper()->execute_single_result(
1495  -SQL => 'select count(*) from gene where canonical_transcript_id =?',
1496  -PARAMS => [$transcript->dbID()]
1497  );
1498 }
1499 
1500 
1501 =head2 remove
1502 
1503  Arg [1] : Bio::EnsEMBL::Transcript $transcript
1504  The transcript to remove from the database
1505  Arg [2] : Boolean, update Gene coordinates after removal. WARNING: this does not alter any other copies of the
1506  gene currently in memory. Other copies will retain their original coordinates. Either refetch them
1507  or go directly through Gene->remove_Transcript first, then remove the Transcript here.
1508  Example : $tr_adaptor->remove($transcript);
1509  Description: Removes a transcript completely from the database, and all
1510  associated information.
1511  This method is usually called by the GeneAdaptor::remove method
1512  because this method will not preform the removal of genes
1513  which are associated with this transcript. Do not call this
1514  method directly unless you know there are no genes associated
1515  with the transcript!
1516  Returntype : none
1517  Exceptions : throw on incorrect arguments
1518  warning if transcript is not in this database
1519  Caller : GeneAdaptor::remove
1520  Status : Stable
1521 
1522 =cut
1523 
1524 sub remove {
1525  my $self = shift;
1526  my $transcript = shift;
1527  my $update = shift;
1528  if(!ref($transcript) || !$transcript->isa('Bio::EnsEMBL::Transcript')) {
1529  throw("Bio::EnsEMBL::Transcript argument expected");
1530  }
1531 
1532  # sanity check: make sure nobody tries to slip past a prediction transcript
1533  # which inherits from transcript but actually uses different tables
1534  if($transcript->isa('Bio::EnsEMBL::PredictionTranscript')) {
1535  throw("TranscriptAdaptor can only remove Transcripts " .
1536  "not PredictionTranscripts");
1537  }
1538 
1539  if ( !$transcript->is_stored($self->db()) ) {
1540  warning("Cannot remove transcript ". $transcript->dbID .". Is not stored ".
1541  "in this database.");
1542  return;
1543  }
1544 
1545  # remove the supporting features of this transcript
1546 
1547  my $prot_adp = $self->db->get_ProteinAlignFeatureAdaptor;
1548  my $dna_adp = $self->db->get_DnaAlignFeatureAdaptor;
1549 
1550  my $sfsth = $self->prepare("SELECT feature_type, feature_id " .
1551  "FROM transcript_supporting_feature " .
1552  "WHERE transcript_id = ?");
1553 
1554  $sfsth->bind_param(1, $transcript->dbID, SQL_INTEGER);
1555  $sfsth->execute();
1556 
1557  # statements to check for shared align_features
1558  my $sth1 = $self->prepare("SELECT count(*) FROM supporting_feature " .
1559  "WHERE feature_type = ? AND feature_id = ?");
1560  my $sth2 = $self->prepare("SELECT count(*) " .
1561  "FROM transcript_supporting_feature " .
1562  "WHERE feature_type = ? AND feature_id = ?");
1563 
1564  SUPPORTING_FEATURE:
1565  while(my ($type, $feature_id) = $sfsth->fetchrow()){
1566 
1567  # only remove align_feature if this is the last reference to it
1568  $sth1->bind_param(1, $type, SQL_VARCHAR);
1569  $sth1->bind_param(2, $feature_id, SQL_INTEGER);
1570  $sth1->execute;
1571  $sth2->bind_param(1, $type, SQL_VARCHAR);
1572  $sth2->bind_param(2, $feature_id, SQL_INTEGER);
1573  $sth2->execute;
1574  my ($count1) = $sth1->fetchrow;
1575  my ($count2) = $sth2->fetchrow;
1576  if ($count1 + $count2 > 1) {
1577  #warn "transcript: shared feature, not removing $type|$feature_id\n";
1578  next SUPPORTING_FEATURE;
1579  }
1580 
1581  #warn "transcript: removing $type|$feature_id\n";
1582 
1583  if($type eq 'protein_align_feature'){
1584  my $f = $prot_adp->fetch_by_dbID($feature_id);
1585  $prot_adp->remove($f);
1586  }
1587  elsif($type eq 'dna_align_feature'){
1588  my $f = $dna_adp->fetch_by_dbID($feature_id);
1589  $dna_adp->remove($f);
1590  }
1591  else {
1592  warning("Unknown supporting feature type $type. Not removing feature.");
1593  }
1594  }
1595  $sfsth->finish();
1596  $sth1->finish();
1597  $sth2->finish();
1598 
1599  # delete the association to supporting features
1600 
1601  $sfsth = $self->prepare("DELETE FROM transcript_supporting_feature WHERE transcript_id = ?");
1602  $sfsth->bind_param(1, $transcript->dbID, SQL_INTEGER);
1603  $sfsth->execute();
1604  $sfsth->finish();
1605 
1606  # delete the associated IntronSupportingEvidence and if the ISE had no more
1607  # linked transcripts remove it
1608  my $ise_adaptor = $self->db->get_IntronSupportingEvidenceAdaptor();
1609  foreach my $ise (@{$transcript->get_all_IntronSupportingEvidence()}) {
1610  $ise_adaptor->remove_transcript_linkage($ise, $transcript);
1611  if(! $ise->has_linked_transcripts()) {
1612  $ise_adaptor->remove($ise);
1613  }
1614  }
1615 
1616  # remove all xref linkages to this transcript
1617 
1618  my $dbeAdaptor = $self->db->get_DBEntryAdaptor();
1619  foreach my $dbe (@{$transcript->get_all_DBEntries}) {
1620  $dbeAdaptor->remove_from_object($dbe, $transcript, 'Transcript');
1621  }
1622 
1623  # remove the attributes associated with this transcript
1624  my $attrib_adp = $self->db->get_AttributeAdaptor;
1625  $attrib_adp->remove_from_Transcript($transcript);
1626 
1627  # remove the translation associated with this transcript
1628 
1629  my $translationAdaptor = $self->db->get_TranslationAdaptor();
1630  if( defined($transcript->translation()) ) {
1631  $translationAdaptor->remove( $transcript->translation );
1632  }
1633 
1634  # remove exon associations to this transcript
1635 
1636  my $exonAdaptor = $self->db->get_ExonAdaptor();
1637  foreach my $exon ( @{$transcript->get_all_Exons()} ) {
1638  # get the number of transcript references to this exon
1639  # only remove the exon if this is the last transcript to
1640  # reference it
1641 
1642  my $sth = $self->prepare( "SELECT count(*)
1643  FROM exon_transcript
1644  WHERE exon_id = ?" );
1645  $sth->bind_param(1, $exon->dbID, SQL_INTEGER);
1646  $sth->execute();
1647  my ($count) = $sth->fetchrow_array();
1648  $sth->finish();
1649 
1650  if($count == 1){
1651  $exonAdaptor->remove( $exon );
1652  }
1653  }
1654 
1655  my $sth = $self->prepare( "DELETE FROM exon_transcript
1656  WHERE transcript_id = ?" );
1657  $sth->bind_param(1, $transcript->dbID, SQL_INTEGER);
1658  $sth->execute();
1659  $sth->finish();
1660 
1661  my $gene = $transcript->get_Gene;
1662 
1663  $sth = $self->prepare( "DELETE FROM transcript
1664  WHERE transcript_id = ?" );
1665  $sth->bind_param(1, $transcript->dbID, SQL_INTEGER);
1666  $sth->execute();
1667  $sth->finish();
1668 
1669  if ($update) {
1670  $gene->remove_Transcript($transcript);
1671  }
1672 
1673  $transcript->dbID(undef);
1674  $transcript->adaptor(undef);
1675 
1676  return;
1677 }
1678 
1679 
1680 =head2 update
1681 
1682  Arg [1] : Bio::EnsEMBL::Transcript $transcript
1683  The transcript to update
1684  Example : $tr_adaptor->update($transcript);
1685  Description: Updates a transcript in the database.
1686  Returntype : None
1687  Exceptions : thrown if the $transcript is not a Bio::EnsEMBL::Transcript.
1688  warn if the method is called on a transcript that does not exist
1689  in the database.
1690  Should warn if trying to update the number of attached exons, but
1691  this is a far more complex process and is not yet implemented.
1692  Caller : general
1693  Status : Stable
1694 
1695 =cut
1696 
1697 sub update {
1698  my ( $self, $transcript ) = @_;
1699 
1700  if ( !defined($transcript)
1701  || !ref($transcript)
1702  || !$transcript->isa('Bio::EnsEMBL::Transcript') )
1703  {
1704  throw("Must update a transcript object, not a $transcript");
1705  }
1706 
1707  my $update_transcript_sql =
1708  sprintf "UPDATE transcript SET stable_id = ?, analysis_id = ?, display_xref_id = ?, description = ?,%s biotype = ?, is_current = ?, canonical_translation_id = ?, version = ? WHERE transcript_id = ?", ($self->schema_version > 74)?" source = ?,":'';
1709 
1710  my $display_xref = $transcript->display_xref();
1711  my $display_xref_id;
1712 
1713  if ( defined($display_xref) && $display_xref->dbID() ) {
1714  $display_xref_id = $display_xref->dbID();
1715  } else {
1716  $display_xref_id = undef;
1717  }
1718 
1719  my $sth = $self->prepare($update_transcript_sql);
1720  my $i = 0;
1721  $sth->bind_param( ++$i, $transcript->stable_id(), SQL_VARCHAR );
1722  $sth->bind_param( ++$i, $transcript->analysis()->dbID(), SQL_INTEGER );
1723  $sth->bind_param( ++$i, $display_xref_id, SQL_INTEGER );
1724  $sth->bind_param( ++$i, $transcript->description(), SQL_LONGVARCHAR );
1725 
1726  $self->schema_version > 74 and
1727  $sth->bind_param( ++$i, $transcript->source(), SQL_VARCHAR );
1728 
1729  $sth->bind_param( ++$i, $transcript->get_Biotype->name, SQL_VARCHAR );
1730  $sth->bind_param( ++$i, $transcript->is_current(), SQL_TINYINT );
1731  $sth->bind_param( ++$i, (
1732  defined( $transcript->translation() )
1733  ? $transcript->translation()->dbID()
1734  : undef ),
1735  SQL_INTEGER );
1736  $sth->bind_param( ++$i, $transcript->version(), SQL_INTEGER );
1737  $sth->bind_param( ++$i, $transcript->dbID(), SQL_INTEGER );
1738 
1739  $sth->execute();
1740 
1741  # Check if transcript is canonical
1742  if ($transcript->is_canonical()) {
1743  my $gene = $transcript->get_Gene();
1744  my $gene_adaptor = $self->db()->get_GeneAdaptor();
1745  $gene->canonical_transcript($transcript);
1746  $gene_adaptor->update($gene);
1747  }
1748 
1749 } ## end sub update
1750 
1751 
1752 =head2 list_dbIDs
1753 
1754  Example : @transcript_ids = @{ $t_adaptor->list_dbIDs };
1755  Description: Gets a list of internal ids for all transcripts in the db.
1756  Arg[1] : <optional> int. not 0 for the ids to be sorted by the seq_region. Returntype : Listref of Ints
1757  Exceptions : none
1758  Caller : general
1759  Status : Stable
1760 
1761 =cut
1762 
1763 sub list_dbIDs {
1764  my ($self, $ordered) = @_;
1765 
1766  return $self->_list_dbIDs("transcript",undef, $ordered);
1767 }
1768 
1769 
1770 =head2 list_stable_ids
1771 
1772  Example : @stable_trans_ids = @{ $transcript_adaptor->list_stable_ids };
1773  Description: Gets a list of stable ids for all transcripts in the current
1774  database.
1775  Returntype : Listref of Strings
1776  Exceptions : none
1777  Caller : general
1778  Status : Stable
1779 
1780 =cut
1781 
1782 sub list_stable_ids {
1783  my ($self) = @_;
1784 
1785  return $self->_list_dbIDs("transcript", "stable_id");
1786 }
1787 
1788 
1789 #_objs_from_sth
1790 
1791 # Arg [1] : StatementHandle $sth
1792 # Arg [2] : Bio::EnsEMBL::AssemblyMapper $mapper
1793 # Arg [3] : Bio::EnsEMBL::Slice $dest_slice
1794 # Description: PROTECTED implementation of abstract superclass method.
1795 # Responsible for the creation of Transcripts.
1796 # Returntype : Listref of Bio::EnsEMBL::Transcripts in target coord system
1797 # Exceptions : none
1798 # Caller : internal
1799 # Status : Stable
1800 
1801 sub _objs_from_sth {
1802  my ($self, $sth, $mapper, $dest_slice) = @_;
1803 
1804  #
1805  # This code is ugly because an attempt has been made to remove as many
1806  # function calls as possible for speed purposes. Thus many caches and
1807  # a fair bit of gymnastics is used.
1808  #
1809 
1810  my $sa = $self->db()->get_SliceAdaptor();
1811  my $aa = $self->db()->get_AnalysisAdaptor();
1812  my $dbEntryAdaptor = $self->db()->get_DBEntryAdaptor();
1813 
1814  my @transcripts;
1815  my %analysis_hash;
1816  my %slice_hash;
1817  my %sr_name_hash;
1818  my %sr_cs_hash;
1819 
1820  my (
1821  $transcript_id, $seq_region_id, $seq_region_start,
1822  $seq_region_end, $seq_region_strand, $analysis_id,
1823  $gene_id, $is_current, $stable_id,
1824  $version, $created_date, $modified_date,
1825  $description, $biotype,
1826  $external_db, $external_status, $external_db_name,
1827  $display_xref_id, $xref_display_label, $xref_primary_acc,
1828  $xref_version, $xref_description, $xref_info_type,
1829  $xref_info_text, $external_release, $source
1830  );
1831 
1832  if ($self->schema_version() > 74) {
1833  $sth->bind_columns(
1834  \(
1835  $transcript_id, $seq_region_id, $seq_region_start,
1836  $seq_region_end, $seq_region_strand, $analysis_id,
1837  $gene_id, $is_current, $stable_id,
1838  $version, $created_date, $modified_date,
1839  $description, $biotype,
1840  $external_db, $external_status, $external_db_name,
1841  $display_xref_id, $xref_display_label, $xref_primary_acc,
1842  $xref_version, $xref_description, $xref_info_type,
1843  $xref_info_text, $external_release, $source
1844  ) );
1845  } else {
1846  $sth->bind_columns(
1847  \(
1848  $transcript_id, $seq_region_id, $seq_region_start,
1849  $seq_region_end, $seq_region_strand, $analysis_id,
1850  $gene_id, $is_current, $stable_id,
1851  $version, $created_date, $modified_date,
1852  $description, $biotype,
1853  $external_db, $external_status, $external_db_name,
1854  $display_xref_id, $xref_display_label, $xref_primary_acc,
1855  $xref_version, $xref_description, $xref_info_type,
1856  $xref_info_text, $external_release
1857  ) );
1858  }
1859 
1860  my $dest_slice_start;
1861  my $dest_slice_end;
1862  my $dest_slice_strand;
1863  my $dest_slice_length;
1864  my $dest_slice_cs;
1865  my $dest_slice_sr_name;
1866  my $dest_slice_sr_id;
1867  my $asma;
1868 
1869  if ($dest_slice) {
1870  $dest_slice_start = $dest_slice->start();
1871  $dest_slice_end = $dest_slice->end();
1872  $dest_slice_strand = $dest_slice->strand();
1873  $dest_slice_length = $dest_slice->length();
1874  $dest_slice_cs = $dest_slice->coord_system();
1875  $dest_slice_sr_name = $dest_slice->seq_region_name();
1876  $dest_slice_sr_id = $dest_slice->get_seq_region_id();
1877  $asma = $self->db->get_AssemblyMapperAdaptor();
1878  }
1879 
1880  FEATURE: while($sth->fetch()) {
1881 
1882  #get the analysis object
1883  my $analysis = $analysis_hash{$analysis_id} ||= $aa->fetch_by_dbID($analysis_id);
1884  $analysis_hash{$analysis_id} = $analysis;
1885 
1886  #need to get the internal_seq_region, if present
1887  $seq_region_id = $self->get_seq_region_id_internal($seq_region_id);
1888  my $slice = $slice_hash{"ID:".$seq_region_id};
1889 
1890  if (!$slice) {
1891  $slice = $sa->fetch_by_seq_region_id($seq_region_id);
1892  $slice_hash{"ID:".$seq_region_id} = $slice;
1893  $sr_name_hash{$seq_region_id} = $slice->seq_region_name();
1894  $sr_cs_hash{$seq_region_id} = $slice->coord_system();
1895  }
1896 
1897  #obtain a mapper if none was defined, but a dest_seq_region was
1898  if(!$mapper && $dest_slice && !$dest_slice_cs->equals($slice->coord_system)) {
1899  $mapper = $asma->fetch_by_CoordSystems($dest_slice_cs, $slice->coord_system);
1900  }
1901 
1902  my $sr_name = $sr_name_hash{$seq_region_id};
1903  my $sr_cs = $sr_cs_hash{$seq_region_id};
1904 
1905  #
1906  # remap the feature coordinates to another coord system
1907  # if a mapper was provided
1908  #
1909 
1910  if ($mapper) {
1911 
1912  if (defined $dest_slice && $mapper->isa('Bio::EnsEMBL::ChainedAssemblyMapper') ) {
1913  ($seq_region_id, $seq_region_start, $seq_region_end, $seq_region_strand) =
1914  $mapper->map($sr_name, $seq_region_start, $seq_region_end, $seq_region_strand, $sr_cs, 1, $dest_slice);
1915 
1916  } else {
1917  ($seq_region_id, $seq_region_start, $seq_region_end, $seq_region_strand) =
1918  $mapper->fastmap($sr_name, $seq_region_start, $seq_region_end, $seq_region_strand, $sr_cs);
1919  }
1920 
1921  #skip features that map to gaps or coord system boundaries
1922  next FEATURE if (!defined($seq_region_id));
1923 
1924  #get a slice in the coord system we just mapped to
1925  $slice = $slice_hash{"ID:".$seq_region_id} ||= $sa->fetch_by_seq_region_id($seq_region_id);
1926  }
1927 
1928  #
1929  # If a destination slice was provided convert the coords.
1930  #
1931  if (defined($dest_slice)) {
1932  my $seq_region_len = $dest_slice->seq_region_length();
1933 
1934  if ( $dest_slice_strand == 1 ) {
1935  $seq_region_start = $seq_region_start - $dest_slice_start + 1;
1936  $seq_region_end = $seq_region_end - $dest_slice_start + 1;
1937 
1938  if ( $dest_slice->is_circular ) {
1939  # Handle circular chromosomes.
1940 
1941  if ( $seq_region_start > $seq_region_end ) {
1942  # Looking at a feature overlapping the chromosome origin.
1943 
1944  if ( $seq_region_end > $dest_slice_start ) {
1945  # Looking at the region in the beginning of the chromosome
1946  $seq_region_start -= $seq_region_len;
1947  }
1948  if ( $seq_region_end < 0 ) {
1949  $seq_region_end += $seq_region_len;
1950  }
1951  } else {
1952  if ($dest_slice_start > $dest_slice_end && $seq_region_end < 0) {
1953  # Looking at the region overlapping the chromosome
1954  # origin and a feature which is at the beginning of the
1955  # chromosome.
1956  $seq_region_start += $seq_region_len;
1957  $seq_region_end += $seq_region_len;
1958  }
1959  }
1960  }
1961  } else {
1962 
1963  my $start = $dest_slice_end - $seq_region_end + 1;
1964  my $end = $dest_slice_end - $seq_region_start + 1;
1965 
1966  if ($dest_slice->is_circular()) {
1967 
1968  if ($dest_slice_start > $dest_slice_end) {
1969  # slice spans origin or replication
1970 
1971  if ($seq_region_start >= $dest_slice_start) {
1972  $end += $seq_region_len;
1973  $start += $seq_region_len if $seq_region_end > $dest_slice_start;
1974 
1975  } elsif ($seq_region_start <= $dest_slice_end) {
1976  # do nothing
1977  } elsif ($seq_region_end >= $dest_slice_start) {
1978  $start += $seq_region_len;
1979  $end += $seq_region_len;
1980 
1981  } elsif ($seq_region_end <= $dest_slice_end) {
1982  $end += $seq_region_len if $end < 0;
1983 
1984  } elsif ($seq_region_start > $seq_region_end) {
1985  $end += $seq_region_len;
1986  }
1987 
1988  } else {
1989 
1990  if ($seq_region_start <= $dest_slice_end and $seq_region_end >= $dest_slice_start) {
1991  # do nothing
1992  } elsif ($seq_region_start > $seq_region_end) {
1993  if ($seq_region_start <= $dest_slice_end) {
1994  $start -= $seq_region_len;
1995  } elsif ($seq_region_end >= $dest_slice_start) {
1996  $end += $seq_region_len;
1997  }
1998  }
1999  }
2000  }
2001 
2002  $seq_region_start = $start;
2003  $seq_region_end = $end;
2004  $seq_region_strand *= -1;
2005 
2006  } ## end else [ if ( $dest_slice_strand...)]
2007 
2008  # Throw away features off the end of the requested slice or on
2009  # different seq_region.
2010  if ($seq_region_end < 1
2011  || $seq_region_start > $dest_slice_length
2012  || ($dest_slice_sr_id != $seq_region_id)) {
2013  next FEATURE;
2014  }
2015  $slice = $dest_slice;
2016  }
2017 
2018  my $display_xref;
2019 
2020  if ($display_xref_id) {
2021  $display_xref = Bio::EnsEMBL::DBEntry->new_fast( {
2022  'dbID' => $display_xref_id,
2023  'adaptor' => $dbEntryAdaptor,
2024  'display_id' => $xref_display_label,
2025  'primary_id' => $xref_primary_acc,
2026  'version' => $xref_version,
2027  'description' => $xref_description,
2028  'release' => $external_release,
2029  'dbname' => $external_db,
2030  'db_display_name' => $external_db_name,
2031  'info_type' => $xref_info_type,
2032  'info_text' => $xref_info_text
2033  });
2034  $display_xref->status($external_status);
2035  }
2036 
2037  # Finally, create the new Transcript.
2038  my $params =
2039  {
2040  'analysis' => $analysis,
2041  'biotype' => $biotype,
2042  'start' => $seq_region_start,
2043  'end' => $seq_region_end,
2044  'strand' => $seq_region_strand,
2045  'adaptor' => $self,
2046  'slice' => $slice,
2047  'dbID' => $transcript_id,
2048  'stable_id' => $stable_id,
2049  'version' => $version,
2050  'created_date' => $created_date || undef,
2051  'modified_date' => $modified_date || undef,
2052  'description' => $description,
2053  'external_name' => $xref_display_label,
2054 
2055  'external_status' => $external_status,
2056  'external_display_name' => $external_db_name,
2057  'external_db' => $external_db,
2058  'display_xref' => $display_xref,
2059  'is_current' => $is_current,
2060  'edits_enabled' => 1
2061  };
2062 
2063  $self->schema_version > 74 and $params->{'source'} = $source;
2064  push( @transcripts,
2065  $self->_create_feature_fast(
2066  'Bio::EnsEMBL::Transcript',$params) );
2067 
2068  }
2069 
2070  return \@transcripts;
2071 }
2072 
2073 
2074 =head2 fetch_all_by_exon_supporting_evidence
2075 
2076  Arg [1] : String $hit_name
2077  Name of supporting feature
2078  Arg [2] : String $feature_type
2079  one of "dna_align_feature" or "protein_align_feature"
2080  Arg [3] : (optional) Bio::Ensembl::Analysis
2081  Example : $tr = $tr_adaptor->fetch_all_by_exon_supporting_evidence
2082  ('XYZ', 'dna_align_feature');
2083  Description: Gets all the transcripts with exons which have a specified hit
2084  on a particular type of feature. Optionally filter by analysis.
2085  Returntype : Listref of Bio::EnsEMBL::Transcript objects
2086  Exceptions : If feature_type is not of correct type.
2087  Caller : general
2088  Status : Stable
2089 
2090 =cut
2091 
2092 sub fetch_all_by_exon_supporting_evidence {
2093  my ($self, $hit_name, $feature_type, $analysis) = @_;
2094 
2095  if($feature_type !~ /(dna)|(protein)_align_feature/) {
2096  throw("feature type must be dna_align_feature or protein_align_feature");
2097  }
2098 
2099  my $anal_from = "";
2100  $anal_from = ", analysis a " if ($analysis);
2101  my $anal_where = "";
2102  $anal_where = "AND a.analysis_id = f.analysis_id AND a.analysis_id=? "
2103  if ($analysis);
2104 
2105  my $sql = qq(
2106  SELECT DISTINCT(t.transcript_id)
2107  FROM transcript t,
2108  exon_transcript et,
2109  supporting_feature sf,
2110  $feature_type f
2111  $anal_from
2112  WHERE t.transcript_id = et.transcript_id
2113  AND t.is_current = 1
2114  AND et.exon_id = sf.exon_id
2115  AND sf.feature_id = f.${feature_type}_id
2116  AND sf.feature_type = ?
2117  AND f.hit_name=?
2118  $anal_where
2119  );
2120 
2121  my $sth = $self->prepare($sql);
2122 
2123  $sth->bind_param(1, $feature_type, SQL_VARCHAR);
2124  $sth->bind_param(2, $hit_name, SQL_VARCHAR);
2125  $sth->bind_param(3, $analysis->dbID(), SQL_INTEGER) if ($analysis);
2126 
2127  $sth->execute();
2128 
2129  my @transcripts;
2130 
2131  while( my $id = $sth->fetchrow_array ) {
2132  my $transcript = $self->fetch_by_dbID( $id );
2133  push(@transcripts, $transcript) if $transcript;
2134  }
2135 
2136  return \@transcripts;
2137 }
2138 
2139 
2140 =head2 fetch_all_by_transcript_supporting_evidence
2141 
2142  Arg [1] : String $hit_name
2143  Name of supporting feature
2144  Arg [2] : String $feature_type
2145  one of "dna_align_feature" or "protein_align_feature"
2146  Arg [3] : (optional) Bio::Ensembl::Analysis
2147  Example : $transcripts = $transcript_adaptor->fetch_all_by_transcript_supporting_evidence('XYZ', 'dna_align_feature');
2148  Description: Gets all the transcripts with evidence from a specified hit_name on a particular type of feature, stored in the
2149  transcript_supporting_feature table. Optionally filter by analysis. For hits stored in the supporting_feature
2150  table (linked to exons) use fetch_all_by_exon_supporting_evidence instead.
2151  Returntype : Listref of Bio::EnsEMBL::Transcript objects
2152  Exceptions : If feature_type is not of correct type.
2153  Caller : general
2154  Status : Stable
2155 
2156 =cut
2157 
2158 sub fetch_all_by_transcript_supporting_evidence {
2159 
2160  my ($self, $hit_name, $feature_type, $analysis) = @_;
2161 
2162  if($feature_type !~ /(dna)|(protein)_align_feature/) {
2163  throw("feature type must be dna_align_feature or protein_align_feature");
2164  }
2165 
2166  my $anal_from = "";
2167  $anal_from = ", analysis a " if ($analysis);
2168  my $anal_where = "";
2169  $anal_where = "AND a.analysis_id = f.analysis_id AND a.analysis_id=? "
2170  if ($analysis);
2171 
2172  my $sql = qq(
2173  SELECT DISTINCT(t.transcript_id)
2174  FROM transcript t,
2175  transcript_supporting_feature sf,
2176  $feature_type f
2177  $anal_from
2178  WHERE t.transcript_id = sf.transcript_id
2179  AND t.is_current = 1
2180  AND sf.feature_id = f.${feature_type}_id
2181  AND sf.feature_type = ?
2182  AND f.hit_name=?
2183  $anal_where
2184  );
2185 
2186  my $sth = $self->prepare($sql);
2187 
2188  $sth->bind_param(1, $feature_type, SQL_VARCHAR);
2189  $sth->bind_param(2, $hit_name, SQL_VARCHAR);
2190  $sth->bind_param(3, $analysis->dbID(), SQL_INTEGER) if ($analysis);
2191 
2192  $sth->execute();
2193 
2194  my @transcripts;
2195 
2196  while( my $id = $sth->fetchrow_array ) {
2197  my $transcript = $self->fetch_by_dbID( $id );
2198  push(@transcripts, $transcript) if $transcript;
2199  }
2200 
2201  return \@transcripts;
2202 }
2203 
2204 sub _final_clause {
2205  return ' ORDER BY t.transcript_id'
2206 }
2207 
2208 sub update_canonical_attribute {
2209  my ($self, $transcript_id, $old_transcript_id) = @_;
2210 
2211  # Get canonical attribute id
2212  my $db = $self->db();
2213  my $attr_adaptor = $db->get_AttributeAdaptor();
2214  my $canonical_attrib_id = @{$attr_adaptor->fetch_by_code('is_canonical')}[0];
2215  throw("No attrib_type_id found for 'is_canonical' attribute in attrib_type table.") if (!defined($canonical_attrib_id));
2216 
2217  # Check if new canonical transcript attribute exists
2218  my $sth = $self->prepare("SELECT value FROM transcript_attrib WHERE transcript_id=? AND attrib_type_id=?");
2219  $sth->execute($transcript_id, $canonical_attrib_id);
2220  if (my ($exists) = $sth->fetchrow_array()) {
2221  $sth->finish();
2222 
2223  $sth = $self->prepare("UPDATE transcript_attrib SET value=? WHERE transcript_id=? AND attrib_type_id=?");
2224  $sth->execute('1', $transcript_id, $canonical_attrib_id);
2225  } else {
2226  $sth->finish();
2227 
2228  $sth = $self->prepare("INSERT INTO transcript_attrib (transcript_id, attrib_type_id, value) values(?,?,?)");
2229  $sth->execute($transcript_id, $canonical_attrib_id, '1');
2230  }
2231  $sth->finish();
2232 
2233  # Delete old canonical transcript attribute
2234  if (defined($old_transcript_id) && $old_transcript_id ne $transcript_id) {
2235  $sth = $self->prepare("DELETE FROM transcript_attrib WHERE transcript_id=? AND attrib_type_id=?");
2236  $sth->execute($old_transcript_id, $canonical_attrib_id);
2237  $sth->finish();
2238  }
2239 }
2240 
2241 1;
transcript
public transcript()
Bio::EnsEMBL::Translation
Definition: Translation.pm:32
Bio::EnsEMBL::Registry::get_adaptor
public Adaptor get_adaptor()
Bio::EnsEMBL::Storable::dbID
public Int dbID()
EnsEMBL
Definition: Filter.pm:1
map
public map()
Bio::EnsEMBL::Slice::is_reference
public Int is_reference()
Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor
Definition: BaseFeatureAdaptor.pm:24
Bio::EnsEMBL::DBSQL::TranscriptAdaptor
Definition: TranscriptAdaptor.pm:47
accession
public accession()
Bio::EnsEMBL::Gene
Definition: Gene.pm:37
Bio::EnsEMBL::Slice
Definition: Slice.pm:50
Bio::EnsEMBL::Registry
Definition: Registry.pm:113
exon
public exon()
Bio::EnsEMBL::Exon
Definition: Exon.pm:42
Bio::EnsEMBL::Transcript
Definition: Transcript.pm:44
Bio::EnsEMBL::Utils::Scalar
Definition: Scalar.pm:66
Bio::EnsEMBL::Registry::load_registry_from_db
public Int load_registry_from_db()
Bio::EnsEMBL::Feature::slice
public Bio::EnsEMBL::Slice slice()
Bio::EnsEMBL::DBEntry
Definition: DBEntry.pm:12
Bio::EnsEMBL::OntologyTerm
Definition: OntologyTerm.pm:10
Bio::EnsEMBL::Storable::new_fast
public Instance new_fast()
Bio
Definition: AltAlleleGroup.pm:4
Bio::EnsEMBL::Utils::Exception
Definition: Exception.pm:68