[LON-CAPA-cvs] cvs: loncom /cgi graph.png /interface loncommon.pm

matthew lon-capa-cvs@mail.lon-capa.org
Mon, 27 Oct 2003 21:21:08 -0000


This is a MIME encoded message

--matthew1067289668
Content-Type: text/plain

matthew		Mon Oct 27 16:21:08 2003 EDT

  Modified files:              
    /loncom/interface	loncommon.pm 
    /loncom/cgi	graph.png 
  Log:
  Complete rewrite of how graph.png works and of the interface routines for
  it in loncommon.pm.  Added &DrawXYGraph which occasionally works.
  
  
--matthew1067289668
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20031027162108.txt"

Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.135 loncom/interface/loncommon.pm:1.136
--- loncom/interface/loncommon.pm:1.135	Fri Oct 24 17:09:24 2003
+++ loncom/interface/loncommon.pm	Mon Oct 27 16:21:08 2003
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.135 2003/10/24 21:09:24 albertel Exp $
+# $Id: loncommon.pm,v 1.136 2003/10/27 21:21:08 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2678,6 +2678,10 @@
     return undef;
 }
 
+sub get_cgi_id {
+    return (time.'_'.int(rand(1000)));
+}
+
 ############################################################
 ############################################################
 
@@ -2685,7 +2689,6 @@
 
 =item DrawBarGraph
 
-
 =cut
 
 ############################################################
@@ -2700,7 +2703,8 @@
                   ]; 
     }
     #
-    my $identifier = time.'_'.int(rand(1000));
+    my $identifier = &get_cgi_id();
+    my $id = 'cgi.'.$identifier;        
     if (! @Values || ref($Values[0]) ne 'ARRAY') {
         return '';
     }
@@ -2709,16 +2713,50 @@
     my $NumSets=1;
     foreach my $array (@Values) {
         next if (! ref($array));
-        $ValuesHash{'cgi.'.$identifier.'.data.'.$NumSets++} = 
+        $ValuesHash{$id.'.data.'.$NumSets++} = 
             join(',',@$array);
     }
     #
+    my ($height,$width,$xskip,$bar_width) = (200,120,1,15);
+    if ($NumBars < 10) {
+        $width = 120+$NumBars*15;
+        $xskip = 1;
+        $bar_width = 15;
+    } elsif ($NumBars <= 25) {
+        $width = 120+$NumBars*11;
+        $xskip = 5;
+        $bar_width = 8;
+    } elsif ($NumBars <= 50) {
+        $width = 120+$NumBars*8;
+        $xskip = 5;
+        $bar_width = 4;
+    } else {
+        $width = 120+$NumBars*8;
+        $xskip = 5;
+        $bar_width = 4;
+    }
+    #
+    my @Labels;
+    for (my $i=0;$i<@{$Values[0]};$i++) {
+        push (@Labels,$i+1);
+    }
+    #
     $Title  = '' if (! defined($Title));
     $xlabel = '' if (! defined($xlabel));
     $ylabel = '' if (! defined($ylabel));
-    $Title  = &Apache::lonnet::escape($Title);
-    $xlabel = &Apache::lonnet::escape($xlabel);
-    $ylabel = &Apache::lonnet::escape($ylabel);
+    $ValuesHash{$id.'.title'}    = &Apache::lonnet::escape($Title);
+    $ValuesHash{$id.'.xlabel'}   = &Apache::lonnet::escape($xlabel);
+    $ValuesHash{$id.'.ylabel'}   = &Apache::lonnet::escape($ylabel);
+    $ValuesHash{$id.'.Max'}      = $Max;
+    $ValuesHash{$id.'.NumBars'}  = $NumBars;
+    $ValuesHash{$id.'.NumSets'}  = $NumSets;
+    $ValuesHash{$id.'.PlotType'} = 'bar';
+    $ValuesHash{$id.'.Colors'}   = join(',',@{$colors});
+    $ValuesHash{$id.'.height'}   = $height;
+    $ValuesHash{$id.'.width'}    = $width;
+    $ValuesHash{$id.'.xskip'}    = $xskip;
+    $ValuesHash{$id.'.bar_width'} = $bar_width;
+    $ValuesHash{$id.'.labels'} = join(',',@Labels);
     #
     $Max = 1 if ($Max < 1);
     if ( int($Max) < $Max ) {
@@ -2726,14 +2764,52 @@
         $Max = int($Max);
     }
     #
-    &Apache::lonnet::appenv('cgi.'.$identifier.'.title'   => $Title,
-                            'cgi.'.$identifier.'.xlabel'  => $xlabel,
-                            'cgi.'.$identifier.'.ylabel'  => $ylabel,
-                            'cgi.'.$identifier.'.Max'     => $Max,
-                            'cgi.'.$identifier.'.NumBars' => $NumBars,
-                            'cgi.'.$identifier.'.NumSets' => $NumSets,
-                            'cgi.'.$identifier.'.Colors'  => join(',',@{$colors}),
-                            %ValuesHash);
+    &Apache::lonnet::appenv(%ValuesHash);
+    return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
+}
+
+############################################################
+############################################################
+
+=pod
+
+=item DrawXYGraph
+
+=cut
+
+############################################################
+############################################################
+sub DrawXYGraph {
+    my ($Title,$xlabel,$ylabel,$Max,$Xlabels,$Ydata,%Values)=@_;
+    #
+    # Create the identifier for the graph
+    my $identifier = &get_cgi_id();
+    my $id = 'cgi.'.$identifier;
+    #
+    $Title  = '' if (! defined($Title));
+    $xlabel = '' if (! defined($xlabel));
+    $ylabel = '' if (! defined($ylabel));
+    my %ValuesHash = 
+        (
+         $id.'.title'  => &Apache::lonnet::escape($Title),
+         $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
+         $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
+         $id.'.Max'    => $Max,
+         $id.'.labels' => join(',',@$Xlabels),
+         $id.'.PlotType' => 'XY',
+         $id.'.NumSets' => 2,
+         );
+    #
+    if (! ref($Ydata) || ref($Ydata) ne 'ARRAY') {
+        return '';
+    }
+    my $NumSets=1;
+    foreach my $array ($Ydata){
+        next if (! ref($array));
+        $ValuesHash{$id.'.data.'.$NumSets++} = join(',',@$array);
+    }
+    #
+    &Apache::lonnet::appenv(%ValuesHash);
     return '<img src="/cgi-bin/graph.png?'.$identifier.'" border="1" />';
 }
 
Index: loncom/cgi/graph.png
diff -u loncom/cgi/graph.png:1.28 loncom/cgi/graph.png:1.29
--- loncom/cgi/graph.png:1.28	Tue Oct 21 11:19:25 2003
+++ loncom/cgi/graph.png	Mon Oct 27 16:21:08 2003
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 #
-# $Id: graph.png,v 1.28 2003/10/21 15:19:25 matthew Exp $
+# $Id: graph.png,v 1.29 2003/10/27 21:21:08 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -57,6 +57,7 @@
 use strict;
 use lib '/home/httpd/lib/perl';
 use GD::Graph::bars;
+use GD::Graph::lines;
 use GD::Graph::colour;
 use GD::Graph::Data;
 use LONCAPA::loncgi();
@@ -67,6 +68,35 @@
     return $str;
 }
 
+sub error {
+    my ($error) = @_;
+    my $Str = <<"END";
+Content-type: text/html
+
+<html>
+<head><title>Bad Graph</title></head>
+<body>
+<p>
+There was an error producing the graph you requested.
+</p><p>
+$error
+</p>
+</body>
+</html>
+END
+    return $Str;
+}
+
+my $id = $ENV{'QUERY_STRING'};
+
+#
+# &get_env($name,$default)
+sub get_env {
+    my $key = 'cgi.'.$id.'.'.(shift());
+    return shift if (! exists($ENV{$key}));
+    return $ENV{$key};
+}
+
 if (! &LONCAPA::loncgi::check_cookie_and_load_env()) {
     print <<END;
 Content-type: text/html
@@ -82,75 +112,24 @@
 }
 
 $|=1;   # Autoflush after each print/write
-my $identifier = $ENV{'QUERY_STRING'};
-my $Title   = &unescape($ENV{'cgi.'.$identifier.'.title'});
-my $xlabel  = &unescape($ENV{'cgi.'.$identifier.'.xlabel'});
-my $ylabel  = &unescape($ENV{'cgi.'.$identifier.'.ylabel'});
-my $Max     = $ENV{'cgi.'.$identifier.'.Max'};
-my $NumBars = $ENV{'cgi.'.$identifier.'.NumBars'};
-my $NumSets = $ENV{'cgi.'.$identifier.'.NumSets'};
-my @Colors  = split(',',$ENV{'cgi.'.$identifier.'.Colors'});
-
-#
-# Labels are always digits
-my @xlabels;
-for (my $nIdx=0; $nIdx<$NumBars; $nIdx++ ) {
-    $xlabels[$nIdx]=$nIdx+1;
-}
-my @data;  # stores the data for the graph
-push(@data,\@xlabels);
-for (my $i=1;$i<=$NumSets;$i++) {
-    push(@data,[split(',',$ENV{'cgi.'.$identifier.'.data.'.$i})]);
-}
-
-my $skip_x = 1;
-my $bar_width=10;
-
-#
-# Customize graph based on the 
-my $width;
-my $height = 200;
-
-if ($NumBars < 10) {
-    $width = 120+$NumBars*15;
-    $skip_x = 1;
-    $bar_width = 15;
-} elsif ($NumBars <= 25) {
-    $width = 120+$NumBars*11;
-    $skip_x = 5;
-    $bar_width = 8;
-} elsif ($NumBars <= 50) {
-    $width = 120+$NumBars*8;
-    $skip_x = 5;
-    $bar_width = 4;
-} else {
-    $width = 120+$NumBars*8;
-    $skip_x = 5;
-    $bar_width = 4;
-}
 
-my $x_tick_offset = 0;
-if ($skip_x > 1) {
-    $x_tick_offset = $skip_x - 1;
-}
-
-my $MyGraph = GD::Graph::bars->new($width,$height);
-my $error = '';
-if (! $MyGraph->set( x_label         => $xlabel,
-                     y_label         => $ylabel,
+my $colordefaults = join(',',
+                         ('#33ff00', 
+                          '#0033cc','#990000','#aaaa66','#663399','#ff9933',
+                          '#66ccff','#ff9999','#cccc33','#660000','#33cc66',
+                          ));
+
+my $height   = &get_env('height',300);
+my $width    = &get_env('width', 400);
+my $PlotType = &get_env('PlotType','bar');
+
+my %GraphSettings = (
+                     title           => &unescape(&get_env('title','')),
+                     x_label         => &unescape(&get_env('xlabel','')),
+                     y_label         => &unescape(&get_env('ylabel','')),
                      x_label_position => 0.5,
-                     long_ticks      => 1,
-                     tick_length     => 0,
-                     x_ticks         => 0,
-                     title           => $Title,
-                     y_max_value     => $Max,
-                     x_label_skip    => $skip_x,   
-                     x_tick_offset   => $x_tick_offset,
-                     #
-                     dclrs           => \@Colors,
-                     bar_width       => $bar_width,
-                     cumulate        => 2,
-                     zero_axis       => 1,
+                     dclrs           => [split(',',&get_env('Colors',
+                                                            $colordefaults))],
                      fgclr           => 'black',
                      boxclr          => 'white',
                      accentclr       => 'dblue',
@@ -159,60 +138,85 @@
                      b_margin        => 10,
                      r_margin        => 10,
                      t_margin        => 10,
-                     #
                      transparent     => 0,
-                     )) {
-    $error = $MyGraph->error;
-    print <<"END";
-Content-type: text/html
+                     );
 
-<html>
-<head><title>Bad Graph</title></head>
-<body>
-<p>
-There was an error producing the graph you requested.
-</p><p>
-$error
-</p>
-</body>
-</html>
-END
+$GraphSettings{'x_label_skip'}  = &get_env('xskip',1);
+$GraphSettings{'x_tick_offset'} = &get_env('x_tick_offset',0);
+$GraphSettings{'y_max_value'}   = &get_env('Max',undef);
+
+my $MyGraph;
+if ($PlotType eq 'bar') {
+    # Pick up bar graph settings
+    $GraphSettings{'bar_width'}     = &get_env('bar_width',undef);
+    $GraphSettings{'long_ticks'}    = 1;
+    $GraphSettings{'tick_length'}   = 0;
+    $GraphSettings{'x_ticks'}       = 0;
+    $GraphSettings{'cumulate'}      = 2;
+    $GraphSettings{'zero_axis'}     = 1;
+} else {
+    #
+    # X label skip setup
+    my $skip_x = &get_env('xskip',1);
+    my $x_tick_offset = &get_env('x_tick_offset',$skip_x-1);
+    my $zero_axis = &get_env('zero_axis',1);
+    #
+    # Fill up %GraphSettings
+    $GraphSettings{'long_ticks'}    = 1;
+    $GraphSettings{'tick_length'}   = 0;
+    $GraphSettings{'x_ticks'}       = &get_env('x_ticks',0),;
+    $GraphSettings{'x_label_skip'}  = $skip_x;
+    $GraphSettings{'x_tick_offset'} = $x_tick_offset;
+    $GraphSettings{'zero_axis'}     = 1;
+}
+#
+# Pick up miscellanious values passed in by the user
+#
+# Create the plot and check it out
+if ($PlotType eq 'bar') {
+    $MyGraph = GD::Graph::bars->new($width,$height);
+} else {
+    $MyGraph = GD::Graph::lines->new($width,$height);
+}
+if (! defined($MyGraph)) {
+    print &error('Unable to create initial graph');
     return;
 }
 
-my $plot = $MyGraph->plot(\@data);
-if (! defined($plot)) {
-    print <<"END";
-Content-type: text/html
+##
+## Build the @Data array
+my $NumSets = &get_env('NumSets');
+my @Data;  # stores the data for the graph
+my @xlabels  = split(',',&get_env('labels'));
+push(@Data,\@xlabels);
+for (my $i=1;$i<=$NumSets;$i++) {
+    push(@Data,[split(',',&get_env('data.'.$i))]);
+}
 
-<html>
-<head><title>Bad Graph</title></head>
-<body>
-The system was unable to create the graph you requested.
-</body>
-</html>
-END
+my $error = '';
+if (! $MyGraph->set(%GraphSettings)) {
+    print &error($MyGraph->error);
     return;
 }
 
+my $plot = $MyGraph->plot(\@Data);
+if (! defined($plot)) {
+    my $error = 'Unable to plot the data provided.';
+    $error .= '<pre>'.join(',',@{$Data[0]}).'</pre>';
+    $error .= '<pre>'.join(',',@{$Data[1]}).'</pre>';
+    $error .= '<pre>'.join(',',@{$Data[2]}).'</pre>';
+    print &error($error);
+    exit;
+}
+
 my $BinaryData=$plot->png;
 undef($MyGraph);
 undef($plot);
 
 if (! defined($BinaryData)) {
-    print <<"END";
-Content-type: text/html
-
-<html>
-<head><title>Bad Graph</title></head>
-<body>
-The system was unable to produce a png image of the graph you requested.
-</body>
-</html>
-END
-    return;
+    print &error('Unable to render graph as image');
+    exit;
 }
-
 
 # Tell the server we are sending a png graphic
 print <<END;

--matthew1067289668--