Mathematica Scripting

Konstantin Kouptsov
Wolfram Research

Mathematica Notebook Front End

• Journal of iterative calculations.

• Automatic structuring of calculations into parts using sections, subsections etc.

• Graphics and formula typesetting.

• Dynamic interactive interfaces.

• Publication-quality printable document.

• Computable Document Format (CDF)

Mathematica scripting

• Encapsulates repetitive multi-step calculations requiring no intermediate user interaction.

• Avoids FE overhead

converting to and from box language

extra memory footprint

communication over mathlink

• Requires no GUI environment, e.g. XWindows,...

• Can work on the server, where no terminal is available

• Deployment on a cluster / cloud.

• Works generally with files: Import, Export, Read, Write, ...

Batch tasks

Version 7 use pattern:

% math < infile.m > outfile

For example:

$ cat a.m
↵
Print[Expand[(x+y)^10]]↵
↵
EOF

Output:

$ MathKernel < a.m
Mathematica 8.0 for Mac OS X x86 (64-bit)
Copyright 1988-2010 Wolfram Research, Inc.

In[1]:= 
In[1]:= 10       9         8  2        7  3        6  4        5  5        4  6
       x   + 10 x  y + 45 x  y  + 120 x  y  + 210 x  y  + 252 x  y  + 210 x  y  + 
 
         3  7       2  8         9    10
>   120 x  y  + 45 x  y  + 10 x y  + y

In[2]:= 
In[2]:= 
In[2]:=

-batchoutput

Problems

• Start up banner

• In/Out prompts

• PageWidth

• OutputForm

Using -batchoutput:

$ MathKernel -batchoutput < a.m

x^10 + 10*x^9*y + 45*x^8*y^2 + 120*x^7*y^3 + 210*x^6*y^4 + 252*x^5*y^5 + 210*x^4*y^6 + 120*x^3*y^7 + 45*x^2*y^8 + 10*x*y^9 + y^10

Still ...

• Redirection of standard input

• If no input is redirected, MathKernel waits for explicit Quit to terminate

$ cat a1.m
↵
Print[Input[]]↵
EOF

$ MathKernel -batchoutput < a1.m

? EndOfFile

-script

Using -script:

$ MathKernel -script a.m
x^10 + 10*x^9*y + 45*x^8*y^2 + 120*x^7*y^3 + 210*x^6*y^4 + 252*x^5*y^5 + 210*x^4*y^6 + 120*x^3*y^7 + 45*x^2*y^8 + 10*x*y^9 + y^10↵

Works as -batchoutput but

• no redirection. Standard input can be used within the script, e.g. in Read.

• prints only when requested:

$ cat b.m
Expand[(x+y)^3]↵
Print[Expand[(x+y)^4]]EOF

$ MathKernel -batchoutput < b.m
↵
x^3 + 3*x^2*y + 3*x*y^2 + y^3↵
x^4 + 4*x^3*y + 6*x^2*y^2 + 4*x*y^3 + y^4↵
↵

$ MathKernel -script b.m
x^4 + 4*x^3*y + 6*x^2*y^2 + 4*x*y^3 + y^4↵

MathKernel -script b.m effectively calls Get[“b.m”], then terminates.

Unix magic (#!)

(Not for that reason but)
The first bytes in a (binary) file often serve as identifier of the file type, and called a magic number.

When #! (0x23 0x21) occur as the first two bytes in a text file, the Unix OS parses the first line to determine the interpreter, which knows how to execute the file.

$ cat f
#!/bin/csh
echo $((1 + 1))

$ ./f
Illegal variable name.

but

$ cat g
#!/bin/sh
echo $((1 + 1))

$ ./g
2

#! - a bit of history

From dmr Thu Jan 10 04:25:49 1980 remote from research

The system has been changed so that if a file being executed
begins with the magic characters #! , the rest of the line is understood
to be the name of an interpreter for the executed file.
Previously (and in fact still) the shell did much of this job;
it automatically executed itself on a text file with executable mode
when the text file’s name was typed as a command.
Putting the facility into the system gives the following
benefits.

1) It makes shell scripts more like real executable files,
because they can be the subject of ‘exec.’

2) If you do a ‘ps’ while such a command is running, its real
name appears instead of ‘sh’.
Likewise, accounting is done on the basis of the real name.

3) Shell scripts can be set-user-ID.

4) It is simpler to have alternate shells available;
e.g. if you like the Berkeley csh there is no question about
which shell is to interpret a file.

5) It will allow other interpreters to fit in more smoothly.

To take advantage of this wonderful opportunity,
put

	#! /bin/sh

at the left margin of the first line of your shell scripts.
Blanks after ! are OK.  Use a complete pathname (no search is done).
At the moment the whole line is restricted to 16 characters but
this limit will be raised.

Advantages of #! scripts

• the executable script is used on equal footing with the compiled programs, e.g. subject to exec() system call

• it is seen as a self–contained executable, that is the user is not required to provide invocation details, such as path to the interpreter or command line switches with each use of the script

• the script can be seamlessly integrated with the other OS commands, e.g. within another script

• the standard input is not redirected, which allows the script to be used in a pipe or interactively

• the name of the script is accessible inside the script

• ps shows the name of the script, not interpreter

• can be made set-UID

#! behind the scenes

C program named mshell, representing the shell interpreter.

The program simply echoes the command line arguments supplied to it. The arguments are printed in square brackets to clarify what makes each of the argument.

#include <stdio.h>

void main(int argc, char **argv) {
	for (int i=0; i<argc; i++)
		printf(“ [%s]”, argv[i]);
}

Shell script named foo.m:

#! mshell -a -script

(* here goes Mathematica code *)
Print[1+1]

When called with arguments, the script displays the values of argv[0], argv[1] etc. On Linux:

$ foo.m 1 2 3
 [mshell] [-a -script] [./foo.m] [1] [2] [3]

On Mac OS X, the structure of the argument is different:

$ foo.m 1 2 3
 [mshell] [-a] [-script] [./foo.m] [1] [2] [3]

Mathematica interpreter — MathematicaScript

$ cat c.m
#!/Users/kkouptsov/bin/MathematicaScript -script

Print[Expand[(x+y)^10]]

$ chmod a+x c.m

$ ./c.m
x^10 + 10*x^9*y + 45*x^8*y^2 + 120*x^7*y^3 + 210*x^6*y^4 + 252*x^5*y^5 + 210*x^4*y^6 + 120*x^3*y^7 + 45*x^2*y^8 + 10*x*y^9 + y^10

The interpreter can be renamed or used via a symbolic link:

$ ln -s /Users/kkouptsov/bin/MathematicaScript /bin/mshell

$ ls -l /bin/mshell
lrwxr-xr-x  mshell -> /Mathematica/8.0/Mathematica.app/Contents/MacOS/MathKernel

$ cat cm.m
#!/bin/mshell -script

Print[Expand[(x+y)^10]]

$ chmod a+x cm.m

$ cm.m
x^10 + 10*x^9*y + 45*x^8*y^2 + 120*x^7*y^3 + 210*x^6*y^4 + 252*x^5*y^5 + 210*x^4*y^6 + 120*x^3*y^7 + 45*x^2*y^8 + 10*x*y^9 + y^10

$ScriptCommandLine

It is equivalent to the argv[] array: argv[0] is the name of the program (script), argv[1] and further are the script’s arguments:

$ cat d.m
#!/Users/kkouptsov/bin/MathematicaScript a b c -script

Print[“$ScriptCommandLine is ”, $ScriptCommandLine]

$ d.m 1 2 3
$ScriptCommandLine is {“./d.m”, “1”, “2”, “3”}

$ cat d.m
#!/Users/kkouptsov/bin/MathematicaScript a b c -script

Print[$CommandLine]

$ d.m 1 2 3
{“/Mathematica/8.0/Mathematica.app/Contents/MacOS/MathKernel”, “-runfirst”, “$TopDirectory=\”/Mathematica/8.0/Mathematica.app\””, “a”, “b”, “c”, “-script”, “./d.m”, “--“, “./d.m”, “1”, “2”, “3”}

Arguments a, b, c and -script are interpreted as options for the MathKernel.

"--" indicates that the following aruments are to be treated literally (not as options). For example, you may want to pass -mathlink  to be used in the script, not by the interpreter.

Get is modified

$ cat b.m
#!/Users/kkouptsov/bin/MathematicaScript -script

Print[Expand[(x+y)^10]]

$ MathKernel
Mathematica 8.0 for Mac OS X x86 (64-bit)
Copyright 1988-2010 Wolfram Research, Inc.

In[1]:= Get[“b.m”]
 10       9         8  2        7  3        6  4        5  5        4  6
x   + 10 x  y + 45 x  y  + 120 x  y  + 210 x  y  + 252 x  y  + 210 x  y  + 
 
         3  7       2  8         9    10
>   120 x  y  + 45 x  y  + 10 x y  + y

Input file name

$InputFileName gives the full path to the script:

$ cat q.m
#!/Users/kkouptsov/bin/MathematicaScript -script

Print[$InputFileName]

Print[$Input]

Print[First[$ScriptCommandLine]]

$ ./q.m
“/Users/kkouptsov/Conference/q.m”
“./q.m”
“./q.m”

Conclusion

Thank you.