version 1.158, 2012/07/04 11:09:22
|
version 1.166, 2012/09/10 09:51:15
|
Line 139 my $sml_test = sub {$_[0]=~/^(\d+|
|
Line 139 my $sml_test = sub {$_[0]=~/^(\d+|
|
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~!\@\#\$\%^&\*\(\)-=_\+\[\]\{\}:\;\'<>,\.\/\?\\]+ ?)+$/}; |
|
|
|
my $arrowhead_test = sub{$_[0]=~/^(nohead|head|heads| )+$/}; |
|
my $arrowstyle_test= sub{$_[0]=~/^(filled|empty|nofilled)+$/}; |
|
my $degree_test = sub{&$pos_real_test($_[0]) && ($_[0] <= 360.0)}; |
|
|
################################################################### |
################################################################### |
## ## |
## ## |
## Attribute metadata ## |
## Attribute metadata ## |
Line 459 my %tic_defaults =
|
Line 463 my %tic_defaults =
|
description => 'Number of minor tics per major tic mark', |
description => 'Number of minor tics per major tic mark', |
edit_type => 'entry', |
edit_type => 'entry', |
size => '10' |
size => '10' |
}, |
}, |
|
rotate => { |
|
default => 'off', |
|
test => $onoff_test, |
|
description => 'Rotate tic label by 90 degrees if on', |
|
edit_type => 'onoff' |
|
} |
); |
); |
|
|
my @axis_edit_order = ('color','xmin','xmax','ymin','ymax','xformat', 'yformat', 'xzero', 'yzero'); |
my @axis_edit_order = ('color','xmin','xmax','ymin','ymax','xformat', 'yformat', 'xzero', 'yzero'); |
Line 533 my %axis_defaults =
|
Line 543 my %axis_defaults =
|
}, |
}, |
); |
); |
|
|
my @curve_edit_order = ('color','name','linestyle','linewidth','linetype','pointtype','pointsize','limit'); |
|
|
my @curve_edit_order = ('color','name','linestyle','linewidth','linetype', |
|
'pointtype','pointsize','limit', 'arrowhead', 'arrowstyle', |
|
'arrowlength', 'arrowangle', 'arrowbackangle' |
|
); |
|
|
my %curve_defaults = |
my %curve_defaults = |
( |
( |
Line 594 my %curve_defaults =
|
Line 608 my %curve_defaults =
|
edit_type => 'choice', |
edit_type => 'choice', |
choices => ['above', 'below', 'closed','x1','x2','y1','y2'] |
choices => ['above', 'below', 'closed','x1','x2','y1','y2'] |
}, |
}, |
|
arrowhead => { |
|
default => 'head', |
|
test => $arrowhead_test, |
|
description => 'Vector arrow head type', |
|
edit_type => 'choice', |
|
choices => ['nohead', 'head', 'heads'] |
|
}, |
|
arrowstyle => { |
|
default => 'filled', |
|
test => $arrowstyle_test, |
|
description => 'Vector arrow head style', |
|
edit_type => 'choice', |
|
choices => ['filled', 'empty', 'nofilled'] |
|
}, |
|
arrowlength => { |
|
default => 0.02, |
|
test => $pos_real_test, |
|
description => "Length of vector arrow (only applies to vector plots)", |
|
edit_type => 'entry', |
|
size => '5' |
|
}, |
|
arrowangle => { |
|
default => 10.0, |
|
test => $degree_test, |
|
description => 'Angle of arrow branches to arrow body (only applies to vector plots)', |
|
edit_type => 'entry', |
|
size => '5' |
|
}, |
|
|
|
arrowbackangle => { |
|
default => 90.0, |
|
test => $degree_test, |
|
descripton => 'Angle of arrow back lines to branches.', |
|
edit_type => 'entry', |
|
size => '5' |
|
} |
|
|
); |
); |
|
|
################################################################### |
################################################################### |
Line 605 my %curve_defaults =
|
Line 656 my %curve_defaults =
|
undef %Apache::lonplot::plot; |
undef %Apache::lonplot::plot; |
my (%key,%axis,$title,$xlabel,$ylabel,@labels,@curves,%xtics,%ytics); |
my (%key,%axis,$title,$xlabel,$ylabel,@labels,@curves,%xtics,%ytics); |
|
|
|
my $current_tics; # Reference to the current tick hash |
|
|
sub start_gnuplot { |
sub start_gnuplot { |
undef(%Apache::lonplot::plot); undef(%key); undef(%axis); |
undef(%Apache::lonplot::plot); undef(%key); undef(%axis); |
undef($title); undef($xlabel); undef($ylabel); |
undef($title); undef($xlabel); undef($ylabel); |
Line 704 sub start_xtics {
|
Line 757 sub start_xtics {
|
if ($target eq 'web' || $target eq 'tex') { |
if ($target eq 'web' || $target eq 'tex') { |
&get_attributes(\%xtics,\%tic_defaults,$parstack,$safeeval, |
&get_attributes(\%xtics,\%tic_defaults,$parstack,$safeeval, |
$tagstack->[-1]); |
$tagstack->[-1]); |
|
$current_tics = \%xtics; |
|
&Apache::lonxml::register('Apache::lonplot', 'tic'); |
} elsif ($target eq 'edit') { |
} elsif ($target eq 'edit') { |
$result .= &Apache::edit::tag_start($target,$token,'xtics'); |
$result .= &Apache::edit::tag_start($target,$token,'xtics'); |
$result .= &edit_attributes($target,$token,\%tic_defaults, |
$result .= &edit_attributes($target,$token,\%tic_defaults, |
Line 722 sub end_xtics {
|
Line 777 sub end_xtics {
|
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') { |
|
&Apache::lonxml::deregister('Apache::lonplot', 'tic'); |
} elsif ($target eq 'edit') { |
} elsif ($target eq 'edit') { |
$result.=&Apache::edit::tag_end($target,$token); |
$result.=&Apache::edit::tag_end($target,$token); |
} |
} |
Line 735 sub start_ytics {
|
Line 791 sub start_ytics {
|
if ($target eq 'web' || $target eq 'tex') { |
if ($target eq 'web' || $target eq 'tex') { |
&get_attributes(\%ytics,\%tic_defaults,$parstack,$safeeval, |
&get_attributes(\%ytics,\%tic_defaults,$parstack,$safeeval, |
$tagstack->[-1]); |
$tagstack->[-1]); |
|
$current_tics = \%ytics; |
|
&Apache::lonxml::register('Apache::lonplot', 'tic'); |
} elsif ($target eq 'edit') { |
} elsif ($target eq 'edit') { |
$result .= &Apache::edit::tag_start($target,$token,'ytics'); |
$result .= &Apache::edit::tag_start($target,$token,'ytics'); |
$result .= &edit_attributes($target,$token,\%tic_defaults, |
$result .= &edit_attributes($target,$token,\%tic_defaults, |
Line 753 sub end_ytics {
|
Line 811 sub end_ytics {
|
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') { |
|
&Apache::lonxml::deregister('Apache::lonplot', 'tic'); |
} elsif ($target eq 'edit') { |
} elsif ($target eq 'edit') { |
$result.=&Apache::edit::tag_end($target,$token); |
$result.=&Apache::edit::tag_end($target,$token); |
} |
} |
return $result; |
return $result; |
} |
} |
|
|
|
|
|
##---------------------------------------------------------------- |
|
# |
|
# Tic handling: |
|
# The <tic> tag allows users to specify exact Tic positions and labels |
|
# for each axis. In this version we only support level 0 tics (major tic). |
|
# Each tic has associated with it a position and a label |
|
# $current_tics is a reference to the current tick description hash. |
|
# We add elements to an array in that has: ticspecs whose elements |
|
# are 'pos' - the tick position and 'label' - the tic label. |
|
# |
|
|
|
|
|
sub start_tic { |
|
my ($target, $token, $tagstack, $parstack, $parser, $safeeval, $style) = @_; |
|
|
|
my $result = ''; |
|
if ($target eq 'web' || $target eq 'tex') { |
|
my $tic_location = &Apache::lonxml::get_param('location', $parstack, $safeeval); |
|
my $tic_label = &Apache::lonxml::get_all_text('/tic', $parser); |
|
|
|
# Tic location must e a real: |
|
|
|
if (!&$real_test($tic_location)) { |
|
&Apache::lonxml::warning("Tic location: $tic_location must be a real number"); |
|
} else { |
|
|
|
if (!defined $current_tics->{'ticspecs'}) { |
|
$current_tics->{'ticspecs'} = []; |
|
} |
|
my $ticspecs = $current_tics->{'ticspecs'}; |
|
push (@$ticspecs, {'pos' => $tic_location, 'label' => $tic_label}); |
|
} |
|
} |
|
|
|
return $result; |
|
} |
|
|
|
sub end_tic { |
|
return ''; |
|
} |
|
|
##-----------------------------------------------------------------font |
##-----------------------------------------------------------------font |
my %font_properties = |
my %font_properties = |
( |
( |
Line 1413 sub start_function {
|
Line 1514 sub start_function {
|
$style); |
$style); |
$function = &Apache::run::evaluate($function,$safeeval,$$parstack[-1]); |
$function = &Apache::run::evaluate($function,$safeeval,$$parstack[-1]); |
$function=~s/\^/\*\*/gs; |
$function=~s/\^/\*\*/gs; |
|
$function=~ s/^\s+//; # Trim leading |
|
$function=~ s/\s+$//; # And trailing whitespace. |
$curves[-1]->{'function'} = $function; |
$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'); |
Line 1592 sub get_attributes{
|
Line 1695 sub get_attributes{
|
} |
} |
return ; |
return ; |
} |
} |
|
## |
|
# Generate tic mark specifications. |
|
# |
|
# @param type - type of tics (xtics or ytics). |
|
# @param spec - Reference to a hash that contains the tic specification. |
|
# @param target - 'tex' if hard copy target. |
|
# |
|
# @return string - the tic specification command. |
|
# |
|
sub generate_tics { |
|
my ($type, $spec, $target) = @_; |
|
my $result = ''; |
|
|
|
|
|
if (defined %$spec) { |
|
|
|
|
|
|
|
# Major tics: - If there are 'ticspecs' these override any other |
|
# specifications: |
|
|
|
|
|
|
|
$result .= "set $type $spec->{'location'} "; |
|
$result .= ($spec->{'mirror'} eq 'on') ? 'mirror ' : 'nomirror '; |
|
if ($spec->{'rotate'} eq 'on') { |
|
$result .= ' rotate '; |
|
} |
|
if (defined $spec->{'ticspecs'}) { |
|
$result .= '( '; |
|
my @ticspecs; |
|
my $ticinfo = $spec->{'ticspecs'}; |
|
foreach my $tic (@$ticinfo) { |
|
push(@ticspecs, '"' . $tic->{'label'} . '" ' . $tic->{'pos'} ); |
|
} |
|
$result .= join(', ', (@ticspecs)); |
|
$result .= ' )'; |
|
} else { |
|
$result .= "$spec->{'start'}, "; |
|
$result .= "$spec->{'increment'}, "; |
|
$result .= "$spec->{'end'} "; |
|
} |
|
if ($target eq 'tex' ) { |
|
$result .= 'font "Helvetica,22"'; |
|
} |
|
$result .= "\n"; |
|
|
|
# minor frequency: |
|
|
|
if ($spec->{'minorfreq'} != 0) { |
|
$result .= "set m$type $spec->{'minorfreq'}\n"; |
|
} |
|
} else { |
|
$result .= "set $type font " . '"Helvetica,22"' ."\n"; |
|
} |
|
|
|
|
|
return $result; |
|
} |
|
|
##------------------------------------------------------- write_gnuplot_file |
##------------------------------------------------------- write_gnuplot_file |
sub write_gnuplot_file { |
sub write_gnuplot_file { |
my ($tmpdir,$filename,$target)= @_; |
my ($tmpdir,$filename,$target)= @_; |
my ($fontsize, $font_properties) = &get_font($target); |
my ($fontsize, $font_properties) = &get_font($target); |
|
&Apache::lonnet::logthis("Fontsize: $fontsize"); |
my $gnuplot_input = ''; |
my $gnuplot_input = ''; |
my $curve; |
my $curve; |
# |
# |
Line 1653 sub write_gnuplot_file {
|
Line 1816 sub write_gnuplot_file {
|
$gnuplot_input .= "set encoding iso_8859_1\n"; # Get access to extended font. |
$gnuplot_input .= "set encoding iso_8859_1\n"; # Get access to extended font. |
|
|
} |
} |
|
$gnuplot_input .= "set encoding utf8\n"; |
# cartesian or polar plot? |
# cartesian or polar plot? |
if (lc($Apache::lonplot::plot{'plottype'}) eq 'polar') { |
if (lc($Apache::lonplot::plot{'plottype'}) eq 'polar') { |
$gnuplot_input .= 'set polar'.$/; |
$gnuplot_input .= 'set polar'.$/; |
Line 1733 sub write_gnuplot_file {
|
Line 1897 sub write_gnuplot_file {
|
$gnuplot_input .= "set ylabel \"$ylabel\" $extra_space_y \n" if (defined($ylabel)); |
$gnuplot_input .= "set ylabel \"$ylabel\" $extra_space_y \n" if (defined($ylabel)); |
} |
} |
# tics |
# tics |
if (%xtics) { |
$gnuplot_input .= &generate_tics('xtics', \%xtics, $target); |
$gnuplot_input .= "set xtics $xtics{'location'} "; |
|
$gnuplot_input .= ( $xtics{'mirror'} eq 'on'?"mirror ":"nomirror "); |
$gnuplot_input .= &generate_tics('ytics', \%ytics, $target); |
$gnuplot_input .= "$xtics{'start'}, "; |
|
$gnuplot_input .= "$xtics{'increment'}, "; |
|
$gnuplot_input .= "$xtics{'end'} "; |
|
if ($target eq 'tex') { |
|
$gnuplot_input .= 'font "Helvetica,22"'; # Needed in iso 8859-1 enc. |
|
} |
|
$gnuplot_input .= "\n"; |
|
if ($xtics{'minorfreq'} != 0) { |
|
$gnuplot_input .= "set mxtics ".$xtics{'minorfreq'}."\n"; |
|
} |
|
} else { |
|
if ($target eq 'tex') { |
|
$gnuplot_input .= 'set xtics font "Helvetica,22"'."\n"; # needed in iso 8859-1 enc |
|
} |
|
} |
|
if (%ytics) { |
|
$gnuplot_input .= "set ytics $ytics{'location'} "; |
|
$gnuplot_input .= ( $ytics{'mirror'} eq 'on'?"mirror ":"nomirror "); |
|
$gnuplot_input .= "$ytics{'start'}, "; |
|
$gnuplot_input .= "$ytics{'increment'}, "; |
|
$gnuplot_input .= "$ytics{'end'} "; |
|
if ($target eq 'tex') { |
|
$gnuplot_input .= 'font "Helvetica,22"'; # Needed in iso-8859-1 encoding. |
|
} |
|
$gnuplot_input .= "\n"; |
|
if ($ytics{'minorfreq'} != 0) { |
|
$gnuplot_input .= "set mytics ".$ytics{'minorfreq'}."\n"; |
|
} |
|
} else { |
|
if ($target eq 'tex') { |
|
$gnuplot_input .= 'set ytics font "Helvetica,22"'."\n"; # Needed for iso 8859-1 enc. |
|
} |
|
} |
|
# axis |
# axis |
if (%axis) { |
if (%axis) { |
if ($axis{'xformat'} ne 'on') { |
if ($axis{'xformat'} ne 'on') { |
Line 1849 sub write_gnuplot_file {
|
Line 1981 sub write_gnuplot_file {
|
my $linestyle_index = 50; |
my $linestyle_index = 50; |
my $line_width = ''; |
my $line_width = ''; |
|
|
|
# If arrows are needed there will be an arrow style for each as well: |
|
# |
|
|
|
my $arrow_style_index = 50; |
|
|
my $plot_command; |
my $plot_command; |
my $plot_type; |
my $plot_type; |
|
|
Line 1891 sub write_gnuplot_file {
|
Line 2028 sub write_gnuplot_file {
|
my $pointtype = ''; |
my $pointtype = ''; |
my $pointsize = ''; |
my $pointsize = ''; |
|
|
|
# Figure out the linestyle: |
|
|
|
my $lt = $curve->{'linetype'} ne '' ? $curve->{'linetype'} |
|
: 'solid'; # Line type defaults to solid. |
|
# The mapping of lt -> the actual gnuplot line type depends on the target: |
|
|
|
if ($target eq 'tex') { |
|
$lt = $ps_linetypes{$lt}; |
|
} else { |
|
$lt = $linetypes{$lt} |
|
} |
|
|
|
my $color = $curve->{'color'}; |
|
$color =~ s/^x/#/; # Convert xhex color -> #hex color. |
|
|
|
my $style_command = "set style line $linestyle_index $pointtype $pointsize linetype $lt linewidth $line_width lc rgb '$color'\n"; |
|
$gnuplot_input .= $style_command; |
|
|
|
|
|
|
if (($curve->{'linestyle'} eq 'points') || |
if (($curve->{'linestyle'} eq 'points') || |
($curve->{'linestyle'} eq 'linespoints') || |
($curve->{'linestyle'} eq 'linespoints') || |
($curve->{'linestyle'} eq 'errorbars') || |
($curve->{'linestyle'} eq 'errorbars') || |
Line 1902 sub write_gnuplot_file {
|
Line 2059 sub write_gnuplot_file {
|
$pointsize =' pointsize '.$curve->{'pointsize'}; |
$pointsize =' pointsize '.$curve->{'pointsize'}; |
} elsif ($curve->{'linestyle'} eq 'filledcurves') { |
} elsif ($curve->{'linestyle'} eq 'filledcurves') { |
$plot_command.= ' '.$curve->{'limit'}; |
$plot_command.= ' '.$curve->{'limit'}; |
} |
} elsif ($curve->{'linestyle'} eq 'vector') { |
|
|
|
# Create the arrow head style add it to |
|
# $gnuplot_input..and ensure it gets |
|
# Selected in the plot command. |
|
|
# Figure out the linestyle: |
$gnuplot_input .= "set style arrow $arrow_style_index "; |
|
$gnuplot_input .= ' ' . $curve->{'arrowhead'}; |
|
$gnuplot_input .= ' size ' . $curve->{'arrowlength'}; |
|
$gnuplot_input .= ','.$curve->{'arrowangle'}; |
|
$gnuplot_input .= ',' . $curve->{'arrowbackangle'}; |
|
$gnuplot_input .= ' ' . $curve->{'arrowstyle'} . " ls $linestyle_index\n"; |
|
|
my $lt = $curve->{'linetype'} ne '' ? $curve->{'linetype'} |
|
: 'solid'; # Line type defaults to solid. |
|
# The mapping of lt -> the actual gnuplot line type depends on the target: |
|
|
|
if ($target eq 'tex') { |
$plot_command .= " arrowstyle $arrow_style_index "; |
$lt = $ps_linetypes{$lt}; |
$arrow_style_index++; |
} else { |
|
$lt = $linetypes{$lt} |
|
} |
} |
|
|
my $color = $curve->{'color'}; |
|
$color =~ s/^x/#/; # Convert xhex color -> #hex color. |
|
|
|
my $style_command = "set style line $linestyle_index $pointtype $pointsize linetype $lt linewidth $line_width lc rgb '$color'\n"; |
|
$gnuplot_input .= $style_command; |
|
|
|
$plot_command.= " ls $linestyle_index"; |
|
|
# The condition below is because gnuplot lumps the linestyle in with the |
|
# arrowstyle _sigh_. |
|
|
|
if ($curve->{'linestyle'} ne 'vector') { |
|
$plot_command.= " ls $linestyle_index"; |
|
} |
|
|
$gnuplot_input .= 'plot ' . $plot_type . ' ' . $plot_command . "\n"; |
$gnuplot_input .= 'plot ' . $plot_type . ' ' . $plot_command . "\n"; |
$linestyle_index++; # Each curve get a unique linestyle. |
$linestyle_index++; # Each curve get a unique linestyle. |
} |
} |
# Write the output to a file. |
# Write the output to a file. |
open (my $fh,">$tmpdir$filename.data"); |
|
binmode($fh, ":utf8"); |
# &Apache::lonnet::logthis($gnuplot_input); # uncomment to log the gnuplot input. |
|
open (my $fh, "> $tmpdir$filename.data"); |
|
binmode($fh, ':utf8'); |
print $fh $gnuplot_input; |
print $fh $gnuplot_input; |
close($fh); |
close($fh); |
# That's all folks. |
# That's all folks. |