TouchDesigner Python family別早見表

# この記事について
TouchDesignerでpythonを書こうとしたときの、「この値どうやって取得するんだっけ」をできる限りこの早見表で網羅したいという記事です。
過去にも早見表作ってくださっている方々はいらっしゃいますが、chopだけだったり基礎的なものだけだったり情報が散乱していたのでできるだけまとめました。
(そういって自分用がメイン)

細かい所やオペレータ毎のメソッドなどは公式のpythonヘルプを見たほうが早いです。

![Desktop Screenshot 2025.02.09 - 03.08.11.79.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480518/008b8f94-3c81-2cca-cb60-bfe39b746b3c.png)

## BASIC
#### パラメータ取得系
| script | 用途 |
|:-:|:-:|
| op('xxx').par.yyy  | オペレータのパラメータの値を取得|
| me.op('xxx').par.yyy  | 子オペレータのパラメータの値を取得(compのみ)|
| op('xxx')['chan1']  | オペレータのチャンネルの値の取得  |
| op('xxx')[0]  |オペレータの配列0番目の値を取得  |
| op('xxx').name  |  オペレータの名前 | 
|  op('xxx').digits |  オペレータ名の末尾の数字取得(ex. constant5 → 5) |  
|  op('xxx').base |  オペレータ名の末尾の数字以外取得(ex. null5 → null) |     
|  op('xxx').inputVal |  オペレータ自身に送られてくる値の取得 |   
| op('xxx').path  |  パスの取得 |   
| root.children  |  ルートの子要素をリストで取得 |  
|len(op('geo1').children)  |  オペレータの子要素数を取得 |   
|len(op('xxx').inputs)  |  オペレータのインプット数を取得 |   
| root.children  |  ルートの子要素をリストで取得 |   
| op('xxx').parent()  | 一個上の親(parent(n)でn階層上の親)  |   
| op('xxx').family  | オペレータの種類(TOP, CHOP, DAT...)  |   
| op('xxx').isTOP  |  オペレータがTOPかどうか(CHOP, DAT, MAT...も有効) |   
|absTime.seconds | 時間取得(秒) (独立) |   
|me.time.seconds | 時間取得(秒) (タイムライン依存) |
|absTime.frame | 時間取得(フレーム) (独立) |  
| me.time.frame |時間取得(フレーム) (タイムライン依存)  |  
|tdu.rand(n)	|ランダムシード(nはシード値)|
 
#### オペレータ自体を編集する系
| script | 用途 |
|:-:|:-:|
| op('/xxx').create(textDAT)  | xxx内にオペレータを作る  |
| op('/xxx').create(textDAT, 'yyy')  | yyyという名前をつける  |
| op('/xxx').copy('/project1/noise1')  | オペレータのコピー |
| op('xxx').changeType(addTOP)  | オペレータタイプの変更  |
|op('xxx').destroy()   | ノードを消す  |
| op('timer1').par.start.pulse()  |  pulseさせる |
|op('xxx').cook()   | オペレータを実行させる  |
|  op('comp1').allowCooking = 1 | オペレータを実行させる（comp）  |
| op('xxx').bypass = 1  |  オペレータをbypassにする |
|  op('xxx').outputConnectors[0].connect(op('yyy')) | ノード同士の接続  |
| op('xxx').outputConnectors[0].connect(op('yyy').inputConnectors[0])  | 接続先が複数の場合  |
| op('xxx').inputConnectors[0].disconnect()  | 接続解除  |
| op('xxx').par.yyy.mode = ParMode.EXPRESSION  | パラメータモードの変更  |
| op('xxx').par.yyy.expr = 'absTime.frame'  |  エクスプレッションにstr型をいれる |
| op('xxx').par.yyy.bindExpr = "op('zzz').par.aaa"  | bindするパラメータを指定  |
| me.time.play = True/False  | タイムラインの再生停止  |
| op('xxx').nodeX  | ノードのx座標取得  |
| op('xxx').nodeY  |  ノードのy座標取得 |

## TOP
| script | 用途 |
|:-:|:-:|
| op('moviefilein1').width  | TOPの横サイズ  |
|  op('moviefilein1').height | TOPの縦サイズ  |
| op('moviefilein1').save('image1.png')  | 画像を保存  |
|  op('moviefilein1').sample(x=0,y=0)[0] | ピクセル(0, 0)のR値を取得 ((u=0.5,v=0.5)で中心)  |
| op('moviefilein1').sample(x=0,y=0)[1]  | ピクセル(0, 0)のG値を取得 ((u=0.5,v=0.5)で中心)  |
| op('moviefilein1').sample(x=0,y=0)[2]  |ピクセル(0, 0)のB値を取得 ((u=0.5,v=0.5)で中心)   |

## CHOP
| script | 用途 |
|:-:|:-:|
| op('noise1')['chan1'].eval()  |  今のフレームの値を取得する |
| op('noise1')['chan1'].eval(n)  |  nサンプル目の値を取得する |
| op('noise1')[n]  |  n番目のチャンネルの値 |
| op('noise1').chan(n)  | 上と同じ  |
|op('noise1')[0][n]|0からn番目のチャンネルを取得|
|  op('noise1').chan('abc*') |  文字列と一致する名前の一番最初のチャンネルの値 |
| op('noise1').chans()  | 全チャンネルの情報を取得  |
| op('noise1').numpyArray()  | 全チャンネルの全サンプルをNumPy配列で取得  |
| op('noise1')[1].name  | チャンネルの名前  |
| op('noise1').numSamples  | サンプル数の取得  |
| op('noise1').numChans  | チャンネル数の取得  |
| op('noise1')['chan1'].vals  | 1チャンネルのサンプルごとの値を配列で取得  |

## SOP
| script | 用途 |
|:-:|:-:|
| op('box1').points[0]  |  ポイント数取得 |
| len(op('box1').points)  | 上に同じ  |
| op('box1').numVertices  | 頂点数取得  |
| op('box1').points[n]  | n番目のポイントの位置取得  |
|op('box1').pointAttribs   | アトリビュート  |
|op('box1').render = 1| レンダーさせる  |

## DAT
| script | 用途 |
|:-:|:-:|
| op('table1')[1,2]  | Tableのセルをインデックスで取得  |
| op('table1')['a1', 'b1']  | Tableのセルをラベルで取得  |
|  op('table1').numRows |  Tableの行数取得 |
|  op('table1').numCols | Tableの列数取得  |
|op('table1')[3,4] = 'hello'|セルに文字列を入れる|
| op('table1').appendRow([1,2,3], 5)  | 5行目の後に1, 2, 3を追加  |
|  op('table1').appendCol([1,2,3], 5) | 5列目の後に1, 2, 3を追加  |
| op('table1').insertRow([1,2,3], 5)  |  5行目の前 |
| op('table1').insertCol([1,2,3], 5)  |  5列目の前 |
|op('table1').clear()   |  テーブル消去 |
|op('table1').copy(op('Table2'))|テーブルを他のテーブルにコピーする|
| op('table1').replaceRow(n)  | n行目の全セルを空にする  |
| op('table1').replaceCol(n)  |  n列目の全セルを空にする |
|op('table1').replaceRow('a', [1,2,3])   | aの行を1,2,3に置き換える  |
|op('table1').replaceCol('a', [1,2,3])   | aの列を1,2,3に置き換える  |
| op('table1').deleteRow(名前かindex)  | 指定した行を消去（複数の場合([x, y, z, ...])）  |
| op('table1').deleteCol(名前かindex)  | 指定した列を消去（複数の場合([x, y, z, ...])）  |
| me.inputCell.val  | セルの値を引き継ぐ  |
| op('table1').isEditable  | 編集可能かどうか  |

## COMP
| script | 用途 |
|:-:|:-:|
| op('comp1').allowCooking = 1  | 実行させる  |
|op('base1').outputCOMPConnectors[0].connect(op('base2').inputConnectors[0])   | compの接続  |

##  python使えるところは使おうのコーナー
わざわざノード使わなくてもpythonの力で楽できそうなコマンドコーナー

### math
エクスプレッションになら一行だけ使えます
| script | 用途 |
|:-:|:-:|
| math.ceil(x)  | 切り上げ  |
| math.floor(x)  |  切り捨て |
|  math.fabs(x) |  絶対値 |
| math.factorial(x)  | 階乗  |
| math.fmod(x, y)  | x/yの剰余  |
| math.exp(x)  | eのべき乗  |
| math.sqrt(x)  |  平方根 |
|math.sin(x) | サイン |  
|math.cos(x) | コサイン |  

など

### tdu module
TouchDesignerにはtdu moduleと呼ばれるあらかじめ用意されてるものがあります。
その一部を載せます。
見やすいように `Value = op('xxx').par.yyy` として表記します。
| script | 用途|
|:-:|:-:|
| tdu.rand(n)  |  ランダムシード(nはシード値) |
| tdu.clamp(Value, min , max)  | minからmaxの間に値を収める  |
| tdu.remap(Value, fromMin, fromMax, toMin, toMax)  | 値をtoMinからtoMaxにリマップする |
| tdu.base(str)  | str型の文字列の数字部分を取り除く  |
| tdu.digits(str)  | str型の文字列の数字部分を取り出す  |
| tdu.expand('A[1-3] B[xyz]')  | ['A1', 'A2', 'A3', 'Bx', 'By', 'Bz']になる  |
| tdu.match('abc*', ['abc', 'def'])  | aaaとマッチした文字列をリストで取得/ワイルドカード対応/ab?でも取得できる  |

詳細や他のモジュールは公式から↓

https://docs.derivative.ca/Tdu_Module


### f-strings
**※注意：f"{}"とop('xxx')のクォートがかぶるとエラーになるため" "か' 'で分ける。**
出力は文字列なのでそれも注意
| script | 用途 |例 |
|:-:|:-:|:-:|
| f"{x:.0f}"  |float xの有効数字指定（{x:.2f}だと小数点2桁）   |f"{op('null1')['chan1'].eval():.0f}"|
|  f"{x:.0%}"  |float xのパーセント表示（{x:.2%}だと小数点2桁）  |上と同じ感じ|
| f"{x:05}"  | ゼロ埋め  |f"{op('null1')['chan1'].eval():05}"|

などなど

### 他
| script | 用途 |例 |
|:-:|:-:|:-:|
| int(x)  | int型にする（切り捨て）  |int(op('null1')['chan1'])|
| float(x)  | float型にする  ||
| str(x)  |  string型にする ||
| round(x, 3)  | float xの有効数字指定(fstringと同じ)(float型)  | round(op('null1')['chan1'], 3)|
| max(x)  | リストの最大値を取得  | max(op('noise1')['chan1'].vals)|
| min(x)  | リストの最小値を取得  | min(op('noise1')['chan1'].vals)|
| sum(x)  | リストの合計値を取得  | sum(op('noise1')['chan1'].vals)|
| string.upper()  | 全部大文字にする  | op('table1').name.upper()|
| string.lower()  | 全部小文字にする  ||
|string.capitalize()   | 先頭の一文字を大文字  ||

などなど

## サードパーティー製のパッケージ
以下のようなパッケージは最初からTouchDesignerにインストールされています。
なので`import cv2`のような形で使えます。

**・openCV**
**・NumPy**
**・pip**
**・jsonpath**

などなど...

一覧はこのサイトの下の方にあります↓

https://docs.derivative.ca/Python_Classes_and_Modules

## Reference
https://docs.derivative.ca/Python_Classes_and_Modules

https://docs.derivative.ca/Tdu_Module

https://docs.derivative.ca/Python_Tips

https://derivative.ca/UserGuide/Optimized_Python_Expressions

https://qiita.com/freeman/items/f0038df7b3cdffcf3925

https://interactiveimmersive.io/blog/python/python-cheat-sheet-for-touchdesigner-developers/

## 最後に
どこか間違えてるとかこれが入ってないとかこれ便利とかあればぜひコメントして下さい