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