David Mertens > PDL-Graphics-Prima-0.13 > PDL::Graphics::Prima::PlotType



Annotate this POD

View/Report Bugs


PDL::Graphics::Prima::PlotType - a collection of plot types


 use PDL;
 use PDL::Graphics::Prima::Simple -sequential;
 my $x = sequence(100)/10;
 my $y = sin($x);
 # A lines+diamonds plot
     -data => ds::Pair(
         plotTypes => [
 # Dandelions:
 $x = random(10);
 $y = random(10) + 0.5;
     -data => ds::Pair(
         plotTypes => [
             ppair::Spikes(colors => cl::Green, lineWidths => 2),
             ppair::Asterisks(N_points => 11, colors => cl::White),
     backColor => cl::LightBlue,
     color => cl::White,


This module provides a number of basic plot types that you can use in a PDL::Graphics::Prima plot. As far as PDL::Graphics::Prima is concerned, there are different kinds of data that you might want to visualize, each with their own distinct plot types. The three kinds of basic data sets, as described in PDL::Graphics::Prima::DataSet, are Sets, Pairs, and Grids. Here, I will discuss the different plot types that you can apply to each of these sorts of data.

Just as you can specify properties for DataSets, you can also specify properties for individual <PlotType>s. XXX working here - discuss PlotType-wide properties (singular) and threaded (plural) properties, and ensure that they are handled as documented.

 # Specify the color for each blob:
 ppair::Blobs(colors => $my_colors)
 # Specify different line widths for each column in the histogram:
 ppair::Histogram(lineWidths => $the_widths)


Many plots are based on plotting x/y pairs

working here

of data or lines, or perhaps shaded areas. If you think of your data as a function of a single variable, like a time series, you will likely use these plot types to visualize your data.

 ppair::Lines( [thread_like => STRING,] options )

Draws the x/y data as lines, connecting each pair of points with a line segment. The behavior of the line drawing depends on what kind of threading you want. You can specify that the threading behave like lines:

 ppair::Lines(thread_like => 'lines', ...)

which is the default, or like points:

 ppair::Lines(thread_like => 'points', ...)

Threading like lines does not play well with the many point-based plotTypes. For all of those plotTypes, you can specify one property per point (like colors and lineWidths), but doing so could lead to thread index mismatch and an error in collate_min_max_wrt_many:

 Index mismatch in collate_min_max_wrt_many ...

So, if you want a line with continually changing thicknesses, or continually changing colors, you should specify that it thread like points.

However, threading like points has one major drawback, which is that it does not properly handle line styles. For example, if you wanted a dashed curve, you would specify

 ppair::Lines(..., lineStyles => lp::Dash)

When you thread like points, each line segment is treated as a seperate line. That mis-applies your dashing style. For large datasets (more than a million points), another problem with point-like threading is that it uses more memory and CPU to perform the drawing.

 ppair::Trendlines( [thread_like => STRING,] [weights => PDL,]
                 [along_dim => INTEGER,] options )

Draws linear fits to the x/y data as lines. This is a descendent of ppair::Lines, so you can specify the style of threading you want employed. You can also specify the weights that you want used for your fitting. The default is equal weights.

If you are using multidimensional data, the fit is performed along the first dimension by default. However, if you need to perform the fit along some other dimension, you can specify that with the along_dim key.

 ppair::Spikes( [x_baseline | y_baseline => PDL], options )

Draws x/y data as a collection of vertical or horizontal lines. In the default behavior, for each (x, y) data point, it draws a line from (x, 0) to (x, y). You can change the baseline by specifying either the y_baseline or x_baseline key. For example, if you specify y_baseline => 5, this will draw lines starting from (x, 5) instead of (x, 0). Specifying x_baseline => -2 will lead to horizontal lines instead of vertical lines, drawn from (-2, y) to (x, y). Finally, if you specify the undefined value, as x_baseline => undef or x_baseline => undef, the baseline will be taken as the minimum of the dataset's x or y data, respectively.

 ppair::Blobs( [radius => PDL], [xRadius => PDL],
            [yRadius => PDL], options )

Lets you draw filled ellipses with per-point x- and y- pixel radii. If you specify the key radius, it draws filled circles with the given radius. The more specific keys xRadius and yRadius override the radius key.

 ppair::Symbols( [size => PDL], [filled => PDL::Byte],
              [N_points => PDL::Byte], [orientation => PDL],
              [skip => PDL::Byte], options )

Lets you draw various geometric symbols, mostly based on regular polygons. This function inspired the creation of "pdl_symbols" in PDL::Drawing::Prima, so you should acquaint yourself with that function's terminology if you want to understand the meaning of the options here. There are also a number of derived Symbol plot types, as discussed below.

For each of your symbols, you can specify the size (radius), number of points, orientation, skip, and whether or not you want the symbol filled. These are the allowed arguments:


The symbols are drawn with a fixed size in pixels. This size is the radius of a circle that would inscribe the symbol. The default size is 5 pixels.


You can draw filled symbols or open symbols. Filled symbols do not have a border. You can specify a per-symbol value of 0 or 1, or you can specify a plotType-wide value of 0, 1, 'yes', or 'no'. The default setting is unfilled. Note that the filling takes winding number into account, so for example, a five-sided star (skip=2) will have a hollow center. This, perhaps, should be changed. I'm still debating about that.


The number of points in your symbol. Values of zero and one are interpreted as circles; values of 2 are interpreted as line segments; values of three or more are interpreted as regular polygons with the specified number of points. The number of points is an integer and must be less than 256. The default value is 5.


The angle in degrees. An orientation of zero points to the right, and the angle increases in a counterclockwise fashion. You can also use the following descriptive (case insensitive) strings:

 up    - 90 degrees
 left  - 180 degrees
 down  - 270 degrees
 right - 0 degrees, or 360 degrees

If the orientation is not specified, the polygon will be drawn 'right'. This means that 4gons are drawn as diamonds, not squares, and triangels will look tilted. (But see "Triangles" and "Squares".)


The default skip is 1 and leads to normal regular polygons, like a pentagon. However, what if you want to draw a five-pointed star instead of a pentagon? In that case, you would specify a skip of 2. This means draw a shape connecting every other point. Higher values of skip are allowed, though I am not sure how useful they would be.

In addition, there are many nicely named derivatives of ppair::Symbols. These give descriptive names to many common symbols and include:

 ppair::Sticks( [size => PDL], [orientation => PDL], options )

ppair::Sticks is a wrapper around the Symbols plotType that draws 2-point polygons, that is, sticks. You can specify the orientation and the size; you can also specify N_points and filled, but those will be ignored.

 ppair::Triangles( [size => PDL], [filled => PDL::Byte],
                [orientation => PDL], options )

ppair::Triangles is a wrapper around the Symbols plotType that draws 3-point regular polygons. It takes the same options as Symbols, except that if you specify N_points, it will be overridden by the value 3. Also, the default orientation which you can override, is 'up'.

 ppair::Squares( [size => PDL], [filled => PDL::Byte], options )

ppair::Squares is a wrapper around Symbols that draws 4-point regular polygon with an orientation that makes it look like a square (instead of a diamond). You can specify vales for N_points and orientation, but they will be ignored.

 ppair::Diamonds( [size => PDL], [filled => PDL::Byte], options )

ppair::Diamonds is just like Squares, but rotated by 45 degrees. Again, you can specify N_points and orientation, but those will be ignored.

 ppair::Stars( [size => PDL], [N_points => PDL::Byte],
            [orientation => PDL], options )

ppair::Stars creates open or filled star shapes. These only look right when you have five or more N_points, though it will plot something with four and fewer. The default orientation is 'up' but that can be overridden. The skip of two, however, cannot be overridden. You can also specify the fill state and the orientation, in addition to all the other Drawable parameters, of course.

 ppair::Asterisks( [size => PDL], [N_points => PDL::Byte],
                [orientation => PDL], options )

ppair::Asterisks creates N-sided asterisks. It does this by forcing a skip of zero that cannot be overridden. As with Stars, the default orientation is 'up' but that can be overridden. You can also specify the fill state, but that will not be used.

 ppair::Xs( [size => PDL], options )

ppair::Xs creates x shaped symbols. This sets all the Symbol arguments except the size, so although you can specify them, they will be ignored.

 ppair::Crosses( [size => PDL], options )

ppair::Crosses creates cross-shaped symbols, i.e. a + shape. As with Xs, you are free to set the size, but all other Symbol options are set for you and will be ignored if you specify them.

 ppair::Histogram( [binEdges => PDL], [baseline => SCALAR],
                [topPadding => SCALAR], options )

Draws a histogram. The bin-centers that are approximated from the x-values and the bin heights are set as the data's y-values. Both positive and negative y-values are allowed.

Histogram computes the inter-point bin edges as the mid-point between each (sequential) pair of x-values. For the first and last bins, the outer edge is the same distance from the center as the corresponding inner edge. If all of your bins have the same width, this will give you exactly what you mean. If your bins do not have identical widths, the center of the bin is guaranteed to fall somewhere within the bin boundaries, but it won't be in the "center". For greater control of where the bin boundaries are placed, you should specify the binEdges key:

 ppair::Histogram(binEdges => $bin_edges)

Note that binEdges should have one more element compared with your y-data, that is, if you have 20 heights, you'll need 21 binEdges. Unfortunately, specifying bin edges in this way does not work very well with having a function-based dataset.

Options for this plotType include:


The histogram is plotted as a series of rectangles. The height of the bottom of these rectangles is zero, but you can set a different heigh using this key.


Sets the location of the bin edges; useful if your histogram does not have identical spacing.


Histograms whose tallest column runs to the top of the graph are very confusing. This plotType includes a little bit of padding to ensure that the top of the highest histogram is plotted below the top axis when you use autoscaling. The same logic is applied to negative columns if you have any.

The histogram plotType works decently well, but it needs improvement. Don't be surprised if this plotType changes in the near future. Potential areas for improvement might be the inclusion of a Scaling property as well as filled/unfilled specifications (as in Symbols).

 ppair::ErrorBars( [x_err => PDL], [y_err => PDL]
                  [x_left_err => PDL], [x_right_err => PDL],
                  [y_upper_err => PDL], [y_lower_err => PDL],
                  [x_err_width => PDL], [y_err_width => PDL],
                  [err_width => PDL], options );

You create an error bars plotType objet with ppair::ErrorBars:

You must specify at least one sort of error bar to plot, though you can mix and match as you wish. Each error specification must be a piddle or something that can be converted to a piddle:

 x_err       - symmetric x error bars
 y_err       - symmetric y error bars
 x_left_err  - left x error bars
 x_right_err - right x error bars
 y_upper_err - upper y error bars
 y_lower_err - lower y error bars

Note that the more specific error bars will override the less specific ones, so if you provide x_err and x_left_err, the left error bars override the basic ones.

You can also specify the width of the error bars in pixels:

 err_width   - width of both error caps
 x_err_width - width of x-error caps
 y_err_width - width of y-error caps

Again, the more specific widths override the less specific ones.

Grid-based plot types

Other plots focus on using color or grayscale to visualize data that is a function of two variables. If you need to visualize the elements of a matrix, you will use these plot types. If would like to visualize an image and have already computed the RGB, HSV, or similar values, you should use pimage::Basic instead.

 pgrid::Matrix( [palette => PDL::Graphics::Prima::Palette], options )

This plot type lets you specify colors or values on a grid to visualize rasterized contour plots (as opposed to line contour plots). The default palette is a grayscale one but you can specify whichever palette you like. See PDL::Graphics::Prima::Palette. If would like to visualize an image and have already computed the RGB, HSV, or similar values, you should use pimage::Basic instead.

The x- and y-bounds of your Grid are taken from the dataset x- and y-bounds, so look into PDL::Graphics::Prima::DataSet for details.

working here - expand, give an example

Image-based Plot Types

While Grid-based plots focus on imaging data with a specified palette, Image-based plots focus on plotting data that has already been converted to a color representation. At the moment, there is only one plot type for images (and there likely will remain only one plot type unless a stroke of brilliance hits me). As it is automatically used as the default plot type by "PDL::Graphics::Prima::DataSet/ds::Image" in ds::Image, and as it does not have any configuration that cannot be specified in the data set, you probably can ignore this.


The most basic image plot type simply draws the imge with the palette provided by the plot type


Annotation Plot Types

Annotation plot types have a number of distinct features compared with other plot types. They do not have any standard data or function arguments. They tend to provide features that are decorative or annotative. Many of them support relative positioning as well. However, none of these are requirements for annotation plot types and they are the general catch-all plot type class for plot types that do not have a sensibly related dataset.

Since Annotation plot types do not presume any form of the data's structure, if you are considering creating a new plot type and cannot figure out which basic plot type to use, the Annotation base class may be the right fit.

As a base class, PDL::Graphics::Prima::PlotType::Annotation provides the following methods that may be useful for your derived classes:


This method standardizes and typo-checks position specifications. The specification can be either a string or an anonymous hash; the return value is an anonymous hash. If you pass in a bad spec, the method croaks. You call it like any other method:

 $hash = $note_obj->parse_position($spec);

A position specification is a powerful and flexible means for specifying a location on a plot widget as a combination of data values, pixel offsets, multiples of the current width of the letter M, and a percentage of the current plot portion of the widget. I think best in terms of examples, so here are a couple that hopefully illustrate how this works.

If passed as a y-specification, i.e. top or bottom specification, this will pick a location that is one M-width below the upper axis. If passed as an x-specification, this will pick a location that is one M-width to the left of the right axis.

 # input
 $spec_string = '100% - 1em';
 # output
 $spec_hash = {
     pct => 100, em => 1

Here's another one. As a y-specification, this will give a location that is five pixels below the y-value of 12. As an x-specification, this will give a location that is five pixels to the left of the x-value of 12.

 # input 
 $spec_string = '12 - 5px';
 # output
 $spec_hash = {
     raw => 12, px => -5,

Allowed postfixes in the spec string are nothing for raw data values, % for plot window percentages, em for M-widths, and px for pixel widths. The corresponding names in the output hash are raw, pct, em, and px, respectively. You can use normal floating-point number notation for the values. When you use a specification string, the values associated with each key in the returned hash will be Perl scalars.

As I already mentioned, this method accepts either a string or a hash and most of what I have documented has focused on the string parsing. If passed a hash, it simply verifies that the keys in the hash are only the above four values. It does not verify the values asssociated with the hash. This lack of data verification is why I discribe it above as a method to "typo-check" a position specification. If you create a specification hash that includes pc instead of px, this will catch it for you.

Why not verify? Your method that ultimately uses the results of the parsed position may be flexible enough to use complex data types, such as piddles or other objects, and I do not want to overly restrict the utility of this method. This can be used to great effect with "pnote::Region", for example, in which you can specify many region highlights with a single set of piddles. The drawing commands automatically thread over those piddle values. For this reason, parse_position assumes that if you specified your position by hand with a hash rather than with a specification string, you know what you are doing.

To translate the resulting hash into a pixel position on the plot widget, use compute_position.


This method takes the current axis and obtains the width of the letter M in pixels. You call it like so:

 $em_width = $note_obj->em_width($y_axis);

Note: you can obtain the x- or y-axis object calling the x and y methods, respectively, of the plot widget.


This method expects a position hash, an axis, and a drawing ratio (which is always supplied as the last argument to draw; if you're not sure what to do, use a value of 1) and computes a pixel offset for the position. The position hash must have a percentage or a raw data value or the method croaks. The returned value is a pixel position that corresponds to the desired location on the plot widget and which can be fed directly into Prima's drawing operations. If any of the values in the position hash are piddles, the result will be a piddle of positions that can be sent to the drawing operations provided by PDL::Drawing::Prima.

This method expects a position hash of the form built (or verified) by parse_position.

There are a number of annotation plot-types:

 pnote::Region( [left   => position-spec],
                [right  => position-spec],
                [bottom => position-spec],
                [top    => position-spec],
                options )

Draws a shaded region, or if any of your position specs include piddles it draws a set of shaded regions in one PDL-threaded drawing operation.

This is useful if you want to highlight certain portions of your figure with a rectangular highlight (or is it a backlight?). Each Region annotation has a position specification for the left, bottom, right, and top edges. The defaults for the left and bottom are the specification string '0%' and the defaults for the right and top are the specification string '100%'.

For more on position specifications, see the discussion of parse_position under "Annotation Plot Types".

 pnote::Box( [left   => position-spec],
             [right  => position-spec],
             [bottom => position-spec],
             [top    => position-spec],
             options )

Draws an outlied box, or if any of your position specs include piddles it draws a set of outlined boxes in one PDL-threaded drawing operation.

This is the outline equivalent of pnote::Region; see those docs for details.

For more on position specifications, see the discussion of parse_position under "Annotation Plot Types".

 pnote::Line( [x1 => position-spec],
              [y1 => position-spec],
              [x2 => position-spec],
              [y2 => position-spec],
              options )

Draws a line from (x1, y1) to (x2, y2). If any of the position specs involve piddles, it will draw a set of lines in one PDL-threaded drawing operation.

The default value for x1 and y1 is '0%' and the default value for x2 and y2 is '100%'.

For more on position specifications, see the discussion of parse_position under "Annotation Plot Types".

 pnote::Text( text-string,
              [x        => position-spec],
              [y        => position-spec],
              [clipRect => clip-spec],
              options )

Adds a text annotation to your plot. The x- and y-position specifications default to the string '50%', i.e. right in the middle of the plot. This may not be terribly useful, but hey, it's a default, right? The default clipRect specification is the string 'normal', which means that the drawing will be clipped like any other plot type to the "plot window", the region within the axes. You can also specify the string 'canvas', which expands the clip region to the entire canvas, or pass a four-element array suitable for a call to the Prima clipRect method. This added flexibility lets you to add notations anywhere on the figure, not just in the plotting region.

For more on position specifications, see the discussion of parse_position under "Annotation Plot Types".

Creating new plot types

If the supplied plot types do not match your needs, you can always make a new one: all of the code for all of these plot types is written in Perl, so it isn't too difficult. This section describes how to create custom plot types for your own needs.

To write your own plot type, you must create a class that is derived from PDL::Graphics::Prima::PlotType. (To make the discussion a bit more concrete, I am going to use the ficticious FooBars plotType, which I suppose would plot some fancy error bars.) Such a derived class would probably start out with these lines of code:

 package PDL::Graphics::Prima::PlotType::Pair::FooBars;
 use base 'PDL::Graphics::Prima::PlotType::Pair';

You must then write a custom draw function, and you can optionally overload the following functions: xmin, xmax, ymin, ymax, initialize.

You should also install a constructor under ppair::FooBars that looks like this:

 sub ppair::FooBars {

That uses the inherited PDL::Graphics::Prima::PlotType::new function, which will eventually call your class's initialize function. If your initializer expects custom arguments, you should overload the initialize function like so:

 # still in the PDL::Graphics::Prima::PlotType::Pair::FooBars package
 sub initialize {
     my $self = shift;
     # You could pull items out of @args at this point if you
     # want. To call the superclass initialization do this:
     # Here's some custom args processing. If the user did
     # not specify a curviness, default to 4:
     $self->{curviness} ||= 4;
     # Could also check that the supplied values make sense:
     croak('Curviness must be a positive integer')
         unless $self->{curviness} =~ /^\d+$/
           and $self->{curviness} > 0;

You could shove all of that construction functionality into ppair::FooBars, but then other classes would not be able to derive functionality from your undoubtedly elegant class without resorting to rather inelegant code.

Which brings me to writing plotTypes that are derived from other plotTypes. That is allowed, of course, in which case you can override whichever class functions you want. At that point, you are doing normal Perl OO programming, so it's as easy (and/or annoying) as that.


This plotType function is called when the graph needs to determine automatic minima and maxima. It is hard to explain and will require some attention in the future to flesh out its documentation. My apologies for now.

This function is called with three arguments and should always return two piddles. The return values should be of the sort described in PDL::Drawing::Prima::collate_min_max_wrt_many. The three arguments are:

plotType object (or class name)

This is whatever you created with your constructor; if you're following the example above, that would be an instance of the plotType. This passes in whatever the dataset was given for the plotType.


The axis for which we need to know the min and the max


The width into which the

If you cannot determine an extremum, or do not want to determine an extremum, you can return two piddles of size $pixel_extent filled with bad values.


This method accumulates all the properties from the plotType object together with those from the dataset into a single hash that you can submit to one of the PDL-based Prima drawing methods or (if you are using a normal Prima::Drawable graphics primitive and expect that all of the properties will be singular) the set method discussed in Prima::Object.

I use this function both in the implementations of the draw and collate_min_max_wrt_many methods, and I have never encountered a reason to override it.


Returns the widget that owns the dataType which, in turn, called this drawing operation.


Returns the dataSet that owns this plotType.


Shorthand: Returns the result of calling the dataset's get_data function.


Needs explanation and examples. This function will be called whenever the plot widget needs to redraw your plotType (window resizes, zooms, etc). It is a simple method call, and is called with the plotType object as the first argument, the canvas upon which to draw as the second argument (typically the widget, but sometimes not), and the canvas ratio if the canvas's size is not the same as the widget's size.

Now, something that I always forget to do is to convert the data values to pixel values. You do that with the widget's x- and y-axis objects with code like

 my $x_to_plot = $self->widget->x->reals_to_pixels($xs, $ratio)

If it seems like your new plot type is not plotting anything, be sure that you have properly converted the points you are trying to plot.

CallBack ^

This class lets you supply your own callback for drawing routines. In time, it may also allow you to supply your own callback for autoscaling, but that's not supported at the moment. This may seem overly high-level, but it's mostly here so that you can implement custom drawing routines, implement user-level tweaks to existing classes, and toy around with new plot types without having to write a full-blown plot class.

New Drawing Techniques

If you like the way that a class operates but want to use your own drawing routines, you can specify a base class and a drawing callback like so:

 my $smiley_plot_type = pt::CallBack(
        base_class => 'PDL::Graphics::Prima::PlotType::Pair::Blobs',
        draw => sub {
                my ($self, $canvas, $ratio) = @_;
                # Retrieve the data from the dataset:
                my ($xs, $ys) = $self->dataset->get_data_as_pixels($ratio);
                # Draw the smileys:
                $canvas->pdl_ellipses($xs, $ys, 20, 20);        # face
                $canvas->pdl_fill_ellipses($xs - 5, $ys + 4, 2, 2);     # left eye
                $canvas->pdl_fill_ellipses($xs + 5, $ys + 4, 2, 2); # right eye
                $canvas->pdl_arcs($xs, $ys, 10, 10, 200, 340); # smiling mouth
        radius => 10,   # be sure to coordinate with pdl_ellipses, above

This will use the Blobs methods for determining xmin, xmax, ymin, and ymax, but use this custom method for drawing smileys.


I have lots of things that need to happen to improve this component of the library.


Are string-properties OK, or should they be constants? (threadlike, for example) Should properties be threadable?

Documentation on Combining

I need to explain how to use multiple plotTypes together in the DESCRIPTION. (For now, the best discussion is in PDL::Graphics::Prima::Simple, in case you're looking.)

New Plot Types

There are many, many plot types that are not yet supported, but should be. Sequential plot-types that come to mind include:


Draw flow-fields with arrows of various sizes and orientations. Args: orientation, style => head, tail (ORable?), filled, length


I would really like to be able to draw error-bands around a best-fit function.


Box-and-whisker plots should be easy enough, a simple extension of error bars.

Set plot-types that come to mind include many fitting types, such as:

 gauss-cdf-fit     gauss-pdf-fit
 lorentz-cdf-fit   lorentz-pdf-fit
 p-law-cdf-fit     p-law-pdf-fit
 log-norm-cdf-fit  log-norm-pdf-fit
 exp-cdf-fit       exp-pdf-fit
 beta-cdf-fit      beta-pdf-fit

Surely there are others. In addition:


A plot type that bins Pair data in x/y bins and plots a grayscale. This would be useful for visualizing huge quantities of x/y data, when plotting with points would fail due to too many in the same place.

simpler image support

pgrid::Color, while immensely flexible, is very slow. Prima has hooks for adding images to a Drawable object, but they have not yet been incorporated into PDL::Drawing::Prima. Once that happens, fast and scalable image support will be possible.

consistent interface for caching

Many of these plottypes could speed up bounds calculations by caching certain results. I need to implement a generic interface for caching, and cache clearing.

Add support for 3d Plots

Dmitry has written a proof-of-concept widget that uses openGL and it should be possible to make many of these plotTypes work with 3d data just as well as with 2d data.


David Mertens (dcmertens.perl@gmail.com)


Here is the full list of modules in this distribution:


Defines the Plot widget for use in Prima applications


Specifies the behavior of axes (but not the scaling)


Specifies the behavior of DataSets


Defines the lm:: namespace


Specifies a collection of different color palettes


Defines the different ways to visualize your data


Encapsulates all interaction with the Term::ReadLine family of modules.


Specifies different kinds of scaling, including linear and logarithmic


Defines a number of useful functions for generating simple and not-so-simple plots


Portions of this module's code are copyright (c) 2011 The Board of Trustees at the University of Illinois.

Portions of this module's code are copyright (c) 2011-2013 Northwestern University.

This module's documentation are copyright (c) 2011-2013 David Mertens.

All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

syntax highlighting: