--- loncom/xml/lonplot.pm 2002/01/28 14:12:34 1.45 +++ loncom/xml/lonplot.pm 2002/02/06 10:33:27 1.49 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Dynamic plot # -# $Id: lonplot.pm,v 1.45 2002/01/28 14:12:34 matthew Exp $ +# $Id: lonplot.pm,v 1.49 2002/02/06 10:33:27 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -29,7 +29,7 @@ # 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 Matthew +# 01/21 02/05 02/06 Matthew package Apache::lonplot; @@ -40,7 +40,7 @@ use Apache::lonxml; use Apache::edit; BEGIN { - &Apache::lonxml::register('Apache::lonplot',('plot')); + &Apache::lonxml::register('Apache::lonplot',('gnuplot')); } ## @@ -113,9 +113,40 @@ my $words_test = sub {$_[0]=~s/\s+/ ## Attribute metadata ## ## ## ################################################################### -my @plot_edit_order = +my @gnuplot_edit_order = qw/bgcolor fgcolor height width font transparent grid border align/; -my %plot_defaults = + +my $gnuplot_help_text = <<"ENDPLOTHELP"; +

+The gnuplot 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 script tag to generate random plots. +

+A gnuplot tag can contain the following sub-tags: +

+
+
Plot Label +
Allows you to place text at a given (x,y) coordinate on the plot. +
Plot Title +
The title of the plot +
Plot Xlabel +
The label on the horizontal axis of the plot +
Plot Ylabel +
The label on the vertical axis of the plot +
Plot Axes +
allows specification of the x and y ranges displayed in the plot +
Plot Key +
Lists the functions displayed in the plot. +
Plot Curve +
Sets the data used in the plot. +
Plot Tics +
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. +
+ENDPLOTHELP + +my %gnuplot_defaults = ( height => { default => 200, @@ -307,6 +338,37 @@ my %axis_defaults = } ); +my $curve_help_text = <<"ENDCURVEHELP"; +The curve tag is where you set the data to be plotted by gnuplot. +There are two ways of entering the information: +
+
Curve Data +
Using a data tag you can specify the numbers used to produce +the plot. +

+By default, two data 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 data tag is +required. Unfortunately, you must make sure the data tags appear +in the order gnuplot expects the data. +

+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 data tags is important. The +first tag will be the X data and the second will be the Y data. +

+
Curve Function +
The function tag allows you to specify the curve to be +plotted as a formula that gnuplot can understand. Be careful using this +tag - 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 function tag. +
+ENDCURVEHELP + my %curve_defaults = ( color => { @@ -339,7 +401,7 @@ my %curve_defaults = ################################################################### my (%plot,%key,%axis,$title,$xlabel,$ylabel,@labels,@curves,%xtics,%ytics); -sub start_plot { +sub start_gnuplot { %plot = (); %key = (); %axis = (); $title = undef; $xlabel = undef; $ylabel = undef; $#labels = -1; $#curves = -1; @@ -352,18 +414,20 @@ sub start_plot { 'xtics','ytics')); push (@Apache::lonxml::namespace,'lonplot'); if ($target eq 'web') { - my $inside = &Apache::lonxml::get_all_text("/plot",$$parser[-1]); + 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,\%plot_defaults,$parstack,$safeeval, + &get_attributes(\%plot,\%gnuplot_defaults,$parstack,$safeeval, $tagstack->[-1]); } elsif ($target eq 'edit') { - $result .= &Apache::edit::tag_start($target,$token,'Plot'); - $result .= &edit_attributes($target,$token,\%plot_defaults, - \@plot_edit_order); + $result .= &Apache::edit::tag_start($target,$token,'GnuPlot'); + $result .= &make_javascript(); + $result .= &help_win($gnuplot_help_text); + $result .= &edit_attributes($target,$token,\%gnuplot_defaults, + \@gnuplot_edit_order); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args - ($token,$parstack,$safeeval,keys(%plot_defaults)); + ($token,$parstack,$safeeval,keys(%gnuplot_defaults)); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } @@ -371,9 +435,8 @@ sub start_plot { return $result; } -sub end_plot { +sub end_gnuplot { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; - pop @Apache::lonxml::namespace; &Apache::lonxml::deregister('Apache::lonplot', ('title','xlabel','ylabel','key','axis','label','curve')); @@ -393,7 +456,7 @@ sub end_plot { width = "$plot{'width'}" height = "$plot{'height'}" align = "$plot{'align'}" - alt = "/cgi-bin/plot.gif?$filename" /> + alt = "image should be /cgi-bin/plot.gif?$filename" /> ENDIMAGE } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_end($target,$token); @@ -501,6 +564,7 @@ sub start_title { my $result=''; if ($target eq 'web') { $title = &Apache::lonxml::get_all_text("/title",$$parser[-1]); + $title =~ s/\n/ /g; if (length($title) > $max_str_len) { $title = substr($title,0,$max_str_len); } @@ -533,6 +597,7 @@ sub start_xlabel { my $result=''; if ($target eq 'web') { $xlabel = &Apache::lonxml::get_all_text("/xlabel",$$parser[-1]); + $xlabel =~ s/\n/ /g; if (length($xlabel) > $max_str_len) { $xlabel = substr($xlabel,0,$max_str_len); } @@ -566,6 +631,7 @@ sub start_ylabel { my $result=''; if ($target eq 'web') { $ylabel = &Apache::lonxml::get_all_text("/ylabel",$$parser[-1]); + $ylabel =~ s/\n/ /g; if (length($ylabel) > $max_str_len) { $ylabel = substr($ylabel,0,$max_str_len); } @@ -602,6 +668,7 @@ sub start_label { &get_attributes(\%label,\%label_defaults,$parstack,$safeeval, $tagstack->[-1]); my $text = &Apache::lonxml::get_all_text("/label",$$parser[-1]); + $text =~ s/\n/ /g; $text = substr($text,0,$max_str_len) if (length($text) > $max_str_len); $label{'text'} = $text; push(@labels,\%label); @@ -645,6 +712,7 @@ sub start_curve { push (@curves,\%curve); } elsif ($target eq 'edit') { $result .= &Apache::edit::tag_start($target,$token,'Curve'); + $result .= &help_win($curve_help_text); $result .= &edit_attributes($target,$token,\%curve_defaults); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args @@ -721,7 +789,7 @@ sub start_data { $datatext = &Apache::run::run('return "'.$datatext.'"', $safeeval,1); } - $datatext =~ s/\s+/ /g; + $datatext =~ s/\s+/ /g; # Need to do some error checking on the @data array - # make sure it's all numbers and make sure each array # is of the same length. @@ -882,14 +950,14 @@ sub write_gnuplot_file { # tics if (%xtics) { $gnuplot_input .= "set xtics $xtics{'location'} "; - $gnuplot_input .= ( $xtics{'mirror'} eq 'on' ? "mirror" : "nomirror "); + $gnuplot_input .= ( $xtics{'mirror'} eq 'on'?"mirror ":"nomirror "); $gnuplot_input .= "$xtics{'start'}, "; $gnuplot_input .= "$xtics{'increment'}, "; $gnuplot_input .= "$xtics{'end'}\n"; } if (%ytics) { $gnuplot_input .= "set ytics $ytics{'location'} "; - $gnuplot_input .= ( $ytics{'mirror'} eq 'on' ? "mirror" : "nomirror "); + $gnuplot_input .= ( $ytics{'mirror'} eq 'on'?"mirror ":"nomirror "); $gnuplot_input .= "$ytics{'start'}, "; $gnuplot_input .= "$ytics{'increment'}, "; $gnuplot_input .= "$ytics{'end'}\n"; @@ -962,7 +1030,7 @@ sub write_gnuplot_file { sub check_inputs { ## Note: no inputs, no outputs - this acts only on global variables. ## Make sure we have all the input we need: - if (! %plot) { &set_defaults(\%plot,\%plot_defaults); } + if (! %plot) { &set_defaults(\%plot,\%gnuplot_defaults); } if (! %key ) {} # No key for this plot, thats okay # if (! %axis) { &set_defaults(\%axis,\%axis_defaults); } if (! defined($title )) {} # No title for this plot, thats okay @@ -1018,16 +1086,15 @@ sub edit_attributes { ## ## ################################################################### -#------------------------------------------------ insert_xxxxxxx -sub insert_plot { +sub insert_gnuplot { my $result = ''; # plot attributes $result .= "{'default'}\"\n"; + foreach my $attr (keys(%gnuplot_defaults)) { + $result .= " $attr=\"$gnuplot_defaults{$attr}->{'default'}\"\n"; } $result .= ">\n"; - # Add the components + # Add the components (most are commented out for simplicity) # $result .= &insert_key(); # $result .= &insert_axis(); # $result .= &insert_title(); @@ -1039,29 +1106,35 @@ sub insert_plot { return $result; } +sub insert_tics { + my $result; + $result .= &insert_xtics() . &insert_ytics; + return $result; +} + sub insert_xtics { my $result; - $result .= " {'default'}\"\n"; + $result .= "$attr=\"$tic_defaults{$attr}->{'default'}\" "; } - $result .= " />\n"; + $result .= "/>\n"; return $result; } sub insert_ytics { my $result; - $result .= " {'default'}\"\n"; + $result .= "$attr=\"$tic_defaults{$attr}->{'default'}\" "; } - $result .= " />\n"; + $result .= "/>\n"; return $result; } sub insert_key { my $result; - $result .= " {'default'}\"\n"; } @@ -1071,7 +1144,7 @@ sub insert_key { sub insert_axis{ my $result; - $result .= ' {'default'}\"\n"; } @@ -1079,13 +1152,13 @@ sub insert_axis{ return $result; } -sub insert_title { return " \n"; } -sub insert_xlabel { return " \n"; } -sub insert_ylabel { return " \n"; } +sub insert_title { return "\n \n"; } +sub insert_xlabel { return "\n \n"; } +sub insert_ylabel { return "\n \n"; } sub insert_label { my $result; - $result .= '