.. _ogn_tutorial_complexData_py:


Tutorial 11 - Complex Data Node in Python
=========================================

This node fills on the remainder of the (CPU for now) data types available through Python. It combines the
progressive introduction in C++ of :ref:`ogn_tutorial_tupleData`, :ref:`ogn_tutorial_arrayData`,
:ref:`ogn_tutorial_tupleArrays`, and :ref:`ogn_tutorial_roleData`.

Rather than providing an exhaustive set of attribute types there will be one chosen from each of the
aforementioned categories of types. See the section `Pythonic Complex Attribute Type Access`_ for details on
how to access the representative types.


OgnTutorialComplexDataPy.ogn
----------------------------
The *ogn* file shows the implementation of a node named "omni.graph.tutorials.ComplexDataPy", which has one
input and one output attribute of each complex (arrays, tuples, roles) type.

.. literalinclude:: OgnTutorialComplexDataPy.ogn
    :linenos:
    :language: json

OgnTutorialComplexDataPy.py
---------------------------
The *py* file contains the implementation of the compute method, which modifies
each of the inputs in a simple way to create outputs that have different values.

.. literalinclude:: OgnTutorialComplexDataPy.py
    :linenos:
    :language: python

Note how the attribute values are available through the ``OgnTutorialComplexDataPyDatabase`` class. The generated
interface creates access methods for every attribute, named for the attribute itself. They are all implemented as Python
properties, where inputs only have get methods and outputs have both get and set methods.


Pythonic Complex Attribute Type Access
--------------------------------------
Complex data in Python takes advantage of the numpy library to handle arrays so you should always include this
line at the top of your node if you have array data:

.. code-block:: python

    import numpy


+----------------------+---------------------+-------------------------+
| Database Property    | Representative Type | Returned Type           |
+======================+=====================+=========================+
| inputs.a_float3      | Tuple               | [float, float, float]   |
+----------------------+---------------------+-------------------------+
| inputs.a_floatArray  | Array               | numpy.ndarray[float, 1] |
+----------------------+---------------------+-------------------------+
| inputs.a_point3Array | Role-Based          | numpy.ndarray[float, 3] |
+----------------------+---------------------+-------------------------+

As with simple data, the values returned are all references to the real data in the FlatCache, our managed memory store,
pointing to the correct location at evaluation time.

Python Role Information
-----------------------
The attribute roles can be checked in Python similar to C++ by using the ``role()`` method on the generated database
class.

.. code-block:: python

    def compute(db) -> bool:
        """Run my algorithm"""
        if db.role(db.outputs.a_pointArray) == db.ROLE_POINT:
            print("Hey, I did get the correct role")

This table shows the list of Python role names and the corresponding attribute types that match them:

+-----------------+---------------------------------+
| Python Role     | Attribute Types                 |
+=================+=================================+
| ROLE_COLOR      | colord, colorf, colorh          |
+-----------------+---------------------------------+
| ROLE_FRAME      | frame                           |
+-----------------+---------------------------------+
| ROLE_NORMAL     | normald, normalf, normalh       |
+-----------------+---------------------------------+
| ROLE_POSITION   | positiond, positionf, positionh |
+-----------------+---------------------------------+
| ROLE_QUATERNION | quatd, quatf, quath             |
+-----------------+---------------------------------+
| ROLE_TEXCOORD   | texcoordd, texcoordf, texcoordh |
+-----------------+---------------------------------+
| ROLE_TIMECODE   | timecode                        |
+-----------------+---------------------------------+
| ROLE_TRANSFORM  | transform                       |
+-----------------+---------------------------------+
| ROLE_VECTOR     | vectord, vectorf, vectorh       |
+-----------------+---------------------------------+
