sync w/ main trunk
[bioperl-live.git] / Bio / SeqFeature / Computation.pm
blob6c94b0a1fbe3b2e1da1b6d7f58d6e75c49b75837
1 # $Id$
3 # BioPerl module for Bio::SeqFeature::Generic
5 # Please direct questions and support issues to <bioperl-l@bioperl.org>
7 # Cared for by mark Fiers <m.w.e.j.fiers@plant.wag-ur.nl>
9 # Copyright Ewan Birney, Mark Fiers
11 # You may distribute this module under the same terms as perl itself
13 # POD documentation - main docs before the code
15 =head1 NAME
17 Bio::SeqFeature::Computation - Computation SeqFeature
19 =head1 SYNOPSIS
21 $feat = Bio::SeqFeature::Computation->new(
22 -start => 10, -end => 100,
23 -strand => -1, -primary => 'repeat',
24 -program_name => 'GeneMark',
25 -program_date => '12-5-2000',
26 -program_version => 'x.y',
27 -database_name => 'Arabidopsis',
28 -database_date => '12-dec-2000',
29 -computation_id => 2231,
30 -score => { no_score => 334 } );
33 =head1 DESCRIPTION
35 Bio::SeqFeature::Computation extends the Generic seqfeature object with
36 a set of computation related fields and a more flexible set of storing
37 more types of score and subseqfeatures. It is compatible with the Generic
38 SeqFeature object.
40 The new way of storing score values is similar to the tag structure in the
41 Generic object. For storing sets of subseqfeatures the array containg the
42 subseqfeatures is now a hash which contains arrays of seqfeatures
43 Both the score and subSeqfeature methods can be called in exactly the same
44 way, the value's will be stored as a 'default' score or subseqfeature.
46 =cut
50 =head1 FEEDBACK
52 =head2 Mailing Lists
54 User feedback is an integral part of the evolution of this and other
55 Bioperl modules. Send your comments and suggestions preferably to one
56 of the Bioperl mailing lists. Your participation is much appreciated.
58 bioperl-l@bioperl.org - General discussion
59 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
61 =head2 Support
63 Please direct usage questions or support issues to the mailing list:
65 L<bioperl-l@bioperl.org>
67 rather than to the module maintainer directly. Many experienced and
68 reponsive experts will be able look at the problem and quickly
69 address it. Please include a thorough description of the problem
70 with code and data examples if at all possible.
72 =head2 Reporting Bugs
74 Report bugs to the Bioperl bug tracking system to help us keep track
75 the bugs and their resolution. Bug reports can be submitted via the
76 web:
78 http://bugzilla.open-bio.org/
80 =head1 AUTHOR - Ewan Birney, Mark Fiers
82 Ewan Birney E<lt>birney@sanger.ac.ukE<gt>
83 Mark Fiers E<lt>m.w.e.j.fiers@plant.wag-ur.nlE<gt>
85 =head1 DEVELOPERS
87 This class has been written with an eye out of inheritance. The fields
88 the actual object hash are:
90 _gsf_sub_hash = reference to a hash containing sets of sub arrays
91 _gsf_score_hash= reference to a hash for the score values
93 =head1 APPENDIX
95 The rest of the documentation details each of the object
96 methods. Internal methods are usually preceded with a _
98 =cut
100 # Let the code begin...
102 package Bio::SeqFeature::Computation;
103 use strict;
105 use base qw(Bio::SeqFeature::Generic);
107 sub new {
108 my ( $class, @args) = @_;
110 my $self = $class->SUPER::new(@args);
113 my ( $computation_id,
114 $program_name, $program_date, $program_version,
115 $database_name, $database_date, $database_version) =
116 $self->_rearrange([qw(COMPUTATION_ID
117 PROGRAM_NAME
118 PROGRAM_DATE
119 PROGRAM_VERSION
120 DATABASE_NAME
121 DATABASE_DATE
122 DATABASE_VERSION
123 )],@args);
125 $program_name && $self->program_name($program_name);
126 $program_date && $self->program_date($program_date);
127 $program_version && $self->program_version($program_version);
128 $database_name && $self->database_name($database_name);
129 $database_date && $self->database_date($database_date);
130 $database_version && $self->database_version($database_version);
131 $computation_id && $self->computation_id($computation_id);
133 return $self;
136 =head2 has_score
138 Title : has_score
139 Usage : $value = $self->has_score('some_score')
140 Function: Tests wether a feature contains a score
141 Returns : TRUE if the SeqFeature has the score,
142 and FALSE otherwise.
143 Args : The name of a score
145 =cut
147 sub has_score {
148 my ($self, $score) = @_;
149 return unless defined $score;
150 return exists $self->{'_gsf_score_hash'}->{$score};
153 =head2 add_score_value
155 Title : add_score_value
156 Usage : $self->add_score_value('P_value',224);
157 Returns : TRUE on success
158 Args : score (string) and value (any scalar)
160 =cut
162 sub add_score_value {
163 my ($self, $score, $value) = @_;
164 if( ! defined $score || ! defined $value ) {
165 $self->warn("must specify a valid $score and $value to add_score_value");
166 return 0;
169 if ( !defined $self->{'_gsf_score_hash'}->{$score} ) {
170 $self->{'_gsf_score_hash'}->{$score} = [];
173 push(@{$self->{'_gsf_score_hash'}->{$score}},$value);
176 =head2 score
178 Title : score
179 Usage : $value = $comp_obj->score()
180 $comp_obj->score($value)
181 Function: Returns the 'default' score or sets the 'default' score
182 This method exist for compatibility options
183 It would equal ($comp_obj->each_score_value('default'))[0];
184 Returns : A value
185 Args : (optional) a new value for the 'default' score
187 =cut
189 sub score {
190 my ($self, $value) = @_;
191 my @v;
192 if (defined $value) {
194 if( ref($value) =~ /HASH/i ) {
195 while( my ($t,$val) = each %{ $value } ) {
196 $self->add_score_value($t,$val);
198 } else {
199 @v = $value;
200 $self->add_score_value('default', $value);
203 } else {
204 @v = $self->each_score_value('default');
206 return $v[0];
209 =head2 each_score_value
211 Title : each_score_value
212 Usage : @values = $gsf->each_score_value('note');
213 Function: Returns a list of all the values stored
214 under a particular score.
215 Returns : A list of scalars
216 Args : The name of the score
218 =cut
220 sub each_score_value {
221 my ($self, $score) = @_;
222 if ( ! exists $self->{'_gsf_score_hash'}->{$score} ) {
223 $self->warn("asking for score value that does not exist $score");
224 return;
226 return @{$self->{'_gsf_score_hash'}->{$score}};
230 =head2 all_scores
232 Title : all_scores
233 Usage : @scores = $feat->all_scores()
234 Function: Get a list of all the scores in a feature
235 Returns : An array of score names
236 Args : none
239 =cut
241 sub all_scores {
242 my ($self, @args) = @_;
244 return keys %{$self->{'_gsf_score_hash'}};
248 =head2 remove_score
250 Title : remove_score
251 Usage : $feat->remove_score('some_score')
252 Function: removes a score from this feature
253 Returns : nothing
254 Args : score (string)
257 =cut
259 sub remove_score {
260 my ($self, $score) = @_;
262 if ( ! exists $self->{'_gsf_score_hash'}->{$score} ) {
263 $self->warn("trying to remove a score that does not exist: $score");
266 delete $self->{'_gsf_score_hash'}->{$score};
269 =head2 computation_id
271 Title : computation_id
272 Usage : $computation_id = $feat->computation_id()
273 $feat->computation_id($computation_id)
274 Function: get/set on program name information
275 Returns : string
276 Args : none if get, the new value if set
279 =cut
281 sub computation_id {
282 my ($self,$value) = @_;
284 if (defined($value)) {
285 $self->{'_gsf_computation_id'} = $value;
288 return $self->{'_gsf_computation_id'};
294 =head2 program_name
296 Title : program_name
297 Usage : $program_name = $feat->program_name()
298 $feat->program_name($program_name)
299 Function: get/set on program name information
300 Returns : string
301 Args : none if get, the new value if set
304 =cut
306 sub program_name {
307 my ($self,$value) = @_;
309 if (defined($value)) {
310 $self->{'_gsf_program_name'} = $value;
313 return $self->{'_gsf_program_name'};
316 =head2 program_date
318 Title : program_date
319 Usage : $program_date = $feat->program_date()
320 $feat->program_date($program_date)
321 Function: get/set on program date information
322 Returns : date (string)
323 Args : none if get, the new value if set
326 =cut
328 sub program_date {
329 my ($self,$value) = @_;
331 if (defined($value)) {
332 $self->{'_gsf_program_date'} = $value;
335 return $self->{'_gsf_program_date'};
339 =head2 program_version
341 Title : program_version
342 Usage : $program_version = $feat->program_version()
343 $feat->program_version($program_version)
344 Function: get/set on program version information
345 Returns : date (string)
346 Args : none if get, the new value if set
349 =cut
351 sub program_version {
352 my ($self,$value) = @_;
354 if (defined($value)) {
355 $self->{'_gsf_program_version'} = $value;
358 return $self->{'_gsf_program_version'};
361 =head2 database_name
363 Title : database_name
364 Usage : $database_name = $feat->database_name()
365 $feat->database_name($database_name)
366 Function: get/set on program name information
367 Returns : string
368 Args : none if get, the new value if set
370 =cut
372 sub database_name {
373 my ($self,$value) = @_;
375 if (defined($value)) {
376 $self->{'_gsf_database_name'} = $value;
379 return $self->{'_gsf_database_name'};
382 =head2 database_date
384 Title : database_date
385 Usage : $database_date = $feat->database_date()
386 $feat->database_date($database_date)
387 Function: get/set on program date information
388 Returns : date (string)
389 Args : none if get, the new value if set
392 =cut
394 sub database_date {
395 my ($self,$value) = @_;
397 if (defined($value)) {
398 $self->{'_gsf_database_date'} = $value;
401 return $self->{'_gsf_database_date'};
405 =head2 database_version
407 Title : database_version
408 Usage : $database_version = $feat->database_version()
409 $feat->database_version($database_version)
410 Function: get/set on program version information
411 Returns : date (string)
412 Args : none if get, the new value if set
415 =cut
417 sub database_version {
418 my ($self,$value) = @_;
420 if (defined($value)) {
421 $self->{'_gsf_database_version'} = $value;
424 return $self->{'_gsf_database_version'};
428 =head2 sub_SeqFeature_type
430 Title : sub_SeqFeature_type
431 Usage : $sub_SeqFeature_type = $feat->sub_SeqFeature_type()
432 $feat->sub_SeqFeature_type($sub_SeqFeature_type)
433 Function: sub_SeqFeature_type is automatically set when adding
434 a sub_computation (sub_SeqFeature) to a computation object
435 Returns : sub_SeqFeature_type (string)
436 Args : none if get, the new value if set
438 =cut
440 sub sub_SeqFeature_type {
441 my ($self, $value) = @_;
443 if (defined($value)) {
444 $self->{'_gsf_sub_SeqFeature_type'} = $value;
446 return $self->{'_gsf_sub_SeqFeature_type'};
449 =head2 all_sub_SeqFeature_types
451 Title : all_Sub_SeqFeature_types
452 Usage : @all_sub_seqfeature_types = $comp->all_Sub_SeqFeature_types();
453 Function: Returns an array with all subseqfeature types
454 Returns : An array
455 Args : none
457 =cut
459 sub all_sub_SeqFeature_types {
460 my ($self) = @_;
461 return keys ( %{$self->{'gsf_sub_hash'}} );
464 =head2 sub_SeqFeature
466 Title : sub_SeqFeature('sub_feature_type')
467 Usage : @feats = $feat->sub_SeqFeature();
468 @feats = $feat->sub_SeqFeature('sub_feature_type');
469 Function: Returns an array of sub Sequence Features of a specific
470 type or, if the type is ommited, all sub Sequence Features
471 Returns : An array
472 Args : (optional) a sub_SeqFeature type (ie exon, pattern)
474 =cut
476 sub sub_SeqFeature {
477 my ($self, $ssf_type) = @_;
478 my (@return_array) = ();
479 if ($ssf_type eq '') {
480 #return all sub_SeqFeatures
481 foreach (keys ( %{$self->{'gsf_sub_hash'}} )){
482 push @return_array, @{$self->{'gsf_sub_hash'}->{$_}};
484 return @return_array;
485 } else {
486 if (defined ($self->{'gsf_sub_hash'}->{$ssf_type})) {
487 return @{$self->{'gsf_sub_hash'}->{$ssf_type}};
488 } else {
489 $self->warn("$ssf_type is not a valid sub SeqFeature type");
494 =head2 add_sub_SeqFeature
496 Title : add_sub_SeqFeature
497 Usage : $feat->add_sub_SeqFeature($subfeat);
498 $feat->add_sub_SeqFeature($subfeat,'sub_seqfeature_type')
499 $feat->add_sub_SeqFeature($subfeat,'EXPAND')
500 $feat->add_sub_SeqFeature($subfeat,'EXPAND','sub_seqfeature_type')
501 Function: adds a SeqFeature into a specific subSeqFeature array.
502 with no 'EXPAND' qualifer, subfeat will be tested
503 as to whether it lies inside the parent, and throw
504 an exception if not.
505 If EXPAND is used, the parents start/end/strand will
506 be adjusted so that it grows to accommodate the new
507 subFeature,
508 optionally a sub_seqfeature type can be defined.
509 Returns : nothing
510 Args : An object which has the SeqFeatureI interface
511 : (optional) 'EXPAND'
512 : (optional) 'sub_SeqFeature_type'
514 =cut
516 sub add_sub_SeqFeature{
517 my ($self,$feat,$var1, $var2) = @_;
518 $var1 = '' unless( defined $var1);
519 $var2 = '' unless( defined $var2);
520 my ($expand, $ssf_type) = ('', $var1 . $var2);
521 $expand = 'EXPAND' if ($ssf_type =~ s/EXPAND//);
523 if ( !$feat->isa('Bio::SeqFeatureI') ) {
524 $self->warn("$feat does not implement Bio::SeqFeatureI. Will add it anyway, but beware...");
527 if($expand eq 'EXPAND') {
528 $self->_expand_region($feat);
529 } else {
530 if ( !$self->contains($feat) ) {
531 $self->throw("$feat is not contained within parent feature, and expansion is not valid");
535 $ssf_type = 'default' if ($ssf_type eq '');
537 if (!(defined ($self->{'gsf_sub_hash'}->{$ssf_type}))) {
538 @{$self->{'gsf_sub_hash'}->{$ssf_type}} = ();
540 $feat->sub_SeqFeature_type($ssf_type);
541 push @{$self->{'gsf_sub_hash'}->{$ssf_type}}, $feat;
544 =head2 flush_sub_SeqFeature
546 Title : flush_sub_SeqFeature
547 Usage : $sf->flush_sub_SeqFeature
548 $sf->flush_sub_SeqFeature('sub_SeqFeature_type');
549 Function: Removes all sub SeqFeature or all sub SeqFeatures
550 of a specified type
551 (if you want to remove a more specific subset, take
552 an array of them all, flush them, and add
553 back only the guys you want)
554 Example :
555 Returns : none
556 Args : none
559 =cut
561 sub flush_sub_SeqFeature {
562 my ($self, $ssf_type) = @_;
563 if ($ssf_type) {
564 if ((defined ($self->{'gsf_sub_hash'}->{$ssf_type}))) {
565 delete $self->{'gsf_sub_hash'}->{$ssf_type};
566 } else {
567 $self->warn("$ssf_type is not a valid sub SeqFeature type");
569 } else {
570 $self->{'_gsf_sub_hash'} = {}; # zap the complete hash implicitly.