Key Error: 'WALL BOTTOM EXTENSION DIST PARAM'

Hi there.
Sorry it’s me again, with further issues.

After struggling with extracting any data from a Speckle stream sent via the Revit plugin, I have tried running a new script found at: [GitHub - oswaldohb/chatSpeckle-ai] by @Oswaldo_Hernandez (GitHub - oswaldohb/chatSpeckle-ai)- which looks great! - however I did not manage to get much out of it…
The images below show that whatever category I choose, errors are always raised. When choosing the category @Views, and selecting the parameter Edited by, I do receive a KeysError.

I have tried to copy and adapt a number of scripts derived by tutorials, but I am still failing with data extraction, and cannot get past a variety of KeyErrors I do not understand.

Even when trying with the default stream from the ChatSpeckle-ai, and trying to interrogate Walls data,

I do encounter the following error:
KeyError: 'WALL_BOTTOM_EXTENSION_DIST_PARAM'

What resources can you please point me to, that can help me troubleshoot this?

Thanks

This could be due to the fact the script is expecting such parameter, but your walls don’t have it?

Here’s a list of Revit BuiltInParameters and their display values (what you see in the interface): BuiltInParameter Enumeration

I’d suggest stripping down the script to the simplest form of it, and then adding a bit by bit newer logic.

@teocomi thanks for your reply. What puzzles me is that the error came from using @Oswaldo_Hernandez 's own stream, not mine!

The error appears to arise from:
get_parameter_by_name(element, s_param, dict) within the function:

with data:
    st.subheader("Data 📚")
    result_data = []
    for element in category_elements:
        dict = {}
        for s_param in selected_parameters:
            get_parameter_by_name(element, s_param, dict)
        result_data.append(dict)
    result_DF = pd.DataFrame.from_dict(result_data)

I will try to follow the resource you suggest, but any further support would be greatly appreciate as I would not have imagined to struggle that much with it!
Thanks!

Hey @andrea.botti ,

Looks like this commit was made from an earlier version of our connector. Just so you know, retrieving categories and category elements from a commit sent from a newer version of our connector will be different.

The problem here is with the logic introduced when retrieving parameter objects, getting values from those objects etc. I wrote those back in the day as an exercise to understand how specklepy works.

As @teocomi mentioned, problem is not all walls have those properties. For example, both Basic walls and Curtain walls are under Walls category but their properties will be different. Basic walls won’t have the properties of a curtain wall (e.g. Adjust for a Mullion size). So we need to future-proof the logic to get and check those parameters.

First problem with the code is how it gets parameters from the selected category. It gets the first item from the selected category, gets all its parameters and shows that as an input. Instead it should loop through all walls and get all parameters, store them in a set and show that as an input to the user.

First, I created a separate function to get API names of parameters. Take a look:

# get all parameter API names
def get_api_parameters_from_category(commit_data, selected_category):
    # get all elements from selected category
    selected_category_elements = commit_data[selected_category] 
    # create an empty set to store api parameters
    selected_category_parameters = set() 
    # loop through selected category elements
    for element in selected_category_elements: 
        # get all their parameters and add them to the set
        selected_category_parameters.update(element.parameters.get_dynamic_member_names()) 
    # return api parameters as a sorted list
    return sorted(selected_category_parameters) 

Feel free to add this to the functions section.

Then I modified the get_parameter_names() function:

# get all user facing names of all parameters
def get_parameter_names(commit_data, selected_category):
    # get all elements belonging to the selected category
    selected_category_elements = commit_data[selected_category]
    # get their API parameters using the function we previously created.
    api_parameters = get_api_parameters_from_category(commit_data, selected_category)
    # create an empty set to store parameter names.
    selected_category_parameter_names = set()
    #  loop through every element in selected category
    for element in selected_category_elements:
        # do a nested loop for every API parameter
        for param in api_parameters:
            # create an empty list to store parameter names for every element
            param_names = []
            # 📌 Check if parameter name exists in the parameters list of the object: THIS IS IMPORTANT. 
            # You can turn a Speckle object into a dictionary using `__dict__` method. 
            if param in element.parameters.__dict__:
                # After this check we are sure that this object has this parameter. So we can get its name from the objects.
                param_names.append(element.parameters[param].name)
            # append parameter names to the empty list
            selected_category_parameter_names.update(param_names)
    # again, return parameter names as a sorted list.
    return sorted(selected_category_parameter_names)

:pushpin: How to check if an object has the parameter value?

I also modified the get_parameter_by_name() method so it doesn’t crash if an element doesn’t have that parameter. Here is the code:

#get parameter value by parameter name
def get_parameter_by_name(element, parameter_name, dict):
    for parameter in parameters:
        # 📌 Check if parameter exists in the object
        if parameter in  element["parameters"].__dict__:
            # Now we are sure the element has the parameter we are trying to get. Let's get it's name.
            key = element.parameters[parameter].name
            # check if the parameter name is equal to the parameter we are looking for
            if key == parameter_name:
                # if so, add it to the dict.
                dict[key] = element["parameters"][parameter]["value"]
    return dict

Here is the full code I modified. I did not get any errors. Let me know if you get any errors:
chatSpeckle.py (5.2 KB)

3 Likes

thank you very much @gokermu !

1 Like