Automatically recomputing dictionaries in GHPython

Hi,

I have data stored in a dictionary and for every parameter change instead of the dictionary to update automatically, I have to manually recompute. Is this from my end or is this a known issue?

What my example file attached is trying to do is loop through empty word lists and fill them with characters relative to the word size and size of the given characters (sliders). When you adjust the sliders, it doesn’t update the output till you recompute.

dictionary issues.gh (7.2 KB)

Thanks

1 Like

Hi @aononye,

You can use the following function by @AndersDeleuran to manually recompute a component. It basically works like a Timer.

import Grasshopper as gh

def update_component():
    """Updates this component, similar to using a Grasshopper timer."""
    # written by Anders Deleuran (andersholdendeleuran.com)
    def call_back(e):
        """Defines a callback action"""
        ghenv.Component.ExpireSolution(False)
    # Get the Grasshopper document
    ghDoc = ghenv.Component.OnPingDocument() 
    # Schedule this component to expire
    ghDoc.ScheduleSolution(1, \
        gh.Kernel.GH_Document.GH_ScheduleDelegate(call_back))

In general, individual components only recompute, if they are explicitly asked to, for instance if one or more of their inputs change, or you animate them to do so otherwise.
Your first GHPython has a static input (i.e. panel) that doesn’t change much and thus the component only runs once, as the panel gets connected to it.
Your second GHPython component is getting recomputed each time that you change one of the merged sliders.

1 Like

This issue is not related to recomputing – it’s related to modifying the only instance of the dictionary that you create, but doing so more downstrams, and observing the results of the same computation on the modified dictionary.

When you use Grasshopper types, GH will create copies of objects for you before they are passed to scripting components. Because we create here our types ourselves, these will just be passed as a reference. All non-Grasshopper types are unknown to Grasshopper, so it does not know how to copy them. You need to copy them yourself, or you can keep inputs unchanged and work only on outputs.

image

A simple way to avoid this, would be to just use copy, a specialized Python module, and make a deep copy of the dictionary before modifying it. A more elegant way would be not to touch the input dictionary, and make changes only on a new data set. To help with this option, you could use a read-only (immutable) type, for example frozenset or tuples and other immutable types. This would prevent accidental modifications downstream.

Also, as a minor comment, it seems that the concept of dictionary is not used sparingly where it’s required here, but has become very pervasive, to the detriment of readability. Dictionaries are meant to be used for particular lookup problems, especially because they are heavy on memory, but also a little difficult/big in implementation and with some problem in behavior where there are many hash collisions. Here, where the word_id is just an increasing integer, this really could just be a list. Again, nothing prohibits you from doing it this way. total_wordSize, avail_wordSize etc could also just be attributes in a class. My 2 cents.

copy-issues.gh (8.2 KB)

3 Likes

Thanks for your response again.

I will look into the read only type much but in the meantime, i will use deep copy as i am familiar with it.

To your last point on the use of dictionaries, i total agree. I have a more robust data structure which benefits from dictionaries lookup abilities. I just used this as an example to illustrate my issues with dictionaries. I appreciate the advice though.

Thanks for your response.

Totally get how component recomputing works now. Will attempt the solution below first as @piac explained its not a recomputing issue.