0
|
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__
|