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

Revision 2058, 11.8 KB (checked in by pkwi, 5 years ago)

From next release, McStas is GPL 2 only.

The debate on the internet about the future GPL 3 suggests that this license might have implications on the 'derived work', hence have implications on what and how our users use their McStas simulations.

  • Property svn:executable set to *
Line 
1#!/usr/bin/perl
2#
3# Script for converting between
4#   Matlab->Scilab
5#   Scilab->Matlab
6# McStas data
7#
8# Cyclic conversion, e.g. Matlab->Scilab->Matlab is NOT supported!
9#
10# Peter Willendrup, Risoe, 20031205
11#
12#   This file is part of the McStas neutron ray-trace simulation package
13#   Copyright (C) 1997-2004, All rights reserved
14#   Risoe National Laborartory, Roskilde, Denmark
15#   Institut Laue Langevin, Grenoble, France
16#
17#   This program is free software; you can redistribute it and/or modify
18#   it under the terms of the GNU General Public License as published by
19#   the Free Software Foundation; version 2 of the License.
20#
21#   This program is distributed in the hope that it will be useful,
22#   but WITHOUT ANY WARRANTY; without even the implied warranty of
23#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24#   GNU General Public License for more details.
25#
26#   You should have received a copy of the GNU General Public License
27#   along with this program; if not, write to the Free Software
28#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29#
30#   Based on / inspired from m2sci.pl:
31#     (m2sci.pl by Torbjorn Pettersen <Torbjorn.Pettersen@broadpark.no>
32#      available from http://home.broadpark.no/~tpette-4/)
33#
34use File::Basename;
35use File::Find;
36use Cwd;
37use Config;
38
39# Declaration of the global scope vars,
40my ($i,$j);
41my ($outdir,$indir);
42my ($format,$randstr,$randdir,$quiet);
43my $cwd = getcwd();
44my @junk;
45
46# Assume no random output dir...
47$randdir = 0;
48# Assume we want status written to output
49$quiet = 0;
50
51# Echo something meaningful to stdout
52print "mcconvert.pl, part of the McStas simulation package\n";
53print "This is free software, licensed under the GPL\n";
54print "Copyright (C) 1997-2004, All rights reserved\n";
55print "Risoe National Laborartory, Roskilde, Denmark\n";
56print "Institut Laue Langevin, Grenoble, France\n\n";
57
58# Parse the commandline args
59for ($i = 0; $i< @ARGV; $i++) {
60  if ($ARGV[$i] =~ /^--format=([a-zA-Z0-9_\"]+)$/) {
61    $format = $1;
62  } elsif ($ARGV[$i] =~ /^--outdir=([a-zA-Z0-9_\\\/\"\:\.~]+)$/) {
63    $outdir = $1;
64  } elsif ($ARGV[$i] =~ /^--indir=([a-zA-Z0-9_\\\/\"\:\.~]+)$/) {
65    $indir = $1;
66  } elsif ($ARGV[$i] eq "--quiet") {
67    $quiet = 1;
68  } elsif ($ARGV[$i] eq "--help") {
69    # Print some help info, next exit
70    print "\nmcconvert.pl script from McStas\n";
71    print "\nConverts between Matlab and Scilab version of\nMcStas output data.\n";
72    print "\nusage:\n";
73    print "\nNo arguments:\n\tWill try to guess wanted output format\n\tWill place files in random subdir\n";
74    print "\tWill try to convert files in current dir\n";
75    print "\n--format=FORMAT\n\tSpecifies wanted output format, i.e. Matlab or Scilab\n";
76    print "\n--outdir=DIR\n\tSpecifies wanted output directory\n";
77    print "\n--indir=DIR\n\tSpecifies wanted input directory\n";
78    print "\n--quiet\n\tSuppress status info (e.g. mcstas.m -> mcstas.sci)\n";
79    print "\nIf no --indir  is specified, --indir=\".\" is assumed\n";
80    print "\nWarning: mcconvert.pl searches the --indir RECURSIVELY\n\n";
81    exit();
82  } else {
83    push @junk, $ARGV[$i];
84  }
85}
86
87if (@junk>0) {
88  print "Warning: Options @junk on commandline not understood...\n\n";
89}
90
91# Handle the indir first...
92if (!$indir) {
93    print "You did not give me any files to convert, assuming that you ment everything in .\n";
94    $indir = ".";
95}
96
97if (! -e $indir) {
98    die "mcconvert.pl: Input directory $indir does not exist...\n\n";
99}
100
101if (-e "$indir/.converted") {
102    print STDERR "\nmcconvert.pl:You are seeminly trying to convert a set of converted data!";
103    die "\nCyclic conversion not supported!\n\n";
104}
105
106if (!$format) {
107    print "You did not specify a conversion format (Scilab/Matlab)\n";
108    print "Trying to guess one... ";
109    if ((-e "$indir/mcstas.sci") && (! -e "$indir/mcstas.m")) {
110        $format = "Matlab";
111    } elsif ((! -e "$indir/mcstas.sci") && (-e "$indir/mcstas.m")) {
112        $format = "Scilab";
113    } elsif ((-e "$indir/mcstas.sci") && (-e "$indir/mcstas.m")) {
114        die "mcconvert.pl: You have mcstas.sci AND mcstas.m - don't know what to do then...\n\n";
115    } else {
116        die "mcconvert.pl: Could not find a Matlab/Scilab mcstas.* to convert from...\n\n";
117    }
118    print "Converting to $format format...\n";
119}
120
121
122if (!$outdir) {
123    # Create a random directory for the converted data
124    $randstr = generate_random_string(5);
125    $outdir = "converted_${format}_${randstr}";
126    $randdir = 1;
127}
128if (! -e $outdir) {
129    mkdir($outdir) or die "mcconvert.pl: Could not create $outdir\n\n";
130    open(TMP,">$outdir/.stop");
131    close(TMP);
132}
133if ($Config{'osname'} eq 'MSWin32') {
134    if (!($outdir =~ /^.:/)) {
135        $outdir = "$cwd/$outdir";       
136    }
137} else {
138    if (!($outdir =~ /^\//)) {
139        $outdir = "$cwd/$outdir";
140    }
141}
142if ($randdir == 1) {
143  print "\nYour files, converted to $format format will be placed in $outdir\n\n";
144}
145
146# If this is Win32, let us simply make any \ in the filenames a /
147if ($Config{'osname'} eq 'MSWin32') {
148    @junk = split(/\\/,$outdir);
149    $outdir = join('/',@junk);
150    @junk = split(/\\/,$indir);
151    $indir = join('/',@junk);
152}
153
154# We are now ready to do the work:
155chdir($indir);
156find(\&findit,".");
157
158open(TMP,">$outdir/.converted");
159close(TMP);
160chdir($cwd);
161print "\n\nmcconvert.pl done...\n\n";
162
163sub findit {
164    my $object = $File::Find::name;
165    $object =~ s!^\.!$outdir!g;
166    if (-e ".stop") {
167        $File::Find::prune = 1;
168    } else {
169        if (-d $_) {
170            if (!($object eq $outdir)) {
171                if ((! -e $object) && (! -e "$_/.stop")) {
172                    mkdir($object) || die "mcconvert.pl: Could not create $object!\n\n";
173                }
174            }
175        } else {
176            convert($_,$object);
177        }
178    }
179}
180
181
182sub convert {
183    my ($infile,$outfile) = @_;
184    my ($tmp, $base, $dirname, $suffix, $NEXTFUNC);
185    $tmp = $File::Find::dir;
186    $tmp =~ s!^\.\/!$indir/!;
187
188    # Split the filename in pieces:
189    ($base, $dirname, $suffix) = fileparse($outfile,".m",".sci");
190    if ($suffix eq ".m") {
191        $outfile = "$dirname$base.sci";
192    } elsif ($suffix eq ".sci") {
193        $outfile = "$dirname$base.m";
194    } else {
195        $outfile = "$dirname$base";
196    }
197
198    # Adjust the $base, remove .'s
199    $base =~ s!\.!_!g;
200
201    if ($quiet == 0) {
202      print "Reading from $tmp/$infile -> ";
203    }
204    open(IN,"<$infile");
205    open(OUT,">$outfile") || die "mcconvert.pl: Unable to create $outfile: $!\n\n";
206    if ($quiet == 0) {
207      print "\t $outfile\n";
208    }
209    $NEXTFUNC = 0;
210    while (<IN>) {
211        if ($format eq "Scilab") {
212            if ((/^\w*function/) & $NEXTFUNC) {
213                print OUT "endfunction\n"; # add endfunction
214            } else { $NEXTFUNC = 1;};
215       
216            unless (/\w*fprintf\w*/) {
217                s/%/\/\//g;                     # Comments are replaced
218            }
219       
220            s/nargout/argn(1)/g;        # Outputarguments to function
221            s/nargin/argn(2)/g;         # Inputarguments to function
222       
223            s/isempty\((\w*)\)/($1==[])/g;
224            s/\r$//g;
225       
226            # Replacing matlab functions with corresponding scilab commands.
227            s/\bchar\b/ascii/;
228            s/\bcompan\b/companion/g;
229            s/\bfclose\b/mclose/g;
230            s/\bfigure\b/xbasc/g;
231            s/\bfopen\b/mopen/g;
232            s/\breshape\b/matrix/g;
233            s/\bfindstr\b/strindex/g;
234            s/\bif\ single_file\b/if\ single_file==1/g;
235            s/\.func=\'/\.func=\'get_/g;
236        } elsif ($format eq "Matlab") {
237            if (/^\w*endfunction/) {
238                print OUT "%" ; # comment out endfunction
239            }
240            unless (/\w*fprintf\w*/) {
241                s/\/\//%/g;                     # Comments are replaced
242            }
243       
244            s/argn\(1\)/nargout/g;      # Outputarguments to function
245            s/argn\(2\)/nargin/g;               # Inputarguments to function
246       
247            s/(\w*)==\[\]/isempty\(($1)\)/g;
248            s/struct\(\)/\[\]/g;
249       
250            # Replacing matlab functions with corresponding scilab commands.
251            s/\bascii\b/char/;
252            s/\bcompanion\b/compan/g;
253            s/\bmclose\b/fclose/g;
254            s/\bxbasc\b/figure/g;
255            s/\bmopen\b/fopen/g;
256            s/\bmatrix\b/reshape/g;
257            s/\bstrindex\b/findstr/g;
258            s/\bif\ single_file==1/if\ single_file/g;
259            s/\bmode\b/\%mode/g;
260        }
261       
262        # Check if we are at one of the inline functions - print new according
263        # to format, then exit (closing the open files...).
264        if (/^\w*function d=mc\w*_inline/) {
265            inline_replace(OUT,$format,$base);
266            close(IN);
267            close(OUT);
268        }
269        print OUT;
270    }
271    close(OUT);
272}
273
274# Function for replacing the inline_ Matlab/Scilab functions
275sub inline_replace {
276    my ($OUTFILE,$format,$base) = @_;
277    if ($format eq "Scilab") {
278        print $OUTFILE
279"function d=mcload_inline(d)
280// local inline func to load data
281execstr(['S=['+part(d.type,10:(length(d.type)-1))+'];']);
282if ~length(d.data)
283 if ~length(strindex(d.format, 'binary'))
284  exec(d.filename,-1);p=d.parent;
285  if ~execstr('d2='+d.func+'();','errcatch'),d=d2; d.parent=p;end
286 else
287  if length(strindex(d.format, 'float')), t='f';
288  elseif length(strindex(d.format, 'double')), t='d';
289  else return; end
290  fid=mopen(d.filename, 'rb');
291  pS = prod(S);
292  x = mget(3*pS, t, fid);
293  d.data  =matrix(x(1:pS), S);
294  if length(x) >= 3*pS,
295  d.errors=matrix(x((pS+1):(2*pS)), S);
296  d.events=matrix(x((2*pS+1):(3*pS)), S);end
297  mclose(fid);
298  return
299 end
300end
301endfunction
302function d=mcplot_inline(d,p)
303// local inline func to plot data
304if ~length(strindex(d.type,'0d')), d=mcload_inline(d); end
305if ~p, return; end;
306execstr(['l=[',d.xylimits,'];']); S=size(d.data);
307t1=['['+d.parent+'] '+d.filename+': '+d.title];t = [t1;['  '+d.variables+'=['+d.values+']'];['  '+d.signal];['  '+d.statistics]];
308mprintf('%s\\n',t(:));
309if length(strindex(d.type,'0d')),return;
310else
311w=winsid();if length(w),w=w(\$)+1; else w=0; end
312xbasr(w); xset('window',w);
313if length(strindex(d.type,'2d'))
314 d.x=linspace(l(1),l(2),S(2)); d.y=linspace(l(3),l(4),S(1)); z=d.data;
315 xlab=d.xlabel; ylab=d.ylabel; x=d.x; y=d.y;
316 fz=max(abs(z));fx=max(abs(d.x));fy=max(abs(d.y));
317 if fx>0,fx=round(log10(fx)); x=x/10^fx; xlab=xlab+' [*10^'+string(fx)+']'; end
318 if fy>0,fy=round(log10(fy)); y=y/10^fy; ylab=ylab+' [*10^'+string(fy)+']'; end
319 if fz>0,fz=round(log10(fz)); z=z/10^fz; t1=t1+' [*10^'+string(fz)+']'; end
320 xset('colormap',hotcolormap(64));
321 plot3d1(x,y,z',90,0,xlab+'@'+ylab+'@'+d.zlabel); xtitle(t);
322else
323d.x=linspace(l(1),l(2),max(S));
324 plot2d(d.x,d.data);xtitle(t,d.xlabel,d.ylabel);end
325end
326xname(t1);
327endfunction
328mc_$base=get_$base();\n"
329} elsif ($format eq "Matlab") {
330    print $OUTFILE
331"function d=mcload_inline(d)
332%% local inline function to load data
333S=d.type; eval(['S=[ ' S(10:(length(S)-1)) ' ];']);
334if isempty(d.data)
335 if ~length(findstr(d.format, 'binary'))
336  copyfile(d.filename,[d.func,'.m']);p=d.parent;path(path);
337  eval(['d=',d.func,';']);d.parent=p;delete([d.func,'.m']);
338 else
339  if length(findstr(d.format, 'float')), t='single';
340  elseif length(findstr(d.format, 'double')), t='double';
341  else return; end
342  if length(S) == 1, S=[S 1]; end
343  fid=fopen(d.filename, 'r');
344  pS = prod(S);
345  x = fread(fid, 3*pS, t);
346  d.data  =reshape(x(1:pS), S);
347  if prod(size(x)) >= 3*pS,
348  d.errors=reshape(x((pS+1):(2*pS)), S);
349  d.events=reshape(x((2*pS+1):(3*pS)), S);end
350  fclose(fid);
351  return
352 end
353end
354return;
355function d=mcplot_inline(d,p)
356%% local inline function to plot data
357if isempty(findstr(d.type,'0d')), d=mcload_inline(d); end\nif ~p, return; end;
358eval(['l=[',d.xylimits,'];']); S=size(d.data);
359t1=['[',d.parent,'] ',d.filename,': ',d.title];t = strvcat(t1,['  ',d.variables,'=[',d.values,']'],['  ',d.signal],['  ',d.statistics]);
360disp(t);
361if ~isempty(findstr(d.type,'0d')), return; end
362figure; if ~isempty(findstr(d.type,'2d'))
363d.x=linspace(l(1),l(2),S(2)); d.y=linspace(l(3),l(4),S(1));
364surface(d.x,d.y,d.data);
365else\nd.x=linspace(l(1),l(2),max(S));\nplot(d.x,d.data);end
366xlabel(d.xlabel); ylabel(d.ylabel); title(t); axis tight;
367set(gca,'position',[.18,.18,.7,.65]); set(gcf,'name',t1);grid on;
368if ~isempty(findstr(d.type,'2d')), colorbar; end"
369}
370}
371
372# This function generates random strings of a given length
373sub generate_random_string
374{
375        my $length_of_randomstring=shift;#the length of the random string to generate
376
377        my @chars=('a'..'z','A'..'Z','0'..'9','_');
378        my $random_string;
379        foreach (1..$length_of_randomstring) 
380        {
381                #rand @chars will generate a random number between 0 and scalar @chars
382                $random_string.=$chars[rand @chars];
383        }
384        return $random_string;
385}
386
Note: See TracBrowser for help on using the browser.