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.
Contents
Node Level Keywords |
Attribute Level Keywords |
---|---|
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 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.
deprecated
The deprecated property is used to indicate that the attribute is being phased out and should no longer be used. The value of the property is a string or array of strings providing users with information on how they should change their graphs to accommodate the eventual removal of the attribute.
"inputs": {
"offset": {
"description": "Value to be added to the result, after 'scale' has been applied.",
"type": "float",
"default": 0.0,
"optional": true,
"deprecated": "Use 'minValue' instead."
},
"scale": {
"description": "Value to multiply the result by, before 'offset' has been applied.",
"type": "float",
"default": 1.0,
"optional": true,
"deprecated": [
"Use 'maxValue' instead.",
"To reproduce the same behavior as before, set 'maxValue' to 'scale' + 'offset'."
]
}
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 a number of attribute metadata keys with special meanings:
allowedTokens |
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 |
hidden |
This is a hint to the application that the attribute should be hidden from the user. "inputs": {
"appearanceHint": {
"description": "Hint to shader writer of how the limbs should be colored.",
"type": "string",
"optional": true,
"metadata": {
"hidden": "true"
}
}
}
Less commonly used attributes are often hidden to declutter the UI and the application may provide a mechanism to allow the user to display them on request. For example, in the Create application hidden attributes are not displayed in its Graph windows but do appear in its Property window from where their hidden state can be toggled off and on. |
internal |
Marks an attribute which is for internal use only. An application would not normally display the attribute to users or allow them to interact with it through its UI. "inputs": {
"debugFlags": {
"description": "Debugging flags. For internal use only.",
"type": "int",
"optional": true,
"metadata": {
"internal": "true"
}
}
}
|
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"
}
}
}
|
outputOnly |
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"
}
}
}
|
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.
uiType
uiType is used to provide a hint to the property panel as to how the property should bre displayed. When “filePath” is specified, string and token fields will create file browser widgets in the property panel. When “color” is specified, 3- and 4-component tuples will use a color picker widget in the property panel.
"metadata": {
"uiType": "color"
}
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" } } } |