Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Flat File Database & GD::Graph (REVISITED)

by suggus (Sexton)
on Mar 18, 2002 at 08:25 UTC ( #152427=perlquestion: print w/ replies, xml ) Need Help??
suggus has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,
ok I've spent about 12 hours pulling my hair on this (and I suspect it's a very simple solution). I'm at the point where I just want it to work and I'm not worried about the esthetics (sorry!)...I need to solve this asap.
I have a flat file database like so:
1|1/27|2002|3|26|19|7|7|21|10|3|34|7|73|undef|71|6|20 2|2/03|2002|3|26|19|8|28|21|10|3|34|7|73|undef|72|6|20 3|2/10|2002|3|24|24|8|28|21|10|3|46|7|73|undef|72|8|20 4|2/17|2002|3|22|23|6|28|21|10|3|46|7|73|undef|72|8|20 5|2/24|2002|3|18|23|6|28|22|10|3|46|38|73|undef|72|8|20 6|3/03|2002|3|13|25|6|36|18|28|9|33|38|44|undef|65|8|20 7|3/10|2002|3|13|35|11|50|22|28|9|33|38|44|undef|65|8|20

I have created a test script to test my parsing...I'm sure there are better ways, but I scrapped this one together. It works...I suppose.
#!/usr/local/bin/perl5 -wT print "Content-type: text/html\n\n"; $debug = 0; # Set 1 to enable debug; set to 0 to disable. open(HANDLE,"integrate.dat"); while (<HANDLE>) { chomp; @temp1 = split(/\|/, $_); $domain = unpack ("A5", $temp1[17]); Debug ("$temp1[1]"); # DEBUG BREAK POINT $date .= "$temp1[1] "; $aaa_partners .= "$temp1[4] "; $aaa_arf .= "$temp1[5] "; } close(HANDLE); print $date; print $aaa_partners; print $aaa_arf; sub Debug { if ( $debug ) { my $msg = shift; print $msg, "\n"; } }

The purpose of this test script was to check to make sure that I was able to parse out the values in the database and print the columns. Now let's go onto the actual script itself:

#!/usr/local/bin/perl5 -wT # Declare the stuff we need to use use strict; use CGI; use GD::Graph::linespoints; use constant TITLE => "AAA Days to Integration Average: Line Chart"; my $q = new CGI; my $graph = new GD::Graph::linespoints(600, 300); open(HANDLE,"integrate.dat"); while (<HANDLE>) { chomp; @temp1 = split(/\|/, $_); $domain = unpack ("A5", $temp1[17]); $date .= "$temp1[1] "; $aaa_partners .= "$temp1[4]"; $aaa_arf .= "$temp1[5]"; } close(HANDLE); my @data = ( [ qw ( $date ) ], [ qw ( $aaa_partners ) ], [ qw ( $aaa_arf ) ], ); $graph->set( title => TITLE, x_label => "Third Quarter FY 2002", y_label => "Average Days", long_ticks => 1, y_max_value => 150, y_min_value => 0, y_tick_number => 10, y_label_skip => 0, bar_spacing => 4, types => [ "linespoints", "linespoints" ], dclrs => [ "red", "black" ], ); $graph->set( markers => [1,1] ); $graph->set_legend( "Partners", "ARF" ); my $gd_image = $graph->plot( \@data ); print $q->header( -type => "image/png", -expires => "-1d" ); binmode STDOUT; print $gd_image->png; get_data();

Why the heck is this not working? So far I suspect the problem is the variables I set in the:
my @data = ( [ qw ( $date ) ], [ qw ( $aaa_partners ) ], [ qw ( $aaa_arf ) ], );

But I'm not sure why? What am I doing wrong?

Comment on Flat File Database & GD::Graph (REVISITED)
Select or Download Code
Re: Flat File Database & GD::Graph (REVISITED)
by busunsl (Vicar) on Mar 18, 2002 at 08:32 UTC
    You're probably right.
    Don't use qw with variable names.

    Try this:

    my @data = ( [ $date ], [ $aaa_partners ], [ $aaa_arf ], );
      That didn't work.
      The reason why I used
      my @data = ( [ qw ( $date ) ], [ qw ( $aaa_partners ) ], [ qw ( $aaa_arf ) ], );

      was because the GD::Graph module allows you to format your data without having to use quotes and commas. like so:
      $graph->set( dclrs => [ qw(green pink blue cyan) ] );

      right? ...remind me not to drink 6 cups of coffee in one sitting. ;)
        I see your problem.

        Try to use arrays for $date and so on:

        (untested)

        while (<HANDLE>) { chomp; @temp1 = split(/\|/, $_); $domain = unpack ("A5", $temp1[17]); push @date, $temp1[1]; push @aaa_partners, $temp1[4]; push @aaa_arf, $temp1[5]; } close(HANDLE); my @data = ( \@date, \@aaa_partners, \@aaa_arf );
        GD::Graph module allows you to format your data without having to use quotes and commas. like so:
        $graph->set( dclrs => [ qw(green pink blue cyan) ] );
        It is not the feature of GD::Graph module that is letting you write code like this. It is the magic of the qw operator. Please see the Quote and Quote-like Operators section in perlop.

        /prakash

Re: Flat File Database & GD::Graph (REVISITED)
by tradez (Pilgrim) on Mar 18, 2002 at 18:27 UTC
    A Good practice I have found while working with GD Graphs is that when setting a max value for the y-axis, do it with a little more intuitiveness. Useually when building you @yAxis structures, you do it in a loop, like you are. Try adding a little flare. Also While looking at this I am seeing a discrepency in your logic, if I see this correctly you will not be getting the output I suspect you want. With this you will get a graph with just one point. I would expect you when a linespoints graph with all of the data from the flat file plotted. maybe something like this.
    my $largestValue = 0; my (@xAxisOfDates,@yAxisOfPartners,@yAxisOfArfi, @data) = (); open(HANDLE,"integrate.dat"); while (<HANDLE>) { chomp; @temp1 = split(/\|/, $_); $domain = unpack ("A5", $temp1[17]); push(@xAxisOfDates, $temp1[1]); push(@yAxisOfPartners, $temp1[4]); push(@yAxisOfArf, $temp1[5]); if ($temp1[4] > $largestValue){ $largetValue = $temp1[4]; } if ($temp1[5] > $largestValue){ $largestValue = $temp1[5]; } } close(HANDLE); @data = (\@xAxisOfDates, \@yAxisOfPartners, \@yAxisOfArf);
    and then this in your setup of graph parameters set your y_max_value => $largestValue
    Hopefully this helps and I was able to see why you were not getting what you expected with output, if I was offtarget, /tell me in the talk window and I will help, I am pretty knowledgable when it comes to GD applications.

    Tradez
    "Never underestimate the predicability of stupidity"
    - Bullet Tooth Tony, Snatch (2001)
      Tradez,

      Has this code been tested? I tried it, but still got a 500 error still. I found only 1 typo where it says:
      my (@xAxisOfDates,@yAxisOfPartners,@yAxisOfArfi, @data) = ();

      Where you had an extra 'i' at the end of the array. It should have been:
      my (@xAxisOfDates,@yAxisOfPartners,@yAxisOfArf, @data) = ();

      I suspect that the array is not spacing out the values and GD::Graph module does not like that formatting. Is there another way to do this?
      ---------------------
      I'm always learning.
      zen-designs.com
Re: Flat File Database & GD::Graph (REVISITED)
by suggus (Sexton) on Mar 19, 2002 at 00:16 UTC
    Hi all,
    Thanks to all of you who posted comments on my problem. I know I'm almost there! Why is this script not working? I've spent another good 7 hours trying to debug it, but I still can't figure it out. I know for a fact that it's where the @data array is at (most likely referencing a multidimensional array from 3 seperate arrays?) You can try it for yourself using this data set:
    1|1/27|2002|3|26|19|7|7|21|10|3|34|7|73|undef|71|6|20 2|2/03|2002|3|26|19|8|28|21|10|3|34|7|73|undef|72|6|20 3|2/10|2002|3|24|24|8|28|21|10|3|46|7|73|undef|72|8|20 4|2/17|2002|3|22|23|6|28|21|10|3|46|7|73|undef|72|8|20 5|2/24|2002|3|18|23|6|28|22|10|3|46|38|73|undef|72|8|20 6|3/03|2002|3|13|25|6|36|18|28|9|33|38|44|undef|65|8|20 7|3/10|2002|3|13|35|11|50|22|28|9|33|38|44|undef|65|8|20 8|3/18|2002|3|12|33|11|62|24|28|9|33|38|44|undef|65|undef|undef

    #!/usr/local/bin/perl5 -wT # Declare the stuff we need to use use strict; use CGI; use GD::Graph::linespoints; use constant TITLE => "AAA Days to Integration Average: Line Chart"; my $q = new CGI; my $graph = new GD::Graph::linespoints(600, 300); my $largestValue = 0; my (@xAxisOfDates,@yAxisOfPartners,@yAxisOfArf, @data) = (); open(HANDLE,"integrate.dat"); while (<HANDLE>) { chomp; @temp1 = split(/\|/, $_); $domain = unpack ("A5", $temp1[17]); push (@xAxisOfDates, $temp1[1]); push (@yAxisOfPartners, $temp1[4]); push (@yAxisOfArf, $temp1[5]); if ($temp1[4] > $largestValue){ $largestValue = $temp1[4]; } if ($temp1[5] > $largestValue){ $largestValue = $temp1[5]; } } close(HANDLE); @data = (\@xAxisOfDates, \@yAxisOfPartners, \@yAxisOfArf); $graph->set( title => TITLE, x_label => "Third Quarter FY 2002", y_label => "Average Days", long_ticks => 1, y_max_value => $largestValue, y_min_value => 0, y_tick_number => 10, y_label_skip => 0, bar_spacing => 4, types => [ "linespoints", "linespoints" ], dclrs => [ "red", "black" ], ); $graph->set( markers => [1,1] ); $graph->set_legend( "Partners", "ARF" ); my $gd_image = $graph->plot( \@data ); print $q->header( -type => "image/png", -expires => "-1d" ); binmode STDOUT; print $gd_image->png; get_data();


    I'm always learning. zen-designs.com
      I can't take the time to install GD::Graph right now and test this, but here are some friendly thoughts as to how to effeciently go about debugging your code -- and ask for help when something goes wrong.

      You say the script doesn't work, but don't explain what you mean. Does it crap out with a 500 Internal Server Error? Does it die at a particular line? Does it not produce the results you expect, or nothing at all? The more specific you can be about what you've done and what's going wrong, the more useful responses you'll get.

      I would start by trying to trim the problem down to the smallest possible scope, create a test case that works, and build up from there. Debugging CGI is generally a hassle; can you (temporarily) throw away the CGI part and just try generating the image from the command line? Can you try to generate the simplest possible chart from your data set (leaving out all the legends and other information)? Can you construct an artificial data set with constrained data?

      Once you have a working core, you can incrementally add back features until something breaks, and you will know that whtever change you last made is the one that's causing the problem.

        seattlejohn,
        I'm sorry I failed to note what my errors were (too much coffee is a bad thing you know :P). I did, perform all of my debugging techniques (including the ones you mentioned before asking my fellow monks for assistance). Thanks for your advice though.
        I'm always learning. http://www.zen-designs.com
      Hi,

      While I also am not entirely clear on your problem, I have managed to get your modified code to work simply scoping @temp1 and $domain using my, and by not printing the header out to the same location as the data. The following code generates a PNG image on STDOUT:

      #!/usr/bin/perl -w # Declare the stuff we need to use use strict; use CGI; use GD::Graph::linespoints; use constant TITLE => "AAA Days to Integration Average: Line Chart"; my $q = new CGI; my $graph = new GD::Graph::linespoints(600, 300); my $largestValue = 0; my (@xAxisOfDates,@yAxisOfPartners,@yAxisOfArf, @data) = (); #open(HANDLE,"integrate.dat"); # commented out 'cos I'm using DATA while (<DATA>) { # note DATA here chomp; my @temp1 = split(/\|/, $_); # use strict needs 'my' here my $domain = unpack ("A5", $temp1[17]); # and here push (@xAxisOfDates, $temp1[1]); push (@yAxisOfPartners, $temp1[4]); push (@yAxisOfArf, $temp1[5]); if ($temp1[4] > $largestValue){ $largestValue = $temp1[4]; } if ($temp1[5] > $largestValue){ $largestValue = $temp1[5]; } } #close(HANDLE); # using DATA for simplicity here @data = (\@xAxisOfDates, \@yAxisOfPartners, \@yAxisOfArf); $graph->set( title => TITLE, x_label => "Third Quarter FY 2002", y_label => "Average Days", long_ticks => 1, y_max_value => $largestValue, y_min_value => 0, y_tick_number => 10, y_label_skip => 0, bar_spacing => 4, types => [ "linespoints", "linespoints" ], dclrs => [ "red", "black" ], ); $graph->set( markers => [1,1] ); $graph->set_legend( "Partners", "ARF" ); my $gd_image = $graph->plot( \@data ); # I don't know where you want this, but putting it # in the png doesn't seem to work :-P #print $q->header( -type => "image/png", -expires => "-1d" ); binmode STDOUT; print $gd_image->png; #get_data(); # undefined function; perl not happy __DATA__ 1|1/27|2002|3|26|19|7|7|21|10|3|34|7|73|undef|71|6|20 2|2/03|2002|3|26|19|8|28|21|10|3|34|7|73|undef|72|6|20 3|2/10|2002|3|24|24|8|28|21|10|3|46|7|73|undef|72|8|20 4|2/17|2002|3|22|23|6|28|21|10|3|46|7|73|undef|72|8|20 5|2/24|2002|3|18|23|6|28|22|10|3|46|38|73|undef|72|8|20 6|3/03|2002|3|13|25|6|36|18|28|9|33|38|44|undef|65|8|20 7|3/10|2002|3|13|35|11|50|22|28|9|33|38|44|undef|65|8|20 8|3/18|2002|3|12|33|11|62|24|28|9|33|38|44|undef|65|undef|undef
      Note that I had to turn taint checking off ("Too late for -T option..."). I'm afraid I don't have the time right now to address this issue and must therefore leave it as an exercise for the reader :-)
      I hope this answers your problem.

      Tim

      Update: *sigh*, shows how often I use -T...
      This thread explains the taint problem I was having. In short: don't worry about it :-P

        Hi Tim,

        Thanks for your help! When I tried it it still gave me a 500 error. I checked the code again for another hour and noticed that you commented out the:
        # I don't know where you want this, but putting it # in the png doesn't seem to work :-P #print $q->header( -type => "image/png", -expires => "-1d" );
        When I uncommented it, it worked fine! What was your reasoning as to why this is not needed? When I initially started this project, I took the bare sample from the CGI programming book (mouse book). It had that line of code in there so I just left it there.
        Slowly but surely, I'll get down Perl like the rest of you cool cats! Thank you everyone who contributed. I've gain tons of wisdom from your help. :)
        I'm always learning. http://www.zen-designs.com

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://152427]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2014-12-20 01:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (95 votes), past polls