File Coverage

blib/lib/Bio/Phylo/Models/Substitution/Binary.pm
Criterion Covered Total %
statement 15 73 20.5
branch 0 12 0.0
condition 0 5 0.0
subroutine 5 12 41.6
pod 6 6 100.0
total 26 108 24.0


line stmt bran cond sub pod time code
1             package Bio::Phylo::Models::Substitution::Binary;
2 13     13   75 use strict;
  13         28  
  13         395  
3 13     13   81 use Data::Dumper;
  13         28  
  13         606  
4 13     13   72 use Bio::Phylo::Util::Logger;
  13         28  
  13         480  
5 13     13   68 use Bio::Phylo::Util::CONSTANT qw'/looks_like/ :objecttypes';
  13         27  
  13         3487  
6 13     13   82 use Bio::Phylo::Util::Exceptions qw'throw';
  13         24  
  13         8414  
7              
8             my $logger = Bio::Phylo::Util::Logger->new;
9              
10             =head1 NAME
11              
12             Bio::Phylo::Models::Substitution::Binary - Binary character substitution model
13              
14             =head1 SYNOPSIS
15              
16             use Bio::Phylo::Models::Substitution::Binary;
17              
18             # create a binary substitution model
19             # by doing a modeltest
20             my $model = Bio::Phylo::Models::Substitution::Binary->modeltest(
21             -tree => $tree, # phylogeny
22             -matrix => $matrix, # character state matrix, standard categorical data
23             -model => 'ARD', # ace model
24             -char => 'c1', # column ID in $matrix
25             );
26              
27             # after model test, forward and reverse instantaneous transition
28             # rates are available, e.g. for simulation
29             print $model->forward, "\n";
30             print $model->reverse, "\n";
31              
32             =head1 DESCRIPTION
33              
34             This is a class that encapsulates an instantaneous transition model
35             for a binary character. The model is asymmetrical in that the forward
36             and reverse rates (can) differ. The rates can be inferred from a
37             character in a character state matrix by modeltesting. This is done
38             by delegation to the R package C. For this to work, you therefore
39             need to have R and C installed, as well as the bridge that allows
40             Perl to communicate with R, which is done by the optional package
41             L.
42              
43             =head1 METHODS
44              
45             =head2 CONSTRUCTOR
46              
47             =over
48              
49             =item new
50              
51             Binary character model constructor.
52              
53             Type : Constructor
54             Title : new
55             Usage : my $model = Bio::Phylo::Models::Substitution::Binary->new(%args);
56             Function: Instantiates a Bio::Phylo::Models::Substitution::Binary object.
57             Returns : A Bio::Phylo::Models::Substitution::Binary object.
58             Args : Optional:
59             -forward => sets forward rate
60             -reverse => sets reverse rate
61              
62             =cut
63              
64             sub new {
65 0     0 1   my $class = shift;
66 0           my %args = looks_like_hash @_;
67 0           my $self = { '_fw' => undef, '_rev' => undef };
68 0           bless $self, $class;
69 0           while ( my ( $key, $value ) = each %args ) {
70 0           $key =~ s/^-/set_/;
71 0           $self->$key($value);
72             }
73 0           return $self;
74             }
75              
76             =item set_forward
77              
78             Setter for forward transition rate
79              
80             Type : method
81             Title : set_forward
82             Usage : $model->set_forward($rate);
83             Function: Setter for forward transition rate
84             Returns : $self
85             Args : A rate (floating point number)
86              
87             =cut
88              
89             sub set_forward {
90 0     0 1   my ( $self, $fw ) = @_;
91 0           $self->{'_fw'} = $fw;
92 0           return $self;
93             }
94              
95             =item set_reverse
96              
97             Setter for reverse transition rate
98              
99             Type : method
100             Title : set_reverse
101             Usage : $model->set_reverse($rate);
102             Function: Setter for reverse transition rate
103             Returns : $self
104             Args : A rate (floating point number)
105              
106             =cut
107              
108             sub set_reverse {
109 0     0 1   my ( $self, $rev ) = @_;
110 0           $self->{'_rev'} = $rev;
111 0           return $self;
112             }
113              
114             =item get_forward
115              
116             Setter for forward transition rate
117              
118             Type : method
119             Title : get_forward
120             Usage : my $rate = $model->get_forward;
121             Function: Getter for forward transition rate
122             Returns : A rate (floating point number)
123             Args : NONE
124              
125             =cut
126              
127 0     0 1   sub get_forward { shift->{'_fw'} }
128              
129             =item get_reverse
130              
131             Setter for reverse transition rate
132              
133             Type : method
134             Title : get_reverse
135             Usage : my $rate = $model->get_reverse;
136             Function: Getter for reverse transition rate
137             Returns : A rate (floating point number)
138             Args : NONE
139              
140             =cut
141              
142 0     0 1   sub get_reverse { shift->{'_rev'} }
143              
144             =item modeltest
145              
146             Performs a model test to infer transition rates
147              
148             Type : method
149             Title : modeltest
150             Usage : my $model = $package->modeltest;
151             Function: Performs a model test to infer transition rates
152             Returns : A populated $model object
153             Args : All required:
154             -tree => $tree, # phylogeny
155             -matrix => $matrix, # character state matrix, standard categorical data
156             -model => 'ARD', # ace model
157             -char => 'c1', # column ID in $matrix
158              
159             =cut
160              
161             sub modeltest {
162              
163             # process arguments
164 0     0 1   my ( $class, %args ) = @_;
165 0 0         my $tree = $args{'-tree'} or throw 'BadArgs' => "Need -tree argument";
166 0 0         my $char = $args{'-char'} or throw 'BadArgs' => "Need -char argument";
167 0 0         my $matrix = $args{'-matrix'} or throw 'BadArgs' => "Need -matrix argument";
168 0   0       my $model = $args{'-model'} || 'ARD';
169            
170             # we don't actually check if the character is binary here. perhaps we should,
171             # and verify that the tips in the tree match the rows in the matrix, and
172             # prune tips with missing data, and, and, and...
173 0 0         if ( $matrix->get_type !~ /standard/i ) {
174 0           throw 'BadArgs' => "Need standard categorical data";
175             }
176 0 0         if ( looks_like_class 'Statistics::R' ) {
177            
178             # start R, load library
179 0           $logger->info("going to run 'ace'");
180 0           my $R = Statistics::R->new;
181 0           $R->run(q[library("ape")]);
182            
183             # insert data
184 0           my $newick = $tree->to_newick;
185 0           my %hash = $class->_data_hash($char,$matrix);
186 0           $R->run(qq[phylo <- read.tree(text="$newick")]);
187 0           $R->set('chars', [values %hash]);
188 0           $R->set('labels', [keys %hash]);
189 0           $R->run(q[names(chars) <- labels]);
190            
191             # do calculation
192 0           $R->run(qq[ans <- ace(chars,phylo,type="d",model="$model")]);
193 0           $R->run(q[rates <- ans$rates]);
194 0           my $rates = $R->get(q[rates]);
195 0           $logger->info("Rates: ".Dumper($rates));
196            
197             # return instance
198 0           return $class->new(
199             '-forward' => $rates->[1],
200             '-reverse' => $rates->[0],
201             );
202             }
203             }
204              
205             sub _data_hash {
206 0     0     my ( $self, $char, $matrix ) = @_;
207 0           my $cid = $char->get_id;
208 0           my $chars = $matrix->get_characters;
209 0           my $nchar = $matrix->get_nchar;
210 0   0       my $name = $char->get_name || $cid;
211            
212             # find index of character
213 0           my $index;
214 0           CHAR: for my $i ( 0 .. $nchar - 1 ) {
215 0           my $c = $chars->get_by_index($i);
216 0 0         if ( $c->get_id == $cid ) {
217 0           $index = $i;
218 0           $logger->info("index of character ${name}: ${index}");
219 0           last CHAR;
220             }
221             }
222            
223             # get character states
224 0           my %result;
225 0           for my $row ( @{ $matrix->get_entities } ) {
  0            
226 0           my @char = $row->get_char;
227 0           my $name = $row->get_name;
228 0           $result{$name} = $char[$index];
229             }
230 0           $logger->debug(Dumper(\%result));
231 0           return %result;
232             }
233              
234             =back
235              
236             =head1 SEE ALSO
237              
238             There is a mailing list at L
239             for any user or developer questions and discussions.
240              
241             =over
242              
243             =item L
244              
245             Also see the manual: L and L.
246              
247             =back
248              
249             =head1 CITATION
250              
251             If you use Bio::Phylo in published research, please cite it:
252              
253             B, B, B, B
254             and B, 2011. Bio::Phylo - phyloinformatic analysis using Perl.
255             I B<12>:63.
256             L
257              
258             =cut
259              
260             1;