Bio::G...:Panel(3pm)
โจ Bio::Graphics::Panel(3pm) โจ
okay bestie, this is the User Contributed Perl Documentation page for Bio::Graphics::Panel(3pm). ๐
โจ NAME โจ
Bio::Graphics::Panel โ Generate GD images of Bio::Seq objects ๐
๐ธ SYNOPSIS ๐ธ
# This script parses a GenBank or EMBL file named on the command
# line and produces a PNG rendering of it. Call it like this:
# render.pl my_file.embl | display -
use strict;
use Bio::Graphics;
use Bio::SeqIO;
my $file = shift or die "provide a sequence file as the argument";
my $io = Bio::SeqIO->new(-file=>$file) or die "could not create Bio::SeqIO";
my $seq = $io->next_seq or die "could not find a sequence in the file";
my @features = $seq->all_SeqFeatures;
# sort features by their primary tags
my %sorted_features;
for my $f (@features) {
my $tag = $f->primary_tag;
push @{$sorted_features{$tag}},$f;
}
my $panel = Bio::Graphics::Panel->new(
-length => $seq->length,
-key_style => 'between',
-width => 800,
-pad_left => 10,
-pad_right => 10,
);
$panel->add_track( arrow => Bio::SeqFeature::Generic->new(-start=>1,
-end=>$seq->length),
-bump => 0,
-double=>1,
-tick => 2);
$panel->add_track(generic => Bio::SeqFeature::Generic->new(-start=>1,
-end=>$seq->length),
-glyph => 'generic',
-bgcolor => 'blue',
-label => 1,
);
# general case
my @colors = qw(cyan orange blue purple green chartreuse magenta yellow aqua);
my $idx = 0;
for my $tag (sort keys %sorted_features) {
my $features = $sorted_features{$tag};
$panel->add_track($features,
-glyph => 'generic',
-bgcolor => $colors[$idx++ % @colors],
-fgcolor => 'black',
-font2color => 'red',
-key => "${tag}s",
-bump => +1,
-height => 8,
-label => 1,
-description => 1,
);
}
print $panel->png;
$panel->finished;
exit 0;
๐ฆ DESCRIPTION ๐ฆ
okay bestie, so the Bio::Graphics::Panel class is literally your drawing-and-formatting bestie for any object that implements the Bio::SeqFeatureI interface, including Ace::Sequence::Feature and Das::Segment::Feature objects. You can use it to draw sequence annotations, physical (contig) maps, or any other type of map where a set of discrete ranges needs to be laid out on the number line. ๐
It supports a drawing style where each type of feature gets its own discrete "track" that spans the width of the display. Every track gets its own distinctive "glyph" โ a configurable graphical representation of the feature. โจ
It also supports a more flexible style where several different feature types and their associated glyphs can share the same track. The choice of glyph is under run-time control. ๐
Semantic zooming (for example, changing the type of glyph depending on the density of features) is supported by a callback system for configuration variables. The module has built-in support for Bio::Das stylesheets, and stylesheet-driven configuration can be intermixed with semantic zooming if you want. ๐ฆ
You can add a key to the generated image using either of two key styles. One style places the key captions at the top of each track. The other style generates a graphical key at the bottom of the image. ๐
๐ note that this module depends onGD. The optional SVG output depends onGD::SVGandSVG.
The installed script glyph_help.pl provides quick help on glyphs and their options. ๐
๐ METHODS ๐
This section describes the class and object methods for Bio::Graphics::Panel. ๐
Typically you'll start by creating a new Bio::Graphics::Panel object, passing it the desired width of the image to generate and an origin and length describing the coordinate range to display. The Bio::Graphics::Panel->new() method has many configuration variables that let you control the appearance of the image. ๐
Then you'll call add_track() one or more times to add sets of related features to the picture. add_track() places a new horizontal track on the image, and it's likewise highly configurable. When you've added all the features you desire, you can call png() to convert the image into a PNG-format image, or boxes() to return coordinate information that can be used to create an imagemap. โจ
๐ CONSTRUCTORS ๐
new() is the constructor for Bio::Graphics::Panel:
$panel = Bio::Graphics::Panel->new(@options)
The new() method creates a new panel object. The options are a set of tag/value pairs as follows:
-offsetโ Base pair to place at extreme left of image, in zero-based coordinates. Default:none-lengthโ Length of sequence segment, in bp. Default:none-startโ Start of range, in 1-based coordinates. Default:none-stopโ Stop of range, in 1-based coordinates. Default:none-endโ Same as-stop. Default:none-segmentโ ABio::SeqIorDas::Segmentobject, used to derive sequence range if not otherwise specified. Default:none-widthโ Desired width of image, in pixels. Default:600-spacingโ Spacing between tracks, in pixels. Default:5-pad_topโ Additional whitespace between top of image and contents, in pixels. Default:0-pad_bottomโ Additional whitespace between top of image and bottom, in pixels. Default:0-pad_leftโ Additional whitespace between left of image and contents, in pixels. Default:0-pad_rightโ Additional whitespace between right of image and bottom, in pixels. Default:0-bgcolorโ Background color for the panel as a whole. Default:white-key_colorโ Background color for the key printed at bottom of panel (if any). Default:wheat-key_spacingโ Spacing between key glyphs in the key printed at bottom of panel (if any). Default:10-key_fontโ Font to use in printed key captions. Default:gdMediumBoldFont-key_styleโ Whether to print key at bottom of panel ("bottom"), between each track ("between"), to the left of each track ("left"), to the right of each track ("right") or not at all ("none"). Default:none-add_category_labelsโ Whether to add the "category" to the track key. The category is an optional argument that can be attached to each track. If a category is present, and this option is true, then the category will be added to the track label in parentheses. For example, if-keyis"Protein matches"and-categoryis"vertebrate", then the track will be labeled"Protein matches (vertebrate)". Default:false-auto_padโ If"left"or"right"keys are in use then settingauto_padto a true value will allow the panel to adjust its width in order to accommodate the length of the longest key. Default:true-empty_tracksโ What to do when a track is empty. Options are to suppress the track completely ("suppress"), to show just the key in"between"mode ("key"), to draw a thin grey line ("line"), or to draw a dashed line ("dashed"). Default:suppress-flipโ flip the drawing coordinates left to right, so that lower coordinates are to the right. This can be useful for drawing(-)strand features. Default:false-all_callbacksโ Whether to invoke callbacks on the automatic"track"and"group"glyphs. Default:false-gridโ Whether to draw a vertical grid in the background. Pass a scalar true value to have a grid drawn at regular intervals (corresponding to the minor ticks of the arrow glyph). Pass an array reference to draw the grid at the specified positions. Default:false-gridcolorโ Color of the grid. Default:lightcyan-gridmajorcolorโ Color of grid major intervals. Default:cyan-extend_gridโ If true, extend the grid into the pad top andpad_bottomregions. Default:false-backgroundโ An image or callback to use for the background of the image. Will be invoked before drawing the grid. Default:none-postgridโ An image or callback to use for the background of the image. Will be invoked after drawing the grid. Default:none-truecolorโ Create a truecolor (24-bit) image. Useful when working with the"image"glyph. Default:false-truetypeโ Render text using scalable vector fonts rather than bitmap fonts. Default:false-image_classโ To create output in scalable vector graphics (SVG), optionally pass the image class parameter'GD::SVG'. Defaults to using vanilla GD. See the correspondingimage_class()method below for details.-link,-title,-targetโ These options are used when creating imagemaps for display on the web. See"Creating Imagemaps".
Typically you will pass new() an object that implements the Bio::RangeI interface, providing a length() method, from which the panel will derive its scale. ๐ซถ
$panel = Bio::Graphics::Panel->new(-segment => $sequence,
-width => 800);
and if something goes sideways, new() hands you back undef โ no drama, no exceptions, just a sad little nothing. check your args bestie ๐
okay so real talk about "left" and "right" key styles ๐ซถ if you go with those, you are the one responsible for allocating enough -pad_left or -pad_right room so the labels actually show up. nobody's gonna do it for you. the width you need is the number of characters in the longest key, times the font width (that's gdMediumBoldFont by default, iykyk) plus 3 pixels of internal padding. the simplest way to figure this out: loop over all the possible track labels, find the biggest one, then compute its width with this formula:
$width = gdMediumBoldFont->width * length($longest_key) +3;
๐ธ want SVG? โ scalable vector graphics, the pretty stuff โ then pass new() the -image_class=>'GD::SVG' parameter. that makes Bio::Graphics::Panel load the optional GD::SVG module. more deets down below in the gd() and svg() methods ๐
you can tile an image onto the panel either before or after it draws the grid, no stress. just hand over the filename of your image in the -background or -postgrid options. the image file has to be PNG, JPEG, XBM or GIF, and its filename has to end in .png, .jpg, .jpeg, .xbm or .gif. that's the vibe check, no exceptions ๐
you can also pass a code ref for the -background or -postgrid option โ in that case the subroutine gets invoked at the appropriate time with the GD::Image object and the Panel object as its two arguments. then you get to use the panel methods to map base pair coordinates into pixel coordinates and do your own custom drawing, main character energy โจ for example, this code fragment draws a gray rectangle between bases 500 and 600 to indicate a "gap" in the sequence:
my $panel = Bio::Graphics::Panel->new(-segment=>$segment,
-grid=>1,
-width=>600,
-postgrid=> \&draw_gap);
sub gap_it {
my $gd = shift;
my $panel = shift;
my ($gap_start,$gap_end) = $panel->location2pixel(500,600);
my $top = $panel->top;
my $bottom = $panel->bottom;
my $gray = $panel->translate_color('gray');
$gd->filledRectangle($gap_start,$top,$gap_end,$bottom,$gray);
}
the -truetype argument turns on rendering of labels using antialiased vector fonts ๐ if it's a value of "1", labels get rendered using the default font (Verdana). pass a font name to make that font the default instead:
-truetype => 'Times New Roman',
and ngl, you can change the font on a track-by-track basis just by using a truetype font name as add_track()'s -font argument. iconic. ๐ฆ
๐ OBJECT METHODS ๐
โญ $track = $panel->add_track($glyph,$features,@options)
add_track() adds a new track to the image. that's the whole job, and it slays it.
tracks are horizontal bands that span the entire width of the panel, periodt. each track holds a bunch of graphical elements called "glyphs", and each glyph corresponds to a sequence feature.
there are a large number of glyph types, fr fr. by default each track is homogeneous on a single glyph type, but bestie you can absolutely mix several glyph types on the same track โ just provide a code reference to the -glyph argument. other options you pass to add_track() control the color and size of the glyphs, whether they're allowed to overlap, and other formatting attributes. heads up: the height of a track is determined from its contents and cannot be directly influenced. it does what it wants ๐
the first two arguments are the glyph name and an array reference containing the list of features to display. the order of the arguments is irrelevant, so both of these idioms work:
$panel->add_track(arrow => \@features);
$panel->add_track(\@features => 'arrow');
the glyph name tells it how each feature is to be rendered. a variety of glyphs are available, and the number is growing ๐ you may omit the glyph name entirely by providing a -glyph argument among @options, as described below.
currently, the following glyphs are available:
anchored_arrowโ a span with vertical bases|---------|. If one or the other end of the feature is off-screen, the base will be replaced by an arrow.arrowโ An arrow; can be unidirectional or bidirectional. It is also capable of displaying a scale with major and minor tickmarks, and can be oriented horizontally or vertically.boxโ A filled rectangle, nondirectional. Subfeatures are ignored.cdsโ Draws CDS features, using the phase information to show the reading frame usage. At high magnifications draws the protein translation.crossboxโ A box with a big "X" inside it.diamondโ A diamond, useful for point features like SNPs.dnaโ At high magnification draws the DNA sequence. At low magnifications draws the GC content.dotโ A circle, useful for point features like SNPs, stop codons, or promoter elements.ellipseโ An oval.extending_arrowโ Similar to arrow, but a dotted line indicates when the feature extends beyond the end of the canvas.genericโ A filled rectangle, nondirectional. Subfeatures are shown as rectangles that are not connected together.graded_segmentsโ Similar to segments, but the intensity of the color is proportional to the score of the feature. This is used for showing the intensity of blast hits or other alignment features.groupโ A group of related features connected by a dashed line. This is used internally by Panel.imageโ A pixmap image that will be layered on top of the graphic.heterogeneous_segmentsโ Like segments, but you can use the source field of the feature to change the color of each segment.lineโ A simple line.pinsertionโ A triangle designed to look like an insertion location (e.g. a transposon insertion).processed_transcriptโ multi-purpose representation of a spliced mRNA, including positions of UTRsprimersโ Two inward pointing arrows connected by a line. Used for STSs.redgreen_boxโ A box that changes from green->yellow->red as the score of the feature increases from 0.0 to 1.0. Useful for representing microarray results.rndrectโ A round-cornered rectangle.segmentsโ A set of filled rectangles connected by solid lines. Used for interrupted features, such as gapped alignments.ruler_arrowโ An arrow with major and minor tick marks and interval labels.toomanyโ Tries to show many features as a cloud. Not very successful.trackโ A group of related features not connected by a line. This is used internally by Panel.transcriptโ Similar to segments, but the connecting line is a "hat" shape, and the direction of transcription is indicated by a small arrow.transcript2โ Similar to transcript, but the direction of transcription is indicated by a terminal exon in the shape of an arrow.translationโ 1, 2 and 3-frame translations. At low magnifications, can be configured to show start and stop codon locations. At high magnifications, shows the multi-frame protein translation.triangleโ A triangle whose width and orientation can be altered.xyplotโ Histograms and other graphs plotted against the genome.stackedplotโ A column plot showing multiple data series across multiple categories.ternary_plotโ Ternary (triangle) plots.whiskerplotโ Box and whisker plot for statistical data
if you omit the glyph name from add_track(), the "generic" glyph is used by default, easy peasy ๐ and if you want the whole tea on a specific glyph, run perldoc on "Bio::Graphics::Glyph::glyphname" โ just swap "glyphname" for the name of the glyph you're curious about.
quick heads up: the"box"glyph is optimized for single features with no subfeatures. if you're drawing a feature like that, using"box"will be noticeably faster than"generic."โก
the @options array is a list of name/value pairs that control the attributes of the track. some options are interpreted directly by the track. others get passed down to the individual glyphs (peep "GLYPH OPTIONS"). the following options are track-specific:
-tkcolorโ Track color. Default:white-glyphโ Glyph class to use. Default:"generic"-color_seriesโ Dynamically choose bgcolor. Default:false-stylesheetโBio::Das::Stylesheetto use to generate glyph classes and options. Default:none
-tkcolor controls the background color of the track as a whole. simple as that ๐
-glyph controls the glyph type. if it's present, it supersedes the glyph name given in the first or second argument to add_track(). the value of -glyph can be a constant string, a hash reference, or a code reference:
- a constant string โ that string is used as the class name for all generated glyphs.
- a hash reference โ then the feature's
primary_tag()is used as the key to the hash, and the value (if any) is used to generate the glyph type. - a code reference โ then this callback gets passed arguments consisting of the feature and the panel object. the callback is expected to examine the feature and return a glyph name as its single result.
example:
$panel->add_track(\@exons,
-glyph => sub { my ($feature,$panel) = @_;
$feature->source_tag eq 'curated'
? 'ellipse' : 'box'; }
);
The -stylesheet argument is how you slide a Bio::Das stylesheet object into the panel. That stylesheet gets called to figure out both the glyph and the glyph options. But bestie, listen โ if you give it a stylesheet and direct options at the same time, the direct options win. They take precedence. ๐
The -color_series argument makes the track straight-up ignore the -bgcolor setting and instead hand your glyphs a whole series of contrasting colors. It's usually paired with -bump=>'overlap' to make overlapping features happen. A true value switches the color series on. You can tweak the default color series with the -color_cycle option, which is either a reference to an array of Bio::Graphics color values, or a space-delimited string of color names/values. โจ
If it works out, add_track() returns a Bio::Graphics::Glyph object. You can use that object to add more features, to control the track's appearance in finer detail, or honestly just ignore it entirely. Tracks get added in order from the top of the image down to the bottom. Wanna add to the top instead? Use unshift_track(). ๐ซถ
Adding groups of features
It's super common to add a group of features that are logically connected โ like the 5' and 3' ends of EST reads. To group features into sets that stay at the same horizontal position and bump together, pass the sets in as an anonymous array. For example:
$panel->add_track(segments => [[$abc_5,$abc_3],
[$xxx_5,$xxx_3],
[$yyy_5,$yyy_3]]
);
Typical usage looks like:
$panel->add_track( transcript => \@genes,
-fillcolor => 'green',
-fgcolor => 'black',
-bump => +1,
-height => 10,
-label => 1);
The track object is literally just a specialized type of glyph. See Bio::Graphics::Glyph for the deets on the methods it supports. ๐
METHODS, continued
$track = unshift_track($glyph,$features,@options)โunshift_track()does the same thing asadd_track(), except the new track goes to the top of the image instead of the bottom. Iconic.$track = $panel->insert_track($position,$glyph,$features,@options)โ Works likeadd_track(), but the track gets inserted at the position you name. It slots in before the indicated position, so if you want the new track at the very beginning, say position0. ๐$gd = $panel->gd([$gd])โ Thegd()method lays out the image and hands you back a GD::Image object holding it. Then you can call the GD::Image object'spng()orjpeg()methods to get the actual image data.
Optionally, you can pass gd() a preexisting GD::Image object that you wanna draw on top of. If you do that, call the width() and height() methods first to make sure the image has big enough dimensions. ๐
And if you gave new() the -image_class=>'GD::SVG' parameter, then gd() returns a GD::SVG::Image object instead. That object overrides GD::Image methods so it can generate SVG output. It behaves exactly like a GD::Image object with one exception: it implements an svg() method instead of the png() or jpeg() methods. Currently there's no direct access to underlying SVG calls, but that's subject to change in the future. ๐ฎ
$png = $panel->pngโ Thepng()method returns the image as a PNG-format drawing, skipping the whole intermediate step of giving you back a GD::Image object.$svg = $panel->svgโ Thesvg()method returns the image in an XML-ified SVG format. โจ$panel->finishedโ Bio::Graphics creates memory cycles. When you're done with the panel you should call itsfinished()method, or else you'll get memory leaks. This only really matters if you're gonna create several panels in one program, ngl.$image_class = $panel->image_classโ Theimage_class()method returns the current drawing package in use, currently one of GD or GD::SVG. It's mostly used internally to make sure calls to GD's exported methods happen in an object-oriented way, so you dodge compile time undefined string errors. Usually not needed for external use.$image_package = $panel->image_packageโ This accessor method, just likeimage_class()above, is a convenience. It returns the current image package in use, currently one of GD::Image or GD::SVG::Image. Not normally used externally.$polygon_package = $panel->polygon_packageโ This accessor method, likeimage_package()above, is another convenience. It returns the current polygon package in use, currently one of GD::Polygon or GD::SVG::Polygon. Not normally used externally, except when you're designing glyphs.$boxes = $panel->boxes@boxes = $panel->boxesโ Theboxes()method returns a list of arrayrefs holding the coordinates of each glyph. It's great for building an image map. In scalar context,boxes()returns an arrayref. In list context, it returns the list directly.
Each member of the list is an arrayref in this format:
[ $feature, $x1, $y1, $x2, $y2, $track ]
The first element is the feature object โ either an Ace::Sequence::Feature, a Das::Segment::Feature, or another Bioperl Bio::SeqFeatureI object. The coordinates are the topleft and bottomright corners of the glyph, including any space set aside for labels. The track is the Bio::Graphics::Glyph object for the track that the feature is rendered inside. ๐
$boxes = $panel->key_boxes@boxes = $panel->key_boxesโ Returns the positions of the track keys as an arrayref or a list, depending on context. Each value in the list is an arrayref in this format:
[ $key_text, $x1, $y1, $x2, $y2, $track ]
$position = $panel->track_position($track)โ After callinggd()orboxes(), you can find out the resulting Y coordinate of a track by callingtrack_position()with the value returned byadd_track()orunshift_track(). It returnsundefif you call it beforegd()orboxes(), or if you hand it an invalid track.$rotate = $panel->rotate([$new_value])โ Gets or sets the "rotate" flag. If rotate is set to true (default is false), then calls togd(),png(),gif(),boxes(), andimage_and_map()all return an image and/or imagemap that's been rotated to the right by 90 degrees. This is mostly useful for drawing karyotypes with the ideogram glyph, so you can rotate the chromosomes into the usual vertical position. ๐งฌ@pixel_coords = $panel->location2pixel(@feature_coords)โ A public routine to map feature coordinates (in base pairs) into pixel coordinates relative to the left-hand edge of the picture. If you define a-backgroundcallback, that callback may wanna invoke this routine to translate base coordinates into pixel coordinates.$left = $panel->left$right = $panel->right$top = $panel->top$bottom = $panel->bottomโ These return the pixel coordinates of the drawing area of the panel โ that is, exclusive of the padding.
GLYPH OPTIONS
Every glyph has its own specialized lil subset of options, but some are shared by all glyphs. Here's the whole squad: ๐
-keyโ Description of track for display in the track label. Default:undef.-categoryโ The category of the track for display in the track label. Default:undef.-fgcolorโ Foreground color. Default:black.-bgcolorโ Background color. Default:turquoise.-linewidthโ Width of lines drawn by glyph. Default:1.-heightโ Height of glyph. Default:10.-fontโ Glyph font. Default:gdSmallFont.-fontcolorโ Primary font color. Default:black.-font2colorโ Secondary font color. Default:turquoise.-opacityโ Value from0.0(invisible) to1.0(opaque) which controls the translucency of overlapping features. Default:1.0.-labelโ Whether to draw a label. Default:false.-descriptionโ Whether to draw a description. Default:false.-bumpโ Bump direction. Default:0.-sort_orderโ Specify layout sort order. Default:"default".-feature_limitโ Maximum number of features to display. Default:undef(unlimited).-bump_limitโ Maximum number of levels to bump. Default:undef(unlimited).-hbumppadโ Additional horizontal padding between bumped features. Default:0.-strand_arrowโ Whether to indicate strandedness. Default:undef(false).-strandedโ Synonym for-strand_arrow. Default:undef(false).-part_labelsโ Whether to label individual subparts. Default:undef(false).-part_label_mergeโ Whether to merge adjacent subparts when labeling. Default:undef(false).-connectorโ Type of connector to use to connect related features. Options are"solid,""hat","dashed","quill"and"none". Default:none.-all_callbacksโ Whether to invoke callbacks for autogenerated"track"and"group"glyphs. Default:undef.-subpart_callbacksโ Whether to invoke callbacks for subparts of the glyph. Default:false.-box_subpartsโ Return boxes around feature subparts rather than around the feature itself. Default:0.-link,-title,-targetโ These options are used when creating imagemaps for display on the web. SeeL</"Creating Imagemaps">.-filterโ Select which features to display. Must be a CODE reference.
Specifying colors
Colors can be expressed in either of two ways: as symbolic names like "cyan", as HTML-style #RRGGBB triples, and r,g,b comma-separated numbers. The symbolic names are the 140 colors defined in the Netscape/Internet Explorer color cube, and you can grab them using the Bio::Graphics::Panel->color_names() method. ๐
Transparent and semi-transparent colors can be specified using this syntax:
#RRGGBBAA - red, green, blue and alpha
r,g,b,a - red, green, blue, alpha
blue:alpha - symbolic name and alpha
rgb(r,g,b) - CSS style rgb values
rgba(r,g,b,a) - CSS style rgba values
Alpha values? Okay bestie, listen ๐ You can write them two ways:
- as GD-style integers from
0(fully opaque) to127(fully transparent) - or as CSS-style floats from
0.0(transparent) through1.0(opaque)
And there's a special-case slay: a totally transparent color can be named literally "transparent". In the rgb() and rgba() forms, red/green/blue can be percentages like rgb(100%,0%,50%) โ otherwise they're plain integers from 0 to 255. No cap. โจ
Also, -fgcolor and -bgcolor accept two extra special color names: "featureScore" and "featureRGB". Here's the tea:
"featureScore"โ Bio::Graphics peeks at every feature in the track for a defined"score"tag (or ascore()method) whose numeric value runs0-1000, then draws a grayscale from lightest (0) to darkest (1000). ๐"featureRGB"โ Bio::Graphics hunts for a tag named"RGB"and uses that as the color. ๐
Foreground color: the -fgcolor option runs the foreground color โ that's your box edges and all the little line-y bits.
Background color: the -bgcolor option runs the background used for filled boxes and other "solid" glyphs. The foreground color handles lines and strings. And -tkcolor handles the background color of the entire track. ๐ซถ
Default opacity: for truecolor images you can slap a default opacity onto both the foreground and background colors by handing over an -opacity argument. It's a CSS-style float from 0.0 to 1.0. BUT โ if a color already has an explicit alpha, the default gets ignored. Rude but fair. ๐
Track color: the -tkcolor option is what you use to set the background of the whole entire track.
Font: the -font option decides which font gets used. Here's the catch, bestie โ if the Panel was created without passing a true value to -truecolor, then the only fonts you get are GD bitmapped fonts: 'gdTinyFont', 'gdSmallFont', 'gdLargeFont', 'gdMediumBoldFont', and 'gdGiantFont'. If the Panel was created with a true value for -truecolor, then you can pass the name of any truetype font installed on the server system. Any of these formats work:
-font => 'Times New Roman', # Times font, let the system pick size
-font => 'Times New Roman-12' # Times font, 12 points
-font => 'Times New Roman-12:Italic' # Times font, 12 points italic
-font => 'Times New Roman-12:Bold' # Times font, 12 points bold
Font color: the -fontcolor option controls the color of primary text, like labels. ๐
Secondary Font color: the -font2color option controls the color of secondary text, like descriptions. ๐ธ
Labels: the -label argument is the yes/no on whether the ID of the feature gets printed next to the feature. Every single glyph accepts it. By default the label prints just above the glyph, left aligned with it. Iconic. ๐
-label can be a constant string or a code reference. The values can be any of:
0โ don't draw a label, periodt1โ calculate a label based on the primary tag of the sequence"a string"โ just use"a string"as the label- code ref โ invoke the code reference to compute the label
โ ๏ธ Known bug alert: with this naming scheme you can't label a feature with the string"1". The workaround is to use"1 "โ and yes, that's a terminal space, don't @ me.
Descriptions: the -description argument decides whether a brief description of the feature gets printed next to it. By default the description prints just below the glyph, left-aligned with it. A value of 0 suppresses it entirely. A value of 1 will "magically" look for tags of type "note" or "description" and draw them if found โ otherwise the source tag, if there is one, gets displayed. A code reference gets invoked to calculate the description on the fly. Anything else is treated as a string and used verbatim. โจ
Connectors: a glyph can contain subglyphs, recursively, like a whole little family tree. The top level glyph is the track, which contains one or more groups, which contain features, which contain subfeatures, and so on forever. By default:
- the
"group"glyph draws dotted lines between each of its subglyphs - the
"segment"glyph draws a solid line between each of its subglyphs - the
"transcript"and"transcript2"glyphs draw hat-shaped lines between their subglyphs
All other glyphs do not connect their components. You can override all this by passing a -connector option to explicitly set the connector type. Valid options are:
"hat"โ an upward-angling connector"solid"โ a straight horizontal connector"quill"โ a decorated line with small arrows indicating strandedness (like the UCSC Genome Browser uses)"dashed"โ a horizontal dashed line.
The -connector_color option controls the color of the connector, if any. ๐
Collision control: the -bump argument is the drama manager for when glyphs collide. By default they just overlap (value 0). But:
-bumpof+1โ overlapping glyphs bump downwards until there's room-bumpof-1โ overlapping glyphs bump upwards-bumpof+2or-2โ activates a very simple type of collision control where each feature occupies its own line. Chef's kiss for showing dense, nearly-full-length features like similarity hits. ๐-bumpof3or the string"fast"โ turns on a faster collision-detection algorithm that only works properly with the default"left"sort order
And finally, a bump value of "overlap" makes features overlap each other and go partially translucent (you control that translucency with the -opacity setting). Features on opposite strands will bump, but ones on the same strand will not. ๐
The bump argument can also be a code reference โ more on that below. ๐
For convenience and backwards compatibility: if you specify a -bump of 1 and you're using the default sort order, the faster algorithm gets used automatically. Nice.
If you want more horizontal whitespace between features sharing a line, that's the -hbumppad option. Positive values increase the whitespace, negative values decrease it.
Keys: the -key argument declares that the track should be shown in a key appended to the bottom of the image. That key holds a picture of a glyph plus a label describing what the glyph means, and the label is whatever you pass to -key. ๐
box_subparts: so normally, when you invoke the boxes() methods to grab the rectangles surrounding the glyphs (which you need to do for clickable imagemaps, for example), those rectangles surround the top level features. If you want the rectangles to surround subpieces of the glyph โ like the exons in a transcript โ set box_subparts to a true numeric value. The value you give controls how many levels of subfeatures the boxes descend into. Example: with the "gene" glyph, set -box_subparts to 2 and you get boxes for the whole gene (level 0), the mRNAs (level 1), and the exons (level 2). Slay. ๐ง
part_labels: if set to true, each subpart of a multipart feature gets labeled with a number starting with 1 at the 5'-most part. Perfect for counting exons. You can also pass a callback to this argument โ the part number and the total number of parts come through as arguments three and four. Like, to label exons as "exon 1", "exon 2" and so on:
-part_labels => sub {
my ($feature,undef,$partno) = @_;
return 'exon '.($partno+1);
}
Heads up: the -label argument must also be true for this to work.
part_labels_merge: if true, this changes the behavior of -part_labels so that features that abut each other with no gap between them get treated as a single feature. Super useful when you want to count the UTR and CDS segments of an exon as one unit โ and it's the default for transcript glyphs. ๐
strand_arrow: if set to true, some glyphs will show off their strandedness, usually by drawing an arrow. For this to actually work, the Bio::SeqFeature has to have a strand of +1 or -1. If the underlying feature has a strand of zero or undef, the glyph just ignores the directive entirely. ๐
sort_order: okay so by default, features are drawn with a layout based only on the position of the feature, which guarantees maximal "packing" of the glyphs when they get bumped. But sometimes it makes more sense to display the glyphs sorted by score or some other comparison โ like so the more "important" features sit nearer the top of the display, stacked above the less important ones. The -sort_order option gives you a few built-in values for changing that default sort order (which is by "left" position):
"low_score"(or"high_score") โ sorts features from lowest to highest score (or vice versa)"left"(or"default") and"right"โ sorts features by their position in the sequence"longest"(or"shortest") โ sorts the longest (or shortest) features first"strand"โ sorts features by strand:"+1"(forward), then"0"(unknown, or NA), then"-1"(reverse)
In every case, the "left" position is used to break any ties. If you want to break ties using a different field, you can string options together with a "|" character โ e.g. "strand|low_score|right" sorts features first by strand, then by score (lowest to highest), then by "right" position in the sequence. Obsessed. ๐
And finally โ the main character move โ you can provide a subroutine coderef with a $$ prototype. It receives two glyphs as arguments and should return -1, 0, or 1 (check Perl's sort() function for more info). For example, to sort a set of database search hits by bits (stored in the features' "score" fields), scaled by the log of the alignment length, with "start" position breaking any ties:
sort_order = sub ($$) {
my ($glyph1,$glyph2) = @_;
my $a = $glyph1->feature;
my $b = $glyph2->feature;
( $b->score/log($b->length)
<=>
$a->score/log($a->length) )
||
( $a->start <=> $b->start )
}
โ ๏ธ Do NOT forget to use the$$prototype exactly as shown in the example. Otherwise Bio::Graphics will quit with an exception. Also important: the arguments are subclasses of Bio::Graphics::Glyph, not the features themselves. Glyphs implement some โ but not all โ of the feature methods, so to be safe, call the two glyphs'feature()methods to convert them into the actual features. ๐ซถ
The '-always_sort' option, if true, will sort features even if bumping is turned off. This is handy when you want overlapping features to stack in a particular order. Features towards the end of the list will overlay those towards the beginning of the sort order. ๐
-feature_limitโ okay so when you set this to a non-zero value, every call to a track'sadd_feature()method keeps a lil count of how many features have been added to that track. Once that count exceeds whatever you set in-feature_limit, the new features start displacing the existing ones in a way that gives you a uniform sampling of the whole feature set. It's giving "protect me from a track that's way too big" energy. And the total number of features added? Grab it with the track'sfeature_count()method. ๐-bump_limitโ so when bumping is chosen, colliding features will ordinarily just keep moving upward or downward with no limit, and when a ton of features collide, that can lead to excessively high images (not the vibe ๐ญ). So you can cap how many levels features will bump by handing over a numericbump_limitoption. After the limit gets hit, features pile up on top of each other, usually as a band at the bottom of the track. ๐ซถ
The -filter option has to be a CODE reference, and it gets invoked once for each feature prior to rendering it. The coderef receives the feature as its single option (argument) and should return true if the feature is to be shown and false otherwise. โจ
๐ Options and Callbacks ๐
Okay bestie, this is the good part. Instead of providing a constant value to an option, you may substitute a code reference. This code reference will be called every time the panel needs to configure a glyph. The callback gets called with three arguments, like this:
sub callback {
my ($feature,$option_name,$part_no,$total_parts,$glyph) = @_;
# do something which results in $option_value being set
return $option_value;
}
The five arguments are $feature, a reference to the IO::SeqFeatureI object; $option_name, the name of the option to configure; $part_no, an integer index indicating which subpart of the feature is being drawn; $total_parts, an integer indicating the total number of subfeatures in the feature; and finally $glyph, the Glyph object itself. The latter fields are useful when you're treating the first or last subfeature differently โ like using a different color for the terminal exon of a gene. Usually you'll only need to examine the first argument, no cap. This example shows a callback examining the score() attribute of a feature (possibly a BLAST hit) and returning the color "red" for high-scoring features, and "green" for low-scoring features:
sub callback {
my $feature = shift;
if ($feature->score > 90) {
return 'red';
else {
return 'green';
}
}
The callback should return a string indicating the desired value of the option. And if you want to tell the panel "girl just use the default," return the string "*default*". ๐
The callback for -grid is slightly different because at the time this option is needed there is no glyph defined. In this case, the callback will get two arguments: the feature and the panel object:
-glyph => sub {
my ($feature,$panel) = @_;
return 'gene' if $panel->length < 10_000;
return 'box';
}
When you install a callback for a feature that contains subparts, the callback will be invoked first for the top-level feature, and then for each of its subparts (recursively). So make sure to examine the feature's type to determine whether the option is appropriate, bestie.
Also be aware that some options are only called for subfeatures. For example, when using multi-segmented features, the "bgcolor" and "fgcolor" options apply to the subfeatures and not to the whole feature; therefore the corresponding callbacks will only be invoked for the subfeatures and not for the top-level feature. To get information that applies to the top-level feature, use the glyph's parent_feature() method. This returns:
- the parent if called with no arguments or with an argument of
(1) - the parent's parent if called with an argument of
(2) - the parent's parent's parent if called with an argument of
(3) - etc.
The general way to take advantage of this feature is:
sub callback {
my ($feature,$option_name,$part_no,$total_parts,$glyph) = @_;
my $parent = $glyph->parent_feature();
# do something which results in $option_value being set
return $option_value;
}
or, more concisely:
sub callback {
my $feature = shift; # first argument
my $glyph = pop; # last argument
my $parent = $glyph->parent_feature();
# do something which results in $option_value being set
return $option_value;
}
Some glyphs deliberately disable recursion into subparts. The "track", "group", "transcript", "transcript2" and "segments" glyphs selectively disable the -bump, -label and -description options. Why? To avoid, for example, a label being attached to each exon in a transcript, or the various segments of a gapped alignment bumping each other. You can override this behavior and force your callback to be invoked by providing add_track() with a true -all_callbacks argument. In this case, you must be prepared to handle configuring options for the "group" and "track" glyphs. ๐
In particular, this means that in order to control the -bump option with a callback, you should specify -all_callbacks=>1, and turn on bumping when the callback is in the track or group glyphs.
The -subpart_callbacks options is similar, except that when this is set to true callbacks are invoked for the main glyph and its subparts. This option only affects the -label and -description options.
๐ธ ACCESSORS ๐ธ
The following accessor methods provide access to various attributes of the panel object. Called with no arguments, they each return the current value of the attribute. Called with a single argument, they set the attribute and return its previous value.
Note that in most cases you must change attributes prior to invokinggd(),png()orboxes(). These three methods all invoke an internallayout()method which places the tracks and the glyphs within them, and then caches the result. So like, change first, render after. ๐
width()โ Get/set width of panelspacing()โ Get/set spacing between trackskey_spacing()โ Get/set spacing between keyslength()โ Get/set length of segment (bp)flip()โ Get/set coordinate flippingpad_top()โ Get/set top paddingpad_left()โ Get/set left paddingpad_bottom()โ Get/set bottom paddingpad_right()โ Get/set right paddingstart()โ Get the start of the sequence (bp; read only)end()โ Get the end of the sequence (bp; read only)left()โ Get the left side of the drawing area (pixels; read only)right()โ Get the right side of the drawing area (pixels; read only)
๐ COLOR METHODS ๐
The following methods are used internally, but may be useful for those implementing new glyph types. iykyk. ๐จ
@names = Bio::Graphics::Panel->color_names
Return the symbolic names of the colors recognized by the panel object. In a scalar context, returns an array reference.
($red,$green,$blue) = Bio::Graphics::Panel->color_name_to_rgb($color)
Given a symbolic color name, returns the red, green, blue components of the color. In a scalar context, returns an array reference to the rgb triplet. Returns undef for an invalid color name.
@rgb = $panel->rgb($index)
Given a GD color index (between 0 and 140), returns the RGB triplet corresponding to this index. This method is only useful within a glyph's draw() routine, after the panel has allocated a GD::Image and is populating it.
$index = $panel->translate_color($color)
Given a color, returns the GD::Image index. The color may be symbolic, such as "turquoise", or a #RRGGBB triple, as in #F0E0A8. This method is only useful within a glyph's draw() routine, after the panel has allocated a GD::Image and is populating it.
$panel->set_pen($width,$color)
Changes the width and color of the GD drawing pen to the values indicated. This is called automatically by the GlyphFactory fgcolor() method. It returns the GD value gdBrushed, which should be used for drawing.
โจ Creating Imagemaps โจ
You may wish to use Bio::Graphics to create clickable imagemaps for display on the web. The main method for achieving this is image_and_map(). Under special circumstances you may instead wish to call either or both of create_web_image() and create_web_map(). ๐ฆ
Here is a synopsis of how to use image_and_map() in a CGI script, using CGI.pm calls to provide the HTML scaffolding:
print h2('My Genome');
my ($url,$map,$mapname) =
$panel->image_and_map(-root => '/var/www/html',
-url => '/tmpimages',
-link => 'http://www.google.com/search?q=$name');
print img({-src=>$url,-usemap=>"#$mapname"});
print $map;
We call image_and_map() with various arguments (described below) to generate a three element list consisting of the URL at which the image can be accessed, an HTML fragment containing the clickable imagemap data, and the name of the map. We print out an <image> tag that uses the URL of the map as its src attribute and the name of the map as the value of its usemap attribute. It is important to note that we must put a "#" in front of the name of the map in order to indicate that the map can be found in the same document as the <image> tag. Lastly, we print out the map itself. Slay. ๐
($url,$map,$mapname) = $panel->image_and_map(@options)
Create the image in a web-accessible directory and return its URL, its clickable imagemap, and the name of the imagemap. The following options are recognized:
-urlโ The URL to store the image at.-rootโ The directory path that should be appended to the start of-urlin order to obtain a physical directory path.-linkโ A string pattern or coderef that will be used to generate the outgoing hypertext links for the imagemap.-titleโ A string pattern or coderef that will be used to generate the"title"tags of each element in the imagemap (these appear as popup hint boxes in certain browsers).-targetโ A string pattern or coderef that will be used to generate the window target for each element. This can be used to pop up a new window when the user clicks on an element.-mapnameโ the name you want to slap on the<map>tag. Don't feel like picking one? It'll autogenerate a unique one for you, bestie. No effort required. ๐
This method hands back a three element list, okay, and those three things are: the URL where the image got written, the imagemap HTML itself, and the name of the map. Most of the time you're gonna fold all that into an HTML doc like this:
my ($url,$map,$mapname) =
$panel->image_and_map(-link=>'http://www.google.com/search?q=$name');
print qq(<img src="$url" usemap="#$mapname">),"\n";
print $map,"\n";
๐ผ๏ธ $url = $panel->create_web_image($url,$root)
Make the image, write it into the directory you get by concatenating $root and $url (so like "$root/$url"), and return $url. Simple as. โจ
๐บ๏ธ $map = $panel->create_web_map('mapname',$linkrule,$titlerule,$targetrule)
Build a clickable imagemap called mapname using the rules you give it โ those rules generate the hypertext links, the element titles, and the window targets for all the graphical elements. It returns the HTML for the map, <map> tag and all, wrapped up and ready. ๐
Okay so to actually use this method like a functioning person, you're gonna need a web server, plus an image directory sitting inside the document tree that the web server user is allowed to write to. For example, if your web server's document root lives at /var/www/html, you might wanna make a directory called tmpimages for exactly this purpose:
mkdir /var/www/html/tmpimages
chmod 1777 /var/www/html/tmpimages
The 1777 privilege lets literally anyone create files and subdirectories in that directory, but only the owner of a given file can delete it. Teamwork, but with boundaries. ๐
When you call image_and_map(), you must hand it two vital pieces of info: the URL of the image directory, and the physical location of the web server's document tree. In our example you'd call:
$panel->image_and_map(-root => '/var/www/html',-url=>'/tmpimages');
Working with virtual hosts? Then you might wanna include the hostname:portnumber part of the URL. This works just as well:
$panel->image_and_map(-root => '/var/www/html',
-url => 'http://myhost.com:8080/tmpimages');
Skip the -root argument and the method will try to figure it out from the DOCUMENT_ROOT environment variable. Skip the -url argument and the method just assumes "/tmp". It's giving resourceful. ๐
While it's running, image_and_map() will generate a unique name for the image using the Digest::MD5 module. You can grab that module on CPAN, and ngl it must be installed or image_and_map() isn't happening. The imagename will be a long hexadecimal string, something like "e7457643f12d413f20843d4030c197c6.png". Its URL will be /tmpimages/e7457643f12d413f20843d4030c197c6.png, and its physical path will be /var/www/html/tmpimages/e7457643f12d413f20843d4030c197c6.png. Cute, right? ๐ฆ
Beyond directory info, you also gotta tell image_and_map() how to create outgoing links for each graphical feature, and โ optionally โ how to create the "hover title" (that popup yellow box most modern browsers show you), plus the name of the window or frame to link to when someone clicks it.
There are three ways to specify the link destination:
- By configuring one or more tracks with a
-linkargument. - By configuring the panel with a
-linkargument. - By passing a
-linkargument in the call toimage_and_map().
The -link argument can be either a string or a coderef. Pass a string and it gets interpreted as a URL pattern containing runtime variables. These variables start with a dollar sign ($), and at run time they get swapped out for the info relating to the selected annotation. Recognized variables include:
$name The feature's name (display name)
$id The feature's id (eg, PK from a database)
$class The feature's class (group class)
$method The feature's method (same as primary tag)
$source The feature's source
$ref The name of the sequence segment (chromosome, contig)
on which this feature is located
$description The feature's description (notes)
$start The start position of this feature, relative to $ref
$end The end position of this feature, relative to $ref
$length Length of this feature
$segstart The left end of $ref displayed in the detailed view
$segend The right end of $ref displayed in the detailed view
So like, if you wanted to link every feature to a Google search on that feature's description, you'd use:
-link => 'http://www.google.com/search?q=$description'
โ ๏ธ Be sure to use single quotes around the pattern, or Perl will try to do variable interpretation before image_and_map() even gets a chance to work on it. And then it's just chaos. ๐ญ
You can also pass a code reference to -link, in which case the code gets called every single time a URL needs to be generated for the imagemap. The subroutine gets called with two arguments โ the feature and the Bio::Graphics::Panel object โ and it should return the URL to link to, or an empty string if you don't want a link at all. Here's a lil example:
-link => sub {
my ($feature,$panel) = @_;
my $type = $feature->primary_tag;
my $name = $feature->display_name;
if ($primary_tag eq 'clone') {
return "http://www.google.com/search?q=$name";
} else {
return "http://www.yahoo.com/search?p=$name";
}
The -link argument cascades, bestie. image_and_map() first looks for a -link option in the track configuration, and if it's not there, it checks the Panel configuration (the one created back during Bio::Graphics::Panel->new). If there's no -link configuration option in either of those spots, then image_and_map() uses the value of -link you passed in its argument list, if there is one.
The -title and -target options work in a similar manner to -link. -title is used to assign each feature "title" and "alt" attributes. The "title" attribute is what lots of browsers use to create a popup hints box when the mouse hovers over the feature's glyph for a preset length of time, while the "alt" attribute is used to create navigable menu items for the visually impaired. Just like with -link, you can set the title by passing either a substitution pattern or a code ref, and the -title option can be set in the track, the panel, or the method call itself โ in that order of priority. Hierarchy, but make it fair. ๐
Don't provide one? Then image_and_map() will autogenerate its own title in the form "<method> <display_name> <seqid>:start..end". She's self-sufficient. โจ
The -target option lets you specify the window or frame that clicked features will link to. By default, when the user clicks on a feature, the loaded URL just replaces the current page. You can change that by giving -target the name of a preexisting or brand new window name, so you can pull off effects like popup windows, multiple frames, popunders and the like. The value of -target follows the same rules as -title and -link, including variable substitution and the use of code refs. ๐
๐ NOTE: Every time you call image_and_map() it will generate a new image file. Images that are identical to an earlier one will reuse the same name, but ones that differ โ even by a single pixel โ will result in a whole new image being generated. If your disk space is limited, you might wanna check the images directory periodically and remove the ones that haven't been accessed recently. The following cron script will remove image files that haven't been accessed in more than 20 days:
30 2 * * * find /var/www/html/tmpimages -type f -atime +20 -exec rm {}
\;
๐ BUGS
Please report them. That's it. That's the section. ๐
๐ SEE ALSO
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::redgreen_box, 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::xyplot, Bio::Graphics::Glyph::whiskerplot, Bio::SeqI, Bio::SeqFeatureI, Bio::Das, GD GD::SVG glyph_help.pl
Like, go read those too. The whole squad. ๐ซถ
๐ AUTHOR
Lincoln Stein <lstein@cshl.org>
Copyright (c) 2001 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.
And that's the whole page, bestie!! ๐ This one's from perl v5.30.0, dated 2019-11-25, and it's the Bio::G...:Panel(3pm) man page โ you read the entire thing, which is genuinely iconic behaviour. Slay. Periodt. ๐
โจ
๐ฆ where this page comes from
- debian bookworm: libbio-graphics-perl 2.40-6 ยท Perl
- debian trixie: libbio-graphics-perl 2.40-6 ยท Perl
- ubuntu jammy: libbio-graphics-perl 2.40-6 ยท Perl
- ubuntu noble: libbio-graphics-perl 2.40-6 ยท Perl
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms