File Coverage

blib/lib/Bio/Phylo/Matrices/Datum.pm
Criterion Covered Total %
statement 68 108 62.9
branch 16 40 40.0
condition 7 17 41.1
subroutine 16 19 84.2
pod 8 8 100.0
total 115 192 59.9


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