Tag Archives: programming

TouchDesigner | Reusable Code Segmentation with Python

reusable-code-segmentation.PNG

Thinking about how to approach re-usability isn’t a new topic here, in fact there’s been plenty of discussion about how to re-use components saved as tox files, how to build out modular pieces, and how to think about using Extensions for building components you want to re-use with special functions.

That’s wonderful and exciting, but for any of us that have built deployed projects have quickly started to think about how to build a standard project that any given installation is just a variation of… a flavor, if you will, of a standard project build. Much of that customization can be handled by a proper configuration process, but there are some outliers in every project… that special method that breaks our beautiful project paradigm with some feature that’s only useful for a single client or application.

What if we could separate our functions into multiple classes – those that are universal to every project we build, and another that’s specific to just the single job we’re working on? Could that help us find a way to preserve a canonical framework with beautiful abstractions while also making space for developing the one-off solutions? What if we needed a solution to handle the above in conjunction with sending messages over a network?  Finally, what if we paired this with some thoughts about how we handle switch-case statements in Python? Could we find a way to help solve this problem more elegantly so we could work smarter, not harder?

Well, that’s exactly what we’re going to take a look at here.

First a little disclaimer, this approach might not be right for everyone, and there’s a strong assumption here that you’ve got some solid Python under your belt before you tackle this process / working style. If you need to tool up a little bit before you dig in, that’s okay. Take a look at the Python posts to help get situated then come back to really dig in.


Getting Set-up

In order to see this approach really sing we need to do a few things to get set-up. We’ll need a few operators in place to see how this works, so before we dig into the python let’s get our network in order.

First let’s create a new base:

base.PNG

Next, inside of our new base let’s set up a typical AB Deck of TOPs with a constant CHOP to swap between them:

typical-ab-deck.PNG

Above we have two moviefilein TOPS connected to a switch TOP that’s terminated in a null TOP. We also have a constant CHOP terminated in a null whose chan1 value is exported to the index parameter of our switch TOP.

Let’s also use the new Layout TOP in another TOP chain:

layout-top.PNG

Here we have a single layout TOP that’s set-up with an export table. If you’ve never used DAT Exports before you might quickly check out the article on the wiki to see how that works. The dime tour of that ideal is that we use a table DAT to export vals to another operator. This is a powerful approach for setting parameters, and certainly worth knowing more about / exploring.

Whew. Okay, now it’s time to set up our extensions. Let’s start by creating a textDAT called messageParserEXT, generalEXT, and one called jobEXT.

parser-general-job.PNG


The Message Parser

A quick note about our parser. The idea here is that a control machine is going to pass along a message to a set of other machines also running on the network. We’re omitting the process of sending and receiving a JSON blob over UPD, but that would be the idea. The control machine passes a JSON message over the network to render nodes who in turn need to decode the message and perform some action. We want a generalized approach to sending those blobs, and we want both the values and the control messages to be embedded in that JSON blob. In our very simple example our JSON blob has only two keys, messagekind and vals:

message = {
        'messagekind' : 'some_method_name',
        'vals' : 'some_value'
}

In this example, I want the messagekind key to be the same as a method name in our General or Specific classes.

Pero, like why?!

Before we get too far ahead of ourselves, let’s first copy and past the code below into our messageParserEXT text DAT, add our General and Specific Classes, and finish setting up our Extensions.

The General Code Bits

In our generalEXT we’re going to create a General class. This works hand in hand with our parser. The parser is going to be our helper class to handle how we pass around commands. The General class is going to handle anything that we need to have persist between projects. The examples here are not representative of the kind of code you’d have your project, instead they’re just here to help us see what’s happening in this approach.

The Specific Code Bits

Here in our Specific class we have the operations that are specific to this single job – or maybe they’re experimental features that we’re not ready to roll into our General class just yet, regardless, these are methods that don’t yet have a place in our canonical code base. For now let’s copy this code block into our jobEXT text DAT.

At this point we’re just about ready to pull apart what on earth is happening. First let’s make sure our extension is correctly set-up. Let’s go back up a level and configure our base component to have the correct path to our newly created extension:

 

reusable-ext-settings.PNG

Wait wait wait… that’s only one extension? What gives? Part of what we’re seeing here is inheritance. Our Specific class inherits from our General class, which inherits form our MessageParser. If you’re scratching your head, consider that a null TOP is also a TOP is also an OP. In the same way we’re taking advantage of Python’s Object oriented nature so we can treat a Specific class as a special kind of General operation that’s related to sending messages between our objects. All of his leads me to believe that we should really talk about object oriented programming… but that’s for another post.

Alright… ALMOST THERE! Finally, let’s head back inside of our base and create three buttons. Lets also create a panel execute for each button:

buttons.PNG

Our first panel execute DAT needs to be set up to watch the state panel value, and to run on Value Change:

change-switch.PNG

Inside of our panel execute DAT our code looks like:

# me - this DAT
# panelValue - the PanelValue object that changed# # Make sure the corresponding toggle is enabled in the Panel Execute DAT.
def onOffToOn(panelValue):
    return
def whileOn(panelValue):
    return
def onOnToOff(panelValue):
    return
def whileOff(panelValue):
    return
def onValueChange(panelValue):
    message = {
        'messagekind' : 'Change_switch',
        'vals' : panelValue } 
    parent().Process_message(message)
    return

If we make our button viewer active, and click out button we should see our constant1 CHOP update, and our switch TOP change:

switch-gif.gif

AHHHHHHHHH!

WHAT JUST HAPPENED?!


The Black Magic

The secret here is that our messagekind key in our panel execute DAT matches an existing method name in our General class. Our ProcessMessage() method accepts a dictionary then extracts the key for messagekind. Next it checks to see if that string matches an existing method in either our General or Specific classes. If it matches, it then calls that method, and passes along the same JSON message blob (which happens to contain our vals) to the correct method for execution.

In this example the messagekind key was Change_switch(). The parser recognized that Change_switch was a valid method for our parent() object, and then called that method and passed along the message JSON blob. If we take a look at the Change_switch() method we can see that it extracts the vals key from the JSON blob, then changes the constant CHOP’s value0 parameter to match the incoming val.

This kind of approach let’s you separate out your experimental or job specific methods from your tried and true methods making it easier in the long run to move from job to job without having to crawl through your extensions to see what can be tossed or what needs to be kept. What’s better still is that this imposes minimal restrictions on how we work – I don’t need to call a separate extension, or create complex branching if-else trees to get the results I want – you’ll also see that in the MessageParser we have a system for managing elegant failure with our simple if hasattr() check – this step ensure that we log that something went wrong, but don’t just throw an error. You’d probably want to also print the key for the method that wasn’t successfully called, but that’s up to you in terms of how you want to approach this challenge.

Next see if you can successfully format a message to call the Image_order() method with another panel execute.

What happens if you call a method that doesn’t exist? Don’t forget to check your text port for this one.

If you’re really getting stuck you might check the link to the repo below so you can see exactly how I’ve set this process up.

If you got this far, here are some other questions to ponder:

  • How would you  use this in production?
  • What problems does this solve for you… does it solve any problems?
  • Are there other places you could apply this same idea in your projects?

At the end of the day this kind of methodology is really looking to help us stop writing the same code bits and bobs, and instead to figure out how to build soft modules for our code so we can work smarter not harder.

With any luck this helps you do just that.

Happy Programming.


Take a look at the sample Repo for this example on Github:
touchdesigner-reusable-code-segmentation-python

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 

adeck.PNG

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

ab_deck.PNG

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.

table_dat.PNG

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.

move-through-cues.PNG

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

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 , 
        10.4
    ] 
}

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

Python in TouchDesigner | Data Structures – Lists | TouchDesigner

Part 1 Core Concepts

  • Lists – a structure and a concept
  • Creating lists – syntax and structure
  • Retrieving items from a list – Syntax
  • Adding items to a list .append() and .extend()
  • Lists of Lists


Part 2 Core Concepts

  • Lists – a structure and a concept
  • Why Lists matter in TouchDesigner
  • The Channel Class – seeing CHOPs as lists
  • The Point Class – thinking of geometry as lists
  • The COMP Class and .findChildren() – pulling apart returned lists
  • More about how to read the TouchDesigner wiki


Lists are the bees knees, they’re the cat’s pajamas, they’re almost better than sliced bread. There are a few important things for us to think about before we dive into the Python of lists. Python lists are just like the lists you might make on a piece of paper. They’re a sequential ordering of items. A grocery list might be:

  • eggs
  • milk
  • bread
  • butter
  • coffee

We often make lists, and while the order of our grocery list might be arbitrary, there are plenty of lists that are not. Frequently a todo list has a specific order:

  1. Have preliminary discussion with collaborators
  2. Check schedule for availability
  3. Block off time for new project
  4. Coordinate schedules
  5. Build a preliminary budget
  6. Draft contracts
  7. Confirm costs
  8. Book space
  9. Purchase equipment

While this is a silly example, the important consideration is that here you wouldn’t purchase equipment before you started a preliminary discussion with your collaborators. Of course that seems obvious – but remember that you have a sense of linearity, a sense of time, a sense of order, and a idiomatic frame that you subconsciously constructed based on the content of the list items. Alright, semiotics aside, the more important idea here is that lists have order. Now while that may seem obvious, we’ll see later that dictionaries don’t necessarily work in the way – and in fact this is an important distinction we need to make early on.

Let’s go back to our grocery list. What might that look like in Python?

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

You’ll notice that our items are enclosed in matching foot or inch marks: ” or “”. We can remember back to our first lesson on printing that this helps us see that these are strings. That’s wonderful. What if we want to print the whole list? Well we can do this:

print( grocery_list )

That prints our whole list. That’s pretty swanky, but what if we just want a single item from our list? How can we just print that? Well, we’ll remember that 0 is still a number for us here in Python. That means the indexing of our list items looks like: 0 1 2 3 4

We can print a single item in our list by indicating the index of the item we want:

print( grocery_list[ 0 ] )

Let’s look at that a little more closely and print out all of the items we have in our list:

print( grocery_list[ 0 ] )
print( grocery_list[ 1 ] )
print( grocery_list[ 2 ] )
print( grocery_list[ 3 ] )
print( grocery_list[ 4 ] )

Let’s go one step further and really make that as explicit as possible – just to make sure we understand.

print( "The item in the 0 position of our list is %r" % grocery_list[ 0 ] )
print( "The item in the 1 position of our list is %r" % grocery_list[ 1 ] )
print( "The item in the 2 position of our list is %r" % grocery_list[ 2 ] )
print( "The item in the 3 position of our list is %r" % grocery_list[ 3 ] )
print( "The item in the 4 position of our list is %r" % grocery_list[ 4 ] )

We can make lists out of just about anything. Let’s make a list out of all of the data types we’ve talked about so far:

my_int_list = [ 1 , 2 , 3 , 4 ]
my_float_list = [ 1.235 , 1.5679 , 9.454 , 4.23485 ]
my_string_list = [ 'apple' , 'kiwi' , 'orange' , 'pineapple' ]
my_bool_list = [ True , True , False , True, False ]
my_mixed_list = [ 1.234 , 5 , 'apple' , True , 3.45 ]

One question we might have is how long is our list? Well, there happens to be an easy way for us to figure that out with len() – as in length.

len( my_int_list )

Practice printing the length of all of your lists.

We can also build lists from scratch. First we need to create an empty list.

my_list = []

print( 'As we go, we will print our list at each' )
print( 'step along the way' )
print( 'My List' , my_list )

Next we can add items to our list with .append( theValueOrStringToBeAddedHere ).

my_list.append( 1 )

# this is here to make a line break
print( '\n' )

print( 'So we just added a single number out our list' )
print( 'what does that look like now?' )
print( 'My List' , my_list )

We can even add multiple items at once with .extend( aListofItemsHere ):

my_list.extend( [ 45 , 2 , 100 , 6 ] )

# this is here to make a line break
print( '\n' )

print( 'Can we add multiple items at once?' )
print( 'My List' , my_list )

print( 'We sure can, we just need to use .extend' )
print( 'instead of .append' )

That’s great… but what does this mean for me in TouchDesigner? Well, in Touch many things are returned as lists. Samples in CHOPs are often a list, as are points in a SOP. Once we have a fundamental understanding of lists as a data structure we can start to really have a lot of fun.

Let’s look at CHOPs first.
First, make sure you add a noise CHOP to your network called noise1.

# define some variables
noise1 = op( 'noise1' )

# understanding the channel operator make
# a big difference in the way we use TouchDesigner
# lets start by just printing our variable

print( 'If we just print our noise1 variable we see this' )
print( noise1 )

print( 'If we print chan1 in noise1 one we see this' )
print( noise1[ 'chan1' ] )

print( 'we can also access this by using .chan( channelIndexHere )' )
print( noise1.chan( 0 ) )

print( 'Finally, we can see the whole list of values if we use' )
print( '.vals as we... that looks like') 
print( 'noise1.( channelIndexHere ).vals' )
print( noise1.chan( 0 ).vals )

That’s pretty fun… but let’s take that a step further.

# okay, but why do we care?

# define some variables
noise1 = op( 'noise1' )

# we can use what we've learned working with the .chans().vals
# to help us understand a little bit more about our CHOP
# for example, if our channel is a list of values, we can
# access those values just like we might in a list

print( noise1[ 'chan1' ][ 0 ] )
print( noise1[ 'chan1' ][ 1 ] )
print( noise1[ 'chan1' ][ 2 ] )

# we can even do the same things we might do in python here
print( len( noise1[ 'chan1' ] ) )

# though if we look at the wiki, we'll find that there's already
# a method to do just this called .numSamples
# and a method called numChans - which tells us how many channels
# If we think of our CHOP as a list of lists... then we can both
# see how many lists, and the length of the lists.

print( noise1.numSamples )
print( noise1.numChans )

Next let’s add a rectangle SOP to our network.

# define some variables
rectangle1 = op( 'rectangle1' )

# That's great... but what about geometry?
# Let's take a closer look at SOPs

print( 'Like with a sop we can print the path to rectangle1 operator' )
print( rectangle1 )

print( 'We can also look at the member .points' )
print( rectangle1.points )

print( 'Seeing that it is an object by itself, means we can look closer' )
print( 'What happens if we just ask for the first item in this object?' )
print( rectangle1.points[ 0 ] )

print( 'What if we ask to make the whole object a list, and the print it out?' )
print( list( rectangle1.points ) )

While CHOPs and SOPs seem like obvious operators that might have lists, they’re certainly not the only ones. The method .findChildren returns a list of operators when dealing with COMPs. Let’s take a closer look at that while we’re at it. I started by making a container and adding three buttons inside. Make sure that you look at the example file to see what I’ve done to get started.

# define some variables
radio_buttons = op( 'container_radio_buttons' )

# Let's take a look at findChildren
# we can see all of the ops inside of our container with:
print( radio_buttons.findChildren() )

# What if we only wanted to see the buttons??
print( radio_buttons.findChildren( depth = 1 ) )

# That's fine as long as there aren't any other operators
# inside of our conatiner. If we wanted to make sure we only
# got a list of buttons, we could be even more specific with

print( radio_buttons.findChildren( type = buttonCOMP , depth = 1 ) )

# Okay... so?
# Well, what we get back is a list, so what if we did this?

print( radio_buttons.findChildren( type = buttonCOMP , depth = 1 )[ 0 ] )

# Maybe we don't want to see the whole path, we just want to see it's name
print( radio_buttons.findChildren( type = buttonCOMP , depth = 1 )[ 0 ].name )

# Or maybe just its digits
print( radio_buttons.findChildren( type = buttonCOMP , depth = 1 )[ 0 ].digits )

# We could even click on one of our buttons this way
radio_buttons.findChildren( type = buttonCOMP , depth = 1 )[ 0 ].click()

Lists are powerful and also flexible data structures. And this is only the start of what we can do with them. Practice making some lists, accessing their contents, and printing out pieces of them.

Learn more about data structures in Python

Download the sample files from github

Python in TouchDesigner | Variables | TouchDesigner

Core Concepts

  • Understanding variables in Python (different form what we mean with TouchDesigner variables)
  • Referencing by using variables in a script
  • simple scripting
  • simple preset recall


There are lots of resources on the web that describe variables better than I might:

The essential idea here, however, is that you have something that you want to reference by name. That something might be a sentence, it might be a quantity, it could be anything really. Again, it’s more important for us in this moment to consider that our something (whatever it is) happens to be a piece of information that we want re-use.

Let’s look at a dead simple example, to help us get started. If variables aren’t new to you feel free to skip ahead.

Let’s imagine you own a toy store. That toy store happens to sell marbles. That’s great, good for you – you’re a marvelous little capitalist. Now, let’s imagine that you want to do an inventory of all of your marbles. You have several different varieties of marbles, and you’d like to be able to think of them as different, while also having a total count. In this situation we might keep track of your marbles by using some variables:

red_marbles = 10
blue_marbles = 5
green_cat_eyes = 6
blue_cat_eyes = 12

Nice work. Now, we can print out each one of those, and get back our stored quantity. We could also do something like this:

total_marbles = red_marbles + blue_marbles + green_cat_eyes + blue_cat_eyes

Now we also know the total quantity of marbles. Super. Finally, we might want to see all of that. Let’s look at what that might look like:

print( "Currently in your inventory you have:" )
print( "%d red marbles" % red_marbles )
print( "%d blue marbles" % blue_marbles )
print( "%d green cat eye marbles" % green_cat_eyes )
print( "%d blue cat eye marbles" % blue_cat_eyes )
print( "-" * 10 )
print( "That makes for %d total marbles" % total_marbles )

That’s great, and hopefully you’re a careful shop keeper and you don’t loose any of your marbles… it was a long set-up for that bad joke.

What does this do for us here in TouchDesigner? When we’re scripting in Touch it’s often useful to be able to assign variables for all sorts of things. This especially useful when referencing operators.

Let’s quickly consider one example. We might, have a level TOP that we want to make changes to. Starting with a simple task, lets imagine we want to use a script to change the opacity of a level TOP to 0. We could easily write something like this to solve this need:

op( 'level1' ).par.opacity = 0

That’s short and simple and gets the job done. Love it. Now, let’s imagine a slightly more complicated world where I want to change lots of parameters for this operator. I want to change the invert, black level, brightness 1, gamma 1, contrast, and opacity. That’s great. Let’s write all of that out and see what we end up with:

op( 'level1' ).par.invert = 0.31
op( 'level1' ).par.blacklevel = 0.27
op( 'level1' ).par.brightness1 = 1.45
op( 'level1' ).par.gamma1 = 0.5
op( 'level1' ).par.contrast = 1.76
op( 'level1' ).par.opacity = 0.782

That’s not too bad, but we could make that a little less error prone if we were to simplify some of our script:

level = op( 'level1' )

level.par.invert = 0.31
level.par.blacklevel = 0.27
level.par.brightness1 = 1.45
level.par.gamma1 = 0.5
level.par.contrast = 1.76
level.par.opacity = 0.782

That’s pretty swanky, but let’s imagine a situation where I’ve made a table full of presets that I want to be able to reference. Let’s look at how we might tackle something like that:

# define our variables:
presets = op( 'table_presets' )
level = op( 'level1' )
row_ref = 'preset1'

# change some parameters
level.par.invert = presets[ row_ref , 'invert' ]
level.par.blacklevel = presets[ row_ref , 'blacklevel' ]
level.par.brightness1 = presets[ row_ref , 'brightness1' ]
level.par.gamma1 = presets[ row_ref , 'gamma1' ]
level.par.contrast = presets[ row_ref , 'contrast' ]
level.par.opacity = presets[ row_ref , 'opacity' ]

Okay… so what happened here? First we defined created a variable called “presets” that stands in for op( ‘table_presets’ ). We also made one called “level” and one called “row_ref”.

Next we wrote a generalized set of instructions to change some parameters using our variables. For the sake of seeing it all written out let’s look write it out long-form:

op( 'level1' ).par.invert = op( 'table_presets' )[ 'preset1' , 'invert' ]
op( 'level1' ).par.blacklevel = op( 'table_presets' )[ 'preset1' , 'blacklevel' ]
op( 'level1' ).par.brightness1 = op( 'table_presets' )[ 'preset1' , 'brightness1' ]
op( 'level1' ).par.gamma1 = op( 'table_presets' )[ 'preset1' , 'gamma1' ]
op( 'level1' ).par.contrast = op( 'table_presets' )[ 'preset1' , 'contrast' ]
op( 'level1' ).par.opacity = op( 'table_presets' )[ 'preset1' , 'opacity' ]

This works just the same… so why use variables. Well, in this case I used variables to keep my code a little more tidy. I also did this because it means I’m less likely to make an error if I’m using shorter names. Most importantly, we did this because we’ve now created a variable called row_ref. This means we can change how this script works, just by altering this single variable. Let’s say that we have two different presets. It would be far less fun to write the same set of scripts all over again just to reference a different preset. Instead, we can just change our variable to indicate which preset to use. That means that by making this single change:

row_ref = 'preset2'

We’ve actually made this change:

op( 'level1' ).par.invert = op( 'table_presets' )[ 'preset2' , 'invert' ]
op( 'level1' ).par.blacklevel = op( 'table_presets' )[ 'preset2' , 'blacklevel' ]
op( 'level1' ).par.brightness1 = op( 'table_presets' )[ 'preset2' , 'brightness1' ]
op( 'level1' ).par.gamma1 = op( 'table_presets' )[ 'preset2' , 'gamma1' ]
op( 'level1' ).par.contrast = op( 'table_presets' )[ 'preset2' , 'contrast' ]
op( 'level1' ).par.opacity = op( 'table_presets' )[ 'preset2' , 'opacity' ]

This is only the tip of the iceberg, but helps us see how useful using variables in Python can be.

Download the sample files from github

Python in TouchDesigner | Printing | TouchDesigner

Core Concepts

  • Using the text port
  • Running scripts
  • print()
  • strings, integers, floats, and booleans
  • printing and joining
  • simple substitution in strings


Printing out lines isn’t especially interesting on the face of it. That being said, this is one of the most powerful places to get your bearings. I almost always start any python related task by printing out bits of pieces of what I’m up to. It lets me see into the otherwise invisible process of code execution. Many folks will swear by this or that debugger, but at the end of the day your best debugging tool is just printing out what’s happening. Learning the ins and outs of printing will also transfer to a number of different bits and pieces along the way. We’ll start here as a way to get a solid handle on a few basic elements.

Download the sample files from github

Advanced Instancing | Puzzle Pieces | TouchDesigner

Part 1

Core Concepts

  • Instancing geometry
  • Replicators and Clones
  • The Sort SOP
  • Images composed out of component pieces
  • Real time rendering


Part 2

Core Concepts

  • Instanced geometry from pixel data
  • Texture Arrays – the 3D Texture TOP
  • The Sort SOP
  • Images composed out of component pieces
  • Real time rendering

Advanced Instancing | Instancing with the Animation COMP | TouchDesigner

Once upon a time this had an audio track, and then suddenly it didn’t. A fix coming by the end of the week. Sorry for the delay.

Core Concepts

  • Instancing geometry
  • Working with the Animation COMP
  • Building Animation Channels
  • The Shuffle CHOP
  • Real time rendering

Advanced Instancing | Pixel Mapping Geometry | TouchDesigner

Part 1

Core Concepts

  • Instancing geometry
  • Transferring data between operator types
  • Real time rendering


Part 2

Core Concepts

  • Instanced geometry from pixel data
  • Transferring data between operator types
  • Real time rendering


Part 3

Core Concepts

  • Spatial representations of time and images
  • Instanced geometry over time
  • Experiments in understanding depth
  • Real time rendering


Part 4

Core Concepts

  • Camera control
  • Spatial representations of time and images
  • Instanced geometry
  • Real time rendering


Download the Example Code from GitHub