[Bioperl-l] bioperl graphics
Jonathan Crabtree
crabtree at tigr.org
Wed Feb 25 11:46:29 EST 2004
Haibo-
hz5 at njit.edu wrote:
>Is there any way to render 2 Bio::Graphics::Panel into one png image? because I
>want 2 different arrows with different labeled coordinates on the same image
>and align to the left, but one Panel can only have one coordinates system.
>
>
The answer is yes, with a couple of caveats. The first is that you will
have to take care of the layout of the individual Panel-generated
images. If you're left-justifying everything then this should be easy
enough. The second is that I would recommend making a one-line change
to Bio/Graphics/Panel.pm, to prevent the package from trying to allocate
the same set of colors twice (when you reuse the same GD object to draw
the two different parts of the image.) Search for the following piece
of code in Panel.pm (at line 411 in bioperl-1.4, I think):
for my $name ('white','black',keys %COLORS) {
my $idx = $gd->colorAllocate(@{$COLORS{$name}});
$translation_table{$name} = $idx;
}
Change "colorAllocate" to "colorResolve"; this should have no effect on
any existing Bio::Graphics code (AFAIK) and will allow you to do your
two (or three or four)-Panel trick. (As an aside, I'd like to lobby for
this one-line change to be made in a future version of
Bio::Graphics::Panel, for precisely this reason.) In any case, once
you've made that change and reinstalled your copy of Bioperl, here is a
rough outline of what you need to do:
1. Set up your individual Bio::Graphics::Panel objects (e.g. $p1, $p2,
$p3, etc.) as desired to draw your images, but do *not* call the gd
method on any of them yet.
2. Create a GD::Image object big enough to hold the images that will be
drawn by $p1, $p2, $p3, etc.:
my $gdImg = GD::Image->new($fullWidth, $fullHeight);
(Note: use $p1->width(), $p1->height(), etc., to determine what
$fullWidth and $fullHeight should be, based on your desired Panel layout
algorithm.)
4. Use a "dummy" Bio::Graphics::Panel object to allocate all your colors
(this is an optional step; I do this because my code does some drawing
that isn't handled by Bio::Graphics::Panel, and want to make sure that
the palette has been allocated before I start):
my $dummyPanel = Bio::Graphics::Panel->new(-length => 100, -offset
=> 0, -width => $fullWidth);
$dummyPanel->gd($gdImg); # forces color allocation
5. Draw the individual panels and generate your png image:
$p1->gd($gdImg);
$p2->gd($gdImg);
my $pngData = $gdImg->png();
I've glossed over some of the details here, for example the fact that
you may need to know the value of $p1->height() before you can
initialize $p2, but that's the basic idea. I've been using this method
to generate some comparative sequence displays and while it's definitely
a bit of a hack, it works well in practice. You can also do the same
thing with a GD::SVG::Image if you'd like to generate SVG output. Good
luck,
Jonathan
More information about the Bioperl-l
mailing list