Houdini 18.5 PDG/TOPsを使ってタスクを実行する方法

プロセッサ系ノードコールバック

プロセッサ系ノードはスケジューラで実行可能なワークアイテムを生成します。

On this page

概要

プロセッサは、PDGグラフで主なタイプのノードの1つです。 各プロセッサ系ノードは、上流の入力ワークアイテム、そのノード自体のパラメータ、外部リソースを使って新しいワークアイテムを生成することができます。 このノードは、ワークアイテムにアトリビュート値を設定し、そのワークアイテム用のコマンドラインを設定し、そのワークアイテムを子プロセスで評価するのか現行Houdiniセッションで評価するのか定義することができます。 MergeTOPとAttribute CreateTOPは、アトリビュート値を持ったワークアイテムを作成する単純なプロセッサであるのに対して、 ROP Fetchは実行するのにスケジュールを組む必要があるワークアイテムを作成するもっと複雑なプロセッサです。

どのプロセッサ系ノードも静的または動的のどちらにも対応しており、これによってプロセッサがワークアイテムを生成するタイミングが決まります。 静的プロセッサは、PDGグラフクックの前に実行される静的プリパス中にワークアイテムを生成します。 動的プロセッサは、入力ノード内のワークアイテムがクックする度に1つ以上のワークアイテムを生成します。 この挙動は、どのプロセッサ系ノードにもある Work Item Generation パラメータを使って設定することができます。 プロセッサ系ノードのインスタンスは、そのパラメータに基づいて、どちらかのタイプのワークアイテムのみを生成します。 プロセッサは、同時に静的ワークアイテムと動的ワークアイテムを混在させることができません。

カスタムノードの登録

カスタムプロセッサノードは、PDG Type Registryを介して登録することができます。 これは、必要に応じてPython Shellから行なうことができたり、または、登録スクリプトを$HOUDINI_PATH/pdg/typesディレクトリ下に追加することで行なうことができます。 Houdiniを起動すると、PDGは、Houdini検索パス上で見つかったpdg/typesディレクトリからすべてのスクリプトとモジュールを自動的に読み込みます。 例えば、カスタムノードクラスを定義するスクリプトを作成し、それを$HOME/houdini18.0/pdg/types/mynode.pyとして保存することができます。 ノード定義だけでなく、さらにそのスクリプトファイル内にregisterTypes関数を定義する必要があります。 この関数は、PDGがそのスクリプトを読み込んだ時に自動的にコールされ、その.pyファイルで定義されているノード(s)を登録する役割を担っています。例:

import pdg
from pdg.processor import PyProcessor

# カスタムノード定義
class CustomProcessor(PyProcessor):
    def __init__(self, node):
        PyProcessor.__init__(self, node)

    # パラメータテンプレート名
    @classmethod
    def templateName(cls):
        return "customprocessor"

    # パラメータテンプレート定義
    @classmethod
    def templateBody(cls):
        return json.dumps({
            "name": "customprocessor",
            "outputPorts" : [
                {
                    "name" : "output"
                }
            ],
            "parameters" : [
                {
                    "name" : "customparm",
                    "type" : "Integer",
                    "value" : 1,
                    "label" : "Custom Parameter"
                }
            ]})

    # ノードコールバック実装は、このクラスのメンバー関数として定義してください。


# スタンドアローンのregisterTypes関数を使用して、カスタムノードをPDGに登録します。
def registerTypes(type_registry):
    type_registry.registerNode(CustomProcessor, pdg.nodeType.Processor,
        name="customprocessor", label="Custom Processor", category="Custom")

登録系メソッド、ノード定義の照会やアクセスするための他のメソッドのさらなる詳細は、pdg.TypeRegistryクラスを参照してください。

ノードコールバック

各プロセッサ系ノードには、その挙動を制御するために実装可能なコールバックがいくつか備わっています。 プロセッサ系ノードでコールバックを記述する時に実装で必須となる唯一のコールバックがonGenerateです。このフックが実際にワークアイテムを生成する役割を担っています。 ワークアイテムが In Process としてマークされた際にそのワークアイテムをクックするのに使用されるロジックを用意したいのであれば、onCookTaskコールバックを実装する必要があります。 ワークアイテムを構築する時にinProcessキーワード引数をTrueに設定すると、そのワークアイテムがIn Processとしてマークされます。 他のすべてのノードコールバックは任意であり、そのノードの挙動をさらにカスタマイズしたい場合にのみ使用します。

コールバックは、それが成功したのか失敗したのかを示したpdg.resultを返すことができます。 pdg.result.Allなどの他の特別な結果タイプは、プロセッサ系ノードでは使用しません。 1つ以上のプロセッサ系ノードが静的ワークアイテム生成パス中に失敗を返したら、そのクックは停止されます。 動的プロセッサの場合、失敗してもクックは停止されず、別の上流ワークアイテムの他のonGenerateコールによって生成されたワークアイテムが実行を継続します。

Warning

PDGは、コールバックの入力として渡されたワークアイテムのアトリビュートが、そのコールバック中に安全に読み込めるようにします。 また、コールバック中に生成されたすべてのワークアイテムを安全に読み書きします。 ただし、ノード上のメンバー変数にワークアイテムを格納することも、上流のワークアイテムにアトリビュートを書き出すこともできません。

どれかのTaskコールバックが実行されている間、Pythonコードは、その関数に直接渡されたワークアイテムのアトリビュートにのみアクセスすることができます。 このコールバックコードは、そのワークアイテムのアトリビュートを読み書きしたり、出力ファイルを追加することができます。 このコールバックコードは、そのワークアイテムの親または依存関係から自由にアトリビュートを読み込むこともできますが、そのノード内の他のワークアイテムにはアクセスしないでください。

onGenerate(item_holder, upstream_items, generation_type)pdg.result

このコールバックは、プロセッサ系ノードが新しいワークアイテムを生成する度に評価されます。 pdg.WorkItemHolder引数は、そのノード内で新しいワークアイテムを生成する際に使用されるファクトリーオブジェクトです。 コールバックが成功を返さない限り、そのワークアイテムはそのプロセッサ系ノードまたはPDGグラフに追加されません。 このコールバックが失敗すると、コールバックの途中まで評価されて生成されたすべてのものが削除されます。

addWorkItemメソッドを使用すると、ワークアイテムをホルダーに追加することができます。このメソッドには、キーワード引数のリストまたはpdg.WorkItemOptionsヘルパーオブジェクトを渡すことができます。 これらの引数は、ネットワークアイテムの名前、インデックス、タイプを設定する際に使用されます。 pdg.WorkItemOptions APIドキュメントに載っている各エントリーも同じ名前を使ってキーワード引数として渡すことができます:

# オプションの使い方:
options = pdg.WorkItemOptions()
options.name = "example"
options.inProcess = True
item_holder.addWorkItem(options)

# kwargsの使い方:
item_holder.addWorkItem(name="example", inProcess=True)

addWorkItemメソッドは、新しいワークアイテムを返すので、コールバックコードでアトリビュート値またはワークアイテムのコマンドラインを設定することができます:

new_item = item_holder.addWorkItem()
new_item.setStringAttrib('example_attrib', 'example value')
new_item.setCommand('echo "hello"')

ノードに何も入力がなかった場合、コールバックに渡される上流ワークアイテムのリストには、何のワークアイテムも入りません。 ノードに入力ノードがあった場合、そのノードが動的であればそのリストには1個のワークアイテムが、静的であればそのリストには上流ワークアイテムの全リストが入ります。 最後に、generation_type引数は、ワークアイテムを生成する際に、そのコールバックを静的ノードまたは動的ノードのどちらに対してコールするのかを決めます。 pdg.generationTypeは、そのコールバック関数に渡された列挙の詳細をリストします。

onRegenerate(item_holder, existing_items, upstream_items)pdg.result

このコールバックは、ノードが既存のワークアイテムを持っていて、且つ、最後のクックからパラメータに変更があった時にクックプロセス中にコールされます。 このコールバックによって、ノードがワークアイテムをDirty(変更あり)、削除、修正したり、新しいワークアイテムを追加する機会が得られます。 デフォルトでは、どのノードもonGenerateフックのコールによってワークアイテムを再生成してマージする標準ビルトインの実装を持っています。 再生成されたワークアイテムは必ずしもDirty(変更あり)とは限りません。 ワークアイテムのアトリビュートがどれも変更されていなければ、そのワークアイテムは再生成される前と同じ状態のままです。 このコールバック関数の引数はonGenerateと同様ですが、追加のexisting_itemsリストには、ノード内の既存の静的ワークアイテムのリストを格納します。 generate_type引数にはpdg.generationType列挙の値を設定します。 あなたのコードでその値を使用することで、ノードが動的なのか静的なのか判断することができます。

通常では、あなたのノードが外部リソースを使ってワークアイテムを生成している場合にのみこのコールバックを実装する必要があります。 例えば、HTTPリクエスト、外部データベース、ディスク上のファイルを介してリソースを照会してワークアイテムを生成している場合です。 別の方法では、あなたのノードがクックの度に常にワークアイテムを再生成するように試みたいのであれば、onConfigureNodeノードコールバックを使用することでisAlwaysRegenerateフラグを設定することができます。 あなたのノードにonRegenerate実装がなくてもPDGは再生成ロジックを実行します。 つまり、PDGは必要に応じてビルトインの実装を代用します。 これは、追跡するのが困難な外部リソースを扱う時、または、単にそのようなリソースを制御する独自コードを記述したくない時に役立ちます。 例えば、File Patternノードはクックの度に常にファイルシステムからワークアイテムを再生成します。

Note

このコールバックは、以前のバージョンのHoudiniの古いonRegenerateStaticメソッドとonRegenerateChildrenメソッドを置換します。 静的ワークアイテム再生成も動的ワークアイテム再生成も今では、静的生成や動的生成とまったく同様に同じコールバックを使用します。 あなたのノードにそれらの古いコールバックがどれか含まれていて、新しいonRegenerateコールバックがなかった場合、PDGはその古いメソッドを使用し、廃止された旨の警告を出します。

onAddInternalDependencies(dependency_holder, work_items, is_static)pdg.result

このメソッドは、onGenerateコールバック時に生成されたワークアイテム間に兄弟/内部依存関係を追加する時にコールします。 これらは、同じノード内のワークアイテム間に存在する依存関係です。 このコールバックの入力は、最後のonGenerateコールバックで生成されたワークアイテムのリストです。

Note

内部依存関係は、同じonGenerateコールで生成されたワークアイテム間にのみ追加することができます。 is_staticブールは、その入力ワークアイテムが静的または動的のどちらで生成されたのかを示します。

PDGは、これらの依存関係すべてがクックされた時にのみワークアイテムをクックするので、あなたのノードが特定の順番で完了させる必要のあるワークアイテムを生成する場合には、内部依存関係の追加が役に立ちます。 例えば、フィードバックループブロックの開始ノードは、ループ内の反復間で内部依存関係を追加します。

onPreCook()pdg.result

このコールバックは、クック中に評価されるすべてのノードに対して、そのクックの開始時点で1度コールされます。 このコールバックは、onGenerateコールバックの前にコールされ、そのノードが共有リソースを読み込んだり、変数を初期化する機会が得られます。

onPostCook()pdg.result

このコールバックは、最後のワークアイテムがクックを完了した後に、クック中にアクティブだったすべてのノードに対して1度コールされます。 このコールバックによって、ノードがクック中に使用した共有リソースをアンロードする機会が得られます。

onPrepareTask(work_item)pdg.result

このコールバックは、そのノード内の各ワークアイテムがクックのスケジュールに組まれる直前に1度コールされます。 このメソッドは、PDGがディスク上のキャッシュファイルをチェックする前にコールされるので、キャッシュ化の用途で必要な出力ファイルを追加する手段として使用することができます。 他にも、出力ファイルやワークアイテムの依存関係のアトリビュートにアクセスしたり、ワークアイテムのコマンドラインを変更したり、ワークアイテムをクックする直前に必要な処理を行う時にも使用することができます。 このメソッドがpdg.result.Failureを返すと、そのワークアイテムは失敗としてマークされます。

ROP Fetchノードは、分散シミュレーションを走らせる際にこのコールバックを使用することで、sim trackerが起動していることを確認し、シミュレーションワークアイテムをクックする前にトラッカー情報をそのシミュレーションワークアイテムに渡します。 ROP Fetch内のワークアイテムは、静的ワークアイテムとして生成することができ、クックを開始するまではsim trackerのポート/IPが分からないので、 このコールバックを使用して、シミュレーションワークアイテムにそのトラッカーの詳細を追加します。

onPrepareTaskコールバックは、バッチワークアイテム自体だけでなく、そのバッチ内のサブワークアイテム毎にコールされます。 コールバック呼び出しの順序は、バッチワークアイテムのアクティベーションモードによって異なります。 バッチのアクティベーションモードがpdg.batchActivation.Allに設定されていれば、PDGは、バッチの実行をするスケジュールが組まれる直前に、サブワークアイテム毎にonPrepareTaskフックを実行してから、そのバッチワークアイテム自体にonPrepareTaskフックを実行します。 アクティベーションモードが他のオプションのどれかに設定されていれば、このコールバックは、サブワークアイテム毎にそのサブワークアイテムの依存関係がすべて完了した後でコールされます。 このコールバックは、バッチの実行準備が整った時にバッチワークアイテム自体に対して実行されます。 つまり、バッチがpdg.batchActivation.Firstに設定されていると、onPrepareTaskコールの順序に保証がありません。 このコールバックは、サブワークアイテムのコール間でバッチワークアイテムに対してコールすることもできます。

onCookTask(work_item)pdg.result

このコールバックは、In-Processワークアイテムがクックを必要とした時にコールされます。 これは、In-Processワークアイテムとして明示的に生成されたワークアイテムに対してのみ実行されます。 In-Processワークアイテムは、onGenerateコールバック時にinProcess=True`引数を渡してワークアイテムをワークアイテムホルダに追加することで生成されます。 このコールバックは、ワークアイテムをクックする上で必要となるIn-Processロジックを実行するだけでなく、ワークアイテムにアトリビュートを書き出したり、出力結果を取り付けることもできます。 このコールバックは、メインHoudiniプロセス内でバックグラウンドスレッド上で実行されます。

Python Scriptノードは、 Evaluate In Process が有効に設定されていると、このコールバックを使ってスクリプトを実行します。

onPostCookTask(work_item)pdg.result

このコールバックは、ワークアイテムがクックに成功した時、且つ、下流ノードがそのワークアイテムから何かを生成する前にコールされます。 これを使用することで、そのワークアイテムの出力ファイルまたはアトリビュートを検証したり、クック中に生成された出力ファイルに基づいてアトリビュートに変更を加えることができます。 このコールバックは、そのワークアイテムがIn-Processでクックされていなかった場合でも実行されます。 このコールバックがpdg.result.Failureを返すと、そのワークアイテムは失敗としてマークされます。

このコールバックは、pdg.WorkItem.setIsPostCookメソッドを使ってポストクックロジックを実行する必要性があるものとしてワークアイテムがマークされた場合にのみコールされます。

onSelectTask(work_item)pdg.result

これは、TOPs用途特有のUIコールバックです。 TOPs UI内でワークアイテムを選択する時、ワークアイテムが選択された後でこのフックが実行されます。 例えば、これをWedgeノードで使用することで、ワークアイテムパラメータ値をシーンに出すことができます。 他にも、独自の視覚化ロジックを実行することができます。

Note

ワークアイテム選択用のイベントフックもあります。 詳細は、pdg.EventTypeイベントタイプリストとイベントハンドリングの概要を参照してください。

onDeselectTask(work_item)pdg.result

このコールバックは、onSelectコールバックの反対です。 TOPs UIでワークアイテムが選択解除される度に実行されます。 例えば、Wedgeノードは、このコールバックを使用して、選択解除時にパラメータ値を元の値に復元します。

onConfigureNode(node_options)pdg.result

現在のパラメータに基づいてノードインスタンスの構成を表現するのに使用可能なpdg.NodeOptionsオブジェクトを使って呼び出します。 ノードに関するテキストの説明を設定したり、ノードがワークアイテムを生成する条件としてすべての入力ノードが生成されていることを必須にするのかどうかを設定することができます。 これは、 Generate WhenAutomatic に設定されている時のその挙動に影響します。 ノードがすべての入力ノードが生成されていることを必須にした場合、Automaticパラメータは常に All Upstream Items are Generated を意味します。

例えば、ROP Fetchノードは、バッチを作成する際に上流のワークアイテムの全リストにアクセスできる必要があります。 ROP Fetchノードがバッチモードの時、そのROP FetchノードはonConfigureNodeメソッドを使用して、その Automatic 生成オプションが常に All Upstream Items are Generated を意味することをPDGに伝えます。

def onConfigureNode(self, node_options):
    if self['batch'].evaluate() > 0:
        node_option.setRequiresGeneratedInputs(True)
    else
        node_option.setRequiresGeneratedInputs(False)

    node_options.setDescription("Node: " + self['targetnode'])

PDG/TOPsを使ってタスクを実行する方法

基本

初心者向けチュートリアル

次のステップ

リファレンス