| Bio-Graphics documentation | Contained in the Bio-Graphics distribution. |
Bio::Graphics::Glyph::ternary_plot - Draw ternary plot data
#!/usr/bin/perl
use strict;
use warnings;
use Bio::Graphics;
use Bio::Graphics::Feature;
my $segment = Bio::Graphics::Feature->new(-start=>1,-end=>700);
my $snp1 = Bio::Graphics::Feature->new(-start => 500,
-end => 501,
-name => 'rs000001',
-attributes=> {triples => [
[0.01, 0.81, 0.18, 'red', 'CEPH'],
[0.25, 0.25, 0.50, 'blue', 'JPT+CHB'],
[0.81, 0.01, 0.18, 'green','YRI'],
]
}
);
my $snp2 = Bio::Graphics::Feature->new(-start => 300,
-end => 301,
-name => 'rs12345',
-attributes=> {triples => [
[0.04, 0.64, 0.32, 'red', 'Controls'],
[0.16, 0.36, 0.48, 'blue', 'Cases'],
]
}
);
my $panel = Bio::Graphics::Panel->new(-segment=>$segment,-width=>800);
$panel->add_track($segment,-glyph=>'arrow',-double=>1,-tick=>2);
$panel->add_track([$snp1,$snp2],
-glyph => 'ternary_plot',
-height => 80,
-fgcolor => 'lightgrey',
-vertices => ['AA','GG','AG'],
-label => 1,
);
print $panel->png;
This glyph draws a light gray equilateral triangle with its base centered on the feature. The top of the equilateral triangle is equal to the specified height. To look good, please choose a height of >= 15.
Inside, the glyph will plot one or more data points using ternary plot conventions (see http://en.wikipedia.org/wiki/Ternary_plot). The data consists of a series of (A,B,C) triplets chosen such that the range of each component is [0.0,1.0] and A + B + C = 1.0. The left, right and apex of the triangle represent the proportions of A, B and C respectively. As a component approaches 1.0, it gets closer to its corresponding vertex.
The data can be represented as one or more feature tags called "triples" each in the format:
A1,B1,C1,<color>,<label> # (color and label are optional)
or as a callback specified by the option -triples, which should return a list of arrays, where each array is a triple, followed by an optional color. E.G.
sub my_calback {
my $feature = shift;
return [[0.1,0.5,0.4,'red','pt1'],[0.2,0.2,0.6,'blue','pt2'],[0.8,0.2,0.0,'green','pt4']];
}
The color, if it is missing, will be the same as the bgcolor.
In addition to the common options, the following glyph-specific options are recognized:
Option Description ------ ----------- -triples The callback to return triple data. -vertices Labels for the left,right & top vertices
Please report them.
Bio::Graphics::Panel, Bio::Graphics::Glyph, Bio::Graphics::Glyph::arrow, Bio::Graphics::Glyph::cds, Bio::Graphics::Glyph::crossbox, Bio::Graphics::Glyph::diamond, Bio::Graphics::Glyph::dna, Bio::Graphics::Glyph::dot, Bio::Graphics::Glyph::ellipse, Bio::Graphics::Glyph::extending_arrow, Bio::Graphics::Glyph::generic, Bio::Graphics::Glyph::graded_segments, Bio::Graphics::Glyph::heterogeneous_segments, Bio::Graphics::Glyph::line, Bio::Graphics::Glyph::pinsertion, Bio::Graphics::Glyph::primers, Bio::Graphics::Glyph::rndrect, Bio::Graphics::Glyph::segments, Bio::Graphics::Glyph::ruler_arrow, Bio::Graphics::Glyph::toomany, Bio::Graphics::Glyph::transcript, Bio::Graphics::Glyph::transcript2, Bio::Graphics::Glyph::translation, Bio::Graphics::Glyph::triangle, Bio::Graphics::Glyph::whiskerplot, Bio::DB::GFF, Bio::SeqI, Bio::SeqFeatureI, Bio::Das, GD
Lincoln Stein <lstein@cshl.org>.
Copyright (c) 2006 Cold Spring Harbor Laboratory
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See DISCLAIMER.txt for disclaimers of warranty.
| Bio-Graphics documentation | Contained in the Bio-Graphics distribution. |
package Bio::Graphics::Glyph::ternary_plot; # Draw ternary (triangle plots) use strict; use base qw(Bio::Graphics::Glyph::generic); use Bio::Graphics::Glyph::xyplot; use constant Sin60 =>0.866025403784439; use constant Tan60 =>1.73205080756888; sub calculate_side { my $self = shift; $self->option('height') / Sin60; } # positioning this properly is a bit tricky, because if the side of the triangle # is greater than the width of the feature, then we need to add extra left and right # padding. sub pad_left { my $self = shift; my $feature = $self->feature; my $left = $self->SUPER::pad_left; my $side = $self->calculate_side; my ($a,$b) = $self->map_pt($feature->start,$feature->stop); my $width = abs($b-$a); my $extra = $width > $side ? 0 : ($side-$width)/2; return $extra > $left ? $extra : $left; } sub pad_right { my $self = shift; my $right = $self->SUPER::pad_right; my $side = $self->calculate_side; my $feature = $self->feature; my ($a,$b) = $self->map_pt($feature->start,$feature->stop); my $width = abs($b-$a); my $extra = $width > $side ? 0 : ($side-$width)/2; return $extra > $right ? $extra : $right; } sub pad_top { my $self = shift; my $pad = $self->SUPER::pad_top; return $pad unless $self->option('vertices'); my $font = $self->image_class->gdTinyFont(); my $lh = $font->height/2; return $pad > $lh ? $pad : $lh; } sub pad_bottom { my $self = shift; my $pad = $self->SUPER::pad_bottom; return $pad unless $self->option('vertices'); my $font = $self->image_class->gdTinyFont(); my $lh = $font->height/2; return $pad > $lh ? $pad : $lh; } sub triples { my $self = shift; my $triples = $self->option('triples'); return $triples if defined $triples; my @triples = $self->feature->get_tag_values('triples'); for my $t (@triples) { next if ref $t && ref $t eq 'ARRAY'; # already in right format $t = [split /[,\w]/,$t]; } return \@triples; } sub draw_component { my $self = shift; my $gd = shift; my $fg = $self->fgcolor; my $bg = $self->bgcolor; # position the left (A) edge my ($x1,$y1,$x2,$y2) = $self->calculate_boundaries(@_); my $xmid = ($x1+$x2)/2; my $side = $self->calculate_side; my $left = $xmid - $side/2; my $right = $left + $side; my $top = $y1; my $bottom=$y2; # draw the triangle my $poly_pkg = $self->polygon_package; my $poly = $poly_pkg->new(); $poly->addPt($left,$bottom); $poly->addPt($right,$bottom); $poly->addPt($xmid,$top); $gd->polygon($poly,$fg); # draw vertex labels, if any my $fontcolor = $self->fontcolor; my $font = $self->image_class->gdTinyFont(); my $lh = $font->height; my $lw = $font->width; if (my $vertex_labels = $self->option('vertices')) { my @labels = @$vertex_labels; $gd->string($font,$left-$lw*length($labels[0]),$bottom+$lh/2,$labels[0],$fontcolor); $gd->string($font,$right,$bottom+$lh/2,$labels[1],$fontcolor); $gd->string($font,$xmid-$lw*length($labels[2])-3,$top-3,$labels[2],$fontcolor); } # get triples my $data = $self->triples; for my $triple (@$data) { my ($a,$b,$c,$color,$label) = @$triple; $color = defined $color ? $self->factory->translate_color($color) : $bg; my $x = $xmid + $side * ($b - $a)/2; my $y = $bottom - $side * ($c * Tan60)/2; draw_disc($gd,$x,$y,3,$color); if ($label) { $gd->string($font,$x+3,$y,$label,$fontcolor); } } } sub draw_disc { my ($gd,$x,$y,$pr,$color) = @_; $gd->filledArc($x,$y,$pr,$pr,0,360,$color); } 1; __END__