Ryszard has asked for the wisdom of the Perl Monks concerning the following question:

I'm having a big lot of trouble with Graph::Map, and pumping it (and associated graph) out to the browser.

When i generate the graph (png) and store it on the disk, the image map works perfectly. When i pump the image out to the browser without putting it on disk the image map is incorrect, it is longer and fatter than the area it's supposed to be mapping over. I just dont get it.

#!/usr/bin/perl -w use GD::Graph::bars; use GD::Graph::Map; use CGI qw/:standard/; use Date::Calc qw/Delta_Days Date_to_Text Add_Delta_Days/; my @data = ( ["node1"], ); my @dates = ("11-3-2002","12-4-2002", "15-5-2002","31-12-2002"); my $startdate = $dates[0]; for (my $i=0;$i<$#dates;$i+=1){ my @basedate = split(/-/, $dates[$i] ); my @nextdate = split(/-/, $dates[$i+1]); my $dd = Delta_Days($basedate[2],$basedate[1],$basedate[0], $nextdate[2],$nextdate[1],$nextdate[0]); push @data, [$dd]; } my $my_graph = new GD::Graph::bars(200,500); $my_graph->set_legend( qw(bar1 bar2 bar3)); $my_graph->set( x_label => 'Node', y_label => 'Date', title => "Technology", y_max_value => 365, y_tick_number => 10, y_label_skip => 2, y_number_format => \&y_format, cumulate => 1, borderclrs => 'black', bar_spacing => 4, bar_width => 30, values_vertical => 1, accntclr => 'lgreen', transparent => 0, ); if (length (my $info = path_info())) { my $format= $my_graph->export_format; print header("image/$format"), ($my_graph->plot(\@data))->$format( +); exit 0; } $map = new GD::Graph::Map($my_graph, info => '%l: x=%x y=%y'); $HTML_Map = $map->imagemap(url()."/sample15.png", \@data); print header; print "bit of text here"; print $HTML_Map; sub y_format { my $val = shift; my @ysd = split(/-/, $startdate); my @delta = Add_Delta_Days($ysd[2],$ysd[1],$ysd[0], int($val) ); return substr(Date_to_Text(@delta), 4); }

boo_radley has a good node that covers Graph::Map however doesnt go into "no disk hits".

As a slight aside, I'm attempting to do this as it will save on IO, and I wont have to write a scavange routine to trash the old graphs. The site will only ever have a small load...

If anyone has any experience in doing this, I would appreciate to hear from you.

No this is not production code... :-)

Replies are listed 'Best First'.
Re: Graph::Map and a Browser (no server side storing)
by rob_au (Abbot) on Apr 02, 2002 at 05:49 UTC
    As a slight aside, I'm attempting to do this as it will save on IO, and I wont have to write a scavange routine to trash the old graphs.

    As a counter-point to the desire to write a scavange routine to clean up old graph image files, I would direct your attention to aspects of temporary file handling described previously by myself here - In particular I would direct your attention to the File::Temp module which provides methods for creating and working with temporary files as anonymous STDIO streams which are not stored beyond the life of the file handle.

    This approach, while still encompassing the aspect of IO hits, would allow you to generate your temporary image files without the need for an expensive clean up routine. Mind you though, if the site is only ever going to serve a small audience, is the IO performance hit really going to impact your application or system load greatly?

     

      I've got a couple of thoughts here:
      1. Create something now on a small load site so I have the "theory" down, and can expand onto a larger volume site
      2. Disparity - The web app its pretty much all encompased within the CGI::Application framework, and having a seperate script kicking around loosens the bundle slightly.
      Thanks for the point in "another" direction.. sometimes I just sit here trying to think around the problem and all I end up with HUA syndrome, and cant see the forest for the trees.
        With regard to disparity, while I still think that your best method for handling temporary files will be through File::Temp, there is another option. If you are looking for something more permanent than anonymous STDIO streams and filehandle scope, for example if you wanted to optimise with some server-side caching (for which I would recommend Cache::Cache), you may want to explore the teardown method from CGI::Application.

        This method is called upon termination of the execution thread and allows for clean-up code to easily be incorporated into the CGI::Application framework. Most commonly, I make use of this method for the closure of file handles and database connections prior to script termination.