OGN Reference Guide

This is a detailed guide to the syntax of the .ogn file. All of the keywords supported are described in detail, and a simplified JSON schema file is provided for reference.

Each of the described elements contains an example of its use in a .ogn file to illustrate the syntax. For a more detailed guide on how each of the elements are used see the OGN User Guide.

Node Level Keywords

Attribute Level Keywords

description

description

exclude

default

icon

memoryType

memoryType

metadata

cudaPointers

maximum

metadata

minimum

singleton

optional

tags

type

tokens

uiName

uiName

unvalidated

version

language

scheduling


Basic Structure

See the OmniGraph Naming Conventions for guidance on how to name your files, nodes, and attributes.

{
    "NodeName": {
        "NODE_PROPERTY": "NODE_PROPERTY_VALUE",
        "inputs": "ATTRIBUTE_DICTIONARY",
        "outputs": "ATTRIBUTE_DICTIONARY",
        "state": "ATTRIBUTE_DICTIONARY",
        "tests": "TEST_DATA"
    }
}

The NODE_PROPERTY values are keywords recognized at the node level. The values in NODE_PROPERTY_VALUE will vary based on the specific keyword to which they pertain.

The ATTRIBUTE_DICTIONARY sections contain all of the information required to define the subset of attributes, each containing a set of Attribute Property Keywords that describe the attribute.

Lastly the TEST_DATA section contains information required to construct one or more Python tests that exercise the basic node operation.

Comments

JSON files do not have a syntax for adding comments, however in order to allow for adding descriptions or disabled values to a .ogn file the leading character “$” will treat the key in any key/value pair as a comment. So while "description":"Hello" will be treated as a value to be added to the node definition, "$description":"Hello" will be ignored and not parsed.

Comments can appear pretty much anywhere in your file. They are used extensively in the omni.graph.tutorials: OmniGraph Walkthrough Tutorials to describe the file contents.

{
    "Node": {
        "$comment": "This node is like a box of chocolates - you never know what you're gonna get",
        "description": [

Node Property Keywords

These are the elements that can appear in the NODE_PROPERTY section. The values they describe pertain to the node type as a whole.

description

The description key value is required on all nodes and will be used in the generated documentation of the node. You can embed reStructuredText code in the string to be rendered in the final node documentation, though it will appear as-is in internal documentation such as Python docstrings.

The value can be a string or a list of strings. If it is a list, they will be concatenated as appropriate in the locations they are used. (Linefeeds preserved in Python docstrings, turned into a single space for text documentation, prepended with comment directives in code…)

Tip

This mandatory string should inform users exactly what function the node performs, as concisely as possible.

{
    "Node": {
        "$comment": "This node is like a box of chocolates - you never know what you're gonna get",
        "description": [
            "This node is part of the OmniGraph node writing examples.",
            "It is structured to include node and attribute information illustrating the .ogn format"
        ],
        "version": 1,

version

The integer value version defines the version number of the current node definition. It is up to the node writer how to manage the encoding of version levels in the integer value. (For example a node might encode a major version of 3, a minor version of 6, and a patch version of 12 in two digit groups as the integer 30612, or it might simply use monotonic increasing values for versions 1, 2, 3…)

Tip

This mandatory value can be anything but by convention should start at 1.

        "description": [
            "This node is part of the OmniGraph node writing examples.",
            "It is structured to include node and attribute information illustrating the .ogn format"
        ],
        "version": 1,
        "exclude": ["c++", "docs", "icon", "python", "template", "tests", "usd"],

exclude

Some node types will not be interested in all generated files, e.g. if the node is a Python node it will not need the C++ interface. Any of the generated files can be skipped by including it in a list of strings whose key is exclude. Here is a node which excludes all generated output, something you might do if you are developing the description of a new node and just want the node syntax to validate without generating code.

Legal values to include in the exclusion list are “c++”, “docs”, “icon”, “python”, “template”, “tests”, or “usd”, in any combination.

Note

C++ is automatically excluded when the implementation language is Python, however when the implementation language is C++ there will still be a Python interface class generated for convenience. It will have less functionality than for nodes implemented in Python and is mainly intended to provide an easy interface to the node from Python scripts.

        "version": 1,
        "exclude": ["c++", "docs", "icon", "python", "template", "tests", "usd"],
        "language": "python",

icon

A string value that represents the path, relative to the .ogn file, of the icon file that represents the node. This icon should be a square SVG file. If not specified then it will default to the file with the same name as the .ogn file with the .svg extension (e.g. OgnMyNode.ogn looks for the file OgnMyNode.svg). When no icon file exists the UI can choose a default for it. The icon will be installed into the extension’s generated ogn/ directory

        },
        "tokens": { "apple": "Granny Smith", "pear": "Bosc Pear", "orange": "Florida Navel Orange"},
        "uiName": "OmniGraph Example Node"

The extended syntax for the icon description adds the ability to specify custom coloring. Instead of just a string path, the icon is represented by a dictionary of icon properties. Allowed values are “path”, the icon location as with the simple syntax, “color”, a color representation for the draw part of the icon’s shape, “backgroundColor”, a color representation for the part of the icon not containing its shape, and “borderColor”, a color representation for the outline of the icon.

Colors are represented in one of two ways - as hexadecimal in the form #AABBGGRR, or as a decimal list of [R, G, B, A], both using the value range [0, 255].

        "exclude": ["c++", "docs", "icon", "python", "template", "tests", "usd"],
        "icon": "icons/CompanyLogo.svg",
        "language": "python"
    },
    "$iconPathWithColor": {
        "exclude": ["c++", "docs", "icon", "python", "template", "tests", "usd"],
        "icon": {
            "path": "icons/CompanyLogo.svg",

Note

Unspecified colors will use the defaults. An unspecified path will look for the icon in the default location.

language

A string value that represents the language of implementation. The default when not specified is “c++”. The other legal value is “python”. This value indicates the language in which the node compute algorithm is written.

        "exclude": ["c++", "docs", "icon", "python", "template", "tests", "usd"],
        "language": "python",
        "memoryType": "cuda",

memoryType

Nodes can be written to work on the CPU, GPU via CUDA, or both. For each case the data access has to take this into account so that the data comes from the correct memory store. The valid values for the memoryType property are cpu, cuda, and any. The first two mean that by default all attribute values on the node are exclusively in either CPU or CUDA-specific GPU memory. any means that the node could run on either CPU or GPU, where the decision of which to use happens at runtime. The default value is cpu.

        "language": "python",
        "memoryType": "cuda",
        "metadata": {

cudaPointers

Usually when the memory type is set to cuda or any the CUDA memory pointers for array types are returned as a GPU pointer to GPU data, so when passing the data to CUDA code you have to pass pointers-to-pointers, since the CPU code cannot dereference them. Sometimes it is more efficient to just pass the GPU pointer directly though, pointed at by a CPU pointer. (It’s still a pointer to allow for null values.) You can do this by specifying “cpu” as your cudaPointers property.

            "metadata": {
                "author": "Bertram P. Knowedrighter"
            },
            "cudaPointers": "cpu",
            "uiName": "OmniGraph Example Node"

Note

You can also specify “cuda” for this value, although as it is the default this has no effect.

metadata

Node types can have key/value style metadata attached to them by adding a dictionary of them using the metadata property. The key and value are any arbitrary string, though it’s a good idea to avoid keywords starting with with underscore (_) as they may have special meaning to the graph. Lists of strings can also be used as metadata values, though they will be transformed into a single comma-separated string.

A simple example of useful metadata is a human readable format for your node type name. UI code can then read the consistently named metadata to provide a better name in any interface requiring node type selection. In the example the keyword author is used.

        "memoryType": "cuda",
        "metadata": {
            "author": "Bertram P. Knowedrighter"
        },
        "tokens": "apple",

Tip

There are several hardcoded metadata values, described in this guide. The keywords under which these are stored are available as constants for consistency, and can be found in Python in the og.MetadataKeys object and in C++ in the file omni/graph/core/ogn/Database.h.

scheduling

A string or list of string values that represent information for the scheduler on how nodes of this type may be safely scheduled. The string values are fixed, and say specific things about the kind of data the node access when computing.

            "version": 1,
            "scheduling": ["global-write", "usd"],
            "language": "python"
            "version": 1,
            "scheduling": "global-write,usd",
            "language": "python"

The strings accepted as values in the .ogn file are described below (extracted directly from the code)

class SchedulingHints:
    """Class managing the scheduling hints.
    The keywords are case-independent during parsing, specified in lower case here for easy checking.

    When there is a -read and -write variant only one of them should be specified at a time:
        no suffix: The item in question is accessed for both read and write
        -read suffix: The item in question is accessed only for reading
        -write suffix: The item in question is accessed only for writing

    These class static values list the possible values for the "scheduling" lists in the .ogn file.

    # Set when the node accesses other global data, i.e. data stored outside of the node, including the data
    # on other nodes.
    GLOBAL_DATA = "global"
    GLOBAL_DATA_READ = "global-read"
    GLOBAL_DATA_WRITE = "global-write"

    # Set when a node accesses static data, i.e. data shared among all nodes of the same type
    STATIC_DATA = "static"
    STATIC_DATA_READ = "static-read"
    STATIC_DATA_WRITE = "static-write"

    # Set when the node is a threadsafe function, i.e. it can be scheduled in parallel with any other nodes, including
    # nodes of the same type. This flag is not allowed to coexist with any of the other types since they all denote
    # unsafe threaded data access.
    THREADSAFE = "threadsafe"

    # Set when the node accesses the graph topology, e.g. connections, attributes, or nodes
    TOPOLOGY = "topology"
    TOPOLOGY_READ = "topology-read"
    TOPOLOGY_WRITE = "topology-write"

    # Set when the node accesses the USD stage data (for read-only, write-only, or both read and write)
    USD = "usd"
    USD_READ = "usd-read"
    USD_WRITE = "usd-write"

    # Set when the scheduling of the node compute may be modified from the evaluator default.
    COMPUTERULE_DEFAULT = "compute-default"
    COMPUTERULE_ON_REQUEST = "compute-on-request"
    """

singleton

singleton is metadata with special meaning to the node type, so as a shortcut it can also be specified as its own keyword at the node level. The meaning is the same; associate a piece of metadata with the node type. This piece of metadata indicates the quality of the node type of only being able to instantiate a single node of that type in a graph or its child graphs. The value is specified as a boolean, though it is stored as the string “1”. (If the boolean is false then nothing is stored, as that is the default.)

        "language": "python",
        "singleton": true,
        "memoryType": "cuda"

tags

tags is a very common piece of metadata, so as a shortcut it can also be specified as its own keyword at the node level. The meaning is the same; associate a piece of metadata with the node type. This piece of metadata can be used by the UI to better organize sets of nodes into common groups.

        "tokens": "apple",
        "tags": "fruit,example,chocolate",
        "uiName": "OmniGraph Example Node",

Tip

Tags can be either a single string, a comma-separated string, or a list of strings. They will all be represented as a comma-separated string in the metadata.

tokens

Token types are more efficient than string types for comparison, and are fairly common. For that reason the .ogn file provides this shortcut to predefine some tokens for use in your node implementation code.

The simplest method of adding tokens is to add a single token string.

        "metadata": {
            "author": "Bertram P. Knowedrighter"
        },
        "tokens": "apple",
        "tags": "fruit,example,chocolate",

If you have multiple tokens then you can instead specify a list:

            "outputs:tuple": {"type:": "float[3]", "value": [12.0, 12.0, 12.0]}
        }
    ],
    "$tokenExamples": "Other types of token access, nested solely for documentation purposes",
    "$tokensWithArrayValue": {

The lookup is the same:

Lastly, if the token value contains illegal names for C++ or Python variables you can specify tokens in a dictionary, where the key is the name through which it will be accessed and the value is the actual token string:

        },
        "tokens": ["apple", "pear", "orange"],
        "uiName": "OmniGraph Example Node"
    },
    "$tokensWithNamedArrayValue": {

See the OGN User Guide for information on how to access the different sets of token in your code.

uiName

uiName is a very common piece of metadata, so as a shortcut it can also be specified as its own keyword at the node level. The meaning is the same; associate a piece of metadata with the node type. This piece of metadata can be used by the UI to present a more human-readable name for the node type.

        "tags": "fruit,example,chocolate",
        "uiName": "OmniGraph Example Node",

Tip

Unlike the actual name, the uiName has no formatting or uniqueness requirements. Choose a name that will make its function obvious to a user selecting it from a list.

Attribute Dictionaries

Each of the three attribute sections, denoted by the keywords inputs, outputs, and state, contain a list of attributes of each respective location and their properties.

inputs

Attributes that are read-only within the node’s compute function. These form the collection of data used to run the node’s computation algorithm.

outputs

Attributes whose values are generated as part of the computation algorithm. Until the node computes their values they will be undefined. This data is passed on to other nodes in the graph, or made available for inspection.

state

Attributes that persist between one evaluation and the next. They are both readable and writable. The primary difference between state attributes and output attributes is that when you set the value on a state attribute that value is guaranteed to be there the next time the node computes. Its data is entirely owned by the node.

        "uiName": "OmniGraph Example Node",
        "inputs": {
        },
        "outputs": {
        },
        "state": {
        }

Note

If there are no attributes of a specific location then that section can simply be omitted.

Attribute Property Keywords

The top level keyword of the attribute is always the unique name. It is always namespaced within the section it resides and only need be unique within that section. For example, the attribute mesh can appear in both the inputs and outputs sections, where it will be named inputs:mesh and outputs:mesh respectively.

Attribute Properties

Like the outer node level, each of the attributes has a set of mandatory and optional attributes.

description

As with the node, the description field is a multi-line description of the attribute, optionally with reStructuredText formatting. The description should contain enough information for the user to know how that attribute will be used (as an input), computed (as an output), or updated (as state).

Tip

This mandatory string should inform users exactly what data the attribute contains, as concisely as possible.

        "inputs": {
            "numberOfLimbs": {
                "description": "The number of limbs present in the generated character",
                "type": "int",

type

The type property is one of several hard-coded values that specify what type of data the attribute contains. As we ramp up not all type combinations are supported; run generate_node.py –help to see the currently supported list of attribute types. For a full list of supported types and the data types they generate see Attribute Data Types.

Tip

This field is mandatory, and will help determine what type of interface is generated for the node.

            "numberOfLimbs": {
                "description": "The number of limbs present in the generated character",
                "type": "int",
                "default": 4,

default

The default property on inputs contains the value of the attribute that will be used when the user has not explicitly set a value or provided an incoming connection to it. For outputs the default value is optional and will only be used when the node compute method cannot be run.

The value type of the default property will be the JSON version of the type of data, shown in Attribute Data Types.

                "type": "int",
                "default": 4,
                "optional": true,

Tip

Although input attributes should all have a default, concrete data types need not have a default set if the intent is for them to have their natural default. It will be assigned to them automatically. e.g. 0 for “int”, [0.0, 0.0, 0.0] for “float[3]”, false for “bool”, and “[]” for any array types.

Warning

Some attribute types, such as “any” and “bundle”, have no well-defined data types and cannot have a default set.

optional

The optional property is used to tell the node whether the attribute’s value needs to be present in order for the compute function to run. If it is set to true then the value is not checked before calling compute. The default value false will not call the compute function if the attribute does not have a valid value.

                "default": 4,
                "optional": true,
                "memoryType": "cpu",

memoryType

By default every attribute in a node will use the memoryType defined at the node level. It’s possible for attributes to override that choice by adding that same keyword in the attribute properties.

Here’s an example of an attribute that overrides the node level memory type to force the attribute onto the CPU. You might do this to keep cheap POD values on the CPU while the expensive data arrays go directly to the GPU.

                "optional": true,
                "memoryType": "cpu",
                "minimum": 2,

minimum/maximum

When specified, these properties represent the minimum and maximum allowable value for the attribute. For arrays the values are applicable to every array element. For tuples the values will themselves be tuples with the same size.

                "memoryType": "cpu",
                "minimum": 2,
                "maximum": 8,
                "metadata": {

Note

These properties are only valid for the numeric attribute types, including tuples and arrays. At present they are not applied at runtime, only for validating test and default values within the .ogn file, however in the future they may be saved so it is always a good idea to specify values here when applicable.

metadata

Attributes can also have key/value style metadata attached to them by adding a dictionary of them using the metadata property. The key and value are any arbitrary string, though it’s a good idea to avoid keywords starting with underscore (_) as they may have special meaning to the graph. Lists of strings can also be used as metadata values, though they will be transformed into a single comma-separated string.

                "maximum": 8,
                "metadata": {
                    "disclaimer": "There is no distinction between 8-limbed spiders and 8-limbed Octopii"
                },
                "uiName": "Number Of Limbs"

There are three special attribute metadata keys: allowedTokens, outputOnly and literalOnly.

allowedTokens is used only for attributes of type token and contains a list of the values that token is allowed to take.

            "inputs": {
                "operator": {
                    "type": "token",
                    "description": "The mathematical operator to apply",
                    "metadata": {
                        "allowedTokens": ["lt", "gt", "ne"]
                    }
                }
            }

Sometimes you may wish to have special characters in the list of allowed tokens. The generated code uses the token name for easy access to its values so in these cases you will have to also supply a corresponding safe name for the token value through which the generated code will access it.

            "inputs": {
                "operator": {
                    "type": "token",
                    "description": "The mathematical operator to apply",
                    "metadata": {
                        "allowedTokens": {
                            "lt": "<",
                            "gt": ">",
                            "ne": "!="
                        }
                    }
                }
            }

In both cases you would access the token values through the database members db.tokens.lt, db.tokens.gt, and db.tokens.ne.

outputOnly is used with an input attribute which can be the source of output connections but should not be the target of input connections. Typically an application will allow input attributes to take their value from an incoming connection or to be set by the user through the UI if they don’t have an incoming connection. The application may also disallow outbound connections. Setting outputOnly to 1 is a hint to the application that it should continue to allow the user to set the attribute’s value through its UI but disallow incoming connections and enable outgoing connections. A typical use for this is with a “constant” node which allows the user to enter a constant value which can then be passed on to other nodes via output connections.

            "inputs": {
                "defaultSpeed": {
                    "type": "double",
                    "description": [ "Default speed for interpolations. By connecting all 'Interpolate To' nodes to",
                                    "this the user can set it in just one place." ],
                    "metadata": {
                        "outputOnly": "1"
                    }
                }
            }

literalOnly indicates that the value of the attribute can only be set to a literal. In other words, if an attribute has literalOnly set to 1, then it cannot be connected to other attributes, so the only way to modify the value of the attribute is to set its value to a literal. A typical use case is the input attributes of event source nodes. Since the action evaluator does not evaluate nodes upstream of an event source node, the input attributes of event source nodes should not be allowed to connect to upstream nodes, so they should be declared as literalOnly.

            "inputs": {
                "keyIn": {
                    "type": "token",
                    "description": "The key to trigger the downstream execution",
                    "metadata": {
                        "literalOnly": "1"
                    }
                }
            }

uiName

uiName is a very common piece of metadata, so as a shortcut it can also be specified as its own keyword at the attribute level. The meaning is the same; associate a piece of metadata with the attribute. This piece of metadata can be used by the UI to present a more human-readable name for the attribute.

                    "disclaimer": "There is no distinction between 8-limbed spiders and 8-limbed Octopii"
                },
                "uiName": "Number Of Limbs"
            }

Tip

Unlike the actual name, the uiName has no formatting or uniqueness requirements. Choose a name that will make its function obvious to a user selecting it from a list. The UI may or may not include the namespace when displaying it so if that distinction is critical, include it in the uiName.

unvalidated

unvalidated is similar to the optional keyword, in that it is used to tag attributes that may not take part in a compute(). The difference is that these attributes will always exists, they just may not have valid data when the compute is invoked. For such attributes the onus is on the node writer to check validity of such attributes if they do end up being used for the compute.

        "inputs": {
            "useInput1": {
                "type": "bool",
                "description": "If true then output the first input"
            },
            "firstInput": {
                "type": "any",
                "description": "First attribute to be checked",
                "unvalidated": true
            },
            "secondInput": {
                "type": "any",
                "description": "Second attribute to be checked",
                "unvalidated": true
            }
        }

Test Definitions

The node generator is also capable of automatically generating some unit tests on the operation of the node’s algorithm through the tests property. This property contains a list of dictionaries, where each entry in the list is a dictionary of attribute name : attribute value.

The test runs by setting all of the input attributes to their corresponding values in the dictionary, executing the node’s compute algorithm, and then comparing the computed values of the outputs against their corrsponding values in the dictionary.

Note

When input attributes do not have a value in the tests their default is used. When output attributes do not have a value in the test they are not checked against the computed result.

There are two methods of specifying test data. They are equivalent so you can use the one that makes the most sense for your particular test cases. They can coexist if you have different types of test data.

The first method is using a single dictionary to specify any non-default attribute values.

        "tests": [
            { "inputs:firstAddend": 1, "inputs:secondAddend" : 2, "outputs:sum": 3 },
            { "inputs:secondAddend": 5, "outputs:sum": 5 },
            {

This example shows test cases to exercise a simple node that adds two integers together. The first test says if the node has inputs 1 and 2 the output should be 3 and the second one says if the node has an input of 5 and a default valued input the output should be 5 (the defaults have been set to 0).

For a more complex text you can specify the data involved in the test by location instead of all in a single dictionary. Here’s a similar example for an 8 dimensional polynomial solver.

            { "inputs:secondAddend": 5, "outputs:sum": 5 },
            {
                "inputs": {
                    "t0": 40320,
                    "t1": -109584,
                    "t2": 118124,
                    "t3": -67284,
                    "t4": 22449,
                    "t5": -4536,
                    "t6": 546,
                    "t7": -36,
                    "t8": 1
                },
                "outputs": { "roots": [1, 2, 3, 4, 5, 6, 7, 8] }
            },
            {

CPU/GPU Data Switch

There is one special piece of test configuration that applies when you have output data that switches at runtime between CPU and GPU (usually through some sort of input information, such as a boolean switch, or a limit on data size). This information tells the test generator that an output should be expected on the GPU instead of the default CPU location.

            {
                "inputs:isGpu": true,
                "inputs:points": [[1.0, 2.0, 3.0], [2.0, 3.0, 4.0]],
                "inputs:multiplier": [2.0, 3.0, 4.0],
                "outputs:points": [[2.0, 6.0, 12.0], [4.0, 9.0, 16.0]],
                "gpu": ["outputs:points"]
            },

This example illustrates testing of an output on GPU, where the GPU location is selected at runtime based on the attribute inputs:isGpu.

Extended Type Test Data

If your node has extended-type attributes, you will have to specify which type you want to use for your test. This is necessary to distinguish between types which aren’t support by json. For example double, float and half.

            {
                "inputs:multiplier": 2.0,
                "inputs:element": {"type": "float", "value": 6.0},
                "outputs:tuple": {"type:": "float[3]", "value": [12.0, 12.0, 12.0]}
            }

This example has one input “multiplier” which is a specific decimal type, input “element” and output “tuple” which are extended-types. “element” and “tuple” are related by the logic of the node in that their base types must match, so the test is specifying the same type for those attributes.

For tests that deal with extended data types you must also specify the data type with the value to be set so that it can properly resolve. (The other way of resolving data types is by connection. These simple tests only involve a single node so resolution can only be done by setting values directly.)

            "tests": [
                { "inputs:firstAddend": {"int": 1}, "inputs:secondAddend" : {"int": 2}, "outputs:sum": 3 },
                { "inputs:firstAddend": {"float": 1.5}, "inputs:secondAddend" : {"float": 2.5}, "outputs:sum": 4.0 }
            ]

State Test Data

In the special case of tests that need to exercise state data extra syntax is added to differentiate between values that should be set on state attributes before the test starts and values that are checked on them after the test is completed. The special suffix _set is appended to the state namespace to signify that a value is to be initialized before a test runs. You may optionally add the suffix _get to the state namespace to clarify which values are to be checked after the test runs but that is the default so it is not necessary.

            "tests": [
                { "state_set:counter": 9, "state_get:counter": 10 },
                { "state_set:counter": 5, "state:counter": 6 },
                {
                    "state_set": {
                        "counter": 9
                    },
                    "state_get": {
                        "counter": 10
                    }
                },
                {
                    "state_set": {
                        "counter": 5
                    },
                    "state": {
                        "counter": 6
                    }
                }
            ]

Test Graph Setup

For more complex situations you may need more than just a single node to test code paths properly. For these situations there is a pre-test setup section you can add, in the form of the Controller.edit function parameters. Only the creation directives are accepted, not the destructive ones such as disconnections.

These creation directives are all executed by the test script before it starts to run, providing you with a known starting graph configuration consisting of any nodes, prims, and connections needed to run the test.

            "tests": [
                {
                    "inputs": {
                        "firstAddend": 1
                    },
                    "outputs": {
                        "sum": 3
                    },
                    "setup": {
                        "create_nodes": [
                            ["TestNode", "omni.graph.examples.Node"]
                        ],
                        "create_prims": [
                            [["Prim1", {"attrInt": ["int", 2]}]]
                        ],
                        "connect": [
                            ["Prim1", "attrInt", "TestNode", "inputs:secondAddend"]
                        ]
                    }
                },
                {
                    "inputs:firstAddend": 10, "outputs:sum": 12
                }
            ]
        },

Note

If you define the graph in this way then the first node in your “nodes” directives must refer to the node being tested. If there is no graph specified then a single node of the type being tested will be the sole contents of the stage when running the test.

Simplified Schema

This schema outlines the relationships between all of the values in the .ogn file. It is simplified in that it does not include schema information that validates data types in default, minimum, maximum, and test section fields. (It’s possible to include such information in a schema, it just makes it very difficult to follow.)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
{
    "$schema": "http://json-schema.org/schema#",
    "type": "object",
    "title": "OmniGraph Compute Node Interface Description",
    "description": "Contains a description of the interfaces available on one or more OmniGraph Compute Nodes.",

    "$comments": "If any dictionary keyword begins with a '$' it will be treated as a comment",

    "definitions": {
        "commentType": {
          "description": "Pattern to allow $comment to be used with any data to annotate the file",
          "type": ["array", "boolean", "integer", "number", "object", "string"]
        },

        "languageType": {
          "description": "Values recognized as valid node language types",
          "pattern": "^(cpp|c\\+\\+|cu|cuda|py|python)$"
        },

        "tags": {
            "description": "Single value or list of value to use as tags on the node",
            "type": ["array", "string"]
          },

          "schedulingHints": {
            "description": "Values recognized as valid scheduling hints",
            "pattern": "^(global|global-read|global-write|static|static-read|static-write|threadsafe|topology|topology-read|topology-write|usd|usd-read|usd-write|compute-default|compute-on-request)$"
          },

          "color": {
            "description": "RGBA Color specification",
            "oneOf": [
                { "pattern": "^#[0-9a-fA-F]{8}$" },
                { "type": "array", "items": { "type": "integer", "minItems": 4, "maxItems": 4 } }
            ]
        },

        "iconDictionary": {
            "description": "Long form specifying icon properties by keyword",
            "type": "object",
            "properties": {
              "path": { "type": "string" },
              "color": { "$ref": "#/definitions/color" },
              "backgroundColor": { "$ref": "#/definitions/color" },
              "borderColor": { "$ref": "#/definitions/color" }
            }
        },
        "icon": {
            "description": "Single string path or dictionary of detailed information to override icon appearance",
            "oneOf": [
                { "type" : "string" },
                { "$ref": "#/definitions/iconDictionary" }
            ]
          },

        "attributeValue": {
          "description": "Simplified match for attribute values specified in the file (no type validation)",
          "type": ["array", "boolean", "integer", "number", "string"]
        },

        "attributeValueType": {
          "description": "Types of data recognized as valid attribute data in JSON form",
          "type": ["array", "boolean", "integer", "number", "string"]
        },

        "typedAttributeValue": {
            "description": "An attribute value that includes type information",
            "type": "object",
            "properties": {
                "type": { "$ref": "#/definitions/attributePattern" },
                "value": { "$ref": "#/definitions/attributeValueType" }
            }
        },

        "maybeTypedAttributeValue": {
            "description": "An attribute value that may be typed",
            "oneOf": [
                { "$ref": "#/definitions/attributeValueType" },
                { "$ref": "#/definitions/typedAttributeValue" }
            ]
        },

        "$subtypes": {"what":"Patterns for matching the attribute type declaration"},
        "simpleType": {
            "description": "Matches an attribute type pattern with no component counts or arrays",
            "pattern": "^[^\\[\\]]+$"
        },
        "componentType": {
            "description": "Matches an attribute type pattern with a simple value with a component count",
            "pattern": "^[^\\[\\]]+\\[[0-9]{1,3}\\]$"
        },
        "arrayType": {
            "description": "Matches an attribute type pattern for an array of simple values",
            "pattern": "^[^\\[\\]]+\\[\\]$"
        },
        "arrayOfArraysType": {
            "description": "Matches an attribute type pattern for an array of arrays of simple values",
            "pattern": "^[^\\[\\]]+\\[\\]\\[\\]$"
        },
        "componentArrayType": {
            "description": "Matches an attribute type pattern for an array of components",
            "pattern": "^[^\\[\\]]+\\[[0-9]{1,3}\\]\\[\\]$"
        },
        "componentArrayOfArraysType": {
            "description": "Matches an attribute type pattern for an array of arrays of components",
            "pattern": "^[^\\[\\]]+\\[[0-9]{1,3}\\]\\[\\]\\[\\]$"
        },
        "attributeTypeName": {
              "description": "Simple attribute type name portion of the pattern",
              "pattern": "^(any|bool|bundle|double|execution|float|half|int|int64|path|string|timecode|token|uchar|uint|uint64)"
        },
        "attributeTypeNameWithRoles": {
              "description": "Simple attribute type name portion of the pattern including role-based attributes",
              "pattern": "^(any|bool|bundle|double|execution|float|half|int|int64|objectId|string|timecode|token|uchar|uint|uint64|(color|normal|point|quat|path|texcoord|vector|(d|f|h))|matrixd|frame|transform)"
        },
        "numericAttributeTypeName": {
            "description": "Numeric attribute types supporting min/max values",
            "pattern": "^(double|float|half|int|int64|timecode|uchar|uint|uint64)"
        },
        "numericAttributeTypeNameWithRoles": {
          "description": "Numeric and role-based attribute types supporting min/max values",
          "pattern": "^(double|float|half|int|int64|timecode|uchar|uint|uint64|(color|normal|point|quat|texcoord|vector|(d|f|h))|(matrix(d|f))|frame|transform)"
        },



        "$allTypes": {"what":"Patterns for matching all valid attribute types and their component or array extensions"},
        "attributePatternSimple": {
            "description": "Simple attribute types, no components or arrays",
            "allOf": [
                { "$ref": "#/definitions/attributeTypeName" },
                { "$ref": "#/definitions/simpleType" }
            ]
        },
        "attributePatternComponent": {
            "description": "Simple attribute types with a non-zero component count, no arrays",
            "allOf": [
                { "$ref": "#/definitions/attributeTypeNameWithRoles" },
                { "$ref": "#/definitions/componentType" }
            ]
        },
        "attributePatternArray": {
            "description": "Array attribute types with no components",
            "allOf": [
                { "$ref": "#/definitions/attributeTypeName" },
                { "$ref": "#/definitions/arrayType" }
            ]
        },
        "attributePatternArrayOfArrays": {
            "description": "Array of arrays of attribute types with no components",
            "allOf": [
                { "$ref": "#/definitions/attributeTypeName" },
                { "$ref": "#/definitions/arrayOfArraysType" }
            ]
        },
        "attributePatternComponentArray": {
            "description": "Array attribute types with a non-zero component count",
            "allOf": [
                { "$ref": "#/definitions/attributeTypeNameWithRoles" },
                { "$ref": "#/definitions/componentArrayType" }
            ]
        },
        "attributePatternComponentArrayOfArrays": {
            "description": "Array of arrays of attribute types with a non-zero component count",
            "allOf": [
                { "$ref": "#/definitions/attributeTypeNameWithRoles" },
                { "$ref": "#/definitions/componentArrayOfArraysType" }
            ]
        },
        "attributePattern": {
            "description": "Match all of the simple types, plus an optional component count, and optional array type",
            "oneOf": [
                { "$ref": "#/definitions/attributePatternSimple" },
                { "$ref": "#/definitions/attributePatternComponent" },
                { "$ref": "#/definitions/attributePatternArray" },
                { "$ref": "#/definitions/attributePatternArrayOfArrays" },
                { "$ref": "#/definitions/attributePatternComponentArray" },
                { "$ref": "#/definitions/attributePatternComponentArrayOfArrays" }
            ]
        },



        "$numericTypes": {"what":"Patterns for recognizing the numeric types, for special handling"},
        "numericAttributePatternSimple": {
            "description": "Numeric attribute types, no components or arrays",
            "allOf": [
                { "$ref": "#/definitions/numericAttributeTypeName" },
                { "$ref": "#/definitions/simpleType" }
            ]
        },
        "numericAttributePatternComponent": {
            "description": "Numeric attribute types with a non-zero component count, no arrays",
            "allOf": [
                { "$ref": "#/definitions/numericAttributeTypeNameWithRoles" },
                { "$ref": "#/definitions/componentType" }
            ]
        },
        "numericAttributePatternArray": {
            "description": "Array of numeric attribute types with no components",
            "allOf": [
                { "$ref": "#/definitions/numericAttributeTypeName" },
                { "$ref": "#/definitions/arrayType" }
            ]
        },
        "numericAttributePatternArrayOfArrays": {
            "description": "Array of arrays of numeric attribute types with no components",
            "allOf": [
                { "$ref": "#/definitions/numericAttributeTypeName" },
                { "$ref": "#/definitions/arrayOfArraysType" }
            ]
        },
        "numericAttributePatternComponentArray": {
            "description": "Array of numeric attribute types with a non-zero component count",
            "allOf": [
                { "$ref": "#/definitions/numericAttributeTypeNameWithRoles" },
                { "$ref": "#/definitions/componentArrayType" }
            ]
        },
        "numericAttributePatternComponentArrayOfArrays": {
            "description": "Array of arrays of numeric attribute types with a non-zero component count",
            "allOf": [
                { "$ref": "#/definitions/numericAttributeTypeNameWithRoles" },
                { "$ref": "#/definitions/componentArrayOfArraysType" }
            ]
        },
        "numericAttributePattern": {
            "description": "Match all of the numeric types, plus an optional component count, and optional array type",
            "oneOf": [
                { "$ref": "#/definitions/numericAttributePatternSimple" },
                { "$ref": "#/definitions/numericAttributePatternComponent" },
                { "$ref": "#/definitions/numericAttributePatternArray" },
                { "$ref": "#/definitions/numericAttributePatternArrayOfArrays" },
                { "$ref": "#/definitions/numericAttributePatternComponentArray" },
                { "$ref": "#/definitions/numericAttributePatternComponentArrayOfArrays" }
            ]
        },

        "memoryTypeName": {
          "description": "Node or attribute-level specification of the memory location",
          "type": "string",
          "pattern": "^(cpu|cuda|any)$"
        },

        "metadata": {
          "description": "Key/Value pairs to be stored with the node or attribute type definition",
          "type": "object",
          "additionalProperties": false,
          "patternProperties": {
              "^\\$": { "$ref": "#/definitions/commentType" },
              "^[^\\$].*": { "type" : "string" }
          }
        },

        "attribute": {
            "type": "object",
            "description": "A single attribute on a node",
            "required": ["description", "type"],
            "properties": {
                "description": { "type": ["string", "array"], "items": { "type": "string" } },
                "array": { "type": "boolean", "default": false },
                "optional": { "type": "boolean", "default": false },
                "unvalidated": { "type": "boolean", "default": false },
                "memoryType": { "$ref": "#/definitions/memoryTypeName" },
                "metadata": { "$ref": "#/definitions/metadata" },
                "type": { "$ref": "#/definitions/attributePattern" },
                "uiName": { "type": "string" }
            },
            "patternProperties": {
                "^\\$": { "$ref": "#/definitions/commentType" }
            },

            "$extraProperties": "Collection of properties that are conditional on attribute types or other values",
            "allOf": [
                {
                    "$attributeDefaults": "Define attribute default types, where omission is okay if attribute is optional or an output",
                    "if" : {
                        "required": ["default"]
                    },
                    "then": {
                        "$comment": "If the default is provided then validate its type",
                        "$ref": "#/definitions/attributeValue"
                    }
                },
                {
                    "description": "A minimum value is only supported on certain attribute types",
                    "if": {
                        "required": ["minimum"]
                    },
                    "then": {
                        "$comment": "If the minimum is provided then validate its type",
                        "$ref": "#/definitions/attributeValue"
                    }
                },
                {
                    "description": "A maximum value is only supported on certain attribute types",
                    "if": {
                        "required": ["maximum"]
                    },
                    "then": {
                        "$comment": "If the maximum is provided then validate its type",
                        "$ref": "#/definitions/attributeValue"
                    }
                }
            ]
        },
        "attributes": {
            "type": "object",
            "default": {},
            "description": "A subset of attributes on a node",
            "$comment": "Attribute names are alphanumeric with underscores, not starting with a number, allowing periods and colons as separators",
            "additionalProperties": false,
            "patternProperties": {
                "^[A-Za-z_][A-Za-z0-9_.:]*$": { "$ref": "#/definitions/attribute" },
                "^\\$" : { "$ref": "#/definitions/commentType" }
            }
        },
        "tests": {
            "description": "Tests consist of a list of objects containing values for input and output attributes",
            "type": "array",
            "items": {
                "description": "Attribute values can either be namespaces as inputs:X/outputs:X/state:X or in objects with keys inputs/outputs/state",
                "type": "object",
                "patternProperties": {
                    "description": { "$ref": "#/definitions/commentType" },
                    "^inputs$": {
                      "type": "object",
                      "description": "Alternative way of specifying inputs without namespacing",
                      "patternProperties": {
                        "^[A-Za-z_][A-Za-z0-9_.:]*$": { "$ref": "#/definitions/maybeTypedAttributeValue" }
                      }
                    },
                    "^outputs$": {
                      "type": "object",
                      "description": "Alternative way of specifying outputs without namespacing",
                      "patternProperties": {
                        "^[A-Za-z_][A-Za-z0-9_.:]*$": { "$ref": "#/definitions/maybeTypedAttributeValue" }
                      }
                    },
                    "^state$": {
                      "type": "object",
                      "description": "Alternative way of specifying state without namespacing",
                      "patternProperties": {
                          "^[A-Za-z_][A-Za-z0-9_.:]*$": { "$ref": "#/definitions/maybeTypedAttributeValue" }
                      }
                    },
                    "^setup$": {
                      "type": "object",
                      "description": "Detailed graph setup prior to a test",
                      "properties": {
                        "nodes": { "type": "array" },
                        "connections": { "type": "array" },
                        "prims": { "type": "array" },
                        "values": { "type": "object" }
                      }
                    },
                    "^inputs:[A-Za-z_][A-Za-z0-9_.:]*$": { "$ref": "#/definitions/maybeTypedAttributeValue" },
                    "^outputs:[A-Za-z_][A-Za-z0-9_.:]*$": { "$ref": "#/definitions/maybeTypedAttributeValue" },
                    "^state:[A-Za-z_][A-Za-z0-9_.:]*$": { "$ref": "#/definitions/maybeTypedAttributeValue" },
                    "^\\$" : { "$ref": "#/definitions/commentType" }
                }
            }
        },
        "node": {
            "type": "object",
            "description": "Referenced schema for describing an OmniGraph Compute Node",
            "required": ["description"],
            "additionalProperties": false,
            "patternProperties": {
                "categories": { "$ref": "#/definitions/categoriesName" },
                "categoryType": { "$ref": "#/definitions/categoryTypeName" },
                "description": { "type": ["string", "array"], "items": { "type": "string" } },
                "exclude": { "type": ["string", "array"], "items": { "type": "string" } },
                "language": { "$ref": "#/definitions/languageType" },
                "inputs": { "$ref": "#/definitions/attributes" },
                "outputs": { "$ref": "#/definitions/attributes" },
                "state": { "$ref": "#/definitions/attributes" },
                "tests": { "$ref": "#/definitions/tests" },
                "version": { "type": "integer", "default": 1 },
                "metadata": { "$ref": "#/definitions/metadata" },
                "memoryType": { "$ref": "#/definitions/memoryTypeName" },
                "scheduling": {
                    "oneOf": [
                        { "type" : "string" },
                        { "$ref": "#/definitions/schedulingHints" }
                    ]
                },
                "uiName": { "type": "string" },
                "icon": { "$ref": "#/definitions/icon" },
                "tags": { "$ref": "#/definitions/tags" },
                "^\\$" : { "$ref": "#/definitions/commentType" }
            }
        }
    },

    "$limitation": "A valid file must have at least one node interface definition",
    "minProperties": 1,

    "additionalProperties": false,
    "patternProperties": {
        "^[A-Za-z_][A-Za-z0-9_]*$": { "$ref": "#/definitions/node" },
        "^\\$" : { "$ref": "#/definitions/commentType" }
    }
}