I need help to understand data trees

Hi there,
I have been working with grasshopper for round about three weeks now, and I can do a great deal in it already. Mostly I work with py3 modules to create the things I directly want to do.

Every time, however, that I want to use data trees, I always stumble into issues.
For one, if I for example have a python 3 module creating lists of e.g. line-like-curves, and these components are fully functional, trying to create a for loop in the script, creating data trees inevitably results in goo and no longer produces usable results. I will put some code examples that I used at the end, but debugging it is not the main issue here.

Another example of my lack of understanding can be seen in the image below. Here, my intent has been fairly simple: Create 3 plates for Tekla, create 41 plates for each of them, all of which are simply used for cutting holes. I had to do this fairly lengthy setup before I finally got it to work. If anyone here can explain to me the differences between list chunks and data trees, and why I have to first tree explode the list chunks before merging them again to obtain usable results, that would be much appreciated. I also don’t understand why the indeces of the exploded list chunks are so long. Why is it e.g. {0;0;0;0}? What is the function of the first three zeros?

Example attempt at creating trees with a branch from each for loop:

import ghpythonlib.treehelpers as th
import ghpythonlib.components as ghcomp
ALL_a = {}
for L in range(1, 5):
computation creating “a”
ALL_a[L]=a

Please upload a GH file, or finding help from this forum is unlikely. If you don’t want to, or can’t share the definition because of IP, at least internalize the outputs from Plate into Data containers, so that we can better show you what’s going on.

I won’t be able to help you with the coding side of things, but data trees is something I have a pretty good handle on.

thank you, I have attached the file referenced in the picture earlier below:
bolt_plates.gh (25.8 KB)

I realise my question is fairly vague, and this reflects my lack of understanding of data trees. It basically boils down to me wanting to understand how data trees actually work, and the syntax required for working with them. I do not understand, for example, why list chunks appear to be different from trees.
Coming from an engineering/math background, my conception of trees and expectation of use is to use them as a sort of matrix.

In a new test done on the same file, I could now get the partition output to work directly on the cut module. Earlier I was only able to do so after doing the tree explosion and merge, which is something I find strange.

You still need to internalize your data from plates in a container. I don’t have your plug-ins. But I see that Callum is writing a response, so…

these will both be of great help (the first is a playlist of many videos)

1 Like

Andrew Heumann’s video “The deal with Data Trees” is excellent :bangbang: I still use ‘Simplify’ for code readability too frequently but can see how that might have caused trouble recently in a couple of complex GH files, so will try harder to avoid it. :+1:

1 Like

Thank you everyone, but I’m still lost and essentially locked out of creating data trees. The reason I want to use datatrees is that I create stuff with my functions, that I want to later be able to call upon and handle separately.
A cumbersome way without trees would be to simply use lists, and append to the lists, and have a second list variable with items containing the length of each unit, and from that calculate the item number where unit X starts by adding the lengths of all previous units and subtracting 1. But since Grasshopper has trees, it feels silly for me not to use it.

I am going to present a simplified ghpython code example below, creating simple vertical lines. We will have one simple single line for easier understanding, as my issue is that I fail right out of the gate, but just know that in reality each unit will be an assembly of all sorts of things.

import Rhino.Geometry as rg
import rhinoscriptsyntax as rs
import math
import System
import ghpythonlib.treehelpers as th
import ghpythonlib.components as ghcomp
import re
COMMENT the one below I can’t get to work because “ModuleNotFoundError: No module named ‘Grasshopper.DataTree’”
COMMENT import Grasshopper.DataTree as DataTree
COMMENT the one below I can’t get to work because “ModuleNotFoundError: No module named ‘Grasshopper.Kernel.Data.GH_Path’”
COMMENT import Grasshopper.Kernel.Data.GH_Path as GH_Path
COMMENT This one I use as a replacement for the previous two, but can’t get it to work:
import Grasshopper as gh

COMMENT Tree attempt 1 does not work because “NameError: name ‘DataTreeobject’ is not defined” and because I cannot import Grasshopper.DataTree and Grasshopper.Kernel.Data.GH_path:
COMMENT T = DataTreeobject

COMMENT Tree attempt 2 does not work because even though importing Grasshopper as gh works, it simply does nothing and results in “AttributeError: DataTreeobject” on the following line:
COMMENT T = gh.DataTreeobject

COMMENT Tree attempt 3 also doesn’t work, but without producing an actual error.
T = {} #initialising the data tree.
A = [ ] # a simple list for comparison, but this is not my preferred solution for the reasons explained earlier.
for i in range(1,15):
unit_input = INPUT.Branch(i) # working through one branch of excel data at a time.
x = float(unit_input[3])
y = float(unit_input[4])
z1 = float(unit_input[5])
z2 = float(unit_input[7])
start_point = rg.Point3d(x , y, z1)
end_point = rg.Point3d(x , y, z2)
a = rg.Line(start_point, end_point) # a simple line that we will use as our example
A.append(a) # the list approach that works but is lacking for the reasons explained earlier.
T[i] = a
print(T[i]) # printing T[i] provides start and end coordinates.
print(T)
printing T provides {1: <Rhino.Geometry.Line object at 0x000001F8877618C0>, 2: <Rhino.Geometry.Line object at 0x000001F887761980>, 3: <Rhino.Geometry.Line object at 0x000001F887761BC0>, 4: <Rhino.Geometry.Line object at 0x000001F88776DA80>, 5: <Rhino.Geometry.Line object at 0x000001F8889753C0>, 6: <Rhino.Geometry.Line object at 0x000001F88776C3C0>, 7: <Rhino.Geometry.Line object at 0x000001F88776C180>, 8: <Rhino.Geometry.Line object at 0x000001F8885BB240>, 9: <Rhino.Geometry.Line object at 0x000001F8885BBE40>, 10: <Rhino.Geometry.Line object at 0x000001F8885BBD00>, 11: <Rhino.Geometry.Line object at 0x000001F8885BB980>, 12: <Rhino.Geometry.Line object at 0x000001F8877619C0>, 13: <Rhino.Geometry.Line object at 0x000001F8877611C0>, 14: <Rhino.Geometry.Line object at 0x000001F887761B40>}
However, T fails to be a meaningful result usable by grasshopper or Rhino:

I hope the above clarifies my question. I quite simply need the correct syntax needed to initialise and add to trees. All of my attempts, such as “T = DataTreeobject” simply fails. I have not been able to find a solution on my own, and as far as I can see neither the Youtube playlist (which adresses trees in general) nor the Youtube video actually look at ghpython. I have also failed to do it in grasshopper without python except through a convoluted process shown in the image in the introductory picture, but since the required Tekla component appears to confuse, and since I’d prefer a coded solution that would allow me to loop through a variable number of loops, let’s focus on the code approach.

EDIT: I was required to replace # at the beginning of code lines with COMMENT in the code I posted above because # simply results in the text being reformatted into bold and big letters. If you throw it into a python module of your own, you should replace it back with #

if you deal with Python, data trees can be thought as nested lists, lists of lists

for instance, the data tree:

{0;0} : a, b, c
{0;1} : d, e, f
{1;0} : g, h, i
{1;1} : j, k, l

can be represented as: [ [ [a, b, c], [d, e, f] ], [ [g, h, i], [j, k , l] ] ]

maybe it’s easier to “see” it like this:

the other important thing you need to consider is that within GH data-tree matching -generally speaking- ignores path addresses ( examples here: Feature request: Trim tree option on component outputs - #8 by inno )
so the most important thing is the number of paths of two different data-trees to match, otherwise the principle of the Longest List will take action (the last item/branch of the shorter one will be repeated/duplicated until it reaches the same length of the longer one)
there are a few cases were the above “rule of thumb” is not valid, but they are easily recognizable: for instance what is indicated as “Pattern” will just repeat itself in its whole length, instead of repeating just the last element (which is the reason why they are called Patterns :slight_smile: )

with the above info, treehelpers from ghpythonlib gives you a very sharp weapon to use, and I believe it will work in the vast majourity of your cases

at this link you can find some examples of treehelpers in action, but also an example of how to code data trees directly in Python: https://developer.rhino3d.com/guides/rhinopython/grasshopper-datatrees-and-python/

Can you please upload a GH file with your data internalized?