5. Python Macros and Scripts

LithoGraphX can be scripted in python in two ways: scripts and macros.

In both cases, you can call any process with the syntax:

Type.Name(parameter1, parameter2, ...)

For example, to call the Average stack process, with a radius of 1 and 3 steps, you will type:

Stack.Average(1, 1, 1, 3)

The parameters are in the order in which they are presented, top to bottom. To make things easier, every time you run a process, the exact Python call is written in the file LithoGraphX.py in the current folder. The current folder is the one of the file marked in the title bar of the application.

In case of an error, three exceptions may be launched:

UserCancelException

If the user canceled the process, this exception will be thrown.

ProcessError

If an error occurs while the process runs, this exception is raised, and the attached string has the error message in it.

NoSuchProcess

Exception thrown if the process doesn’t exist.

5.1. Python Scripts

Python script are the simpler ones to make. Just write a script that will be executed using the Global process Execute Python in the Python folder.

5.2. Python Macros

Macros are more like processes. They are python modules, placed in the user or system macro folder. They appear at the same place as any other process. Also, while in scripts, the names Stack, Mesh and Global are always defined, in macros they need to be imported from the lgxPy module.

To be a valid macro, the module need to define a function run:

def run(p1=default1, p2=default2, p3=default3, ...):
    ...

Remember that the parameter received are always strings, even if defaults are specified otherwise.

The number, name and default values of the parameters will be automatically extracted and presented in the user interface of LithoGraphX.

You can also define an initialize function, which need to take the same number of parameters as the run function, plus one. The extra parameter, placed at the end of the list, is the parent window, used to create dialog boxes. The function needs to return the list of parameters to pass to the run function:

def initialize(p1, p2, p3, ..., parent):
    ...
    return (p1, p2, p3, ...)

At last, we noticed that the initialize and run typically have to perform the same argument parsing. To help with that, you can define a function that will be called automatically before either run or initialize to parse the arguments:

def parseParms(p1, p2, p3, ...):
    return (p1, p2, p3, ...)

The number of returned argument must be the same as the number of parameter, but they will typically be of the correct type.

Other variables that the module can defines are:

processName

Name of the process, instead of the name of the module. If not specified, the default is the name of the module (e.g. the name of the file without the .py).

processType

Must be one of Stack, Mesh or Global. If not Global, only processes of the same type can be called. If not specify, the default is Global.

processFolder

Folder in which the process will be seen. If not specified, the default is Python.

parmsDescs

Dictionnary giving, for each named parameter, a description. It will appear in the online parameter help.

parmsChoice

Dictionnary giving, for each named parameter, a list of choices to display as drop-down list.

processIcon

String with the path to the icon of the process. The path can be relative to the module path.

5.2.2. Parameter Handling

LithoGraphX provides three options to manage parameters, which you can choose by setting the parmsHandling module variable:

smart
This is the default. In this mode, parameters will be converted to the Python object closest to the C++ object. In practice, any argument provided directly by the user will be a string, but if another process provide a number, it will be a number. Any other type will still be a QVariant.
string only
In this mode, all arguments are always converted to string.
qvariant
In this mode, your Python process received the QVariant directly, like in C++.

5.2.2.1. Example Macro

Here is a simple example macro, calling a number of times the blur process:

# This first line is for modules to work with Python 2 or 3
from __future__ import print_function, division
# This is to access the Stack processes
from lgxPy import Stack
# This is to provide a user interface: note that for windows, LithoGraphX
# provides its own version of PyQt5
from PyQt5 import QtWidgets

processType = "Stack"
processName = "Repeat Blur"
processFolder = "Filters"
parmsChoice = dict(repeat=[1, 2, 3, 4, 5, 6, 7, 8, 9])
processIcon = ":/images/Blur.png" # we are re-using icons in the Qt resources
parmsDescs = dict(printed="Number of repetition of the blur")

def initialize(X, Y, Z, repeat, parent):
    repeat, ok = QtWidgets.QInputDialog.getInt(parent, "Number of repeats", "N = ", int(repeat), 0, 10)
    if not ok:
        return False
    return X, Y, Z, repeat

def run(X=.3, Y=.3, Z=.3, repeat=1):
    for i in range(int(repeat)):
        Stack.Gaussian_Blur_Stack(X, Y, Z)

Simply copy and paste this example in a file with a py extension and copy it to the user macro folder. The simplest way to access this folder is from the Macros menu in LithoGraphX. After that, select the Reload Macros entry in the same menu.

Hint

As LithoGraphX may be compiled with Python 2.7 or Pythong 3.4 or later, I recommend you use the __future__ module.