Get layer of an object with rs.ObjectLayer(x) inside Python compnent

I opened your file before I replied to you. It seems to me that some kind of geometry parameter (Geo, Crv, Pt, Brep, etc) is more likely to be used for importing Rhino geometry, then connected through a Guid component, than setting a Guid param directly? Is there any reason to set type hint to ‘str’ instead of ‘No type hint’ or "ghdoc Object when geometry’, which also work?

The two lines of code in the OP from @Bogdan_Chipara work fine when a Guid is used with it. While I generally don’t work with scripting, I vaguely recall knowing this from past forum posts. A little surprising that we are still discussing something so simple.

RhinoScript accepts Guids expressed as System.Guid and as strings. That’s the only reason. By setting one of the two type hints, you are sure that at least the type is correct. The runtime behavior, if the incoming object type is right, is the same.

In general, Grasshopper does not work with Rhino document data, and does not transport it along computations. If you transform (e.g., move) an object, its original ID is lost. That’s why the ID param makes it at least clear.

Please also note that the example you posted is a little deceiving. In fact, it only works because in that script above, you forget to set back the scriptcontext.doc variable: scriptcontext.doc = ghdoc. In the script below, then, the ID is searched in the right document because of that… If you modify the state of the scriptcontext module, please reset it to its pristine state when you are done.

I don’t really know what this means? I guess you are referring to this version posted by @clement?

import Rhino
import scriptcontext as sc

sc.doc = Rhino.RhinoDoc.ActiveDoc
obj = sc.doc.Objects.Find(x)

def MyGetObjectLayer(obj):
    index = obj.Attributes.LayerIndex
    layer = sc.doc.Layers[index]
    return layer.Name
    
a = MyGetObjectLayer(obj)

My preference here is the two simple lines of code in @Bogdan_Chipara’s first post; no need that I can see to make it so obscure and complicated?

import rhinoscriptsyntax as rs
a = rs.ObjectLayer(x)

You are trying to make this work in 5 or 6, or both?

I refer to this.

This line:

changes the state of the rhinoscript doc.

I’m using only Rhino 5, like the OP (@Bogdan_Chipara), but this is his thread, not mine.

Either I don’t understand you or this statement below just isn’t correct? WAIT!!! I closed Rhino, re-opened it and the code I just posted (below) now fails! This is ridiculous.

python3
python_get_layer2.gh (2.3 KB) (bad code, don’t use)

This is what I get with a new instance of Rhino and your file. I think you have a file open in GH that has the side effect that I mentioned above.

Yeah, I figured that out. See previous post, amended… sigh. How bizarre. Can you folks make this any more obscure? :roll_eyes: :face_with_raised_eyebrow:

No wonder @Bogdan_Chipara has been baffled.

I don’t find it so bizarre, sorry… if I move a plant in my house from the kitchen to the bathroom, I don’t usually expect it to move back to the kitchen on it own.

After modifying the target document, you will just need to set back its original value. A variable named ghdoc is provided to make the task easier, but you may also just store the original value in scriptcontext.doc, like so…

prev = scriptcontext.doc
scriptcontext.doc = Rhino.RhinoDoc.ActiveDoc
#do everything required
scriptcontext.doc = prev

If you change the value, GhPython does all the necessary steps to make sure that the value you requested is kept while Grasshopper runs.

Maybe we could change the behavior if many users are confused or request it; it would require to basically always reset the value.

Poison Kool-Aid as far as I’m concerned.

I logged RH-43802.

Just two more cents:

Python is a great language, since its syntax is very easy and clear. The more i do Python, the more I like it. Regarding “easiness” its better as c# and even much more better as c/c++.
However there is a reason why most tech universities begin teaching computer science/informatics in c and why I’m trying to get good at pure c programming. You actually have a hard time understanding whats really going on if you don’t care about the lower mechanics. All the comfort a “higher” languages offers you; you wont understand anything right if you didn’t do it on a lower Level (at least once). Same analogy for modelling, algorithms and library usage.
Usually a mix of understanding debugging, reading error messages inbetween their lines and error checking (at least at the critical parts) helps you in solving these problems by your own.
It is really hard to study a unknown library, sometimes harder as learning the language. However using IronPython to learn a c# wrapper library is rather hardcore. Therefore , if you guys want to do things beyond rhinscriptsyntax believe me, its much easier if you understand concepts of C#. Understanding C# is for Rhino/Grasshopper much more benefical. If you know both you can do Rhinocommon in Python.

1 Like

Hi Giulio, i think i forgot to reset it since ghdoc was not there without importing it. Imho for a more seamless integration of rhinoscript syntax things like rs.ObjectLayer should work out of the box.

_
c.

1 Like

My programming background goes back to assembly language and Fortran, so I understand what’s “under the hood”. I’ve worked in many flavors of code since then including Pascal, Algol, Java, Javascript, PHP, Python and others. I developed an aversion to C in the early days because it allowed stupid things like assigning a long string to an integer, corrupting memory, where compilers in more strongly typed languages prevented that kind of mistake. I like Python, though I’m not making any effort to learn it in the GH/Rhino context. From time to time, someone posts something mildly interesting, like this thread, and I take a look. The behavior I saw today regarding temporary override and restore of a global ‘scriptcontext’ object horrifies me. Very far away from my idea of best practices in programming.

Ok, this works with rhinoscriptsyntax. (With Geometry ID as input for x and No Type Hint).

import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
sc.doc = Rhino.RhinoDoc.ActiveDoc

a = rs.ObjectLayer(x)

sc.doc = ghdoc

So to use rhinoscriptsyntax I always have to set the scriptcontext to the active document.
I don’t really understand the reason for this, but it’s good to know.

Also, I wish it would update automatically when i place the object into another layer

According to @piac, this is the recommended “best practice” , where the “finally:” clause restores the previous value of sc.doc. Ugh! :frowning:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

old_doc = sc.doc
try:
    
    sc.doc = Rhino.RhinoDoc.ActiveDoc
    a = rs.ObjectLayer(x)
    
finally:
    sc.doc = old_doc

To quote from GhPython description:

Unlike other scripting components, GhPython allows to use the rhinoscriptsyntax to start scripting without needing to be a programmer.

:joy::joy::joy:

1 Like

well, excluding this problem and using rhinoscriptsyntax only, it is actually quite easy. However rs doesn’t fully wrap around rhinocommon.dll, and also not around grasshopper.dll. So the moment you need to do more as provided you will get into bigger trouble as learning c#. And C# is actually not that complicated as c.
So for example doing datatrees with python is kind of weird for beginners, because you mix c# style with python and if wouldn’t have started with c# in first place,you wouldn’t understand this weird construct at all.

Didn’t know that you have such a strong programming background, but then you excactly understand my point. Its the hatelove I share with python → Python emphasis so much on clean syntax that it gets inconsistent. This is esspecially true for the dotnet port of IronPython, and even more for GHPython.
In the end your increased productivity through simpler syntax gets pointless when you running into weird behaviour through inconsisty and not being strongly typed…

Guys, let me be quite frank. Layers and Grasshopper is definitely not a strong point, because Grasshopper does NOT include layer information in its default logic. No matter what you do, it will be awkward because attributes are not what Grasshopper is specialized in dealing with. It specializes in geometry. It discards attributes immediately after the first calculation.

They will, once Grasshopper will have object attributes (like layer, color, etc) held together with geometry items. Right now, we added Guids, as you could see, for Rhino 6, but attributes are part of the discussion for GH2. I remember also a specific discussion on the topic with David. No promises, yet, though.

Thanks. This is exactly what we hope for.

Yes I agree. The DataTree type is extremely hard in Python. I’d go so far as to argue that DataTrees are hard and a little inconsistent in any language. I much prefer nested lists when possible, and ghpythonlib.treehelpers allows to translate seamlessly from one to the other. This stuff.

I was thinking about this and I agree that GhPython should set back the “normal Grasshopper document” even if you do not do it yourself. If you happen to have modified it by accident like this without resetting it, it’s puzzling (like when you try to pick a point at random and you have OSnap ON). All “modes” have this peculiarity, and, in this case, I should have thought about that. Bash me.

Please use this:

import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
sc.doc = Rhino.RhinoDoc.ActiveDoc

a = rs.ObjectLayer(x)

sc.doc = ghdoc #important, set it back to default

I agree. We need to hook up the debugger for GhPython, at least the same type that is in the _EditPythonScript editor. In general, GhPython is there to offer people that like Python the possibility to script with it, not to take it away from people who like C#.

I also think rhinoscriptsyntax with GhPython for geometry is at least in 3 aspects simpler for beginners than RhinoCommon with C#, because it does not have objects, because it requires no understanding of methods (only functions), and because it’s procedural with examples. Personally, I like C# for other things, like UI, customizations, where there is a need for fast calculations, etc.

1 Like

FYI:
https://www.google.com/search?q=scriptcontext+python+doc

http://developer.rhino3d.com/api/RhinoCommonWin/html/T_Rhino_RhinoDoc.htm

WARNING!! Do not use the ActiveDoc if you don’t have to. Under Mac Rhino the ActiveDoc can change while a command is running. Use the doc that is passed to you in your RunCommand function or continue to use the same doc after the first call to ActiveDoc.

This is a very succinct tutorial on the practical use of GhPython:
TIPS | SCRIPT CONTEXT IN GH PYTHON

Of the languages I mentioned, I was deeply immersed in Pascal, Java, PHP and Javascript and barely dipped my toe in Python, on one project based on the Django web framework. I was stunned and appalled at the use of indentation alone instead of “{}” curly brackets to indicate code blocks! One of the dumbest “enhancements” I’ve ever seen in the long history of programming languages.

I have not delved deeply enough into Rhino/GH scripting to understand this scriptcontext.doc issue but I can recognize a hazardous abstraction when I see one. If I ever do decide to get serious about Rhino/GH “scripting”, I’ll remember your advice about C# and look into it. Perhaps I missed something good there. I’ll never touch VB Script on general principles and would prefer to use JavaScript if I could.

Cheers

VB, a wannabe Pascal. So it wouldn’t be a big step for you. I’m a Pascal/Delphi oldtimer myself, started out with VB.NET for RhinoCommon, but people here strongly encouraged me to do C# instead. So I did (~6 month ago).

No problem, once I broke my neck trying to view type declarations which are on the wrong side. I got over it in a few weeks.

And some degree of duck typing is there as well. No need to repeat types over and over again. This works better (and an optimization tool in VS suggest I drop all the types and go for war, i mean, var declarations instead, like so):

var i = 0;                    // int
var d = 0.0;                  // double
var pt = new Point3d(0,0,0);  // crystal clear type.
var vec = new Vector3d(pt1 - pt0); // that's all it takes
var lst = new List<double>(); // guess

// The list above can be repeated for no good reason;
List<double> lst = new List<double>(); // guess

for (var j = 0; j <  lst.Count; j++)
{
    var item = lst[j];        // item gets it right,
    ...
}
// aso.

In short, C# is pretty straightforward for anyone having used object oriented languages. I miss pointers though, GC makes you lazy.

// Rolf