Bio-Graphics
view release on metacpan or search on metacpan
lib/Bio/Graphics/Glyph/xyplot.pm view on Meta::CPAN
my @parts = $self->parts;
return $self->SUPER::draw(@_) unless @parts > 0;
$self->panel->startGroup($gd);
my ($min_score,$max_score) = $self->minmax(\@parts);
my $side = $self->_determine_side();
# if a scale is called for, then we adjust the max and min to be even
# multiples of a power of 10.
if ($side) {
$max_score = max10($max_score);
$min_score = min10($min_score);
}
my $height = $bottom - $top;
my $scale = $max_score > $min_score ? $height/($max_score-$min_score)
: 1;
my $x = $left;
my $y = $top + $self->pad_top;
# position of "0" on the scale
my $y_origin = $min_score <= 0 ? $bottom - (0 - $min_score) * $scale : $bottom;
$y_origin = $top if $max_score < 0;
my $clip_ok = $self->option('clip');
$self->{_clip_ok} = $clip_ok;
$self->{_scale} = $scale;
$self->{_min_score} = $min_score;
$self->{_max_score} = $max_score;
$self->{_top} = $top;
$self->{_bottom} = $bottom;
# now seed all the parts with the information they need to draw their positions
foreach (@parts) {
my $s = $_->score;
$_->{_y_position} = $self->score2position($s);
warn "y_position = $_->{_y_position}" if DEBUG;
}
my $type = $self->option('graph_type') || $self->option('graphtype') || 'boxes';
my (@draw_methods) = $self->lookup_draw_method($type);
$self->throw("Invalid graph type '$type'") unless @draw_methods;
$self->panel->startGroup($gd);
$self->_draw_grid($gd,$scale,$min_score,$max_score,$dx,$dy,$y_origin);
$self->panel->endGroup($gd);
for my $draw_method (@draw_methods) {
$self->$draw_method($gd,$dx,$dy,$y_origin);
}
$self->panel->startGroup($gd);
$self->_draw_scale($gd,$scale,$min_score,$max_score,$dx,$dy,$y_origin);
$self->panel->endGroup($gd);
$self->draw_label(@_) if $self->option('label') or $self->record_label_positions;
$self->draw_description(@_) if $self->option('description');
$self->draw_legend(@_) if $self->option('overlay');
$self->panel->endGroup($gd);
}
sub lookup_draw_method {
my $self = shift;
my $type = shift;
return '_draw_boxes' if $type eq 'histogram'; # same thing
return '_draw_boxes' if $type eq 'boxes';
return qw(_draw_line _draw_points) if $type eq 'linepoints';
return '_draw_line' if $type eq 'line';
return '_draw_points' if $type eq 'points';
return;
}
sub normalize_track {
my $self = shift;
my @glyphs_in_track = @_;
my ($global_min,$global_max);
for my $g (@glyphs_in_track) {
my ($min_score,$max_score) = $g->minmax($g->get_parts);
$global_min = $min_score if !defined $global_min || $min_score < $global_min;
$global_max = $max_score if !defined $global_max || $max_score > $global_max;
}
# note that configure applies to the whole track
$glyphs_in_track[0]->configure(-min_score => $global_min);
$glyphs_in_track[0]->configure(-max_score => $global_max);
}
sub get_parts {
my $self = shift;
my @parts = $self->parts;
return \@parts;
}
sub score {
my $self = shift;
my $s = $self->option('score');
return $s if defined $s;
return eval { $self->feature->score };
}
sub score2position {
my $self = shift;
my $score = shift;
return undef unless defined $score;
if ($self->{_clip_ok} && $score < $self->{_min_score}) {
return $self->{_bottom};
}
elsif ($self->{_clip_ok} && $score > $self->{_max_score}) {
return $self->{_top};
}
else {
warn "score = $score, _top = $self->{_top}, _bottom = $self->{_bottom}, max = $self->{_max_score}, min=$self->{_min_score}" if DEBUG;
my $position = ($score-$self->{_min_score}) * $self->{_scale};
lib/Bio/Graphics/Glyph/xyplot.pm view on Meta::CPAN
($feature->segments)[2]->score(25);
my $factory = $self->factory->clone;
$factory->set_option(label => 1);
$factory->set_option(bump => 0);
$factory->set_option(connector => 'solid');
my $glyph = $factory->make_glyph(0,$feature);
return $glyph;
}
sub symbols {
my $self = shift;
return \%SYMBOLS;
}
sub draw_label {
my $self = shift;
my ($gd,$left,$top,$partno,$total_parts) = @_;
my $label = $self->label or return;
if ($self->bump eq 'overlap') {
my $x = $self->left + $left + $self->pad_left;
$x = $self->panel->left + 1 if $x <= $self->panel->left;
$x += ($self->panel->glyph_scratch||0);
my $font = $self->labelfont;
my $width = $self->string_width($label,$font)+4;
my $height= $self->string_height('',$font);
unless ($self->record_label_positions) {
$gd->filledRectangle($x,$top,$x+$width+6,$top+$height,$self->bgcolor);
local $self->{default_opacity} = 1;
$gd->string($font,$x+3,$top,$label,$self->contrasting_label_color($gd,$self->bgcolor));
}
$self->panel->glyph_scratch($self->panel->glyph_scratch + $width);
$self->panel->add_key_box($self,$label,$x,$top) if $self->record_label_positions;
} elsif ($self->label_position eq 'left') {
my $font = $self->labelfont;
my $x = $self->left + $left - $self->string_width($label,$font) - $self->extra_label_pad;
my $y = $self->{top} + $top;
$self->render_label($gd,
$font,
$x,
$y,
$label);
} else {
$self->SUPER::draw_label(@_);
}
}
sub contrasting_label_color {
my $self = shift;
my ($gd,$bgcolor) = @_;
my ($r,$g,$b) = $gd->rgb($bgcolor);
my $avg = ($r+$g+$b)/3;
return $self->translate_color($avg > 128 ? 'black' : 'white');
}
sub draw_legend {
my $self = shift;
my ($gd,$left,$top,$partno,$total_parts) = @_;
return if $self->bump eq 'overlap';
my $color = $self->option('fgcolor');
my $name = $self->feature->{name};
my $label = "<a id=\"legend_$name\" target=\"_blank\" href=\"#\"> <font color=\'$color\';\">" . $name . "</font></a>" or return;
my $font = $self->labelfont;
my $x = $self->left + $left - $self->string_width($label,$font) - $self->extra_label_pad;
my $y = $self->{top} + $top;
my $is_legend = 1;
$self->render_label($gd,
$font,
$x,
$y,
$label,
$is_legend);
}
1;
__END__
=head1 NAME
Bio::Graphics::Glyph::xyplot - The xyplot glyph
=head1 SYNOPSIS
See L<Bio::Graphics::Panel> and L<Bio::Graphics::Glyph>.
=head1 DESCRIPTION
This glyph is used for drawing features that have a position on the
genome and a numeric value. It can be used to represent gene
prediction scores, motif-calling scores, percent similarity,
microarray intensities, or other features that require a line plot.
The X axis represents the position on the genome, as per all other
glyphs. The Y axis represents the score. Options allow you to set
the height of the glyph, the maximum and minimum scores, the color of
the line and axis, and the symbol to draw.
The plot is designed to work on a single feature group that contains
subfeatures. It is the subfeatures that carry the score
information. The best way to arrange for this is to create an
aggregator for the feature. We'll take as an example a histogram of
repeat density in which interval are spaced every megabase and the
score indicates the number of repeats in the interval; we'll assume
that the database has been loaded in in such a way that each interval
is a distinct feature with the method name "density" and the source
name "repeat". Furthermore, all the repeat features are grouped
together into a single group (the name of the group is irrelevant).
If you are using Bio::DB::GFF and Bio::Graphics directly, the sequence
of events would look like this:
my $agg = Bio::DB::GFF::Aggregator->new(-method => 'repeat_density',
-sub_parts => 'density:repeat');
my $db = Bio::DB::GFF->new(-dsn=>'my_database',
-aggregators => $agg);
my $segment = $db->segment('Chr1');
my @features = $segment->features('repeat_density');
my $panel = Bio::Graphics::Panel->new(-pad_left=>40,-pad_right=>40);
$panel->add_track(\@features,
-glyph => 'xyplot',
-graph_type=>'points',
-point_symbol=>'disc',
-point_radius=>4,
-scale=>'both',
-height=>200,
);
If you are using Generic Genome Browser, you will add this to the
configuration file:
aggregators = repeat_density{density:repeat}
( run in 0.988 second using v1.01-cache-2.11-cpan-39bf76dae61 )