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
#
# 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

19
Abstract class - should not be instantiated.  Implementation of
20 21 22 23 24 25 26 27
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 29
=head1 CONTACT

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

=cut

package Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor;
35
use vars qw(@ISA $SLICE_FEATURE_CACHE_SIZE);
36 37 38
use strict;

use Bio::EnsEMBL::DBSQL::BaseAdaptor;
39
use Bio::EnsEMBL::Utils::Cache;
40 41 42

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

43
$SLICE_FEATURE_CACHE_SIZE = 4;
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63


=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
64 65
  $self->{'_slice_feature_cache'} = {};

66 67 68 69 70 71
  tie(%{$self->{'_slice_feature_cache'}}, 
      'Bio::EnsEMBL::Utils::Cache',
      $SLICE_FEATURE_CACHE_SIZE);

  return $self;
}
72 73 74 75 76 77 78

=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
79
  Example    : $fts = $a->generic_fetch('contig_id in (1234, 1235)', 'Swall');
80 81
  Description: Performs a database fetch and returns feature objects in
               contig coordinates.
82
  Returntype : listref of Bio::EnsEMBL::SeqFeature in contig coordinates
83 84 85 86
  Exceptions : none
  Caller     : BaseFeatureAdaptor, ProxyDnaAlignFeatureAdaptor::generic_fetch

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

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

108
    if($constraint) {
109
      $constraint .= " AND ${syn}.analysis_id = $analysis_id";
110
    } else {
111
      $constraint = " ${syn}.analysis_id = $analysis_id";
112 113
    }
  } 
114 115 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

  #
  # 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";
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157

  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";

158
  my $sth = $self->prepare($sql);
159 160 161
  
  $sth->execute;  

162
  return $self->_objs_from_sth($sth, $mapper, $slice);
163 164 165 166
}


=head2 fetch_by_dbID
167 168 169 170 171 172

  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. 
173
  Returntype : Bio::EnsEMBL::SeqFeature
174 175
  Exceptions : thrown if $id is not defined
  Caller     : general
176 177 178 179 180 181 182 183 184 185

=cut

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

186 187 188 189 190 191
  my @tabs = $self->_tables;

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

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

193
  #return first element of _generic_fetch list
194
  my ($feat) = @{$self->generic_fetch($constraint)}; 
195
  return $feat;
196 197 198
}


199
=head2 fetch_all_by_RawContig_constraint
200

201 202
  Arg [1]    : Bio::EnsEMBL::RawContig $contig
               The contig object from which features are to be obtained
203 204 205 206
  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
207 208
  Example    : $fs = $a->fetch_all_by_Contig_constraint($ctg,'perc_ident>5.0');
  Description: Returns a listref of features created from the database which 
209 210 211
               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. 
212
  Returntype : listref of Bio::EnsEMBL::SeqFeature in contig coordinates
213 214
  Exceptions : thrown if $cid is not defined
  Caller     : general
215 216 217

=cut

218
sub fetch_all_by_RawContig_constraint {
219
  my ($self, $contig, $constraint, $logic_name) = @_;
220
  
221 222
  unless( defined $contig ) {
    $self->throw("fetch_by_Contig_constraint must have an contig");
223 224
  }

225 226 227 228 229 230
  unless( ref $contig && $contig->isa('Bio::EnsEMBL::RawContig')) {
    $self->throw("contig argument is not a Bio::EnsEMBL::RawContig object\n");
  }

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

231 232 233 234
  #get the synonym of the primary_table
  my @tabs = $self->_tables;
  my $syn = $tabs[0]->[1];

235
  if($constraint) {
236
    $constraint .= " AND ${syn}.contig_id = $cid";
237
  } else {
238
    $constraint = "${syn}.contig_id = $cid";
239 240
  }

Alistair Rust's avatar
Alistair Rust committed
241
  return $self->generic_fetch($constraint, $logic_name);
242 243
}

244

Arne Stabenau's avatar
Arne Stabenau committed
245
=head2 fetch_all_by_RawContig
246

247 248
  Arg [1]    : Bio::EnsEMBL::RawContig $contig 
               the contig from which features should be obtained
249 250
  Arg [2]    : (optional) string $logic_name
               the logic name of the type of features to obtain
251
  Example    : @fts = $a->fetch_all_by_RawContig($contig, 'wall');
252 253 254 255
  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. 
256
  Returntype : listref of Bio::EnsEMBL::*Feature in contig coordinates
257 258 259 260
  Exceptions : none
  Caller     : general

=cut
261
   
Arne Stabenau's avatar
Arne Stabenau committed
262 263 264
sub fetch_all_by_RawContig {
  my ( $self, $contig, $logic_name ) = @_;

265
  return $self->fetch_all_by_RawContig_constraint($contig, '',$logic_name);
266 267 268
}


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

=cut

287
sub fetch_all_by_RawContig_and_score{
288
  my($self, $contig, $score, $logic_name) = @_;
289 290 291

  my $constraint;

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


304
=head2 fetch_all_by_Slice
305 306 307 308 309

  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
310 311 312 313 314 315
  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
316 317 318 319 320
  Exceptions : none
  Caller     : Bio::EnsEMBL::Slice

=cut

321
sub fetch_all_by_Slice {
322 323 324
  my ($self, $slice, $logic_name) = @_;
  
  #fetch by constraint with empty constraint
325
  return $self->fetch_all_by_Slice_constraint($slice, '', $logic_name);
326 327 328
}


329
=head2 fetch_all_by_Slice_and_score
330 331 332

  Arg [1]    : Bio::EnsEMBL::Slice $slice
               the slice from which to obtain features
333
  Arg [2]    : (optional) float $score
334 335 336
               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
337
  Example    : $fts = $a->fetch_all_by_Slice($slice, 'Swall');
338 339 340 341 342
  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. 
343
  Returntype : listref of Bio::EnsEMBL::SeqFeatures in Slice coordinates
344 345 346 347 348
  Exceptions : none
  Caller     : Bio::EnsEMBL::Slice

=cut

349
sub fetch_all_by_Slice_and_score {
350 351 352
  my ($self, $slice, $score, $logic_name) = @_;
  my $constraint;

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

360 361
  return $self->fetch_all_by_Slice_constraint($slice, $constraint, 
					      $logic_name);
362 363 364
}  


365
=head2 fetch_all_by_Slice_constraint
366

367 368 369 370 371
  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
372
               the logic name of the type of features to obtain
373 374
  Example    : $fs = $a->fetch_all_by_Slice_constraint($slc, 'perc_ident > 5');
  Description: Returns a listref of features created from the database which 
375 376 377 378
               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. 
379
  Returntype : listref of Bio::EnsEMBL::SeqFeatures in Slice coordinates
380 381
  Exceptions : thrown if $slice is not defined
  Caller     : Bio::EnsEMBL::Slice
382 383 384

=cut

385
sub fetch_all_by_Slice_constraint {
386
  my($self, $slice, $constraint, $logic_name) = @_;
387

388 389
  unless(defined $slice && ref $slice && $slice->isa("Bio::EnsEMBL::Slice")) {
    $self->throw("Slice arg must be a Bio::EnsEMBL::Slice not a [$slice]\n");
390 391
  }

392 393
  $logic_name = '' unless $logic_name;
  $constraint = '' unless $constraint;
394

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

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

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

415 416 417 418
  #get the synonym of the primary_table
  my @tabs = $self->_tables;
  my $syn = $tabs[0]->[1];

419
  #construct the SQL constraint for the contig ids 
420
  if($constraint) {
421
    $constraint .= " AND ${syn}.contig_id IN ($cid_list)";
422
  } else {
423
    $constraint = "${syn}.contig_id IN ($cid_list)";
424
  }
425

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

437 438
  #remapping has not been done, we have to do our own conversion from
  # raw contig coords to slice coords
439

440
  my @out = ();
441
  
442 443
  my ($feat_start, $feat_end, $feat_strand); 

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

448
    my ($chr_name, $start, $end, $strand) = 
449 450
      $mapper->fast_to_assembly($contig_id, $f->start(), 
				$f->end(),$f->strand(),"rawcontig");
451

452
    # undefined start means gap
453
    next unless defined $start;     
454

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


475
=head2 store
476

477
  Arg [1]    : list of Bio::EnsEMBL::SeqFeature
478 479 480 481 482 483 484
  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
485 486 487 488 489 490 491 492 493 494

=cut

sub store{
  my $self = @_;

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


495 496 497 498 499 500 501 502 503
=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
504
               feature to be removed from the database a dbID value must
505 506 507 508 509 510 511 512
               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

513

514 515 516 517 518 519 520 521 522 523 524 525
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");
  }

526 527
  my @tabs = $self->_tables;
  my ($table) = @{$tabs[0]};
528 529 530 531 532 533 534 535 536 537 538

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

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


539

540
=head2 remove_by_RawContig
541 542

  Arg [1]    : Bio::Ensembl::RawContig $contig 
543
  Example    : $feature_adaptor->remove_by_RawContig($contig);
544 545 546 547
  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.
548
  Returntype : none
549
  Exceptions : thrown if no contig is supplied
550 551 552 553
  Caller     : general

=cut

554
sub remove_by_RawContig {
555
  my ($self, $contig) = @_;
556

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

562
  my @tabs = $self->_tables;
563

564
  my ($table_name) = @{$tabs[0]};
565

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

569
  $sth->execute($contig->dbID);
570 571 572 573 574 575

  return;
}



576
=head2 _tables
577

578 579 580
  Args       : none
  Example    : $tablename = $self->_table_name()
  Description: ABSTRACT PROTECTED Subclasses are responsible for implementing
581 582 583 584 585 586
               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']);
587
               used to obtain features.  
588
  Returntype : list of [tablename, alias] pairs
589 590
  Exceptions : thrown if not implemented by subclass
  Caller     : BaseFeatureAdaptor::generic_fetch
591 592 593

=cut

594
sub _tables {
595 596
  my $self = shift;

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

602

603 604
=head2 _columns

605 606 607 608 609 610 611 612
  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
613 614 615 616 617 618 619

=cut

sub _columns {
  my $self = shift;

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


624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639

=head2 _left_join

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

=cut





640 641 642 643 644 645 646
=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
647
               where clause
648 649 650 651 652 653 654 655 656 657 658 659 660
  Returntype : string
  Exceptions : none
  Caller     : generic_fetch

=cut

sub _default_where_clause {
  my $self = shift;

  return '';
}


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

=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 '';
}



683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
=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 '';
}

703
=head2 _objs_from_sth
704 705 706 707 708 709 710 711 712 713 714 715 716

  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

717
sub _objs_from_sth {
718 719
  my $self = shift;

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

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

=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'}} = ();
}

744 745 746
1;