Cookie Notice

As far as I know, and as far as I remember, nothing in this page does anything with Cookies.

2010/01/14

Making Pretty Pictures

GD::Graph


R


Chart::Clicker
This should have times across the bottom. It doesn't. I don't know why.

These three images are of the same thing, graphed with different tools. I start by getting the data for these arrays out of the database:






















@number #temp_f @date
1 33 14:20
2 35 15:00
3 36 16:00
4 37 17:00
5 37 18:00
6 35 19:00
7 33 20:00
8 32 21:00
9 33 22:00
10 32 23:00
11 32 00:00
12 32 01:00
13 32 02:00
14 32 03:00
15 30 04:00
16 30 05:00
17 30 06:00
18 29 07:00
19 30 08:00
20 32 09:00


These three examples use the same basic information to draw the graph.

The database code



#!/usr/bin/perl

####################################
###### Draw Weather Graph ######
####################################

use 5.010 ;
use strict ;
use warnings ;

use Chart::Clicker;
use Chart::Clicker::Context;
use Chart::Clicker::Data::DataSet;
use Chart::Clicker::Data::Marker;
use Chart::Clicker::Data::Series;
use Chart::Clicker::Renderer::Area;
use Chart::Clicker::Renderer::Point;
use Chart::Clicker::Renderer::StackedArea;
use Geometry::Primitive::Rectangle;
use Geometry::Primitive::Circle;
use Graphics::Color::RGB;
use Graphics::Primitive::Font;
use Graphics::Primitive::Brush;

use Data::Dumper ;
use DBI ;
use Getopt::Long ;
use IO::Interactive qw{ interactive } ;

use lib '/home/jacoby/lib' ;
use MyDB 'db_connect' ;
use subs qw{
high low mean median mode range
} ;

my $dbh = db_connect() ;
my $sql ;

$sql .= 'SELECT ' ;
$sql .= 'time , ' ;
$sql .= 'temp_f ' ;
$sql .= 'FROM weather WHERE zip = "47909" ' ;
$sql .= 'AND HOUR( TIMEDIFF( SYSDATE() , time ) ) < 25 ' ;
$sql .= 'GROUP BY HOUR(time)' ;
$sql .= 'ORDER BY time' ;

my $hr = $dbh->selectall_arrayref( $sql ) or croak $dbh->errstr ;
my %tg ;

my @temp_f ;
my @date ;
my @number ;
my $count = 1 ;

for my $a ( @$hr ) {
$$a[0] = join ':' , ( split m{:} , ( split m{\s}mx , $$a[0] )[1] )[0..1];
push @date , $$a[0] ;
push @temp_f , $$a[1] ;
push @number , $count++ ;
}


Making the GD PNG



my @data = (
[@date] ,
[@temp_f]
) ;

my $graph = new GD::Graph::lines( 500,200 ) or die;
$graph->set(
x_label => 'Temperature',
y_label => 'Time',
bgclr => 'white' ,
transparent => 0 ,
title => 'Lafayette,IN Temperatures in F for the last 24 Hours',
) or die $graph->error;
$graph->set_title_font( '/home/jacoby/.fonts/trebuc.ttf' , 12 ) or die $graph->error;
$graph->set_legend_font( '/home/jacoby/.fonts/trebuc.ttf' , 8 ) or die $graph->error;
$graph->set_x_label_font( '/home/jacoby/.fonts/trebuc.ttf' , 10 ) or die $graph->error;
$graph->set_y_label_font( '/home/jacoby/.fonts/trebuc.ttf' , 10 ) or die $graph->error;
my $gd = $graph->plot(\@data) or die $graph->error;

open(IMG, '>' , '/home/jacoby/Desktop/24gd.png') or die $!;
binmode IMG;
print IMG $gd->png;




Making the R output



my $number = join ',' , @number;
my $temp_f = join ',' , @temp_f ;
my $date = join ' , ' , ( map { qq("$_") } @date );

my $r = <<"R" ;
#x <- (1:24)
x <- c( $number )
#x <- c( $date )
data <- c( $temp_f )
png(filename='/home/jacoby/Desktop/24r.png', width=500 ,height=200 )
plot(
x ,
data ,
type='l',
main='Lafayette,IN Temperatures in F for the last 24 Hours',
xlab='Time' ,
ylab='Temperature (f)'
)
#axis( 1 , at=1:48 )
dev.off()
R

open my $rh , '>' , '/home/jacoby/Desktop/24r.R' ;
say $rh $r ;

Which then has R CMD BATCH filename.R run on it to plot the graph. I could put that in as a qx{} bit, but I didn't here. Normally, yes, I would and in fact we have several that do.


Making the Chart::Clicker PNG




my $cc = Chart::Clicker->new(width => 500, height => 200, format => 'png');
my $series1 = Chart::Clicker::Data::Series->new(
keys => \@number ,
values => \@temp_f ,
);
my $dataset = Chart::Clicker::Data::DataSet->new(
series => [ $series1 ] ,
);

$cc->title->text('Lafayette,IN Temperatures in F for the last 24 Hours');
$cc->add_to_datasets($dataset);

$cc->get_context('default')->domain_axis->tick_values($series1->keys);
$cc->get_context('default')->domain_axis->tick_labels(\@date);
$cc->get_context('default')->domain_axis->tick_label_angle(1);

$cc->get_context('default')->domain_axis->fudge_amount( 0.05 );
$cc->get_context('default')->range_axis->fudge_amount( 0.1 );

my $defctx = $cc->get_context('default');
$defctx->range_axis->label( ' Temperature ' );
$defctx->domain_axis->label('Time');
$defctx->renderer->brush->width(2);
$cc->write_output('/home/jacoby/Desktop/24cc.png');

The big win is that it's graphed right. The next win is that it's all Perl, so I don't need to go back and run a plotter on the output. The last win is that it looks good.

BTW, I find it interesting that, at least on Jan 14 2010, when I do an image search on Chart::Clicker, this blog gets the top spot.

No comments:

Post a Comment