HOM

From Odwiki

Jump to: navigation, search

Contents

HOM: Houdini Object Model

The Houdini Object Model is an application programming interface (API) that lets you get information from and control Houdini using the Python scripting language. HOM replaces the functionality of Houdini's previous scripting solutions, the expression language and HScript.

In Python, the hou package is the top of a hierarchy of modules, functions, and classes that define the HOM.

kwargs Dictionaries

In many places in Houdini where you can use Python, a keyword arguments (kwargs) dictionary object is available. This dictionary stores various data dependent upon the context in which it exists. This data can include instances of hou.Node, hou.Parm, running tools, key click modifiers, node types, etc. Some places kwargs is available include:

  • shelf tools
  • parameter callbacks
  • parameter menu scripts
  • digital asset Python Modules and event handlers
  • global event handlers
  • PARMmenu.xml

Places to use Python

Accessing & Modifying the UI

Script Locations

Python scripts and modules can be placed in different locations throughout the HOUDINI_PATH.

  • General, non-version specific .py files can be placed in any scripts/python/ folders in the path.
  • Python-version specific files can be placed in python2.Xlibs/ folders where X is 5 or 6 depending on your Python version. These folders are not children of the scripts/ folder.

You might also wish to set the HOUDINI_SCRIPT_PATH variable for more control. This path is compatible with both Python and Hscript. Because of this, Houdini will search the path directories for folders named python/ to find .py files. You can also point directly to a path that contains .py files as well.

Storing Data in a Scene

Sometimes it is necessary to store data in your scene temporarily or more permanently assigned to specific nodes.

hou.session module

The hou.session module is a Python module that is accessible from anywhere hou is available. It allows you to create functions and assign objects to variables and store them attached to this module. The module source can be modified by using the Python Source Editor (PSE) window.

Persistence of data with hou.session can be somewhat confusing. A good way to think of it is as follows:

When you use the PSE window to define constants or write functions or classes you are doing the equivalent of writing an actual Python module that is then imported into Houdini and available as an object like any other imported module. Every time you hit Apply/Accept you are in essence performing a module reload command; the source code you have typed is run to create your constants and function or class objects.

When you are interacting with it from outside the PSE, hou.session is no different than any other module object. You can access your constants and functions just like you would from any other module. Also, like when you import any module, you can assign attributes to it.

hou.session.foo = 5
hou.session.double = lambda x: x*2
 
print hou.session.double(hou.session.foo) # Output: 10

These attributes are now attached to the module, but only so long as the session is active.

It is possible to get and set the source code of the module should you desire. This allows you the option to perhaps serialize a data structure into the module so you can access it at a later time or edit it directly.

x = 'a'
# When you set the module source the module code is automatically run.
hou.setSessionModuleSource("x = %s" % repr(x))
print hou.sessionModuleSource() # Output: x = 'a'
print hou.session.x # Output: a
 
# Append to the code.
text = "\ny = 'b'\n"
hou.setSessionModuleSource(hou.sessionModuleSource() + text)
print hou.session.y # Output: b

If you modify anything that is defined in the source and hit Accept/Apply any modifications are removed. Any attributes you have attached yourself are unaffected.

# Assume the session module is defined as in the last example.
hou.session.y = 5
print hou.session.x # Output: a
hou.session.x = ‘b’
print hou.session.x # Output: b
 
# Open the PSE window and hit Accept/Apply.
print hou.session.x # Output: a
print hou.session.y # Output: 5

User Data dictionary

As of Houdini 11.0 it is possible to assign and store string data to actual nodes through a user data dictionary associated with each node. This dictionary is a standard Python dictionary whose data is saved in the hip file. This gives it the advantage of being much more permanent than the hou.session module.

A usage example is that Houdini makes use of the dictionary by storing source tool name information: the new feature in Houdini 11.0 where you can hit the 'n' key to toggle between node names, nothing, and the name of the creator tool.

User data can be accessed as follows:

# data_node is some instance of hou.Node that you might want to store data on.
date_node.userDataDict() # Output: {}
 
data_node.setUserData("val", "1")
data_node.userDataDict() # Output: {'val': '1'}
data_node.userData("val") # Output: ‘1’
 
data_node.destroyUserData("val")
data_node.userDataDict() # Output: {}

Note:

  • The dictionary returned by hou.Node.userDataDict() is a copy, not a reference to the original dictionary. Any modification to the returned dictionary will not be passed on to the actual node’s data. To make changes you must use hou.Node.setUserData().

Serializing Data

While you might think being able to store strings is limiting, it is not the case. You can use various modules such as cPickle to convert complex data structures to string representations and store them using the data dictionaries.

import cPickle
vals = range(10)
print vals # Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 
result = cPickle.dumps(vals)
print result # Output '(lp1\nI0\naI1\naI2\naI3\naI4\naI5\naI6\naI7\naI8\naI9\na.'
 
mynode.setUserData("range_10", result)
new_vals = cPickle.loads(mynode.userData("range_10"))
print new_vals # Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

String Parameters

Before the addition of the user data dictionaries the best way to store data in nodes was to use (hidden) string parameters and then serialize the data similarly to above. This method is still possible but no longer necessary.

HOM Exceptions

In HOM, Houdini specific Python exceptions are handled similarly to the built-in exceptions. The base exception class is hou.Error and all other exception classes (hou.OperationFailed, hou.PermissionError, etc) are subclasses of hou.Error. However, hou.Error is not a subclass of Python's standard Exception class. One consequence of this is you cannot use the following code to trap exceptions.

try:
    raise hou.Error("This is an error.")
except Exception:
    print "Oops, I Excepted."

The raised hou.Error will not be caught because it is not a subclass of Exception.

The following is valid however:

try:
    raise hou.Error("This is an error.")
except hou.Error:
    print "Oops, I hou Errored."

As with the built-in exceptions, we can except the base class to catch all Houdini exceptions:

try:
    raise hou.OperationFailed("I was unsuccessful.")
except hou.Error:
    print "Oops, I hou Errored."

Module Scope

In Houdini, most different locations where you can use Python exist in their own name space. This means that any modules imported or functions and constants defined in one location may not be available in others.

The main name space in Houdini is accessible from the Python Shell and can be modified normally from within pythonrc.py, 123.py and 456.py. You can use this to import various modules you want available throughout Houdini.

Tools, the Python Source Editor, HDA Python Modules and sections, parameter callbacks, and Python event handlers exist in their own name spaces in which the only thing of consequence available is the hou module.

Parameter expressions are also in their own space but for convenience have the following automatically setup.

from hou import *
from math import *

You can easily view and modify this parameter namespace as a simple Python dictionary.

exp = hou.expressionGlobals()
 
def test():
    return 99
 
exp["foo"] = test
# In a Python parameter you can now use the following.
foo() # Returns the value 99.

In order to access modules, functions and constants imported or defined in the main space from any of these others you need to import the main module.

import __main__
__main__.foo()
__main__.my_module.bar()

Shelftools examples

Center Pivot

List available cameras

PythonSOP examples

Using numpy/scipy against Volumes

This example shows how to transfer a Houdini Volume into a numpy array and process it with scipy. The values are then quickly returned to the Houdini Volume.

import numpy
import scipy.ndimage
 
# This code is called when instances of this SOP cook.
geo = hou.pwd().geometry()
volume = geo.prims()[0]
np = numpy.array(volume.allVoxels()).reshape(volume.resolution())
 
# Now we have our numpy 3d array... have fun!
sigma= 2.5
np = scipy.ndimage.filters.gaussian_filter( np, sigma  )
 
# set the values of the volume back in Houdini
volume.setAllVoxels( np.flatten() )
© 2009 od[force].net | advertise