Diff for /loncom/xml/lonplot.pm between versions 1.54 and 1.94

version 1.54, 2002/03/01 14:03:50 version 1.94, 2004/01/07 18:16:02
Line 34 Line 34
 package Apache::lonplot;  package Apache::lonplot;
   
 use strict;  use strict;
   use warnings FATAL=>'all';
   no warnings 'uninitialized';
 use Apache::File;  use Apache::File;
 use Apache::response;  use Apache::response;
 use Apache::lonxml;  use Apache::lonxml;
Line 91  my %linestyles = Line 93  my %linestyles =
      yerrorbars    => [3,4],       yerrorbars    => [3,4],
      xyerrorbars    => [4,6],       xyerrorbars    => [4,6],
      boxes          => 3,       boxes          => 3,
 #     boxerrorbars   => [3,4,5],  
 #     boxxyerrorbars => [4,6,7],  
 #     financebars    => 5,  
 #     candlesticks   => 5,  
      vector    => 4       vector    => 4
     );          );    
   
 my $int_test       = sub {$_[0]=~s/\s+//g;$_[0]=~/^\d+$/};  my $int_test       = sub {$_[0]=~s/\s+//g;$_[0]=~/^\d+$/};
 my $real_test      =   my $real_test      = 
     sub {$_[0]=~s/\s+//g;$_[0]=~/^[+-]?\d*\.?\d*([eE][+-]\d+)?$/};      sub {$_[0]=~s/\s+//g;$_[0]=~/^[+-]?\d*\.?\d*([eE][+-]\d+)?$/};
 my $color_test     = sub {$_[0]=~s/\s+//g;$_[0]=~/^x[\da-f]{6}$/};  my $pos_real_test  =
       sub {$_[0]=~s/\s+//g;$_[0]=~/^[+]?\d*\.?\d*([eE][+-]\d+)?$/};
   my $color_test     = sub {$_[0]=~s/\s+//g;$_[0]=~/^x[\da-fA-F]{6}$/};
 my $onoff_test     = sub {$_[0]=~/^(on|off)$/};  my $onoff_test     = sub {$_[0]=~/^(on|off)$/};
 my $key_pos_test   = sub {$_[0]=~/^(top|bottom|right|left|outside|below| )+$/};  my $key_pos_test   = sub {$_[0]=~/^(top|bottom|right|left|outside|below| )+$/};
 my $sml_test       = sub {$_[0]=~/^(small|medium|large)$/};  my $sml_test       = sub {$_[0]=~/^(small|medium|large)$/};
 my $linestyle_test = sub {exists($linestyles{$_[0]})};  my $linestyle_test = sub {exists($linestyles{$_[0]})};
 my $words_test     = sub {$_[0]=~s/\s+/ /g;$_[0]=~/^([\w\(\)]+ ?)+$/};  my $words_test     = sub {$_[0]=~s/\s+/ /g;$_[0]=~/^([\w~!\@\#\$\%^&\*\(\)-=_\+\[\]\{\}:\;\'<>,\.\/\?\\]+ ?)+$/};
   
 ###################################################################  ###################################################################
 ##                                                               ##  ##                                                               ##
Line 114  my $words_test     = sub {$_[0]=~s/\s+/ Line 114  my $words_test     = sub {$_[0]=~s/\s+/
 ##                                                               ##  ##                                                               ##
 ###################################################################  ###################################################################
 my @gnuplot_edit_order =   my @gnuplot_edit_order = 
     qw/bgcolor fgcolor height width font transparent grid border align/;      qw/alttag bgcolor fgcolor height width font transparent grid samples 
       border align texwidth texfont plottype/;
   
 my $gnuplot_help_text = <<"ENDPLOTHELP";  my $gnuplot_help_text = <<"ENDPLOTHELP";
 <p>  <p>
Line 144  A <b>gnuplot</b> tag can contain the fol Line 145  A <b>gnuplot</b> tag can contain the fol
     <dd> Allows specification of the x and y coordinate 'tics' on the axes.      <dd> Allows specification of the x and y coordinate 'tics' on the axes.
 This is mostly used to adjust the grid lines when a grid is displayed.  This is mostly used to adjust the grid lines when a grid is displayed.
 </dl>  </dl>
   If you are having trouble with your plot, please read the help
   available on Plot Curve.
 ENDPLOTHELP  ENDPLOTHELP
   
 my %gnuplot_defaults =   my %gnuplot_defaults = 
     (      (
        alttag       => {
    default     => 'dynamically generated plot',
    test        => $words_test,
    description => 'brief description of the plot',
         edit_type   => 'entry',
    size        => '40'
    },
      height       => {       height       => {
  default     => 200,   default     => 300,
  test        => $int_test,   test        => $int_test,
  description => 'height of image (pixels)',   description => 'height of image (pixels)',
       edit_type   => 'entry',        edit_type   => 'entry',
  size        => '10'   size        => '10'
  },   },
      width        => {       width        => {
  default     => 200,   default     => 400,
  test        => $int_test,   test        => $int_test,
  description => 'width of image (pixels)',   description => 'width of image (pixels)',
  edit_type   => 'entry',   edit_type   => 'entry',
Line 183  my %gnuplot_defaults = Line 193  my %gnuplot_defaults =
  edit_type   => 'onoff'   edit_type   => 'onoff'
  },   },
      grid         => {       grid         => {
  default     => 'off',   default     => 'on',
  test        => $onoff_test,    test        => $onoff_test, 
  description => 'Display grid',   description => 'Display grid',
  edit_type   => 'onoff'   edit_type   => 'onoff'
Line 201  my %gnuplot_defaults = Line 211  my %gnuplot_defaults =
  edit_type   => 'choice',   edit_type   => 'choice',
  choices     => ['small','medium','large']   choices     => ['small','medium','large']
  },   },
        samples         => {
    default     => '100',
    test        => $int_test,
    description => 'Number of samples for non-data plots',
    edit_type   => 'choice',
    choices     => ['100','200','500','1000','2000','5000']
    },
      align        => {       align        => {
  default     => 'left',   default     => 'center',
  test        => sub {$_[0]=~/^(left|right|center)$/},   test        => sub {$_[0]=~/^(left|right|center)$/},
  description => 'alignment for image in html',   description => 'alignment for image in html',
  edit_type   => 'choice',   edit_type   => 'choice',
  choices     => ['left','right','center']   choices     => ['left','right','center']
  }    },
        texwidth     => {
            default     => '93',
            test        => $int_test,
            description => 'Width of plot when printed (mm)',
            edit_type   => 'entry',
            size        => '5'
            },
        texfont     => {
            default     => '22',
            test        => $int_test,
            description => 'Font size to use in TeX output (pts):',
            edit_type   => 'choice',
            choices     => [qw/10 12 14 16 18 20 22 24 26 28 30 32 34 36/],
            },
        plottype  => {
    default     => 'Cartesian',
    test        => sub {$_[0]=~/^(Polar|Cartesian)$/},
    description => 'Plot type:',
    edit_type   => 'choice',
            choices     => ['Cartesian','Polar']
            },
      );       );
   
 my %key_defaults =   my %key_defaults = 
Line 260  my %label_defaults = Line 298  my %label_defaults =
      }       }
      );       );
   
 my @tic_edit_order = ('location','mirror','start','increment','end');  my @tic_edit_order = ('location','mirror','start','increment','end',
                         'minorfreq');
 my %tic_defaults =  my %tic_defaults =
     (      (
      location => {       location => {
  default => 'border',    default => 'border', 
  test => sub {$_[0]=~/^(border|axis)$/},   test => sub {$_[0]=~/^(border|axis)$/},
  description => 'Location of tick marks',   description => 'Location of major tic marks',
  edit_type   => 'choice',   edit_type   => 'choice',
  choices     => ['border','axis']   choices     => ['border','axis']
  },   },
      mirror => {       mirror => {
  default => 'on',    default => 'on', 
  test => $onoff_test,   test => $onoff_test,
  description => 'mirror ticks on opposite axis?',   description => 'mirror tics on opposite axis?',
  edit_type   => 'onoff'   edit_type   => 'onoff'
  },   },
      start => {       start => {
  default => '-10.0',   default => '-10.0',
  test => $real_test,   test => $real_test,
  description => 'Start ticks at',   description => 'Start major tics at',
  edit_type   => 'entry',   edit_type   => 'entry',
  size        => '10'   size        => '10'
  },   },
      increment => {       increment => {
  default => '1.0',   default => '1.0',
  test => $real_test,   test => $real_test,
  description => 'Place a tick every',   description => 'Place a major tic every',
  edit_type   => 'entry',   edit_type   => 'entry',
  size        => '10'   size        => '10'
  },   },
      end => {       end => {
  default => ' 10.0',   default => ' 10.0',
  test => $real_test,   test => $real_test,
  description => 'Stop ticks at ',   description => 'Stop major tics at ',
  edit_type   => 'entry',   edit_type   => 'entry',
  size        => '10'   size        => '10'
  },   },
        minorfreq => {
    default => '0',
    test => $int_test,
    description => 'Number of minor tics between major tic marks',
    edit_type   => 'entry',
    size        => '10'
    },         
      );       );
   
   my @axis_edit_order = ('color','xmin','xmax','ymin','ymax');
 my %axis_defaults =   my %axis_defaults = 
     (      (
      color   => {       color   => {
  default => 'x000000',    default => 'x000000', 
  test => $color_test,   test => $color_test,
  description => 'color of axes (x000000)',   description => 'color of grid lines (x000000)',
  edit_type   => 'entry',   edit_type   => 'entry',
  size        => '10'   size        => '10'
  },   },
Line 360  first tag will be the X data and the sec Line 407  first tag will be the X data and the sec
 </p>  </p>
     <dt> Curve Function      <dt> Curve Function
     <dd> The <b>function</b> tag allows you to specify the curve to be       <dd> The <b>function</b> tag allows you to specify the curve to be 
 plotted as a formula that gnuplot can understand.  Be careful using this  plotted as a formula that gnuplot can understand.  <b>Be careful using this
 tag - it is surprisingly easy to give gnuplot a function it cannot deal  tag.</b>  It is surprisingly easy to give gnuplot a function it cannot deal
 with properly.  Be explicit: 2*sin(2*3.141592*x/4) will work but  with properly.  Be explicit: 2*sin(2*3.141592*x/4) will work but
 2sin(2*3.141592x/4) will not.  If you do not receive any errors in the  2sin(2*3.141592x/4) will not.  If you do not receive any errors in the
 gnuplot data but still do not have an image produced, it is likely there  gnuplot data but still do not have an image produced, it is likely there
Line 369  is an error in your <b>function</b> tag. Line 416  is an error in your <b>function</b> tag.
 </dl>  </dl>
 ENDCURVEHELP  ENDCURVEHELP
   
   my @curve_edit_order = ('color','name','linestyle','pointtype','pointsize');
   
 my %curve_defaults =   my %curve_defaults = 
     (      (
      color     => {       color     => {
Line 391  my %curve_defaults = Line 440  my %curve_defaults =
  description => 'Line style',   description => 'Line style',
  edit_type   => 'choice',   edit_type   => 'choice',
  choices     => [keys(%linestyles)]   choices     => [keys(%linestyles)]
  }   },
   # gnuplots term=gif driver does not handle linewidth :(
   #     linewidth => {
   #         default     => 1,
   #         test        => $int_test,
   #         description => 'Line width (may not apply to all line styles)',
   #         edit_type   => 'choice',
   #         choices     => [1,2,3,4,5,6,7,8,9,10]
   #         },
        pointsize => {
            default     => 1,
            test        => $pos_real_test,
            description => 'point size (may not apply to all line styles)',
            edit_type   => 'entry',
            size        => '5'
            },
        pointtype => {
            default     => 1,
            test        => $int_test,
            description => 'point type (may not apply to all line styles)',
            edit_type   => 'choice',
            choices     => [0,1,2,3,4,5,6]
            }
      );       );
   
 ###################################################################  ###################################################################
Line 402  my %curve_defaults = Line 473  my %curve_defaults =
 my (%plot,%key,%axis,$title,$xlabel,$ylabel,@labels,@curves,%xtics,%ytics);  my (%plot,%key,%axis,$title,$xlabel,$ylabel,@labels,@curves,%xtics,%ytics);
   
 sub start_gnuplot {  sub start_gnuplot {
     %plot    = ();      %key     = ();      %axis   = ();       undef(%plot);   undef(%key);    undef(%axis);
     $title   = undef;   $xlabel  = undef;   $ylabel = undef;      undef($title);  undef($xlabel); undef($ylabel);
     $#labels = -1;      $#curves = -1;      undef(@labels); undef(@curves);
     %xtics    = ();      %ytics    = ();      undef(%xtics);  undef(%ytics);
     #      #
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     my $result='';      my $result='';
Line 414  sub start_gnuplot { Line 485  sub start_gnuplot {
       'xtics','ytics'));        'xtics','ytics'));
     push (@Apache::lonxml::namespace,'lonplot');      push (@Apache::lonxml::namespace,'lonplot');
     if ($target eq 'web' || $target eq 'tex') {      if ($target eq 'web' || $target eq 'tex') {
  my $inside = &Apache::lonxml::get_all_text("/gnuplot",$$parser[-1]);  
  $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]);  
  &Apache::lonxml::newparser($parser,\$inside);  
  &get_attributes(\%plot,\%gnuplot_defaults,$parstack,$safeeval,   &get_attributes(\%plot,\%gnuplot_defaults,$parstack,$safeeval,
  $tagstack->[-1]);   $tagstack->[-1]);
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
Line 441  sub end_gnuplot { Line 509  sub end_gnuplot {
     &Apache::lonxml::deregister('Apache::lonplot',      &Apache::lonxml::deregister('Apache::lonplot',
  ('title','xlabel','ylabel','key','axis','label','curve'));   ('title','xlabel','ylabel','key','axis','label','curve'));
     my $result = '';      my $result = '';
       my $randnumber;
       # need to call rand everytime start_script would evaluate, as the
       # safe space rand number generator and the global rand generator 
       # are not seperate
       if ($target eq 'web' || $target eq 'tex' || $target eq 'grade' ||
    $target eq 'answer') {
         $randnumber=int(rand(1000));
       }
     if ($target eq 'web' || $target eq 'tex') {      if ($target eq 'web' || $target eq 'tex') {
  &check_inputs(); # Make sure we have all the data we need   &check_inputs(); # Make sure we have all the data we need
  ##   ##
  ## Determine filename   ## Determine filename
  my $tmpdir = '/home/httpd/perl/tmp/';   my $tmpdir = '/home/httpd/perl/tmp/';
  my $filename = $ENV{'user.name'}.'_'.$ENV{'user.domain'}.   my $filename = $ENV{'user.name'}.'_'.$ENV{'user.domain'}.
     '_'.time.'_'.$$.int(rand(1000)).'_plot.data';      '_'.time.'_'.$$.$randnumber.'_plot';
  ## Write the plot description to the file   ## Write the plot description to the file
  &write_gnuplot_file($tmpdir,$filename,$target);   &write_gnuplot_file($tmpdir,$filename,$target);
  $filename = &Apache::lonnet::escape($filename);   $filename = &Apache::lonnet::escape($filename);
  ## return image tag for the plot   ## return image tag for the plot
  if ($target eq 'web') {   if ($target eq 'web') {
     $result .= <<"ENDIMAGE";      $result .= <<"ENDIMAGE";
 <img src    = "/cgi-bin/plot.gif?file=$filename&output=gif"   <img src    = "/cgi-bin/plot.gif?file=$filename.data&output=gif" 
      width  = "$plot{'width'}"        width  = "$plot{'width'}"
      height = "$plot{'height'}"       height = "$plot{'height'}"
      align  = "$plot{'align'}"       align  = "$plot{'align'}"
      alt    = "image should be /cgi-bin/plot.gif?$filename" />       alt    = "$plot{'alttag'}" />
 ENDIMAGE  ENDIMAGE
         } elsif ($target eq 'tex') {          } elsif ($target eq 'tex') {
     &Apache::lonnet::ssi('cgi-bin/plot.gif?file=$filename'.      #might be inside the safe space, register the URL for later
  '&output=eps');      &Apache::lonxml::register_ssi("/cgi-bin/plot.gif?file=$filename.data&output=eps");
     $result = "$filename.eps";      $result = '\graphicspath{{/home/httpd/perl/tmp/}}\includegraphics[width='.$plot{'texwidth'}.' mm]{'.&Apache::lonnet::unescape($filename).'.eps}';
  }   }
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result.=&Apache::edit::tag_end($target,$token);   $result.=&Apache::edit::tag_end($target,$token);
Line 570  sub start_title { Line 646  sub start_title {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     my $result='';      my $result='';
     if ($target eq 'web' || $target eq 'tex') {      if ($target eq 'web' || $target eq 'tex') {
  $title = &Apache::lonxml::get_all_text("/title",$$parser[-1]);   $title = &Apache::lonxml::get_all_text("/title",$parser);
    $title=&Apache::run::evaluate($title,$safeeval,$$parstack[-1]);
  $title =~ s/\n/ /g;   $title =~ s/\n/ /g;
  if (length($title) > $max_str_len) {   if (length($title) > $max_str_len) {
     $title = substr($title,0,$max_str_len);      $title = substr($title,0,$max_str_len);
  }   }
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result.=&Apache::edit::tag_start($target,$token,'Plot Title');   $result.=&Apache::edit::tag_start($target,$token,'Plot Title');
  my $text=&Apache::lonxml::get_all_text("/title",$$parser[-1]);   my $text=&Apache::lonxml::get_all_text("/title",$parser);
  $result.=&Apache::edit::end_row().   $result.=&Apache::edit::end_row().
     &Apache::edit::start_spanning_row().      &Apache::edit::start_spanning_row().
     &Apache::edit::editfield('',$text,'',60,1);      &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  my $text=$$parser[-1]->get_text("/title");  
  $result.=&Apache::edit::rebuild_tag($token);   $result.=&Apache::edit::rebuild_tag($token);
  $result.=&Apache::edit::modifiedfield($token);   $result.=&Apache::edit::modifiedfield("/title",$parser);
     }      }
     return $result;      return $result;
 }  }
Line 603  sub start_xlabel { Line 679  sub start_xlabel {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     my $result='';      my $result='';
     if ($target eq 'web' || $target eq 'tex') {      if ($target eq 'web' || $target eq 'tex') {
  $xlabel = &Apache::lonxml::get_all_text("/xlabel",$$parser[-1]);   $xlabel = &Apache::lonxml::get_all_text("/xlabel",$parser);
    $xlabel=&Apache::run::evaluate($xlabel,$safeeval,$$parstack[-1]);
  $xlabel =~ s/\n/ /g;   $xlabel =~ s/\n/ /g;
  if (length($xlabel) > $max_str_len) {   if (length($xlabel) > $max_str_len) {
     $xlabel = substr($xlabel,0,$max_str_len);      $xlabel = substr($xlabel,0,$max_str_len);
  }   }
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result.=&Apache::edit::tag_start($target,$token,'Plot Xlabel');   $result.=&Apache::edit::tag_start($target,$token,'Plot Xlabel');
  my $text=&Apache::lonxml::get_all_text("/xlabel",$$parser[-1]);   my $text=&Apache::lonxml::get_all_text("/xlabel",$parser);
  $result.=&Apache::edit::end_row().   $result.=&Apache::edit::end_row().
     &Apache::edit::start_spanning_row().      &Apache::edit::start_spanning_row().
     &Apache::edit::editfield('',$text,'',60,1);      &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  my $text=$$parser[-1]->get_text("/xlabel");  
  $result.=&Apache::edit::rebuild_tag($token);   $result.=&Apache::edit::rebuild_tag($token);
  $result.=&Apache::edit::modifiedfield($token);   $result.=&Apache::edit::modifiedfield("/xlabel",$parser);
     }      }
     return $result;      return $result;
 }  }
Line 637  sub start_ylabel { Line 713  sub start_ylabel {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     my $result='';      my $result='';
     if ($target eq 'web' || $target eq 'tex') {      if ($target eq 'web' || $target eq 'tex') {
  $ylabel = &Apache::lonxml::get_all_text("/ylabel",$$parser[-1]);   $ylabel = &Apache::lonxml::get_all_text("/ylabel",$parser);
    $ylabel = &Apache::run::evaluate($ylabel,$safeeval,$$parstack[-1]);
  $ylabel =~ s/\n/ /g;   $ylabel =~ s/\n/ /g;
  if (length($ylabel) > $max_str_len) {   if (length($ylabel) > $max_str_len) {
     $ylabel = substr($ylabel,0,$max_str_len);      $ylabel = substr($ylabel,0,$max_str_len);
  }   }
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result .= &Apache::edit::tag_start($target,$token,'Plot Ylabel');   $result .= &Apache::edit::tag_start($target,$token,'Plot Ylabel');
  my $text = &Apache::lonxml::get_all_text("/ylabel",$$parser[-1]);   my $text = &Apache::lonxml::get_all_text("/ylabel",$parser);
  $result .= &Apache::edit::end_row().   $result .= &Apache::edit::end_row().
     &Apache::edit::start_spanning_row().      &Apache::edit::start_spanning_row().
     &Apache::edit::editfield('',$text,'',60,1);      &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  my $text=$$parser[-1]->get_text("/ylabel");  
  $result.=&Apache::edit::rebuild_tag($token);   $result.=&Apache::edit::rebuild_tag($token);
  $result.=&Apache::edit::modifiedfield($token);   $result.=&Apache::edit::modifiedfield("/ylabel",$parser);
     }      }
     return $result;      return $result;
 }  }
Line 674  sub start_label { Line 750  sub start_label {
  my %label;   my %label;
  &get_attributes(\%label,\%label_defaults,$parstack,$safeeval,   &get_attributes(\%label,\%label_defaults,$parstack,$safeeval,
     $tagstack->[-1]);      $tagstack->[-1]);
  my $text = &Apache::lonxml::get_all_text("/label",$$parser[-1]);   my $text = &Apache::lonxml::get_all_text("/label",$parser);
    $text = &Apache::run::evaluate($text,$safeeval,$$parstack[-1]);
  $text =~ s/\n/ /g;   $text =~ s/\n/ /g;
  $text = substr($text,0,$max_str_len) if (length($text) > $max_str_len);   $text = substr($text,0,$max_str_len) if (length($text) > $max_str_len);
  $label{'text'} = $text;   $label{'text'} = $text;
Line 682  sub start_label { Line 759  sub start_label {
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result .= &Apache::edit::tag_start($target,$token,'Plot Label');   $result .= &Apache::edit::tag_start($target,$token,'Plot Label');
  $result .= &edit_attributes($target,$token,\%label_defaults);   $result .= &edit_attributes($target,$token,\%label_defaults);
  my $text = &Apache::lonxml::get_all_text("/label",$$parser[-1]);   my $text = &Apache::lonxml::get_all_text("/label",$parser);
  $result .= &Apache::edit::end_row().   $result .= &Apache::edit::end_row().
     &Apache::edit::start_spanning_row().      &Apache::edit::start_spanning_row().
     &Apache::edit::editfield('',$text,'',60,1);      &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  &Apache::edit::get_new_args   &Apache::edit::get_new_args
     ($token,$parstack,$safeeval,keys(%label_defaults));      ($token,$parstack,$safeeval,keys(%label_defaults));
  $result.=&Apache::edit::rebuild_tag($token);   $result.=&Apache::edit::rebuild_tag($token);
  my $text=$$parser[-1]->get_text("/label");   $result.=&Apache::edit::modifiedfield("/label",$parser);
  $result.=&Apache::edit::modifiedfield($token);  
     }      }
     return $result;      return $result;
 }  }
Line 720  sub start_curve { Line 796  sub start_curve {
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result .= &Apache::edit::tag_start($target,$token,'Curve');   $result .= &Apache::edit::tag_start($target,$token,'Curve');
  $result .= &help_win($curve_help_text);   $result .= &help_win($curve_help_text);
  $result .= &edit_attributes($target,$token,\%curve_defaults);   $result .= &edit_attributes($target,$token,\%curve_defaults,
                                       \@curve_edit_order);
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  my $constructtag=&Apache::edit::get_new_args   my $constructtag=&Apache::edit::get_new_args
     ($token,$parstack,$safeeval,keys(%curve_defaults));      ($token,$parstack,$safeeval,keys(%curve_defaults));
Line 750  sub start_function { Line 827  sub start_function {
     my $result='';      my $result='';
     if ($target eq 'web' || $target eq 'tex') {      if ($target eq 'web' || $target eq 'tex') {
  if (exists($curves[-1]->{'data'})) {   if (exists($curves[-1]->{'data'})) {
     &Apache::lonxml::warning('Use of <function> precludes use of <data>.  The <data> will be omitted in favor of the <function> declaration.');      &Apache::lonxml::warning
                   ('Use of the <b>curve function</b> tag precludes use of '.
                    ' the <b>curve data</b> tag.  '.
                    'The curve data tag will be omitted in favor of the '.
                    'curve function declaration.');
     delete $curves[-1]->{'data'} ;      delete $curves[-1]->{'data'} ;
  }   }
  $curves[-1]->{'function'} =           my $function = &Apache::lonxml::get_all_text("/function",$parser);
     &Apache::lonxml::get_all_text("/function",$$parser[-1]);   $function = &Apache::run::evaluate($function,$safeeval,$$parstack[-1]);
    $curves[-1]->{'function'} = $function; 
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result .= &Apache::edit::tag_start($target,$token,'Gnuplot compatible curve function');   $result .= &Apache::edit::tag_start($target,$token,'Gnuplot compatible curve function');
  my $text = &Apache::lonxml::get_all_text("/function",$$parser[-1]);   my $text = &Apache::lonxml::get_all_text("/function",$parser);
  $result .= &Apache::edit::end_row().   $result .= &Apache::edit::end_row().
     &Apache::edit::start_spanning_row().      &Apache::edit::start_spanning_row().
     &Apache::edit::editfield('',$text,'',60,1);      &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  $result.=&Apache::edit::rebuild_tag($token);   $result.=&Apache::edit::rebuild_tag($token);
  my $text=$$parser[-1]->get_text("/function");   $result.=&Apache::edit::modifiedfield("/function",$parser);
  $result.=&Apache::edit::modifiedfield($token);  
     }      }
     return $result;      return $result;
 }  }
Line 785  sub start_data { Line 866  sub start_data {
     my $result='';      my $result='';
     if ($target eq 'web' || $target eq 'tex') {      if ($target eq 'web' || $target eq 'tex') {
  if (exists($curves[-1]->{'function'})) {   if (exists($curves[-1]->{'function'})) {
     &Apache::lonxml::warning('Use of <data> precludes use of .'.      &Apache::lonxml::warning
     '<function>.  The <function> will be omitted in favor of '.                  ('Use of the <b>curve function</b> tag precludes use of '.
             'the <data> declaration.');                   ' the <b>curve data</b> tag.  '.
                    'The curve function tag will be omitted in favor of the '.
                    'curve data declaration.');
     delete($curves[-1]->{'function'});      delete($curves[-1]->{'function'});
  }   }
  my $datatext = &Apache::lonxml::get_all_text("/data",$$parser[-1]);   my $datatext = &Apache::lonxml::get_all_text("/data",$parser);
    $datatext=&Apache::run::evaluate($datatext,$safeeval,$$parstack[-1]);
  # Deal with cases where we're given an array...   # Deal with cases where we're given an array...
  if ($datatext =~ /^\@/) {   if ($datatext =~ /^\@/) {
     $datatext = &Apache::run::run('return "'.$datatext.'"',      $datatext = &Apache::run::run('return "'.$datatext.'"',
Line 810  sub start_data { Line 894  sub start_data {
     # Check that it's non-empty      # Check that it's non-empty
     if (! defined($data[$i])) {      if (! defined($data[$i])) {
  &Apache::lonxml::warning(   &Apache::lonxml::warning(
     'undefined <data> value.  Replacing with '.      'undefined curve data value.  Replacing with '.
     ' pi/e = 1.15572734979092');      ' pi/e = 1.15572734979092');
  $data[$i] = 1.15572734979092;   $data[$i] = 1.15572734979092;
     }      }
     # Check that it's a number      # Check that it's a number
     if (! &$real_test($data[$i]) & ! &$int_test($data[$i])) {      if (! &$real_test($data[$i]) & ! &$int_test($data[$i])) {
  &Apache::lonxml::warning(   &Apache::lonxml::warning(
     'Bad <data> value of '.$data[$i].'  Replacing with '.      'Bad curve data value of '.$data[$i].'  Replacing with '.
     ' pi/e = 1.15572734979092');      ' pi/e = 1.15572734979092');
  $data[$i] = 1.15572734979092;   $data[$i] = 1.15572734979092;
     }      }
Line 832  sub start_data { Line 916  sub start_data {
  push  @{$curves[-1]->{'data'}},\@data;   push  @{$curves[-1]->{'data'}},\@data;
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result .= &Apache::edit::tag_start($target,$token,'Comma or space deliminated curve data');   $result .= &Apache::edit::tag_start($target,$token,'Comma or space deliminated curve data');
  my $text = &Apache::lonxml::get_all_text("/data",$$parser[-1]);   my $text = &Apache::lonxml::get_all_text("/data",$parser);
  $result .= &Apache::edit::end_row().   $result .= &Apache::edit::end_row().
     &Apache::edit::start_spanning_row().      &Apache::edit::start_spanning_row().
     &Apache::edit::editfield('',$text,'',60,1);      &Apache::edit::editline('',$text,'',60);
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  $result.=&Apache::edit::rebuild_tag($token);   $result.=&Apache::edit::rebuild_tag($token);
  my $text=$$parser[-1]->get_text("/data");   $result.=&Apache::edit::modifiedfield("/data",$parser);
  $result.=&Apache::edit::modifiedfield($token);  
     }      }
     return $result;      return $result;
 }  }
Line 863  sub start_axis { Line 946  sub start_axis {
  $tagstack->[-1]);   $tagstack->[-1]);
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result .= &Apache::edit::tag_start($target,$token,'Plot Axes');   $result .= &Apache::edit::tag_start($target,$token,'Plot Axes');
  $result .= &edit_attributes($target,$token,\%axis_defaults);   $result .= &edit_attributes($target,$token,\%axis_defaults,
       \@axis_edit_order);
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  my $constructtag=&Apache::edit::get_new_args   my $constructtag=&Apache::edit::get_new_args
     ($token,$parstack,$safeeval,keys(%axis_defaults));      ($token,$parstack,$safeeval,keys(%axis_defaults));
Line 904  sub set_defaults { Line 988  sub set_defaults {
 sub get_attributes{  sub get_attributes{
     my ($values,$defaults,$parstack,$safeeval,$tag) = @_;      my ($values,$defaults,$parstack,$safeeval,$tag) = @_;
     foreach my $attr (keys(%{$defaults})) {      foreach my $attr (keys(%{$defaults})) {
  $values->{$attr} =    if ($attr eq 'texwidth' || $attr eq 'texfont') {
     &Apache::lonxml::get_param($attr,$parstack,$safeeval);      $values->{$attr} = 
    &Apache::lonxml::get_param($attr,$parstack,$safeeval,undef,1);
    } else {
       $values->{$attr} = 
    &Apache::lonxml::get_param($attr,$parstack,$safeeval);
    }
  if ($values->{$attr} eq '' | !defined($values->{$attr})) {   if ($values->{$attr} eq '' | !defined($values->{$attr})) {
     $values->{$attr} = $defaults->{$attr}->{'default'};      $values->{$attr} = $defaults->{$attr}->{'default'};
     next;      next;
Line 926  sub write_gnuplot_file { Line 1015  sub write_gnuplot_file {
     my ($tmpdir,$filename,$target)= @_;      my ($tmpdir,$filename,$target)= @_;
     my $gnuplot_input = '';      my $gnuplot_input = '';
     my $curve;      my $curve;
       my $pt = $plot{'texfont'};
     # Collect all the colors      # Collect all the colors
     my @Colors;      my @Colors;
     push @Colors, $plot{'bgcolor'};      push @Colors, $plot{'bgcolor'};
Line 946  sub write_gnuplot_file { Line 1036  sub write_gnuplot_file {
  # set output   # set output
  $gnuplot_input .= "set output\n";   $gnuplot_input .= "set output\n";
     } elsif ($target eq 'tex') {      } elsif ($target eq 'tex') {
  $gnuplot_input .= "set term postscript eps monochrome\n";   $gnuplot_input .= "set term postscript eps monochrome solid \"Helvetica\" $pt \n";
  $gnuplot_input .= "set output \"$filename.eps\"\n";   $gnuplot_input .= "set output \"/home/httpd/perl/tmp/".
       &Apache::lonnet::unescape($filename).".eps\"\n";
       }
       # cartesian or polar?
       if (lc($plot{'plottype'}) eq 'polar') {
           $gnuplot_input .= 'set polar'.$/;
       } else {
           # Assume Cartesian
     }      }
     # grid      # grid
     $gnuplot_input .= 'set grid'.$/ if ($plot{'grid'} eq 'on');      $gnuplot_input .= 'set grid'.$/ if ($plot{'grid'} eq 'on');
     # border      # border
     $gnuplot_input .= ($plot{'border'} eq 'on'?      $gnuplot_input .= ($plot{'border'} eq 'on'?
        'set border'.$/           :         'set border'.$/           :
        'set noborder'.$/         );    # title, xlabel, ylabel         'set noborder'.$/         );
       # sampling rate for non-data curves
       $gnuplot_input .= "set samples $plot{'samples'}\n";
       # title, xlabel, ylabel
     # titles      # titles
     $gnuplot_input .= "set title  \"$title\"\n"  if (defined($title)) ;      if ($target eq 'tex') {
     $gnuplot_input .= "set xlabel \"$xlabel\"\n" if (defined($xlabel));          $gnuplot_input .= "set title  \"$title\" font \"Helvetica,".$pt."pt\"\n"  if (defined($title)) ;
     $gnuplot_input .= "set ylabel \"$ylabel\"\n" if (defined($ylabel));          $gnuplot_input .= "set xlabel \"$xlabel\" font \"Helvetica,".$pt."pt\" \n" if (defined($xlabel));
           $gnuplot_input .= "set ylabel \"$ylabel\" font \"Helvetica,".$pt."pt\"\n" if (defined($ylabel));
       } else {
           $gnuplot_input .= "set title  \"$title\"  \n"  if (defined($title)) ;
           $gnuplot_input .= "set xlabel \"$xlabel\" \n" if (defined($xlabel));
           $gnuplot_input .= "set ylabel \"$ylabel\" \n" if (defined($ylabel));
       }
     # tics      # tics
     if (%xtics) {          if (%xtics) {    
  $gnuplot_input .= "set xtics $xtics{'location'} ";   $gnuplot_input .= "set xtics $xtics{'location'} ";
Line 966  sub write_gnuplot_file { Line 1072  sub write_gnuplot_file {
  $gnuplot_input .= "$xtics{'start'}, ";   $gnuplot_input .= "$xtics{'start'}, ";
  $gnuplot_input .= "$xtics{'increment'}, ";   $gnuplot_input .= "$xtics{'increment'}, ";
  $gnuplot_input .= "$xtics{'end'}\n";   $gnuplot_input .= "$xtics{'end'}\n";
           if ($xtics{'minorfreq'} != 0) {
               $gnuplot_input .= "set mxtics ".$xtics{'minorfreq'}."\n";
           } 
     }      }
     if (%ytics) {          if (%ytics) {    
  $gnuplot_input .= "set ytics $ytics{'location'} ";   $gnuplot_input .= "set ytics $ytics{'location'} ";
Line 973  sub write_gnuplot_file { Line 1082  sub write_gnuplot_file {
  $gnuplot_input .= "$ytics{'start'}, ";   $gnuplot_input .= "$ytics{'start'}, ";
  $gnuplot_input .= "$ytics{'increment'}, ";   $gnuplot_input .= "$ytics{'increment'}, ";
         $gnuplot_input .= "$ytics{'end'}\n";          $gnuplot_input .= "$ytics{'end'}\n";
           if ($ytics{'minorfreq'} != 0) {
               $gnuplot_input .= "set mytics ".$ytics{'minorfreq'}."\n";
           } 
     }      }
     # axis      # axis
     if (%axis) {      if (%axis) {
Line 983  sub write_gnuplot_file { Line 1095  sub write_gnuplot_file {
     if (%key) {      if (%key) {
  $gnuplot_input .= 'set key '.$key{'pos'}.' ';   $gnuplot_input .= 'set key '.$key{'pos'}.' ';
  if ($key{'title'} ne '') {   if ($key{'title'} ne '') {
     $gnuplot_input .= 'title " '.$key{'title'}.'" ';      $gnuplot_input .= 'title "'.$key{'title'}.'" ';
  }    } 
  $gnuplot_input .= ($key{'box'} eq 'on' ? 'box ' : 'nobox ').$/;   $gnuplot_input .= ($key{'box'} eq 'on' ? 'box ' : 'nobox ').$/;
     } else {      } else {
Line 993  sub write_gnuplot_file { Line 1105  sub write_gnuplot_file {
     my $label;      my $label;
     foreach $label (@labels) {      foreach $label (@labels) {
  $gnuplot_input .= 'set label "'.$label->{'text'}.'" at '.   $gnuplot_input .= 'set label "'.$label->{'text'}.'" at '.
     $label->{'xpos'}.','.$label->{'ypos'}.' '.$label->{'justify'}.$/ ;      $label->{'xpos'}.','.$label->{'ypos'}.' '.$label->{'justify'}.' font "Helvetica,'.$pt.'pt"'.$/ ;
     }      }
       if ($target eq 'tex') {
           $gnuplot_input .="set size 1,".$plot{'height'}/$plot{'width'}*1.38;
           $gnuplot_input .="\n";
           }
     # curves      # curves
     $gnuplot_input .= 'plot ';      $gnuplot_input .= 'plot ';
     for (my $i = 0;$i<=$#curves;$i++) {      for (my $i = 0;$i<=$#curves;$i++) {
Line 1004  sub write_gnuplot_file { Line 1120  sub write_gnuplot_file {
     $gnuplot_input.=       $gnuplot_input.= 
  $curve->{'function'}.' title "'.   $curve->{'function'}.' title "'.
  $curve->{'name'}.'" with '.   $curve->{'name'}.'" with '.
  $curve->{'linestyle'};                  $curve->{'linestyle'};
               $gnuplot_input.= ' linewidth 4 ' if ($target eq 'tex');
               if (($curve->{'linestyle'} eq 'points')      ||
                   ($curve->{'linestyle'} eq 'linespoints') ||
                   ($curve->{'linestyle'} eq 'errorbars')   ||
                   ($curve->{'linestyle'} eq 'xerrorbars')  ||
                   ($curve->{'linestyle'} eq 'yerrorbars')  ||
                   ($curve->{'linestyle'} eq 'xyerrorbars')) {
                   $gnuplot_input.=' pointtype '.$curve->{'pointtype'};
                   $gnuplot_input.=' pointsize '.$curve->{'pointsize'};
               }
  } elsif (exists($curve->{'data'})) {   } elsif (exists($curve->{'data'})) {
     # Store data values in $datatext      # Store data values in $datatext
     my $datatext = '';      my $datatext = '';
     #   get new filename      #   get new filename
     my $datafilename = "$tmpdir/$filename.$i";      my $datafilename = "$tmpdir/$filename.data.$i";
     my $fh=Apache::File->new(">$datafilename");      my $fh=Apache::File->new(">$datafilename");
     # Compile data      # Compile data
     my @Data = @{$curve->{'data'}};      my @Data = @{$curve->{'data'}};
Line 1028  sub write_gnuplot_file { Line 1154  sub write_gnuplot_file {
     $gnuplot_input.= '"'.$datafilename.'" title "'.      $gnuplot_input.= '"'.$datafilename.'" title "'.
  $curve->{'name'}.'" with '.   $curve->{'name'}.'" with '.
  $curve->{'linestyle'};   $curve->{'linestyle'};
               $gnuplot_input.= ' linewidth 4 ' if ($target eq 'tex');
               if (($curve->{'linestyle'} eq 'points')      ||
                   ($curve->{'linestyle'} eq 'linespoints') ||
                   ($curve->{'linestyle'} eq 'errorbars')   ||
                   ($curve->{'linestyle'} eq 'xerrorbars')  ||
                   ($curve->{'linestyle'} eq 'yerrorbars')  ||
                   ($curve->{'linestyle'} eq 'xyerrorbars')) {
                   $gnuplot_input.=' pointtype '.$curve->{'pointtype'};
                   $gnuplot_input.=' pointsize '.$curve->{'pointsize'};
               }
  }   }
     }      }
     # Write the output to a file.      # Write the output to a file.
     my $fh=Apache::File->new(">$tmpdir$filename");      my $fh=Apache::File->new(">$tmpdir$filename.data");
     print $fh $gnuplot_input;      print $fh $gnuplot_input;
     close($fh);      close($fh);
     # That's all folks.      # That's all folks.
Line 1056  sub check_inputs { Line 1192  sub check_inputs {
     my $curve;      my $curve;
     foreach $curve (@curves) {      foreach $curve (@curves) {
  if (!defined($curve->{'function'})&&!defined($curve->{'data'})){   if (!defined($curve->{'function'})&&!defined($curve->{'data'})){
     &Apache::lonxml::warning("One of the curves specified did not contain any <data> or <function> declarations\n");      &Apache::lonxml::warning("One of the curves specified did not contain any curve data or curve function declarations\n");
     return '';      return '';
  }   }
     }      }
Line 1101  sub edit_attributes { Line 1237  sub edit_attributes {
 sub insert_gnuplot {  sub insert_gnuplot {
     my $result = '';      my $result = '';
     #  plot attributes      #  plot attributes
     $result .= "<gnuplot \n";      $result .= "\n<gnuplot ";
     foreach my $attr (keys(%gnuplot_defaults)) {      foreach my $attr (keys(%gnuplot_defaults)) {
  $result .= "     $attr=\"$gnuplot_defaults{$attr}->{'default'}\"\n";   $result .= "\n     $attr=\"$gnuplot_defaults{$attr}->{'default'}\"";
     }      }
     $result .= ">\n";      $result .= ">";
     # Add the components (most are commented out for simplicity)      # Add the components (most are commented out for simplicity)
     # $result .= &insert_key();      # $result .= &insert_key();
     # $result .= &insert_axis();      # $result .= &insert_axis();
Line 1114  sub insert_gnuplot { Line 1250  sub insert_gnuplot {
     # $result .= &insert_ylabel();          # $result .= &insert_ylabel();    
     $result .= &insert_curve();      $result .= &insert_curve();
     # close up the <gnuplot>      # close up the <gnuplot>
     $result .= "</gnuplot>\n";      $result .= "\n</gnuplot>";
     return $result;      return $result;
 }  }
   
Line 1128  sub insert_xtics { Line 1264  sub insert_xtics {
     my $result;      my $result;
     $result .= "\n    <xtics ";      $result .= "\n    <xtics ";
     foreach my $attr (keys(%tic_defaults)) {      foreach my $attr (keys(%tic_defaults)) {
  $result .= "$attr=\"$tic_defaults{$attr}->{'default'}\" ";   $result .= "\n        $attr=\"$tic_defaults{$attr}->{'default'}\" ";
     }      }
     $result .= "/>\n";      $result .= "/>";
     return $result;      return $result;
 }  }
   
Line 1138  sub insert_ytics { Line 1274  sub insert_ytics {
     my $result;      my $result;
     $result .= "\n    <ytics ";      $result .= "\n    <ytics ";
     foreach my $attr (keys(%tic_defaults)) {      foreach my $attr (keys(%tic_defaults)) {
  $result .= "$attr=\"$tic_defaults{$attr}->{'default'}\" ";   $result .= "\n        $attr=\"$tic_defaults{$attr}->{'default'}\" ";
     }      }
     $result .= "/>\n";      $result .= "/>";
     return $result;      return $result;
 }  }
   
 sub insert_key {  sub insert_key {
     my $result;      my $result;
     $result .= "\n    <key \n";      $result .= "\n    <key ";
     foreach my $attr (keys(%key_defaults)) {      foreach my $attr (keys(%key_defaults)) {
  $result .= "         $attr=\"$key_defaults{$attr}->{'default'}\"\n";   $result .= "\n         $attr=\"$key_defaults{$attr}->{'default'}\"";
     }      }
     $result .= "   />\n";      $result .= " />";
     return $result;      return $result;
 }  }
   
Line 1158  sub insert_axis{ Line 1294  sub insert_axis{
     my $result;      my $result;
     $result .= "\n    <axis ";      $result .= "\n    <axis ";
    foreach my $attr (keys(%axis_defaults)) {     foreach my $attr (keys(%axis_defaults)) {
  $result .= "         $attr=\"$axis_defaults{$attr}->{'default'}\"\n";   $result .= "\n         $attr=\"$axis_defaults{$attr}->{'default'}\"";
     }      }
     $result .= "   />\n";      $result .= " />";
     return $result;      return $result;
 }  }
   
 sub insert_title { return "\n    <title></title>\n"; }  sub insert_title  { return "\n    <title></title>"; }
 sub insert_xlabel { return "\n    <xlabel></xlabel>\n"; }  sub insert_xlabel { return "\n    <xlabel></xlabel>"; }
 sub insert_ylabel { return "\n    <ylabel></ylabel>\n"; }  sub insert_ylabel { return "\n    <ylabel></ylabel>"; }
   
 sub insert_label {  sub insert_label {
     my $result;      my $result;
     $result .= "\n    <label ";      $result .= "\n    <label ";
     foreach my $attr (keys(%label_defaults)) {      foreach my $attr (keys(%label_defaults)) {
  $result .= '         '.$attr.'="'.   $result .= "\n         $attr=\"".
     $label_defaults{$attr}->{'default'}."\"\n";              $label_defaults{$attr}->{'default'}."\"";
     }      }
     $result .= "   ></label>\n";      $result .= "></label>";
     return $result;      return $result;
 }  }
   
Line 1183  sub insert_curve { Line 1319  sub insert_curve {
     my $result;      my $result;
     $result .= "\n    <curve ";      $result .= "\n    <curve ";
     foreach my $attr (keys(%curve_defaults)) {      foreach my $attr (keys(%curve_defaults)) {
  $result .= '         '.$attr.'="'.   $result .= "\n         $attr=\"".
     $curve_defaults{$attr}->{'default'}."\"\n";      $curve_defaults{$attr}->{'default'}."\"";
     }      }
     $result .= "    >\n";      $result .= " >";
     $result .= &insert_data().&insert_data()."</curve>\n";      $result .= &insert_data().&insert_data()."\n    </curve>";
 }  }
   
 sub insert_function {  sub insert_function {
     my $result;      my $result;
     $result .= "<function></function>\n";      $result .= "\n        <function></function>";
     return $result;      return $result;
 }  }
   
 sub insert_data {  sub insert_data {
     my $result;      my $result;
     $result .= "     <data></data>\n";      $result .= "\n        <data></data>";
     return $result;      return $result;
 }  }
   

Removed from v.1.54  
changed lines
  Added in v.1.94


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>