BaseFeatureAdaptor.pm 21 KB
Newer Older
1
#
Simon Potter's avatar
Simon Potter committed
2
# EnsEMBL module for Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
#
# Cared for by Ewan Birney <birney@ebi.ac.uk>
#
# Copyright Ewan Birney
#
# You may distribute this module under the same terms as perl itself

# POD documentation - main docs before the code

=head1 NAME

Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor - Abstract Base class for 
                                          FeatureAdaptors

=head1 SYNOPSIS

Abstract class should not be instantiated.  Implementation of
abstract methods must be performed by subclasses.

=head1 DESCRIPTION

This is a base adaptor for feature adaptors. This base class is simply a way
of eliminating code duplication through the implementation of methods 
common to all feature adaptors.

28
Contact EnsEMBL development list for info: <ensembl-dev@ebi.ac.uk>
29 30 31 32 33 34 35 36

=cut


# Let the code begin...


package Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor;
37
use vars qw(@ISA $SLICE_FEATURE_CACHE_SIZE);
38 39 40 41 42
use strict;

# Object preamble - inherits from Bio::EnsEMBL::Root

use Bio::EnsEMBL::DBSQL::BaseAdaptor;
43
use Bio::EnsEMBL::Utils::Cache;
44 45 46

@ISA = qw(Bio::EnsEMBL::DBSQL::BaseAdaptor);

47
$SLICE_FEATURE_CACHE_SIZE = 4;
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67


=head2 new

  Arg [1]    : list of args @args
               Superclass constructor arguments
  Example    : none
  Description: Constructor which just initializes internal cache structures
  Returntype : Bio::EnsEMBL::BaseFeatureAdaptor
  Exceptions : none
  Caller     : implementing subclass constructors

=cut

sub new {
  my ($class, @args) = @_;

  my $self = $class->SUPER::new(@args);

  #initialize caching data structures
68 69
  $self->{'_slice_feature_cache'} = {};

70 71 72 73 74 75
  tie(%{$self->{'_slice_feature_cache'}}, 
      'Bio::EnsEMBL::Utils::Cache',
      $SLICE_FEATURE_CACHE_SIZE);

  return $self;
}
76 77 78 79 80 81 82

=head2 generic_fetch

  Arg [1]    : (optional) string $constraint
               An SQL query constraint (i.e. part of the WHERE clause)
  Arg [2]    : (optional) string $logic_name
               the logic_name of the analysis of the features to obtain
83
  Example    : $fts = $a->generic_fetch('contig_id in (1234, 1235)', 'Swall');
84 85
  Description: Performs a database fetch and returns feature objects in
               contig coordinates.
86
  Returntype : listref of Bio::EnsEMBL::SeqFeature in contig coordinates
87 88 89 90
  Exceptions : none
  Caller     : BaseFeatureAdaptor, ProxyDnaAlignFeatureAdaptor::generic_fetch

=cut
91 92
  
sub generic_fetch {
93
  my ($self, $constraint, $logic_name, $mapper, $slice) = @_;
94
  
95
  my @tabs = $self->_tables;
96 97 98 99
  my $columns = join(', ', $self->_columns());
  
  if($logic_name) {
    #determine the analysis id via the logic_name
100 101
    my $analysis = 
      $self->db->get_AnalysisAdaptor()->fetch_by_logic_name($logic_name);
102 103
    unless(defined $analysis && $analysis->dbID() ) {
      $self->warn("No analysis for logic name $logic_name exists\n");
Web Admin's avatar
Web Admin committed
104
      return [];
105 106 107
    }
    
    my $analysis_id = $analysis->dbID();
108 109 110 111

    #get the synonym for the primary table
    my $syn = $tabs[0]->[1];

112
    if($constraint) {
113
      $constraint .= " AND ${syn}.analysis_id = $analysis_id";
114
    } else {
115
      $constraint = " ${syn}.analysis_id = $analysis_id";
116 117
    }
  } 
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

  #
  # Construct a left join statement if one was defined, and remove the
  # left-joined table from the table list
  #
  my ($tablename, $condition) = $self->_left_join;
  my $left_join = '';
  my @tables;
  if($tablename && $condition) {
    while(my $t = shift @tabs) {
      if($tablename eq $t->[0]) {
	my $syn = $t->[1]; 
	$left_join =  "LEFT JOIN $tablename $syn $condition";
	push @tables, @tabs;
	last;
      } else {
	push @tables, $t;
      }
    }
  } else {
    @tables = @tabs;
  }
      
  #construct a nice table string like 'table1 t1, table2 t2'
  my $tablenames = join(', ', map({ join(' ', @$_) } @tables));

  my $sql = "SELECT $columns FROM $tablenames $left_join";
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

  my $default_where = $self->_default_where_clause;
  my $final_clause = $self->_final_clause;

  #append a where clause if it was defined
  if($constraint) { 
    $sql .= " where $constraint ";
    if($default_where) {
      $sql .= " and $default_where ";
    }
  } elsif($default_where) {
    $sql .= " where $default_where ";
  }

  #append additional clauses which may have been defined
  $sql .= " $final_clause";

162
  my $sth = $self->prepare($sql);
163 164 165
  
  $sth->execute;  

166
  return $self->_objs_from_sth($sth, $mapper, $slice);
167 168 169 170
}


=head2 fetch_by_dbID
171 172 173 174 175 176

  Arg [1]    : int $id
               the unique database identifier for the feature to be obtained 
  Example    : $feat = $adaptor->fetch_by_dbID(1234);
  Description: Returns the feature created from the database defined by the
               the id $id. 
177
  Returntype : Bio::EnsEMBL::SeqFeature
178 179
  Exceptions : thrown if $id is not defined
  Caller     : general
180 181 182 183 184 185 186 187 188 189

=cut

sub fetch_by_dbID{
  my ($self,$id) = @_;
  
  unless(defined $id) {
    $self->throw("fetch_by_dbID must have an id");
  }

190 191 192 193 194 195
  my @tabs = $self->_tables;

  my ($name, $syn) = @{$tabs[0]};

  #construct a constraint like 't1.table1_id = 1'
  my $constraint = "${syn}.${name}_id = $id";
196

197
  #return first element of _generic_fetch list
198
  my ($feat) = @{$self->generic_fetch($constraint)}; 
199
  return $feat;
200 201 202
}


203
=head2 fetch_all_by_RawContig_constraint
204

205 206
  Arg [1]    : Bio::EnsEMBL::RawContig $contig
               The contig object from which features are to be obtained
207 208 209 210
  Arg [2]    : (optional) string $constraint
               An SQL query constraint (i.e. part of the WHERE clause)
  Arg [3]    : (optional) string $logic_name
               the logic name of the type of features to obtain
211 212
  Example    : $fs = $a->fetch_all_by_Contig_constraint($ctg,'perc_ident>5.0');
  Description: Returns a listref of features created from the database which 
213 214 215
               are on the contig defined by $cid and fulfill the SQL constraint
               defined by $constraint. If logic name is defined, only features
               with an analysis of type $logic_name will be returned. 
216
  Returntype : listref of Bio::EnsEMBL::SeqFeature in contig coordinates
217 218
  Exceptions : thrown if $cid is not defined
  Caller     : general
219 220 221

=cut

222
sub fetch_all_by_RawContig_constraint {
223
  my ($self, $contig, $constraint, $logic_name) = @_;
224
  
225 226
  unless( defined $contig ) {
    $self->throw("fetch_by_Contig_constraint must have an contig");
227 228
  }

229 230 231 232 233 234
  unless( ref $contig && $contig->isa('Bio::EnsEMBL::RawContig')) {
    $self->throw("contig argument is not a Bio::EnsEMBL::RawContig object\n");
  }

  my $cid = $contig->dbID();

235 236 237 238
  #get the synonym of the primary_table
  my @tabs = $self->_tables;
  my $syn = $tabs[0]->[1];

239
  if($constraint) {
240
    $constraint .= " AND ${syn}.contig_id = $cid";
241
  } else {
242
    $constraint = "${syn}.contig_id = $cid";
243 244
  }

Alistair Rust's avatar
Alistair Rust committed
245
  return $self->generic_fetch($constraint, $logic_name);
246 247
}

248

Arne Stabenau's avatar
Arne Stabenau committed
249
=head2 fetch_all_by_RawContig
250

251 252
  Arg [1]    : Bio::EnsEMBL::RawContig $contig 
               the contig from which features should be obtained
253 254
  Arg [2]    : (optional) string $logic_name
               the logic name of the type of features to obtain
255
  Example    : @fts = $a->fetch_all_by_RawContig($contig, 'wall');
256 257 258 259
  Description: Returns a list of features created from the database which are 
               are on the contig defined by $cid If logic name is defined, 
               only features with an analysis of type $logic_name will be 
               returned. 
260
  Returntype : listref of Bio::EnsEMBL::*Feature in contig coordinates
261 262 263 264
  Exceptions : none
  Caller     : general

=cut
265
   
Arne Stabenau's avatar
Arne Stabenau committed
266 267 268
sub fetch_all_by_RawContig {
  my ( $self, $contig, $logic_name ) = @_;

269
  return $self->fetch_all_by_RawContig_constraint($contig, '',$logic_name);
270 271 272
}


273
=head2 fetch_all_by_RawContig_and_score
274 275
  Arg [1]    : Bio::EnsEMBL::RawContig $contig 
               the contig from which features should be obtained
276
  Arg [2]    : (optional) float $score
277 278 279
               the lower bound of the score of the features to obtain
  Arg [3]    : (optional) string $logic_name
               the logic name of the type of features to obtain
280
  Example    : @fts = $a->fetch_by_RawContig_and_score(1, 50.0, 'Swall');
281
  Description: Returns a list of features created from the database which are 
282
               are on the contig defined by $cid and which have score greater  
283 284
               than score.  If logic name is defined, only features with an 
               analysis of type $logic_name will be returned. 
285
  Returntype : listref of Bio::EnsEMBL::*Feature in contig coordinates
286 287 288 289 290
  Exceptions : thrown if $score is not defined
  Caller     : general

=cut

291
sub fetch_all_by_RawContig_and_score{
292
  my($self, $contig, $score, $logic_name) = @_;
293 294 295

  my $constraint;

296
  if(defined $score){
297 298 299 300
    #get the synonym of the primary_table
    my @tabs = $self->_tables;
    my $syn = $tabs[0]->[1];
    $constraint = "${syn}.score > $score";
301 302
  }
    
303
  return $self->fetch_all_by_RawContig_constraint($contig, $constraint, 
304
					       $logic_name);
305 306 307
}


308
=head2 fetch_all_by_Slice
309 310 311 312 313

  Arg [1]    : Bio::EnsEMBL::Slice $slice
               the slice from which to obtain features
  Arg [2]    : (optional) string $logic_name
               the logic name of the type of features to obtain
314 315 316 317 318 319
  Example    : $fts = $a->fetch_all_by_Slice($slice, 'Swall');
  Description: Returns a listref of features created from the database 
               which are on the Slice defined by $slice. If $logic_name is 
               defined only features with an analysis of type $logic_name 
               will be returned. 
  Returntype : listref of Bio::EnsEMBL::SeqFeatures in Slice coordinates
320 321 322 323 324
  Exceptions : none
  Caller     : Bio::EnsEMBL::Slice

=cut

325
sub fetch_all_by_Slice {
326 327 328
  my ($self, $slice, $logic_name) = @_;
  
  #fetch by constraint with empty constraint
329
  return $self->fetch_all_by_Slice_constraint($slice, '', $logic_name);
330 331 332
}


333
=head2 fetch_all_by_Slice_and_score
334 335 336

  Arg [1]    : Bio::EnsEMBL::Slice $slice
               the slice from which to obtain features
337
  Arg [2]    : (optional) float $score
338 339 340
               lower bound of the the score of the features retrieved
  Arg [3]    : (optional) string $logic_name
               the logic name of the type of features to obtain
341
  Example    : $fts = $a->fetch_all_by_Slice($slice, 'Swall');
342 343 344 345 346
  Description: Returns a list of features created from the database which are 
               are on the Slice defined by $slice and which have a score 
               greated than $score. If $logic_name is defined, 
               only features with an analysis of type $logic_name will be 
               returned. 
347
  Returntype : listref of Bio::EnsEMBL::SeqFeatures in Slice coordinates
348 349 350 351 352
  Exceptions : none
  Caller     : Bio::EnsEMBL::Slice

=cut

353
sub fetch_all_by_Slice_and_score {
354 355 356
  my ($self, $slice, $score, $logic_name) = @_;
  my $constraint;

357
  if(defined $score) {
358 359 360 361
    #get the synonym of the primary_table
    my @tabs = $self->_tables;
    my $syn = $tabs[0]->[1];
    $constraint = "${syn}.score > $score";
362 363
  }

364 365
  return $self->fetch_all_by_Slice_constraint($slice, $constraint, 
					      $logic_name);
366 367 368
}  


369
=head2 fetch_all_by_Slice_constraint
370

371 372 373 374 375
  Arg [1]    : Bio::EnsEMBL::Slice $slice
               the slice from which to obtain features
  Arg [2]    : (optional) string $constraint
               An SQL query constraint (i.e. part of the WHERE clause)
  Arg [3]    : (optional) string $logic_name
376
               the logic name of the type of features to obtain
377 378
  Example    : $fs = $a->fetch_all_by_Slice_constraint($slc, 'perc_ident > 5');
  Description: Returns a listref of features created from the database which 
379 380 381 382
               are on the Slice defined by $slice and fulfill the SQL 
               constraint defined by $constraint. If logic name is defined, 
               only features with an analysis of type $logic_name will be 
               returned. 
383
  Returntype : listref of Bio::EnsEMBL::SeqFeatures in Slice coordinates
384 385
  Exceptions : thrown if $slice is not defined
  Caller     : Bio::EnsEMBL::Slice
386 387 388

=cut

389
sub fetch_all_by_Slice_constraint {
390
  my($self, $slice, $constraint, $logic_name) = @_;
391

392 393
  unless(defined $slice && ref $slice && $slice->isa("Bio::EnsEMBL::Slice")) {
    $self->throw("Slice arg must be a Bio::EnsEMBL::Slice not a [$slice]\n");
394 395
  }

396 397
  $logic_name = '' unless $logic_name;
  $constraint = '' unless $constraint;
398

399
  #check the cache and return if we have already done this query
Web Admin's avatar
Web Admin committed
400
  my $key = join($slice->name, $constraint, $logic_name);
401 402
  return $self->{'_slice_feature_cache'}{$key} 
    if $self->{'_slice_feature_cache'}{$key};
Web Admin's avatar
Web Admin committed
403
    
404 405 406 407
  my $slice_start  = $slice->chr_start();
  my $slice_end    = $slice->chr_end();
  my $slice_strand = $slice->strand();
		 
408 409
  my $mapper = 
    $self->db->get_AssemblyMapperAdaptor->fetch_by_type($slice->assembly_type);
410 411

  #get the list of contigs this slice is on
412
  my @cids = 
413
    $mapper->list_contig_ids( $slice->chr_name, $slice_start ,$slice_end );
414
  
Web Admin's avatar
Web Admin committed
415
  return [] unless scalar(@cids);
416 417 418

  my $cid_list = join(',',@cids);

419 420 421 422
  #get the synonym of the primary_table
  my @tabs = $self->_tables;
  my $syn = $tabs[0]->[1];

423
  #construct the SQL constraint for the contig ids 
424
  if($constraint) {
425
    $constraint .= " AND ${syn}.contig_id IN ($cid_list)";
426
  } else {
427
    $constraint = "${syn}.contig_id IN ($cid_list)";
428
  }
429

430
  #for speed the remapping to slice may be done at the time of object creation
431 432
  my $features = 
    $self->generic_fetch($constraint, $logic_name, $mapper, $slice); 
Graham McVicker's avatar
Graham McVicker committed
433
  
434 435
  if(@$features && (!$features->[0]->can('contig') || 
		    $features->[0]->contig == $slice)) {
Graham McVicker's avatar
Graham McVicker committed
436
    #features have been converted to slice coords already, cache and return
Web Admin's avatar
Web Admin committed
437
    return $self->{'_slice_feature_cache'}{$key} = $features;
438
  }
439

440 441
  #remapping has not been done, we have to do our own conversion from
  # raw contig coords to slice coords
442

443
  my @out = ();
444
  
445 446
  my ($feat_start, $feat_end, $feat_strand); 

447
  foreach my $f (@$features) {
448
    #since feats were obtained in contig coords, attached seq is a contig
449
    my $contig_id = $f->contig->dbID();
450

451
    my ($chr_name, $start, $end, $strand) = 
452 453
      $mapper->fast_to_assembly($contig_id, $f->start(), 
				$f->end(),$f->strand(),"rawcontig");
454

455
    # undefined start means gap
456
    next unless defined $start;     
457

458
    # maps to region outside desired area 
459
    next if ($start > $slice_end) || ($end < $slice_start);  
460 461
    
    #shift the feature start, end and strand in one call
462
    if($slice_strand == -1) {
463
      $f->move( $slice_end - $end + 1, $slice_end - $start + 1, $strand * -1 );
464 465 466 467
    } else {
      $f->move( $start - $slice_start + 1, $end - $slice_start + 1, $strand );
    }
    
468
    $f->contig($slice);
469
    
Web Admin's avatar
Web Admin committed
470
    push @out,$f;
471 472
  }
  
473
  #update the cache
Web Admin's avatar
Web Admin committed
474
  return $self->{'_slice_feature_cache'}{$key} = \@out;
475 476 477
}


478
=head2 store
479

480
  Arg [1]    : list of Bio::EnsEMBL::SeqFeature
481 482 483 484 485 486 487
  Example    : $adaptor->store(@feats);
  Description: ABSTRACT  Subclasses are responsible for implementing this 
               method.  It should take a list of features and store them in 
               the database.
  Returntype : none
  Exceptions : thrown method is not implemented by subclass
  Caller     : general
488 489 490 491 492 493 494 495 496 497

=cut

sub store{
  my $self = @_;

  $self->throw("Abstract method store not defined by implementing subclass\n");
}


498 499 500 501 502 503 504 505 506
=head2 remove

  Arg [1]    : A feature $feature 
  Example    : $feature_adaptor->remove($feature);
  Description: This removes a feature from the database.  The table the
               feature is removed from is defined by the abstract method
               _tablename, and the primary key of the table is assumed
               to be _tablename() . '_id'.  The feature argument must 
               be an object implementing the dbID method, and for the
507
               feature to be removed from the database a dbID value must
508 509 510 511 512 513 514 515
               be returned.
  Returntype : none
  Exceptions : thrown if $feature arg does not implement dbID(), or if 
               $feature->dbID is not a true value               
  Caller     : general

=cut

516

517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
sub remove {
  my ($self, $feature) = @_;

  unless($feature->can('dbID')) {
    $self->throw("Feature [$feature] does not implement method dbID");
  }

  unless($feature->dbID) {
    $self->warn("BaseFeatureAdaptor::remove - dbID not defined - " .
                "feature could not be removed");
  }

  my $table = $self->_tablename();

  my $sth = $self->prepare("DELETE FROM $table WHERE ${table}_id = ?");
  $sth->execute($feature->dbID());

  #unset the feature dbID
  $feature->dbID('');
  
  return;
}


541

542
=head2 remove_by_RawContig
543 544

  Arg [1]    : Bio::Ensembl::RawContig $contig 
545
  Example    : $feature_adaptor->remove_by_RawContig($contig);
546 547 548 549
  Description: This removes features from the database which lie on a removed
               contig.  The table the features are removed from is defined by 
               the abstract method_tablename, and the primary key of the table
               is assumed to be contig_id.
550
  Returntype : none
551
  Exceptions : thrown if no contig is supplied
552 553 554 555
  Caller     : general

=cut

556
sub remove_by_RawContig {
557
  my ($self, $contig) = @_;
558

559 560 561
  unless($contig) {
    $self->throw("BaseFeatureAdaptor::remove - no contig supplied: ".
		 "Deletion of features failed.");
562 563
  }

564
  my @tabs = $self->_tables;
565

566
  my ($table_name) = @{$tabs[0]};
567

568 569
  my $sth = $self->prepare("DELETE FROM $table_name
                            WHERE contig_id = ?");
570

571
  $sth->execute($contig->dbID);
572 573 574 575 576 577

  return;
}



578
=head2 _tables
579

580 581 582
  Args       : none
  Example    : $tablename = $self->_table_name()
  Description: ABSTRACT PROTECTED Subclasses are responsible for implementing
583 584 585 586 587 588
               this method.  It should list of [tablename, alias] pairs.  
               Additionally the primary table (with the dbID, analysis_id, and
               score) should be the first table in the list.
               e.g:
               ( ['repeat_feature',   'rf'],
                 ['repeat_consensus', 'rc']);
589
               used to obtain features.  
590
  Returntype : list of [tablename, alias] pairs
591 592
  Exceptions : thrown if not implemented by subclass
  Caller     : BaseFeatureAdaptor::generic_fetch
593 594 595

=cut

596
sub _tables {
597 598
  my $self = shift;

599
  $self->throw("abstract method _tables not defined by implementing" .
Simon Potter's avatar
Simon Potter committed
600
               " subclass of BaseFeatureAdaptor");
601 602 603
  return undef;
}

604

605 606
=head2 _columns

607 608 609 610 611 612 613 614
  Args       : none
  Example    : $tablename = $self->_columns()
  Description: ABSTRACT PROTECTED Subclasses are responsible for implementing
               this method.  It should return a list of columns to be used
               for feature creation
  Returntype : list of strings
  Exceptions : thrown if not implemented by subclass
  Caller     : BaseFeatureAdaptor::generic_fetch
615 616 617 618 619 620 621

=cut

sub _columns {
  my $self = shift;

  $self->throw("abstract method _columns not defined by implementing" .
Simon Potter's avatar
Simon Potter committed
622
               " subclass of BaseFeatureAdaptor");
623 624 625
}


626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641

=head2 _left_join

  Arg [1]    : none
  Example    : 
  Description: 
  Returntype : 
  Exceptions : 
  Caller     : 

=cut





642 643 644 645 646 647 648
=head2 _default_where_clause

  Arg [1]    : none
  Example    : none
  Description: May be overridden to provide an additional where constraint to 
               the SQL query which is generated to fetch feature records.
               This constraint is always appended to the end of the generated
649
               where clause
650 651 652 653 654 655 656 657 658 659 660 661 662
  Returntype : string
  Exceptions : none
  Caller     : generic_fetch

=cut

sub _default_where_clause {
  my $self = shift;

  return '';
}


663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684

=head2 _left_join

  Arg [1]    : none
  Example    : none
  Description: Can be overridden by a subclass to specify any left joins
               which should occur. The table name specigfied in the join
               must still be present in the return values of 
  Returntype : a {'tablename' => 'join condition'} pair 
  Exceptions : none
  Caller     : general

=cut

sub _left_join {
  my $self = shift;

  return '';
}



685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
=head2 _final_clause

  Arg [1]    : none
  Example    : none
  Description: May be overriden to provide an additional clause to the end
               of the SQL query used to fetch feature records.  
               This is useful to add a required ORDER BY clause to the 
               query for example.
  Returntype : string
  Exceptions : none
  Caller     : generic_fetch

=cut

sub _final_clause {
  my $self = shift;

  return '';
}

705
=head2 _objs_from_sth
706 707 708 709 710 711 712 713 714 715 716 717 718

  Arg [1]    : DBI::row_hashref $hashref containing key-value pairs 
               for each of the columns specified by the _columns method
  Example    : my @feats = $self->_obj_from_hashref
  Description: ABSTRACT PROTECTED The subclass is responsible for implementing
               this method.  It should take in a DBI row hash reference and
               return a list of created features in contig coordinates.
  Returntype : list of Bio::EnsEMBL::*Features in contig coordinates
  Exceptions : thrown if not implemented by subclass
  Caller     : BaseFeatureAdaptor::generic_fetch

=cut

719
sub _objs_from_sth {
720 721
  my $self = shift;

722
  $self->throw("abstract method _obj_from_sth not defined by implementing"
Simon Potter's avatar
Simon Potter committed
723
             . " subclass of BaseFeatureAdaptor");
724 725
} 

726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745

=head2 deleteObj

  Arg [1]    : none
  Example    : none
  Description: Cleans up internal caches and references to other objects so
               that correct garbage collection may occur.
  Returntype : none
  Exceptions : none
  Caller     : Bio::EnsEMBL::DBConnection::deleteObj

=cut

sub deleteObj {
  my $self = shift;

  #flush feature cache
  %{$self->{'_slice_feature_cache'}} = ();
}

746 747 748
1;