One of the most powerful features of TouchDesigner for developing projects is the thorough integration of Python within the program. Almost anything you can think of within the program has an associated class, member, and/or method, allow for the development of basically whatever complex project functionality you can dream up.
A couple of years ago, we posted a TouchDesigner Python Cheat Sheet for Developers, which, while comprehensive, was by no means complete! In this post, we’ve put together another Python and TouchDesigner cheat sheet, this time aimed at the intermediate level developer who has moved beyond CHOP references into scripting.
td Module
See: td Module page in the TouchDesigner Documentation
You’re probably familiar with a lot of the td Module’s functionality without even realizing it! The td module contains all TouchDesigner related Python classes and utilities, and is automatically imported. It contains commonly used members like me
, op
, parent
and absTime
. There are a number of useful functions that can be helpful as you’re developing projects, including debugging tools, accessing monitor info, project info, and more.
Python Expression | Description | Example |
debug(*args) | Print all args and extra debug info (default is DAT and line number) to texport. TIP: Use debug instead of print when debugging Python scripts in order to see object types and the source of the output. | a = op('noise1')[0] |
monitors | Reference to the group of available monitors. The Monitors class has a number of useful members accessible for each monitor, including which monitor is primary , width , height , and left /right /top /bottom positions of the combined monitor area. | len(monitors) # number of monitors |
opex | An operator finder object, for accessing operators through paths or shortcuts. Works like the op() shortcut method, except it will raise an exception if it fails to find the node instead of returning None as op() does. This is now the recommended way to get nodes in parameter expressions. | opex('geo1') # returns geo1 operator # If no operator with the specified name/pattern is found, you'll receive an error that is more specific/clear than you would with op(). Here's an example: Traceback (most recent call last): |
project | Reference to the project session. The Project class includes a number of useful members, including name, folder, saveBuild, saveOSName, and more. | project.name # returns the filename under which the project is saved |
tdu Module, Continued
See: tdu Module page in the TouchDesigner Documentation
In the last post, we looked at some of the TDU Module’s functionality, including random value generation, clamping values, and more. There’s still more to the TDU Module! This time around, we’ve included some useful functions that give you access to TouchDesigner’s very useful pattern matching and pattern expansion, along with other string-related processing tools.
Python Expression | Description | Example |
tdu.base(str) | Returns the beginning portion of the string occurring before any digits. The search begins after the last slash if any are present. | tdu.base('arm123') # returns 'arm' |
tdu.digits(str) | Returns the numeric value of the last consecutive group of digits in the string, or None if not found. The search begins after the last slash if any are present. The digits do not necessarily need to be at the end of the string. | tdu.digits('arm123') # returns 123 |
tdu.expand(pattern) | Return a list of the expanded items, following the rules of Pattern Expansion. | tdu.expand('A[1-3] B[xyz]') # return ['A1', 'A2', 'A3', 'Bx', 'By', 'Bz'] |
tdu.match(pattern, inputList, caseSensitive=True) | Return a subset of inputList, in which each element matches the pattern. Wildcards are supported. | tdu.match('foo*', ['foo', 'bar']) # return ['foo'] |
tdu.split(string, eval=False) | Return a list from a space separated string, allowing quote delimiters. – string – Any Python object, as it will be evaluated as str(string). Parameters will work. – eval (Keyword, Optional) – If True convert any valid Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None. | split('1 2.3 None fred "one \'2\'" "[1,2]"') #yields ['1', '2.3', 'None', 'fred', "one '2'", '[1, 2]'] split('1 2.3 None fred "one \'2\'" "[1,2]"', True) #yields [1, 2.3, None, 'fred', "one '2'", [1, 2]] |
Get Our 7 Core TouchDesigner Templates, FREE
We’re making our 7 core project file templates available – for free.
These templates shed light into the most useful and sometimes obtuse features of TouchDesigner.
They’re designed to be immediately applicable for the complete TouchDesigner beginner, while also providing inspiration for the advanced user.
Python Storage
See: Storage page and Storage section of OP Class page in TouchDesigner Docs.
As you progress with Python in TouchDesigner, you’re likely to run into situations where you need to store some form of data. Whether that’s presets, locations of assets, or the current state of portions of your project, storage is the preferred way to work with persistent global data in Python, since it can store any data type.
Python Expression | Description | Example |
---|---|---|
store(key, value) | Setting a value in storage of a component n | n = op('pattern1') n.store('level', 0.5) |
fetch(key, default, search=True, storeDefault=False) | Getting a value from storage – key – The name of the entry to retrieve.– default – (Optional) If provided and no item is found then the passed value/object is returned instead.– storeDefault – (Keyword, Optional) If True, and the key is not found, the default is stored as well.– search – (Keyword, Optional) If True, the parent of each OP is searched recursively until a match is found | n.fetch('level') # returns 0.5 |
storage | Directly access the storage dictionary | n.storage # returns {'level': 0.5} |
storage['keyname'] | Directly access a key in the storage dictionary | n.storage['level'] # returns 0.5 |
'keyname' in storage | Test if a key exists in the storage dictionary | 'level' in n.storage # returns True |
unstore(keys1, keys2..) | For key, remove it from the OP’s storage dictionary. Pattern Matching is supported as well. | n.unstore('level') # removes entry from this OP's storage for the key 'level' |
DATs, Continued
See: DAT Class in TouchDesigner Docs
We looked at working with Python and DATs last time, but this was mainly focused on table-based operations. As DATs are going to be the place where you write most of your Python scripts, we’ve chosen a text-based focus for this post, showcasing members/methods used for editing text, parsing content as JSON, saving text to file, and more. We’ve also included a few additional methods for table manipulation that are sure to come in handy!
Python Expression | Description | Example |
op(‘datName’).text | Get or set contents. Tables are treated as tab delimited columns, newline delimited rows. | op('text1').text = 'Hello world' # sets text1 DAT's contents to 'Hello world' |
op(‘datName’).jsonObject | Parses the DAT as JSON and returns a Python object | print(op('text3').jsonObject) # returns {'store': {'book': [{'category': 'reference', 'author': 'Nigel Rees', 'title': 'Sayings of the Century', 'price': 8.95}, {'category': 'fiction', 'author': 'Herman Melville', 'title': 'Moby Dick', 'isbn': '0-553-21311-3', 'price': 9.99}, {'category': 'fiction', 'author': 'J.R.R. Tolkien', 'title': 'The Lord of the Rings', 'isbn': '0-395-19395-8', 'price': 22.99}]}} |
op('datName').run(arg1, arg2..., endFrame=False, fromOP=None, asParameter=False, group=None, delayFrames=0, delayMilliSeconds=0, delayRef=me) | Run the contents of the DAT as a script, returning a Run object which can be used to optionally modify its execution. See DAT Class Methods page for full description of each argument. | op('text1').run() # runs contents of text1 DAT as a Python script |
op('datName').save(filepath, append=False, createFolders=False) | Saves the content of the DAT to the file system. Returns the file path that it was saved to. – filepath – (Optional) The path and filename to save the file to. If this is not given then a default named file will be saved to project.folder– append – (Keyword, Optional) If set to True and the format is txt, then the contents are appended to the existing file.– createFolders – (Keyword, Optional) If True, it creates the not existent directories provided by the filepath. | op('text1').save() # saves in native format with default name |
op('datName').deleteRow(nameOrIndex) | Delete a single row at specified name or index | op('table1').deleteRow(4) # deletes row at index 4 |
op('datName').deleteCol(nameOrIndex) | Delete a single column at specified name or index | op('table1').deleteCol('tx') # deletes column with name tx |
op('datName').row(*nameOrIndexes, caseSensitive=True, val=False) | Returns a list of cells from the first row matching the name/index, or None if nothing is found. – nameOrIndexes – Include any number of these. If a string it specifies a row name, if it’s numeric it specifies a row index. Pattern Matching is supported. – caseSensitive – (Optional) Specifies whether or not case sensitivity is used. – val – (Optional) If set to true, returns list of cell item strings instead of list of Cell Class items. | op('table1').row(0) # returns [type:Cell cell:(0, 0) owner:/project1/table1 value:tx, type:Cell cell:(0, 1) owner:/project1/table1 value:ty, type:Cell cell:(0, 2) owner:/project1/table1 value:tz] |
op('datName').col(*nameOrIndexes, caseSensitive=True, val=False) | Returns a list of cells from the first column matching the name/index, or None if nothing is found. See above .row() listing for a description of arguments | op('table1').col(1) # returns [type:Cell cell:(0, 1) owner:/project1/table1 value:ty, type:Cell cell:(1, 1) owner:/project1/table1 value:-2, type:Cell cell:(2, 1) owner:/project1/table1 value:-0.5] |
As in the previous article, the above information is adapted from the Derivative wiki for TouchDesigner, which is an indispensable tool for wrapping your head around the Python members and methods that the software offers. If you’re interested in diving deeper into Python in TouchDesigner, it’s well worth checking out the following wiki articles:
- Introduction to Python Tutorial
- Python Tips
- Working with OPs in Python
- Category:Python Reference
- Python Classes and Modules
- tdu Module
Wrap-Up
Once again, I hope that this post has given you a look at how neatly integrated Python is within the TouchDesigner environment, and provides you with a useful resource for some of the common Python members and methods that you’ll use as you develop projects in TouchDesigner. Happy programming!