File Coverage

blib/lib/Bio/Phylo/Treedrawer/Processing.pm
Criterion Covered Total %
statement 91 144 63.1
branch 15 42 35.7
condition 1 10 10.0
subroutine 13 17 76.4
pod n/a
total 120 213 56.3


line stmt bran cond sub pod time code
1             package Bio::Phylo::Treedrawer::Processing;
2 1     1   5 use strict;
  1         2  
  1         30  
3 1     1   4 use base 'Bio::Phylo::Treedrawer::Abstract';
  1         2  
  1         313  
4 1     1   7 use Bio::Phylo::Util::Logger;
  1         2  
  1         33  
5 1     1   5 use Bio::Phylo::Util::Exceptions 'throw';
  1         1  
  1         33  
6 1     1   4 use Bio::Phylo::Util::CONSTANT '_PI_';
  1         2  
  1         1202  
7              
8             =head1 NAME
9              
10             Bio::Phylo::Treedrawer::Processing - Graphics format writer used by treedrawer,
11             no serviceable parts inside
12              
13             =head1 DESCRIPTION
14              
15             This module creates a Processing graphic from a Bio::Phylo::Forest::DrawTree
16             object. It is called by the L object, so look there to
17             learn how to create tree drawings.
18              
19             =cut
20              
21             my $logger = Bio::Phylo::Util::Logger->new;
22             my $black = 0;
23             my $white = 255;
24             my %colors;
25             my $PI = _PI_;
26              
27             sub _new {
28 1     1   4 my $class = shift;
29 1         4 my %args = @_;
30 1         2 my $commands;
31 1         11 my $self = $class->SUPER::_new( %args, '-api' => \$commands );
32 1         3 return bless $self, $class;
33             }
34              
35             sub _draw_pies {
36 1     1   2 my $self = shift;
37 1         5 my $api = $self->_api;
38             $self->_tree->visit_level_order(
39             sub {
40 7     7   10 my $node = shift;
41 7 50       33 if ( not $node->get_collapsed ) {
42 7         34 my $cx = sprintf( "%.3f", $node->get_x );
43 7         38 my $cy = sprintf( "%.3f", $node->get_y );
44 7         14 my $r;
45 7 100       24 if ( $node->is_internal ) {
46 3         9 $r =
47             sprintf( "%.3f", $self->_drawer->get_node_radius($node) );
48             }
49             else {
50 4         12 $r =
51             sprintf( "%.3f", $self->_drawer->get_tip_radius($node) );
52             }
53 7 50       31 if ( my $pievalues = $node->get_generic('pie') ) {
54 7         10 my @keys = keys %{$pievalues};
  7         30  
55 7         12 my $start = 0;
56 7         9 my $total;
57 7         22 $total += $pievalues->{$_} for @keys;
58 7         17 for my $i ( 0 .. $#keys ) {
59 14 100       29 next if not $pievalues->{ $keys[$i] };
60             my $slice =
61 13         27 $pievalues->{ $keys[$i] } / $total * 2 * $PI;
62 13         18 my $color = $colors{ $keys[$i] };
63 13 100       22 if ( not $color ) {
64 4         10 $colors{ $keys[$i] } = $color =
65             int( ( $i / $#keys ) * 256 );
66             }
67 13         20 my $stop = $start + $slice;
68 13         67 $$api .=
69             " drawArc($cx,$cy,$r,0,1,$color,$start,$stop);\n";
70 13         31 $start += $slice;
71             }
72             }
73             }
74             }
75 1         4 );
76             }
77              
78             sub _draw_legend {
79 1     1   3 my $self = shift;
80 1 50       3 if (%colors) {
81 1         2 my $api = $self->_api;
82 1         2 my $tree = $self->_tree;
83 1         2 my $draw = $self->_drawer;
84 1         3 my @keys = keys %colors;
85 1         11 my $increment =
86             ( $tree->get_tallest_tip->get_x - $tree->get_root->get_x ) /
87             scalar @keys;
88 1         6 my $x = sprintf( "%.3f", $tree->get_root->get_x + 5 );
89 1         3 foreach my $key (@keys) {
90 2         7 my $y = sprintf( "%.3f", $draw->get_height - 90 );
91 2         8 my $width = sprintf( "%.3f", $increment - 10 );
92 2         4 my $height = sprintf( "%.3f", 10.0 );
93 2         4 my $color = int $colors{$key};
94 2         7 $$api .= " drawRectangle($x,$y,$width,$height,$color);\n";
95 2   50     7 $self->_draw_text(
96             '-x' => int($x),
97             '-y' => int( $draw->get_height - 60 ),
98             '-text' => $key || ' ',
99             );
100 2         5 $x += $increment;
101             }
102             $self->_draw_text(
103 1         4 '-x' => int(
104             $tree->get_tallest_tip->get_x + $draw->get_text_horiz_offset
105             ),
106             '-y' => int( $draw->get_height - 80 ),
107             '-text' => 'Node value legend',
108             );
109             }
110             }
111              
112             sub _finish {
113 1     1   2 my $self = shift;
114 1         3 my $commands = $self->_api;
115 1         2 my $tmpl = do { local $/; };
  1         5  
  1         42  
116 1         60 return sprintf( $tmpl,
117             __PACKAGE__, my $time = localtime(),
118             $self->_drawer->get_width, $self->_drawer->get_height,
119             $white, $$commands );
120             }
121              
122             sub _draw_text {
123 7     7   12 my $self = shift;
124 7         32 my %args = @_;
125 7         22 my ( $x, $y, $text, $url, $stroke ) = @args{qw(-x -y -text -url -color)};
126 7 50       18 $stroke = $black if not defined $stroke;
127 7         15 my $api = $self->_api;
128 7         40 $$api .= " drawText(\"$text\",$x,$y,$stroke);\n";
129             }
130              
131             sub _draw_line {
132 0     0   0 my $self = shift;
133 0         0 my %args = @_;
134 0         0 my @keys = qw(-x1 -y1 -x2 -y2 -width -color);
135 0         0 my ( $x1, $y1, $x2, $y2, $width, $color ) = @args{@keys};
136 0 0       0 $color = $black if not defined $color;
137 0 0       0 $width = 1 if not defined $width;
138 0         0 my $api = $self->_api;
139 0         0 $$api .= sprintf(" drawLine(%u,%u,%u,%u,%u,%u);\n",$x1,$y1,$x2,$y2,$color,$width);
140             }
141              
142             sub _draw_curve {
143 0     0   0 my $self = shift;
144 0         0 my $api = $self->_api;
145 0         0 my %args = @_;
146 0         0 my @keys = qw(-x1 -y1 -x2 -y2 -width -color);
147 0         0 my ( $x1, $y1, $x3, $y3, $width, $color ) = @args{@keys};
148 0         0 $x1 = sprintf( "%.3f", $x1 );
149 0         0 $x3 = sprintf( "%.3f", $x3 );
150 0         0 $y1 = sprintf( "%.3f", $y1 );
151 0         0 $y3 = sprintf( "%.3f", $y3 );
152 0 0       0 $color = $black if not defined $color;
153 0 0       0 $width = 1 if not defined $width;
154 0         0 $$api .= " drawCurve($x1,$y1,$x3,$y3,$color,$width);\n";
155             }
156              
157             sub _draw_arc {
158 0     0   0 my $self = shift;
159 0         0 my $api = $self->_api;
160 0         0 my %args = @_;
161 0         0 my @keys = qw(-x1 -y1 -x2 -y2 -radius -width -color);
162 0         0 my ( $x1, $y1, $x2, $y2, $radius, $lineWidth, $lineColor ) = @args{@keys};
163 0 0       0 $lineColor = $black if not defined $lineColor;
164 0 0       0 $lineWidth = 1 if not defined $lineWidth;
165 0 0       0 $radius = 0 if not defined $radius;
166 0         0 $radius *= 2;
167 0         0 my $fillColor = $white;
168            
169             # get center of arc
170 0         0 my $drawer = $self->_drawer;
171 0         0 my $cx = $drawer->get_width / 2;
172 0         0 my $cy = $drawer->get_height / 2;
173              
174             # compute start and end
175 0         0 my ( $r1, $start ) = $drawer->cartesian_to_polar( $x1 - $cx, $y1 - $cy );
176 0         0 my ( $r2, $stop ) = $drawer->cartesian_to_polar( $x2 - $cx, $y2 - $cy );
177 0 0       0 $start += 360 if $start < 0;
178 0 0       0 $stop += 360 if $stop < 0;
179 0         0 $start = ( $start / 360 ) * 2 * $PI;
180 0         0 $stop = ( $stop / 360 ) * 2 * $PI;
181 0         0 $start = sprintf( "%.3f", $start );
182 0         0 $stop = sprintf( "%.3f", $stop );
183            
184 0         0 $$api .= " drawArc($cx,$cy,$radius,$lineColor,$lineWidth,$fillColor,$start,$stop);\n";
185             }
186              
187             sub _draw_multi {
188 6     6   11 my $self = shift;
189 6         20 my $api = $self->_api;
190 6         33 my %args = @_;
191 6         18 my @keys = qw(-x1 -y1 -x2 -y2 -width -color);
192 6         16 my ( $x1, $y1, $x2, $y2, $width, $color ) = @args{@keys};
193 6 50       14 $color = $black if not defined $color;
194 6 50       14 $width = 1 if not defined $width;
195 6         54 $$api .= sprintf( " drawMulti(%u,%u,%u,%u,%u,%u);\n",
196             $x1, $y1, $x2, $y2, $color, $width );
197             }
198              
199             sub _draw_triangle {
200 0     0   0 my $self = shift;
201 0         0 my $api = $self->_api;
202 0         0 my %args = @_;
203 0         0 my @coord = qw(-x1 -y1 -x2 -y2 -x3 -y3);
204 0         0 my ( $x1, $y1, $x2, $y2, $x3, $y3 ) = @args{@coord};
205 0         0 my @optional = qw(-fill -stroke -width -url -api);
206 0   0     0 my $fill = $args{'-fill'} || $white;
207 0   0     0 my $stroke = $args{'-stroke'} || $black;
208 0   0     0 my $width = $args{'-width'} || 1;
209 0         0 my $url = $args{'-url'};
210 0         0 $$api .=
211             " drawTriangle($x1,$y1,$x2,$y2,$x3,$y3,$stroke,$width,$fill);\n";
212             }
213              
214             sub _draw_circle {
215 7     7   11 my $self = shift;
216 7         17 my $api = $self->_api;
217 7         28 my %args = @_;
218             my ( $x, $y, $radius, $width, $stroke, $fill, $url ) =
219 7         24 @args{qw(-x -y -radius -width -stroke -fill -url)};
220 7 50       16 $stroke = $black if not defined $stroke;
221 7 50       15 $width = 1 if not defined $width;
222 7 50       14 $fill = $white if not defined $fill;
223 7         48 $$api .= sprintf( " drawCircle(%u,%u,%u,%u,%u,%u,\"%s\");\n",
224             $x, $y, $radius, $stroke, $width, $fill, $url );
225             }
226              
227             =head1 SEE ALSO
228              
229             There is a mailing list at L
230             for any user or developer questions and discussions.
231              
232             =over
233              
234             =item L
235              
236             This treedrawer produces a tree description in Processing language syntax. Visit
237             the website to learn more about how to deploy such graphics.
238              
239             =item L
240              
241             The processing treedrawer is called by the L object.
242             Look there to learn how to create tree drawings.
243              
244             =item L
245              
246             Also see the manual: L and L.
247              
248             =back
249              
250             =head1 CITATION
251              
252             If you use Bio::Phylo in published research, please cite it:
253              
254             B, B, B, B
255             and B, 2011. Bio::Phylo - phyloinformatic analysis using Perl.
256             I B<12>:63.
257             L
258              
259             =cut
260              
261             1;
262             __DATA__