| 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 | # |
|---|
| 34 | use File::Basename; |
|---|
| 35 | use File::Find; |
|---|
| 36 | use Cwd; |
|---|
| 37 | use Config; |
|---|
| 38 | |
|---|
| 39 | # Declaration of the global scope vars, |
|---|
| 40 | my ($i,$j); |
|---|
| 41 | my ($outdir,$indir); |
|---|
| 42 | my ($format,$randstr,$randdir,$quiet); |
|---|
| 43 | my $cwd = getcwd(); |
|---|
| 44 | my @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 |
|---|
| 52 | print "mcconvert.pl, part of the McStas simulation package\n"; |
|---|
| 53 | print "This is free software, licensed under the GPL\n"; |
|---|
| 54 | print "Copyright (C) 1997-2004, All rights reserved\n"; |
|---|
| 55 | print "Risoe National Laborartory, Roskilde, Denmark\n"; |
|---|
| 56 | print "Institut Laue Langevin, Grenoble, France\n\n"; |
|---|
| 57 | |
|---|
| 58 | # Parse the commandline args |
|---|
| 59 | for ($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 | |
|---|
| 87 | if (@junk>0) { |
|---|
| 88 | print "Warning: Options @junk on commandline not understood...\n\n"; |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | # Handle the indir first... |
|---|
| 92 | if (!$indir) { |
|---|
| 93 | print "You did not give me any files to convert, assuming that you ment everything in .\n"; |
|---|
| 94 | $indir = "."; |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | if (! -e $indir) { |
|---|
| 98 | die "mcconvert.pl: Input directory $indir does not exist...\n\n"; |
|---|
| 99 | } |
|---|
| 100 | |
|---|
| 101 | if (-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 | |
|---|
| 106 | if (!$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 | |
|---|
| 122 | if (!$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 | } |
|---|
| 128 | if (! -e $outdir) { |
|---|
| 129 | mkdir($outdir) or die "mcconvert.pl: Could not create $outdir\n\n"; |
|---|
| 130 | open(TMP,">$outdir/.stop"); |
|---|
| 131 | close(TMP); |
|---|
| 132 | } |
|---|
| 133 | if ($Config{'osname'} eq 'MSWin32') { |
|---|
| 134 | if (!($outdir =~ /^.:/)) { |
|---|
| 135 | $outdir = "$cwd/$outdir"; |
|---|
| 136 | } |
|---|
| 137 | } else { |
|---|
| 138 | if (!($outdir =~ /^\//)) { |
|---|
| 139 | $outdir = "$cwd/$outdir"; |
|---|
| 140 | } |
|---|
| 141 | } |
|---|
| 142 | if ($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 / |
|---|
| 147 | if ($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: |
|---|
| 155 | chdir($indir); |
|---|
| 156 | find(\&findit,"."); |
|---|
| 157 | |
|---|
| 158 | open(TMP,">$outdir/.converted"); |
|---|
| 159 | close(TMP); |
|---|
| 160 | chdir($cwd); |
|---|
| 161 | print "\n\nmcconvert.pl done...\n\n"; |
|---|
| 162 | |
|---|
| 163 | sub 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 | |
|---|
| 182 | sub 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 |
|---|
| 275 | sub 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 |
|---|
| 281 | execstr(['S=['+part(d.type,10:(length(d.type)-1))+'];']); |
|---|
| 282 | if ~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 |
|---|
| 300 | end |
|---|
| 301 | endfunction |
|---|
| 302 | function d=mcplot_inline(d,p) |
|---|
| 303 | // local inline func to plot data |
|---|
| 304 | if ~length(strindex(d.type,'0d')), d=mcload_inline(d); end |
|---|
| 305 | if ~p, return; end; |
|---|
| 306 | execstr(['l=[',d.xylimits,'];']); S=size(d.data); |
|---|
| 307 | t1=['['+d.parent+'] '+d.filename+': '+d.title];t = [t1;[' '+d.variables+'=['+d.values+']'];[' '+d.signal];[' '+d.statistics]]; |
|---|
| 308 | mprintf('%s\\n',t(:)); |
|---|
| 309 | if length(strindex(d.type,'0d')),return; |
|---|
| 310 | else |
|---|
| 311 | w=winsid();if length(w),w=w(\$)+1; else w=0; end |
|---|
| 312 | xbasr(w); xset('window',w); |
|---|
| 313 | if 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); |
|---|
| 322 | else |
|---|
| 323 | d.x=linspace(l(1),l(2),max(S)); |
|---|
| 324 | plot2d(d.x,d.data);xtitle(t,d.xlabel,d.ylabel);end |
|---|
| 325 | end |
|---|
| 326 | xname(t1); |
|---|
| 327 | endfunction |
|---|
| 328 | mc_$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 |
|---|
| 333 | S=d.type; eval(['S=[ ' S(10:(length(S)-1)) ' ];']); |
|---|
| 334 | if 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 |
|---|
| 353 | end |
|---|
| 354 | return; |
|---|
| 355 | function d=mcplot_inline(d,p) |
|---|
| 356 | %% local inline function to plot data |
|---|
| 357 | if isempty(findstr(d.type,'0d')), d=mcload_inline(d); end\nif ~p, return; end; |
|---|
| 358 | eval(['l=[',d.xylimits,'];']); S=size(d.data); |
|---|
| 359 | t1=['[',d.parent,'] ',d.filename,': ',d.title];t = strvcat(t1,[' ',d.variables,'=[',d.values,']'],[' ',d.signal],[' ',d.statistics]); |
|---|
| 360 | disp(t); |
|---|
| 361 | if ~isempty(findstr(d.type,'0d')), return; end |
|---|
| 362 | figure; if ~isempty(findstr(d.type,'2d')) |
|---|
| 363 | d.x=linspace(l(1),l(2),S(2)); d.y=linspace(l(3),l(4),S(1)); |
|---|
| 364 | surface(d.x,d.y,d.data); |
|---|
| 365 | else\nd.x=linspace(l(1),l(2),max(S));\nplot(d.x,d.data);end |
|---|
| 366 | xlabel(d.xlabel); ylabel(d.ylabel); title(t); axis tight; |
|---|
| 367 | set(gca,'position',[.18,.18,.7,.65]); set(gcf,'name',t1);grid on; |
|---|
| 368 | if ~isempty(findstr(d.type,'2d')), colorbar; end" |
|---|
| 369 | } |
|---|
| 370 | } |
|---|
| 371 | |
|---|
| 372 | # This function generates random strings of a given length |
|---|
| 373 | sub 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 | |
|---|