************************* Python Macros and Scripts ************************* .. highlight:: python 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. 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. 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. .. toctree:: lgxPy 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++. 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.