ensembl-hive  2.7.0
OperonAdaptor.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 
22 =head1 CONTACT
23 
24  Please email comments or questions to the public Ensembl
25  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.
26 
27  Questions may also be sent to the Ensembl help desk at
28  <http://www.ensembl.org/Help/Contact>.
29 
30 =cut
31 
32 =head1 NAME
33 
34 Bio::EnsEMBL::DBSQL::OperonAdaptor - Database adaptor for the retrieval and
35 storage of Operon objects
36 
37 =head1 SYNOPSIS
38 
39 my $operon_adaptor = Bio::EnsEMBL::DBSQL::OperonAdaptor->new($dba);
40 $operon_adaptor->store($operon);
41 my $operon2 = $operon_adaptor->fetch_by_dbID( $operon->dbID() );
42 
43 =head1 DESCRIPTION
44 
45 This is a database aware adaptor for the retrieval and storage of operon
46 objects.
47 
48 =head1 METHODS
49 
50 =cut
51 
52 package Bio::EnsEMBL::DBSQL::OperonAdaptor;
53 
54 use strict;
55 
56 use Bio::EnsEMBL::Utils::Exception qw( throw warning );
57 use Bio::EnsEMBL::Utils::Scalar qw( assert_ref );
62 
63 use vars '@ISA';
65 
66 # _tables
67 # Arg [1] : 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 # Status : Stable
74 
75 sub _tables {
76  return ( [ 'operon', 'o' ] );
77 }
78 
79 # _columns
80 # Arg [1] : none
81 # Example : none
82 # Description: PROTECTED implementation of superclass abstract method.
83 # Returns a list of columns to use for queries.
84 # Returntype : list of strings
85 # Exceptions : none
86 # Caller : internal
87 # Status : Stable
88 
89 sub _columns {
90  my ($self) = @_;
91 
92  my $created_date =
93  $self->db()->dbc()->from_date_to_seconds("o.created_date");
94  my $modified_date =
95  $self->db()->dbc()->from_date_to_seconds("o.modified_date");
96 
97  return ( 'o.operon_id', 'o.seq_region_id', 'o.seq_region_start',
98  'o.seq_region_end', 'o.seq_region_strand', 'o.display_label',
99  'o.analysis_id', 'o.stable_id', 'o.version',
100  $created_date, $modified_date );
101 }
102 
103 =head2 list_dbIDs
104 
105  Example : @operon_ids = @{$operon_adaptor->list_dbIDs()};
106  Description: Gets an array of internal ids for all operons in the current db
107  Arg[1] : <optional> int. not 0 for the ids to be sorted by the seq_region.
108  Returntype : Listref of Ints
109  Exceptions : none
110  Caller : general
111  Status : Stable
112 
113 =cut
114 
115 sub list_dbIDs {
116  my ( $self, $ordered ) = @_;
117 
118  return $self->_list_dbIDs( "operon", undef, $ordered );
119 }
120 
121 =head2 list_stable_ids
122 
123  Example : @stable_operon_ids = @{$operon_adaptor->list_stable_ids()};
124  Description: Gets an listref of stable ids for all operons in the current db
125  Returntype : reference to a list of strings
126  Exceptions : none
127  Caller : general
128  Status : Stable
129 
130 =cut
131 
132 sub list_stable_ids {
133  my ($self) = @_;
134 
135  return $self->_list_dbIDs( "operon", "stable_id" );
136 }
137 
138 sub list_seq_region_ids {
139  my $self = shift;
140 
141  return $self->_list_seq_region_ids('operon');
142 }
143 
144 =head2 fetch_by_name
145 
146  Arg [1] : String $label - name of operon to fetch
147  Example : my $operon = $operonAdaptor->fetch_by_name("accBC");
148  Description: Returns the operon which has the given display label or undef if
149  there is none. If there are more than 1, only the first is
150  reported.
151  Returntype : Bio::EnsEMBL::Operon
152  Exceptions : none
153  Caller : general
154  Status : Stable
155 
156 =cut
157 
158 sub fetch_by_name {
159  my $self = shift;
160  my $label = shift;
161 
162  my $constraint = "o.display_label = ?";
163  $self->bind_param_generic_fetch( $label, SQL_VARCHAR );
164  my ($operon) = @{ $self->generic_fetch($constraint) };
165 
166  return $operon;
167 }
168 
169 =head2 fetch_by_stable_id
170 
171  Arg [1] : String $id
172  The stable ID of the operon to retrieve
173  Example : $operon = $operon_adaptor->fetch_by_stable_id('ENSG00000148944');
174  Description: Retrieves a operon object from the database via its stable id.
175  The operon will be retrieved in its native coordinate system (i.e.
176  in the coordinate system it is stored in the database). It may
177  be converted to a different coordinate system through a call to
178  transform() or transfer(). If the operon or exon is not found
179  undef is returned instead.
180  Returntype : Bio::EnsEMBL::Operon or undef
181  Exceptions : if we cant get the operon in given coord system
182  Caller : general
183  Status : Stable
184 
185 =cut
186 
187 sub fetch_by_stable_id {
188  my ( $self, $stable_id ) = @_;
189 
190  my $constraint = "o.stable_id = ?";
191  $self->bind_param_generic_fetch( $stable_id, SQL_VARCHAR );
192  my ($operon) = @{ $self->generic_fetch($constraint) };
193 
194  # If we didn't get anything back, desperately try to see if there's
195  # a version number in the stable_id
196  if(!defined($operon) && (my $vindex = rindex($stable_id, '.'))) {
197  $operon = $self->fetch_by_stable_id_version(substr($stable_id,0,$vindex),
198  substr($stable_id,$vindex+1));
199  }
200 
201  return $operon;
202 }
203 
204 =head2 fetch_all
205 
206  Example : $operons = $operon_adaptor->fetch_all();
207  Description : Similar to fetch_by_stable_id, but retrieves all
208  operons stored in the database.
209  Returntype : listref of Bio::EnsEMBL::Operon
210  Caller : general
211  Status : At Risk
212 
213 =cut
214 
215 =head2 fetch_by_stable_id_version
216 
217  Arg [1] : String $id
218  The stable ID of the operon to retrieve
219  Arg [2] : Integer $version
220  The version of the stable_id to retrieve
221  Example : $operon = $operon_adaptor->fetch_by_stable_id('16152-16153-4840', 2);
222  Description: Retrieves an operon object from the database via its stable id and version.
223  The operon will be retrieved in its native coordinate system (i.e.
224  in the coordinate system it is stored in the database). It may
225  be converted to a different coordinate system through a call to
226  transform() or transfer(). If the operon is not found
227  undef is returned instead.
228  Returntype : Bio::EnsEMBL::Operon or undef
229  Exceptions : if we cant get the operon in given coord system
230  Caller : general
231  Status : Stable
232 
233 =cut
234 
235 sub fetch_by_stable_id_version {
236  my ($self, $stable_id, $version) = @_;
237 
238  # Enforce that version be numeric
239  return unless($version =~ /^\d+$/);
240 
241  my $constraint = "o.stable_id = ? AND o.version = ?";
242  $self->bind_param_generic_fetch($stable_id, SQL_VARCHAR);
243  $self->bind_param_generic_fetch($version, SQL_INTEGER);
244  my ($operon) = @{$self->generic_fetch($constraint)};
245 
246  return $operon;
247 }
248 
249 sub fetch_all {
250  my ($self) = @_;
251 
252  my $constraint = '';
253  my @operons = @{ $self->generic_fetch($constraint) };
254  return \@operons;
255 }
256 
257 =head2 fetch_all_versions_by_stable_id
258 
259  Arg [1] : String $stable_id
260  The stable ID of the operon to retrieve
261  Example : $operon = $operon_adaptor->fetch_all_versions_by_stable_id
262  ('ENSG00000148944');
263  Description : Similar to fetch_by_stable_id, but retrieves all versions of a
264  operon stored in the database.
265  Returntype : listref of Bio::EnsEMBL::Operon
266  Exceptions : if we cant get the operon in given coord system
267  Caller : general
268  Status : At Risk
269 
270 =cut
271 
272 sub fetch_all_versions_by_stable_id {
273  my ( $self, $stable_id ) = @_;
274 
275  my $constraint = "o.stable_id = ?";
276  $self->bind_param_generic_fetch( $stable_id, SQL_VARCHAR );
277  return $self->generic_fetch($constraint);
278 }
279 
280 =head2 fetch_all_by_Slice
281 
282  Arg [1] : Bio::EnsEMBL::Slice $slice
283  The slice to fetch operons on.
284  Arg [2] : (optional) string $logic_name
285  the logic name of the type of features to obtain
286  Arg [3] : (optional) boolean $load_transcripts
287  if true, transcripts will be loaded immediately rather than
288  lazy loaded later.
289  Arg [4] : (optional) string $source
290  the source name of the features to obtain.
291  Arg [5] : (optional) string biotype
292  the biotype of the features to obtain.
293  Example : @operons = @{$operon_adaptor->fetch_all_by_Slice()};
294  Description: Overrides superclass method to optionally load transcripts
295  immediately rather than lazy-loading them later. This
296  is more efficient when there are a lot of operons whose
297  transcripts are going to be used.
298  Returntype : reference to list of operons
299  Exceptions : thrown if exon cannot be placed on transcript slice
300  Caller : Slice::get_all_operons
301  Status : Stable
302 
303 =cut
304 
305 sub fetch_all_by_Slice {
306  my ( $self, $slice, $logic_name, $load_transcripts ) = @_;
307 
308  my $constraint = '';
309  my $operons =
310  $self->SUPER::fetch_all_by_Slice_constraint( $slice, $constraint,
311  $logic_name );
312 
313  # If there are less than two operons, still do lazy-loading.
314  if ( !$load_transcripts || @$operons < 2 ) {
315  return $operons;
316  }
317 
318  # Preload all of the transcripts now, instead of lazy loading later,
319  # faster than one query per transcript.
320 
321  # First check if transcripts are already preloaded.
322  # FIXME: Should check all transcripts.
323  if ( exists( $operons->[0]->{'_operon_transcript_array'} ) ) {
324  return $operons;
325  }
326 
327  # Get extent of region spanned by transcripts.
328  my ($min_start, $max_end);
329  my $ext_slice;
330 
331  unless ($slice->is_circular()) {
332  foreach my $o (@$operons) {
333  if (!defined($min_start) || $o->seq_region_start() < $min_start) {
334  $min_start = $o->seq_region_start();
335  }
336  if (!defined($max_end) || $o->seq_region_end() > $max_end) {
337  $max_end = $o->seq_region_end();
338  }
339  }
340 
341  if ($min_start >= $slice->start() && $max_end <= $slice->end()) {
342  $ext_slice = $slice;
343  } else {
344  my $sa = $self->db()->get_SliceAdaptor();
345  $ext_slice = $sa->fetch_by_region($slice->coord_system->name(), $slice->seq_region_name(), $min_start, $max_end, $slice->strand(), $slice->coord_system->version());
346  }
347 
348  } else {
349  # feature might be crossing the origin of replication (i.e. seq_region_start > seq_region_end)
350  # the computation of min_start|end based on seq_region_start|end is not safe
351  # use feature start/end relative to the slice instead
352  my ($min_start_feature, $max_end_feature);
353  foreach my $o (@$operons) {
354  if (!defined($min_start) || ($o->start() >= 0 && $o->start() < $min_start)) {
355  $min_start = $o->start();
356  $min_start_feature = $o;
357  }
358  if (!defined($max_end) || ($o->end() >= 0 && $o->end() > $max_end)) {
359  $max_end = $o->end();
360  $max_end_feature = $o;
361  }
362  }
363 
364  # now we can reassign min_start|end to seq_region_start|end of
365  # the feature which spans the largest region
366  $min_start = $min_start_feature->seq_region_start();
367  $max_end = $max_end_feature->seq_region_end();
368 
369  my $sa = $self->db()->get_SliceAdaptor();
370  $ext_slice =
371  $sa->fetch_by_region($slice->coord_system->name(),
372  $slice->seq_region_name(),
373  $min_start,
374  $max_end,
375  $slice->strand(),
376  $slice->coord_system->version());
377  }
378 
379 
380  # Associate transcript identifiers with operons.
381 
382  my %o_hash = map { $_->dbID => $_ } @{$operons};
383 
384  my $o_id_str = join( ',', keys(%o_hash) );
385 
386  my $sth =
387  $self->prepare( "SELECT operon_id, operon_transcript_id "
388  . "FROM operon_transcript "
389  . "WHERE operon_id IN ($o_id_str)" );
390 
391  $sth->execute();
392 
393  my ( $o_id, $tr_id );
394  $sth->bind_columns( \( $o_id, $tr_id ) );
395 
396  my %tr_o_hash;
397 
398  while ( $sth->fetch() ) {
399  $tr_o_hash{$tr_id} = $o_hash{$o_id};
400  }
401 
402  my $ta = $self->db()->get_OperonTranscriptAdaptor();
403  my $transcripts =
404  $ta->fetch_all_by_Slice( $ext_slice,
405  1, undef,
406  sprintf( "ot.operon_transcript_id IN (%s)",
407  join( ',',
408  sort { $a <=> $b }
409  keys(%tr_o_hash) ) ) );
410 
411  # Move transcripts onto operon slice, and add them to operons.
412  foreach my $tr ( @{$transcripts} ) {
413  if ( !exists( $tr_o_hash{ $tr->dbID() } ) ) {
414  next;
415  }
416 
417  my $new_tr;
418  if ( $slice != $ext_slice ) {
419  $new_tr = $tr->transfer($slice);
420  if ( !defined($new_tr) ) {
421  throw( "Unexpected. "
422  . "Transcript could not be transfered onto operon slice."
423  );
424  }
425  } else {
426  $new_tr = $tr;
427  }
428 
429  $tr_o_hash{ $tr->dbID() }->add_OperonTranscript($new_tr);
430  }
431 
432  return $operons;
433 } ## end sub fetch_all_by_Slice
434 
435 =head2 fetch_by_transcript_id
436 
437  Arg [1] : Int $trans_id
438  Unique database identifier for the transcript whose operon should
439  be retrieved. The operon is returned in its native coord
440  system (i.e. the coord_system it is stored in). If the coord
441  system needs to be changed, then tranform or transfer should
442  be called on the returned object. undef is returned if the
443  operon or transcript is not found in the database.
444  Example : $operon = $operon_adaptor->fetch_by_transcript_id(1241);
445  Description: Retrieves a operon from the database via the database identifier
446  of one of its transcripts.
447  Returntype : Bio::EnsEMBL::Operon
448  Exceptions : none
449  Caller : operonral
450  Status : Stable
451 
452 =cut
453 
454 sub fetch_by_operon_transcript_id {
455  my ( $self, $trans_id ) = @_;
456 
457  # this is a cheap SQL call
458  my $sth = $self->prepare(
459  qq(
460  SELECT tr.operon_id
461  FROM operon_transcript tr
462  WHERE tr.operon_transcript_id = ?
463  ) );
464 
465  $sth->bind_param( 1, $trans_id, SQL_INTEGER );
466  $sth->execute();
467 
468  my ($operonid) = $sth->fetchrow_array();
469 
470  $sth->finish();
471 
472  return undef if ( !defined $operonid );
473 
474  my $operon = $self->fetch_by_dbID($operonid);
475  return $operon;
476 }
477 
478 =head2 fetch_by_operon_transcript_stable_id
479 
480  Arg [1] : string $trans_stable_id
481  transcript stable ID whose operon should be retrieved
482  Example : my $operon = $operon_adaptor->fetch_by_operon_transcript_stable_id
483  ('ENST0000234');
484  Description: Retrieves a operon from the database via the stable ID of one of
485  its transcripts
486  Returntype : Bio::EnsEMBL::Operon
487  Exceptions : none
488  Caller : operonral
489  Status : Stable
490 
491 =cut
492 
493 sub fetch_by_operon_transcript_stable_id {
494  my ( $self, $trans_stable_id ) = @_;
495 
496  my $sth = $self->prepare(
497  qq(
498  SELECT operon_id
499  FROM operon_transcript
500  WHERE stable_id = ?
501  ) );
502 
503  $sth->bind_param( 1, $trans_stable_id, SQL_VARCHAR );
504  $sth->execute();
505 
506  my ($operonid) = $sth->fetchrow_array();
507  $sth->finish;
508 
509  return undef if ( !defined $operonid );
510 
511  my $operon = $self->fetch_by_dbID($operonid);
512  return $operon;
513 }
514 
515 sub fetch_by_operon_transcript {
516  my ( $self, $trans ) = @_;
517  assert_ref( $trans, 'Bio::EnsEMBL::OperonTranscript' );
518  $self->fetch_by_operon_transcript_id( $trans->dbID() );
519 }
520 
521 =head2 store
522 
523  Arg [1] : Bio::EnsEMBL::Operon $operon
524  The operon to store in the database
525  Arg [2] : ignore_release in xrefs [default 1] set to 0 to use release info
526  in external database references
527  Example : $operon_adaptor->store($operon);
528  Description: Stores a operon in the database.
529  Returntype : the database identifier (dbID) of the newly stored operon
530  Exceptions : thrown if the $operon is not a Bio::EnsEMBL::Operon or if
531  $operon does not have an analysis object
532  Caller : general
533  Status : Stable
534 
535 =cut
536 
537 sub store {
538  my ( $self, $operon, $ignore_release ) = @_;
539 
540  if ( !ref $operon || !$operon->isa('Bio::EnsEMBL::Operon') ) {
541  throw("Must store a operon object, not a $operon");
542  }
543 
544  my $db = $self->db();
545 
546  if ( $operon->is_stored($db) ) {
547  return $operon->dbID();
548  }
549  my $analysis = $operon->analysis();
550  throw("Operons must have an analysis object.") if(!defined($analysis));
551  my $analysis_id;
552  if ( $analysis->is_stored($db) ) {
553  $analysis_id = $analysis->dbID();
554  } else {
555  $analysis_id = $db->get_AnalysisAdaptor->store( $analysis );
556  }
557  # ensure coords are correct before storing
558  #$operon->recalculate_coordinates();
559 
560  my $seq_region_id;
561 
562  ( $operon, $seq_region_id ) = $self->_pre_store($operon);
563 
564  my @columns = qw(
565  seq_region_id
566  seq_region_start
567  seq_region_end
568  seq_region_strand
569  display_label
570  analysis_id
571  );
572  my @canned_columns;
573  my @canned_values;
574 
575  if ( defined($operon->stable_id()) ) {
576  push @columns, qw(
577  stable_id
578  version
579  );
580  my $created = $self->db->dbc->from_seconds_to_date($operon->created_date());
581  my $modified = $self->db->dbc->from_seconds_to_date($operon->modified_date());
582 
583  if ($created) {
584  push @canned_columns, 'created_date';
585  push @canned_values, $created;
586  }
587  if ($modified) {
588  push @canned_columns, 'modified_date';
589  push @canned_values, $modified;
590  }
591  }
592 
593  my $i_columns = join(', ', @columns, @canned_columns);
594  my $i_values = join(', ', (('?') x scalar(@columns)), @canned_values);
595  my $store_operon_sql = qq(
596  INSERT INTO operon ( ${i_columns} ) VALUES ( $i_values )
597  );
598 
599  my $sth = $self->prepare($store_operon_sql);
600  $sth->bind_param( 1, $seq_region_id, SQL_INTEGER );
601  $sth->bind_param( 2, $operon->start(), SQL_INTEGER );
602  $sth->bind_param( 3, $operon->end(), SQL_INTEGER );
603  $sth->bind_param( 4, $operon->strand(), SQL_TINYINT );
604  $sth->bind_param( 5, $operon->display_label(), SQL_VARCHAR );
605  $sth->bind_param( 6, $analysis_id, SQL_INTEGER );
606 
607  if ( defined($operon->stable_id()) ) {
608  $sth->bind_param( 7, $operon->stable_id(), SQL_VARCHAR );
609  my $version = ($operon->version()) ? $operon->version() : 1;
610  $sth->bind_param( 8, $version, SQL_INTEGER );
611  }
612  $sth->execute();
613  $sth->finish();
614 
615  my $operon_dbID = $self->last_insert_id('operon_id', undef, 'operon');
616 
617  my $transcripts = $operon->get_all_OperonTranscripts();
618 
619  if ( $transcripts && scalar @$transcripts ) {
620  my $transcript_adaptor = $db->get_OperonTranscriptAdaptor();
621  for my $transcript (@$transcripts) {
622  $transcript_adaptor->store( $transcript, $operon_dbID );
623  }
624  }
625 
626  # store the dbentries associated with this operon
627  my $dbEntryAdaptor = $db->get_DBEntryAdaptor();
628 
629  foreach my $dbe ( @{ $operon->get_all_DBEntries } ) {
630  $dbEntryAdaptor->store( $dbe, $operon_dbID, "Operon", $ignore_release );
631  }
632 
633  # store operon attributes if there are any
634  my $attrs = $operon->get_all_Attributes();
635  if ( $attrs && scalar @$attrs ) {
636  my $attr_adaptor = $db->get_AttributeAdaptor();
637  $attr_adaptor->store_on_Operon( $operon, $attrs );
638  }
639 
640  # set the adaptor and dbID on the original passed in operon not the
641  # transfered copy
642  $operon->adaptor($self);
643  $operon->dbID($operon_dbID);
644 
645  return $operon_dbID;
646 } ## end sub store
647 
648 =head2 remove
649 
650  Arg [1] : Bio::EnsEMBL::Operon $operon
651  the operon to remove from the database
652  Example : $operon_adaptor->remove($operon);
653  Description: Removes a operon completely from the database. All associated
654  transcripts, exons, stable_identifiers, descriptions, etc.
655  are removed as well. Use with caution!
656  Returntype : none
657  Exceptions : throw on incorrect arguments
658  warning if operon is not stored in this database
659  Caller : general
660  Status : Stable
661 
662 =cut
663 
664 sub remove {
665  my $self = shift;
666  my $operon = shift;
667 
668  if ( !ref($operon) || !$operon->isa('Bio::EnsEMBL::Operon') ) {
669  throw("Bio::EnsEMBL::Operon argument expected.");
670  }
671 
672  if ( !$operon->is_stored( $self->db() ) ) {
673  warning( "Cannot remove operon "
674  . $operon->dbID()
675  . ". Is not stored in "
676  . "this database." );
677  return;
678  }
679 
680  # remove all object xrefs associated with this operon
681 
682  my $dbe_adaptor = $self->db()->get_DBEntryAdaptor();
683  foreach my $dbe ( @{ $operon->get_all_DBEntries() } ) {
684  $dbe_adaptor->remove_from_object( $dbe, $operon, 'Operon' );
685  }
686 
687  # remove all of the transcripts associated with this operon
688  my $transcriptAdaptor = $self->db->get_OperonTranscriptAdaptor();
689  foreach my $trans ( @{ $operon->get_all_OperonTranscripts() } ) {
690  $transcriptAdaptor->remove($trans);
691  }
692 
693  # remove this operon from the database
694 
695  my $sth = $self->prepare("DELETE FROM operon WHERE operon_id = ? ");
696  $sth->bind_param( 1, $operon->dbID, SQL_INTEGER );
697  $sth->execute();
698  $sth->finish();
699 
700  # unset the operon identifier and adaptor thereby flagging it as unstored
701 
702  $operon->dbID(undef);
703  $operon->adaptor(undef);
704 
705  return;
706 } ## end sub remove
707 
708 # _objs_from_sth
709 
710 # Arg [1] : StatementHandle $sth
711 # Arg [2] : Bio::EnsEMBL::AssemblyMapper $mapper
712 # Arg [3] : Bio::EnsEMBL::Slice $dest_slice
713 # Description: PROTECTED implementation of abstract superclass method.
714 # responsible for the creation of Operons
715 # Returntype : listref of Bio::EnsEMBL::Operon in target coordinate system
716 # Exceptions : none
717 # Caller : internal
718 # Status : Stable
719 
720 sub _objs_from_sth {
721  my ($self, $sth, $mapper, $dest_slice) = @_;
722 
723  #
724  # This code is ugly because an attempt has been made to remove as many
725  # function calls as possible for speed purposes. Thus many caches and
726  # a fair bit of gymnastics is used.
727  #
728 
729  my $sa = $self->db()->get_SliceAdaptor();
730  my $aa = $self->db()->get_AnalysisAdaptor();
731 
732  my @operons;
733  my %analysis_hash;
734  my %slice_hash;
735  my %sr_name_hash;
736  my %sr_cs_hash;
737 
738  my (
739  $operon_id, $seq_region_id, $seq_region_start,
740  $seq_region_end, $seq_region_strand, $display_label,
741  $analysis_id, $stable_id, $version,
742  $created_date, $modified_date
743  );
744 
745  $sth->bind_columns( \(
746  $operon_id, $seq_region_id, $seq_region_start,
747  $seq_region_end, $seq_region_strand, $display_label,
748  $analysis_id, $stable_id, $version,
749  $created_date, $modified_date ));
750 
751  my $dest_slice_start;
752  my $dest_slice_end;
753  my $dest_slice_strand;
754  my $dest_slice_length;
755  my $dest_slice_cs;
756  my $dest_slice_sr_name;
757  my $dest_slice_sr_id;
758  my $asma;
759 
760  if ($dest_slice) {
761  $dest_slice_start = $dest_slice->start();
762  $dest_slice_end = $dest_slice->end();
763  $dest_slice_strand = $dest_slice->strand();
764  $dest_slice_length = $dest_slice->length();
765  $dest_slice_cs = $dest_slice->coord_system();
766  $dest_slice_sr_name = $dest_slice->seq_region_name();
767  $dest_slice_sr_id = $dest_slice->get_seq_region_id();
768  $asma = $self->db->get_AssemblyMapperAdaptor();
769  }
770 
771  OPERON: while ( $sth->fetch() ) {
772 
773  #get the analysis object
774  my $analysis = $analysis_hash{$analysis_id} ||= $aa->fetch_by_dbID($analysis_id);
775  $analysis_hash{$analysis_id} = $analysis;
776 
777  #need to get the internal_seq_region, if present
778  $seq_region_id = $self->get_seq_region_id_internal($seq_region_id);
779  my $slice = $slice_hash{"ID:".$seq_region_id};
780 
781  if (!$slice) {
782  $slice = $sa->fetch_by_seq_region_id($seq_region_id);
783  $slice_hash{"ID:".$seq_region_id} = $slice;
784  $sr_name_hash{$seq_region_id} = $slice->seq_region_name();
785  $sr_cs_hash{$seq_region_id} = $slice->coord_system();
786  }
787 
788  #obtain a mapper if none was defined, but a dest_seq_region was
789  if(!$mapper && $dest_slice && !$dest_slice_cs->equals($slice->coord_system)) {
790  $mapper = $asma->fetch_by_CoordSystems($dest_slice_cs, $slice->coord_system);
791  }
792 
793  my $sr_name = $sr_name_hash{$seq_region_id};
794  my $sr_cs = $sr_cs_hash{$seq_region_id};
795 
796  #
797  # remap the feature coordinates to another coord system
798  # if a mapper was provided
799  #
800 
801  if ($mapper) {
802 
803  if (defined $dest_slice && $mapper->isa('Bio::EnsEMBL::ChainedAssemblyMapper') ) {
804  ($seq_region_id, $seq_region_start, $seq_region_end, $seq_region_strand) =
805  $mapper->map($sr_name, $seq_region_start, $seq_region_end, $seq_region_strand, $sr_cs, 1, $dest_slice);
806 
807  } else {
808  ($seq_region_id, $seq_region_start, $seq_region_end, $seq_region_strand) =
809  $mapper->fastmap($sr_name, $seq_region_start, $seq_region_end, $seq_region_strand, $sr_cs);
810  }
811 
812  #skip features that map to gaps or coord system boundaries
813  next OPERON if (!defined($seq_region_id));
814 
815  #get a slice in the coord system we just mapped to
816  $slice = $slice_hash{"ID:".$seq_region_id} ||= $sa->fetch_by_seq_region_id($seq_region_id);
817  }
818 
819  #
820  # If a destination slice was provided convert the coords.
821  #
822  if (defined($dest_slice)) {
823  my $seq_region_len = $dest_slice->seq_region_length();
824 
825  if ( $dest_slice_strand == 1 ) {
826  $seq_region_start = $seq_region_start - $dest_slice_start + 1;
827  $seq_region_end = $seq_region_end - $dest_slice_start + 1;
828 
829  if ( $dest_slice->is_circular ) {
830  # Handle circular chromosomes.
831 
832  if ( $seq_region_start > $seq_region_end ) {
833  # Looking at a feature overlapping the chromosome origin.
834 
835  if ( $seq_region_end > $dest_slice_start ) {
836  # Looking at the region in the beginning of the chromosome
837  $seq_region_start -= $seq_region_len;
838  }
839  if ( $seq_region_end < 0 ) {
840  $seq_region_end += $seq_region_len;
841  }
842  } else {
843  if ($dest_slice_start > $dest_slice_end && $seq_region_end < 0) {
844  # Looking at the region overlapping the chromosome
845  # origin and a feature which is at the beginning of the
846  # chromosome.
847  $seq_region_start += $seq_region_len;
848  $seq_region_end += $seq_region_len;
849  }
850  }
851  }
852  } else {
853 
854  my $start = $dest_slice_end - $seq_region_end + 1;
855  my $end = $dest_slice_end - $seq_region_start + 1;
856 
857  if ($dest_slice->is_circular()) {
858 
859  if ($dest_slice_start > $dest_slice_end) {
860  # slice spans origin or replication
861 
862  if ($seq_region_start >= $dest_slice_start) {
863  $end += $seq_region_len;
864  $start += $seq_region_len if $seq_region_end > $dest_slice_start;
865 
866  } elsif ($seq_region_start <= $dest_slice_end) {
867  # do nothing
868  } elsif ($seq_region_end >= $dest_slice_start) {
869  $start += $seq_region_len;
870  $end += $seq_region_len;
871 
872  } elsif ($seq_region_end <= $dest_slice_end) {
873  $end += $seq_region_len if $end < 0;
874 
875  } elsif ($seq_region_start > $seq_region_end) {
876  $end += $seq_region_len;
877  }
878 
879  } else {
880 
881  if ($seq_region_start <= $dest_slice_end and $seq_region_end >= $dest_slice_start) {
882  # do nothing
883  } elsif ($seq_region_start > $seq_region_end) {
884  if ($seq_region_start <= $dest_slice_end) {
885  $start -= $seq_region_len;
886  } elsif ($seq_region_end >= $dest_slice_start) {
887  $end += $seq_region_len;
888  }
889  }
890  }
891  }
892 
893  $seq_region_start = $start;
894  $seq_region_end = $end;
895  $seq_region_strand *= -1;
896 
897  } ## end else [ if ( $dest_slice_strand...)]
898 
899  # Throw away features off the end of the requested slice or on
900  # different seq_region.
901  if ($seq_region_end < 1
902  || $seq_region_start > $dest_slice_length
903  || ($dest_slice_sr_id != $seq_region_id)) {
904  next OPERON;
905  }
906  $slice = $dest_slice;
907  } ## end if ($dest_slice)
908 
909  push( @operons,
911  -START => $seq_region_start,
912  -END => $seq_region_end,
913  -STRAND => $seq_region_strand,
914  -SLICE => $slice,
915  -DISPLAY_LABEL => $display_label,
916  -ADAPTOR => $self,
917  -DBID => $operon_id,
918  -STABLE_ID => $stable_id,
919  -VERSION => $version,
920  -CREATED_DATE => $created_date || undef,
921  -MODIFIED_DATE => $modified_date || undef,
922  -ANALYSIS => $analysis ) );
923 
924  } ## end while ( $sth->fetch() )
925 
926  return \@operons;
927 } ## end sub _objs_from_sth
928 
929 1;
930 
transcript
public transcript()
Bio::EnsEMBL::Storable::dbID
public Int dbID()
Bio::EnsEMBL::Operon
Definition: Operon.pm:30
Bio::EnsEMBL::DBSQL::DBAdaptor
Definition: DBAdaptor.pm:40
map
public map()
Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor
Definition: BaseFeatureAdaptor.pm:24
Bio::EnsEMBL::DBSQL::SliceAdaptor
Definition: SliceAdaptor.pm:78
Bio::EnsEMBL::DBSQL::OperonAdaptor
Definition: OperonAdaptor.pm:24
Bio::EnsEMBL::Slice
Definition: Slice.pm:50
exon
public exon()
Bio::EnsEMBL::Utils::Scalar
Definition: Scalar.pm:66
Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor::new
public Bio::EnsEMBL::BaseFeatureAdaptor new()
info
public info()
Bio::EnsEMBL::Utils::Exception
Definition: Exception.pm:68