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

I'm new to this so please excuse ignorance. Thanks in advance for your help.

Output looks like this

I've searched the docs but can't see an example to do what I want. I'm wanting to put two separate lines on a gd::graph which I can achieve. The problem is aligning them AND retaining the second set of x-axis labels distinguished (and preferably below) below the first (ie. I want the green x-axis labels below the red, otherwise they don't all fit and it gets very confusing). I guess the question is really how do you offset the x-axis labels without off-setting the graphs and sort out the mess I've ended up with...

Code looks like this:

$sth->bind_columns(\($year,$pop,$notes,$name)); my (@pop_loop); while ($sth->fetch) { my (%row); $row{YEAR} = $year; $row{POP} = $pop; $row{SEQNO} = $seqno; $row{NOTES} = $notes; push (@pop_loop,\%row); if ($pop > $maxy) { $maxy=$pop } # print "$year - $pop\n"; if ($year > 1900) { push(@{$graph_data1[0]},$year); push(@{$graph_data1[1]},$pop); $data1_exists = 1; } else { push(@{$graph_data2[0]},$year); push(@{$graph_data2[1]},$pop); $data2_exists = 1; } } if ($maxy == 0) { # This is not ideal as it needs to be updated with every census! $row{YEAR} = "2001"; $row{POP} = "N/A"; push (@pop_loop,\%row); return(\@pop_loop,$sth->rows) } if (length($name) < 20) { $name = "POPULATION TREND: ".uc($name); } else { $name = "POP TREND: ".uc($name); } ##The maximum value for printed on the new line.If the max value on th +e y axis is less than 1000, to round it up to the next full value, ##that max value should be multiply by 1.2/100 and again multiply by 1 +00 if ($maxy < 1000) { $maxy=ceil(($maxy*1.2)/100)*100; } elsif ($maxy < 10000) { $maxy=ceil(($maxy*1.2)/1000)*1000; } elsif ($maxy < 100000) { $maxy=ceil(($maxy*1.2)/10000)*10000; } elsif ($maxy > 100001) { $maxy=ceil(($maxy*1.2)/100000)*100000; } my $mygraph = GD::Graph::linespoints->new(320, 160); $mygraph->set( x_label => 'YEAR', y_label=> 'POPULATION', title => $name, fgclr => '#804000', labelclr => '#2B60DE', textclr => '#000000', line_types=> [1], line_width=> 2, long_ticks=> 1, dclrs => ['red'], markers => [5], y_max_value =>$maxy, y_min_value => 0, y_label_skip => 0, y_label_position => 1/2, x_label_position => 1/2, #bgclr => 'blue', labelclr => 'dblue', axislabelclr => 'red', textclr => 'red', text_space=> 4, tick_length => 4, y_tick_number=> 4, show_values => 1, x_labels_vertical => 0, ) or warn $mygraph->error; $mygraph->set_legend_font(GD::gdMediumBoldFont); $mygraph->set_title_font(GD::gdMediumBoldFont); $mygraph->set_x_axis_font( "Giant" ); $mygraph->set_x_label_font(GD::gdMediumBoldFont); $mygraph->set_y_axis_font( "luximr", 9 ); $mygraph->set_y_label_font(GD::gdMediumBoldFont); if ($data1_exists) { $myimage = $mygraph->plot(\@graph_data1) or die +$mygraph->error } $mygraph->set( textclr => '#000000', line_width=> 2, dclrs => ['green'], y_label_position => 1/2, x_label_position => 1/2, #bgclr => 'blue', labelclr => 'dblue', axislabelclr => 'green', textclr => 'red', text_space=> 4, long_ticks=>0, tick_length => 0, y_tick_number=> 4, show_values => 1, x_labels_vertical => 0, x_label => '', y_label => '' ) or warn $mygraph->error; if ($data2_exists) { $myimage = $mygraph->plot(\@graph_data2) or die $ +mygraph->error } open (OUTPUT, ">$hostpath/graphs/pop$seqno.png"); print OUTPUT $myimage->png; close OUTPUT;

Replies are listed 'Best First'.
Re: Multiple data sets on one gd::graph
by GrandFather (Saint) on Aug 09, 2007 at 02:10 UTC

    What do you mean "lined up". Do you mean you want to do some sort of curve fit so that you can interpolate points and calculate a Y value for specific X values? Do you mean that you want the same X scaling for each line? What is the graph supposed to show (how is it expected to be used)?


    DWIM is Perl's answer to Gödel
      Apols for lack of clarity

      By 'lined-up' I mean consistent Y axis, for both lines (green and red), no over-writing axis titles, or double labelling on y-axis and consistent origin. But I would like to have two sets of x axis labels (one red, one green) to show that there are two sets of years (one 19th century, one 20th century). Basically this is a popultion graph, with one line for each century. Drawing the lines themseles seems fine, its the axis labelling that's a problem.

      Thanks!

        I'd be inclined to draw just one set of year labeling using just the tens digits for the year and provide a key for the century line colors. If the users really need the precise data it should be provided in an accompanying table - the graph really just shows the trends.


        DWIM is Perl's answer to Gödel
Re: Multiple data sets on one gd::graph
by CountZero (Bishop) on Aug 09, 2007 at 06:14 UTC
    I am no GD-guru at all, but perhaps the following can help you (the actual implementation is left to you):

    • make the red grid with all labels as usual
    • add the red data to this grid; then add the green data to this grid (but do not include axis labels for the green data)
    • make the green 'grid' which only consists of the 'year' labels, offset as required
    • combine all into one graph

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James