File Coverage

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


line stmt bran cond sub pod time code
1             package Bio::Phylo::Treedrawer::Processing;
2 1     1   6 use strict;
  1         3  
  1         30  
3 1     1   4 use base 'Bio::Phylo::Treedrawer::Abstract';
  1         3  
  1         358  
4 1     1   6 use Bio::Phylo::Util::Logger;
  1         2  
  1         33  
5 1     1   5 use Bio::Phylo::Util::Exceptions 'throw';
  1         3  
  1         34  
6 1     1   5 use Bio::Phylo::Util::CONSTANT '_PI_';
  1         2  
  1         1247  
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<Bio::Phylo::Treedrawer> 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   3 my $class = shift;
29 1         4 my %args = @_;
30 1         2 my $commands;
31 1         14 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         4 my $api = $self->_api;
38             $self->_tree->visit_level_order(
39             sub {
40 7     7   10 my $node = shift;
41 7 50       29 if ( not $node->get_collapsed ) {
42 7         29 my $cx = sprintf( "%.3f", $node->get_x );
43 7         34 my $cy = sprintf( "%.3f", $node->get_y );
44 7         12 my $r;
45 7 100       29 if ( $node->is_internal ) {
46 3         10 $r =
47             sprintf( "%.3f", $self->_drawer->get_node_radius($node) );
48             }
49             else {
50 4         11 $r =
51             sprintf( "%.3f", $self->_drawer->get_tip_radius($node) );
52             }
53 7 50       31 if ( my $pievalues = $node->get_generic('pie') ) {
54 7         11 my @keys = keys %{$pievalues};
  7         21  
55 7         11 my $start = 0;
56 7         9 my $total;
57 7         20 $total += $pievalues->{$_} for @keys;
58 7         15 for my $i ( 0 .. $#keys ) {
59 14 50       31 next if not $pievalues->{ $keys[$i] };
60             my $slice =
61 14         25 $pievalues->{ $keys[$i] } / $total * 2 * $PI;
62 14         17 my $color = $colors{ $keys[$i] };
63 14 100       26 if ( not $color ) {
64 3         8 $colors{ $keys[$i] } = $color =
65             int( ( $i / $#keys ) * 256 );
66             }
67 14         23 my $stop = $start + $slice;
68 14         72 $$api .=
69             " drawArc($cx,$cy,$r,0,1,$color,$start,$stop);\n";
70 14         36 $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         4 my $api = $self->_api;
82 1         4 my $tree = $self->_tree;
83 1         3 my $draw = $self->_drawer;
84 1         3 my @keys = keys %colors;
85 1         9 my $increment =
86             ( $tree->get_tallest_tip->get_x - $tree->get_root->get_x ) /
87             scalar @keys;
88 1         5 my $x = sprintf( "%.3f", $tree->get_root->get_x + 5 );
89 1         4 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         3 my $height = sprintf( "%.3f", 10.0 );
93 2         4 my $color = int $colors{$key};
94 2         9 $$api .= " drawRectangle($x,$y,$width,$height,$color);\n";
95 2   50     6 $self->_draw_text(
96             '-x' => int($x),
97             '-y' => int( $draw->get_height - 60 ),
98             '-text' => $key || ' ',
99             );
100 2         4 $x += $increment;
101             }
102             $self->_draw_text(
103 1         3 '-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   3 my $self = shift;
114 1         4 my $commands = $self->_api;
115 1         3 my $tmpl = do { local $/; <DATA> };
  1         5  
  1         50  
116 1         65 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   11 my $self = shift;
124 7         33 my %args = @_;
125 7         22 my ( $x, $y, $text, $url, $stroke ) = @args{qw(-x -y -text -url -color)};
126 7 50       16 $stroke = $black if not defined $stroke;
127 7         17 my $api = $self->_api;
128 7         39 $$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   10 my $self = shift;
189 6         18 my $api = $self->_api;
190 6         22 my %args = @_;
191 6         33 my @keys = qw(-x1 -y1 -x2 -y2 -width -color);
192 6         18 my ( $x1, $y1, $x2, $y2, $width, $color ) = @args{@keys};
193 6 50       14 $color = $black if not defined $color;
194 6 50       15 $width = 1 if not defined $width;
195 6         44 $$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 3     3   5 my $self = shift;
216 3         7 my $api = $self->_api;
217 3         13 my %args = @_;
218             my ( $x, $y, $radius, $width, $stroke, $fill, $url ) =
219 3         9 @args{qw(-x -y -radius -width -stroke -fill -url)};
220 3 50       8 $stroke = $black if not defined $stroke;
221 3 50       7 $width = 1 if not defined $width;
222 3 50       12 $fill = $white if not defined $fill;
223 3         21 $$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<https://groups.google.com/forum/#!forum/bio-phylo>
230             for any user or developer questions and discussions.
231              
232             =over
233              
234             =item L<http://processing.org>
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<Bio::Phylo::Treedrawer>
240              
241             The processing treedrawer is called by the L<Bio::Phylo::Treedrawer> object.
242             Look there to learn how to create tree drawings.
243              
244             =item L<Bio::Phylo::Manual>
245              
246             Also see the manual: L<Bio::Phylo::Manual> and L<http://rutgervos.blogspot.com>.
247              
248             =back
249              
250             =head1 CITATION
251              
252             If you use Bio::Phylo in published research, please cite it:
253              
254             B<Rutger A Vos>, B<Jason Caravas>, B<Klaas Hartmann>, B<Mark A Jensen>
255             and B<Chase Miller>, 2011. Bio::Phylo - phyloinformatic analysis using Perl.
256             I<BMC Bioinformatics> B<12>:63.
257             L<http://dx.doi.org/10.1186/1471-2105-12-63>
258              
259             =cut
260              
261             1;
262             __DATA__
263              
264             /*
265             * This code was generated by %s on %s - do need edit this, regenerate it
266             */
267              
268             ArrayList coordinates = new ArrayList();
269              
270             void mouseClicked() {
271             for (int i = coordinates.size()-1; i >= 0; i--) {
272             HashMap co = (HashMap) coordinates.get(i);
273             int minX = (Integer) co.get("minX");
274             int maxX = (Integer) co.get("maxX");
275             int minY = (Integer) co.get("minY");
276             int maxY = (Integer) co.get("maxY");
277             if ( mouseX > minX && mouseX < maxX && mouseY > minY && mouseY < maxY ) {
278             link((String)co.get("url"));
279             }
280             }
281             }
282              
283             void drawText(String textString, int x, int y, int textColor) {
284             fill(textColor);
285             text(textString,x,y);
286             noFill();
287             }
288              
289             void drawLine(int x1, int y1, int x2, int y2, int lineColor, int lineWidth) {
290             stroke(lineColor);
291             strokeWeight(lineWidth);
292             line(x1,y1,x2,y2);
293             strokeWeight(1);
294             noStroke();
295             }
296              
297             void drawMulti(int x1, int y1, int x2, int y2, int lineColor, int lineWidth) {
298             drawLine(x1,y1,x1,y2,lineColor,lineWidth);
299             drawLine(x1,y2,x2,y2,lineColor,lineWidth);
300             }
301              
302             void drawCircle(int x, int y, int radius, int lineColor, int lineWidth, int fillColor, String url) {
303             fill(fillColor);
304             stroke(lineColor);
305             strokeWeight(lineWidth);
306             ellipse(x, y, radius, radius);
307             strokeWeight(1);
308             noStroke();
309             noFill();
310             if ( url != null ) {
311             HashMap coordinate = new HashMap();
312             coordinate.put("url",url);
313             coordinate.put("minX",x-radius);
314             coordinate.put("maxX",x+radius);
315             coordinate.put("minY",y-radius);
316             coordinate.put("maxY",y+radius);
317             coordinates.add(coordinate);
318             }
319             }
320              
321             void drawCurve(float x1, float y1, float x3, float y3, int lineColor, int lineWidth) {
322             stroke(lineColor);
323             strokeWeight(lineWidth);
324             noFill();
325             float ellipseWidth = abs(x1-x3) * 2;
326             float ellipseHeight = abs(y1-y3) * 2;
327             float start;
328             float stop;
329             if ( y1 < y3 ) {
330             start = PI / 2;
331             stop = PI;
332             }
333             else {
334             start = PI;
335             stop = TWO_PI - PI / 2;
336             }
337             arc(x3,y1,ellipseWidth,ellipseHeight,start,stop);
338             strokeWeight(1);
339             noStroke();
340             }
341              
342             void drawArc(float x, float y, float radius, int lineColor, int lineWidth, int fillColor, float start, float stop) {
343             fill(fillColor);
344             stroke(lineColor);
345             strokeWeight(lineWidth);
346             arc(x,y,radius,radius,start,stop);
347             strokeWeight(1);
348             noStroke();
349             noFill();
350             }
351              
352             void drawRectangle(float x, float y, float width, float height, int fillColor) {
353             fill(fillColor);
354             stroke(0);
355             strokeWeight(1);
356             rect(x,y,width,height);
357             noStroke();
358             noFill();
359             }
360              
361             void drawTriangle(float x1, float y1, float x2, float y2, float x3, float y3, int lineColor, int lineWidth, int fillColor) {
362             fill(fillColor);
363             stroke(lineColor);
364             strokeWeight(lineWidth);
365             triangle(x1, y1, x2, y2, x3, y3);
366             strokeWeight(1);
367             noStroke();
368             noFill();
369             }
370              
371             void setup() {
372             size(%u, %u);
373             background(%s);
374             smooth();
375             %s
376             }
377              
378             void draw() {}