Add module that creates graphs for the statistics system; add a script
with usage examples. Available graphs are: pie charts, bar charts, bar chart
with multiple bars, line graphs.
Patch by anarres.
diffs (386 lines):
diff -r be9772bf3332 -r a71463d5d873 bin/dev/graphs_usage.pl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/dev/graphs_usage.pl Wed Jul 28 22:56:28 2010 -0700
@@ -0,0 +1,110 @@
+#!/usr/bin/perl
+#
+# dw/bin/dev/graphs_usage.pl - Graphs usage examples
+#
+# Authors:
+# Anarres <[email protected]>
+#
+# Copyright (c) 2010 by Dreamwidth Studios, LLC.
+#
+# Gives examples of usage of the DW::Graphs module to make pie, bar, and line
+# graphs. This script is only for the purpose of showing how the Graphs module
+# works, normally the Graphs module would be used by graph image controller
modules
+# such as DW::Controller::PaidAccountsGraph, not by a standalone script.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself. For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+
+use lib "$ENV{LJHOME}/cgi-bin";
+use DW::Graphs;
+use strict;
+use warnings;
+
+# Generate a pie chart pie.png
------------------------------------------------>
+my $pie_ref = {
+ "label 1" => 1,
+ "label 2" => 0.05,
+ "label 3" => 0.07,
+ "label 4" => 1.5,
+ "label 5" => 0.12,
+};
+
+# Make the graph
+my $gd = DW::Graphs::pie( $pie_ref );
+
+# Print the graph to a file
+open(IMG, '>pie.png') or die $!;
+binmode IMG;
+print IMG $gd->png;
+
+
+# Generate a bar chart bar.png
------------------------------------------------>
+my $bar_ref = [ 13.377, 15.9, 145.67788, 123.1111, 0.1, 44.03455, 33.3, 43,
123 ];
+
+# Labels - one label per bar. If labels are not wanted pass empty strings.
+# Optinally put "\n" in front of every 2nd label to stop them crowding
each-other.
+my $bar_labels = [ ( "label 1", "\nlabel 2", "label 3", "\nlabel 4", "label 5",
+ "\nlabel 6", "label 7", "\nlabel 8", "label 9" ) ];
+
+# Make the graph
+my $bar_gd = DW::Graphs::bar( $bar_ref, $bar_labels, 'x-axis label', 'y-axis
label' );
+
+# Print the graph to a file
+open(IMG, '>bar.png') or die $!;
+binmode IMG;
+print IMG $bar_gd->png;
+
+
+# Generate a bar chart bar2.png with two datasets
----------------------------->
+
+# You can have any number of datasets - here there are two
+my @values1 = ( 7243, 15901, 26188 );
+my @values2 = ( 4243, 12901, 11188 );
+
+# Dataset names to distinguish the datasets, used in the legend. The number
+# of dataset names must be the same as the number of datasets!
+my $names_ref = [ ( "Dataset 1", "Dataset 2" ) ];
+
+# labels - one label per bar. The number of labels must be the same as the
+# number of values per dataset. If labels are not wanted pass empty strings.
+my @bar2_labels = ( "Bar 1", "Bar 2", "Bar 3" );
+
+# Package the input
+my $bar2_input = [ [...@bar2_labels], [...@values1], [...@values2] ];
+
+# Make the graph
+my $bar2_gd = DW::Graphs::bar2( $bar2_input, 'x-axis label', 'y-axis label',
$names_ref);
+
+# Print the graph to a file
+open(IMG, '>bar2.png') or die $!;
+binmode IMG;
+print IMG $bar2_gd->png;
+
+
+# Generate a line graph lines.png
--------------------------------------------->
+
+# Define labels to go along the horizontal axis under the graph.
+# If you don't want labels, use empty strings
+my @line_labels = ( "1st","2nd","3rd","4th","5th","6th","7th", "8th" );
+
+# Define the datasets - each dataset will form one line on the graph
+# Each dataset should have the same length as the number of labels
+my @dataset1 = qw( 1900 2035 2078 2140 2141 2200 2460 2470 2576 );
+my @dataset2 = qw( 871 996 990 1058 1102 1162 1105 1150 );
+my @dataset3 = qw( 200 360 370 471 496 690 758 802 );
+
+# Names for the datasets, to go in the graph legend
+my $line_names = [ "1st dataset", "2nd dataset", "3rd dataset" ];
+
+# Put the data in a format that the Graphs module can deal with
+my $line_ref = [ [...@line_labels], [...@dataset1], [...@dataset2],
[...@dataset3] ];
+
+# Make the graph
+my $line_gd = DW::Graphs::lines( $line_ref, 'x-axis label', 'y-axis label',
+ $line_names );
+
+# Print the graph to a file
+open(IMG, '>lines.png') or die $!;
+binmode IMG;
+print IMG $line_gd->png;
diff -r be9772bf3332 -r a71463d5d873 cgi-bin/DW/Graphs.pm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Graphs.pm Wed Jul 28 22:56:28 2010 -0700
@@ -0,0 +1,232 @@
+#!/usr/bin/perl
+#
+# DW::Graphs - creates graphs for the statistics system
+#
+# Authors:
+# Anarres <[email protected]>
+#
+# Copyright (c) 2010 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself. For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+
+package DW::Graphs;
+
+use strict;
+use warnings;
+use lib "$ENV{LJHOME}/cgi-bin";
+require 'ljlib.pl';
+use GD::Graph;
+use GD::Graph::bars;
+use GD::Graph::hbars;
+use GD::Graph::pie;
+use GD::Graph::lines;
+use GD::Text;
+use GD::Graph::colour;
+GD::Graph::colour::read_rgb("$LJ::HOME/etc/clrs.txt")
+ or die "cannot read colours";
+
+# Generates a pie chart. The argument is a hashref of labels and values.
+# Returns graph object $gd which can be printed with the command: print
$gd->png;
+# See ~/dw/bin/dev/graphs_usage.pl for more detailed usage information.
+sub pie {
+ my ( $pie_ref ) = @_;
+
+ # Sort the key-value pairs of %$pie_ref by value:
+ # @pie_labels is the keys and @pie_values is the values
+ my @pie_labels = sort { $pie_ref->{$a} cmp $pie_ref->{$b} } keys %$pie_ref;
+ my @pie_values = map { $pie_ref->{$_} } @pie_labels;
+
+ # Package the data in a way that makes GD::Graph happy
+ my $pie = [ [...@pie_labels], [...@pie_values] ];
+
+ # Create graph object
+ my $graph = GD::Graph::pie->new( 300, 300 );
+ $graph->set(
+ transparent => 0, # Set this to 1 for transparent background
+ accentclr => 'nearly_white',
+ start_angle => 90, # Angle of first slice of pie, 0 = 6 o'clock
+ suppress_angle => 5, # Smaller slices than this have no labels
+ bgclr => 'background',
+ dclrs => [ qw( pie_blue pie_orange pie_bluegreen pie_green
+ pie_yellow pie_pink ) ],
+ labelclr => '#000000',
+ valuesclr => '#000000',
+ textclr => 'dw_red',
+ '3d' => 0,
+ ) or die $graph->error;
+
+ # FIXME: make the pathnames and font sizes configurable
+
$graph->set_title_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
14);
+
$graph->set_value_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
$graph->set_label_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
+ my $gd = $graph->plot( $pie ) or die $graph->error;
+ return $gd;
+}
+
+# Generates a bar chart. Arguments: a ref to an array of values, a ref to an
+# array of labels, title, x-axis label, y-axis label. # Returns graph object
+# $gd which can be printed with the command: print $gd->png; see
+# graphs_usage.pl for more detailed usage information.
+sub bar {
+ my ( $values_ref, $labels_ref, $xlabel, $ylabel ) = @_;
+
+ # Package the input as required by GD Graph
+ my $input_ref = [ $labels_ref, $values_ref ];
+
+ # Create graph object
+ my $graph = GD::Graph::bars->new(500, 350);
+
+ # Graph settings
+ $graph->set(
+ x_label => "\n$xlabel",
+ y_label => $ylabel,
+ show_values => 1,
+ values_space => 1, # Pixels between top of bar and value above
+ b_margin => 20, # Bottom margin (makes space for labels)
+ bar_spacing => 50, # Higher value = thinner bars
+
+ bgclr => 'background',
+ fgclr => 'white',
+ boxclr => '#f4eedc', # Shaded-in background
+ long_ticks => 1, # Background grid lines
+ accentclr => 'lgray', # Colour of grid lines
+ accent_treshold => 500, # Get rid of outline around bars
+
+ labelclr => '#000000',
+ axislabelclr => '#000000',
+ legendclr => '#000000',
+ valuesclr => '#000000',
+ textclr => 'dw_red',
+
+ transparent => 0, # 1 for transparent background
+ dclrs => [ qw( pie_blue pie_orange pie_bluegreen pie_green
+ pie_yellow pie_pink ) ],
+ ) or die $graph->error;
+
+ # FIXME: make the pathnames and font sizes configurable
+
$graph->set_title_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
14);
+
$graph->set_x_label_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
12);
+
$graph->set_y_label_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
12);
+
$graph->set_x_axis_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
$graph->set_y_axis_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
$graph->set_values_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
+ # Make the graph
+ my $gd = $graph->plot( $input_ref ) or die $graph->error;
+ return $gd;
+}
+
+# Generates a bar chart with two or more sets of data represented by each bar.
+# Arguments: a reference containing labels and datasets, x-axis label,
+# y-axis label, ref to array of names for datasets. Returns graph object
+# $gd which can be printed with the command: print $gd->png; see
+# ~/dw/bin/dev/graphs_usage.pl for more detailed usage information.
+sub bar2 {
+ my ( $ref, $xlabel, $ylabel, $names_ref ) = @_;
+
+ # Create graph object
+ my $graph = GD::Graph::bars->new(500, 350);
+
+ # Graph settings
+ $graph->set(
+ x_label => "\n$xlabel",
+ y_label => $ylabel,
+ show_values => 1,
+ values_space => 1, # Pixels between top of bar and value above
+ b_margin => 20, # Bottom margin (makes space for labels)
+ bar_spacing => 50, # Higher value = thinner bars
+ legend_placement => 'RC', # Right centre
+ cumulate => 'true', # Put the two datasets in one bar
+
+ shadowclr => 'background',
+ bgclr => 'background',
+ fgclr => 'white',
+ boxclr => '#f4eedc', # Shaded-in background
+ long_ticks => 1, # Background grid lines
+ accentclr => 'white', # Colour of grid lines
+ transparent => 0, # 1 for transparent background
+ #accent_treshold => 500, # Get rid of outline around bars
+
+ labelclr => '#000000',
+ axislabelclr => '#000000',
+ legendclr => '#000000',
+ valuesclr => '#000000',
+ textclr => 'dw_red',
+
+ dclrs => [ qw( pie_blue pie_orange pie_bluegreen pie_green
+ pie_yellow pie_pink ) ],
+ ) or die $graph->error;
+
+ # FIXME: make the pathnames and font sizes configurable
+
$graph->set_title_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
14);
+
$graph->set_x_label_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
12);
+
$graph->set_y_label_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
12);
+
$graph->set_x_axis_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
$graph->set_y_axis_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
$graph->set_values_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
$graph->set_legend_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
+ # Set legend
+ $graph->set_legend( @$names_ref );
+
+ # Make the graph
+ my $gd = $graph->plot( $ref ) or die $graph->error;
+ return $gd;
+}
+
+# Generates a line graph. Arguments: a reference containing labels and
datasets,
+# x-axis label, y-axis label, ref to array of names for datasets. Returns
+# graph object $gd which can be printed with the command: print $gd->png; see
+# ~/dw/bin/dev/graphs_usage.pl for more detailed usage information.
+sub lines {
+ my ( $data_ref, $xlabel, $ylabel, $data_names ) = @_;
+
+ # Create new Graph object $graph 750px by 320 px
+ my $graph = GD::Graph::lines->new(750, 320);
+
+ # Graph settings:
+ $graph->set(
+ x_label => $xlabel,
+ y_label => $ylabel,
+ show_values => 0,
+ transparent => 0, # Set this to 1 for transparent
background
+ line_width => 1,
+ long_ticks => 1, # Background grid lines
+ line_width => 4, # Line width in pixels
+ legend_placement => 'RC', # Right centre
+
+ bgclr => 'background',
+ fgclr => 'white',
+ boxclr => '#f4eedc', # Shaded-in background colour
+ accentclr => 'lgray',
+
+ labelclr => '#000000',
+ axislabelclr => '#000000',
+ legendclr => '#000000',
+ valuesclr => '#000000',
+ textclr => 'dw_red',
+ dclrs => [ qw( solid0 solid1 solid2 solid3 solid4 ) ],
+ ) or die $graph->error;
+
+ $graph->set( line_types => [1, 2, 3, 4] ); # 1:solid 2:dash 3:dot
4:dot-dash
+
+ # FIXME: make the pathnames and font sizes configurable
+
$graph->set_title_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
14);
+
$graph->set_legend_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
12);
+
$graph->set_x_label_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
12);
+
$graph->set_y_label_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
12);
+
$graph->set_x_axis_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
$graph->set_y_axis_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
$graph->set_values_font("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
10);
+
+ # Set legend
+ $graph->set_legend( @$data_names );
+
+ # Make the plot
+ my $gd = $graph->plot( $data_ref ) or die $graph->error;
+ return $gd;
+}
+1;
diff -r be9772bf3332 -r a71463d5d873 etc/clrs.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/clrs.txt Wed Jul 28 22:56:28 2010 -0700
@@ -0,0 +1,32 @@
+# dw/etc/clrs.txt
+#
+# Defines colours to be used by DW::Graphs
+#
+# Authors:
+# Anarres <[email protected]>
+#
+# Copyright (c) 2010 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself. For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+
+# Solid colours
+90 132 0 solid0
+146 13 27 solid1
+17 6 82 solid2
+229 187 27 solid3
+13 61 37 solid4
+
+# Colours for pie charts
+126 175 210 pie_blue
+243 151 62 pie_orange
+119 203 162 pie_bluegreen
+165 198 64 pie_green
+237 211 68 pie_yellow
+215 139 169 pie_pink
+
+# Other
+247 247 247 background
+197 53 60 dw_red
+248 248 248 nearly_white
_______________________________________________
dw-changelog mailing list
[email protected]
http://lists.dwscoalition.org/mailman/listinfo/dw-changelog