Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/EnsEMBL/DBSQL/ExonAdaptor.pm @ 0:1f6dce3d34e0
Uploaded
| author | mahtabm |
|---|---|
| date | Thu, 11 Apr 2013 02:01:53 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:1f6dce3d34e0 |
|---|---|
| 1 =head1 LICENSE | |
| 2 | |
| 3 Copyright (c) 1999-2012 The European Bioinformatics Institute and | |
| 4 Genome Research Limited. All rights reserved. | |
| 5 | |
| 6 This software is distributed under a modified Apache license. | |
| 7 For license details, please see | |
| 8 | |
| 9 http://www.ensembl.org/info/about/code_licence.html | |
| 10 | |
| 11 =head1 CONTACT | |
| 12 | |
| 13 Please email comments or questions to the public Ensembl | |
| 14 developers list at <dev@ensembl.org>. | |
| 15 | |
| 16 Questions may also be sent to the Ensembl help desk at | |
| 17 <helpdesk@ensembl.org>. | |
| 18 | |
| 19 =cut | |
| 20 | |
| 21 =head1 NAME | |
| 22 | |
| 23 Bio::EnsEMBL::DBSQL::ExonAdaptor - An adaptor responsible for the retrieval and | |
| 24 storage of exon objects | |
| 25 | |
| 26 =head1 SYNOPSIS | |
| 27 | |
| 28 my $exon_adaptor = $registry->get_adaptor( 'Human', 'Core', 'Exon' ); | |
| 29 | |
| 30 my $exon = $exon_adaptor->fetch_by_dbID($dbID); | |
| 31 | |
| 32 =head1 DESCRIPTION | |
| 33 | |
| 34 The ExonAdaptor is responsible for retrieving and storing Exon objects | |
| 35 from an Ensembl database. Most of the ExonAdaptor functionality is | |
| 36 inherited from the B<Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor> class. | |
| 37 | |
| 38 =head1 METHODS | |
| 39 | |
| 40 =cut | |
| 41 | |
| 42 package Bio::EnsEMBL::DBSQL::ExonAdaptor; | |
| 43 | |
| 44 use strict; | |
| 45 | |
| 46 use Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor; | |
| 47 use Bio::EnsEMBL::Exon; | |
| 48 use Bio::EnsEMBL::Utils::Exception qw( warning throw deprecate ); | |
| 49 | |
| 50 use vars qw( @ISA ); | |
| 51 @ISA = qw( Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor ); | |
| 52 | |
| 53 | |
| 54 #_tables | |
| 55 # | |
| 56 # Arg [1] : none | |
| 57 # Example : none | |
| 58 # Description: PROTECTED implementation of superclass abstract method | |
| 59 # returns the names, aliases of the tables to use for queries | |
| 60 # Returntype : list of listrefs of strings | |
| 61 # Exceptions : none | |
| 62 # Caller : internal | |
| 63 | |
| 64 sub _tables { | |
| 65 my $self = shift; | |
| 66 | |
| 67 # Allow the table definition to be overridden by certain methods. | |
| 68 if ( defined( $self->{'tables'} ) ) { | |
| 69 return @{ $self->{'tables'} }; | |
| 70 } | |
| 71 | |
| 72 return ( [ 'exon', 'e' ] ); | |
| 73 } | |
| 74 | |
| 75 | |
| 76 # _columns | |
| 77 # | |
| 78 # Arg [1] : none | |
| 79 # Example : none | |
| 80 # Description: PROTECTED implementation of superclass abstract method | |
| 81 # returns a list of columns to use for queries | |
| 82 # Returntype : list of strings | |
| 83 # Exceptions : none | |
| 84 # Caller : internal | |
| 85 | |
| 86 sub _columns { | |
| 87 my $self = shift; | |
| 88 | |
| 89 my $created_date = | |
| 90 $self->db->dbc->from_date_to_seconds("created_date"); | |
| 91 my $modified_date = | |
| 92 $self->db->dbc->from_date_to_seconds("modified_date"); | |
| 93 | |
| 94 return ( | |
| 95 'e.exon_id', 'e.seq_region_id', 'e.seq_region_start', | |
| 96 'e.seq_region_end', 'e.seq_region_strand', 'e.phase', | |
| 97 'e.end_phase', 'e.is_current', 'e.is_constitutive', | |
| 98 'e.stable_id', 'e.version', $created_date, | |
| 99 $modified_date | |
| 100 ); | |
| 101 } | |
| 102 | |
| 103 | |
| 104 | |
| 105 # _final_clause | |
| 106 # | |
| 107 # Arg [1] : none | |
| 108 # Example : none | |
| 109 # Description: PROTECTED implementation of superclass abstract method | |
| 110 # returns a default end for the SQL-query (ORDER BY) | |
| 111 # Returntype : string | |
| 112 # Exceptions : none | |
| 113 # Caller : internal | |
| 114 | |
| 115 sub _final_clause { | |
| 116 my $self = shift; | |
| 117 return $self->{'final_clause'} || ''; | |
| 118 } | |
| 119 | |
| 120 | |
| 121 sub fetch_all { | |
| 122 my ($self) = @_; | |
| 123 | |
| 124 my $constraint = 'e.is_current = 1'; | |
| 125 my @exons = @{ $self->generic_fetch($constraint) }; | |
| 126 return \@exons ; | |
| 127 } | |
| 128 | |
| 129 =head2 fetch_by_stable_id | |
| 130 | |
| 131 Arg [1] : string $stable_id | |
| 132 the stable id of the exon to retrieve | |
| 133 Example : $exon = $exon_adaptor->fetch_by_stable_id('ENSE0000988221'); | |
| 134 Description: Retrieves an Exon from the database via its stable id | |
| 135 Returntype : Bio::EnsEMBL::Exon in native coordinates. | |
| 136 Exceptions : none | |
| 137 Caller : general | |
| 138 Status : Stable | |
| 139 | |
| 140 =cut | |
| 141 | |
| 142 sub fetch_by_stable_id { | |
| 143 my ($self, $stable_id) = @_; | |
| 144 | |
| 145 my $constraint = "e.stable_id = ? AND e.is_current = 1"; | |
| 146 | |
| 147 $self->bind_param_generic_fetch($stable_id,SQL_VARCHAR); | |
| 148 my ($exon) = @{ $self->generic_fetch($constraint) }; | |
| 149 | |
| 150 return $exon; | |
| 151 } | |
| 152 | |
| 153 | |
| 154 =head2 fetch_all_versions_by_stable_id | |
| 155 | |
| 156 Arg [1] : String $stable_id | |
| 157 The stable ID of the exon to retrieve | |
| 158 Example : my $exon = $exon_adaptor->fetch_all_version_by_stable_id | |
| 159 ('ENSE00000309301'); | |
| 160 Description : Similar to fetch_by_stable_id, but retrieves all versions of an | |
| 161 exon stored in the database. | |
| 162 Returntype : listref of Bio::EnsEMBL::Exon objects | |
| 163 Exceptions : if we cant get the gene in given coord system | |
| 164 Caller : general | |
| 165 Status : At Risk | |
| 166 | |
| 167 =cut | |
| 168 | |
| 169 sub fetch_all_versions_by_stable_id { | |
| 170 my ($self, $stable_id) = @_; | |
| 171 | |
| 172 my $constraint = "e.stable_id = ?"; | |
| 173 | |
| 174 $self->bind_param_generic_fetch($stable_id,SQL_VARCHAR); | |
| 175 | |
| 176 return $self->generic_fetch($constraint); | |
| 177 } | |
| 178 | |
| 179 | |
| 180 =head2 fetch_all_by_Transcript | |
| 181 | |
| 182 Arg [1] : Bio::EnsEMBL::Transcript $transcript | |
| 183 Example : none | |
| 184 Description: Retrieves all Exons for the Transcript in 5-3 order | |
| 185 Returntype : listref Bio::EnsEMBL::Exon on Transcript slice | |
| 186 Exceptions : throws if transcript has no slice | |
| 187 Caller : Transcript->get_all_Exons() | |
| 188 Status : Stable | |
| 189 | |
| 190 =cut | |
| 191 | |
| 192 sub fetch_all_by_Transcript { | |
| 193 my ( $self, $transcript ) = @_; | |
| 194 | |
| 195 my $tslice = $transcript->slice(); | |
| 196 my $slice; | |
| 197 | |
| 198 if ( !defined($tslice) ) { | |
| 199 throw("Transcript must have attached slice to retrieve exons."); | |
| 200 } | |
| 201 | |
| 202 # use a small slice the same size as the transcript | |
| 203 if ( !$tslice->is_circular() ) { | |
| 204 $slice = | |
| 205 $self->db()->get_SliceAdaptor()->fetch_by_Feature($transcript); | |
| 206 } else { | |
| 207 # Circular. | |
| 208 $slice = $tslice; | |
| 209 } | |
| 210 | |
| 211 # Override the tables definition to provide an additional join to the | |
| 212 # exon_transcript table. For efficiency we cannot afford to have this | |
| 213 # in as a left join every time. | |
| 214 my @tables = $self->_tables(); | |
| 215 | |
| 216 # Be extra cautious so that we do not add 'exon_transcript' twice. | |
| 217 my $found = 0; | |
| 218 foreach my $table (@tables) { | |
| 219 if ( $table->[0] eq 'exon_transcript' ) { | |
| 220 $found = 1; | |
| 221 last; | |
| 222 } | |
| 223 } | |
| 224 if ( !$found ) { | |
| 225 push @tables, [ 'exon_transcript', 'et' ]; | |
| 226 } | |
| 227 | |
| 228 $self->{'tables'} = \@tables; | |
| 229 $self->{'final_clause'} = "ORDER BY et.transcript_id, et.rank"; | |
| 230 | |
| 231 my $constraint = | |
| 232 "et.transcript_id = " | |
| 233 . $transcript->dbID() | |
| 234 . " AND e.exon_id = et.exon_id"; | |
| 235 | |
| 236 # fetch all of the exons | |
| 237 my $exons = $self->fetch_all_by_Slice_constraint($slice, $constraint); | |
| 238 | |
| 239 # un-override the table definition | |
| 240 delete( $self->{'tables'} ); | |
| 241 delete( $self->{'final_clause'} ); | |
| 242 | |
| 243 # remap exon coordinates if necessary | |
| 244 if($slice->name() ne $tslice->name()) { | |
| 245 my @out; | |
| 246 foreach my $ex (@$exons) { | |
| 247 push @out, $ex->transfer($tslice); | |
| 248 } | |
| 249 $exons = \@out; | |
| 250 } | |
| 251 | |
| 252 return $exons; | |
| 253 } | |
| 254 | |
| 255 | |
| 256 =head2 store | |
| 257 | |
| 258 Arg [1] : Bio::EnsEMBL::Exon $exon | |
| 259 the exon to store in this database | |
| 260 Example : $exon_adaptor->store($exon); | |
| 261 Description: Stores an exon in the database | |
| 262 Returntype : none | |
| 263 Exceptions : thrown if exon (or component exons) do not have a contig_id | |
| 264 or if $exon->start, $exon->end, $exon->strand, or $exon->phase | |
| 265 are not defined or if $exon is not a Bio::EnsEMBL::Exon | |
| 266 Caller : general | |
| 267 Status : Stable | |
| 268 | |
| 269 =cut | |
| 270 | |
| 271 sub store { | |
| 272 my ($self, $exon) = @_; | |
| 273 | |
| 274 if( ! $exon->isa('Bio::EnsEMBL::Exon') ) { | |
| 275 throw("$exon is not a EnsEMBL exon - not storing."); | |
| 276 } | |
| 277 | |
| 278 my $db = $self->db(); | |
| 279 | |
| 280 if($exon->is_stored($db)) { | |
| 281 return $exon->dbID(); | |
| 282 } | |
| 283 | |
| 284 if( ! $exon->start || ! $exon->end || | |
| 285 ! $exon->strand || ! defined $exon->phase ) { | |
| 286 throw("Exon does not have all attributes to store"); | |
| 287 } | |
| 288 | |
| 289 # Default to is_current = 1 if this attribute is not set | |
| 290 my $is_current = $exon->is_current(); | |
| 291 if ( !defined($is_current) ) { $is_current = 1 } | |
| 292 | |
| 293 # Default to is_constitutive = 0 if this attribute is not set | |
| 294 my $is_constitutive = $exon->is_constitutive(); | |
| 295 if ( !defined($is_constitutive) ) { $is_constitutive = 0 } | |
| 296 | |
| 297 my $exon_sql = q{ | |
| 298 INSERT into exon ( seq_region_id, seq_region_start, | |
| 299 seq_region_end, seq_region_strand, phase, | |
| 300 end_phase, is_current, is_constitutive | |
| 301 }; | |
| 302 if ( defined($exon->stable_id) ) { | |
| 303 my $created = $self->db->dbc->from_seconds_to_date($exon->created_date()); | |
| 304 my $modified = $self->db->dbc->from_seconds_to_date($exon->modified_date()); | |
| 305 $exon_sql .= ", stable_id, version, created_date, modified_date) VALUES ( ?,?,?,?,?,?,?,?,?,?,". $created . ",". $modified ." )"; | |
| 306 | |
| 307 } else { | |
| 308 $exon_sql .= q{ | |
| 309 ) VALUES ( ?,?,?,?,?,?,?,?) | |
| 310 }; | |
| 311 } | |
| 312 | |
| 313 | |
| 314 my $exonst = $self->prepare($exon_sql); | |
| 315 | |
| 316 my $exonId = undef; | |
| 317 | |
| 318 my $original = $exon; | |
| 319 my $seq_region_id; | |
| 320 ($exon, $seq_region_id) = $self->_pre_store($exon); | |
| 321 | |
| 322 #store the exon | |
| 323 $exonst->bind_param( 1, $seq_region_id, SQL_INTEGER ); | |
| 324 $exonst->bind_param( 2, $exon->start, SQL_INTEGER ); | |
| 325 $exonst->bind_param( 3, $exon->end, SQL_INTEGER ); | |
| 326 $exonst->bind_param( 4, $exon->strand, SQL_TINYINT ); | |
| 327 $exonst->bind_param( 5, $exon->phase, SQL_TINYINT ); | |
| 328 $exonst->bind_param( 6, $exon->end_phase, SQL_TINYINT ); | |
| 329 $exonst->bind_param( 7, $is_current, SQL_TINYINT ); | |
| 330 $exonst->bind_param( 8, $is_constitutive, SQL_TINYINT ); | |
| 331 | |
| 332 if ( defined($exon->stable_id) ) { | |
| 333 | |
| 334 $exonst->bind_param( 9, $exon->stable_id, SQL_VARCHAR ); | |
| 335 my $version = ($exon->version()) ? $exon->version() : 1; | |
| 336 $exonst->bind_param( 10, $version, SQL_INTEGER ); | |
| 337 } | |
| 338 | |
| 339 $exonst->execute(); | |
| 340 $exonId = $exonst->{'mysql_insertid'}; | |
| 341 | |
| 342 # Now the supporting evidence | |
| 343 my $esf_adaptor = $db->get_SupportingFeatureAdaptor; | |
| 344 $esf_adaptor->store($exonId, $exon->get_all_supporting_features); | |
| 345 | |
| 346 # | |
| 347 # Finally, update the dbID and adaptor of the exon (and any component exons) | |
| 348 # to point to the new database | |
| 349 # | |
| 350 | |
| 351 $original->adaptor($self); | |
| 352 $original->dbID($exonId); | |
| 353 | |
| 354 return $exonId; | |
| 355 } | |
| 356 | |
| 357 | |
| 358 =head2 remove | |
| 359 | |
| 360 Arg [1] : Bio::EnsEMBL::Exon $exon | |
| 361 the exon to remove from the database | |
| 362 Example : $exon_adaptor->remove($exon); | |
| 363 Description: Removes an exon from the database. This method is generally | |
| 364 called by the TranscriptAdaptor::store method. Database | |
| 365 integrity will not be maintained if this method is simply | |
| 366 called on its own without taking into account transcripts which | |
| 367 may refer to the exon being removed. | |
| 368 Returntype : none | |
| 369 Exceptions : none | |
| 370 Caller : general | |
| 371 Status : Stable | |
| 372 | |
| 373 =cut | |
| 374 | |
| 375 sub remove { | |
| 376 my $self = shift; | |
| 377 my $exon = shift; | |
| 378 | |
| 379 if(!ref($exon) || !$exon->isa('Bio::EnsEMBL::Exon')) { | |
| 380 throw('Bio::EnsEMBL::Exon argument expected.'); | |
| 381 } | |
| 382 | |
| 383 if(!$exon->is_stored($self->db())) { | |
| 384 warning("Cannot remove exon " .$exon->dbID. | |
| 385 "Is not stored in this database."); | |
| 386 return; | |
| 387 } | |
| 388 | |
| 389 # sanity check: make sure nobdody tries to slip past a prediction exon | |
| 390 # which inherits from exon but actually uses different tables | |
| 391 if($exon->isa('Bio::EnsEMBL::PredictionExon')) { | |
| 392 throw("ExonAdaptor can only remove Exons not PredictionExons."); | |
| 393 } | |
| 394 | |
| 395 # Remove the supporting features of this exon | |
| 396 | |
| 397 my $prot_adp = $self->db->get_ProteinAlignFeatureAdaptor; | |
| 398 my $dna_adp = $self->db->get_DnaAlignFeatureAdaptor; | |
| 399 | |
| 400 my $sth = $self->prepare("SELECT feature_type, feature_id " . | |
| 401 "FROM supporting_feature " . | |
| 402 "WHERE exon_id = ?"); | |
| 403 $sth->bind_param(1, $exon->dbID, SQL_INTEGER); | |
| 404 $sth->execute(); | |
| 405 | |
| 406 # statements to check for shared align_features | |
| 407 my $sth1 = $self->prepare("SELECT count(*) FROM supporting_feature " . | |
| 408 "WHERE feature_type = ? AND feature_id = ?"); | |
| 409 my $sth2 = $self->prepare("SELECT count(*) " . | |
| 410 "FROM transcript_supporting_feature " . | |
| 411 "WHERE feature_type = ? AND feature_id = ?"); | |
| 412 | |
| 413 SUPPORTING_FEATURE: | |
| 414 while(my ($type, $feature_id) = $sth->fetchrow()){ | |
| 415 | |
| 416 # only remove align_feature if this is the last reference to it | |
| 417 $sth1->bind_param(1, $type, SQL_VARCHAR); | |
| 418 $sth1->bind_param(2, $feature_id, SQL_INTEGER); | |
| 419 $sth1->execute; | |
| 420 $sth2->bind_param(1, $type, SQL_VARCHAR); | |
| 421 $sth2->bind_param(2, $feature_id, SQL_INTEGER); | |
| 422 $sth2->execute; | |
| 423 my ($count1) = $sth1->fetchrow; | |
| 424 my ($count2) = $sth2->fetchrow; | |
| 425 if ($count1 + $count2 > 1) { | |
| 426 #warn "shared feature, not removing $type|$feature_id\n"; | |
| 427 next SUPPORTING_FEATURE; | |
| 428 } | |
| 429 | |
| 430 #warn "removing $type|$feature_id\n"; | |
| 431 | |
| 432 if($type eq 'protein_align_feature'){ | |
| 433 my $f = $prot_adp->fetch_by_dbID($feature_id); | |
| 434 $prot_adp->remove($f); | |
| 435 } | |
| 436 elsif($type eq 'dna_align_feature'){ | |
| 437 my $f = $dna_adp->fetch_by_dbID($feature_id); | |
| 438 $dna_adp->remove($f); | |
| 439 } | |
| 440 else { | |
| 441 warning("Unknown supporting feature type $type. Not removing feature."); | |
| 442 } | |
| 443 } | |
| 444 $sth->finish(); | |
| 445 $sth1->finish(); | |
| 446 $sth2->finish(); | |
| 447 | |
| 448 # delete the association to supporting features | |
| 449 | |
| 450 $sth = $self->prepare("DELETE FROM supporting_feature WHERE exon_id = ?"); | |
| 451 $sth->bind_param(1, $exon->dbID, SQL_INTEGER); | |
| 452 $sth->execute(); | |
| 453 $sth->finish(); | |
| 454 | |
| 455 | |
| 456 # delete the exon | |
| 457 | |
| 458 $sth = $self->prepare( "DELETE FROM exon WHERE exon_id = ?" ); | |
| 459 $sth->bind_param(1, $exon->dbID, SQL_INTEGER); | |
| 460 $sth->execute(); | |
| 461 $sth->finish(); | |
| 462 | |
| 463 $exon->dbID(undef); | |
| 464 $exon->adaptor(undef); | |
| 465 | |
| 466 return; | |
| 467 } | |
| 468 | |
| 469 | |
| 470 =head2 list_dbIDs | |
| 471 | |
| 472 Arg [1] : none | |
| 473 Example : @exon_ids = @{$exon_adaptor->list_dbIDs()}; | |
| 474 Description: Gets an array of internal ids for all exons in the current db | |
| 475 Arg[1] : <optional> int. not 0 for the ids to be sorted by the seq_region. | |
| 476 Returntype : list of ints | |
| 477 Exceptions : none | |
| 478 Caller : ? | |
| 479 Status : Stable | |
| 480 | |
| 481 =cut | |
| 482 | |
| 483 sub list_dbIDs { | |
| 484 my ($self, $ordered) = @_; | |
| 485 | |
| 486 return $self->_list_dbIDs("exon",undef, $ordered); | |
| 487 } | |
| 488 | |
| 489 | |
| 490 =head2 list_stable_ids | |
| 491 | |
| 492 Arg [1] : none | |
| 493 Example : @stable_exon_ids = @{$exon_adaptor->list_stable_dbIDs()}; | |
| 494 Description: Gets an array of stable ids for all exons in the current db | |
| 495 Returntype : list of ints | |
| 496 Exceptions : none | |
| 497 Caller : ? | |
| 498 Status : Stable | |
| 499 | |
| 500 =cut | |
| 501 | |
| 502 sub list_stable_ids { | |
| 503 my ($self) = @_; | |
| 504 | |
| 505 return $self->_list_dbIDs("exon", "stable_id"); | |
| 506 } | |
| 507 | |
| 508 #_objs_from_sth | |
| 509 # | |
| 510 # Arg [1] : StatementHandle $sth | |
| 511 # Example : none | |
| 512 # Description: PROTECTED implementation of abstract superclass method. | |
| 513 # responsible for the creation of Exons | |
| 514 # Returntype : listref of Bio::EnsEMBL::Exons in target coordinate system | |
| 515 # Exceptions : none | |
| 516 # Caller : internal | |
| 517 | |
| 518 sub _objs_from_sth { | |
| 519 my ( $self, $sth, $mapper, $dest_slice ) = @_; | |
| 520 | |
| 521 # | |
| 522 # This code is ugly because an attempt has been made to remove as many | |
| 523 # function calls as possible for speed purposes. Thus many caches and | |
| 524 # a fair bit of gymnastics is used. | |
| 525 # | |
| 526 | |
| 527 my $sa = $self->db()->get_SliceAdaptor(); | |
| 528 | |
| 529 my @exons; | |
| 530 my %slice_hash; | |
| 531 my %sr_name_hash; | |
| 532 my %sr_cs_hash; | |
| 533 | |
| 534 my ( $exon_id, $seq_region_id, $seq_region_start, | |
| 535 $seq_region_end, $seq_region_strand, $phase, | |
| 536 $end_phase, $is_current, $is_constitutive, | |
| 537 $stable_id, $version, $created_date, | |
| 538 $modified_date ); | |
| 539 | |
| 540 $sth->bind_columns( \( $exon_id, $seq_region_id, $seq_region_start, | |
| 541 $seq_region_end, $seq_region_strand, $phase, | |
| 542 $end_phase, $is_current, $is_constitutive, | |
| 543 $stable_id, $version, $created_date, | |
| 544 $modified_date ) ); | |
| 545 | |
| 546 my $asm_cs; | |
| 547 my $cmp_cs; | |
| 548 my $asm_cs_vers; | |
| 549 my $asm_cs_name; | |
| 550 my $cmp_cs_vers; | |
| 551 my $cmp_cs_name; | |
| 552 | |
| 553 if ($mapper) { | |
| 554 $asm_cs = $mapper->assembled_CoordSystem(); | |
| 555 $cmp_cs = $mapper->component_CoordSystem(); | |
| 556 $asm_cs_name = $asm_cs->name(); | |
| 557 $asm_cs_vers = $asm_cs->version(); | |
| 558 $cmp_cs_name = $cmp_cs->name(); | |
| 559 $cmp_cs_vers = $cmp_cs->version(); | |
| 560 } | |
| 561 | |
| 562 my $dest_slice_start; | |
| 563 my $dest_slice_end; | |
| 564 my $dest_slice_strand; | |
| 565 my $dest_slice_length; | |
| 566 my $dest_slice_cs; | |
| 567 my $dest_slice_sr_name; | |
| 568 my $dest_slice_sr_id; | |
| 569 my $asma; | |
| 570 | |
| 571 if ($dest_slice) { | |
| 572 $dest_slice_start = $dest_slice->start(); | |
| 573 $dest_slice_end = $dest_slice->end(); | |
| 574 $dest_slice_strand = $dest_slice->strand(); | |
| 575 $dest_slice_length = $dest_slice->length(); | |
| 576 $dest_slice_cs = $dest_slice->coord_system(); | |
| 577 $dest_slice_sr_name = $dest_slice->seq_region_name(); | |
| 578 $dest_slice_sr_id = $dest_slice->get_seq_region_id(); | |
| 579 $asma = $self->db->get_AssemblyMapperAdaptor(); | |
| 580 } | |
| 581 | |
| 582 FEATURE: while ( $sth->fetch() ) { | |
| 583 #need to get the internal_seq_region, if present | |
| 584 $seq_region_id = $self->get_seq_region_id_internal($seq_region_id); | |
| 585 | |
| 586 my $slice = $slice_hash{ "ID:" . $seq_region_id }; | |
| 587 my $dest_mapper = $mapper; | |
| 588 | |
| 589 if ( !$slice ) { | |
| 590 $slice = $sa->fetch_by_seq_region_id($seq_region_id); | |
| 591 $slice_hash{ "ID:" . $seq_region_id } = $slice; | |
| 592 $sr_name_hash{$seq_region_id} = $slice->seq_region_name(); | |
| 593 $sr_cs_hash{$seq_region_id} = $slice->coord_system(); | |
| 594 } | |
| 595 | |
| 596 #obtain a mapper if none was defined, but a dest_seq_region was | |
| 597 if ( !$dest_mapper | |
| 598 && $dest_slice | |
| 599 && !$dest_slice_cs->equals( $slice->coord_system ) ) | |
| 600 { | |
| 601 $dest_mapper = | |
| 602 $asma->fetch_by_CoordSystems( $dest_slice_cs, | |
| 603 $slice->coord_system ); | |
| 604 $asm_cs = $dest_mapper->assembled_CoordSystem(); | |
| 605 $cmp_cs = $dest_mapper->component_CoordSystem(); | |
| 606 $asm_cs_name = $asm_cs->name(); | |
| 607 $asm_cs_vers = $asm_cs->version(); | |
| 608 $cmp_cs_name = $cmp_cs->name(); | |
| 609 $cmp_cs_vers = $cmp_cs->version(); | |
| 610 } | |
| 611 | |
| 612 my $sr_name = $sr_name_hash{$seq_region_id}; | |
| 613 my $sr_cs = $sr_cs_hash{$seq_region_id}; | |
| 614 | |
| 615 # | |
| 616 # Remap the feature coordinates to another coord system if a mapper | |
| 617 # was provided. | |
| 618 # | |
| 619 if ( defined($dest_mapper) ) { | |
| 620 | |
| 621 if (defined $dest_slice && $dest_mapper->isa('Bio::EnsEMBL::ChainedAssemblyMapper') ) { | |
| 622 ( $seq_region_id, $seq_region_start, | |
| 623 $seq_region_end, $seq_region_strand ) | |
| 624 = | |
| 625 $dest_mapper->map( $sr_name, $seq_region_start, $seq_region_end, | |
| 626 $seq_region_strand, $sr_cs, 1, $dest_slice); | |
| 627 | |
| 628 } else { | |
| 629 | |
| 630 ( $seq_region_id, $seq_region_start, | |
| 631 $seq_region_end, $seq_region_strand ) | |
| 632 = $dest_mapper->fastmap( $sr_name, $seq_region_start, | |
| 633 $seq_region_end, $seq_region_strand, | |
| 634 $sr_cs ); | |
| 635 } | |
| 636 | |
| 637 # Skip features that map to gaps or coord system boundaries. | |
| 638 if ( !defined($seq_region_id) ) { next FEATURE } | |
| 639 | |
| 640 # Get a slice in the coord system we just mapped to | |
| 641 $slice = $slice_hash{ "ID:" . $seq_region_id } ||= | |
| 642 $sa->fetch_by_seq_region_id($seq_region_id); | |
| 643 } | |
| 644 | |
| 645 # | |
| 646 # If a destination slice was provided convert the coords. | |
| 647 # | |
| 648 if ( defined($dest_slice) ) { | |
| 649 if ( $dest_slice_strand == 1 ) { | |
| 650 # On the positive strand. | |
| 651 | |
| 652 $seq_region_start = $seq_region_start - $dest_slice_start + 1; | |
| 653 $seq_region_end = $seq_region_end - $dest_slice_start + 1; | |
| 654 | |
| 655 if ( ( $seq_region_end > $dest_slice_start || $seq_region_end < 0 || ( $dest_slice_start > $dest_slice_end | |
| 656 && $seq_region_end < 0 ) ) && $dest_slice->is_circular() ) { | |
| 657 # Handle circular chromosomes. | |
| 658 | |
| 659 if ( $seq_region_start > $seq_region_end ) { | |
| 660 # Looking at a feature overlapping the chromsome origin. | |
| 661 | |
| 662 if ( $seq_region_end > $dest_slice_start ) { | |
| 663 # Looking at the region in the beginning of the | |
| 664 # chromosome. | |
| 665 $seq_region_start -= $dest_slice->seq_region_length(); | |
| 666 } | |
| 667 | |
| 668 if ( $seq_region_end < 0 ) { | |
| 669 $seq_region_end += $dest_slice->seq_region_length(); | |
| 670 } | |
| 671 | |
| 672 } else { | |
| 673 if ( $dest_slice_start > $dest_slice_end | |
| 674 && $seq_region_end < 0 ) | |
| 675 { | |
| 676 # Looking at the region overlapping the chromosome | |
| 677 # origin and a feature which is at the beginning of the | |
| 678 # chromosome. | |
| 679 $seq_region_start += $dest_slice->seq_region_length(); | |
| 680 $seq_region_end += $dest_slice->seq_region_length(); | |
| 681 } | |
| 682 } | |
| 683 } | |
| 684 | |
| 685 } else { | |
| 686 # On the negative strand. | |
| 687 | |
| 688 if ( $seq_region_start > $seq_region_end && $dest_slice->is_circular() ) | |
| 689 { | |
| 690 # Handle circular chromosomes. | |
| 691 | |
| 692 if ( $dest_slice_start > $dest_slice_end ) { | |
| 693 my $tmp_seq_region_start = $seq_region_start; | |
| 694 $seq_region_start = $dest_slice_end - $seq_region_end + 1; | |
| 695 $seq_region_end = | |
| 696 $dest_slice_end + | |
| 697 $dest_slice->seq_region_length() - | |
| 698 $tmp_seq_region_start + 1; | |
| 699 } else { | |
| 700 | |
| 701 if ( $seq_region_end > $dest_slice_start ) { | |
| 702 # Looking at the region in the beginning of the | |
| 703 # chromosome. | |
| 704 $seq_region_start = $dest_slice_end - $seq_region_end + 1; | |
| 705 $seq_region_end = | |
| 706 $seq_region_end - | |
| 707 $dest_slice->seq_region_length() - | |
| 708 $dest_slice_start + 1; | |
| 709 } else { | |
| 710 my $tmp_seq_region_start = $seq_region_start; | |
| 711 $seq_region_start = | |
| 712 $dest_slice_end - | |
| 713 $seq_region_end - | |
| 714 $dest_slice->seq_region_length() + 1; | |
| 715 $seq_region_end = | |
| 716 $dest_slice_end - $tmp_seq_region_start + 1; | |
| 717 } | |
| 718 | |
| 719 } | |
| 720 | |
| 721 } else { | |
| 722 # Non-circular chromosome. | |
| 723 | |
| 724 my $tmp_seq_region_start = $seq_region_start; | |
| 725 $seq_region_start = $dest_slice_end - $seq_region_end + 1; | |
| 726 $seq_region_end = $dest_slice_end - $tmp_seq_region_start + 1; | |
| 727 } | |
| 728 | |
| 729 $seq_region_strand = -$seq_region_strand; | |
| 730 | |
| 731 } ## end else [ if ( $dest_slice_strand...)] | |
| 732 | |
| 733 # Throw away features off the end of the requested slice. | |
| 734 if ( $seq_region_end < 1 | |
| 735 || $seq_region_start > $dest_slice_length | |
| 736 || ( $dest_slice_sr_id != $seq_region_id ) ) | |
| 737 { | |
| 738 next FEATURE; | |
| 739 } | |
| 740 | |
| 741 $slice = $dest_slice; | |
| 742 } ## end if ( defined($dest_slice...)) | |
| 743 | |
| 744 # Finally, create the new exon. | |
| 745 push( @exons, | |
| 746 $self->_create_feature_fast( | |
| 747 'Bio::EnsEMBL::Exon', { | |
| 748 'start' => $seq_region_start, | |
| 749 'end' => $seq_region_end, | |
| 750 'strand' => $seq_region_strand, | |
| 751 'adaptor' => $self, | |
| 752 'slice' => $slice, | |
| 753 'dbID' => $exon_id, | |
| 754 'stable_id' => $stable_id, | |
| 755 'version' => $version, | |
| 756 'created_date' => $created_date || undef, | |
| 757 'modified_date' => $modified_date || undef, | |
| 758 'phase' => $phase, | |
| 759 'end_phase' => $end_phase, | |
| 760 'is_current' => $is_current, | |
| 761 'is_constitutive' => $is_constitutive } ) | |
| 762 ); | |
| 763 | |
| 764 } ## end while ( $sth->fetch() ) | |
| 765 | |
| 766 return \@exons; | |
| 767 } ## end sub _objs_from_sth | |
| 768 | |
| 769 =head1 DEPRECATED METHODS | |
| 770 | |
| 771 =cut | |
| 772 | |
| 773 | |
| 774 =head2 get_stable_entry_info | |
| 775 | |
| 776 Description: DEPRECATED. This method is no longer necessary. Exons are | |
| 777 always fetched with their stable identifiers (if they exist) and | |
| 778 no lazy loading is necessary. | |
| 779 | |
| 780 =cut | |
| 781 | |
| 782 sub get_stable_entry_info { | |
| 783 my ($self,$exon) = @_; | |
| 784 | |
| 785 deprecated( "This method call shouldnt be necessary" ); | |
| 786 | |
| 787 if( !$exon || !ref $exon || !$exon->isa('Bio::EnsEMBL::Exon') ) { | |
| 788 $self->throw("Needs a exon object, not a $exon"); | |
| 789 } | |
| 790 if(!$exon->dbID){ | |
| 791 #$self->throw("can't fetch stable info with no dbID"); | |
| 792 return; | |
| 793 } | |
| 794 | |
| 795 my $created_date = $self->db->dbc->from_date_to_seconds("created_date"); | |
| 796 my $modified_date = $self->db->dbc->from_date_to_seconds("modified_date"); | |
| 797 my $sth = $self->prepare("SELECT stable_id, " . $created_date . ", | |
| 798 " . $modified_date . ", version | |
| 799 FROM exon | |
| 800 WHERE exon_id = "); | |
| 801 | |
| 802 $sth->bind_param(1, $exon->dbID, SQL_INTEGER); | |
| 803 $sth->execute(); | |
| 804 | |
| 805 # my @array = $sth->fetchrow_array(); | |
| 806 if( my $aref = $sth->fetchrow_arrayref() ) { | |
| 807 $exon->{'_stable_id'} = $aref->[0]; | |
| 808 $exon->{'_created'} = $aref->[1]; | |
| 809 $exon->{'_modified'} = $aref->[2]; | |
| 810 $exon->{'_version'} = $aref->[3]; | |
| 811 } | |
| 812 | |
| 813 return 1; | |
| 814 } | |
| 815 | |
| 816 | |
| 817 =head2 fetch_all_by_gene_id | |
| 818 | |
| 819 Description: DEPRECATED. This method should not be needed - Exons can | |
| 820 be fetched by Transcript. | |
| 821 | |
| 822 =cut | |
| 823 | |
| 824 sub fetch_all_by_gene_id { | |
| 825 my ( $self, $gene_id ) = @_; | |
| 826 my %exons; | |
| 827 my $hashRef; | |
| 828 my ( $currentId, $currentTranscript ); | |
| 829 | |
| 830 deprecated( "Hopefully this method is not needed any more. Exons should be fetched by Transcript" ); | |
| 831 | |
| 832 if( !$gene_id ) { | |
| 833 $self->throw("Gene dbID not defined"); | |
| 834 } | |
| 835 | |
| 836 $self->{rchash} = {}; | |
| 837 | |
| 838 my $query = qq { | |
| 839 SELECT | |
| 840 STRAIGHT_JOIN | |
| 841 e.exon_id | |
| 842 , e.contig_id | |
| 843 , e.contig_start | |
| 844 , e.contig_end | |
| 845 , e.contig_strand | |
| 846 , e.phase | |
| 847 , e.end_phase | |
| 848 , e.sticky_rank | |
| 849 FROM transcript t | |
| 850 , exon_transcript et | |
| 851 , exon e | |
| 852 WHERE t.gene_id = ? | |
| 853 AND et.transcript_id = t.transcript_id | |
| 854 AND e.exon_id = et.exon_id | |
| 855 ORDER BY t.transcript_id,e.exon_id | |
| 856 , e.sticky_rank DESC | |
| 857 }; | |
| 858 | |
| 859 my $sth = $self->prepare( $query ); | |
| 860 $sth->bind_param(1,$gene_id,SQL_INTEGER); | |
| 861 $sth->execute(); | |
| 862 | |
| 863 while( $hashRef = $sth->fetchrow_hashref() ) { | |
| 864 if( ! exists $exons{ $hashRef->{exon_id} } ) { | |
| 865 | |
| 866 my $exon = $self->_exon_from_sth( $sth, $hashRef ); | |
| 867 | |
| 868 $exons{$exon->dbID} = $exon; | |
| 869 } | |
| 870 } | |
| 871 delete $self->{rchash}; | |
| 872 | |
| 873 my @out = (); | |
| 874 | |
| 875 push @out, values %exons; | |
| 876 | |
| 877 return \@out; | |
| 878 } | |
| 879 | |
| 880 | |
| 881 1; | |
| 882 | |
| 883 |
