Search - User list
Full Version: LopSelectionRule - I'm doing it wrong
Root » Solaris and Karma » LopSelectionRule - I'm doing it wrong
Marco Dörner
Hi
I'm trying to resolve a LopSelectionRule and yet in the simplest of scenes I get an error saying “infinite recursion” - what am I doing wrong here?
jsmack
instead of hou.pwd(), what about the input node?

Edit:
I get a warning about a read lock fail due to existing lock when I tried it. Not sure how it's supposed to be used.
mtucker
From the drop down next to the python code parameter, choose “Dim All Lights”. It shows how to use a LopSelectionRule in a python LOP, and explains why things need to be done in a particular order.
Marco Dörner
Thanks! With the selection rule applied to the node before it worked.
I still got the following warning: “Read lock failed because of existing lock” but after looking at the example of diming the lights I learned that one should get the stage after doing the selections.

Cheers!
chendryx
I tried scanning through the docs, but I couldn't find any explanation as to what "Read lock failed because of existing lock" either - @mtucker is there an explanation anywhere as to what that means, and/or how Houdini is handling the UsdStage such that such a warning is necessary?
Tim Crowson
I have to admit I still see this "Read lock failed because of existing lock" message from time. I am uncertain 1) what it actually means, 2) how it's really effecting performance and 3) what I'm supposed to do about it.
Vladimir_Chesnokov
jsmack
instead of hou.pwd(), what about the input node?

Edit:
I get a warning about a read lock fail due to existing lock when I tried it. Not sure how it's supposed to be used.
Hi! Any updates on what this warning means and how to deal with it?
Cicuta
Tim Crowson
I have to admit I still see this "Read lock failed because of existing lock" message from time. I am uncertain 1) what it actually means, 2) how it's really effecting performance and 3) what I'm supposed to do about it.
Same, would be awesome to get a deeper understanding on this topic. Thanks!
robp_sidefx
A chain of LOP nodes effectively shares a USD stage and we do some on-the-fly mutation as the user jumps around the nodegraph (or makes API calls to access the stage at different nodes). When you call stage()or editableStage(), we perform the necessary mutation to ensure the shared stage has the right composition for the node you called that method on. We then lock things so you can get a consistent view of the stage for the lifetime of your variable without it further mutating under your feet.

What this means, though, is if you *also* ask for the stage from a different point in the LOP chain, we can't just do a cheap(/cheapish) mutation, we have to recompose a whole new stage for you, so that you have both the original stage and now this new one.

You may be looking at your script and saying "I'm not calling stage()/editableStage()multiple times!", but you may be triggering the same effect through other calls - selection rule expansion is the one we most commonly see. If we consider the "Dim the lights" example for the Python LOP, there's a block:
ls = hou.LopSelectionRule()
ls.setPathPattern('%type:Light')
paths = ls.expandedPaths(node.inputs()[0])

That last line (the expandedPathsline) is effectively asking for the stage from node.inputs()[0], so if you've previously asked for the stage from node, you've just run into the "need to recompose a whole new stage for you" situation.

We generally advise doing as much reading up-front as possible (and, if necessary, scoping your variables to help release locks as early as possible) and only calling editableStage()when you truly need to do the authoring.

Something else we added in Houdini 19.5, which we've perhaps not advertised well enough, is the ability to evaluate selection rules directly against stages rather than nodes (from which we internally extract a stage). So if you've already run something like theLockedStage = node.editableStage()you can call ls.expandedPaths(stage=theLockedStage)without the recomposition hit.

I hope this offers better insight into the warning you're getting. Do take it seriously with larger scenes; recomposition can be very expensive.
Tim Crowson
Cheers Rob! Thanks for so much for explaining that!
Cicuta
robp_sidefx
We generally advise doing as much reading up-front as possible (and, if necessary, scoping your variables to help release locks as early as possible) and only calling editableStage()when you truly need to do the authoring.

So this means that for now, if we need to access stage to get the data for setPathParent(), there is no way around it. We have to call stage at least twice.

robp_sidefx
Something else we added in Houdini 19.5, which we've perhaps not advertised well enough, is the ability to evaluate selection rules directly against stages rather than nodes (from which we internally extract a stage). So if you've already run something like theLockedStage = node.editableStage()you can call ls.expandedPaths(stage=theLockedStage)without the recomposition hit.

This seems like it will be very useful indeed.

robp_sidefx
I hope this offers better insight into the warning you're getting. Do take it seriously with larger scenes; recomposition can be very expensive.

Definitely. Thank you so much.
robp_sidefx
Cicuta
So this means that for now, if we need to access stage to get the data for setPathParent(), there is no way around it. We have to call stage at least twice.

If you're willing to share your script/hip here (or via support), I'd be happy to take a look.
Cicuta
That's so nice of you. You are already familiar with what I was trying to do from this post here:https://www.sidefx.com/forum/topic/82343/?page=1#post-394926. [www.sidefx.com] My goal is getting "All the bound geometry" from a material that matches an expression, in this case whenever a material has a node with a specific key in it. Without a python equivalent to the primitive pattern %geofrommat, my only guess for doing this through python was using the suggested setPathParent() method in that very same post. In doing so, since the objective is dynamic, I need to access the primitives first to fill the information of the setPathParent() which is exactly where I get the warning.
The attachment was my first approach. Thank you so much!

(The file is working with arnold materials)
robp_sidefx
Right ... so this is a good example where ls.expandedPaths(node.inputs()[0])can be replaced with ls.expandedPaths(stage=stage)and the warning will go away.

Alternatively, here's the script re-written into discrete read/write blocks:

node = hou.pwd()
from pxr import Usd, UsdGeom, UsdShade

# SHARED

coll_path = "/collections/fx"
bound_list = []

# READING

stage = node.inputs()[0].stage()
coll = stage.GetPrimAtPath(coll_path)
coll_api = Usd.CollectionAPI(coll, "key")
key_coll = coll_api.GetIncludesRel()

targets = key_coll.GetTargets() 
for target in targets:
    material_path = target.GetParentPath()
    material = stage.GetPrimAtPath(material_path)
    ls = hou.LopSelectionRule()
    expression = "%geofrommat:" + str(material.GetPath())
    ls.setPathPattern(expression)
    bound = ls.expandedPaths(node.inputs()[0])[0]  # or replace "node.inputs()[0]" with "stage=stage"
    bound_list.append(str(bound))

# WRITING

stage = node.editableStage()
coll = stage.GetPrimAtPath(coll_path)
coll_api = Usd.CollectionAPI(coll, "bound")
bound_coll = coll_api.GetIncludesRel()

bound_coll.SetTargets(bound_list)        
Cicuta
Oh I didn't think of the
stage = node.inputs()[0].stage()
line. Makes a lot of sense. Thanks a lot!! Unfortunately I am locked in h.19 right now so I cannot use the ls.expandedPaths(stage=stage) trick right now, but will note it. Amazing.

Now that I have the chance, what is the programmatic logic behind the %geofrommat pattern/"Select All Bound Geometry"? Are there plans on having something similar in python or VEX?

Thanks again!
robp_sidefx
Cicuta
what is the programmatic logic behind the %geofrommat pattern/"Select All Bound Geometry"?

It's part of the public Github repo, so I'll take the easy way out here and say "have a look for yourself"
https://github.com/sideeffects/HoudiniUsdBridge/blob/houdini19.5/src/houdini/lib/H_USD/HUSD/XUSD_AutoCollection.C#L1778-L1857 [github.com]

Are there plans on having something similar in python or VEX?

Can you elaborate a bit more on what's missing for you in Python? Where are you finding it problematic to construct & evaluate a selection rule?
Cicuta
robp_sidefx
It's part of the public Github repo, so I'll take the easy way out here and say "have a look for yourself"
https://github.com/sideeffects/HoudiniUsdBridge/blob/houdini19.5/src/houdini/lib/H_USD/HUSD/XUSD_AutoCollection.C#L1778-L1857 [github.com]

Awesome!

It was not related with contruct & evaluate a selection rule, that was the remedy. Going back to this topic: https://www.sidefx.com/forum/topic/82343/?page=1#post-394926, [www.sidefx.com] I haven't been able to find something like %geofrommat in python, like I have for %matfromgeo (https://openusd.org/release/api/class_usd_shade_material_binding_a_p_i.html#a5602550a78f68f6a1d1bf62187e22edd).
But now reading the repo you sent I think I have an idea of what its doing.

Thanks! This has been truly revealing!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB