Tag Archives: Python

TouchDesigner | Delay Scripts

It’s hard to appreciate some of the stranger complexities of working in a programming environment until you stumble on something good and strange. Strange how Matt? What a lovely question, and I’m so glad that you asked!

Time is a strange animal – our relationship to it is often changed by how we perceive the future or the past, and our experience of the now is often clouded by what we’re expecting to need to do soon or reflections of what we did some time ago. Those same ideas find their way into how we program machines, or expect operations to happen – I need some-something to happen at some time in the future. Well, that’s simple enough on the face of it, but how do we think about that when we’re programming?

Typically we start to consider this through operations that involve some form of delay. I might issue the command for an operation now, but I want the environment to wait some fixed period of time before executing those instructions. In Python we have a lovely option for using the time module to perform an operation called sleep – this seems like a lovely choice, but in fact you’ll be oh so sorry if you try this approach:

But whyyyyyyyy?!

Well, Python is blocking inside of TouchDesigner. This means that all of the Python code needs to execute before you can proceed to the next frame. So what does that mean? Well, copy and paste the code above into a text DAT and run this script.


If you keep an eye on the timeline at the bottom of the screen, you should see it pause for 1 second while the time.sleep() operation happens, then we print “oh, hello there” to the text port and we start back up again. In practice this will seem like Touch has frozen, and you’ll soon be cursing yourself for thinking that such a thing would be so easy.

So, if that doesn’t work… what does? Is there any way to delay operations in Python? What do we do?!

Well, as luck would have it there’s a lovely method called run() in the td module. That’s lovely and all, but it’s a little strange to understand how to use this method. There’s lots of interesting nuance to this method, but for now let’s just get a handle on how to use it – both from a simple standpoint, and with more complex configurations.

To get started let’s examine the same idea that we saw above. Instead of using time.sleep() we can instead use run() with an argument called delayFrames. The same operation that we looked at above, but run in a non-blocking way would look like this:

If you try copying and pasting the code above into a text DAT you should have much better results – or at least results where TouchDesigner doesn’t stop running while it waits for the Python bits to finish.

Okay… so that sure is swell and all, so what’s so complicated? Well, let’s suppose you want to pass some arguments into that script – in fact we’ll see in a moment that we sometimes have to pass arguments into that script. First things first – how does that work?

Notice how when we wrote our string we used args[some_index_value] to indicate how to use an argument. That’s great, right? I know… but why do we need that exactly? Well, as it turns out there are some interesting things to consider about running scripts. Let’s think about a situation where we have a constant CHOP whose parameter value0 we want to change each time in a for loop. How do we do that? We need to pass a new value into our script each time it runs. Let’s try something like:

What you should see is that your constant CHOP increments every second:


But that’s just the tip of the iceberg. We can run strings, whole DATs, even the contents of a table cell.

This approach isn’t great for everything… in fact, I’m always hesitant to use delay scripts too heavily – but sometimes they’re just what you need, and for that very reason they’re worth understanding.

If you’ve gotten this far and are wondering why on earth this is worth writing about – check out this post on the forum: Replicator set custom parms error. It’s a pretty solid example of how and why it’s worth having a better understanding of how delay scripts work, and how you can make them better work for you.

Happy Programming.


TouchDesigner | Finding Dominant Color

Programming is a strange practice. It’s not uncommon that in order to make what’s really interesting, or what you promised the client, or what’s driving a part of your project you have to build another tool.

You want to detect motion, so you need to build out a means of comparing frames, and then determining where the most change has occurred. You want to make visuals that react to audio, but first you need to build out the process for finding meaningful patterns in the audio. And on and on and on.

And so it goes that I’ve been thinking about finding dominant color in an image. There are lots of ways to do this, and one approach is to use a technique called KMeans clustering. This approach isn’t without its faults, but it is interesting and relatively straightforward to implement. The catch is that it’s not fast enough for a realtime application – at least not if you’re using Python. So what can we do? Well, we can still use KMeans clustering, but we need to understand how to use multi-threading in python so we don’t block our main thread in TouchDesigner.

The project / tool / example below does just that – it’s a mechanism for finding dominant color in an image with an approach that uses a background thread for processing that request.

TouchDesigner Dominant Color

An approach for finding dominant color in an image using KMeans clustering with scikit learn and openCV. The approach here is built for realtime applications using TouchDesigner and python multi-threading.

TouchDesigner Version

Build 2018.22800

Python Dependencies

  • numpy
  • scipy
  • sklearn
  • cv2



A tool for finding Dominant Color with openCV.

Here we find an attempt at locating dominant colors from a source image with openCV and KMeans clustering. The large idea is to sample colors from a source image build averages from clustered samples and return a best estimation of dominant color. While this works well, it’s not perfect, and in this class you’ll find a number of helper methods to resolve some of the shortcomings of this process.

Procedurally, you’ll find that that the process starts by saving out a small resolution version of the sampled file. This is then hadned over to openCV for some preliminary analysis before being again handed over to sklearn (sci-kit learn) for the KMeans portion of the process. While there is a built-in function for KMeans sorting in openCV the sklearn method is a little less cumbersome and has better reference documentation for building functionality. After the clustering process each resulting sample is processed to find its luminance. Luminance values outside of the set bounds are discarded before assembling a final array of pixel values to be used.

It’s worth noting that this method relies on a number of additional python libraries. These can all be pip installed, and the recommended build approach here would be to use Python35. In the developer’s experience this produces the least number of errors and issues – and boy did the developer stumble along the way here.

Other considerations you’ll find below are that this extension supports a multi-threaded approach to finding results.


Dominant Color

  • Image Process Status – (string) The thread process status.
  • Temp Image Cache – (folder) A directory location for a temp image file.
  • Source Image – (TouchDesigner TOP) A TOP (still) used for color analysis.
  • Clusters – (int) The number of requested clusters.
  • Luminance Bounds – (int, tuple) Luminance bounds, mine and max expressed as value between 0 and 1.
  • Clusters within Bounds – (int) The number of clusters within the Luminance Bounds.
  • Smooth Ramp – (toggle) Texture interpolation on output image.
  • Ramp Width – (int) Number of pixels in the output Ramp.
  • Output Image – (menu) A drop-down menu for selecting a ramp or only the returned clusters.
  • Find Colors – (pulse) Issues the command to find dominant colors.


  • Python Externals – (path) A path to the directory with python external libraries.
  • Check Imports – (pulse) A pulse button to check if sklearn was correctly imported.

Using this Module

To use this module there are a few essential elements to keep in mind.

Getting Python in Order

If you haven’t worked with external Python Libraries inside of Touch yet, please take a moment to familiarize yourself with the process. You can read more about it on the Derivative Wiki – Importing Modules

Before you can run this module you’ll need to ensure that your Python environment is correctly set-up. I’d recommend that you install Python 3.5+ as that matches the Python installation in Touch. In building out this tool I ran into some wobbly pieces that largely centered around installing sklearn using Python 3.6 – so take it from someone whose already ran into some issues, you’ll encounter the fewest challenges / configuration issues if you start there. Sklearn (the primary external library used by this module) requires both scipy and numpy – if you have pip installed the process is straightforward. From a command prompt you can run each of these commands consecutively:

pip install numpy
pip install scipy
pip install sklearn

Once you’ve installed the libraries above, you can confirm that they’re available in python by invoking python in your command prompt, and then importing the libraries one by one. Testing to make sure you’ve correctly installed your libraries in a Python only environment first, will help ensure that any debugging you need to do in TouchDesigner is more straightforward.


Working with TouchDesigner

Python | Importing Modules

If you haven’t imported external libraries in TouchDesigner before there’s an additional step you’ll need to take care of – adding your external site-packages path to TouchDesigner. You can do this with a regular text DAT and by modifying the example below:

import sys
mypath = "C:/Python35/Lib/site-packages/mymodule"
if mypath not in sys.path:

Copy and paste the above into your text DAT, and modify mypath to be a string that points do your Python externals site-packages directory.


If that sounds a little out of your depth, you can use a helper feature on the Dominant Color module. On the Python page, navigate to your Python Externals directory. It should likely be a path like: C:\Program Files\Python35\Lib\site-packages

Your path may be different, especially if when you installed Python you didn’t use the checkbox to install for all users. After navigating to your externals directory, pulse the Check imports parameter. If you don’t see a pop-up window then sklearnwas successfully imported. If you do see a pop-up window then something is not quite right, and you’ll need to do a bit of leg-work to get your Python pieces in order before you can use the module.

Using the Dominant Color

With all of your Python elements in order, you’re ready to start using this module.


The process for finding dominant color uses a KMeans clustering algorithm for grouping similar values. Luckily we don’t need to know all of the statistics that goes into that mechanism in order to take full advantage of the approach, but it is important to know that we need to be mindful a few elements. For this to work efficiently, we’ll need to save our image out to an external file. For this to work you need to make sure that this module has a cache for saving temporary images. The process will verify that the directory you’ve pointed it to exists before saving out a file, and will create a directory if one doesn’t yet exist. That’s mostly sanity checking to ensure that you don’t have to loose time trying to figure out why your file isn’t saving.

Give that this process happens in another thread, it’s also important to consider that this functions based on a still image, not on a moving one. While it would be slick to have a fast operation for finding KMeans clusters in video, that’s not what this tool does. Instead the assumption here is that you’re using a single frame of reference content, not video. You point this module to a target source, by dropping a TOP onto the Source Image parameter.

Next you’ll need to define the number of clusters you want to look for. Here the term clusters is akin to what’s the target number of dominant colors you’re looking to find – the top 3, the top 10, the top 20? It’s up to you, but keep in mind that more clusters takes longer to produce a result. You’re also likely to want to bound your results with some luminance measure – for example, you probably don’t want colors that are too dark, or too light. The luminance bounds parameters are for luminance measures that are normalized as 0 to 1. Clusters within bounds, then, tells you how many clusters were returned from the process that fell within your specified regions. This is, essentially, a way to know how many swatches work within the brightness ranges you’ve set.

The output ramp from this process can be interpolated and smooth, or Nearest Pixel swatches. You can also choose to output a ramp that’s any length. You might, for example, want a gradient that’s spread over 100 or 1000 pixels rather than just the discrete samples. You can set the number of output pixels with the ramp width parameter.

On the otherside of that equation, you might just want only the samples that came out of the process. In the Output Image parameter, if you choose clusters from the drop down menu you’ll get only the valid samples that fell within your specified luminance bounds.

Finally, to run the operation pulse Find Colors. As an operational note, this process would normally block / lock-up TouchDesigner. To avoid that unsavory circumstance, this module runs the KMeans clustering process in another thread. It’s slightly slower than if it ran in the main thread, but the benefit is that Touch will continue running. You’ll notice that Image Process Status parameter displays Processing while the separate thread is running. Once the result has been returned you’ll Ready displayed in the parameter.


Notes from Other Programmers

I don’t use CONDA, but for those of you that do, you can install sklearn with the following command:
conda install scikit-learn

TouchDesigner | Multi-Threading

Multi-threading is no easy task to wrap your head around, and there are plenty of pit-falls when it comes to using it in in Touch. Below we have three simple examples of seeing how that works. It’s not the most thrilling topic in the world, until it’s something that you need – desperately – then it might just save your project.

You can grab the whole repo here: touchdesigner-multi-threading

Three Examples

A simple example of creating a function that runs in another thread. As noted in the forum reference post it’s important to consider what operations can potentially create race conditions in Touch. The suggested consideration here is to avoid the use of any operations that will interact with a touch Object. Looking more closely at this example we can see here that we’re using only Pythonic approaches to editing an external file. In our first example we use a simple text file approach to ensure that we have the simplest possible exploration of a concept.

In the opeCV example we look at how one might consider taking the approach of working with image processing through the openCV library. While this example only creates a random red circle, with a little imagination we might see how this would be useful for doing an external image processing pass – finding image features, identifying colors, etc. Running this as a for loop makes it easy to see how this process can block TouchDesigner’s main thread, and why it would be useful to have a means of executing this function in a way that minimizes impact on the running project.

While the example pyThreads_opneCV is an excellent start, that doesn’t help us if we need to know when an outside operation has completed. The use of Queue helps resolve this issue. A Queue object can be placed into storage and act as an interchange between threads. It’s marked as a thread safe operation, and in our case is used to help track when we’re working function is “Processing” or “Ready”. You’ll notice that the complications here are that we have a less than ideal need to use an execute DAT to run a frame start script to check for our completed status each frame. This is less than ideal but a reasonable solution for an otherwise blocking operation. Notice that the execute DAT will disable the operation of the frame start script after it’s “Ready”. This kind of approach helps to ensure that the execute DAT only runs the frame start script when necessary and not every frame.

Forum Example

Forum Example 1 python_threading_sample.toe

An example from the forum used to sort out the essential pieces of working with multiple threads, queues, and how to approach this issue without crashing Touch. Many thanks to the original authors for their work helping to shed some light on this murkey part of working in TouchDesigner.

presets and cue building | TouchDesigner 099

I’ve been thinking about state machines and cuing systems lately. Specifically, that there aren’t many good resources that I’ve found so far that talk new artist programmers through how to think about or wrestle with these ideas. Like many Touch programmers I’ve tried lots of different ways of thinking about this problem, and just today I saw someone post on the Facebook help group.

from the facebook help group:

Hi, i’m working arround Matthews AME394 Simple VJ-Setup Tutorial. No Questions, but how can i do nearly the same with different blending times between the moduls. I tried a lot with getting different values out of a table DAT into the length parameter of a timerCHOP. But cannot figur out the right steps to get my goal. Any helps? this i need in a theater situation with different scenes to blend one after another with scenebuttons or only one button and a countCHOP or something else.

This challenge is so very familiar, and while there are lots of ways to solve this problem sometimes the hardest part is having an idea of where to start.  Today what I want to look at is just that – where do we start? This isn’t the best solution, or the only solution – it’s just a starting point solution. It’s a pass at the most basic parts of this equation to help us get started in thinking about what the real problems are, how we want to tackle them, and how we can go about exposes the real issues we need to solve for.

So where do we start? In this simple little state machine we’re going to start with a table full of states. For the sake of simplicity I’m going to keep this as simple as possible… though it might well uncover the more interesting and more challenging pieces that lie ahead.

I’m going to start with the idea that I’ve got a piece of content (an image or a movie) that I want to play. I want to apply some post process effects (in this case just black level and image inversion changes), and I want to have different transition times between these fixed states. Here the only transition I’m worrying about is one that goes from one chain of operations to another. I’m also going to stick with images for now.

So what do we need in our network to get started?!

We’re going to borrow from an idea that often gets used in these kinds of challenges, and we’re going to think of this as operating with two decks – an A deck, and a B deck. Our deck is essentially a chain of operators that allow for all of the possibilities that we might want to explore in our application. In this case I’m only working with a level TOP, but you can imagine that we might use all sorts of operations to make for interesting composition choices.

Alright, so we’re going to lay out a quick easy deck:

moviefilein > level > fit 


Next we’re going to repeat this whole chain, then connect both of our fit TOPs to a cross TOP:


If you’re scratching your head at this fit TOP in line, that’s okay. For us, the fit TOP is going to act as our safety. This makes sure that no matter what the resolution of the incoming file might be, that we always make sure that both decks have matching proportions. We’d probably want a little more thought in how this would work for an event or a show, but for now this is enough to help ensure that don’t experience any unexpected resolution shifts during our transitions.

Next we’re going to add a simple tweening system to our network to control how we blend between states. In this case I’m going to use a constant, a speed, and a null. I need to make sure that my speed is set to clamp, and that my min and max values are 0 and 1 respectively. Right now I only have two different decks, so I don’t want to go any higher that 1 or any lower than 0.

Now we’re cooking with propane! So where do we go next?

some simple cues

movie_file trans_time blk_lvl invert
Banana.tif 1 0 0
Butterfly1.tif 2 0.12 1
Butterfly5.tif 5 0.2 0
Mettler.2.jpg 10 0.05 0
OilDrums.jpg 0.5 0.25 1
Starfish.tif 1 0 1

In this simple examination of this challenge I’m going to use a table to store our cues. In a larger system I’d probably use python storage (which is really a dictionary), but for the sake of keeping it simple let’s start with just a table. Our simple cues are organized above, and we can put all of those values into a table DAT. You’ll notice that for now I’m only worrying about file name and not path – all of these files come from the same directory so we can treat them mostly the same way. We’ll also notice that I’m thinking of my transition times in terms of seconds. All of this can, of course, be much more complicated. The trick is to sort out a very simple example first to identify pressure points and challenges before you dig yourself into a hole.

Okay, let’s add a table DAT to our network and copy all over our cues over.


Now that we have all of our pieces organized it is time to think through the logic of how we make this all work. For now let’s use a button, a count CHOP, and a CHOP Execute DAT. We need to make sure our button is set to be momentary, and we also need to make sure our count CHOP is set to loop – starting at 1 and ending at 6. That matches our row indices from our table DAT.


This is great Matt, but why python?

Well, we could do a lot of this with a complex set of CHOPs and selects but these kinds of states tend to be better handled, logically at least, through written code. Python will let us explicitly describe exactly what happens, and in what order those things happen. That’s no small thing, and while it might be a little rocky to wrap your head around using Python in Touch at first, it’s well worth it in the end. So what do we write in our CHOP Execute?

a little bit of logic | python

Uhhhhhhh… wait. What?

Okay. First off we just define a set of variables that we’re going to use. This makes our code a little easier to write, and easier to read. Next all of the action really happens in our onValueChange function.

We’re going to do all of this in a little logical if statement. If this thing, do that thing… in all the other cases, do something else.

First we check to see what our deck position is… which means that we check to see which output we’re currently seeing more of. If our cross TOP’s index is greater that 0.5 we know that we’re closer to 1, which also means we’re seeing more of deck B than deck A. That means that we want to make changes in deck A before we start transitioning. First we change our file, change all of our settings, then finally set a value in our constant CHOP. But why 1 / that value? And why multiplied by -1?

A default network runs at 60 fps. A speed CHOP fed by a constant with a value of 1 will rise a count of 1 over 60 frames. Said another way, an input value of 1 to our speed in a default network will increase by a count of one every second. If we divide that number in half we go twice as slow. A value of 0.5 will increase by a count of 1 every 2 seconds. 1 / our table value will let us think in seconds rather than in fractions while we’re writing our cues. Yeah, but what about being multiplied by -1?! Well, if we want to get back to the 0 index in our cross TOP we need a negative value feeding our speed CHOP. Multiplying by -1 here means that we don’t need to think about the order of cues in our table DAT, and instead our bits of Python will keep us on the rails. Our else statement does all of the same things, but to our B deck. It also uses a positive value to feed our speed CHOP – since we need an increasing value.

There you have it, a simple cuing system.

simple cues.gif

This is great Matt, but what if I want to tween settings on that level TOP? Or any other set of complicated things?! Well, I’d be that at this point you’ve got enough to get you started. You might use a column to indicate if you’re transitioning to a totally new cue or just to new values in the same source image. You could also choose to put your parameter values in CHOPs instead so you could manipulate them with other CHOPs before exporting them to your decks.

What if I don’t want linear transitions?! A speed is just a linear ramp! That’s okay. You might choose to use a lookup CHOP and a more complicated curve. You could even make several types of curves with animation COMPs and switch between them. Or you could use a lag  CHOP to change your attack and release slopes. Or you could use a trigger CHOP, or a fileter CHOP. There are lots of ways to shape curves with math, now it’s up to you to figure out exactly what you’re after.

Happy programming!

pull it apart

Pull apart the example in 088
Pull apart the example in 099

textport for performance | TouchDesiger


I love a good challenge, and today on the TouchDesigner slack channel there was an interesting question about how you might go about getting the contents of the textport into a texture to display. That’s a great question, and I can imagine a circumstance where that might be a fun and interesting addition to a set. Sadly, I have no idea about how you might make that happen. I looked through the wiki a bit to see if there were any leads, and it’s difficult to see if there’s actually a good way to grab the contents of the textport.

What do we do then?!

Well, it just so happens that this might be another great place to look at how to take advantage of using extensions in TouchDesigner. Here our extension is going to do some double duty for us. The big picture idea is that we’ll want to be able to use a single call to either display a string, or print and display a string. If you only wanted to print it you could just use print(), so we’ll leave that one out of the mix for now.

Let’s take a look at the extension and then pull apart what’s happening in side.

Okay, so what exactly are we doing here?!

The big picture is that we want a way to be able to log something to a text  object that can be displayed. In this case I choose a table DAT. The reasoning here is that a table DAT before being converted to just a text DAT allows us to do some simple clean up and line adjustments. Each new entry is posted in a row – which makes for an easy way to limit the number of displayed rows. We can do this with a select DAT – which is where we use our StartRow and EndRow members.

Why exactly do we use these? Well, this helps ensure that we can keep our newest row displayed. A text TOP can accept a text DAT of any length, but at some point the text will spill off the bottom – unless you use adaptive sizing. The catch there is that at some point the text will become impossible to read. A top and bottom boundary ensures that we can always have something portion of our text displayed. We use a simple logical test in our Display() method to see if we’ve hit that boundary yet, and if we have we can update our members plus one… moving them both along at the same time.

You may also notice that we have a separate method to display and print… why not just do this in a single method. Well, that’s a great question. We could just use a single method for this with another argument. That’s probably a better way to tackle this challenge, but I wanted to use this opportunity to show how we might call another method from within our class. This can be helpful in a number of different situations, and while this application is a little too simple to really take advantage of that technique, it gives you a peak into how it might work.

Want to download the tox and take it for a test drive? You can find the source code here.

scriptDAT | Tips and Tricks | TouchDesigner

If you spend lots of time setting up parameters in your UI elements and want a faster way to use a set of presets to populate some parameters, then the Script DAT might be just what you’re looking for.

Let’s look at a fast simple example that might have you re-thinking how to quickly set up pars in a project. Keep in mind that this won’t work in every situation, but it might work for an awful lot of them and in ways that you might not have expected.

To get started let us imagine that we have a simple set-up where we have a UI element and a display element. We want a fast way to quickly update their parameters. For the sake of this example let’s imagine that we do not need any fancy scaling or changes on the fly. This is going to be used on a set of displays where we know exactly how they’re going to display. We might think about using storage to set and pull parameters, but you might be hesitant to use too much python for those bits and bobs. Okay, so exports it is… they’re a little more cumbersome to set up, but they are much faster – fine.


I guess we need to start setting up an export table, or a constant CHOP and dragging and dropping all over creation. Before you do that though, take a closer look that is the majesty of the Script DAT:

The Script DAT runs a script each time the DAT cooks and can build/modify the output table based in the optional input tables. The Script DAT is created with a docked (attached) DAT that contains three Python methods: cook, onPulse, and setupParameters. The cook method is run each time the Script DAT cooks. The setupParameters method is run whenever the Setup Parameter button on the Script page is pressed. The onPulse method is run whenever a custom pulse parameter is pushed.

Maybe we can use the Script DAT to make an export table for us with just a little bit of python.

We can start by putting a few things into storage. Let’s create a new dictionary but follow some simple rules:

  • The keys in this dictionary are going to be operator names or paths
  • Each operator is itself a key for another dictionary
  • The keys of that dictionary must be proper parameter names
  • The values associated with these keys need to be legal entries for parameters

Okay, with these rules in mind let’s see what we can do. Open up a new project, in project1 let’s create two new containers:

  • container_ui
  • continer_led_display

Add a new text DAT and create a simple dictionary to put into storage, and let’s follow the rules we described above:

Alright, so far so good. Now let’s add a Script DAT.

We’re going to use our Script DAT to look at our stored vals and create an export table on the fly for whatever is in the storage dictionary “attr” – easy.

Let’s edit our Script DAT to have the following contents:

Finally, let’s turn on the green export flag at the bottom of our Script DAT:


And just like that we’ve set-up an auto-export system. Now every time we update our dictionary run our script to put the contents into storage we’ll automatically push those changes to an export table.

Looking for an example to pull apart – head over to github and download a simple example to look over.

Python in TouchDesigner | Extensions | TouchDesigner

Rounding out some of our work here with Python is to look extensions. If you’ve been following along with other posts you’ve probably already looked over some extensions in this post. If you’re brand new to this idea, check out that example first.

Rather than re-inventing the wheel and setting up a completely new example, let’s instead look at our previous example of making a logger and see how that would be different with extensions as compared to a module on demand.

A warning for those following along at home, we’re now knee deep in Python territory, so what’ we’ll find here is less specific to TouchDesigner and more of a look at using Classes in Python.

In our previous example looking at modules we wrote several functions that we left in a text DAT. We used the mod class in TouchDesigner to treat this text DAT as a python module. That’s a neat trick, and for some applications and situations this might be the right approach to take for a given problem. If we’re working on a stand alone component that we want to use and re-use with a minimal amount of additional effort, then extensions might be a great solution for us to consider.

Wait, what are extensions?! Extensions are way that we can extend a custom component that we make in TouchDesigner. This largely makes several scripting processes much simpler and allows us to treat a component more like an autonomous object rather than a complex set of dependent objects. If you find yourself re-reading that last statement let’s take a moment to see if we can find an analogy to help understand this abstract concept.

When we talked about for loops we used a simple analogy about washing dishes. In that example we didn’t bother to really think deeply about the process of washing dishes – we didn’t think about how much detergent, how much water, water temperature, washing method, et cetera. If we were to approach this problem more programatically we’d probably consider making a whole class to deal with the process of washing dishes:

Okay, so the above seems awfully silly… what’s going on here? In our silly example we can see that rather than one long function for Wash() or Dry(), we instead use several smaller helper functions in the process. Why do this? Well, for one thing it lets you debug your code much more easily. It also means that by separating out some of these elements into different processes we can fix a single part of our pipeline without having to do a complete refactor of the entire Wash() or Dry() methods. Why does that matter? Well, what if we decide that there’s a better way to determine how much soap to use. Rather than having to sort through a single long complex method for Wash() we can instead just look at Set_soap(). It makes unit testing easier, and allows us to replace or develop that method outside the context of the larger method. It also means that if we’re collaborating with other programmers we can divide up the process of writing methods.

What’s this self. business? self. allows us to call a method from inside another method in the same class. This is where extensions begin to really shine as opposed to using modules on demand. We an also use things like attributes andinheritance.

Okay, so how can we think about actually using this?

Let’s take a look at what this approach looks like in python:

So getting started we set up a couple of variables that we were going to reuse several times. Next we declared our class, and then nested our methods inside of that class. You’ll notice that different from methods, we need to include the argument self in our method definitions:

# syntax for just a function
def Clear_log():

# syntax for just a method in a class
def Clear_log( self ):

We can also see how we’ve got several helper functions here to get us up and running – ways to add to the log, save the log to an external file, a way to clear the log. We can imagine in the future we might want to add another method that both clears the log, and saves an empty file, like a reset. Since we’ve already broken those functions into their own methods we could simply add this method like this:

def Reset_log():

Now it’s time to experiment.

Over the course of this series we’ve looked at lots of fundamental pieces of working with Python in TouchDesigner. Now it’s your turn to start playing and experimenting.

Happy programming!

Python in TouchDesigner | Modules | TouchDesigner

There are a number of ways that we might use modules on demand in TouchDesigner. Before we get too far along, however, we might first ask “what is a module on demand?”

According to the TouchDesigner wiki:

The MOD class provides access to Module On Demand object, 
which allows DATs to be dynamically imported as modules. 
It can be accessed with the mod object, found in the automatically 
imported td module. 

Alternatively, one can use the regular python statement: import. 
Use of the import statement is limited to modules in the search path, 
where as the mod format allows complete statements in one line, 
which is more useful for entering expressions. Also note that DAT modules 
cannot be organized into packages as regular file system based 
python modules can be.

What does this mean? It’s hard to sum up in just a single sentence, but the big thing to take away is that we can essentially use any text DAT to hold whole functions for us that we can then call whenever we want.

Let’s take a closer look at this process. We’ll start with some simple ideas, then work our way up to something a little more complicated.

First we turn things way down, and just think about storing variables. To be clear, we probably wouldn’t use this in a project, but it can be helpful for us when we’re trying to understand what exactly is going on here.

Let’s create a new text DAT and call it “text_variables”, inside let’s put the following text:

width       = 1280
height      = 720

budget      = 'small'

Using the mod class we can access these variables in other operators! To do this we’ll use the following syntax:

mod( 'text_variables' ).width
mod( 'text_variables' ).height
mod( 'text_variables' ).budget

Try adding a constant CHOP, and a text TOP to your network and using the expressions above to retrieve these values.

Next try printing these values:

print( mod( 'text_variables' ).width )
print( mod( 'text_variables' ).height )
print( mod( 'text_variables' ).budget )

So, it looks like we can access the contents of a module as a means of storing variables. That’s hip. Let’s take a moment and circle back to one of the other use cases that we’ve already seen for a module. More than just a single value, we can also put a whole dictionary in a module and then call it on demand. We’ve already done this in some of our previous examples, but we can take a quick look at that process again to make sure we understand.

Let’s create a new text DAT called “text_dictionary_as_module”, inside of this text DAT let’s define the following dictionary:

fruit = {
    "apple" : 10,
    "orange"    : 5,
    "kiwi"  : 16

Let’s first print the whole dictionary object:

print( mod( 'text_dictionary_as_module' ).fruit )

Alternatively, we can also access individual keys in the dictionary:

mod( 'text_dictionary_as_module' ).fruit[ 'apple' ]
mod( 'text_dictionary_as_module' ).fruit[ 'orange' ]
mod( 'text_dictionary_as_module' ).fruit[ 'kiwi' ]

What can you do with this?! Well, you might store your config file in a text DAT that you can call from a module on demand. You might use this to store configuration variables for your UI – colors, fonts, etc. ; you might decide to use this to configure some portion of a network, or to hold on to data that you want to recall later; or really any number of things.

Before we get too excited about storing variables in modules on demand, let’s look at an even more powerful feature that will help us better understand where they really start to shine.

Up next we’re going to look at writing a simple function that we can use as a module on demand. In addition to writing some simple little functions, we’re also going to embrace docstrings – a feature of the python language that makes documenting your work easier. Docstings allow us to leave behind some notes for our future selves, or other programmers. One of the single most powerful changes you can make to how you work is to document your code. It’s a difficult practice to establish, and can be frustrating to maintain – but it is hands down one of the most important changes you can make in how you work.

Alright, I’ll get off my documentation soapbox for now. Let’s write a few methods and see how this works in TouchDesigner.

We can start by creating a new text DAT called “text_simple_reutrn”, inside of this DAT we’ll write out our new functions:

Great! But what can we do with these? We can start by using some eval DATs or print statements to see what we’ve got. I’m going to use eval DATs. Let’s add several to our network and try out some calls to our new module on demand. First let’s look at the generic syntax:

mod( name_of_text_dat ).name_of_method

In practice that will look like:

mod( 'text_simple_reutrn' ).multi_by_two( 5 )
mod( 'text_simple_reutrn' ).multi_by_two( 2.5524 )
mod( 'text_simple_reutrn' ).logic_test( 5 )
mod( 'text_simple_reutrn' ).logic_test( 6 )
mod( 'text_simple_reutrn' ).logic_test_two( "TouchDesigner" )

Now we can see that we wrote several small functions that we can then call from anywhere, as long as we know the path to the text DAT we’re using as a module on demand! Here’s where we start to really unlock the potential of modules on demand. As we begin to get a better handle on the kind of function we might write / need for a project we can begin to better understand how to take full advantage of this feature in TouchDesiger.

Doc Strings

Since we took the time to write out all of those doc strings, let’s look at how we might be able to print them out! Part of what’s great about doc strings is that there’s a standard way to retrieve them, and therefore to print them. This means that you can quickly get a some information about your function printed right in the text port. Let’s take a closer look by printing out the doc stings for all of our functions:

That worked pretty well! But looking back at this it seems like we repeated a lot of work. We just learned about for loops, so let’s look at how we could do the same thing with a loop instead:

A Practical Example

This is all fun and games, but what can we do with this? There are any number of functions you might write for a project, but part of what’s exciting here is the ability to write something re-usable in Python. What might that look like? Well, let’s look at an example of a logger. There are a number of events we might want to log in TouchDesigner when we have a complex project.

In our case we’ll write out a method that allows a verbose or compact message, a way to print it to the text port or not, and a way to append a file or not. Alright, here goes:

So now that we’ve written out the method, what would call for this look like?

operator = me

message ='''
Just a friendly message from your TouchDesigner Network.
Anything could go here, an error message an init message.

You dream it up, and it'll print

# print and append log file with a verbose log message
mod( 'text_module1' ).Log_message( operator, message, verbose = True )

# print and append log file with a compact log message
# mod( 'text_module1' ).Log_message( operator, message )

# append log file with verbose log message
# mod( 'text_module1' ).Log_message( operator, message, verbose = True, text_port_print = False )

# print a compact log message
# mod( 'text_module1' ).Log_message( operator, message, append_log = False )

Take a moment to look at the example network and then un-comment a line at a time in the text DAT with the script above. Take note of how things are printed in the text port, or how they’re appended to a file. This is our first generalized function that has some far reaching implications for our work in touch. Here we’ve started with a simple way to log system events, both to a file and to the text port. This is also a very re-usable piece of code. There’s nothing here that’s highly specific to this project, and with a little more thought we could turn this into a module that could be dropped into any project.

Local Modules

We’ve learned a lot so far about modules on demand, but the one glaring shortcoming here is that we need the path to the text DAT in question. That might not be so bad in some cases, but in complex networks writing a relative path might be complicated, and using an absolute path might be limiting. What can we do to solve this problem. We’re in luck, as there’s one feature of modules we haven’t looked at just yet. We can simplify the calling / locating of modules with a little extra organization.

First we need to add a base and rename it to “local”, inside of this base add another base and rename it to “modules”. Perfect. I’m going to reuse one of our existing code examples so we can see a small change in syntax here. I’ve also changed the name of the text DAT inside of local>modules to “simple_return”.

mod.simple_return.multi_by_two( 5 )
mod.simple_return.multi_by_two( 2.5524 )
mod.simple_return.logic_test( 5 )
mod.simple_return.logic_test( 6 )
mod.simple_return.logic_test_two( "TouchDesigner" )
mod.simple_return.logic_test_two( 10 )

Looking at the above, we can see that we were able to remove the parentheses after “mod”. But what else changed? Why is this any better? The benefit to placing this set of functions in local>modules is that as long as you’re inside of this component, you no longer need to use a path to locate the module you’re looking for.

Alright, now it’s time for you to take these ideas out for a test drive and see what you can learn.

Python in TouchDesigner | Intro to Functions | TouchDesigner

Core Concepts

  • Functions as a concept
  • Anatomy of a function
  • Writing functions
  • Calling functions
  • Returning values
  • Passing arguments

Before we can tackle CHOP executes we need to take a moment to learn about functions. There’s a lot to learn about with functions, so we’re not going to dive too deep just yet… yet. We are, however, going to peer into this idea so we can better understand part of what we’ll see next as we move into the exciting world of executes.

Let’s start by looking at what a function actually is:

“A function is a block of organized, reusable code that is used to perform a single, related action. Functions provide better modularity for your application and a high degree of code reusing.

As you already know, Python gives you many built-in functions like print(), etc. but you can also create your own functions.”
Tutorials Point

Great! But… how can we better understand that? For a moment let’s first appreciate that we have a wide variety of functions that we do on a regular basis… we just don’t think of them as functions. Most of us know how to calculate a tip, or gas mileage, or estimate travel time, or pack a suitcase, or make lunch, or or or, and and and. We don’t think of these as functions, but if we had to write out very specific instructions about how to complete one of these tasks we’d actually be close to starting to wrestle with the idea of what a function is – it’s okay if that doesn’t make sense yet. Hang on tight, because we’re gonna get there.

Let’s first look at a simple example that examines the anatomy of a function. Next we’ll write a few simple functions. Then we’ll look at why that’s important when it comes to thinking about CHOP executes.

Starting with Anatomy.

Here we go, we’re going to write a dead simple function:

def first_function():
    print( 'Hello World' )


There we go. We did it. Now, if we were to run this in TouchDesigner, nothing would happen… so at first glance it would seem like we didn’t really write a function after all. That might be a good guess, but the reason nothing happened is because we never actually called our function, we just defined it – we wrote out all of the instructions, but we never asked TouchDesigner to actually run the function. To see anything happen, we need to actually call the function – we need to tell TouchDesigner that we need to run it. Let’s modify our example to see what that would look like.

def first_function():
    print( 'Hello World' )



Okay… time to take this all apart and see what makes it tick.

  • We’re started out by indicating that we were going to define a function… that’s really what we meant when we wrote “def.”
  • Next we gave that function a name, in our case we called it “first_function.”
  • Next we specified that we weren’t going to pass in any arguments or parameters by writing “()” – don’t worry, we’re going to learn more about that in a second.
  • Then we indicated that we were going to outline what was in the function with our “:”
  • The next line is indented one tab space and here we print out “Hello World”
  • We ended the function with a return statement, which in this case didn’t return anything.
  • Finally, we summoned our function into action by saying its name… well, writing its name “first_function()”

At this point we’ve written a very simple function that just prints out “Hello World.” We started with this simple example so we could just talk about its anatomy. Before we can move on to something a little more interesting, we need to unpack a few things. Specifically, we need to talk more about what it means to *return* something, and what an argument or parameter is when it comes to functions.

Let’s start with *return*. Like it’s name suggests, to return something is to give it back, or deliver something. Seems straightforward enough, right? We might imagine that sometimes we don’t want to print out the result of a function, but we do want to get something out the other side to use in another process. In this case, we want something returned to us after the function has run. Let’s look at that in a concrete way.

We’re going to use our same example first function, but make a few changes.

def first_function():
    text = 'Hello World'

    return text


Okay, here we can see that we changed our function so we don’t actually print out “Hello World” anymore, instead we return it at the end. If we run our function, we encounter our same problem that we saw earlier… it would seem as if nothing happened. What gives. Let’s change our function in one small way and see what we end up with:

def first_function():
    text = 'Hello World'

    return text

print( first_function() )

The small change to print out first_function() means that we’re now printing out what’s returned from this function. It might feel like a small difference, but it means that we’re able to control what comes out of our function when we summon it into action. That’s actually a very important thing, and we’ll see why shortly.

If we can control what comes out of our functions, surely we can control what goes into them… right? In fact, you are right.

Now that we now how to get something out of our function, let’s pass it some information do to something with. We’re going to write another simple function, this time to do some simple math.

def percent( val1 ):
    calculation = val1 * 0.01

    return calculation

print( percent( 50 ) )

Alright, what do we have here? Let’s imagine we want to change an integer into it’s float equivalent as a percentage. 50% as becomes 0.5, 10% would be 0.1, and so on and so on. Here we’ve written a function to do just that. In this case we’ve specified that our function accepts one argument which is named val1. We later see in our function that “calculation” is val1 * 0.01. Finally, we return calculation. This means we can give percent any number, and get a float value in return. Not bad.

Okay, let’s look at two more examples. Next we’ll write a simple function to calculate a tip based on a total bill. At the end of this we want to see our tip and our total bill – using our new found lingo, we’re going to return these values.

Okay, let’s make some Python magic happen. If you’re playing along at home, trying writing this yourself before you look at how I did it.

def tip_calculator( total , tip_percentage ):

    tip = total * ( tip_percentage / 100 )
    total_bill = total + tip
    return tip , total_bill

print( tip_calculator( 50 , 15 ) )

Here we want two things back, our tip and our total_bill. We start by calculating the tip, and then by adding that to our total. Finally we return these two values.

Let’s try one more idea on for size. This next time around you’re challenge is to use the function we just wrote, and to write another function as a compliment. This second function is going to print out these values to our text port so we can see them. By writing this as two separate functions we decide when we want to print out our results, and when we want to just return our tip and total_bill. As an extra challenge, see if you can write your new function to accept only a single argument.

Okay, let’s look at how you might solve this problem:

def tip_calculator( total , tip_percentage ):
    tip = total * ( tip_percentage / 100 )
    total_bill = total + tip
    return tip , total_bill

def display_total( tip_and_total_bill ):
    dotted_line = '- ' * 10
    tip_text = "Your total tip is {}"
    total_bill_text = "Your total bill is {}"
    print( dotted_line )
    print( tip_text.format( tip_and_total_bill[ 0 ] ) )
    print( total_bill_text.format( tip_and_total_bill[ 1 ] ) )
    print( dotted_line )


total = 100
tip_percentage = 20

print( tip_calculator( total , tip_percentage ) )

display_total( tip_calculator( total , tip_percentage ) )

How did you do? We can see that our first function stayed the same. Our second function accepts a single argument – tip_and_total_bill. This tuple (a series of values) is then used by our second function when printing out to our textport. This probably isn’t the best way to solve this problem… but for the sake of a simple example our chances of getting into trouble are pretty slim.

Okay, so why do all of this?! Well, let’s take a sneak peak at what’s coming next. If we look at the contents of a CHOP execute we see:

# me - this DAT
# channel - the Channel object which has changed
# sampleIndex - the index of the changed sample
# val - the numeric value of the changed sample
# prev - the previous sample value
# Make sure the corresponding toggle is enabled in the CHOP Execute DAT.

def offToOn(channel, sampleIndex, val, prev):

def whileOn(channel, sampleIndex, val, prev):

def onToOff(channel, sampleIndex, val, prev):

def whileOff(channel, sampleIndex, val, prev):

def valueChange(channel, sampleIndex, val, prev):

We should now recognize the contents of these DATs as functions… and not only are they functions, they’re functions with four named incoming arguments. Now we can really start to have fun.

Learn more about functions in Python

Download the sample files from github

Python in TouchDesigner | Data Structures – Dictionaries | TouchDesigner

Part 1 Core Concepts

  • Dictionaries – a structure and a concept
  • Looking at Dictionaries and Lists side by side
  • What are key value pairs
  • Retrieving values from dictionaries
  • Retrieving .keys() and .values()
  • Adding items to dictionaries
  • Nested data structures
  • A better text formatting approach with .format() (a big thank you to Willy Nolan for setting me on the right path with text formatting in Python 3)

Part 2 Core Concepts

  • Dictionaries – a structure and a concept
  • A practical look at dictionaries in TouchDesigner
  • Nested data structures – dictionaries in dictionaries
  • Using Dictionaries as a preset structure
  • Using Python to set parameters
  • Using Python variables in scripts to generalize our code

This isn’t the first time I’ve been on a tear about using Dictionaries in TouchDesigner – THP 494 & 598, Presets. That said, sometimes it’s easier to understand a concept if we back down a little bit and start from the beginning. With that in mind, let’s turn the speed down to 0.1 before we turn it up to 12 again.

Dictionaries are another type of data structure that we can use in Python. They’re similar to lists in that we can store information in them, and retrieve them easily. Dictionaries, however, are distinctly different from lists. Where lists are index based – which is to say that they have a specific order – dictionaries are key based.

What does that mean, and why do we care?! We think of dictionaries as being a pair of things a key, and a value. We might think of this as a name and its corresponding piece of information. Let’s look at something simple to get started. To get started let’s go back to our grocery example when we were talking about lists. In making a list for our trip to the grocery store we listed all of the items we needed from the store. We didn’t however, make any notes about quantity. Let’s quickly make that list again:

grocery_list = [ 'eggs' , 'milk' , 'bread' , 'butter' , 'coffee' ]

This is great, and it tells us lots of information, but maybe not all of the information we need. If I’m going to the store myself, this is a fine list. If I’m asking someone else to pick up these things for me, well then I need at least one other piece of information – quantity. If we’re using lists, we might do something clever, like make a list of lists with two items – the grocery item, and the desired quantity. That might look something like this:

grocery_list = [ 
    ['eggs' , '1 dozen' ] , 
    ['milk' , '1 pint' ] , 
    ['bread' , '2 loaves' ] , 
    ['butter' , '1 lb' ] , 
    ['coffee', '2 lbs' ]

This works fine, and might be a great way to hold onto this information. We can, however, use a dictionary to do this same thing. In this case we’re going to think of our grocery items as a keys, and quantities as values. Let’s look at what means:

grocery_list = {
    'eggs' : '1 dozen' , 
    'milk' : '1 pint' , 
    'bread' : '2 loaves' , 
    'butter' : '1 lb' , 
    'coffee': '2 lbs'

It’s important to note that I’ve used some indenting to make this easier to read, but another perfectly valid way to write this dictionary would be:

grocery_list = { 'eggs' : '1 dozen' , 'milk' : '1 pint' , 'bread' : '2 loaves', 'butter' : '1 lb' , 'coffee': '2 lbs' }

I just happen to think that anytime you can make something easier to read by a human, the better.

Okay, let’s talk about syntax here for a second. So the first thing we did was declare our dictionary as a variable. Next we used curly brackets to open our dictionary ( {} – these are curly brackets ). Next we wrote out our dictionary as key and value pairs separated by a colon – keys on the left, values on the right. Now in this example all of our values were strings, but they could just as easily have been integers, floats, booleans, lists, or even other dictionaries.

This is all well and good, but how do we get things out of our dictionary? We know how to retrieve things from a list, but a dictionary is a little different. When retrieving something from a dictionary we typically use a key. Let’s consider our first example again for a second. Let’s say we want to print out the quantity of eggs that we’re supposed to get from the store. We can do that like this:

print( grocery_list[ 'eggs' ] )

We can also retrieve the contests of dictionary with .keys() and .values():

print( grocery_list.keys() )
print( grocery_list.values() )

In both of these cases we get a list of keys or values.

It’s also important to know how to add items to our dictionary. There are a few ways to go about this, but let’s just look at one for now. We should start by creating an empty dictionary:

my_dictionary = {}

Now that we have an empty dictionary, we can add items to it. We do this by starting with the dictionary name, then placing the key in square brackets ([] these things), followed by an equal sign, and then what we want to be placed into the dictionary as the value. Let’s look at an example:

my_dictionary[ 'new_item1' ] = "cookies"

Okay, now that we’ve added one key value pair, let’s print out the keys and values in our list (to practice), and add a few more items:

my_dictionary = {}

my_dictionary[ 'new_item1' ] = "cookies"

print( my_dictionary.keys() )
print( my_dictionary.values() )

my_dictionary[ 'new_item2' ] = "cell_phones"

print( my_dictionary.keys() )
print( my_dictionary.values() )

my_dictionary[ 'new_item3' ] = 55

print( my_dictionary.keys() )
print( my_dictionary.values() )

my_dictionary[ 'new_item4' ] = [ 1 , 2 , 3 ]

print( my_dictionary.keys() )
print( my_dictionary.values() )

Wait… what did we just do there with item4?! Most of that should look pretty straightforward, and hopefully that makes sense for the most part. It is not, however, the most exciting part of using dictionaries. Dictionaries become the most exciting when we start to see how we can nest other lists or dictionaries inside of them.

Let’s look at a dictionary of mixed contents:

my_dictionary = { 
    "apple" : "these are delicious" , 
    "orange" : 12 , 
    "kiwi" : 55.5 , 
    "lots_of_things" : [
        "paper" , 
        "pens" ,
        44 , 

So we know how to get to the values associated with “apple” , “orange” , and “kiwi” , but how do we get to the contents of that list? Well, we can write something like this:

print( my_dictionary[ 'lots_of_things' ][ 0 ] )
print( my_dictionary[ 'lots_of_things' ][ 1 ] )
print( my_dictionary[ 'lots_of_things' ][ 2 ] )
print( my_dictionary[ 'lots_of_things' ][ 3 ] )

Here we see the same syntax that we use when retrieving list items.

That’s wonderful! So what about when we store dictionaries inside of dictionaries? Let’s look at a simple example. We can start by creating a dictionary with fruit’s as our keys. Each fruit will have a corresponding dictionary of quantity, origin, and if the fruit is organic. Okay, what would that look like:

my_dictionary_of_dictionaries = { 
    "apple" : {
        "quantity" : 10 ,
        "origin" : "Vermont" ,
        "organic" : True 
    } , 
    "orange" : {
        "quantity" : 20 ,
        "origin" : "California" ,
        "organic" : False
    } , 
    "kiwi" : {
        "quantity" : 26 ,
        "origin" : "Mexico" ,
        "organic" : False
    } , 
    "grapes" : {
        "quantity" : 50 ,
        "origin" : "Peru" ,
        "organic" : True

That’s pretty snazzy and all, but how do we pull things out of this data structure? We can follow the example we learned with lists, but instead of using index values, we can instead use keys. Let’s look at just apple to get started:

print( "Let's just look at apple" )
print( "quanitity -" , my_dictionary_of_dictionaries[ 'apple' ][ 'quantity' ] )
print( "origin -" , my_dictionary_of_dictionaries[ 'apple' ][ 'origin' ] )
print( "organic -" , my_dictionary_of_dictionaries[ 'apple' ][ 'organic' ] )

Here we can see that we start with our dictionary, with a key in square brackets, followed by another key in square brackets. Practice retrieving other keys – what about grapes, or oranges? Also practice by adding other keys inside of the fruit dictionaries. Don’t forget to pay careful attention to where you’ve placed your commas and, remember that keys are strings so they need quotation marks.

Once you’ve done that, let’s consider how we might use something like a dictionary here in TouchDesigner. We’re going to look something a little complex, but still relatively simple to help us get our bearings. Dictionaries can be a great help to us when we want to do things like creating save states. Let’s first think about what it would mean to set the properties of a text TOP with the contents of a dictionary.

Let’s start by making our dictionary. I’m going to use the same names for our dictionary keys that we find in our parameter names – just to make sure we know exactly where a value is going.

top_dictionary = { 
    "text" : 'monkey' , 
    "fontsizex" : 15 ,
    "alignx" : 1 ,
    "aligny" : 1 ,
    "fontcolorr" : 1.0 ,
    "fontcolorg" : 0.0 ,
    "fontcolorb" : 0.0 ,
    "fontalpha" : 1.0 ,
    "bgcolorr" : 0.0 ,
    "bgcolorg" : 0.0 ,
    "bgcolorb" : 0.0 ,
    "bgalpha" : 1.0

Now let’s flesh out our script to change the parameters of our TOP:

target_text = op( 'text1' )

target_text.par.text = top_dictionary[ 'text' ]

target_text.par.fontsizex = top_dictionary[ 'fontsizex' ]
target_text.par.alignx = top_dictionary[ 'alignx' ]
target_text.par.aligny = top_dictionary[ 'aligny' ]
target_text.par.fontcolorr = top_dictionary[ 'fontcolorr' ]
target_text.par.fontcolorg = top_dictionary[ 'fontcolorg' ]
target_text.par.fontcolorb = top_dictionary[ 'fontcolorb' ]
target_text.par.fontalpha = top_dictionary[ 'fontalpha' ]
target_text.par.bgcolorr = top_dictionary[ 'bgcolorr' ]
target_text.par.bgcolorg = top_dictionary[ 'bgcolorg' ]
target_text.par.bgcolorb = top_dictionary[ 'bgcolorb' ]
target_text.par.bgalpha = top_dictionary[ 'bgalpha' ]

That’s pretty great – but goodness that’s a lot of work just to change some settings. How might we think about using this idea to create a preset system? We’re not that far off form this idea at this point, so let’s dig in a little deeper. To really make this work, we need to revisit our dictionary. Specifically, we need to encapsulate our presets inside another layer. We need to make them their own dictionary as a set of values for another key. For example, we might want a named structure like “preset1” , “preset2” etc. to be how we retrieve settings. Let’s change our dictionary to make that happen:

top_dictionary = { 
    "preset1" : {
        "text" : 'monkey' , 
        "fontsizex" : 15 ,
        "alignx" : 1 ,
        "aligny" : 1 ,
        "fontcolorr" : 1.0 ,
        "fontcolorg" : 0.0 ,
        "fontcolorb" : 0.0 ,
        "fontalpha" : 1.0 ,
        "bgcolorr" : 0.0 ,
        "bgcolorg" : 0.0 ,
        "bgcolorb" : 0.0 ,
        "bgalpha" : 1.0
    } ,
    "preset2" : {
        "text" : 'pig' , 
        "fontsizex" : 80 ,
        "alignx" : 1 ,
        "aligny" : 0 ,
        "fontcolorr" : 0.0 ,
        "fontcolorg" : 0.0 ,
        "fontcolorb" : 1.0 ,
        "fontalpha" : 1.0 ,
        "bgcolorr" : 1.0 ,
        "bgcolorg" : 1.0 ,
        "bgcolorb" : 1.0 ,
        "bgalpha" : 1.0

Not bad. Now, how can apply these presets to our top? To do this we’re going to do one tricky thing. We’re going to write our scripts so that a python variable can stand in our first key. This will mean that we only need to change a single variable before re-running our script. That would look like this:

target_text = op( 'text1' )
dictionary_preset = 'preset2'

target_text.par.text = top_dictionary[ dictionary_preset ][ 'text' ]
target_text.par.fontsizex = top_dictionary[ dictionary_preset ][ 'fontsizex' ]
target_text.par.alignx = top_dictionary[ dictionary_preset ][ 'alignx' ]
target_text.par.aligny = top_dictionary[ dictionary_preset ][ 'aligny' ]
target_text.par.fontcolorr = top_dictionary[ dictionary_preset ][ 'fontcolorr' ]
target_text.par.fontcolorg = top_dictionary[ dictionary_preset ][ 'fontcolorg' ]
target_text.par.fontcolorb = top_dictionary[ dictionary_preset ][ 'fontcolorb' ]
target_text.par.fontalpha = top_dictionary[ dictionary_preset ][ 'fontalpha' ]
target_text.par.bgcolorr = top_dictionary[ dictionary_preset ][ 'bgcolorr' ]
target_text.par.bgcolorg = top_dictionary[ dictionary_preset ][ 'bgcolorg' ]
target_text.par.bgcolorb = top_dictionary[ dictionary_preset ][ 'bgcolorb' ]
target_text.par.bgalpha = top_dictionary[ dictionary_preset ][ 'bgalpha' ]

Alright. Looking closely at the above, we can see that we need only change the variable “dictionary_preset” in order to fetch a whole different set of values. Not bad, right?

Take some time to experiment with these ideas. As we head forward we’re going to start to look at how we can use executes and for loops to see how we can really start to make headway in using Python. We’ve laid a lot of ground work so we can really plow ahead.

Learn more about Python Data Structures

Download the sample files from github