Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/EnsEMBL/Funcgen/RegulatoryFeature.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 | |
| 2 =head1 LICENSE | |
| 3 | |
| 4 Copyright (c) 1999-2012 The European Bioinformatics Institute and | |
| 5 Genome Research Limited. All rights reserved. | |
| 6 | |
| 7 This software is distributed under a modified Apache license. | |
| 8 For license details, please see | |
| 9 | |
| 10 http://www.ensembl.org/info/about/code_licence.html | |
| 11 | |
| 12 =head1 CONTACT | |
| 13 | |
| 14 Please email comments or questions to the public Ensembl | |
| 15 developers list at <ensembl-dev@ebi.ac.uk>. | |
| 16 | |
| 17 Questions may also be sent to the Ensembl help desk at | |
| 18 <helpdesk@ensembl.org>. | |
| 19 | |
| 20 =head1 NAME | |
| 21 | |
| 22 Bio::EnsEMBL::Funcgen::RegulatoryFeature | |
| 23 | |
| 24 =head1 SYNOPSIS | |
| 25 | |
| 26 use Bio::EnsEMBL::Registry; | |
| 27 use Bio::EnsEMBL::Funcgen::RegulatoryFeature; | |
| 28 my $reg = Bio::EnsEMBL::Registry->load_adaptors_from_db | |
| 29 ( | |
| 30 -host => 'ensembldb.ensembl.org', | |
| 31 -user => 'anonymous' | |
| 32 ); | |
| 33 | |
| 34 my $regfeat_adaptor = $reg->get_adaptor($species, 'funcgen', 'RegulatoryFeature'); | |
| 35 | |
| 36 | |
| 37 ### Creating/storing a RegulatoryFeature Set ### | |
| 38 my $feature = Bio::EnsEMBL::Funcgen::RegulatoryFeature->new | |
| 39 ( | |
| 40 -SLICE => $chr_1_slice, | |
| 41 -START => 1_000_000, | |
| 42 -END => 1_000_024, | |
| 43 -STRAND => 0, | |
| 44 -DISPLAY_LABEL => $text, | |
| 45 -FEATURE_SET => $fset, | |
| 46 -FEATURE_TYPE => $reg_ftype, | |
| 47 -ATTRIBUTE_CACHE => \%attr_cache, | |
| 48 ); | |
| 49 | |
| 50 my ($stored_feat) = @{$regfeat_adaptor->store([$feature])}; | |
| 51 | |
| 52 | |
| 53 ### Fetching some RegualtoryFeatures | |
| 54 my @regfeats = @{$regfeat_adaptor->fetch_all_by_Slice_FeatureSets($slice, \@fsets)}; | |
| 55 | |
| 56 | |
| 57 ### Print the bound and core loci | |
| 58 print join(' - ', ($reg_feat->bound_start, | |
| 59 $reg_feat->start, | |
| 60 $reg_feat->end, | |
| 61 $reg_feat->bound_end)."\n"; | |
| 62 | |
| 63 | |
| 64 ### Getting some supporting evidence for a RegualtoryFeatures | |
| 65 my @reg_attrs = @{$reg_feat->regulatory_attributes('annotated')}; | |
| 66 | |
| 67 | |
| 68 =head1 DESCRIPTION | |
| 69 | |
| 70 A RegulatoryFeature object represents the output of the Ensembl RegulatoryBuild: | |
| 71 http://www.ensembl.org/info/docs/funcgen/regulatory_build.html | |
| 72 | |
| 73 It is comprises many possible histone, transcription factor, polymerase and open | |
| 74 chromatin features, which have been combined to provide a summary view and | |
| 75 classification of the regulatory status at a given loci. | |
| 76 | |
| 77 | |
| 78 =head1 SEE ALSO | |
| 79 | |
| 80 Bio::EnsEMBL:Funcgen::DBSQL::RegulatoryFeatureAdaptor | |
| 81 Bio::EnsEMBL::Funcgen::SetFeature | |
| 82 | |
| 83 =cut | |
| 84 | |
| 85 | |
| 86 package Bio::EnsEMBL::Funcgen::RegulatoryFeature; | |
| 87 | |
| 88 use Bio::EnsEMBL::Utils::Argument qw( rearrange ); | |
| 89 use Bio::EnsEMBL::Utils::Exception qw( throw ); | |
| 90 use strict; | |
| 91 use warnings; | |
| 92 | |
| 93 use base qw(Bio::EnsEMBL::Funcgen::SetFeature); #@ISA | |
| 94 | |
| 95 | |
| 96 =head2 new | |
| 97 | |
| 98 Arg [-SLICE] : Bio::EnsEMBL::Slice - The slice on which this feature is located. | |
| 99 Arg [-START] : int - The start coordinate of this feature relative to the start of the slice | |
| 100 it is sitting on. Coordinates start at 1 and are inclusive. | |
| 101 Arg [-END] : int -The end coordinate of this feature relative to the start of the slice | |
| 102 it is sitting on. Coordinates start at 1 and are inclusive. | |
| 103 Arg [-FEATURE_SET] : Bio::EnsEMBL::Funcgen::FeatureSet - Regulatory Feature set | |
| 104 Arg [-FEATURE_TYPE] : Bio::EnsEMBL::Funcgen::FeatureType - Regulatory Feature sub type | |
| 105 Arg [-BINARY_STRING] : (optional) string - Regulatory Build binary string | |
| 106 Arg [-STABLE_ID] : (optional) string - Stable ID for this RegualtoryFeature e.g. ENSR00000000001 | |
| 107 Arg [-DISPLAY_LABEL] : (optional) string - Display label for this feature | |
| 108 Arg [-ATTRIBUTE_CACHE] : (optional) HASHREF of feature class dbID|Object lists | |
| 109 Arg [-PROJECTED] : (optional) boolean - Flag to specify whether this feature has been projected or not | |
| 110 Arg [-dbID] : (optional) int - Internal database ID. | |
| 111 Arg [-ADAPTOR] : (optional) Bio::EnsEMBL::DBSQL::BaseAdaptor - Database adaptor. | |
| 112 | |
| 113 Example : my $feature = Bio::EnsEMBL::Funcgen::RegulatoryFeature->new( | |
| 114 -SLICE => $chr_1_slice, | |
| 115 -START => 1000000, | |
| 116 -END => 1000024, | |
| 117 -DISPLAY_LABEL => $text, | |
| 118 -FEATURE_SET => $fset, | |
| 119 -FEATURE_TYPE => $reg_ftype, | |
| 120 -ATTRIBUTE_CACHE => \%attr_cache, | |
| 121 ); | |
| 122 | |
| 123 | |
| 124 Description: Constructor for RegulatoryFeature objects. | |
| 125 Returntype : Bio::EnsEMBL::Funcgen::RegulatoryFeature | |
| 126 Exceptions : None | |
| 127 Caller : General | |
| 128 Status : Stable | |
| 129 | |
| 130 =cut | |
| 131 | |
| 132 sub new { | |
| 133 my $caller = shift; | |
| 134 my $class = ref($caller) || $caller; | |
| 135 my $self = $class->SUPER::new(@_); | |
| 136 | |
| 137 my ($stable_id, $attr_cache, $bin_string, $projected) | |
| 138 = rearrange(['STABLE_ID', 'ATTRIBUTE_CACHE', 'BINARY_STRING', 'PROJECTED'], @_); | |
| 139 | |
| 140 #None of these are mandatory at creation | |
| 141 #under different use cases | |
| 142 $self->{binary_string} = $bin_string if defined $bin_string; | |
| 143 $self->{stable_id} = $stable_id if defined $stable_id; | |
| 144 $self->{projected} = $projected if defined $projected; | |
| 145 $self->attribute_cache($attr_cache) if $attr_cache; | |
| 146 | |
| 147 return $self; | |
| 148 } | |
| 149 | |
| 150 | |
| 151 =head2 display_label | |
| 152 | |
| 153 Example : my $label = $feature->display_label(); | |
| 154 Description: Getter for the display label of this feature. | |
| 155 Returntype : String | |
| 156 Exceptions : None | |
| 157 Caller : General | |
| 158 Status : Stable | |
| 159 | |
| 160 =cut | |
| 161 | |
| 162 sub display_label { | |
| 163 my $self = shift; | |
| 164 | |
| 165 if(! defined $self->{'display_label'}){ | |
| 166 $self->{'display_label'} = $self->feature_type->name.' Regulatory Feature'; | |
| 167 | |
| 168 if( defined $self->cell_type ){ | |
| 169 $self->{'display_label'} .= ' - '.$self->cell_type->name; | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 return $self->{display_label}; | |
| 174 } | |
| 175 | |
| 176 =head2 display_id | |
| 177 | |
| 178 Example : print $feature->display_id(); | |
| 179 Description: This method returns a string that is considered to be | |
| 180 the 'display' identifier. In this case the stable Id is | |
| 181 preferred | |
| 182 Returntype : String | |
| 183 Exceptions : none | |
| 184 Caller : web drawing code, Region Report tool | |
| 185 Status : Stable | |
| 186 | |
| 187 =cut | |
| 188 | |
| 189 sub display_id { return $_[0]->{stable_id}; } | |
| 190 | |
| 191 | |
| 192 =head2 binary_string | |
| 193 | |
| 194 Arg [1] : optional string - binary string from regulatory build | |
| 195 Example : my $bin_string = $feature->binary_string(); | |
| 196 Description: Getter and setter for the binary_string for this feature. | |
| 197 Returntype : String | |
| 198 Exceptions : None | |
| 199 Caller : General | |
| 200 Status : At Risk - May change to BLOB, remove setter functionality | |
| 201 | |
| 202 =cut | |
| 203 | |
| 204 sub binary_string{ | |
| 205 my ($self, $bin_string) = @_; | |
| 206 | |
| 207 if (defined $bin_string){ | |
| 208 #added v67 | |
| 209 warn "RegualtoryFeature::binary_string setter functionality is being removed\n"; | |
| 210 $self->{binary_string} = $bin_string; | |
| 211 } | |
| 212 | |
| 213 return $self->{binary_string}; | |
| 214 } | |
| 215 | |
| 216 | |
| 217 =head2 stable_id | |
| 218 | |
| 219 Arg [1] : (optional) string - stable_id e.g ENSR00000000001 | |
| 220 Example : my $stable_id = $feature->stable_id(); | |
| 221 Description: Getter and setter for the stable_id attribute for this feature. | |
| 222 Returntype : string | |
| 223 Exceptions : None | |
| 224 Caller : General | |
| 225 Status : At risk - setter functionality to be removed | |
| 226 | |
| 227 =cut | |
| 228 | |
| 229 sub stable_id { | |
| 230 my $self = shift; | |
| 231 | |
| 232 if (@_){ | |
| 233 #added v67 | |
| 234 warn "RegualtoryFeature::stable_id setter functionality is being removed\n"; | |
| 235 $self->{stable_id} = shift; | |
| 236 } | |
| 237 | |
| 238 return $self->{stable_id}; | |
| 239 } | |
| 240 | |
| 241 | |
| 242 =head2 regulatory_attributes | |
| 243 | |
| 244 Arg [1] : String (optional) - Class of feature e.g. annotated or motif | |
| 245 Example : print "Regulatory Attributes:\n\t".join("\n\t", (map $_->feature_type->name, @{$feature->regulatory_attributes()}))."\n"; | |
| 246 Description: Getter for the regulatory_attributes for this feature. | |
| 247 Returntype : ARRAYREF | |
| 248 Exceptions : Throws if feature class not valid | |
| 249 Caller : General | |
| 250 Status : At Risk | |
| 251 | |
| 252 =cut | |
| 253 | |
| 254 | |
| 255 sub regulatory_attributes{ | |
| 256 my ($self, $feature_class) = @_; | |
| 257 | |
| 258 #Incorporating the MFs like this does cause some redundancy in the DB | |
| 259 #But will speed up display of the RegFeat image including the MFs | |
| 260 #Redefine the cache to have class keys e.g. TFBS, OpenChromatin, Histone Mods | |
| 261 #Can't do this as we need the table key to be able to fetch the features | |
| 262 #Really need something to be able to draw the image first, then create the zmenu details later. | |
| 263 | |
| 264 my %adaptors = ( | |
| 265 'annotated' => $self->adaptor->db->get_AnnotatedFeatureAdaptor, | |
| 266 'motif' => $self->adaptor->db->get_MotifFeatureAdaptor, | |
| 267 #external | |
| 268 ); | |
| 269 | |
| 270 my @fclasses; | |
| 271 | |
| 272 if(defined $feature_class){ | |
| 273 | |
| 274 if(exists $adaptors{lc($feature_class)}){ | |
| 275 @fclasses = (lc($feature_class)); | |
| 276 } | |
| 277 else{ | |
| 278 throw("The feature class you specified is not valid:\t$feature_class\n". | |
| 279 "Please use one of:\t".join(', ', keys %adaptors)); | |
| 280 } | |
| 281 } | |
| 282 else{ | |
| 283 @fclasses = keys %adaptors; | |
| 284 } | |
| 285 | |
| 286 foreach my $fclass(@fclasses){ | |
| 287 #Now structured as hash to facilitate faster has_attribute method | |
| 288 #Very little difference to array based cache | |
| 289 | |
| 290 my @attr_dbIDs = keys %{$self->{'attribute_cache'}{$fclass}}; | |
| 291 | |
| 292 | |
| 293 if(scalar(@attr_dbIDs) > 0){ | |
| 294 | |
| 295 if( ! ( ref($self->{'regulatory_attributes'}{$fclass}->[0]) && | |
| 296 ref($self->{'regulatory_attributes'}{$fclass}->[0])->isa('Bio::EnsEMBL::Feature') )){ | |
| 297 | |
| 298 $adaptors{$fclass}->force_reslice(1);#So we don't lose attrs which aren't on the slice | |
| 299 $self->{'regulatory_attributes'}{$fclass} = $adaptors{$fclass}->fetch_all_by_dbID_list(\@attr_dbIDs, $self->slice); | |
| 300 | |
| 301 #Having problems here if we are trying to project between Y PAR and X | |
| 302 #Current dest_slice mapping code simply changes the start end values assuming the slice is correct | |
| 303 #currently no test for seq_region name match | |
| 304 | |
| 305 | |
| 306 #foreach my $attr(@{ $self->{'regulatory_attributes'}{$fclass}}){ | |
| 307 # warn "$attr ".$attr->dbID." ".$attr->feature_Slice->name."\n"; | |
| 308 #} | |
| 309 | |
| 310 | |
| 311 $adaptors{$fclass}->force_reslice(0); | |
| 312 | |
| 313 #Problems here with attrs not being returning when they do not lie on dest slice | |
| 314 #i.e. core projected to cell line, but dest slice only over laps a region of the core which | |
| 315 #actually has no attrs. | |
| 316 #either use the feature_Slice and reslice everthing to the dest slice | |
| 317 #or skip test in attr obj_frm_sth? | |
| 318 # | |
| 319 | |
| 320 #This method transfers to the query slice, do not use fetch_by_dbID | |
| 321 #It also should use _final_clause | |
| 322 #This is currently only specified in the MotifFeatureAdaptor | |
| 323 #as these are required to be sorted to relate to the structure string | |
| 324 | |
| 325 #but we are stll storing in has where order is not preserved!! | |
| 326 #so this will not match order of underlying strcture! | |
| 327 | |
| 328 #separate so we can have ordered array returned | |
| 329 #do we need redundant caches? | |
| 330 #defo need db id cache for 'has' methods | |
| 331 | |
| 332 #foreach my $attr(@{$fclass_attrs}){ | |
| 333 # $self->{'regulatory_attributes'}{$fclass}{$attr->dbID} = $attr; | |
| 334 #} | |
| 335 } | |
| 336 } | |
| 337 else{ | |
| 338 $self->{'regulatory_attributes'}{$fclass} = []; | |
| 339 } | |
| 340 } | |
| 341 | |
| 342 return [ map { @{$self->{'regulatory_attributes'}{$_}} } @fclasses ]; | |
| 343 } | |
| 344 | |
| 345 =head2 has_attribute | |
| 346 | |
| 347 Arg [1] : Attribute Feature dbID | |
| 348 Arg [2] : Attribute Feature class e.g. motif or annotated | |
| 349 Example : if($regf->has_attribute($af->dbID, 'annotated'){ #do something here } | |
| 350 Description: Identifies whether this RegualtoryFeature has a given attribute | |
| 351 Returntype : Boolean | |
| 352 Exceptions : Throws if args are not defined | |
| 353 Caller : General | |
| 354 Status : Stable | |
| 355 | |
| 356 =cut | |
| 357 | |
| 358 | |
| 359 sub has_attribute{ | |
| 360 my ($self, $dbID, $fclass) = @_; | |
| 361 | |
| 362 throw('Must provide a dbID and a Feature class argument') if ! $dbID && $fclass; | |
| 363 | |
| 364 return exists ${$self->attribute_cache}{$fclass}{$dbID}; | |
| 365 } | |
| 366 | |
| 367 =head2 get_focus_attributes | |
| 368 | |
| 369 Arg [1] : None | |
| 370 Example : my @focus_attrs = @{$regf->get_focus_attributes}; | |
| 371 Description: Getter for the focus features of this RegualtoryFeature, used to defined the core region | |
| 372 Returntype : ARRAYREF | |
| 373 Exceptions : None | |
| 374 Caller : General | |
| 375 Status : Stable | |
| 376 | |
| 377 =cut | |
| 378 | |
| 379 sub get_focus_attributes{ | |
| 380 my $self = shift; | |
| 381 | |
| 382 if(! exists $self->{'focus_attributes'} || | |
| 383 ! @{$self->{'focus_attributes'}}){ | |
| 384 $self->_sort_attributes; | |
| 385 } | |
| 386 | |
| 387 | |
| 388 return $self->{'focus_attributes'}; | |
| 389 } | |
| 390 | |
| 391 | |
| 392 =head2 get_nonfocus_attributes | |
| 393 | |
| 394 Arg [1] : None | |
| 395 Example : my @non_focus_attrs = @{$regf->get_nonfocus_attributes}; | |
| 396 Description: Getter for the non-focus features of this RegulatoryFeature, used to defined | |
| 397 the non core region i.e. the whiskers. | |
| 398 Returntype : ARRAYREF | |
| 399 Exceptions : None | |
| 400 Caller : General | |
| 401 Status : Stable | |
| 402 | |
| 403 =cut | |
| 404 | |
| 405 sub get_nonfocus_attributes{ | |
| 406 my $self = shift; | |
| 407 | |
| 408 #Test focus here as we may not have any nonfocus | |
| 409 #But focus will show that we have sorted already | |
| 410 if(! exists $self->{'focus_attributes'} || | |
| 411 ! @{$self->{'focus_attributes'}}){ | |
| 412 $self->_sort_attributes; | |
| 413 } | |
| 414 | |
| 415 return $self->{'nonfocus_attributes'}; | |
| 416 } | |
| 417 | |
| 418 #Add pod here | |
| 419 | |
| 420 sub _sort_attributes{ | |
| 421 my $self = shift; | |
| 422 | |
| 423 $self->{'focus_attributes'} = []; | |
| 424 $self->{'nonfocus_attributes'} = []; | |
| 425 | |
| 426 foreach my $attrf(@{$self->regulatory_attributes}){ | |
| 427 | |
| 428 if($attrf->isa('Bio::EnsEMBL::Funcgen::MotifFeature') || | |
| 429 $attrf->feature_set->is_focus_set){ | |
| 430 push @{$self->{'focus_attributes'}}, $attrf; | |
| 431 } | |
| 432 else{ | |
| 433 push @{$self->{'nonfocus_attributes'}}, $attrf; | |
| 434 } | |
| 435 } | |
| 436 | |
| 437 return; | |
| 438 } | |
| 439 | |
| 440 | |
| 441 =head2 attribute_cache | |
| 442 | |
| 443 Arg [1] : optional - HASHREF of attribute table keys with values as either a list of attribute | |
| 444 feature dbIDs or objects. If passing object, any MotifFeature objects should be in position | |
| 445 order with respect to the slice. | |
| 446 Example : $feature->attribute_cache(\%attribute_feature_info); | |
| 447 Description: Setter for the regulatory_attribute cache for this feature. This is a short cut method used by the | |
| 448 regulatory build and the webcode to avoid unnecessary fetching and enable enable lazy loading | |
| 449 Returntype : HASHREF | |
| 450 Exceptions : Throws if trying to overwrite existing cache | |
| 451 Caller : RegulatoryFeatureAdaptor.pm and build_regulatory_features.pl | |
| 452 Status : At Risk | |
| 453 | |
| 454 =cut | |
| 455 | |
| 456 | |
| 457 sub attribute_cache{ | |
| 458 my ($self, $attr_hash) = @_; | |
| 459 | |
| 460 # if(! defined $attr_hash){ | |
| 461 # $self->regulatory_attributes; #Fetch the attrs? | |
| 462 # | |
| 463 # | |
| 464 # #Do we need to do this now we have separated the caches? | |
| 465 # | |
| 466 # } | |
| 467 | |
| 468 if(defined $attr_hash){ | |
| 469 | |
| 470 foreach my $fclass(keys %{$attr_hash}){ | |
| 471 | |
| 472 if(exists $self->{'attribute_cache'}{$fclass}){ | |
| 473 throw("You are trying to overwrite a pre-existing regulatory attribute cache entry for feature class:\t$fclass"); | |
| 474 } | |
| 475 else{ | |
| 476 $self->{'attribute_cache'}{$fclass} = $attr_hash->{$fclass}; | |
| 477 } | |
| 478 } | |
| 479 } | |
| 480 | |
| 481 return $self->{'attribute_cache'} || {}; | |
| 482 } | |
| 483 | |
| 484 | |
| 485 =head2 bound_start | |
| 486 | |
| 487 Example : my $bound_start = $feature->bound_start(); | |
| 488 Description: Getter for the bound_start attribute for this feature. | |
| 489 Gives the 5' most start value of the underlying attribute | |
| 490 features. | |
| 491 Returntype : string | |
| 492 Exceptions : None | |
| 493 Caller : General | |
| 494 Status : Stable | |
| 495 | |
| 496 =cut | |
| 497 | |
| 498 sub bound_start { | |
| 499 my $self = shift; | |
| 500 $self->get_underlying_structure if ! defined $self->{'bound_start'}; | |
| 501 | |
| 502 return $self->{'bound_start'}; | |
| 503 } | |
| 504 | |
| 505 | |
| 506 =head2 bound_end | |
| 507 | |
| 508 Example : my $bound_end = $feature->bound_start(); | |
| 509 Description: Getter for the bound_end attribute for this feature. | |
| 510 Gives the 3' most end value of the underlying attribute | |
| 511 features. | |
| 512 Returntype : string | |
| 513 Exceptions : None | |
| 514 Caller : General | |
| 515 Status : Stable | |
| 516 | |
| 517 =cut | |
| 518 | |
| 519 sub bound_end { | |
| 520 my $self = shift; | |
| 521 $self->get_underlying_structure if ! defined $self->{'bound_end'}; | |
| 522 | |
| 523 return $self->{'bound_end'}; | |
| 524 } | |
| 525 | |
| 526 | |
| 527 =head2 bound_seq_region_start | |
| 528 | |
| 529 Example : my $bound_sr_start = $feature->bound_seq_region_start; | |
| 530 Description: Getter for the seq_region bound_start attribute for this feature. | |
| 531 Gives the 5' most start value of the underlying attribute | |
| 532 features. | |
| 533 Returntype : string | |
| 534 Exceptions : None | |
| 535 Caller : General | |
| 536 Status : Stable | |
| 537 | |
| 538 =cut | |
| 539 | |
| 540 sub bound_seq_region_start { | |
| 541 my $self = shift; | |
| 542 | |
| 543 if(! defined $self->{bound_seq_region_start}){ | |
| 544 | |
| 545 if($self->slice->strand == 1){ | |
| 546 $self->{bound_seq_region_start} = $self->slice->start + $self->bound_start - 1; | |
| 547 } | |
| 548 else{ #strand = -1 | |
| 549 $self->{bound_seq_region_start} = $self->slice->end - $self->bound_end + 1; | |
| 550 } | |
| 551 } | |
| 552 | |
| 553 return $self->{bound_seq_region_start}; | |
| 554 } | |
| 555 | |
| 556 | |
| 557 =head2 bound_seq_region_end | |
| 558 | |
| 559 Example : my $bound_sr_end = $feature->bound_seq_region_end; | |
| 560 Description: Getter for the seq_region bound_end attribute for this feature. | |
| 561 Gives the 3' most end value of the underlying attribute | |
| 562 features. | |
| 563 Returntype : string | |
| 564 Exceptions : None | |
| 565 Caller : General | |
| 566 Status : Stable | |
| 567 | |
| 568 =cut | |
| 569 | |
| 570 | |
| 571 sub bound_seq_region_end { | |
| 572 my $self = shift; | |
| 573 | |
| 574 if(! defined $self->{bound_seq_region_end}){ | |
| 575 | |
| 576 if($self->slice->strand == 1){ | |
| 577 $self->{bound_seq_region_end} = $self->slice->start + $self->bound_end - 1; | |
| 578 } | |
| 579 else{ #strand = -1 | |
| 580 $self->{bound_seq_region_end} = $self->slice->end - $self->bound_start + 1; | |
| 581 } | |
| 582 } | |
| 583 | |
| 584 return $self->{bound_seq_region_end}; | |
| 585 } | |
| 586 | |
| 587 | |
| 588 | |
| 589 | |
| 590 | |
| 591 | |
| 592 =head2 is_projected | |
| 593 | |
| 594 Arg [1] : optional - boolean | |
| 595 Example : if($regf->is_projected){ #do something different here } | |
| 596 Description: Getter/Setter for the projected attribute. | |
| 597 Returntype : boolean | |
| 598 Exceptions : None | |
| 599 Caller : General | |
| 600 Status : At risk - remove setter functionality | |
| 601 | |
| 602 =cut | |
| 603 | |
| 604 sub is_projected { | |
| 605 my $self = shift; | |
| 606 | |
| 607 if(@_){ | |
| 608 #added v67 | |
| 609 warn "RegulatoryFeature::is_projected setter functionality is being removed\n"; | |
| 610 $self->{'projected'} = shift; | |
| 611 } | |
| 612 | |
| 613 return $self->{'projected'}; | |
| 614 } | |
| 615 | |
| 616 | |
| 617 =head2 get_underlying_structure | |
| 618 | |
| 619 Example : $self->get_underlying_structure() if(! exists $self->{'bound_end'}); | |
| 620 Description: Getter for the bound_end attribute for this feature. | |
| 621 Gives the 3' most end value of the underlying attribute | |
| 622 features. | |
| 623 Returntype : string | |
| 624 Exceptions : None | |
| 625 Caller : General | |
| 626 Status : At Risk | |
| 627 | |
| 628 =cut | |
| 629 | |
| 630 #This should really be precomputed and stored in the DB to avoid the MF attr fetch | |
| 631 #Need to be aware of projecting here, as these will expire if we project after this method is called | |
| 632 | |
| 633 sub get_underlying_structure{ | |
| 634 my $self = shift; | |
| 635 | |
| 636 if(! defined $self->{underlying_structure}){ | |
| 637 | |
| 638 my @attrs = @{$self->regulatory_attributes()}; | |
| 639 | |
| 640 if(! @attrs){ | |
| 641 throw('No underlying regulatory_attribute features to get_underlying_structure for dbID '.$self->dbID); | |
| 642 #This should never happen even with a projection build | |
| 643 } | |
| 644 else{ | |
| 645 | |
| 646 | |
| 647 #We only need to set the bounds when storing on full slice/seq_region values | |
| 648 #else they should be fetched from the DB | |
| 649 | |
| 650 if(! defined $self->{'bound_start'}){ | |
| 651 | |
| 652 my (@start_ends); | |
| 653 | |
| 654 foreach my $attr(@attrs){ | |
| 655 push @start_ends, ($attr->start, $attr->end); | |
| 656 } | |
| 657 | |
| 658 #Accounts for core region, where data may be absent on this cell type | |
| 659 push @start_ends, ($self->start, $self->end); | |
| 660 | |
| 661 @start_ends = sort { $a <=> $b } @start_ends; | |
| 662 | |
| 663 $self->{'bound_end'} = pop @start_ends; | |
| 664 $self->{'bound_start'} = shift @start_ends; | |
| 665 | |
| 666 #Need to account for projection build here | |
| 667 #i.e. attr extremeties may not extend past core start/end | |
| 668 | |
| 669 if($self->is_projected){ | |
| 670 $self->{'bound_end'} = $self->end if $self->end > $self->{'bound_end'}; | |
| 671 $self->{'bound_start'} = $self->start if $self->start < $self->{'bound_start'}; | |
| 672 } | |
| 673 } | |
| 674 | |
| 675 #Now deal with MotifFeature loci | |
| 676 my @mf_loci; | |
| 677 | |
| 678 foreach my $mf(@{$self->regulatory_attributes('motif')}){ | |
| 679 push @mf_loci, ($mf->start, $mf->end); | |
| 680 } | |
| 681 | |
| 682 $self->{underlying_structure} = [$self->{'bound_start'}, $self->start, @mf_loci, $self->end, $self->{'bound_end'}]; | |
| 683 } | |
| 684 } | |
| 685 | |
| 686 return $self->{underlying_structure}; | |
| 687 } | |
| 688 | |
| 689 | |
| 690 =head2 is_unique_to_FeatureSets | |
| 691 | |
| 692 Arg[1] : optional - ARRAYREF of regualtory Bio::EnsEMBL::Funcgen::FeatureSet objects | |
| 693 Default is FeatureSet of given RegulatoryFeature, else need to be | |
| 694 defined explicitly. | |
| 695 Arg[2] : optional - HASHREF Params hash: | |
| 696 { | |
| 697 include_projected => 0|1, # Boolean, include 'projected' features | |
| 698 } | |
| 699 Example : if($reg_feat->is_unique_to_FeatureSets($fsets)}{ | |
| 700 #then do some analysis here | |
| 701 } | |
| 702 Description: Identifies whether this RegualtoryFeature is unique to a set of FeatureSets. | |
| 703 Returntype : boolean | |
| 704 Exceptions : Throw is arguments not stored or valid. | |
| 705 Caller : General | |
| 706 Status : At risk | |
| 707 | |
| 708 =cut | |
| 709 | |
| 710 #Probably want to add in an FeatureType constraint here | |
| 711 #e.g. so we can compare active vs inactive or poised promoters | |
| 712 | |
| 713 #omit include_multi doesn't make sense here | |
| 714 | |
| 715 sub is_unique_to_FeatureSets{ | |
| 716 my ($self, $fsets, $params_hash) = @_; | |
| 717 | |
| 718 $fsets ||= [$self->feature_set]; | |
| 719 my @fset_ids; | |
| 720 | |
| 721 | |
| 722 #define to avoid deref fails below. | |
| 723 $params_hash ||= {}; | |
| 724 if(ref($params_hash) ne 'HASH'){ | |
| 725 throw("The params hash argument must be a valid HASHREF:\t".ref($params_hash)); | |
| 726 } | |
| 727 | |
| 728 | |
| 729 foreach my $fset(@$fsets){ | |
| 730 #assume we have an adaptor set | |
| 731 $self->adaptor->db->is_stored_and_valid('Bio::EnsEMBL::Funcgen::FeatureSet', $fset); | |
| 732 | |
| 733 if($fset->feature_class ne 'regulatory'){ | |
| 734 throw('Found non-regulatory FeatureSet'); | |
| 735 } | |
| 736 | |
| 737 push @fset_ids, $fset->dbID; | |
| 738 } | |
| 739 | |
| 740 my $stable_id; | |
| 741 ($stable_id = $self->stable_id) =~ s/^[A-Z0]+//; | |
| 742 | |
| 743 | |
| 744 my @other_rf_ids = @{$self->adaptor->_fetch_other_dbIDs_by_stable_feature_set_ids | |
| 745 ($stable_id, | |
| 746 \@fset_ids, | |
| 747 { include_projected => $params_hash->{include_projected}} )}; | |
| 748 | |
| 749 return (@other_rf_ids) ? 0 : 1; | |
| 750 } | |
| 751 | |
| 752 | |
| 753 | |
| 754 =head2 get_other_RegulatoryFeatures | |
| 755 | |
| 756 Arg[1] : optional - ARRAYREF of regualtory Bio::EnsEMBL::Funcgen::FeatureSet objects | |
| 757 Default is FeatureSet of given RegulatoryFeature, else need to be | |
| 758 defined explicitly. | |
| 759 Arg[2] : optional - HASHREF Params hash: | |
| 760 { | |
| 761 include_projected => 0|1, # Boolean, include 'projected' features | |
| 762 include_multicell => 0|1, # Boolean, include MultiCell features | |
| 763 } | |
| 764 Example : my @other_fsets = @{$reg_feat->get_other_FeatureSets($fsets)}; | |
| 765 Description: Gets other RegualtoryFeatures (linked via the stable ID) which are present in the | |
| 766 specified list of FeatureSets. | |
| 767 Returntype : ARRAYREF of Bio::EnsEMBL::Funcgen::RegulatoryFeature objects | |
| 768 Exceptions : Throw is arguments not stored or valid. | |
| 769 Caller : General | |
| 770 Status : At risk | |
| 771 | |
| 772 =cut | |
| 773 | |
| 774 sub get_other_RegulatoryFeatures{ | |
| 775 my ($self, $fsets, $params_hash) = @_; | |
| 776 | |
| 777 #define to avoid deref fails below. | |
| 778 $params_hash ||= {}; | |
| 779 if(ref($params_hash) ne 'HASH'){ | |
| 780 throw("The params hash argument must be a valid HASHREF:\t".ref($params_hash)); | |
| 781 } | |
| 782 | |
| 783 $fsets ||= [$self->feature_set]; | |
| 784 my @fset_ids; | |
| 785 | |
| 786 foreach my $fset(@$fsets){ | |
| 787 #assume we have an adaptor set | |
| 788 $self->adaptor->db->is_stored_and_valid('Bio::EnsEMBL::Funcgen::FeatureSet', $fset); | |
| 789 | |
| 790 if($fset->feature_class ne 'regulatory'){ | |
| 791 throw('Found non-regulatory FeatureSet'); | |
| 792 } | |
| 793 | |
| 794 push @fset_ids, $fset->dbID; | |
| 795 } | |
| 796 | |
| 797 my $stable_id; | |
| 798 ($stable_id = $self->stable_id) =~ s/^[A-Z0]+//; | |
| 799 | |
| 800 my @other_fsets_ids = @{$self->adaptor->_fetch_other_dbIDs_by_stable_feature_set_ids | |
| 801 ($stable_id, \@fset_ids, | |
| 802 { | |
| 803 include_projected => $params_hash->{include_projected}, | |
| 804 include_multicell => $params_hash->{include_multicell}, | |
| 805 })}; | |
| 806 | |
| 807 return $self->adaptor->fetch_all_by_dbID_list(\@other_fsets_ids); | |
| 808 } | |
| 809 | |
| 810 | |
| 811 | |
| 812 1; | |
| 813 | |
| 814 __END__ |
