[dw-free] Tweak bar graphs generated by DW::Graphs
[commit: http://hg.dwscoalition.org/dw-free/rev/cae9d7ed7ee7]
http://bugs.dwscoalition.org/show_bug.cgi?id=2951
Tweak settings on DW::Graphs and make fonts, graph settings and image
Patch by
anarres.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=2951
Tweak settings on DW::Graphs and make fonts, graph settings and image
Patch by
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Files modified:
- bin/dev/graphs_usage.pl
- cgi-bin/DW/Graphs.pm
- etc/example.yaml
-------------------------------------------------------------------------------- diff -r 8389c2912ff2 -r cae9d7ed7ee7 bin/dev/graphs_usage.pl --- a/bin/dev/graphs_usage.pl Thu Apr 28 12:30:01 2011 +0800 +++ b/bin/dev/graphs_usage.pl Thu Apr 28 12:43:50 2011 +0800 @@ -10,7 +10,9 @@ # 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. +# such as DW::Controller::PaidAccountsGraph, not by a standalone script. A config +# file example.yaml (which just repeats the default settings) is used, but this can +# be left out in which case a graph is made using the default configuration. # # 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 @@ -21,25 +23,24 @@ use strict; use strict; use warnings; -# Generate a pie chart pie.png ------------------------------------------------> +# -------------------------- Generate a pie chart ---------------------------> my $pie_ref = { "label 1" => 1, "label 2" => 0.05, "label 3" => 0.07, "label 4" => 1.5, "label 5" => 0.12, + "label 6" => 0.06, }; - -# Make the graph -my $gd = DW::Graphs::pie( $pie_ref ); +my $gd = DW::Graphs::pie( $pie_ref, "example.yaml" ); # Print the graph to a file open(IMG, '>pie.png') or die $!; binmode IMG; print IMG $gd->png; +# ---------------------- Generate a bar chart -------------------------------> -# 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. @@ -47,16 +48,15 @@ my $bar_labels = [ ( "label 1", "\nlabel 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' ); +my $bar_gd = DW::Graphs::bar( $bar_ref, $bar_labels, 'x-axis label', + 'y-axis label', "example.yaml" ); # 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 -----------------------------> +# ---------- Generate a bar chart with two (or more) datasets -------------> # You can have any number of datasets - here there are two my @values1 = ( 7243, 15901, 26188 ); @@ -73,19 +73,18 @@ my @bar2_labels = ( "Bar 1", "Bar 2", "B # 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); +my $bar2_gd = DW::Graphs::bar2( $bar2_input, 'x-axis label', 'y-axis label', + $names_ref, "example.yaml" ); # 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 ---------------------------------------------> +# --------------------- Generate a line graph --------------------------------> # Define labels to go along the horizontal axis under the graph. -# If you don't want labels, use empty strings +# If labels are not wanted 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 @@ -94,15 +93,14 @@ my @dataset2 = qw( 871 996 990 1058 1102 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 +# Names for the datasets, for 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 +# Put the data in a format DW::Graphs 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 ); +my $line_gd = DW::Graphs::lines( $line_ref, 'x-axis label', 'y-axis label', + $line_names, "example.yaml" ); # Print the graph to a file open(IMG, '>lines.png') or die $!; diff -r 8389c2912ff2 -r cae9d7ed7ee7 cgi-bin/DW/Graphs.pm --- a/cgi-bin/DW/Graphs.pm Thu Apr 28 12:30:01 2011 +0800 +++ b/cgi-bin/DW/Graphs.pm Thu Apr 28 12:43:50 2011 +0800 @@ -16,7 +16,7 @@ use strict; use strict; use warnings; use lib "$ENV{LJHOME}/cgi-bin"; -require 'ljlib.pl'; +require 'ljlib.pl'; use GD::Graph; use GD::Graph::bars; use GD::Graph::hbars; @@ -24,14 +24,30 @@ use GD::Graph::lines; 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"; +use YAML (); +# Define colours - the arrays can be over-ridden by config file +my $background = '#f7f7f7'; +my $nearly_white = '#f8f8f8'; +my $textclr = '#c1272d'; +my $clrs = [ '#7eafd2', '#f3973e', '#77cba2', '#edd344', '#a5c640' , '#d87ba9' ]; +my $dark_clrs = [ '#11061b', '#920d00', '#0d3d1b', '#490045', '#4e1b05' ]; + +# Default font and font sizes +my %fonts = ( + font => "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", + title_size => 14, + value_size => 10, + label_size_pie => 10, + label_size => 12, + axis_size => 10, + legend_size => 12, +); # 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 ) = @_; + my ( $pie_ref, $config_filename ) = @_; # Sort the key-value pairs of %$pie_ref by value: # @pie_labels is the keys and @pie_values is the values @@ -41,133 +57,213 @@ sub pie { # 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( + # Default settings (can be over-ridden by config file) + my %settings = ( transparent => 0, # Set this to 1 for transparent background - accentclr => 'nearly_white', + 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 ) ], + bgclr => $background, + dclrs => $clrs, labelclr => '#000000', valuesclr => '#000000', - textclr => 'dw_red', + textclr => $textclr, '3d' => 0, - ) or die $graph->error; + ); + my $image_width = 300; # Image width in pixels - can be over-ridden + my $image_height = 300; - # 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); + # If there is a config file, get any settings from it + if ( defined $config_filename ) { + my $config = YAML::LoadFile( "$LJ::HOME/etc/$config_filename" ); + + # Image size + $image_width = $config->{image_width} + if defined $config->{image_width}; + $image_height = $config->{image_height} + if defined $config->{image_height}; + + # Over-ride %settings with settings in config file, if they exist + foreach my $k ( keys %settings ) { + $settings{$k} = $config->{$k} + if defined $config->{$k}; + } + + # Over-ride %fonts with font settings in config file, if they exist + my $config_fonts = $config->{fonts}; + if ( defined $config_fonts ) { + $fonts{$_} = $config_fonts->{$_} + foreach keys %$config_fonts; + } + } + + # Create graph object + my $graph = GD::Graph::pie->new( $image_width, $image_height ); + $graph->set( %settings ) or die $graph->error; + + # Fonts defined at top in %fonts, and can be over-ridden by config file + $graph->set_title_font( $fonts{font}, $fonts{title_size} ); + $graph->set_value_font( $fonts{font}, $fonts{value_size} ); + $graph->set_label_font( $fonts{font}, $fonts{label_size_pie} ); 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 +# $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 ) = @_; + my ( $values_ref, $labels_ref, $xlabel, $ylabel, $config_filename ) = @_; # Package the input as required by GD Graph my $input_ref = [ $labels_ref, $values_ref ]; + # Default settings (can be over-ridden by config file) + my %settings = ( + 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) + t_margin => 50, # Top margin - makes space for value above highest bar + y_min_value => 0.0, # Stop scale going below zero + + bgclr => $background, + fgclr => 'white', + boxclr => '#f4eedc', # Shaded-in background + long_ticks => 1, # Background grid lines + accentclr => $background, # Colour of grid lines + + labelclr => '#000000', + axislabelclr => '#000000', + legendclr => '#000000', + valuesclr => '#000000', + textclr => $textclr, + transparent => 0, # 1 for transparent background + dclrs => $clrs, + ); + my $image_width = 500; # Image width in pixels - can be over-ridden + my $image_height = 350; + + # If there is a config file, get any settings from it + if ( defined $config_filename ) { + my $config = YAML::LoadFile( "$LJ::HOME/etc/$config_filename" ); + + # Image size + $image_width = $config->{image_width} + if defined $config->{image_width}; + $image_height = $config->{image_height} + if defined $config->{image_height}; + + # Over-ride %settings with settings in config file, if they exist + foreach my $k ( keys %settings ) { + $settings{$k} = $config->{$k} + if defined $config->{$k}; + } + + # Over-ride %fonts with font settings in config file, if they exist + my $config_fonts = $config->{fonts}; + if ( defined $config_fonts ) { + $fonts{$_} = $config_fonts->{$_} + foreach keys %$config_fonts; + } + } + # Create graph object - my $graph = GD::Graph::bars->new(500, 350); + my $graph = GD::Graph::bars->new( $image_width, $image_height ); + $graph->set( %settings ) or die $graph->error; - # 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); + # Fonts defined at top in %fonts, and can be over-ridden by config file + $graph->set_title_font( $fonts{font}, $fonts{title_size} ); + $graph->set_x_label_font( $fonts{font}, $fonts{label_size} ); + $graph->set_y_label_font( $fonts{font}, $fonts{label_size} ); + $graph->set_x_axis_font( $fonts{font}, $fonts{axis_size} ); + $graph->set_y_axis_font( $fonts{font}, $fonts{axis_size} ); + $graph->set_values_font( $fonts{font}, $fonts{value_size} ); # 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 +# 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 ) = @_; + my ( $ref, $xlabel, $ylabel, $names_ref, $config_filename ) = @_; - # Create graph object - my $graph = GD::Graph::bars->new(500, 350); - - # Graph settings - $graph->set( + #Default settings (can be over-ridden by config file) + my %settings = ( x_label => "\n$xlabel", y_label => $ylabel, show_values => 1, - values_space => 1, # Pixels between top of bar and value above + 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 + t_margin => 50, # Top margin - makes space for value above highest bar + y_min_value => 0.0, # Stop scale going below zero + legend_placement => 'RC', # Right centre - cumulate => 'true', # Put the two datasets in one bar + cumulate => 'true', # Put the two datasets in one bar + bar_spacing => undef, - shadowclr => 'background', - bgclr => 'background', + shadowclr => $background, + bgclr => $background, fgclr => 'white', - boxclr => '#f4eedc', # Shaded-in background + 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', + textclr => $textclr, + dclrs => $clrs, + ); + my $image_width = 500; # Image width in pixels - can be over-ridden + my $image_height = 350; - dclrs => [ qw( pie_blue pie_orange pie_bluegreen pie_green - pie_yellow pie_pink ) ], - ) or die $graph->error; + # If there is a config file, get any settings from it + if ( defined $config_filename ) { + my $config = YAML::LoadFile( "$LJ::HOME/etc/$config_filename" ); - # 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); + # Image size + $image_width = $config->{image_width} + if defined $config->{image_width}; + $image_height = $config->{image_height} + if defined $config->{image_height}; + + # Over-ride %settings with settings in config file, if they exist + foreach my $k ( keys %settings ) { + $settings{$k} = $config->{$k} + if defined $config->{$k}; + } + + # Over-ride %fonts with font settings in config file, if they exist + my $config_fonts = $config->{fonts}; + if ( defined $config_fonts ) { + $fonts{$_} = $config_fonts->{$_} + foreach keys %$config_fonts; + } + } + + # Create graph object + my $graph = GD::Graph::bars->new( $image_width, $image_height ); + $graph->set( %settings ) or die $graph->error; + + # Fonts defined at top in %fonts, and can be over-ridden by config file + $graph->set_title_font( $fonts{font}, $fonts{title_size} ); + $graph->set_x_label_font( $fonts{font}, $fonts{label_size} ); + $graph->set_y_label_font( $fonts{font}, $fonts{label_size} ); + $graph->set_x_axis_font( $fonts{font}, $fonts{axis_size} ); + $graph->set_y_axis_font( $fonts{font}, $fonts{axis_size} ); + $graph->set_values_font( $fonts{font}, $fonts{value_size} ); + $graph->set_legend_font( $fonts{font}, $fonts{legend_size} ); # Set legend $graph->set_legend( @$names_ref ); @@ -182,13 +278,10 @@ sub bar2 { # 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 ) = @_; + my ( $data_ref, $xlabel, $ylabel, $data_names, $config_filename ) = @_; - # Create new Graph object $graph 750px by 320 px - my $graph = GD::Graph::lines->new(750, 320); - - # Graph settings: - $graph->set( + #Default settings (can be over-ridden by config file) + my %settings = ( x_label => $xlabel, y_label => $ylabel, show_values => 0, @@ -198,35 +291,63 @@ sub lines { line_width => 4, # Line width in pixels legend_placement => 'RC', # Right centre - bgclr => 'background', + 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; + labelclr => '#000000', + axislabelclr => '#000000', + legendclr => '#000000', + valuesclr => '#000000', + textclr => $textclr, + dclrs => $dark_clrs, + ); + my $image_width = 750; # Image width in pixels - can be over-ridden + my $image_height = 320; + # If there is a config file, get any settings from it + if ( defined $config_filename ) { + my $config = YAML::LoadFile( "$LJ::HOME/etc/$config_filename" ); + + # Image size + $image_width = $config->{image_width} + if defined $config->{image_width}; + $image_height = $config->{image_height} + if defined $config->{image_height}; + + # Over-ride %settings with settings in config file, if they exist + foreach my $k ( keys %settings ) { + $settings{$k} = $config->{$k} + if defined $config->{$k}; + } + + # Over-ride %fonts with font settings in config file, if they exist + my $config_fonts = $config->{fonts}; + if ( defined $config_fonts ) { + $fonts{$_} = $config_fonts->{$_} + foreach keys %$config_fonts; + } + } + + # Create Graph + my $graph = GD::Graph::lines->new( $image_width, $image_height ); + $graph->set( %settings ) or die $graph->error; $graph->set( line_types => [1, 2, 3, 4] ); # 1:solid 2:dash 3:dot 4:dot-dash + $graph->set_legend( @$data_names ); - # 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 ); + # Fonts defined at top in %fonts, and can be over-ridden by config file + $graph->set_title_font( $fonts{font}, $fonts{title_size} ); + $graph->set_x_label_font( $fonts{font}, $fonts{label_size} ); + $graph->set_y_label_font( $fonts{font}, $fonts{label_size} ); + $graph->set_x_axis_font( $fonts{font}, $fonts{axis_size} ); + $graph->set_y_axis_font( $fonts{font}, $fonts{axis_size} ); + $graph->set_values_font( $fonts{font}, $fonts{value_size} ); + $graph->set_legend_font( $fonts{font}, $fonts{legend_size} ); # Make the plot my $gd = $graph->plot( $data_ref ) or die $graph->error; return $gd; } + 1; diff -r 8389c2912ff2 -r cae9d7ed7ee7 etc/example.yaml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/etc/example.yaml Thu Apr 28 12:43:50 2011 +0800 @@ -0,0 +1,32 @@ +# etc/example.yaml +# +# Example configuration file for DW::Graphs +# +# Authors: +# Anarres <anarres@dreamwidth.org> +# +# Copyright (c) 2011 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'. +--- +bgclr: #f7f7f7 +# Colors to use in order, one per dataset. See GD::Graph->set for details. +dclrs: + - #7eafd2 + - #f3973e + - #77cba2 + - #edd344 + - #a5c640 + - #d87ba9 +fonts: + font: /usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf + title_size: 14 + value_size: 10 + label_size_pie: 10 + label_size: 12 + axis_size: 10 + legend_size: 12 +image_height: 600 +image_width: 600 --------------------------------------------------------------------------------