AcePerl
view release on metacpan or search on metacpan
Ace/Graphics/Track.pm view on Meta::CPAN
sub set_scale {
my $self = shift;
my ($bp,$desired_width) = @_;
$desired_width ||= 512;
$self->scale($desired_width/$bp);
$self->width($desired_width);
}
# return the glyph class
sub factory {
my $self = shift;
my $g = $self->{factory};
$self->{factory} = shift if @_;
$g;
}
# return boxes for each of the glyphs
# will be an array of four-element [$feature,l,t,r,b] arrays
sub boxes {
my $self = shift;
my ($left,$top) = @_;
$top += 0; $left += 0;
my @result;
my $glyphs = $self->layout;
for my $g (@$glyphs) {
my ($l,$t,$r,$b) = $g->box;
push @result,[$g->feature,$left+$l,$top+$t,$left+$r,$top+$b];
}
return wantarray ? @result : \@result;
}
# synthesize a key glyph
sub keyglyph {
my $self = shift;
my $scale = 1/$self->scale; # base pairs/pixel
# two segments, at pixels 0->50, 60->80
my $offset = $self->offset;
my $feature = Ace::Graphics::Fk->new(-segments=>[ [ 0*$scale +$offset,50*$scale+$offset],
[60*$scale+$offset, 80*$scale+$offset]
],
-name => $self->option('key'),
-strand => '+1');
my $factory = $self->factory->clone;
$factory->scale($self->scale);
$factory->width($self->width);
$factory->option(label=>1); # turn on labels
return $factory->glyph($feature);
}
# draw glyphs onto a GD object at the indicated position
sub draw {
my $self = shift;
my ($gd,$left,$top) = @_;
$top += 0; $left += 0;
my $glyphs = $self->layout;
# draw background
my $bgcolor = $self->factory->bgcolor;
# $gd->filledRectangle($left,$top,$left+$self->width,$top+$self->height,$bgcolor);
if (my $label = $self->factory->option('track_label')) {
my $font = $self->factory->font;
my $y = $top + ($self->height-$font->height)/2;
my $x = $left - length($label) * $font->width;
$gd->string($font,$x,$y,$label,$self->factory->fontcolor);
}
$_->draw($gd,$left,$top) foreach @$glyphs;
if ($self->factory->option('connectgroups')) {
$_->draw($gd,$left,$top) foreach @{$self->{groups}};
}
}
# lay out -- this uses the infamous bump algorithm
sub layout {
my $self = shift;
my $force = shift || 0;
return $self->{glyphs} if $self->{glyphs} && !$force;
my $f = $self->{features};
my $factory = $self->factory;
$factory->scale($self->scale); # set the horizontal scale
$factory->width($self->width);
# create singleton glyphs
my @singletons = map { $factory->glyph($_) } @$f;
# create linked groups of glyphs
my @groups;
if (my $groups = $self->{group_ids}) {
my $groupfactory = Ace::Graphics::GlyphFactory->new('group');
for my $g (values %$groups) {
my @g = map { $factory->glyph($_) } @$g;
push @groups,$groupfactory->glyph(\@g);
}
}
return $self->{glyphs} = [] unless @singletons || @groups;
# run the bumper on the groups
$self->_bump([@singletons,@groups]) if $self->bump;
# merge the singletons and groups and sort them horizontally
my @glyphs = sort {$a->left <=> $b->left } @singletons,map {$_->members} @groups;
# If -1 bumping was allowed, then normalize so that the top glyph is at zero
my ($topmost) = sort {$a->top <=> $b->top} @glyphs;
my $offset = 0 - $topmost->top;
$_->move(0,$offset) foreach @glyphs;
$self->{groups} = \@groups;
return $self->{glyphs} = \@glyphs;
}
# bumper - glyphs already sorted left to right
sub _bump {
my $self = shift;
( run in 0.615 second using v1.01-cache-2.11-cpan-d8267643d1d )