[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]
LINUX GAZETTE
...making Linux just a little more fun!
Exploring Perl Modules - Part2: Creating Charts with GD::Graph
By Pradeep Padala

Introduction

If you have read my previous article on GD, you might have noticed that creating charts with the GD module is cumbersome. (That article also contains some general information about loading Perl modules.) Martien Verbruggen has created the GD::Graph module that allows easy creation of charts. This module has useful functions to create various types of charts such as bar charts, pie charts, line charts etc... The module is very useful in creating dynamic charts depicting network statistics, web page access statistics etc...

In this article, I will describe a general way of using the module and also show a few examples of creating various charts.

Typical Way of Using the GD::Graph Module

A perl script using GD::Graph to create charts typically contains the following things:

A Simple Example

Let's draw a simple chart following above steps. This script uses CGI to output the image on to a web page.
[Text version of this listing.]

#!/usr/local/bin/perl -w
# Change above line to point to your perl binary

use CGI ':standard';
use GD::Graph::bars;
use strict;

# Both the arrays should same number of entries.
my @data = (["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
             "Sep", "Oct", "Nov", "Dec"],
            [23, 5, 2, 20, 11, 33, 7, 31, 77, 18, 65, 52]);

my $mygraph = GD::Graph::bars->new(500, 300);
$mygraph->set(
    x_label     => 'Month',
    y_label     => 'Number of Hits',
    title       => 'Number of Hits in Each Month in 2002',
) or warn $mygraph->error;

my $myimage = $mygraph->plot(\@data) or die $mygraph->error;

print "Content-type: image/png\n\n";
print $myimage->png;

The output of the program can be seen here

The above program is pretty much self-explanatory. The @data variable is an array of arrays. The first array represents the labels on X-axis and all the subsequent arrays present different datasets.

Tweaking the options

As you can see, the graph produced by above program is quite bland and simple. We can tweak various options to produce better looking and customized graphs. There are a multitude of options to control the various aspects of the graph. Options are divided into two types: the options common to all types of graphs, and the options specific to each type of graph.

Options can be set while creating the graph or with

    $mygraph->set(attrib1 => value1, attrib2 => value2, ...);

Let us write a script setting legends, a grid and few options.
[Text version of this listing.]

#!/usr/local/bin/perl -w
# Change above line to point to your perl binary

use CGI ':standard';
use GD::Graph::bars;
use strict;

# Both the arrays should same number of entries.
my @data = (['Fall 01', 'Spr 01', 'Fall 02', 'Spr 02' ],
            [80, 90, 85, 75],
            [76, 55, 75, 95],
            [66, 58, 92, 83]);

my $mygraph = GD::Graph::bars->new(500, 300);
$mygraph->set(
    x_label     => 'Semester',
    y_label     => 'Marks',
    title       => 'Grade report for a student',
    # Draw bars with width 3 pixels
    bar_width   => 3,
    # Sepearte the bars with 4 pixels
    bar_spacing => 4,
    # Show the grid
    long_ticks  => 1,
    # Show values on top of each bar
    show_values => 1,
) or warn $mygraph->error;

$mygraph->set_legend_font(GD::gdMediumBoldFont);
$mygraph->set_legend('Exam 1', 'Exam 2', 'Exam 3');
my $myimage = $mygraph->plot(\@data) or die $mygraph->error;

print "Content-type: image/png\n\n";
print $myimage->png;

The output of above program can be seen here

Graph with a logo in the background

Again as you can see, GD::Graph provides a flexible to way to create customized graphs. Let's prepare another chart with a logo.

Text version of the file can be found here
#!/usr/local/bin/perl -w
# Change above line to point to your perl binary

use CGI ':standard';
use lib '/cise/homes/ppadala/mydepot/lib/perl5/site_perl';
use GD::Graph::bars;
use strict;

# Both the arrays should same number of entries.
my @data = (['Fall 01', 'Spr 01', 'Fall 02', 'Spr 02' ],
            [80, 90, 85, 75],
            [76, 55, 75, 95],
            [66, 58, 92, 83]);

my $mygraph = GD::Graph::bars->new(500, 300);
$mygraph->set(
    x_label     => 'Semester',
    y_label     => 'Marks',
    title       => 'Grade report for a student',
    # Draw bars with width 3 pixels
    bar_width   => 3,
    # Sepearte the bars with 4 pixels
    bar_spacing => 4,
    # Show the grid
    long_ticks  => 1,
    # Show values on top of each bar
    show_values => 1,
) or warn $mygraph->error;

$mygraph->set(logo => 'lglogo.png');
$mygraph->set(logo_resize => 0.5);
$mygraph->set(logo_position => 'LL');
$mygraph->set_legend_font(GD::gdMediumBoldFont);
$mygraph->set_legend('Exam 1', 'Exam 2', 'Exam 3');
my $myimage = $mygraph->plot(\@data) or die $mygraph->error;
print "Content-type: image/png\n\n";
print $myimage->png;

Output of above program can be seen here

Here's the Linux Gazette logo I used. It's in PNG format. The current version of GD::Graph doesn't recognize any image types besides GIF (although it can write PNG, go figure). I submitted a patch to fix this. You can either apply the patch or use an older version of GD or GD::Graph.

Graph with Lines

Some information can be better presented with line graphs. Here's an example showing a line graph.
[Text version of this listing.]

#!/usr/local/bin/perl -w
# Change above line to point to your perl binary

use CGI ':standard';
use GD::Graph::lines;
use strict;

# Both the arrays should same number of entries.
my @data = (['Fall 01', 'Spr 01', 'Fall 02', 'Spr 02' ],
            [80, 90, 85, 75],
            [76, 55, 75, 95],
            [66, 58, 92, 83]);

my $mygraph = GD::Graph::lines->new(600, 300);
$mygraph->set(
    x_label     => 'Semester',
    y_label     => 'Marks',
    title       => 'Grade report for a student',
    # Draw datasets in 'solid', 'dashed' and 'dotted-dashed' lines
    line_types  => [1, 2, 4],
    # Set the thickness of line
    line_width  => 2,
    # Set colors for datasets
    dclrs       => ['blue', 'green', 'cyan'],
) or warn $mygraph->error;

$mygraph->set_legend_font(GD::gdMediumBoldFont);
$mygraph->set_legend('Exam 1', 'Exam 2', 'Exam 3');
my $myimage = $mygraph->plot(\@data) or die $mygraph->error;

print "Content-type: image/png\n\n";
print $myimage->png;

Output of above program can be seen here

Here I have used GD::Graph::lines to create the graph handle. But for this change, the program follows the same pattern for creating graphs.

A Pie Graph

Similarly we can create a pie chart.
[Text version of this listing.]

#!/usr/local/bin/perl -w
# Change above line to point to your perl binary

use CGI ':standard';
use GD::Graph::pie;
use strict;

# Both the arrays should same number of entries.
my @data = (['Project', 'HW1', 'HW2', 'HW3', 'MidTerm', 'Final'],
            [25, 6, 7, 2, 25, 35]);

my $mygraph = GD::Graph::pie->new(300, 300);
$mygraph->set(
    title       => 'Grading Policy for COP5555 course',
    '3d'          => 1,
) or warn $mygraph->error;

$mygraph->set_value_font(GD::gdMediumBoldFont);
my $myimage = $mygraph->plot(\@data) or die $mygraph->error;

print "Content-type: image/png\n\n";
print $myimage->png;

The output pie chart can be seen here

The '3d' option draws the pie chart in 3d.

An Area Graph

An area graph shows the data as area under a line.
[Text version of this listing.]

#!/usr/local/bin/perl -w
# Change above line to point to your perl binary

use CGI ':standard';
use GD::Graph::area;
use strict;

# Both the arrays should same number of entries.
my @data = (["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
             "Sep", "Oct", "Nov", "Dec"],
            [23, 5, 2, 20, 11, 33, 7, 31, 77, 18, 65, 52]);

my $mygraph = GD::Graph::area->new(500, 300);
$mygraph->set(
    x_label     => 'Month',
    y_label     => 'Number of Hits',
    title       => 'Number of Hits in Each Month in 2002',
) or warn $mygraph->error;

my $myimage = $mygraph->plot(\@data) or die $mygraph->error;

print "Content-type: image/png\n\n";
print $myimage->png;

Output image can be seen here

Conclusion

The GD::Graph module provides a powerful and flexible way to create charts. It's very useful for creating graphs dynamically for serving on web.

I hope you have enjoyed reading this article. Next month, we will have a look at the PerlMagic Module.


Copyright © 2002, Pradeep Padala. Copying license http://www.linuxgazette.net/copying.html
Published in Issue 83 of Linux Gazette, October 2002

[ Prev ][ Table of Contents ][ Front Page ][ Talkback ][ FAQ ][ Next ]