TypeError: getset_descriptor is not callable

Hello all,

I have created a simple sample script to obtain volume information of a wall that changes the unconnected height parameter for every iteration in the for loop. However, I run into the following error:

Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
Traceback (most recent call last):
File “”, line 20, in
TypeError: getset_descriptor is not callable

I was able to achieve a similar workflow using the periodic run. However, I am wondering why this script is not working. I have attached a screenshot of the script that I have use. Could someone please look into this.

Thanks in advance!

My guess is because you’re attempting to repeatedly edit an element and report the values in a single transaction, but I can’t confirm without spending more time than I have to give at the moment. Try adding a transaction into the loop and see what happens.

2 Likes

Hello Jacob!

Thanks for your suggestion. I tried adding a transaction into the loop and used the GetParameterValueByName function instead to resolve the errors. However, the value of volume does not update for each iteration and returns the same number. Could you please have a look at it. I have attached a screen grab of the script and the output.

Thanks!

Post the full dyn and the rvt - otherwise you’re asking someone to donate ~2-4 hours of their time retyping your code, reworking your graph so we have correct inputs, and reworking your Revit model so it can pull the correct information.

In the end I don’t think this is the correct method - Project Refinery is a better fit.

Project3.rvt (1.4 MB) calcVolume.dyn (6.5 KB)

Hello,

I apologize for not attaching the rvt and dyn graph earlier. Please have a look at it.

I agree with you that project refinery is a better fit. However, I have the similar issue where it displays the same value for volume, despite changing the height. I am simply looking at both methods to understand and see which works better for more complex iterations.

Thanks for your help! I really appreciate it.

The Reinfery method will need to avoid the use of Revit objects in the calculations. I’ll see if I can come up with a workable example in that context later this week. :slight_smile:

1 Like

Ok… hope you’re sitting down for this one as I got a bit wordy… Sorry in advance.

First up, this is all likely a VERY bad idea. Revit is an extremely complex system and iterating over a wide set of options so you can find an optimal value when you could just do similar iterations in an external database and find the resulting optimal via multi-objective optimization is likely a more stable and complete way to go. That said, you and others have asked for it, so I unleash this onto the world. Use this at your own risk and with great caution.

Onto the ‘how to’ for transaction based testing of results.

Because you’re trying to work with the computed volume, the usual methods for Revit interaction via Dynamo are invalidated. This is because Dynamo wraps all results in a single transaction (This post by @Konrad_K_Sobon is my goto for explaining this - he breaks down the why as well as I ever could), and as you noticed Revit can’t compute the volume until the transaction is done. So since you were using a single transaction (even inside the loop that is the result), you only ever saw the ‘last’ volume value which was returned as that was the state the parameter was in when you closed the transaction.

Side note: Calculated built-in parameters are the Schrödinger’s cat of Revit. When you open the box (close the transaction) the cat (parameter) will report whatever it’s status is, but while the box is closed (transaction is open) the cat (parameter) exists in all possible states (values).

So since you need to get multiple transactions inside one event, but likely don’t want to clutter your undo menu and risk corrupting your data set with so many ‘set, get, start again’ transactions we have to leverage transaction’s big brother: Transaction Groups. The psudo code is something like this:

  • First close the transaction that is likely open - sorry to say you’ll likely suffer with other aspects of Dynamo-Revit interaction as a result of this, but you’re stuck going full python build up on much (all?) of this anyway so that shouldn’t be too much of an issue.

  • Create a transaction group which we’ll eventually roll back, and start the transaction group.

  • For each value you want to iterate over, create a new named transaction, perform the stuff you want to perform, append the data results, and commit the transaction to the database.

  • When you’re done with the list you want to iterate over, roll-back the transaction group so it’s like you were never there.

Overall a case like yours looks something like this:

And the Revit model starts and finishes looking like this (note the complete lack of undo capability):

And the graph which does this looks like this:

So… if all of that sounded scary, it’s because it is. This is a VERY big dive into completely code based exploration, in a way which doesn’t even attempt to parse out any errors which will likely occur (wall joins, elements no longer connected after modification, host not within a wall, etc.).

So what would I recommend instead? Look hard at moving to a Refinery based workflow. If you’re curious give it a shot and post back, I’ll try and help out there as well (though perhaps in not as in depth of a dive - there is less confusion there after all).

Edit: Added the graph in the example
calcVolume with transactions.dyn (10.2 KB)

5 Likes

Hello Jacob,

First and foremost, I would like to thank you for the elaborate explanation. I must say that the side notes, references and suggestions that you included makes the post interesting to read and easy to understand. :slightly_smiling_face:

Based on your recommendation, I have tried to accomplish a similar task using Refinery. I have attached the Dynamo script here (I tried tagging you on a post I made earlier on the Refinery forum - but it wouldn’t let me).

The issue in Refinery with using the randomize function is that changing the height does not give me the corresponding value for volume; it rather returns a constant value as seen in the image below.

Lilli Smith, suggested trying ‘get’ instead of ‘set’ geometry from Revit and then caching it with the remember node. Since the ‘select model element node’ cannot be fed directly to the ‘Remember node’ I had to convert the element to geometry. But, this resulted in the wall element losing its parameters as seen below.

Which is the reason why, I turned towards using a full python build to accomplish this task. Using a complete python build is far more complex that I had earlier envisioned (agreed).

Again, I would like to appreciate the time and effort that you took with answering my questions. I look forward to the .dyn that you worked on and your feedback for the Refinery workflow.

Thanks!

Project2.rvt (1.4 MB) refinery trial 1.dyn (23.9 KB)

DYN is attached to the previous post now. What type of thing are you optimizing for? Refinery is likely the ‘quicker’ path to where you want to be (shouldn’t be shocking as that is what it’s intended for). Just a matter of reframing your perspective.

1 Like

I am looking at MOO for building life cycle energy (operating and embodied energy). I started with volume calculation for a single wall as a sample trial. I would be using BOQ’s to compute embodied energy as I progress further along.
Update: The refinery script works! It definitely was a much simpler solution.

Thanks for your help!

Thats a good use and something I have thought about tackling a few times now. More time consuming that I have tile for at the moment, mostly due to my not knowing how to do the manual calculation for embodied energy for a single wall, never mind the full Dynamo version. Hopefully you’ll be Willing and able to share the results and the story as you go.

Feel free to reach out to me via PM here if you have any other road blocks along the way or if you just want to discuss your ideas and plan.