1# Library of McStas plotting functions (gnuplot related) 2# 3# This file is part of the McStas neutron ray-trace simulation package 4# Copyright (C) 1997-2004, All rights reserved 5# Risoe National Laborartory, Roskilde, Denmark 6# Institut Laue Langevin, Grenoble, France 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; version 2 of the License. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program; if not, write to the Free Software 19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20# 21# 22 23require "mcplotlib.pl"; 24use IPC::Open2; 25use Config; 26 27my $pid = 0; 28my $instr_inf, $sim_inf, $datalist, $sim_error; 29my $TkUp = 0; 30my $termnum = 0; 31my $default_term; 32# This part should perhaps go to mccode_config.perl 33if ($Config{'osname'} eq 'MSWin32') { 34 $default_term="windows"; 35 $termnum =""; 36} elsif ($Config{'osname'} eq 'darwin') { 37 $default_term="aqua"; 38} else { 39 $default_term="x11"; 40} 41$default_term = $MCSTAS::mcstas_config{GNUDEV}; 42my $term = $default_term; 43my @monitornames; 44my $currentmon = 'Overview'; 45my $monitorlist; 46my @gformats = ('psc','ps','gif','png'); 47my $gformat = 'psc'; 48my @suffixes = ('ps','ps','gif','png'); 49my $suffix = '.ps'; 50my @terms = ('postscript color','postscript','gif','png'); 51 52sub gnuplotit { 53 # Set up pipe to gnuplot, do first overview plot 54 # and build the Tk based gui. 55 if ($pid == 0) { 56 $pid = open2(FGNUPLOT, GNUPLOT, $MCSTAS::mcstas_config{GNUPLOT}); 57 # Allow gnuplot time to settle. 58 sleep 2; 59 } 60 ($instr_inf, $sim_inf, $datalist, $sim_error) = read_sim_file($file); 61 die "No data in simulation file '$file'" 62 unless @$datalist; 63 print GNUPLOT "\nset term $default_term\n"; 64 overview_gnuplot(); 65 if ($TkUp == 0) { 66 Tkgui(); 67 } else { 68 $currentmon = 'Overview'; 69 $monitorlist->configure(-options =>[@monitornames]); 70 } 71} 72 73sub overview_gnuplot { 74 my ($nx, $ny) = calc_panel_size(int(@$datalist)); 75 my $type; 76 @monitornames = ('Overview'); 77 # On Win32, multiple windows are not supported... 78 if (int(@$datalist) < 100 || ($default_term eq "windows")) { 79 $type = 0; 80 print GNUPLOT "\nset multiplot layout $ny,$nx\n"; 81 } else { 82 $type = 1; 83 } 84 my $info; 85 if (($term eq $default_term) && !($default_term eq "windows")) { 86 $termnum=0; 87 } 88 my $index=0; 89 for $info (@$datalist) { 90 if ($type) { 91 print GNUPLOT "\nset term $term $termnum\n"; 92 } 93 push @monitornames, $info->{'Component'}; 94 if ($info->{'Origin'} eq "scanfile") { 95 $index++; 96 } 97 gnuplot_dat_info($info, $index,$nx*$ny>1); 98 if ($type) { 99 $termnum++; 100 } 101 } 102 if (!$type) { 103 print GNUPLOT "\nunset multiplot\n"; 104 } 105} 106 107sub gnuplot_single { 108 if ($currentmon eq "Overview") { 109 overview_gnuplot(); 110 } else { 111 if (!($default_term eq "windows")) { 112 $termnum++; 113 } 114 print GNUPLOT "\nset term $term $termnum\n"; 115 my $index=0; 116 for $info (@$datalist) { 117 if ($info->{'Origin'} eq "scanfile") { 118 $index++; 119 } 120 if ($info->{'Component'} eq $currentmon) { 121 gnuplot_dat_info($info, $index,0); 122 } 123 } 124 } 125} 126 127sub gnuplot_save { 128 my $i; 129 for ($i=0; $i<@gformats; $i++) { 130 if ($gformat eq $gformats[$i]) { 131 $term = $terms[$i]; 132 $suffix = $suffixes[$i]; 133 } 134 } 135 print GNUPLOT "\nset term $term\n"; 136 if ($currentmon eq "Overview") { 137 print GNUPLOT "\nset output \"$file.$suffix\"\n"; 138 overview_gnuplot(); 139 print "Saved overview plot \"$file.$suffix\"\n"; 140 } else { 141 if (!($default_term eq "windows")) { 142 $termnum++; 143 } 144 print GNUPLOT "\nset term $term\n"; 145 my $index=0; 146 for $info (@$datalist) { 147 if ($info->{'Origin'} eq "scanfile") { 148 $index++; 149 } 150 if ($info->{'Component'} eq $currentmon) { 151 print GNUPLOT "\nset output \"$currentmon.$suffix\"\n"; 152 gnuplot_dat_info($info, $index,0); 153 print "Saved hardcopy \"$currentmon.$suffix\"\n"; 154 } 155 } 156 } 157 $term = $default_term; 158 print GNUPLOT "\nset term $term\n"; 159} 160 161sub gnuplot_dat_info { 162 my ($info, $index, $overview) = @_; 163 if ($index == 0) { 164 $index = 1; 165 } 166 my $type = $info->{'Type'}; 167 if($type =~ /^\s*array_2d\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*$/i) { 168 gnuplot_array_2d($info, $1, $2, $overview); 169 }elsif($type =~ /^\s*array_1d\s*\(\s*([0-9]+)\s*\)\s*$/i) { 170 gnuplot_array_1d($info, $1, $index, $overview); 171 } else { 172 print "Warning: Unimplemented plot type '$type' in file '$info->{Filename}' (plot_dat_info)"; 173 } 174} 175 176sub gnuplot_array_2d { 177 my ($info,$m,$n,$overview) = @_; 178 print GNUPLOT "\nset view map\n"; 179 if ($overview) { 180 print GNUPLOT "\nunset colorbox\n"; 181 print GNUPLOT "\nunset xtics\n"; 182 print GNUPLOT "\nunset ytics\n"; 183 } else { 184 print GNUPLOT "\nset colorbox\n"; 185 print GNUPLOT "\nset xlabel \"$info->{'Xlabel'}\"\nset ylabel \"$info->{'Ylabel'}\"\n"; 186 print GNUPLOT "\nset xtics\n"; 187 print GNUPLOT "\nset ytics\n"; 188 } 189 print GNUPLOT "\nset title \"$info->{'Component'}\"\n"; 190 my ($x0,$x1,$y0,$y1) = @{$info->{'Limits'}}; 191 my ($dx,$dy) = (($x1 - $x0)/($m-1), ($y1 - $y0)/($n-1)); 192 print GNUPLOT "\nsplot \"$info->{Filename}\" using ($x0+\$1*$dx):($y0+\$2*$dy):3 matrix index 0 w image notitle\n"; 193 print "\nsplot \"$info->{Filename}\" using ($x0+\$1*$dx):($y0+\$2*$dy):3 matrix index 0 w image notitle\n"; 194} 195 196 197sub gnuplot_array_1d { 198 my ($info,$m,$n,$overview) = @_; 199 print GNUPLOT "\nset title \"$info->{'Component'}\"\n"; 200 if ($overview) { 201 print GNUPLOT "\nunset xtics\n"; 202 print GNUPLOT "\nunset ytics\n"; 203 } else { 204 print GNUPLOT "\nset xlabel \"$info->{'Xlabel'}\"\nset ylabel \"$info->{'Ylabel'}\"\n"; 205 print GNUPLOT "\nset xtics\n"; 206 print GNUPLOT "\nset ytics\n"; 207 } 208 my $int = 2*$n; 209 my $err = 2*$n+1; 210 print GNUPLOT "\nplot \"$info->{Filename}\" u 1:$int with lines notitle, "; 211 print GNUPLOT " \"$info->{Filename}\" u 1:$int:$err with errorbars notitle\n"; 212} 213 214sub Tkgui { 215 use Tk; 216 use Tk::Toplevel; 217 use Tk::DirTree; 218 use Tk::Balloon; 219 $continue = 0; 220 my $win = new MainWindow(-title => "McGnuplot"); 221 eval { # Try specified color palette... 222 $win -> setPalette($MCSTAS::mcstas_config{'TKPALETTE'}); 223 }; 224 if ($@) { # or continue with system default if that failed. 225 printf "Specified colorscheme '$MCSTAS::mcstas_config{'TKPALETTE'}' failed. Using system default.\n"; 226 } 227 228 if (!($MCSTAS::mcstas_config{'TKFONT'} eq "")) { # Only try loading a font if non-empty string is defined 229 eval { # Try loading specified font... 230 $win->optionAdd("*font", $MCSTAS::mcstas_config{'TKFONT'}); 231 $win->optionAdd("*borderWidth", 1); 232 }; 233 if ($@) { # or continue with system default if that failed 234 printf "Specified font '$MCSTAS::mcstas_config{'TKFONT'}' failed. Using system default.\n"; 235 } 236 } 237 build_gui($win); 238 $TkUp=1; 239 MainLoop; 240} 241 242sub build_gui { 243 # When mcdaemon is run without any input parms, we'll build a gui 244 # to set the parameters. 245 my ($win) = @_; 246 my $topframe = $win->Frame(-relief => 'raised', -borderwidth => 2); 247 my $b = $win->Balloon(-state => 'balloon'); 248 $topframe->pack(-side => "top", -fill => "both", -ipady => 3, -ipadx => 3); 249 my $tmp1=$topframe->Label(-text => "Datafile:", -fg => 'blue', -anchor => 'w', 250 -justify => "center")->pack(-side => "left"); 251 $b->attach($tmp1, -balloonmsg => "Chosen Datafile"); 252 my $filelabel = $topframe->Label(-width => 60, 253 -textvariable => \$file)->pack(-side => "left"); 254 my $fileselect = $topframe->Button(-text => "Select", -command => [\&select_file, $win])->pack(-side => "right"); 255 $b->attach($fileselect, -balloonmsg => "Click here to select a new file to plot (e.g. mcstas.sim)"); 256 #my $dirselect = $topframe->Button(-text => "Dir", -command => [\&select_dir])->pack(-side => "left"); 257 #$b->attach($dirselect, -balloonmsg => "Click here to select a directory to monitor"); 258 my $midframe = $win->Frame(-relief => 'raised', -borderwidth => 2); 259 $midframe->pack(-side => "top", -fill => "both", -ipady => 3, -ipadx => 3); 260 my $tmp2= $midframe->Label(-text => "Plot monitor: ", -anchor => 'w', 261 -justify => "center")->pack(-side => "left"); 262 $b->attach($tmp2, -balloonmsg => "Sets the time between changes check"); 263 $monitorlist = $midframe->Optionmenu(-textvariable => \$currentmon, -options => 264 [@monitornames])->pack(-side => 'left'); 265 my $tmp3=$midframe->Button(-text => "Display", -anchor => 'w', 266 -justify => "center", -command => [\&gnuplot_single])->pack(-side => "left"); 267 $b->attach($tmp3, -balloonmsg => "Plot selected monitor on screen"); 268 my $tmp4=$midframe->Button(-text => "Save, format ->", -anchor => 'w', 269 -justify => "center", -command => [\&gnuplot_save])->pack(-side => "left"); 270 $b->attach($tmp4, -balloonmsg => "Save selected monitor to file"); 271 my $graphics = $midframe->Optionmenu(-textvariable => \$gformat, -options => 272 [@gformats])->pack(-side => 'left'); 273 my $bottomframe = $win->Frame(-relief => 'raised', -borderwidth => 2); 274 $bottomframe->pack(-side => "top", -fill => "both", -ipady => 3, -ipadx => 3); 275 276 $bottomframe->Button(-text => "Exit", -fg => 'green', -command => sub {$continue=1; $win->destroy; print GNUPLOT "\n\nexit\n";})->pack(-side => "right", -anchor => "w"); 277} 278 279sub select_file { 280 my ($w) = @_; 281 my $filename = $w->getOpenFile(-title => "Select file to plot", -initialdir => getcwd()); 282 if (!$filename == '') { 283 $file = $filename; 284 gnuplotit(); 285 } 286} 287 288sub select_dir { 289 my $top = new MainWindow; 290 $top->withdraw; 291 292 my $t = $top->Toplevel; 293 $t->title("Choose dir to monitor:"); 294 my $ok = 0; 295 my $f = $t->Frame->pack(-fill => "x", -side => "bottom"); 296 297 my $curr_dir = getcwd(); 298 299 my $d; 300 $d = $t->Scrolled('DirTree', 301 -scrollbars => 'osoe', 302 -width => 35, 303 -height => 20, 304 -selectmode => 'browse', 305 -exportselection => 1, 306 -browsecmd => sub { $curr_dir = shift }, 307 -command => sub { $ok = 1 }, 308 )->pack(-fill => "both", -expand => 1); 309 $f->Button(-text => 'Ok', 310 -command => sub { $ok = 1 })->pack(-side => 'left'); 311 $f->Button(-text => 'Cancel', 312 -command => sub { $ok = -1 })->pack(-side => 'left'); 313 314 $f->waitVariable(\$ok); 315 316 if ($ok == 1) { 317 $filename = $curr_dir; 318 } 319 $top->destroy; 320} 321 3221; 323