Forum archive 2000-2006

Michael Gage - On-the-fly graphics example

Michael Gage - On-the-fly graphics example

by Arnold Pizer -
Number of replies: 0
inactiveTopicOn-the-fly graphics example topic started 5/9/2000; 4:02:53 PM
last post 6/1/2001; 11:59:55 AM
userMichael Gage - On-the-fly graphics example  blueArrow
5/9/2000; 4:02:53 PM (reads: 4521, responses: 2)

The on-the-fly graphics example

To obtain this problem
(1 pt) rochesterLibrary/setMAAtutorial/ontheflygraphicsexample1.pg

On-the-fly Graphics Example1

gage-1234-setMAAtutorialprob1image1-.png

Identify the graphs A (blue), B( red) and C (green) as the graphs of a function and its derivatives (click on the graph to see an enlarged image):

is the graph of the function

is the graph of the function's first derivative

is the graph of the function's second derivative

 

 

 


WARNINGS
µ¦å{h­

 

DOCUMENT();
loadMacros(
"PGbasicmacros.pl",
"PGchoicemacros.pl",
"PGanswermacros.pl",
"PGgraphmacros.pl"
);

TEXT(beginproblem(), $BR,$BBOLD, "On-the-fly Graphics Example1", $EBOLD, $BR,$BR);
$showPartialCorrectAnswers = 0;

# First we define a graph with x and y in the range -4 to 4, axes (strong lines)
# defined at the point [0,0] and
# with 8 gridlines horizontally and 8 grid lines veritically.
# $graph is a graph object (or more appropriately, a pointer to a graph object).

# We will define a function and it's first and second derivatives defined
# on the domain [-4,4]
$dom = 4;
$graph = init_graph(-$dom,-$dom,$dom,$dom,'axes'=>[0,0],'grid'=>[8,8]);

# Here are the basic colors -- we'll mix them up in the next example
@colors = ("blue", "red", "green"); #orange, yellow,
@scrambled_colors = @colors;
@labels = ('A', 'B', 'C');
@scrambled_labels = @labels;

$a=random(0, 6.3, .1);
$b=random(1.1, 1.5, .1);
# now define the functions too be graphed
# defining strings need to be on one line (\n is not handled correctly)
# The three variables $f, $fp, and $fpp contain strings
# with the correct syntax to be inputs into the plot_function
# macro. The FEQ macro (Format EQuation) cleans up the writing of the function.
# Otherwise we would need to worry about the signs of $a, $b and so forth.
# For example if $b were negative, then after interpolation
# $a+$b might look like 3+-5. FEQ replaces the +- pair by -, which is what you want.

# The first string (for $f) should be read as: "The function is calculated
# using sin($a+$b*cos(x))
# and is defined for all x in the
# interval -$dom to +$dom. Draw the function using the first color
# in the permuted color list @scrambled_colors
# and using a weight (width) of two pixels."

$f = FEQ(
"sin($a+$b*cos(x)) for x in <-$dom,$dom> using color:$scrambled_colors[0] and weight:2"
);
$fp = FEQ(
"cos($a+${b}*cos(x))*(-$b)*sin(x) for x in <-$dom,$dom> using color=$scrambled_colors[1] and weight:2"
);
# The multiplication signs are not actually needed, although they are allowed.
$fpp = FEQ("-sin($a+${b}*cos(x))*$b*$b* sin(x)* sin(x)+ cos($a+$b* cos(x))*(-$b)*cos(x) for x in <-$dom,$dom> using color=$scrambled_colors[2] and weight=2"
);



# Install the functions into the graph object.
# Plot_functions converts the string to a subroutine which performs the
# necessary calculations and
# asks the graph object to plot the functions.

($fRef,$fpRef,$fppRef) = plot_functions( $graph,
$f,$fp,$fpp
);

# The output of plot_functions is a list of pointers to functions which
# contain the appropriate data and methods.
# So $fpRef->rule points to the method which will calculate the value
# of the function.
# &{$fpRef->rule}(3) calculates the value of the function at 3.

# create labels for each function
# The 'left' tag determines the justification of the label to the defining point.


$label_point=-0.75;
$label_f = new Label ( $label_point,&{$fRef->rule}($label_point),
$scrambled_labels[0], $scrambled_colors[0],'left');
# NOTE: $fRef->ruleis a reference to the subroutine which calculates the
# function. It was defined in the output of plot_functions.
# It is used here to calculate the y value of the label corresponding
# to the function, and below to find the y values for the labels
# corresponding to the first and second derivatives.

$label_fp = new Label ( $label_point,&{$fpRef->rule}($label_point),
$scrambled_labels[1],$scrambled_colors[1],'left');
# Place the second letter in the permuted letter list at the point
# (-.75, fp(-.75)) using the second color in the permuted color list.

$label_fpp = new Label ( $label_point,&{$fppRef->rule}($label_point),
$scrambled_labels[2],$scrambled_colors[2],'left');

# insert the labels into the graph
$graph->lb($label_f,$label_fp,$label_fpp);

# make sure that the browser will fetch
# the new picture when it is created by changing the name of the
# graph each time the problem seed is changed. This helps prevent caching problems
# on browsers.

$graph->gifName($graph->gifName()."-$newProblemSeed");
# Begin writing the problem.
# This inserts the graph and then asks three questions:

BEGIN_TEXT
\{ image(insertGraph($graph)) \} $PAR
Identify the graphs A (blue), B( red) and C (green) as the graphs
of a function and its
derivatives (click on the graph to see an enlarged image):$PAR
\{ans_rule(4)\} is the graph of the function $PAR
\{ans_rule(4)\} is the graph of the function's first derivative $PAR
\{ans_rule(4)\} is the graph of the function's second derivative $PAR
END_TEXT
ANS(str_cmp( [@scrambled_labels] ) );

ENDDOCUMENT();



 


Comments:

  1. First we define a graph with x and y in the range -4 to 4, axes (strong lines) defined at the point [0,0] and with 8 gridlines horizontally and 8 grid lines veritically. $graph is a graph object (or more appropriately, a pointer to a graph object).
  2. We define a function and it's first and second derivatives on the domain [-4,4]
    We need to mix up the colors assigned to each function, since it won't do us any good if every student's function is colored blue, their first derivative red, and their second derivative green.
    Create a scrambled list of colors and letters. Here are the basic colors @colors = ("blue", "red", "green"); Slice will contain the numbers 1,2,3 in some permuted order @slice = NchooseK(3,3); The slice of the color list (sc) contains the colors in a new order defined by the ordering in @slice. This construction @array[@slice] is the way to apply a permutation to a list. @sc = @colors[@slice]; Now we scramble the letters labeling the graphs using the same permutation. These list will contain the correct answers in the proper order. @sa = ('A','B','C')[@slice];
  3. $f = FEQ("sin($a+$b*cos(x)) for x in <-$dom,$dom> using color:$sc[0] and weight:2");

    The first string (for $f) should be read as: "The function is calculated using sin($a+$b*cos(x)) and is defined for all x in the interval -$dom to +$dom. Draw the function using the first color in the permuted color list @sc and using a weight (width) of two pixels."

    The FEQ macro (Format EQuation) cleans up the writing of the function. Otherwise we would need to worry about the signs of $a, $b and so forth. For example if $b were negative, then after interpolation $a+$b might look like 3+-5. FEQ replaces the +- pair by -, which is what you want.

  4. Install the functions into the graph object. Plot_functions converts the string to a subroutine which performs the necessary calculations and asks the graph object to plot the functions. ($fRef,$fpRef,$fppRef) = plot_functions( $graph, $f,$fp,$fpp );

    The output of plot_functions is a list of pointers to functions which contain the appropriate data and methods. So $fpRef->rule points to the method which will calculate the value of the function. &{$fpRef->rule}(3) calculates the value of the function at 3. See Fun.pm for more details.

  5. Create labels for each function The 'left' tag determines the justification of the label to the defining point.
    Place the second letter in the permuted letter list at the point (-.75, fp(-.75)) using the second color in the permuted color list.
  6. The construction \{ image(insertGraph($graph)) \} inserts the graph at this point in the text.

 

<| Post or View Comments |>


userSusan Diesel - Re: On-the-fly graphics example  blueArrow
6/1/2001; 10:38:23 AM (reads: 2848, responses: 0)
With our most recent installation of WW 1.6 at Dartmouth, I receive compiler errors with any on-the-fly graphics problem, including this one. What's going wrong?
* This option |vars| is not recognized in this subroutine
HASH(0x83e7bf0) store_in => rf_correct_ans
vars => ( x , )
at (eval 111) line 3589.
##More details:
-------- PG_priv::set_default_options called at (eval 111) line 2096
---- PG_priv::function_from_string2 called at (eval 112) line 352
---- PG_priv::string_to_sub called at (eval 112) line 217
---- PG_priv::plot_functions called at (eval 49) line 40
---- PG_priv::__ANON__ called at /usr/lib/perl/5.6.0/Safe.pm line 222
---- Safe::reval called at /var/webwork_1.6/system//PGtranslator.pm line 691
---- PGtranslator::translate called at /usr/lib/cgi-bin/webwork/system_1.6/cgi-scripts/processProblem8.pl line 420



<| Post or View Comments |>


userMichael Gage - Re: On-the-fly graphics example  blueArrow
6/1/2001; 11:59:55 AM (reads: 2883, responses: 0)
Susan,

This is a compatibility bug in PGanswermacros/PGgraphmacros we'll get this fixed permanently soon. For now I believe that changing var => ['x'] to ra_vars =>['x'] in the subroutine string_to_sub in the file PGgraphmacros.pl will fix your problem.

 



sub string_to_sub {
my $str_in = shift;
my $var = shift;
my $out = undef;
if ( defined(&check_syntax) ) {
#prepare the correct answer and check it's syntax
my $rh_correct_ans = new AnswerHash;
$rh_correct_ans->input($str_in);
$rh_correct_ans = check_syntax($rh_correct_ans);
warn $rh_correct_ans->{error_message} if $rh_correct_ans->{error_flag};
$rh_correct_ans->clear_error();
## replace this next line by the one following it
# $rh_correct_ans = function_from_string2($rh_correct_ans, vars => ['x'], store_in =>'rf_correct_ans');
$rh_correct_ans = function_from_string2($rh_correct_ans, ra_vars => ['x'], store_in =>'rf_correct_ans');
###########################
my $correct_eqn_sub = $rh_correct_ans->{rf_correct_ans};
warn $rh_correct_ans->{error_message} if $rh_correct_ans->{error_flag};
$out = sub{ scalar( &$correct_eqn_sub(@_) ) }; #ignore the error messages from the function.



} else {
my $in =$str_in;

$in =~ s/b$varb/$XVAR/g;
$in = &my_math_constants($in);
my ($subRef, $PG_eval_errors,$PG_full_error_report) = PG_restricted_eval( " sub { my \$XVAR = shift; my \$out = $in; \$out; } ");
if ($PG_eval_errors) {
die " ERROR while defining a function from the string:\n\n$main::BR $main::BR $str_in $main::BR $main::BR\n\n $PG_eval_errors"
} else {
$out = $subRef;
}

}
$out;
}

<| Post or View Comments |>