HDA Python callback Class usage

   6279   10   1
User Avatar
Member
30 posts
Joined: July 2005
Offline
Hi!

I'm looking to maintain persistent data between cooks in an HDA (SOp) that I am creating. The SOp has buttons with associated Python callback functions, and I would like to reduce redundant computation by storing results in class-owned data.

Does anyone have any experience or pointers?

Other approaches to maintaining persistent data would be welcome as well. I am looking to store statistical data (as floats, etc) as well as list data.

I could store this info within Houdini data (lists into point attributes, etc.), but that's inelegant, and lists are faster to access, which is much of the initial reasoning for keeping data in lists in the first place.

Thanks!

-caleb
My avatar was rendered from PRISMS
User Avatar
Member
1921 posts
Joined: Nov. 2006
Online
One option I've used a bunch to store python data on a specific node is to store the data in a string parameter.

You can convert a list of standard types to a string using repr(), and then you can convert that string back to values using eval(). I've stored large dictionaries of lists/tuples/values like this and it has worked pretty well.

Edit:

As an example, create a string parm with a default value of an empty dictionary, ‘{}’

In your code you can do something like this:

data = mynode.evalParm(“data”)
data_dict = eval(data, globals())

data_dict = range(10)

mynode.parm(“data”).set(repr(data_dict))

Your string parm now holds an dictionary with an list of then numbers 0-9
Graham Thompson, Technical Artist @ Rockstar Games
User Avatar
Member
30 posts
Joined: July 2005
Offline
Good idea! Thanks.

I gather then that there is no way to instantiate a class that persists between cooks to manage my data?

How big a string will Houdini cope with? I'm dealing with some big datasets.

Thanks!

-caleb
My avatar was rendered from PRISMS
User Avatar
Member
1921 posts
Joined: Nov. 2006
Online
Well you could use a custom class assuming you wrote a proper __repr__ function to go with it. In that case you could output the class to the parm. You could also look at the pickle module to do that.

Also, you could take the data away from the actual node and store it in the hou.session module. In the case of multiple instances of the same SOP type you'd probably want a dictionary to hold your class instance using the path or something as the key. Using the session module means you'd have to handle the fact the data might not be there such as when you first load the file and your sops have to cook for the first time. You could also add that stuff to an OnLoaded handler for the asset as well.
Edited by - Jan. 5, 2010 19:13:46
Graham Thompson, Technical Artist @ Rockstar Games
User Avatar
Member
30 posts
Joined: July 2005
Offline
hmm… on second thought, does this do what I need? I need to store persistent data between cooks, not pass data down the SOp chain. If I create a string attrib, I would expect it to get clobbered when the gdp is killed and recreated as data comes down the chain from the previous SOp on the next cook. I want the data to persist in the Node itself.

I remember the feedback SOp… sigh.

Thanks!

-caleb
My avatar was rendered from PRISMS
User Avatar
Member
30 posts
Joined: July 2005
Offline
That sounds more promising… I'll look at this. I gather there is nothing in existence which does this sort of thing already, eh? An example is worth a thousand docs. ;-)

Thanks!
My avatar was rendered from PRISMS
User Avatar
Member
1921 posts
Joined: Nov. 2006
Online
It should do what you want. It doesn't use a string attribute, it uses a string parameter (most likely hidden). The parameter only changes when you write data to it so it will always be there between cooks.
Graham Thompson, Technical Artist @ Rockstar Games
User Avatar
Member
1921 posts
Joined: Nov. 2006
Online
Here's an example file.

I have a SOP that just counts how many times it's cooked since creation. The data is stored in a string parm and uses what I mentioned about.

Attachments:
parm_data_storage.hipnc (41.3 KB)

Graham Thompson, Technical Artist @ Rockstar Games
User Avatar
Member
30 posts
Joined: July 2005
Offline
Yeah! This hit me shortly after I posted. Of course! Cool! Thanks!

This should do just what I need! Thanks!

-caleb
My avatar was rendered from PRISMS
User Avatar
Member
30 posts
Joined: July 2005
Offline
(Still… It'd be nice to just keep a persistent class instance around. I'm just sayin')

Thanks again!
My avatar was rendered from PRISMS
User Avatar
Member
30 posts
Joined: July 2005
Offline
poop. This won't do at all (I don't think).

I have a list of houdini nodes - each is an instance of an HDA created from a subnet with all sorts of structure and parameters.

repr() just returns a string like the following:

[
<hou.ObjNode of type foo_CV_bezier_handle at /obj/Test/bar/OBJECT_NETWORK_CVs/CV_1>,

<hou.ObjNode of type foo_CV_bezier_handle at /obj/Test/bar/OBJECT_NETWORK_CVs/CV_2>,


]

…which string I don't think I can use to rebuild my list of nodes later.

Can I?

I think I really need a way to keep a persistent (static?) python structure associated with a node between cooks. It really seems like this should be an obvious and straightforward need to fulfill.

Translating my list of nodes into lists of parameter lists looks like it will be slower that it's worth.

poop.

Is there a way to build a dictionary of parameters from a node, perhaps, and then to use a dictionary to set all the parms of the node. Failing that, is there any general way to store node data unambiguously as a string, with the ability to reconstruct the node from the string?

back to the drawing board.

Thanks!

-caleb
My avatar was rendered from PRISMS
  • Quick Links