Software Design
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming Languages - MoreSoftware Design

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old May 7th, 2004, 04:01 AM
easy_coder easy_coder is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Oct 2003
Posts: 421 easy_coder User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 2 Days 12 h 50 m 2 sec
Reputation Power: 6
moving average and smoothed calculations for gd::graph

I create line graphs on the fly using gd::graph. I would like to have a moving average and also a smothed graph. With a smooth graph, data2002 for May would not spike as much. The moving average could go back 2 and 6 months. I take my values from a MySQL select where I select between epoch time stamps. I store the rows returned and dynamicly generate the labels.

Code:
my @xLabels  = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
my @data2002 = qw(  17  19  26  38  130 64  67  53  40  29  21  13 );
my @data2003 = qw(  19  24  27  41  56  69  75  60  44  33  22  15 );


This code below works and creates a graph using values between two epoch time stamps. It would be much nicer if I had totals for every minute yet were displayed as an hour. You see the problem is that it sums up the rows for each hour and then uses hours for labels. If only I could have hours as labels and then minutes as values it would show better. Any potential problems with running that many select statement on a MySql table? What if I went back every minute (or 5 minutes) for a week? I've had alot of help with pieces of this from the forum and tutorials on the net. Here it is all together. Any advice. Thanks

Code:
#!/usr/bin/perl -w
use strict;

use GD::Graph::mixed;
use GD::Graph::colour qw( :files );
use GD::Text;
use Time::Local;
use DBI;

# Set value -can be dynamicly set to go back x hours
my $set = 48;


my @matrix;
my @xLabels;
my @avDown;
my @avUp;
my @down;
my @up;
my @data;


# for (my $count=0; $count<8; $count++)	# counts 0 to -7
for (my $count=0; $count<$set; $count++)	# counts 0 to -7
{
my $neg = -1;
my $negative_count = $count * $neg;
my $negative_count_less = $negative_count - 1;

# Finds top of the hour
my $sid = 60*60; #seconds in 1 hr
# grab this moment
my $time = time;

my $top_of_hour = $time - ($time % $sid);

# go back x many hrs
my $period_days= $negative_count;		# period in days

# set period in seconds (hrs)
my $period = 60*60 * $period_days;

# set epoch date
my $start_of_day_period_one = ($period + $top_of_hour);

# parse date for human use
my @dayofweek = (qw(Sun Mon Tue Wed Th Fri Sat));
my @monthnames = (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec));
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime($start_of_day_period_one);
$year += 1900;
$mday = "0$mday" if ($mday < 10); 
$hour = " $hour"if ($hour < 10);


my $interval_one = "$monthnames[$mon] $mday $hour:00";


#################################################################################

# Finds top of hour for today
my $sid = 60*60; #seconds in hr
my $time = time;
my $top_of_hour = $time - ($time % $sid);

# go back x many days
my $period_days= $negative_count_less;		# period in days

# set period in seconds
my $period = 60*60 * $period_days;

# set epoch date
my $start_of_day_period_two = ($period + $top_of_hour);

# parse date for human use
my @dayofweek = (qw(Sun Mon Tue Wed Th Fri Sat));
my @monthnames = (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec));
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime($start_of_day_period_two);
$year += 1900;
my $interval_two = "$monthnames[$mon] $mday $hour:00";

###########################################################################################
my $db		= "";	# Database name
my $localhost	= "";  # localhost
my $username	= "";	# Username
my $password	= "";	# Password

############## prints all rows - dumps data ##################
# connect to DB
  my $dbh = DBI->connect ("DBI:mysql:$db:$localhost",
                           "$username","$password")
             || die "Could not connect to database: "
             . DBI-> errstr;	# display error

# $start_of_day_period_one $start_of_day_period_two
my $sql = qq{ SELECT id FROM data where time_stamp BETWEEN $start_of_day_period_two and $start_of_day_period_one};
my $sth = $dbh->prepare( $sql );
$sth->execute();

# for capturing number of rows
my $rv = $sth->execute || die $sth->errstr;

## Set Vars  ########
my $num = 0;  		# if no row is returned
my $zero = "0E0";

if ($rv == $zero){
	push ( @matrix , [ $interval_one, $num ] );
	next;
}
push ( @matrix , [ $interval_one, $rv ] );

# Don't need the database connection anymore
$sth->finish();
$dbh->disconnect();

} # end of for (my $count=1; $count<8; $count++)	# counts -1 to -7

for my $row (@matrix) {
  print "Val: @$row[0] Day: @$row[1]\n";
}
#
# Put test data into labels array, value array
my @xlabels = ();
my @avDown = ();

for my $row (@matrix) {
  push @xlabels, @$row[1];
  push @avDown, @$row[0];
}

####################################################
# example
#my @data = ( ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
#             [ 17, 19, 26, 38, 56, 64, 67, 53, 40, 29, 21, 13],
#             [ 19, 24, 27, 41, 56, 69, 75, 60, 44, 33, 22, 15] );


my @avDown_rev;
my @xlabels_rev;
my @avDown_rev = reverse(@avDown);
my @xlabels_rev = reverse(@xlabels);
  my @data = (
  	    [(@avDown_rev)],
  	    [@xlabels_rev],
  	    );

  my $graph = GD::Graph::lines->new( 700, 300 );
  
######################## 
  
GD::Graph::colour::read_rgb( "/usr/X11R6/lib/X11/rgb.txt" ) or
  die( "Can't read colours" );

$graph->set( title            => "Statistics",
             t_margin         => 10,
             b_margin         => 10,
             l_margin         => 10,
             r_margin         => 10,
             x_label          => "Hours",
             x_label_position => 0.5,
             x_labels_vertical => 1,
             y_label          => "Counts per Hour",
             y_max_value      => 100,             
             y_tick_number    => 10,
             y_label_skip     => 1,
             dclrs            => [ qw(coral LightYellow4 orange1 orange2) ],
             line_width       => 1,
             long_ticks       => 1,
             markers          => [ 5, 5 ],
             boxclr	      => 'LightGoldenrodYellow', 
	     fgclr            => 'khaki', 	     
             legend_placement => "BT" );

$graph->set_legend( "Total");

GD::Text->font_path( "/usr/lib/X11/fonts/truetype/" );
$graph->set_title_font( "luximr", 16 );
$graph->set_legend_font( "luximr", 10 );
$graph->set_x_axis_font( "luximr", 9 );
$graph->set_x_label_font( "luximr", 11 );
$graph->set_y_axis_font( "luximr", 9 );
$graph->set_y_label_font( "luximr", 11 ); 
################################
my $image = $graph->plot(\@data) or die $graph->error;

Reply With Quote
  #2  
Old May 7th, 2004, 12:31 PM
dog135's Avatar
dog135 dog135 is offline
Doggie
Dev Shed Novice (500 - 999 posts)
 
Join Date: Jul 2003
Location: Seattle, WA
Posts: 751 dog135 User rank is Corporal (100 - 500 Reputation Level)dog135 User rank is Corporal (100 - 500 Reputation Level)dog135 User rank is Corporal (100 - 500 Reputation Level)dog135 User rank is Corporal (100 - 500 Reputation Level) 
Time spent in forums: 10 h 38 m 25 sec
Reputation Power: 7
I don't see any problem with running a select statement that large, though if you run this report often, you may want to make a second table that just contains the hourly averages. That way the report will run fast each time.

You'd update the second table every day, etc. and combine it's data with the averages for the current day's hours, which you would calculate. That way you only calculate the hours for one day at the most.

As far as displaying the data goes, you may need to write your own program. Line graphs are probably the easiest to make of any graphs, so it shouldn't take you long.
__________________
"Science is constructed of facts as a house is of stones. But a collection of facts is no more a science than a heap of stones is a house." - Henri Poincare

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming Languages - MoreSoftware Design > moving average and smoothed calculations for gd::graph


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump


Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 





© 2003-2008 by Developer Shed. All rights reserved. DS Cluster 1 hosted by Hostway
Stay green...Green IT