--- loncom/xml/lonplot.pm 2002/03/22 16:04:09 1.61 +++ loncom/xml/lonplot.pm 2004/01/07 18:16:02 1.94 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Dynamic plot # -# $Id: lonplot.pm,v 1.61 2002/03/22 16:04:09 matthew Exp $ +# $Id: lonplot.pm,v 1.94 2004/01/07 18:16:02 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -34,6 +34,8 @@ package Apache::lonplot; use strict; +use warnings FATAL=>'all'; +no warnings 'uninitialized'; use Apache::File; use Apache::response; use Apache::lonxml; @@ -97,12 +99,14 @@ my %linestyles = my $int_test = sub {$_[0]=~s/\s+//g;$_[0]=~/^\d+$/}; my $real_test = 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 $key_pos_test = sub {$_[0]=~/^(top|bottom|right|left|outside|below| )+$/}; my $sml_test = sub {$_[0]=~/^(small|medium|large)$/}; 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~!\@\#\$\%^&\*\(\)-=_\+\[\]\{\}:\;\'<>,\.\/\?\\]+ ?)+$/}; ################################################################### ## ## @@ -110,7 +114,8 @@ my $words_test = sub {$_[0]=~s/\s+/ ## ## ################################################################### 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";
@@ -146,15 +151,22 @@ ENDPLOTHELP
my %gnuplot_defaults =
(
+ alttag => {
+ default => 'dynamically generated plot',
+ test => $words_test,
+ description => 'brief description of the plot',
+ edit_type => 'entry',
+ size => '40'
+ },
height => {
- default => 200,
+ default => 300,
test => $int_test,
description => 'height of image (pixels)',
edit_type => 'entry',
size => '10'
},
width => {
- default => 200,
+ default => 400,
test => $int_test,
description => 'width of image (pixels)',
edit_type => 'entry',
@@ -181,7 +193,7 @@ my %gnuplot_defaults =
edit_type => 'onoff'
},
grid => {
- default => 'off',
+ default => 'on',
test => $onoff_test,
description => 'Display grid',
edit_type => 'onoff'
@@ -199,13 +211,41 @@ my %gnuplot_defaults =
edit_type => 'choice',
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 => {
- default => 'left',
+ default => 'center',
test => sub {$_[0]=~/^(left|right|center)$/},
description => 'alignment for image in html',
edit_type => 'choice',
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 =
@@ -258,51 +298,60 @@ 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 =
(
location => {
default => 'border',
test => sub {$_[0]=~/^(border|axis)$/},
- description => 'Location of tick marks',
+ description => 'Location of major tic marks',
edit_type => 'choice',
choices => ['border','axis']
},
mirror => {
default => 'on',
test => $onoff_test,
- description => 'mirror ticks on opposite axis?',
+ description => 'mirror tics on opposite axis?',
edit_type => 'onoff'
},
start => {
default => '-10.0',
test => $real_test,
- description => 'Start ticks at',
+ description => 'Start major tics at',
edit_type => 'entry',
size => '10'
},
increment => {
default => '1.0',
test => $real_test,
- description => 'Place a tick every',
+ description => 'Place a major tic every',
edit_type => 'entry',
size => '10'
},
end => {
default => ' 10.0',
test => $real_test,
- description => 'Stop ticks at ',
+ description => 'Stop major tics at ',
edit_type => 'entry',
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 =
(
color => {
default => 'x000000',
test => $color_test,
- description => 'color of axes (x000000)',
+ description => 'color of grid lines (x000000)',
edit_type => 'entry',
size => '10'
},
@@ -367,7 +416,7 @@ is an error in your function tag.
ENDCURVEHELP
-my @curve_edit_order = ('color','name','linestyle','pointsize');
+my @curve_edit_order = ('color','name','linestyle','pointtype','pointsize');
my %curve_defaults =
(
@@ -402,10 +451,17 @@ my %curve_defaults =
# },
pointsize => {
default => 1,
- test => $int_test,
+ 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,7,8,9,10]
+ choices => [0,1,2,3,4,5,6]
}
);
@@ -417,10 +473,10 @@ my %curve_defaults =
my (%plot,%key,%axis,$title,$xlabel,$ylabel,@labels,@curves,%xtics,%ytics);
sub start_gnuplot {
- %plot = (); %key = (); %axis = ();
- $title = undef; $xlabel = undef; $ylabel = undef;
- $#labels = -1; $#curves = -1;
- %xtics = (); %ytics = ();
+ undef(%plot); undef(%key); undef(%axis);
+ undef($title); undef($xlabel); undef($ylabel);
+ undef(@labels); undef(@curves);
+ undef(%xtics); undef(%ytics);
#
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
my $result='';
@@ -467,23 +523,23 @@ sub end_gnuplot {
## Determine filename
my $tmpdir = '/home/httpd/perl/tmp/';
my $filename = $ENV{'user.name'}.'_'.$ENV{'user.domain'}.
- '_'.time.'_'.$$.$randnumber.'_plot.data';
+ '_'.time.'_'.$$.$randnumber.'_plot';
## Write the plot description to the file
&write_gnuplot_file($tmpdir,$filename,$target);
$filename = &Apache::lonnet::escape($filename);
## return image tag for the plot
if ($target eq 'web') {
$result .= <<"ENDIMAGE";
-
+ alt = "$plot{'alttag'}" />
ENDIMAGE
} elsif ($target eq 'tex') {
- &Apache::lonnet::ssi('cgi-bin/plot.gif?file=$filename'.
- '&output=eps');
- $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') {
$result.=&Apache::edit::tag_end($target,$token);
@@ -590,7 +646,7 @@ sub start_title {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
my $result='';
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;
if (length($title) > $max_str_len) {
@@ -598,14 +654,13 @@ sub start_title {
}
} elsif ($target eq 'edit') {
$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().
&Apache::edit::start_spanning_row().
- &Apache::edit::textfield('',$text,'',60);
+ &Apache::edit::editline('',$text,'',60);
} elsif ($target eq 'modified') {
- my $text=$$parser[-1]->get_text("/title");
$result.=&Apache::edit::rebuild_tag($token);
- $result.=&Apache::edit::modifiedfield($token);
+ $result.=&Apache::edit::modifiedfield("/title",$parser);
}
return $result;
}
@@ -624,7 +679,7 @@ sub start_xlabel {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
my $result='';
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;
if (length($xlabel) > $max_str_len) {
@@ -632,14 +687,13 @@ sub start_xlabel {
}
} elsif ($target eq 'edit') {
$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().
&Apache::edit::start_spanning_row().
- &Apache::edit::textfield('',$text,'',60);
+ &Apache::edit::editline('',$text,'',60);
} elsif ($target eq 'modified') {
- my $text=$$parser[-1]->get_text("/xlabel");
$result.=&Apache::edit::rebuild_tag($token);
- $result.=&Apache::edit::modifiedfield($token);
+ $result.=&Apache::edit::modifiedfield("/xlabel",$parser);
}
return $result;
}
@@ -659,7 +713,7 @@ sub start_ylabel {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
my $result='';
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;
if (length($ylabel) > $max_str_len) {
@@ -667,14 +721,13 @@ sub start_ylabel {
}
} elsif ($target eq 'edit') {
$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().
&Apache::edit::start_spanning_row().
- &Apache::edit::textfield('',$text,'',60);
+ &Apache::edit::editline('',$text,'',60);
} elsif ($target eq 'modified') {
- my $text=$$parser[-1]->get_text("/ylabel");
$result.=&Apache::edit::rebuild_tag($token);
- $result.=&Apache::edit::modifiedfield($token);
+ $result.=&Apache::edit::modifiedfield("/ylabel",$parser);
}
return $result;
}
@@ -697,7 +750,7 @@ sub start_label {
my %label;
&get_attributes(\%label,\%label_defaults,$parstack,$safeeval,
$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 = substr($text,0,$max_str_len) if (length($text) > $max_str_len);
@@ -706,16 +759,15 @@ sub start_label {
} elsif ($target eq 'edit') {
$result .= &Apache::edit::tag_start($target,$token,'Plot Label');
$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().
&Apache::edit::start_spanning_row().
- &Apache::edit::textfield('',$text,'',60);
+ &Apache::edit::editline('',$text,'',60);
} elsif ($target eq 'modified') {
&Apache::edit::get_new_args
($token,$parstack,$safeeval,keys(%label_defaults));
$result.=&Apache::edit::rebuild_tag($token);
- my $text=$$parser[-1]->get_text("/label");
- $result.=&Apache::edit::modifiedfield($token);
+ $result.=&Apache::edit::modifiedfield("/label",$parser);
}
return $result;
}
@@ -775,22 +827,25 @@ sub start_function {
my $result='';
if ($target eq 'web' || $target eq 'tex') {
if (exists($curves[-1]->{'data'})) {
- &Apache::lonxml::warning('Use of