[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