File Coverage

blib/lib/Bio/Phylo/Matrices/Datum.pm
Criterion Covered Total %
statement 71 111 63.9
branch 16 40 40.0
condition 7 17 41.1
subroutine 17 20 85.0
pod 8 8 100.0
total 119 196 60.7


line stmt bran cond sub pod time code
1             package Bio::Phylo::Matrices::Datum;
2 16     16   125662 use strict;
  16         39  
  16         420  
3 16     16   73 use warnings;
  16         27  
  16         362  
4 16     16   5297 use Bio::Phylo::Matrices::DatumRole;
  16         41  
  16         220  
5 16     16   115 use base qw'Bio::Phylo::Matrices::DatumRole';
  16         36  
  16         1654  
6 16     16   105 use Bio::Phylo::Util::Exceptions 'throw';
  16         33  
  16         762  
7 16     16   94 use Bio::Phylo::Util::CONSTANT qw'/looks_like/';
  16         33  
  16         3997  
8              
9             {
10              
11             my $logger = __PACKAGE__->get_logger;
12             my @fields = \( my ( %weight, %position, %annotations ) );
13              
14             =head1 NAME
15              
16             Bio::Phylo::Matrices::Datum - Character state sequence
17              
18             =head1 SYNOPSIS
19              
20             use Bio::Phylo::Factory;
21             my $fac = Bio::Phylo::Factory->new;
22              
23             # instantiating a datum object...
24             my $datum = $fac->create_datum(
25             -name => 'Tooth comb size,
26             -type => 'STANDARD',
27             -desc => 'number of teeth in lower jaw comb',
28             -pos => 1,
29             -weight => 2,
30             -char => [ 6 ],
31             );
32              
33             # ...and linking it to a taxon object
34             my $taxon = $fac->create_taxon(
35             -name => 'Lemur_catta'
36             );
37             $datum->set_taxon( $taxon );
38              
39             # instantiating a matrix...
40             my $matrix = $fac->create_matrix;
41              
42             # ...and insert datum in matrix
43             $matrix->insert($datum);
44              
45             =head1 DESCRIPTION
46              
47             The datum object models a single observation or a sequence of observations,
48             which can be linked to a taxon object. This package contains the getters
49             and setters that alter the internal state of the datum object. Additional
50             (stateless) behaviours are defined in the L<Bio::Phylo::Matrices::DatumRole>
51             package.
52              
53             =head1 METHODS
54              
55             =head2 MUTATORS
56              
57             =over
58              
59             =item set_weight()
60              
61             Sets invocant weight.
62              
63             Type : Mutator
64             Title : set_weight
65             Usage : $datum->set_weight($weight);
66             Function: Assigns a datum's weight.
67             Returns : Modified object.
68             Args : The $weight argument must be a
69             number in any of Perl's number
70             formats.
71              
72             =cut
73              
74             sub set_weight : Clonable {
75 20     20 1 266 my ( $self, $weight ) = @_;
76 20         42 my $id = $self->get_id;
77 20 100       43 if ( looks_like_number $weight ) {
    100          
78 1         3 $weight{$id} = $weight;
79 1         6 $logger->info("setting weight '$weight'");
80             }
81             elsif ( defined $weight ) {
82 1         8 throw 'BadNumber' => 'Not a number!';
83             }
84             else {
85 18         33 $weight{$id} = undef;
86             }
87 19         41 return $self;
88 16     16   114 }
  16         29  
  16         84  
89              
90             =item set_position()
91              
92             Set invocant starting position.
93              
94             Type : Mutator
95             Title : set_position
96             Usage : $datum->set_position($pos);
97             Function: Assigns a datum's position.
98             Returns : Modified object.
99             Args : $pos must be an integer.
100              
101             =cut
102              
103             sub set_position : Clonable {
104 20     20 1 276 my ( $self, $pos ) = @_;
105 20 100 66     47 if ( looks_like_number $pos && $pos >= 1 && $pos / int($pos) == 1 ) {
    100 66        
106 1         6 $position{ $self->get_id } = $pos;
107 1         10 $logger->info("setting position '$pos'");
108             }
109             elsif ( defined $pos ) {
110 1         7 throw 'BadNumber' => "'$pos' not a positive integer!";
111             }
112             else {
113 18         36 $position{ $self->get_id } = undef;
114             }
115 19         44 return $self;
116 16     16   5545 }
  16         51  
  16         62  
117              
118             =item set_annotation()
119              
120             Sets single annotation.
121              
122             Type : Mutator
123             Title : set_annotation
124             Usage : $datum->set_annotation(
125             -char => 1,
126             -annotation => { -codonpos => 1 }
127             );
128             Function: Assigns an annotation to a
129             character in the datum.
130             Returns : Modified object.
131             Args : Required: -char => $int
132             Optional: -annotation => $hashref
133             Comments: Use this method to annotate
134             a single character. To annotate
135             multiple characters, use
136             'set_annotations' (see below).
137              
138             =cut
139              
140             sub set_annotation {
141 0     0 1 0 my $self = shift;
142 0 0       0 if (@_) {
143 0         0 my %opt = looks_like_hash @_;
144 0 0       0 if ( not exists $opt{'-char'} ) {
145 0         0 throw 'BadArgs' => "No character to annotate specified!";
146             }
147 0         0 my $i = $opt{'-char'};
148 0         0 my $id = $self->get_id;
149 0         0 my $pos = $self->get_position;
150 0         0 my $len = $self->get_length;
151 0 0 0     0 if ( $i > ( $pos + $len ) || $i < $pos ) {
152 0         0 throw 'OutOfBounds' => "Specified char ($i) does not exist!";
153             }
154 0 0       0 if ( exists $opt{'-annotation'} ) {
155 0         0 my $note = $opt{'-annotation'};
156 0 0       0 $annotations{$id}->[$i] = {} if !$annotations{$id}->[$i];
157 0         0 while ( my ( $k, $v ) = each %{$note} ) {
  0         0  
158 0         0 $annotations{$id}->[$i]->{$k} = $v;
159             }
160             }
161             else {
162 0         0 $annotations{$id}->[$i] = undef;
163             }
164             }
165             else {
166 0         0 throw 'BadArgs' => "No character to annotate specified!";
167             }
168 0         0 return $self;
169             }
170              
171             =item set_annotations()
172              
173             Sets list of annotations.
174              
175             Type : Mutator
176             Title : set_annotations
177             Usage : $datum->set_annotations(
178             { '-codonpos' => 1 },
179             { '-codonpos' => 2 },
180             { '-codonpos' => 3 },
181             );
182             Function: Assign annotations to
183             characters in the datum.
184             Returns : Modified object.
185             Args : Hash references, where
186             position in the argument
187             list matches that of the
188             specified characters in
189             the character list. If no
190             argument given, annotations
191             are reset.
192             Comments: Use this method to annotate
193             multiple characters. To
194             annotate a single character,
195             use 'set_annotation' (see
196             above).
197              
198             =cut
199              
200             sub set_annotations : Clonable {
201 1308     1308 1 1782 my $self = shift;
202 1308         1740 my @anno;
203 1308 100 66     3668 if ( scalar @_ == 1 and looks_like_instance( $_[0], 'ARRAY' ) ) {
204 602         803 @anno = @{ $_[0] };
  602         3455  
205             }
206             else {
207 706         1169 @anno = @_;
208             }
209 1308         3229 my $id = $self->get_id;
210 1308 100       2439 if (@anno) {
211 584         1354 my $max_index = $self->get_length - 1;
212 584         1608 for my $i ( 0 .. $#anno ) {
213 82243 50       113864 if ( $i > $max_index ) {
214 0         0 throw 'OutOfBounds' =>
215             "Specified char ($i) does not exist!";
216             }
217             else {
218 82243 50       131555 if ( looks_like_instance( $anno[$i], 'HASH' ) ) {
219             $annotations{$id}->[$i] = {}
220 82243 50       159002 if !$annotations{$id}->[$i];
221 82243         101697 while ( my ( $k, $v ) = each %{ $anno[$i] } ) {
  164486         380748  
222 82243         138377 $annotations{$id}->[$i]->{$k} = $v;
223             }
224             }
225             else {
226 0         0 next;
227             }
228             }
229             }
230             }
231             else {
232 724         1775 $annotations{$id} = [];
233             }
234 16     16   8930 }
  16         37  
  16         77  
235              
236             =back
237              
238             =head2 ACCESSORS
239              
240             =over
241              
242             =item get_weight()
243              
244             Gets invocant weight.
245              
246             Type : Accessor
247             Title : get_weight
248             Usage : my $weight = $datum->get_weight;
249             Function: Retrieves a datum's weight.
250             Returns : FLOAT
251             Args : NONE
252              
253             =cut
254              
255 19     19 1 46 sub get_weight { $weight{ shift->get_id } }
256              
257             =item get_position()
258              
259             Gets invocant starting position.
260              
261             Type : Accessor
262             Title : get_position
263             Usage : my $pos = $datum->get_position;
264             Function: Retrieves a datum's position.
265             Returns : a SCALAR integer.
266             Args : NONE
267              
268             =cut
269              
270 2005     2005 1 3831 sub get_position { $position{ shift->get_id } }
271              
272             =item get_annotation()
273              
274             Retrieves character annotation (hashref).
275              
276             Type : Accessor
277             Title : get_annotation
278             Usage : $datum->get_annotation(
279             '-char' => 1,
280             '-key' => '-codonpos',
281             );
282             Function: Retrieves an annotation to
283             a character in the datum.
284             Returns : SCALAR or HASH
285             Args : Optional: -char => $int
286             Optional: -key => $key
287              
288             =cut
289              
290             sub get_annotation {
291 0     0 1 0 my $self = shift;
292 0         0 my $id = $self->get_id;
293 0 0       0 if (@_) {
294 0         0 my %opt = looks_like_hash @_;
295 0 0       0 if ( not exists $opt{'-char'} ) {
296 0         0 throw 'BadArgs' =>
297             "No character to return annotation for specified!";
298             }
299 0         0 my $i = $opt{'-char'};
300 0         0 my $pos = $self->get_position;
301 0         0 my $len = $self->get_length;
302 0 0 0     0 if ( $i < $pos || $i > ( $pos + $len ) ) {
303 0         0 throw 'OutOfBounds' => "Specified char ($i) does not exist!";
304             }
305 0 0       0 if ( exists $opt{'-key'} ) {
306 0         0 return $annotations{$id}->[$i]->{ $opt{'-key'} };
307             }
308             else {
309 0         0 return $annotations{$id}->[$i];
310             }
311             }
312             else {
313 0         0 return $annotations{$id};
314             }
315             }
316              
317             =item get_annotations()
318              
319             Retrieves character annotations (array ref).
320              
321             Type : Accessor
322             Title : get_annotations
323             Usage : my @anno = @{ $datum->get_annotation() };
324             Function: Retrieves annotations
325             Returns : ARRAY
326             Args : NONE
327              
328             =cut
329              
330             sub get_annotations {
331 618     618 1 2898 my $self = shift;
332 618   50     1413 return $annotations{ $self->get_id } || [];
333             }
334              
335             sub _cleanup : Destructor {
336 724     724   1101 my $self = shift;
337 724         3278 $logger->info("cleaning up '$self'");
338 724 50       1687 if ( defined( my $id = $self->get_id ) ) {
339 724         1394 for my $field (@fields) {
340 2172         14703 delete $field->{$id};
341             }
342             }
343 16     16   7445 }
  16         35  
  16         59  
344            
345             sub _update_characters {
346 0     0     my $self = shift;
347 0 0         if ( my $matrix = $self->get_matrix ) {
348 0           $matrix->_update_characters;
349             }
350             }
351             }
352              
353             =back
354              
355             =cut
356              
357             # podinherit_insert_token
358              
359             =head1 SEE ALSO
360              
361             There is a mailing list at L<https://groups.google.com/forum/#!forum/bio-phylo>
362             for any user or developer questions and discussions.
363              
364             =over
365              
366             =item L<Bio::Phylo::Matrices::DatumRole>
367              
368             This object inherits from L<Bio::Phylo::Matrices::DatumRole>, so the methods
369             defined therein are also applicable to L<Bio::Phylo::Matrices::Datum> objects.
370              
371             =item L<Bio::Phylo::Manual>
372              
373             Also see the manual: L<Bio::Phylo::Manual> and L<http://rutgervos.blogspot.com>.
374              
375             =back
376              
377             =head1 CITATION
378              
379             If you use Bio::Phylo in published research, please cite it:
380              
381             B<Rutger A Vos>, B<Jason Caravas>, B<Klaas Hartmann>, B<Mark A Jensen>
382             and B<Chase Miller>, 2011. Bio::Phylo - phyloinformatic analysis using Perl.
383             I<BMC Bioinformatics> B<12>:63.
384             L<http://dx.doi.org/10.1186/1471-2105-12-63>
385              
386             =cut
387              
388             1;