TouchDesigner | Getting More out of the CHOP Execute DAT

One of the most challenging elements for me to wrap my heard around when using TouchDesigner was the Execute DATs. When scripting was still new to me, it was hard to understand where to start, or what to write. It was also hard to understand what kind of options I had when dealing with the execute family of DATs. Let’s take a closer look at some of the interesting elements that you can extract from a CHOP Execute DAT, and hopefully learn a few things along the way.

CHOP Execute DATs allow us to run a script at particular events. The functions that you see in the CHOP Execute specify what kind of event, and what kind of information gets passed into those events that you might take advantage of. Looking at the CHOP Execute DAT we can see the following kinds of events that we might want to take advantage of:

Off to On

While On

On to Off

While Off

Value Change

That’s all well and good, but what do those things actually mean? Let’s create a simple script to see what we end up with. We’ll work mostly with the Off to On Definition – with what we learn here you can start to explore what the other definitions do (when I say definitions, I’m mean the portions of the Execute DAT that begin with def).

Before we can get started we need a CHOP in our network to associate with our CHOP Execute DAT. Let’s add an LFO CHOP, and a CHOP Execute DAT to our network.

Next we need to associate our CHOP with our DAT. We can do this by dragging the LFO CHOP onto the CHOP Execute DAT.

Next we need to make sure that in the parameters of our Execute DAT that the flag which corresponds to our definition is turned on.

With my default values, I can see that something isn’t quite right. Here my “Value Change” Flag is turned on, I want to turn off that flag and turn on the Off to On Flag. The parameters for your CHOP Execute should now look like this:

Alright, now that we’re just about set up let’s see what happens when we write some scripts for our Execute DAT. The simplest place for us to start might be to just print a string. Let’s add this line to inside of our definition:

print('Hello World')

Because this is inside of a defined function, we’ll also need to make sure that it’s indented. The whole function should look like this in your DAT:

That’s all well and good, but what does that do? Well, if we open up our text port we should see that ever time we cross the 0 threshold in our LFO that we print “Hello World” to the text port.

That in itself isn’t very excited, but we might imagine a situation where we want to run a script at a given regular interval, and this is exactly the kind of technique we might use to make that happen. You might also notice that there are several other parameters for this function that we might be interested in.

Before we get in too deep, lets remember to read what’s already in our DAT. We can see that the header comment reads:

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

In general I like to think about any scripting with the following kind of mantra – “When in Doubt, Print it Out.” With that in mind, let’s just print out these parameters to see what they are. To do that, we’ll change our function to read like the following:

This should give us a sense of the kinds of information that we can pull out of our Panel Execute DAT. Before we stop, let’s push a little harder on one of these ideas. First we need to make some changes to our LFO. Let’s first use some pattern matching to add some more channels. We can do this on the Channel Page of our CHOP by specifying that our Channel Names should be chan[1-5]:

Next, lets give these unique all a unique phase with the following python expression:

me.chanIndex/me.numChans

Alright, now we should have an LFO that looks something like this:

Let’s change up our Execute DAT to see what kinds of interesting information we might be able to extract from this. First let’s just see if we can retrieve the channel index as our wave passes through zero. We can do this by changing our function to read:

That’s pretty interesting, but what if we only want to print out a line of text when a certain set of conditions are met? We might imagine a scenery where we want to first match a logical test, then run a script.

Let’s try writing something like this:

def offToOn(channel, sampleIndex, val, prev):
if channel.index == 0:
print('This will only appear when index 0 fires')
if channel.index == 1:
print('This will only appear when index 1 fires')
if channel.index == 2:
print('This will only appear when index 2 fires')
if channel.index == 3:
print('This will only appear when index 3 fires')
if channel.index == 4:
print('This will only appear when index 4 fires')
return

We’ve now set up a series of tests where we’ll only see a particular line of text when the if conditions are met. As a result we should see this in the text port:

This may initially seem unimpressive, but when you begin to imagine how you might combine the power of CHOPs with the extensible nature of scripting you soon end up with a world of options that wasn’t present before.