File Coverage

blib/lib/Bio/Phylo/Treedrawer/Processing.pm
Criterion Covered Total %
statement 94 147 63.9
branch 14 42 33.3
condition 1 10 10.0
subroutine 14 18 77.7
pod n/a
total 123 217 56.6


line stmt bran cond sub pod time code
1             package Bio::Phylo::Treedrawer::Processing;
2 1     1   6 use strict;
  1         2  
  1         29  
3 1     1   4 use warnings;
  1         2  
  1         31  
4 1     1   4 use base 'Bio::Phylo::Treedrawer::Abstract';
  1         1  
  1         327  
5 1     1   7 use Bio::Phylo::Util::Logger;
  1         2  
  1         33  
6 1     1   5 use Bio::Phylo::Util::Exceptions 'throw';
  1         2  
  1         35  
7 1     1   5 use Bio::Phylo::Util::CONSTANT '_PI_';
  1         2  
  1         1207  
8              
9             =head1 NAME
10              
11             Bio::Phylo::Treedrawer::Processing - Graphics format writer used by treedrawer,
12             no serviceable parts inside
13              
14             =head1 DESCRIPTION
15              
16             This module creates a Processing graphic from a Bio::Phylo::Forest::DrawTree
17             object. It is called by the L<Bio::Phylo::Treedrawer> object, so look there to
18             learn how to create tree drawings.
19              
20             =cut
21              
22             my $logger = Bio::Phylo::Util::Logger->new;
23             my $black = 0;
24             my $white = 255;
25             my %colors;
26             my $PI = _PI_;
27              
28             sub _new {
29 1     1   2 my $class = shift;
30 1         4 my %args = @_;
31 1         2 my $commands;
32 1         25 my $self = $class->SUPER::_new( %args, '-api' => \$commands );
33 1         4 return bless $self, $class;
34             }
35              
36             sub _draw_pies {
37 1     1   3 my $self = shift;
38 1         3 my $api = $self->_api;
39             $self->_tree->visit_level_order(
40             sub {
41 7     7   9 my $node = shift;
42 7 50       30 if ( not $node->get_collapsed ) {
43 7         29 my $cx = sprintf( "%.3f", $node->get_x );
44 7         30 my $cy = sprintf( "%.3f", $node->get_y );
45 7         14 my $r;
46 7 100       21 if ( $node->is_internal ) {
47 3         10 $r =
48             sprintf( "%.3f", $self->_drawer->get_node_radius($node) );
49             }
50             else {
51 4         13 $r =
52             sprintf( "%.3f", $self->_drawer->get_tip_radius($node) );
53             }
54 7 50       35 if ( my $pievalues = $node->get_generic('pie') ) {
55 7         10 my @keys = keys %{$pievalues};
  7         22  
56 7         9 my $start = 0;
57 7         10 my $total;
58 7         19 $total += $pievalues->{$_} for @keys;
59 7         17 for my $i ( 0 .. $#keys ) {
60 14 50       28 next if not $pievalues->{ $keys[$i] };
61             my $slice =
62 14         27 $pievalues->{ $keys[$i] } / $total * 2 * $PI;
63 14         19 my $color = $colors{ $keys[$i] };
64 14 100       24 if ( not $color ) {
65 4         16 $colors{ $keys[$i] } = $color =
66             int( ( $i / $#keys ) * 256 );
67             }
68 14         19 my $stop = $start + $slice;
69 14         67 $$api .=
70             " drawArc($cx,$cy,$r,0,1,$color,$start,$stop);\n";
71 14         32 $start += $slice;
72             }
73             }
74             }
75             }
76 1         5 );
77             }
78              
79             sub _draw_legend {
80 1     1   2 my $self = shift;
81 1 50       3 if (%colors) {
82 1         4 my $api = $self->_api;
83 1         3 my $tree = $self->_tree;
84 1         4 my $draw = $self->_drawer;
85 1         4 my @keys = keys %colors;
86 1         9 my $increment =
87             ( $tree->get_tallest_tip->get_x - $tree->get_root->get_x ) /
88             scalar @keys;
89 1         30 my $x = sprintf( "%.3f", $tree->get_root->get_x + 5 );
90 1         3 foreach my $key (@keys) {
91 2         8 my $y = sprintf( "%.3f", $draw->get_height - 90 );
92 2         9 my $width = sprintf( "%.3f", $increment - 10 );
93 2         3 my $height = sprintf( "%.3f", 10.0 );
94 2         4 my $color = int $colors{$key};
95 2         9 $$api .= " drawRectangle($x,$y,$width,$height,$color);\n";
96 2   50     5 $self->_draw_text(
97             '-x' => int($x),
98             '-y' => int( $draw->get_height - 60 ),
99             '-text' => $key || ' ',
100             );
101 2         5 $x += $increment;
102             }
103             $self->_draw_text(
104 1         4 '-x' => int(
105             $tree->get_tallest_tip->get_x + $draw->get_text_horiz_offset
106             ),
107             '-y' => int( $draw->get_height - 80 ),
108             '-text' => 'Node value legend',
109             );
110             }
111             }
112              
113             sub _finish {
114 1     1   2 my $self = shift;
115 1         4 my $commands = $self->_api;
116 1         3 my $tmpl = do { local $/; <DATA> };
  1         4  
  1         46  
117 1         61 return sprintf( $tmpl,
118             __PACKAGE__, my $time = localtime(),
119             $self->_drawer->get_width, $self->_drawer->get_height,
120             $white, $$commands );
121             }
122              
123             sub _draw_text {
124 7     7   12 my $self = shift;
125 7         38 my %args = @_;
126 7         23 my ( $x, $y, $text, $url, $stroke ) = @args{qw(-x -y -text -url -color)};
127 7 50       21 $stroke = $black if not defined $stroke;
128 7         28 my $api = $self->_api;
129 7         37 $$api .= " drawText(\"$text\",$x,$y,$stroke);\n";
130             }
131              
132             sub _draw_line {
133 0     0   0 my $self = shift;
134 0         0 my %args = @_;
135 0         0 my @keys = qw(-x1 -y1 -x2 -y2 -width -color);
136 0         0 my ( $x1, $y1, $x2, $y2, $width, $color ) = @args{@keys};
137 0 0       0 $color = $black if not defined $color;
138 0 0       0 $width = 1 if not defined $width;
139 0         0 my $api = $self->_api;
140 0         0 $$api .= sprintf(" drawLine(%u,%u,%u,%u,%u,%u);\n",$x1,$y1,$x2,$y2,$color,$width);
141             }
142              
143             sub _draw_curve {
144 0     0   0 my $self = shift;
145 0         0 my $api = $self->_api;
146 0         0 my %args = @_;
147 0         0 my @keys = qw(-x1 -y1 -x2 -y2 -width -color);
148 0         0 my ( $x1, $y1, $x3, $y3, $width, $color ) = @args{@keys};
149 0         0 $x1 = sprintf( "%.3f", $x1 );
150 0         0 $x3 = sprintf( "%.3f", $x3 );
151 0         0 $y1 = sprintf( "%.3f", $y1 );
152 0         0 $y3 = sprintf( "%.3f", $y3 );
153 0 0       0 $color = $black if not defined $color;
154 0 0       0 $width = 1 if not defined $width;
155 0         0 $$api .= " drawCurve($x1,$y1,$x3,$y3,$color,$width);\n";
156             }
157              
158             sub _draw_arc {
159 0     0   0 my $self = shift;
160 0         0 my $api = $self->_api;
161 0         0 my %args = @_;
162 0         0 my @keys = qw(-x1 -y1 -x2 -y2 -radius -width -color);
163 0         0 my ( $x1, $y1, $x2, $y2, $radius, $lineWidth, $lineColor ) = @args{@keys};
164 0 0       0 $lineColor = $black if not defined $lineColor;
165 0 0       0 $lineWidth = 1 if not defined $lineWidth;
166 0 0       0 $radius = 0 if not defined $radius;
167 0         0 $radius *= 2;
168 0         0 my $fillColor = $white;
169            
170             # get center of arc
171 0         0 my $drawer = $self->_drawer;
172 0         0 my $cx = $drawer->get_width / 2;
173 0         0 my $cy = $drawer->get_height / 2;
174              
175             # compute start and end
176 0         0 my ( $r1, $start ) = $drawer->cartesian_to_polar( $x1 - $cx, $y1 - $cy );
177 0         0 my ( $r2, $stop ) = $drawer->cartesian_to_polar( $x2 - $cx, $y2 - $cy );
178 0 0       0 $start += 360 if $start < 0;
179 0 0       0 $stop += 360 if $stop < 0;
180 0         0 $start = ( $start / 360 ) * 2 * $PI;
181 0         0 $stop = ( $stop / 360 ) * 2 * $PI;
182 0         0 $start = sprintf( "%.3f", $start );
183 0         0 $stop = sprintf( "%.3f", $stop );
184            
185 0         0 $$api .= " drawArc($cx,$cy,$radius,$lineColor,$lineWidth,$fillColor,$start,$stop);\n";
186             }
187              
188             sub _draw_multi {
189 6     6   12 my $self = shift;
190 6         23 my $api = $self->_api;
191 6         30 my %args = @_;
192 6         18 my @keys = qw(-x1 -y1 -x2 -y2 -width -color);
193 6         18 my ( $x1, $y1, $x2, $y2, $width, $color ) = @args{@keys};
194 6 50       16 $color = $black if not defined $color;
195 6 50       13 $width = 1 if not defined $width;
196 6         43 $$api .= sprintf( " drawMulti(%u,%u,%u,%u,%u,%u);\n",
197             $x1, $y1, $x2, $y2, $color, $width );
198             }
199              
200             sub _draw_triangle {
201 0     0   0 my $self = shift;
202 0         0 my $api = $self->_api;
203 0         0 my %args = @_;
204 0         0 my @coord = qw(-x1 -y1 -x2 -y2 -x3 -y3);
205 0         0 my ( $x1, $y1, $x2, $y2, $x3, $y3 ) = @args{@coord};
206 0         0 my @optional = qw(-fill -stroke -width -url -api);
207 0   0     0 my $fill = $args{'-fill'} || $white;
208 0   0     0 my $stroke = $args{'-stroke'} || $black;
209 0   0     0 my $width = $args{'-width'} || 1;
210 0         0 my $url = $args{'-url'};
211 0         0 $$api .=
212             " drawTriangle($x1,$y1,$x2,$y2,$x3,$y3,$stroke,$width,$fill);\n";
213             }
214              
215             sub _draw_circle {
216 3     3   6 my $self = shift;
217 3         10 my $api = $self->_api;
218 3         13 my %args = @_;
219             my ( $x, $y, $radius, $width, $stroke, $fill, $url ) =
220 3         10 @args{qw(-x -y -radius -width -stroke -fill -url)};
221 3 50       8 $stroke = $black if not defined $stroke;
222 3 50       10 $width = 1 if not defined $width;
223 3 50       7 $fill = $white if not defined $fill;
224 3         21 $$api .= sprintf( " drawCircle(%u,%u,%u,%u,%u,%u,\"%s\");\n",
225             $x, $y, $radius, $stroke, $width, $fill, $url );
226             }
227              
228             =head1 SEE ALSO
229              
230             There is a mailing list at L<https://groups.google.com/forum/#!forum/bio-phylo>
231             for any user or developer questions and discussions.
232              
233             =over
234              
235             =item L<http://processing.org>
236              
237             This treedrawer produces a tree description in Processing language syntax. Visit
238             the website to learn more about how to deploy such graphics.
239              
240             =item L<Bio::Phylo::Treedrawer>
241              
242             The processing treedrawer is called by the L<Bio::Phylo::Treedrawer> object.
243             Look there to learn how to create tree drawings.
244              
245             =item L<Bio::Phylo::Manual>
246              
247             Also see the manual: L<Bio::Phylo::Manual> and L<http://rutgervos.blogspot.com>.
248              
249             =back
250              
251             =head1 CITATION
252              
253             If you use Bio::Phylo in published research, please cite it:
254              
255             B<Rutger A Vos>, B<Jason Caravas>, B<Klaas Hartmann>, B<Mark A Jensen>
256             and B<Chase Miller>, 2011. Bio::Phylo - phyloinformatic analysis using Perl.
257             I<BMC Bioinformatics> B<12>:63.
258             L<http://dx.doi.org/10.1186/1471-2105-12-63>
259              
260             =cut
261              
262             1;
263             __DATA__
264              
265             /*
266             * This code was generated by %s on %s - do need edit this, regenerate it
267             */
268              
269             ArrayList coordinates = new ArrayList();
270              
271             void mouseClicked() {
272             for (int i = coordinates.size()-1; i >= 0; i--) {
273             HashMap co = (HashMap) coordinates.get(i);
274             int minX = (Integer) co.get("minX");
275             int maxX = (Integer) co.get("maxX");
276             int minY = (Integer) co.get("minY");
277             int maxY = (Integer) co.get("maxY");
278             if ( mouseX > minX && mouseX < maxX && mouseY > minY && mouseY < maxY ) {
279             link((String)co.get("url"));
280             }
281             }
282             }
283              
284             void drawText(String textString, int x, int y, int textColor) {
285             fill(textColor);
286             text(textString,x,y);
287             noFill();
288             }
289              
290             void drawLine(int x1, int y1, int x2, int y2, int lineColor, int lineWidth) {
291             stroke(lineColor);
292             strokeWeight(lineWidth);
293             line(x1,y1,x2,y2);
294             strokeWeight(1);
295             noStroke();
296             }
297              
298             void drawMulti(int x1, int y1, int x2, int y2, int lineColor, int lineWidth) {
299             drawLine(x1,y1,x1,y2,lineColor,lineWidth);
300             drawLine(x1,y2,x2,y2,lineColor,lineWidth);
301             }
302              
303             void drawCircle(int x, int y, int radius, int lineColor, int lineWidth, int fillColor, String url) {
304             fill(fillColor);
305             stroke(lineColor);
306             strokeWeight(lineWidth);
307             ellipse(x, y, radius, radius);
308             strokeWeight(1);
309             noStroke();
310             noFill();
311             if ( url != null ) {
312             HashMap coordinate = new HashMap();
313             coordinate.put("url",url);
314             coordinate.put("minX",x-radius);
315             coordinate.put("maxX",x+radius);
316             coordinate.put("minY",y-radius);
317             coordinate.put("maxY",y+radius);
318             coordinates.add(coordinate);
319             }
320             }
321              
322             void drawCurve(float x1, float y1, float x3, float y3, int lineColor, int lineWidth) {
323             stroke(lineColor);
324             strokeWeight(lineWidth);
325             noFill();
326             float ellipseWidth = abs(x1-x3) * 2;
327             float ellipseHeight = abs(y1-y3) * 2;
328             float start;
329             float stop;
330             if ( y1 < y3 ) {
331             start = PI / 2;
332             stop = PI;
333             }
334             else {
335             start = PI;
336             stop = TWO_PI - PI / 2;
337             }
338             arc(x3,y1,ellipseWidth,ellipseHeight,start,stop);
339             strokeWeight(1);
340             noStroke();
341             }
342              
343             void drawArc(float x, float y, float radius, int lineColor, int lineWidth, int fillColor, float start, float stop) {
344             fill(fillColor);
345             stroke(lineColor);
346             strokeWeight(lineWidth);
347             arc(x,y,radius,radius,start,stop);
348             strokeWeight(1);
349             noStroke();
350             noFill();
351             }
352              
353             void drawRectangle(float x, float y, float width, float height, int fillColor) {
354             fill(fillColor);
355             stroke(0);
356             strokeWeight(1);
357             rect(x,y,width,height);
358             noStroke();
359             noFill();
360             }
361              
362             void drawTriangle(float x1, float y1, float x2, float y2, float x3, float y3, int lineColor, int lineWidth, int fillColor) {
363             fill(fillColor);
364             stroke(lineColor);
365             strokeWeight(lineWidth);
366             triangle(x1, y1, x2, y2, x3, y3);
367             strokeWeight(1);
368             noStroke();
369             noFill();
370             }
371              
372             void setup() {
373             size(%u, %u);
374             background(%s);
375             smooth();
376             %s
377             }
378              
379             void draw() {}