6. Python Scripts

Scripting allows for automation of repetitive tasks and as such is a valuable tool to increase productivity and to avoid unnecessary clicking and typing. To this end, baspl++ makes use of the Python programming language.

6.1. Creating and Writing Python Scripts

The conventional way of creating a Python script is to write it; that is, to start a text editor, create a new text document, and write the Python code line by line. baspl++ knows a faster and easier way to create Python scripts.

Assume that several baspl++ objects (Model, Field, NPart, etc.) have already been created by the user by means of the graphical user interface. At this point, selecting in the main menu File>Create Script... will do the following: A file dialog opens where the name of the script to be created must be entered, and the script is created.

This create-script function looks up all currently existing (baspl++) Python objects, their current settings, and the current relationships between them. From this information, several lines of Python code are written to the selected file. Note that this is not a "trace" of what the user has entered into the graphical user interface during the whole session. Instead, it is a concise set of Python commands which reproduces the situation at the time when the create-script function was invoked.

Executing this script later when re-starting baspl++ will re-create all baspl++ objects with their settings.

Instead of using the graphical user interface, the script can be created from the Python console by typing

>>> create_script()

By default, the lines of Python code will be written to the Python console rather than to a file. Typing

>>> create_script('view.py')

will write the generated Python code to the file "view.py".

The created script file(s) can then be opened in a text editor and further customized.

6.2. Executing a Python Script at Startup

See the section Section 3 on how to execute a Python script when starting baspl++.

6.3. Executing Python Scripts from within baspl++

To execute a Python script from within a running baspl++ session, either

  • Select File->Execute Script... from the main menu. A file dialog opens where the Python script to be executed can be chosen.

  • Or, on the Python console, use Python's execfile function:

    >>> execfile('view.py')

    [Note] Note

    If this script takes command-line arguments (it reads the variable sys.argv), modify sys.argv accordingly prior to calling execfile.

6.4. A Few Notes on the Python Programming Language

For the Python interface of baspl++, the complete Python environment is installed automatically when baspl++ is installed. To make productive use of baspl++'s Python interface, basic knowledge of the popular Python programming language is required.

Documentation on the Python environment (the interpreter, the language, the modules, etc.) can be found here. For beginners, it is recommended to start with the introduction of the tutorial.

The remainder of this section describes a number of particular points which might be useful when writing Python scripts for baspl++.

6.5. Pre-Imported Python Modules

On the baspl++ Python console and from the Python scripts executed by baspl++, the following standard Python modules are already imported:

  • os: Miscellaneous operating system interfaces.

  • sys: Access system-specific parameters and functions. Of special importance are the sys.argv variable and the sys.exit() function.

  • time: Time access and conversions. Useful is the time.sleep() function for animations.

The following non-standard Python modules are also imported:

  • numpy: mathematical operations over arrays, linear algebra, Fourier transform, etc.

  • GL and GLU: OpenGL functions.

  • memcom: The Python interface to the MemCom data manager (SMR).

  • mci: The MemCom Indexing Framework(SMR).

6.6. Pre-Defined Global Variables

On the baspl++ Python console and from the Python scripts executed by baspl++, the following global variables are defined:

  • iwd: The initial working directory (see Section 6.8 below) .

  • l: A reference to the default LightSource object. Note that, when baspl++ is started with the --no-scene or the --no-lightsource option, l is not defined.

  • s: A reference to the default Scene object. Note that, when baspl++ is started with the --no-scene option, s is not defined.

  • m, m1, m2...: For each database given on the command-line, a Model object is created and referenced by the global variable m, m1, m2, respectively.

In addition, any global object (variable, module, function, class, etc.) defined or imported in a script remains defined after termination of the script. For instance, if the script assigns a Model object to the global variable m and a Field object to the global variable f, the variables m and f can be used to access the respective objects from the Python console once the script has terminated.

6.7. Using the sys.argv variable.

The variable sys.argv is a list containing the command-line arguments. Following standard UNIX convention, the first argument (sys.argv[0]) is the program's name, thus the first user-supplied argument is in sys.argv[1]. To obtain the number of user-supplied arguments, use the universal len() function of Python:

len(sys.argv[1:])

Assume the file view.py contains the following lines of Python:

if len(sys.argv[1:]) != 1:
    print 'usage: baspl++ view.py database'
    sys.exit(1)
m = Model(sys.argv[1]) # get the Model name from the command-line args
f = Field(m, name='VELO', cycle=1)
p = NPart(m)
p.contour.compname = 'amplitude'
p.contour.field = f
p.faceset.extract = 1

Further assume that in the same directory, there is a CFD MemCom database called airfoil.mc.

To execute view.py with that database, enter the following command on the terminal.

baspl++ view.py airfoil.mc

6.8. The Working Directories

The current working directory can always be obtained by means of Python's os.getcwd() function. During script execution, baspl++ sets the working directory to the directory containing the script. When the script terminates, baspl++ returns to the initial working directory. This way, databases can be accessed relative to the directory containing the script.

But sometimes it is necessary to access files and directories relative to the path where baspl++ was started. For this reason, the iwd (initial working directory) global variable is initialized at startup and can be used to access databases that are in the directory where baspl++ was started.

The code in the following example must be placed in a script (that is, in a text file, for example "view.py"). It demonstrates how the iwd variable can be used to access files relative to the directory where baspl++ was started. The os.path.join() function is the standard Python mechanism to concatenate file paths. On UNIX systems, os.path.join(a, b) is equivalent to a + '/' + b.

print 'Current working directory (script):', os.getcwd()
print 'Initial working directory         :', iwd

dbname = os.path.join(iwd, sys.argv[1]) # take db name from command-line
print 'Database path                     :', dbname
pixname = os.path.join(iwd, 'a.png')
print 'Raster image path                 :', pixname

m = Model(dbname)         # Create the Model 
p = NPart(m)              # Create the Part
p.elements.extract = 1    # Select all elements
s.export_to_file(pixname) # Make a picture from the default Scene

In the following we assume that the script "view.py" resides in the directory /home/user/scripts, while the database "zalt.b2m" is in /home/user/bridge. We start the script from the latter directory:

$ cd /home/user/bridge

$ ls -l
total 360
drwxr-x---  3 user     user        512 Oct 29  2004 zalt.b2m

$ baspl++ -t /home/user/scripts/view.py zalt.b2m
Current working directory (script): /home/user/scripts
Initial working directory         : /home/user/bridge
Database path                     : /home/user/bridge/zalt.b2m
Raster image path                 : /home/user/bridge/a.png

$ ls -l
total 360
drwxr-x---  3 tludwig  tludwig     512 Oct 29  2004 zalt.b2m
-rw-r--r--  1 tludwig  tludwig      75 Apr 19 15:29 a.png