Documentation guide for python script to connect grasshopper

Hello all please let me know of documentation guide for python script to connect to grasshopper. The script mentioned in tutorial here has different output geometry when connected with different script instead of sample grasshopper.gh

Hi @murali.manoj,

As far as I understand you are trying to build a connection with a Grasshopper file with multiple Context Bake components (with unique names!).

In the tutorial the EvaluateDefinition function returns a large dictionary with a lot of information, you could debug / print it, in order to investigate it and retrieve the data. I usually use the following as a snippet to retrieve certain outputs (based on the name of the Context Bake components.

# Evaluate the Grasshopper definition
output = gh.EvaluateDefinition(
    workdir + 'your_complicated_script.gh',
    input_trees
)


def get_value_from_tree(datatree: dict, param_name: str):
    """Get first value in datatree that matches given param_name"""
    for val in datatree['values']:
        if val["ParamName"] == param_name:
            return val['InnerTree']['{0}'][0]['data']

# Create a new rhino3dm file and save resulting geometry to file
file = rhino3dm.File3dm()
output_geometry = get_value_from_tree(output, "Output01")
output_geometry = get_value_from_tree(output, "Output02")
obj = rhino3dm.CommonObject.Decode(json.loads(output_geometry))
file.Objects.AddMesh(obj)

# Save Rhino file to working directory
file.Write(workdir + 'geometry.3dm', 7)

TypeError: Controller.run_grasshopper() missing 1 required positional argument: โ€˜input_treesโ€™

may i know how to resolve this

is there a common python script that runs grasshopper script ?

Hi @murali.manoj ,

The script you see on this tutorial is our common python script. If you have multiple Context Bake components with meshes, we recommend merging them into 1 Context Bake component.

Only if you want to reuse some data (by e.g. saving it into Storage, or displaying numbers in a graph), weโ€™d recommend the script above. The python script in the tutorial is most used, but if you want to, you can retrieve your other Context Bakes as previously mentioned. I did paste a slightly outdated snippet here above, so let me update it. Please note that this is a snippet, so it should give you an idea on how to solve it for your problem!

Snippet
import ...

class Parametrization(ViktorParametrization):
    intro = Text("## Grasshopper app \n This app parametrically generates and visualizes a 3D model of a box using a Grasshopper script. \n\n Please fill in the following parameters:")

    # Input fields
    width = NumberField('Width', default=5)
    length = NumberField('Length', default=6)
    height = NumberField('Height', default=7)


class Controller(ViktorController):
    label = 'My Entity Type'
    parametrization = Parametrization

    @GeometryView("Geometry", duration_guess=10, x_axis_to_right=True, update_label='Run Grasshopper')
    def run_grasshopper(self, params, **kwargs):
        grasshopper_script_path = Path(__file__).parent / "sample_box_grasshopper.gh"
        script = File.from_path(grasshopper_script_path)
        input_parameters = dict(params)

        # Run the Grasshopper analysis and obtain the output data
        analysis = GrasshopperAnalysis(script=script, input_parameters=input_parameters)
        analysis.execute(timeout=30)
        output = analysis.get_output()

        def get_value_from_tree(datatree: dict, param_name: str):
          """Get first value in datatree that matches given param_name"""
          for val in datatree['values']:
              if val["ParamName"] == param_name:
                  return val['InnerTree']['{0}'][0]['data']
        
        # Save something to storage (assuming this is e.g. a number)
        data = get_value_from_tree(output, "Output01")
        storage = Storage()
        storage.set('some_data', data=File.from_data(data), scope='entity')
        
        # Use the data
        file3dm = rhino3dm.File3dm()
        output_geometry = get_value_from_tree(output, "Output02")
        obj = rhino3dm.CommonObject.Decode(json.loads(output_geometry))
        file3dm.Objects.Add(obj)

        # Write to geometry_file
        geometry_file = File()
        file3dm.Write(geometry_file.source, version=7)
        return GeometryResult(geometry=geometry_file, geometry_type="3dm")

Hopefully that helps you out!