Diff for /loncom/xml/lonplot.pm between versions 1.51 and 1.91

version 1.51, 2002/02/27 22:10:23 version 1.91, 2003/09/27 04:08:56
Line 29 Line 29
 # 12/17 12/18 12/19 12/20 12/21 12/27 12/28 12/30 12/31 Matthew  # 12/17 12/18 12/19 12/20 12/21 12/27 12/28 12/30 12/31 Matthew
 # 01/01/02 Matthew  # 01/01/02 Matthew
 # 01/02 01/03 01/04 01/07 01/08 01/09 Matthew  # 01/02 01/03 01/04 01/07 01/08 01/09 Matthew
 # 01/21 02/05 02/06 Matthew  # 01/21 02/05 02/06 2/28Matthew
   
 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 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'
            },
        plottype  => {
    default     => 'Cartesian',
    test        => sub {$_[0]=~/^(Polar|Cartesian)$/},
    description => 'Plot type:',
    edit_type   => 'choice',
            choices     => ['Polar','Cartesian']
            },
      );       );
   
 my %key_defaults =   my %key_defaults = 
Line 260  my %label_defaults = Line 291  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 400  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 409  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 433  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 466  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 478  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 502  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);
  ## 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?$filename"   <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') {
     $result = "$filename.eps";      #might be inside the safe space, register the URL for later
       &Apache::lonxml::register_ssi("/cgi-bin/plot.gif?file=$filename.data&output=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 567  sub start_title { Line 639  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");   my $text=$$parser[-1]->get_text("/title");
  $result.=&Apache::edit::rebuild_tag($token);   $result.=&Apache::edit::rebuild_tag($token);
Line 600  sub start_xlabel { Line 673  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");   my $text=$$parser[-1]->get_text("/xlabel");
  $result.=&Apache::edit::rebuild_tag($token);   $result.=&Apache::edit::rebuild_tag($token);
Line 634  sub start_ylabel { Line 708  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");   my $text=$$parser[-1]->get_text("/ylabel");
  $result.=&Apache::edit::rebuild_tag($token);   $result.=&Apache::edit::rebuild_tag($token);
Line 671  sub start_label { Line 746  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 679  sub start_label { Line 755  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));
Line 717  sub start_curve { Line 793  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 747  sub start_function { Line 824  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");   my $text=$$parser[-1]->get_text("/function");
Line 782  sub start_data { Line 864  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 807  sub start_data { Line 892  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 829  sub start_data { Line 914  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");   my $text=$$parser[-1]->get_text("/data");
Line 860  sub start_axis { Line 945  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 901  sub set_defaults { Line 987  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') {
     &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 943  sub write_gnuplot_file { Line 1034  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\" 25 \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,25pt\"\n"  if (defined($title)) ;
     $gnuplot_input .= "set ylabel \"$ylabel\"\n" if (defined($ylabel));          $gnuplot_input .= "set xlabel \"$xlabel\" font \"Helvetica,25pt\" \n" if (defined($xlabel));
           $gnuplot_input .= "set ylabel \"$ylabel\" font \"Helvetica,25pt\"\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 963  sub write_gnuplot_file { Line 1070  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 970  sub write_gnuplot_file { Line 1080  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 980  sub write_gnuplot_file { Line 1093  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 990  sub write_gnuplot_file { Line 1103  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,25pt"'.$/ ;
     }      }
       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 1001  sub write_gnuplot_file { Line 1118  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 1025  sub write_gnuplot_file { Line 1152  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 1053  sub check_inputs { Line 1190  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 1098  sub edit_attributes { Line 1235  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 1111  sub insert_gnuplot { Line 1248  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 1125  sub insert_xtics { Line 1262  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 1135  sub insert_ytics { Line 1272  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 1155  sub insert_axis{ Line 1292  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 1180  sub insert_curve { Line 1317  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.51  
changed lines
  Added in v.1.91


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