version 1.92, 2003/10/24 17:35:32
|
version 1.103, 2004/09/13 13:34:06
|
Line 25
|
Line 25
|
# |
# |
# http://www.lon-capa.org/ |
# http://www.lon-capa.org/ |
# |
# |
# 12/15/01 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/02 01/03 01/04 01/07 01/08 01/09 Matthew |
|
# 01/21 02/05 02/06 2/28Matthew |
|
|
|
package Apache::lonplot; |
package Apache::lonplot; |
|
|
Line 41 use Apache::response;
|
Line 36 use Apache::response;
|
use Apache::lonxml; |
use Apache::lonxml; |
use Apache::edit; |
use Apache::edit; |
|
|
|
use vars qw/$weboutputformat $versionstring/; |
|
|
BEGIN { |
BEGIN { |
&Apache::lonxml::register('Apache::lonplot',('gnuplot')); |
&Apache::lonxml::register('Apache::lonplot',('gnuplot')); |
|
# |
|
# Determine the version of GNUPLOT |
|
$weboutputformat = 'gif'; |
|
$versionstring = `gnuplot --version 2>/dev/null`; |
|
if ($versionstring =~ /^gnuplot 4/) { |
|
$weboutputformat = 'png'; |
|
} |
} |
} |
|
|
## |
## |
Line 115 my $words_test = sub {$_[0]=~s/\s+/
|
Line 119 my $words_test = sub {$_[0]=~s/\s+/
|
################################################################### |
################################################################### |
my @gnuplot_edit_order = |
my @gnuplot_edit_order = |
qw/alttag bgcolor fgcolor height width font transparent grid samples |
qw/alttag bgcolor fgcolor height width font transparent grid samples |
border align texwidth texfont plottype/; |
border align texwidth texfont plottype lmargin rmargin tmargin bmargin |
|
major_ticscale minor_ticscale/; |
|
|
my $gnuplot_help_text = <<"ENDPLOTHELP"; |
my $margin_choices = ['default', |
<p> |
qw{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20}]; |
The <b>gnuplot</b> tag allows an author to design a plot which can |
|
be created on the fly. This is intended for use in homework problems |
|
where each student needs to see a distinct plot. It can be used in |
|
conjunction with a <b>script</b> tag to generate random plots. |
|
</p><p> |
|
A <b>gnuplot</b> tag can contain the following sub-tags: |
|
</p> |
|
<dl> |
|
<dt> Plot Label |
|
<dd> Allows you to place text at a given (x,y) coordinate on the plot. |
|
<dt> Plot Title |
|
<dd> The title of the plot |
|
<dt> Plot Xlabel |
|
<dd> The label on the horizontal axis of the plot |
|
<dt> Plot Ylabel |
|
<dd> The label on the vertical axis of the plot |
|
<dt> Plot Axes |
|
<dd> allows specification of the x and y ranges displayed in the plot |
|
<dt> Plot Key |
|
<dd> Lists the functions displayed in the plot. |
|
<dt> Plot Curve |
|
<dd> Sets the data used in the plot. |
|
<dt> Plot Tics |
|
<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. |
|
</dl> |
|
If you are having trouble with your plot, please read the help |
|
available on Plot Curve. |
|
ENDPLOTHELP |
|
|
|
my %gnuplot_defaults = |
my %gnuplot_defaults = |
( |
( |
Line 237 my %gnuplot_defaults =
|
Line 213 my %gnuplot_defaults =
|
test => $int_test, |
test => $int_test, |
description => 'Font size to use in TeX output (pts):', |
description => 'Font size to use in TeX output (pts):', |
edit_type => 'choice', |
edit_type => 'choice', |
choices => [qw/10 12 14 16 18 20 22 24 26 28 30 32 34 36/], |
choices => [qw/8 10 12 14 16 18 20 22 24 26 28 30 32 34 36/], |
}, |
}, |
plottype => { |
plottype => { |
default => 'Cartesian', |
default => 'Cartesian', |
test => sub {$_[0]=~/^(Polar|Cartesian)$/}, |
test => sub {$_[0]=~/^(Polar|Cartesian)$/}, |
description => 'Plot type:', |
description => 'Plot type:', |
edit_type => 'choice', |
edit_type => 'choice', |
choices => ['Polar','Cartesian'] |
choices => ['Cartesian','Polar'] |
|
}, |
|
lmargin => { |
|
default => 'default', |
|
test => sub {$_[0]=~/^(default|\d+)$/}, |
|
description => 'Left margin width (pts):', |
|
edit_type => 'choice', |
|
choices => $margin_choices, |
|
}, |
|
rmargin => { |
|
default => 'default', |
|
test => sub {$_[0]=~/^(default|\d+)$/}, |
|
description => 'Right margin width (pts):', |
|
edit_type => 'choice', |
|
choices => $margin_choices, |
|
}, |
|
tmargin => { |
|
default => 'default', |
|
test => sub {$_[0]=~/^(default|\d+)$/}, |
|
description => 'Top margin width (pts):', |
|
edit_type => 'choice', |
|
choices => $margin_choices, |
|
}, |
|
bmargin => { |
|
default => 'default', |
|
test => sub {$_[0]=~/^(default|\d+)$/}, |
|
description => 'Bottm margin width (pts):', |
|
edit_type => 'choice', |
|
choices => $margin_choices, |
|
}, |
|
major_ticscale => { |
|
default => '1', |
|
test => $real_test, |
|
description => 'Size of major tic marks (plot coordinates)', |
|
edit_type => 'entry', |
|
size => '5' |
|
}, |
|
minor_ticscale => { |
|
default => '0.5', |
|
test => $real_test, |
|
description => 'Size of minor tic mark (plot coordinates)', |
|
edit_type => 'entry', |
|
size => '5' |
}, |
}, |
); |
); |
|
|
Line 339 my %tic_defaults =
|
Line 357 my %tic_defaults =
|
minorfreq => { |
minorfreq => { |
default => '0', |
default => '0', |
test => $int_test, |
test => $int_test, |
description => 'Number of minor tics between major tic marks', |
description => 'Number of minor tics per major tic mark', |
edit_type => 'entry', |
edit_type => 'entry', |
size => '10' |
size => '10' |
}, |
}, |
Line 385 my %axis_defaults =
|
Line 403 my %axis_defaults =
|
} |
} |
); |
); |
|
|
my $curve_help_text = <<"ENDCURVEHELP"; |
|
The <b>curve</b> tag is where you set the data to be plotted by gnuplot. |
|
There are two ways of entering the information: |
|
<dl> |
|
<dt> Curve Data |
|
<dd> Using a <b>data</b> tag you can specify the numbers used to produce |
|
the plot. |
|
<p> |
|
By default, two <b>data</b> tags will be available in a plot. The |
|
first will specify X coordinates of the data and the second will |
|
give the Y coordinates of the data. When working with a linestyle that |
|
requires more than two data sets, inserting another <b>data</b> tag is |
|
required. Unfortunately, you must make sure the <b>data</b> tags appear |
|
in the order gnuplot expects the data. |
|
</p><p> |
|
Specifying the data should usually be done with a perl variable or array, |
|
such as \@Xdata and \@Ydata. You may also specify numerical data seperated |
|
by commas. Again, the order of the <b>data</b> tags is important. The |
|
first tag will be the X data and the second will be the Y data. |
|
</p> |
|
<dt> Curve Function |
|
<dd> The <b>function</b> tag allows you to specify the curve to be |
|
plotted as a formula that gnuplot can understand. <b>Be careful using this |
|
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 |
|
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 |
|
is an error in your <b>function</b> tag. |
|
</dl> |
|
ENDCURVEHELP |
|
|
|
my @curve_edit_order = ('color','name','linestyle','pointtype','pointsize'); |
my @curve_edit_order = ('color','name','linestyle','pointtype','pointsize'); |
|
|
my %curve_defaults = |
my %curve_defaults = |
Line 489 sub start_gnuplot {
|
Line 476 sub start_gnuplot {
|
$tagstack->[-1]); |
$tagstack->[-1]); |
} elsif ($target eq 'edit') { |
} elsif ($target eq 'edit') { |
$result .= &Apache::edit::tag_start($target,$token,'GnuPlot'); |
$result .= &Apache::edit::tag_start($target,$token,'GnuPlot'); |
$result .= &make_javascript(); |
|
$result .= &help_win($gnuplot_help_text); |
|
$result .= &edit_attributes($target,$token,\%gnuplot_defaults, |
$result .= &edit_attributes($target,$token,\%gnuplot_defaults, |
\@gnuplot_edit_order); |
\@gnuplot_edit_order); |
} elsif ($target eq 'modified') { |
} elsif ($target eq 'modified') { |
Line 512 sub end_gnuplot {
|
Line 497 sub end_gnuplot {
|
my $randnumber; |
my $randnumber; |
# need to call rand everytime start_script would evaluate, as the |
# need to call rand everytime start_script would evaluate, as the |
# safe space rand number generator and the global rand generator |
# safe space rand number generator and the global rand generator |
# are not seperate |
# are not separate |
if ($target eq 'web' || $target eq 'tex' || $target eq 'grade' || |
if ($target eq 'web' || $target eq 'tex' || $target eq 'grade' || |
$target eq 'answer') { |
$target eq 'answer') { |
$randnumber=int(rand(1000)); |
$randnumber=int(rand(1000)); |
Line 530 sub end_gnuplot {
|
Line 515 sub end_gnuplot {
|
## 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.data&output=gif" |
<img src = "/cgi-bin/plot.gif?file=$filename.data&output=$weboutputformat" |
width = "$plot{'width'}" |
width = "$plot{'width'}" |
height = "$plot{'height'}" |
height = "$plot{'height'}" |
align = "$plot{'align'}" |
align = "$plot{'align'}" |
Line 659 sub start_title {
|
Line 644 sub start_title {
|
&Apache::edit::start_spanning_row(). |
&Apache::edit::start_spanning_row(). |
&Apache::edit::editline('',$text,'',60); |
&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 693 sub start_xlabel {
|
Line 677 sub start_xlabel {
|
&Apache::edit::start_spanning_row(). |
&Apache::edit::start_spanning_row(). |
&Apache::edit::editline('',$text,'',60); |
&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 728 sub start_ylabel {
|
Line 711 sub start_ylabel {
|
&Apache::edit::start_spanning_row(). |
&Apache::edit::start_spanning_row(). |
&Apache::edit::editline('',$text,'',60); |
&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 770 sub start_label {
|
Line 752 sub start_label {
|
&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 799 sub start_curve {
|
Line 780 sub start_curve {
|
push (@curves,\%curve); |
push (@curves,\%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 .= &edit_attributes($target,$token,\%curve_defaults, |
$result .= &edit_attributes($target,$token,\%curve_defaults, |
\@curve_edit_order); |
\@curve_edit_order); |
} elsif ($target eq 'modified') { |
} elsif ($target eq 'modified') { |
Line 849 sub start_function {
|
Line 829 sub start_function {
|
&Apache::edit::editline('',$text,'',60); |
&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 892 sub start_data {
|
Line 871 sub start_data {
|
my @data; |
my @data; |
if ($datatext =~ /,/) { # comma deliminated |
if ($datatext =~ /,/) { # comma deliminated |
@data = split /,/,$datatext; |
@data = split /,/,$datatext; |
} else { # Assume it's space seperated. |
} else { # Assume it's space separated. |
@data = split / /,$datatext; |
@data = split / /,$datatext; |
} |
} |
for (my $i=0;$i<=$#data;$i++) { |
for (my $i=0;$i<=$#data;$i++) { |
Line 927 sub start_data {
|
Line 906 sub start_data {
|
&Apache::edit::editline('',$text,'',60); |
&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 1022 sub write_gnuplot_file {
|
Line 1000 sub write_gnuplot_file {
|
my $gnuplot_input = ''; |
my $gnuplot_input = ''; |
my $curve; |
my $curve; |
my $pt = $plot{'texfont'}; |
my $pt = $plot{'texfont'}; |
|
# |
|
# Check to be sure we do not have any empty curves |
|
my @curvescopy; |
|
foreach my $curve (@curves) { |
|
if (exists($curve->{'function'})) { |
|
if ($curve->{'function'} !~ /^\s*$/) { |
|
push(@curvescopy,$curve); |
|
} |
|
} elsif (exists($curve->{'data'})) { |
|
foreach my $data (@{$curve->{'data'}}) { |
|
if (scalar(@$data) > 0) { |
|
push(@curvescopy,$curve); |
|
last; |
|
} |
|
} |
|
} |
|
} |
|
@curves = @curvescopy; |
# Collect all the colors |
# Collect all the colors |
my @Colors; |
my @Colors; |
push @Colors, $plot{'bgcolor'}; |
push @Colors, $plot{'bgcolor'}; |
Line 1034 sub write_gnuplot_file {
|
Line 1030 sub write_gnuplot_file {
|
} |
} |
# set term |
# set term |
if ($target eq 'web') { |
if ($target eq 'web') { |
$gnuplot_input .= 'set term gif '; |
$gnuplot_input .= 'set term '.$weboutputformat .' '; |
$gnuplot_input .= 'transparent ' if ($plot{'transparent'} eq 'on'); |
$gnuplot_input .= 'transparent ' if ($plot{'transparent'} eq 'on'); |
$gnuplot_input .= $plot{'font'} . ' '; |
$gnuplot_input .= $plot{'font'} . ' '; |
$gnuplot_input .= 'size '.$plot{'width'}.','.$plot{'height'}.' '; |
$gnuplot_input .= 'size '.$plot{'width'}.','.$plot{'height'}.' '; |
Line 1052 sub write_gnuplot_file {
|
Line 1048 sub write_gnuplot_file {
|
} else { |
} else { |
# Assume Cartesian |
# Assume Cartesian |
} |
} |
|
# margin |
|
if (lc($plot{'lmargin'}) ne 'default') { |
|
$gnuplot_input .= 'set lmargin '.$plot{'lmargin'}.$/; |
|
} |
|
if (lc($plot{'rmargin'}) ne 'default') { |
|
$gnuplot_input .= 'set rmargin '.$plot{'rmargin'}.$/; |
|
} |
|
if (lc($plot{'tmargin'}) ne 'default') { |
|
$gnuplot_input .= 'set tmargin '.$plot{'tmargin'}.$/; |
|
} |
|
if (lc($plot{'bmargin'}) ne 'default') { |
|
$gnuplot_input .= 'set bmargin '.$plot{'bmargin'}.$/; |
|
} |
|
# tic scales |
|
$gnuplot_input .= 'set ticscale '. |
|
$plot{'major_ticscale'}.' '.$plot{'minor_ticscale'}.$/; |
# grid |
# grid |
$gnuplot_input .= 'set grid'.$/ if ($plot{'grid'} eq 'on'); |
$gnuplot_input .= 'set grid'.$/ if ($plot{'grid'} eq 'on'); |
# border |
# border |
Line 1111 sub write_gnuplot_file {
|
Line 1123 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'}.' font "Helvetica,'.$pt.'pt"'.$/ ; |
$label->{'xpos'}.','.$label->{'ypos'}.' '.$label->{'justify'}; |
|
if ($target eq 'tex') { |
|
$gnuplot_input .=' font "Helvetica,'.$pt.'pt"' ; |
|
} |
|
$gnuplot_input .= $/; |
} |
} |
if ($target eq 'tex') { |
if ($target eq 'tex') { |
$gnuplot_input .="set size 1,".$plot{'height'}/$plot{'width'}*1.38; |
$gnuplot_input .="set size 1,".$plot{'height'}/$plot{'width'}*1.38; |
Line 1222 sub edit_attributes {
|
Line 1238 sub edit_attributes {
|
($description,$attr,$token, |
($description,$attr,$token, |
$defaults->{$attr}->{'size'}); |
$defaults->{$attr}->{'size'}); |
} elsif ($defaults->{$attr}->{'edit_type'} eq 'choice') { |
} elsif ($defaults->{$attr}->{'edit_type'} eq 'choice') { |
$result .= &Apache::edit::select_arg |
$result .= &Apache::edit::select_or_text_arg |
($description,$attr,$defaults->{$attr}->{'choices'},$token); |
($description,$attr,$defaults->{$attr}->{'choices'},$token); |
} elsif ($defaults->{$attr}->{'edit_type'} eq 'onoff') { |
} elsif ($defaults->{$attr}->{'edit_type'} eq 'onoff') { |
$result .= &Apache::edit::select_arg |
$result .= &Apache::edit::select_or_text_arg |
($description,$attr,['on','off'],$token); |
($description,$attr,['on','off'],$token); |
} |
} |
$result .= '<br />'; |
$result .= '<br />'; |
Line 1345 sub insert_data {
|
Line 1361 sub insert_data {
|
} |
} |
|
|
##---------------------------------------------------------------------- |
##---------------------------------------------------------------------- |
# Javascript functions to display help for tags |
|
|
|
sub make_javascript { |
|
my $helpwindowwidth = 400; |
|
my $helpwindowheight = 400; |
|
my $result = ''; |
|
$result.=<<"ENDFUNCTION"; |
|
<script language="JavaScript"> |
|
function openWin(text) |
|
{ |
|
newWin = open("", "new_W", "width=$helpwindowwidth,height=$helpwindowheight,resizable=1,scrollbars=1"); |
|
newWin.document.open("text/html", "replace"); |
|
newWin.document.writeln(text); |
|
newWin.document.writeln('<center><a href=\"javascript:window.close()\">close this window</a></center>'); |
|
newWin.document.close(); |
|
} |
|
</script> |
|
ENDFUNCTION |
|
return $result; |
|
} |
|
|
|
sub help_win { |
|
my ($helptext)=@_; |
|
$helptext =~ s/\n/ /g; |
|
$helptext =~ s/\'/\\\'/g; |
|
my $result = ''; |
|
$result.=<<"ENDWIN"; |
|
<table width="100%"><tr><td align="right"> |
|
<a href="javascript:openWin('$helptext')">help</a> |
|
</td></tr></table><hr /> |
|
ENDWIN |
|
return $result; |
|
} |
|
##---------------------------------------------------------------------- |
|
1; |
1; |
__END__ |
__END__ |
|
|