root/branches/mcstas-1.x/mcstas2vitess.pl

Revision 2161, 10.9 KB (checked in by pkwi, 4 years ago)

(primarily) Win32 related fixes...

  • Property svn:executable set to *
Line 
1#! /usr/bin/perl -w
2#
3# Converts McStas instruments to Vitess equivalents. Has not been tested
4# with current versions of Vitess (20031128)
5#
6#   This file is part of the McStas neutron ray-trace simulation package
7#   Copyright (C) 1997-2004, All rights reserved
8#   Risoe National Laborartory, Roskilde, Denmark
9#   Institut Laue Langevin, Grenoble, France
10#
11#   This program is free software; you can redistribute it and/or modify
12#   it under the terms of the GNU General Public License as published by
13#   the Free Software Foundation; version 2 of the License.
14#
15#   This program is distributed in the hope that it will be useful,
16#   but WITHOUT ANY WARRANTY; without even the implied warranty of
17#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18#   GNU General Public License for more details.
19#
20#   You should have received a copy of the GNU General Public License
21#   along with this program; if not, write to the Free Software
22#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
24# Determine the path to the McStas system directory. This must be done
25# in the BEGIN block so that it can be used in a "use lib" statement
26# afterwards.
27BEGIN {
28    if($ENV{"MCSTAS"}) {
29        $MCSTAS::sys_dir = $ENV{"MCSTAS"};
30    } else {
31        $MCSTAS::sys_dir = "/usr/local/lib/mcstas";
32    }
33    $MCSTAS::perl_dir = "$MCSTAS::sys_dir/tools/perl"
34}
35use lib $MCSTAS::perl_dir;
36
37use FileHandle;
38
39require "mcstas_config.perl";
40
41# Overload with user's personal config
42if ($ENV{"HOME"} && -e $ENV{"HOME"}."/.mcstas/mcstas_config.perl") {
43  require $ENV{"HOME"}."/.mcstas/mcstas_config.perl";
44}
45
46require "mcrunlib.pl";
47
48sub make_instr_file {
49    my ($F, $par, $d) = @_;
50    my $double_decl = "";
51    my $str_decl = "";
52    my $double_adr = "";
53    my $str_adr = "";
54    my $double_letters = "";
55    my $str_letters = "";
56    my $comp_name = $d->{'name'};
57    my $comp_actuals = "";
58    for (@$par) {
59        my ($p, $let, $typ) = @$_;
60        $comp_actuals = $comp_actuals ? "$comp_actuals, $p=$p" : "$p=$p";
61        if($typ eq 'double') {
62            $double_decl = $double_decl ? "$double_decl, $p" : "double $p";
63            $double_adr = $double_adr ? "$double_adr &$p," : "&$p,";
64            $double_letters = $double_letters ? "$double_letters '$let'," : "'$let',";
65        } elsif($typ eq 'string') {
66            $str_decl = $str_decl ? "$str_decl, *$p" : "char *$p";
67            $str_adr = $str_adr ? "$str_adr &$p," : "&$p,";
68            $str_letters = $str_letters ? "$str_letters '$let'," : "'$let',";
69        } else {
70            die "Internal: make_instr_file()";
71        }
72    }
73
74    print $F <<INSTR_END;
75DEFINE INSTRUMENT McStas_$comp_name()
76/*
77 * This file has been automatically generated using the mcstas2vitess tool.
78 * See http://www.mcstas.org
79 * Component $comp_name converted into an instrument with Vitess I/O functions
80 */
81DECLARE
82%{
83/* Component parameters. */
84$double_decl;
85$str_decl;
86double pos_x, pos_y, pos_z;
87double *dptr[] =
88  {
89    $double_adr
90    &pos_x, &pos_y, &pos_z,
91    0
92  };
93char **sptr[] =
94  {
95    $str_adr
96    0
97  };
98char dchr[] =
99  {
100    $double_letters
101    'x', 'y', 'z', 0
102  };
103char schr[] =
104  {
105    $str_letters
106    0
107  };
108
109/* vitess-lib will be included when embedding Vitess_input component */
110
111/* Pointer to check whether all neutrons have been read. */
112int *check_finished;
113
114/* event parameters that exist in VITESS, but not in McStas */
115short   vitess_col;
116TotalID vitess_ID;
117
118/* Our main() function. */
119int main(int argc, char *argv[])
120{
121  mcformat=mcuse_format(getenv("MCSTAS_FORMAT") ? getenv("MCSTAS_FORMAT") : MCSTAS_FORMAT);
122  /* default is to output as McStas format */
123  mcformat_data.Name=NULL;
124  if (!mcformat_data.Name && strstr(mcformat.Name, "HTML"))
125    mcformat_data = mcuse_format("VRML");
126
127  srandom(time(NULL));  /* Random seed */
128  vitess_parseopt(argc, argv, dptr, dchr, sptr, schr); /* VITESS-style option parser */
129  mcinit();
130  do
131  {
132    mcsetstate(0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
133    mcraytrace();
134  } while(!*check_finished);
135
136  mcfinally();
137  exit(0);
138}
139%}
140INITIALIZE
141%{
142  %include "vitess-lib.h"
143  /* This double-indirection is necessary here since MC_GETPAR is not
144     available in the DECLARE section. */
145  check_finished = &MC_GETPAR(vitess_in, finished);
146  vitess_col =0;
147%}
148TRACE
149
150COMPONENT vitess_in = Vitess_input(
151    file = vitess_infile, repeat_count = vitess_repcnt,
152    bufsize = vitess_bufsize)
153  AT (0, 0, 0) ABSOLUTE
154
155COMPONENT comp = $comp_name(
156    $comp_actuals)
157  AT (pos_x, pos_y, pos_z) ABSOLUTE
158  ROTATED (0, 0, 0) ABSOLUTE
159
160COMPONENT vitess_out = Vitess_output(
161    file = vitess_outfile, bufsize = vitess_bufsize,
162    progress = vitess_tracepoints)
163  AT (0, 0, 0) ABSOLUTE
164
165FINALLY
166%{
167  double p_sum=0.0, p2_sum=0.0;
168
169  p_sum  = MC_GETPAR(vitess_out, p_out);
170  p2_sum = MC_GETPAR(vitess_out, p2_out);
171  vitess_write(mcNCounter[1]-1, mcNCounter[3], p_sum, p2_sum, pos_x, pos_y, pos_z, 0.0, 0.0);
172%}
173
174END
175INSTR_END
176}
177
178sub make_tcl_file {
179    my ($F, $par, $d) = @_;
180
181    print $F "### $d->{'name'}\n###\n";
182    print $F "gSet mcstas_", lc($d->{'name'}), "ESET {\n";
183    my $dsc = $d->{'identification'}{'short'};
184    chomp $dsc;
185    $dsc =~ s/\n/\\n/g;
186    print $F "  {\"$dsc\" header}\n";
187    for (@$par) {
188        my ($p, $let, $typ) = @$_;
189        print $F "  {$p ";
190        if($typ eq 'double') {
191            print $F "float";
192            if($d->{'parhelp'}{$p}{'default'}) {
193                print $F " $d->{'parhelp'}{$p}{'default'}";
194            } else {
195                print $F " \"\"";
196            }
197        } elsif($typ eq 'string') {
198            print $F "string";
199            if($d->{'parhelp'}{$p}{'default'}) {
200                print $F " \"$d->{'parhelp'}{$p}{'default'}\"";
201            } else {
202                print $F " \"\"";
203            }
204        } else {
205            die "Internal: make_tcl_file()";
206        }
207        print $F " {\"$p";
208        print $F " [$d->{'parhelp'}{$p}{'unit'}]" if $d->{'parhelp'}{$p}{'unit'};
209        print $F "\" ";
210        print $F "\"";
211        if($d->{'parhelp'}{$p}{'text'}) {
212            my $txt =  $d->{'parhelp'}{$p}{'text'};
213            $txt =~ s/\s+$//;
214            $txt =~ s/\n/\\n/g;
215            print $F $txt;
216        }
217        print $F "\" ";
218        print $F "\"\" $let}";
219        if($typ eq 'double') {
220            print $F " 1" unless $d->{'parhelp'}{$p}{'default'};
221        } elsif($typ eq 'string') {
222            print $F " \"\" \"\" 1" unless $d->{'parhelp'}{$p}{'default'};
223        } else {
224            die "Internal: make_tcl_file()";
225        }
226        print $F "}\n";
227    }
228    print $F "  {xpos float 0 {\"X position [m]\" \"X position of module\" \"\" x}}\n";
229    print $F "  {ypos float 0 {\"Y position [m]\" \"Y position of module\" \"\" y}}\n";
230    print $F "  {zpos float 0 {\"Z position [m]\" \"Z position of module\" \"\" z}}\n";
231    print $F "}\n";
232}
233
234if(@ARGV != 1) {
235    print STDERR "Usage: mcstas2vitess component\n";
236    print STDERR "       This tool enables to convert a single McStas component into\n";
237    print STDERR "       a Vitess module. Component string parameters should be declared\n";
238    print STDERR "       as 'char*' setting parameters. Default values are allowed.\n";
239    print STDERR "SEE ALSO: mcstas, mcdoc, mcplot, mcrun, mcgui, mcresplot, mcstas2vitess\n";
240    print STDERR "DOC:      Please visit http://www.mcstas.org\n";
241    exit 1;
242}
243
244my $compfile = $ARGV[0];
245my $compname = $compfile;
246$compname = $1 if $compname =~ /^(.*)\.(comp|cmp|com)$/;
247
248my $data = component_information($compfile);
249die "Failed to get information for component '$compfile'"
250    unless defined($data);
251
252# Read the corresponding .vif file if available.
253my %vif = ();
254my %vifletters = ();
255my $VIF = new FileHandle;
256my $vifname = "$compname.vif";
257if(open($VIF, $vifname)) {
258    while(<$VIF>) {
259        if(/^\s*([a-zA-Zᅵᅵᅵ0-9_]+)\s+-([a-zA-Z0-9])\s+(string|double)\s*$/) {
260            $vif{$1} = [$2, $3];
261            $vifletters{$2} = $1;
262        } elsif(/^\s*([a-zA-Zᅵᅵᅵ0-9_]+)\s+-([a-zA-Z0-9])\s*$/) {
263            $vif{$1} = [$2, 'double'];
264            $vifletters{$2} = $1;
265        } else {
266            die "Invalid line:\n$_\nin VITESS information file '$vifname'";
267        }
268    }
269    close $VIF;
270} else {
271    print "Note: No VITESS information file (.vif) found.\n";
272}
273
274# Now decide on how the name and type of each component parameter.
275# The following option letters are not available: fFJLZABxyz
276my @optletter = ('a', 'b', 'c', 'd', 'e', 'g', 'h', 'i',
277                 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
278                 'r', 's', 't', 'u', 'v', 'w', 'C', 'D',
279                 'E', 'G', 'H', 'I', 'K', 'M', 'N', 'O',
280                 'P', 'Q', 'R', 'S', 'T', 'Y', 'V', 'W',
281                 'X', 'Y');
282my @param = ();
283my $p;
284for $p (@{$data->{'inputpar'}}) {
285    # First look for an option letter from the .vif.
286    my ($let, $typ) = $vif{$p} ? @{$vif{$p}} : (undef, undef);
287    unless($let) {
288        # Pick a default option letter not mentioned in the .vif.
289        do {
290            $let = shift @optletter;
291        } while($let && $vifletters{$let});
292        die "Too many component parameters!" unless $let;
293    }
294    if($p =~ /(char\s*\*|string)\s+([a-zA-Zᅵᅵᅵ0-9_]+)/i)
295      { $typ = 'string'; $p=$2; }
296    $typ = 'double' unless $typ;
297    push @param, [$p, $let, $typ];
298}
299
300print "mcstas2vitess: Converting McStas component ${compname} into Vitess Module 'McStas_${compname}'\n";
301# Output the .instr file.
302my $INSTR = new FileHandle;
303my $instr_name = "McStas_${compname}.instr";
304my $c_name = "McStas_${compname}.c";
305open($INSTR, ">$instr_name") ||
306    die "Could not open output Vitess Module instrument file '$instr_name'.";
307make_instr_file($INSTR, \@param, $data);
308close($INSTR);
309print "Wrote Vitess Module instrument file '$instr_name'.\n";
310
311my @mcstas_cmd = ("mcstas", "--no-main", "-o", $c_name, $instr_name);
312print join(" ", @mcstas_cmd), "\n";
313if(system(@mcstas_cmd)) {
314    print "*** Error exit ***\n";
315    print STDERR "McStas compilation failed.\n";
316    exit 1;
317}
318print "Wrote C file '$c_name'.\n";
319
320my $out_name = "McStas_${compname}";
321my $cc = $ENV{'MCSTAS_CC'} || $MCSTAS::mcstas_config{CC};
322my $cflags = $ENV{'MCSTAS_CFLAGS'} || $MCSTAS::mcstas_config{CFLAGS};
323my $vitess_lib_name = "vitess-lib.c";
324$vitess_lib_name = $MCSTAS::sys_dir . "/share/" . $vitess_lib_name
325    unless -r $vitess_lib_name;
326die "Cannot find VITESS library file '$vitess_lib_name'"
327    unless -r $vitess_lib_name;
328my @cc_cmd = ($cc, split(' ', $cflags), "-o", $out_name,
329              "-I$MCSTAS::sys_dir", $c_name, "-lm");
330print join(" ", @cc_cmd), "\n";
331if(system(@cc_cmd)) {
332    print "*** Error exit ***\n";
333    print STDERR "C compilation failed.\n";
334    exit 1;
335}
336print "Wrote executable Vitess Module file '$out_name'.\n";
337
338# Output the .tcl file for the VITESS gui.
339my $TCL = new FileHandle;
340my $tcl_name = "McStas_${compname}.tcl";
341open($TCL, ">$tcl_name") ||
342    die "Could not open output Vitess Module Tcl file '$tcl_name'.";
343make_tcl_file($TCL, \@param, $data);
344close($TCL);
345print "Wrote Vitess Module Tcl GUI file '$tcl_name'.\n";
346print "mcstas2vitess: Convertion has been performed\n";
347
348exit 0;
Note: See TracBrowser for help on using the browser.