2024 π Daylatest newsbuy art
Embrace me, surround me as the rush comes.Motorcycledrift deeper into the soundmore quotes
very clickable
data + munging

The Perl Journal

Volumes 1–6 (1996–2002)

Code tarballs available for issues 1–21.

I reformatted the CD-ROM contents. Some things may still be a little wonky — oh, why hello there <FONT> tag. Syntax highlighting is iffy. Please report any glaring issues.

The Perl Journal
#18
Summer 2000
vol 5
num 2
Jeremy Wadsack (2000) GDGraph3d. The Perl Journal, vol 5(2), issue #18, Summer 2000.

GDGraph3d

Jeremy Wadsack


  Packages:  
GDGraph3d, GD::Graph, GD, GDTextUtil, PDL ......... CPAN
zlib ............ ftp://ftp.freesoftware.com/pub/infozip/zlib/zlib.tar.gz
libpng .................................... ftp://ftp.cdrom.com/pub/png/src/
lttf ...................... https://freetype.sourceforge.net/download.html
jpeg-6b ....................................... ftp://ftp.uu.net/graphics/jpeg/
libgd .................................. ftp://ftp.boutell.com/pub/boutell/gd/

When it comes to understanding large amounts of data, we humans have two stages of interpretation. First, we analyze the data, organizing it in myriad ways to find the hidden relationships, quantities, and trends that deliver meaning to our world. Second, we present it somehow, often by displaying it visually. With graphs and charts we can visualize trends, understand relationships, and compare quantities at a glance.

Figure 1: Sample GDGraph3d output.
Sample GDGraph3d output

Over the course of the last year I developed the Perl package GDGraph3d as part of a statistics presentation tool I work on for analyzing the huge amounts of data available to and generated by web servers. Report Magic for Analog, our companion presentation package for the Analog web site statistics analysis tool, uses GDGraph3d to present Analog's log file analyses in a friendly manner with graphs like Figure 1.

GDGraph3d is an extension to Martien Verbruggen's GD::Graph package. GD::Graph draws only two-dimensional images (except for the 3d option on pie charts), but provides the basis for data management, labeling, legends and other routine graph operations that are common to both packages.

Using GDGraph3d

In order to use GDGraph3d, you will need to install several packages: at a minimum, the GD::Graph and GD Perl modules, and the libgd library. Fortunately for Windows and Mac users, GD and the libgd library are included in ActivePerl and MacPerl. If you have ActivePerl, you can use the PPM or VPM tool to acquire the latest version of GD. With PPM you can simply use this command:

  > ppm install GD

On Unix (and Unix-like) systems, the installation is a lot more complex. libgd is a C library that itself depends on the libpng and zlib libraries. If you want TrueType font support (recommended if you're using a character set other than Latin-1 or Latin-2) you'll need FreeType's lttf. In order to build GD on top of libgd, you will also need to install the jpeg-6b library. Complete details for installing this are listed on the libgd website (https://www.boutell.com/gd/); a summary is available in the sidebar, Installing GD.

Installing GD::Graph and GDGraph3d should be fairly simple. Both are located on CPAN and can be found through the CPAN search engine at https://search.cpan.org. You'll also need to install the GDTextUtil package, which you can find there as well.

Once you have all the proper modules and libraries installed, it's time to write some code and make some pictures. Listing 1 contains a simple script to generate the graph in Figure 2. We'll go through the script line by line.

Figure 2: The output of Listing 1.
output of Listing 1 Listing 1: A sample GDGraph3D program.

The first line tells Perl which graph module you want to use. With both GD::Graph and GDGraph3d, you use the type of graph you wish to make. So in this instance, since we are making a line graph, we use GD::Graph::lines3d.

The next set of lines creates a data structure containing the data to be graphed. GDGraph3d uses an array of an array of values. The first row holds the labels for the x -axis, and the subsequent rows are the data for each line of the graph. In this example, we've coded the values by hand, but in a real application, you'd get these from a database, an external file, or some other source. Check out the GD::Graph::Data class for methods that make it easy to read data from delimited text files and DBI sources.

On line 14 we create a new graph "lines3d" object. GDGraph3d objects cannot be reused - you create a new one for each set of data you wish to plot.

Lines 17 to 21 set several self-explanatory options for the graph. GDGraph3d supports all the options that GD::Graph does (and there are many), as well as a few options specifically for three-dimensional output (like the z-directional depth of the lines). We'll go into more detail below about using options to improve the look of the graph.

Line 24 tells GDGraph3d to plot the data to an image. The plot method returns a reference to a GD image object. If you wish, you can further process this image with additional GD methods.

Because the GD library can output in different formats (GIF, PNG, JPEG, and so on) GDGraph3d offers a method to return the default format. For new installations, this call will return png. If you happen to have an old version of GD and libgd on your system, this returns the patent-infringing gif.

Now, using the format that GDGraph3d found for us, we can write the contents of the image to a file on the system: in our example, either sample.png or sample.gif. The binmode call is included for systems that make a distinction between binary and text files (like Windows). On other systems, this has no effect.

GD::Graph and GDGraph3d allow you to adjust the graph in many ways. We'll start by setting some colors. GDGraph3d has 29 predefined colors (white, lgray, gray, dgray, black, lblue, blue, dblue, gold, lyellow, yellow, dyellow, lgreen, green, dgreen, lred, red, dred, lpurple, purple, dpurple, lorange, orange, pink, dpink, marine, cyan, lbrown, and dbrown) or can accept any RGB color defined with HTML syntax. To set the colors, we'll add some key/value pairs to the $graph->set() statement so that it looks like this:

 # Set some labels
 $graph->set( 
     x_label  => 'Month, 1999',
     y_label  => 'Revenue ($US)',
       title  => 'Monthly revenue for 1999',
       dclrs  => ['#9999CC', '#CCCC66', '#339900', 
	   		'#990000', '#FFCC33'],
      boxclr  => '#FFFFCC',
  long_ticks  => 1,
 );

dclrs sets a list of colors to use for each data set, boxclr sets the color to use in the background of the plot, and setting long_ticks to a true value tells GDGraph3d to draw a grid on the background (connecting all the ticks). See Figure 3 for the results.

Figure 3: Choosing colors.
Choosing colors

Now let's work on the fonts. GDGraph3d uses GD's font mechanisms (through GD::Text). This means, that by default, you can choose one of five predefined fonts, defined in the GD::Font class (GD::Font->Small, GD::Font->Large, GD::Font->MediumBold, GD::Font->Tiny, or GD::Font->Giant). If you built libgd with TrueType support (ActiveState's build includes this on Win32), then you can also use TrueType fonts (if you give the full pathname to the font). For this example, we'll use built-in fonts and insert these three lines after the $graph->set() call to specify the fonts to use for the title above the graph and the labels on each axis:

 $graph->set_title_font(   GD::Font->Giant );
 $graph->set_x_label_font( GD::Font->MediumBold );
 $graph->set_y_label_font( GD::Font->MediumBold );

We'd also like to add a legend to the graph so that the people who see it know what each line refers to. First, we add these key/value pairs to the $graph->set() statement:

  legend_placement  => 'RC',
  legend_spacing    => 10,

(RC means "Right Center".) We also add these two new statements later to create the legend, by defining the labels associated with each data set and setting the font for the legend text.

# Define a legend
$graph->set_legend( 'Affiliate A', 'Affiliate B', 'Affiliate C', 
                  'Affiliate D', 'Affiliate E' ); 
$graph->set_legend_font( GD::Font->MediumBold ); 

The result is shown in Figure 4.

Figure 4: Specifying fonts and adding a legend.
Specifying fonts and adding legend

There is a lot more you can do with GDGraph3d. For example, you could format the y -axis labels to include the "$" sign, or you could adjust the maximum y -value by hand to better fit the data, as shown in Figure 5. Read the documentation in GD::Graph and GDGraph3d for details on the options and settings available.

What The Future Holds

Like many Perl modules, GDGraph3d is a work in progress. One of the first improvements I would like to make is to add shading to the faces. I'd also like to include a drop-shadow option for the pie charts. The drop-shadow rendering could be improved to look more shadow-like, although it would slow down graph generation. I would also like to complete three-dimensional versions of the point, area, and point-and-line graphs available in GD::Graph. Finally, the ultimate goal of GDGraph3d would be to handle the projections for any viewing angle.

Figure 5: Bells and whistles.
Bells and whistles

GDGraph3d isn't meant to meet the needs of all applications. There are now a number of graphing modules available for Perl, mainly differentiated by which graphics library they require under the hood. GDGraph3d also does not provide for graphing of true three-dimensional data - it merely graphs two-dimensional data with a three-dimensional extrusion. For real three-dimensional rendering, users should use the Perl Data Language (PDL) and its associated graphing and rendering modules. Installing GD




Jeremy Wadsack (jwadsack@wadsack-allen.com) is a web site analysis consultant for the Wadsack-Allen Digital Group (https://www.wadsack-allen.com/digitalgroup/), a division of the Wadsack-Allen publishing company in Flagstaff, Arizona.

listing 1

GDGraph3D The Perl Journal, Summer 2000
Jeremy Wadsack (2000) GDGraph3d. The Perl Journal, vol 5(2), issue #18, Summer 2000.
 
#!/usr/bin/perl -w
############################################################
#
# Description: 
# Draws a basic multi-set line chart with GDGraph3d
#
# Created: 31.May.2000 by Jeremy Wadsack for Wadsack-Allen Digital Group
# Copyright (C) 2000 Wadsack-Allen. All rights reserved.
#
# This script is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
############################################################
use strict;
#**** Line numbering in the article starts here ****
use GD::Graph::lines3d;
# Create an array of data
my @data = ( 
 [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
 [  860,   813,   1694,  957,   1805,  1835,  2335,  1272,  1562,  2296,  2123,  1882,],
 [  1249,  483,   1731,  1617,  1166,  1761,  1111,  1635,  2158,  2007,  2250,  2858,],
 [  747,   1216,  525,   1028,  1053,  1860,  2282,  1871,  2143,  1845,  2924,	 2858,],
 [  1220,  864,   1325,  967,   1200,  1371,  1759,  1512,  1484,  1683,  1965,  2458,],
 [  1276,  639,   931,   1288,  2049,  909,   1617,  1432,  1615,  2605,  2712,  2429,],
);
# Make a new graph object that is 600 pixels wide by 400 pixels high
my $graph = new GD::Graph::lines3d( 600, 400 );
# Set some labels
$graph->set( 
	x_label           => 'Month, 1999',
	y_label           => 'Revenue ($US)',
	title             => 'Monthly revenue for 1999',
);
# Plot the graph to a GD object
my $gd = $graph->plot( \@data );
# Figure out what the default output format is
my $format = $graph->export_format;
# Now open a file locally and write it
open(IMG, ">sample.$format") or die $!;
	binmode IMG;
	print IMG $gd->$format();
close IMG;

listing 2

Jeremy Wadsack (2000) GDGraph3d. The Perl Journal, vol 5(2), issue #18, Summer 2000.

To install GD on your system, you'll need to install some system libraries first. Here is a step-by-step guide to retrieving and installing them. Again, none of this is necessary if you're using Perl on Windows or a Mac.

zlib The zlib compression library can be obtained from ftp://ftp.freesoftware.com/pub/infozip/zlib/zlib.tar.gz . Download and extract the archive. On most systems (Solaris is an exception) you will not have to build the zlib library, because when you build libpng later, it incorporates the source files rather than the actual library. If you choose to build and install zlib , use the standard install procedure:

  % ./configure
  % make
  # make install (as root)

libpng

Installing libpng is a little more complicated. You can get the latest version from ftp://ftp.cdrom.com/pub/png/src/. Look for something like "libpng-x.y.z.tar.gz", where x.y.z is the highest version number. Download and extract the archive. You'll need zlib on the same level as the libpng directory, and they should both be named without their versions. In other words, your directory structure should look like this:

           |
           +- zlib
           |
           +- libpng

Something like the following should do it. The actual commands may differ from system to system. You'll have to remove the archive before doing this (rm *.tar or rm *.tar.gz).

  % mv zlib* zlib
  % mv libpng* libpng
  % cd libpng
  % cp scripts/makefile.stf Makefile
  % make
  # make install (as root)

You should choose one of the makefiles in the libpng/scripts directory according to your system (such as scripts/makefile.linux for Linux or scripts/makefile.sunos for Solaris).

lttf (optional)

If you want support for TrueType fonts in your graphs (say, because you want your axis labels in Japanese), you can install the lttf library. You cannot build this if you don't have X Windows installed. You can download lttf from https://freetype.sourceforge.net/download.html and then build it as usual:

  % ./configure
  % make
  # make install (as root)

jpeg-6b

You will need the jpeg-6a (or later) library on your system for GD.pm to compile. It is often already installed, so check /usr/lib or /usr/local/lib for libjpeg. If it's not installed, you can download it from ftp://ftp.uu.net/graphics/jpeg/ and build it with the steps shown above. Alternately, there may be a precompiled packaged version (RPM, DEB, etc.) available from your local package site.

libgd

Installing libgd should now be straightforward. Download the latest version from ftp://ftp.boutell.com/pub/boutell/gd/. After extracting the archive, edit the Makefile so that it includes support for jpeg and ttf if you installed those packages. You may also have to add -I/usr/local/include/freetype to the INCLUDEDIRS= line to make it work with freetype-1.3.1. You can then build the library as follows:

  % make
  # make install (as root)

You will now be able to install GD and the rest of the Perl modules mentioned in this article.

Martin Krzywinski | contact | Canada's Michael Smith Genome Sciences CentreBC Cancer Research CenterBC CancerPHSA
Google whack “vicissitudinal corporealization”
{ 10.9.234.152 }