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?
LopSelectionRule - I'm doing it wrong
4324 16 4- Marco Dörner
- Member
- 31 posts
- Joined: June 2016
- Offline
- jsmack
- Member
- 7658 posts
- Joined: Sept. 2011
- Online
- mtucker
- Staff
- 4419 posts
- Joined: July 2005
- Offline
- Marco Dörner
- Member
- 31 posts
- Joined: June 2016
- Offline
- chendryx
- Member
- 86 posts
- Joined: Jan. 2015
- Offline
- Tim Crowson
- Member
- 235 posts
- Joined: Oct. 2014
- Offline
- Vladimir_Chesnokov
- Member
- 8 posts
- Joined: Oct. 2021
- Offline
- Cicuta
- Member
- 54 posts
- Joined: Nov. 2019
- Offline
Tim CrowsonSame, would be awesome to get a deeper understanding on this topic. Thanks!
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.
- robp_sidefx
- Staff
- 446 posts
- Joined: June 2020
- Offline
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
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
That last line (the
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
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
I hope this offers better insight into the warning you're getting. Do take it seriously with larger scenes; recomposition can be very expensive.
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
expandedPaths
line) 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
- Member
- 235 posts
- Joined: Oct. 2014
- Offline
- Cicuta
- Member
- 54 posts
- Joined: Nov. 2019
- Offline
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 callingeditableStage()
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 liketheLockedStage = node.editableStage()
you can callls.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.
Edited by Cicuta - July 4, 2023 06:19:24
- robp_sidefx
- Staff
- 446 posts
- Joined: June 2020
- Offline
- Cicuta
- Member
- 54 posts
- Joined: Nov. 2019
- Offline
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)
The attachment was my first approach. Thank you so much!
(The file is working with arnold materials)
Edited by Cicuta - July 4, 2023 11:23:52
- robp_sidefx
- Staff
- 446 posts
- Joined: June 2020
- Offline
Right ... so this is a good example where
Alternatively, here's the script re-written into discrete read/write blocks:
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
- Member
- 54 posts
- Joined: Nov. 2019
- Offline
Oh I didn't think of the 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!
stage = node.inputs()[0].stage()
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!
Edited by Cicuta - July 4, 2023 16:37:42
- robp_sidefx
- Staff
- 446 posts
- Joined: June 2020
- Offline
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
- Member
- 54 posts
- Joined: Nov. 2019
- Offline
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!
Edited by Cicuta - July 5, 2023 05:18:42
-
- Quick Links