Python for Loop - Hide Grid Bubbles

Hello Dynamo Community :slight_smile:

I´m using this working python code to set the visibility of grid bubbles in a single view.

g = UnwrapElement(IN[0])
bx = UnwrapElement(IN[1])
by = UnwrapElement(IN[2])
v = UnwrapElement(IN[3])

TransactionManager.Instance.EnsureInTransaction(doc)

for g, bx, by in zip(g, bx, by):
	if bx and by:
		g.ShowBubbleInView(DatumEnds.End1,v)
		g.HideBubbleInView(DatumEnds.End0,v)
	elif bx:
		g.HideBubbleInView(DatumEnds.End1,v)
		g.ShowBubbleInView(DatumEnds.End0,v)
	elif by:
		g.ShowBubbleInView(DatumEnds.End1,v)
		g.HideBubbleInView(DatumEnds.End0,v)	
	else:
		g.HideBubbleInView(DatumEnds.End0,v)
		g.ShowBubbleInView(DatumEnds.End1,v)
	
TransactionManager.Instance.TransactionTaskDone()

doc.Regenerate()

OUT = g

Now i want to make it work for a list of views, this is my failing attempt. Notice that for every view there is a list of grids and a list of bools.

g = UnwrapElement(IN[0])
bx = UnwrapElement(IN[1])
by = UnwrapElement(IN[2])
v = UnwrapElement(IN[3])
views = v

TransactionManager.Instance.EnsureInTransaction(doc)

for views in v:

	for g, bx, by in zip(g, bx, by):
		if bx and by:
			g.ShowBubbleInView(DatumEnds.End1,v)
			g.HideBubbleInView(DatumEnds.End0,v)
		elif bx:
			g.HideBubbleInView(DatumEnds.End1,v)
			g.ShowBubbleInView(DatumEnds.End0,v)
		elif by:
			g.ShowBubbleInView(DatumEnds.End1,v)
			g.HideBubbleInView(DatumEnds.End0,v)	
		else:
			g.HideBubbleInView(DatumEnds.End0,v)
			g.ShowBubbleInView(DatumEnds.End1,v)
	
TransactionManager.Instance.TransactionTaskDone()

doc.Regenerate()

OUT = g

Thankful for any advice :slight_smile:
Kind Regards

Hi,

so you have said:

for views in v:

But then you have said:

g.ShowBubbleInView(DatumEnds.End1,v)

instead of:

g.ShowBubbleInView(DatumEnds.End1,views)

The warning gives a clue ‘List object’ has no attribute… Instead of ‘Grid object’ for example… I also try to comment my way through the code, explaining it to myself helps me better understand what is going on. Also trying to keep everything very obvious helps me :slight_smile:

viewList = UnwrapElement(IN[3]) #unwrap everything in the list
TransactionManager.Instance.EnsureInTransaction(doc) #start transaction
for view in viewList: #get each view in the viewList
   for g, bx, by in zip(g, bx, by): #run through everything in the sub lists, keep them the same length
   	if bx and by: #boolean check
   		g.ShowBubbleInView(DatumEnds.End1,view) #in each view show if the end value is true

Hope that helps,

Mark

3 Likes

Hello Mark,

Ok, so now i understand the Loop method:

TransactionManager.Instance.EnsureInTransaction(doc)

for ELEMENT in LIST: 

     (do something with ELEMENT)

TransactionManager.Instance.TransactionTaskDone()

But I´m still getting the error.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference("RevitServices")
import RevitServices

from RevitServices.Persistence import *
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

g = UnwrapElement(IN[0])
bx = UnwrapElement(IN[1])
by = UnwrapElement(IN[2])
viewList = UnwrapElement(IN[3]) #unwrap everything in the list

TransactionManager.Instance.EnsureInTransaction(doc)

for view in viewList: #get each view in the viewList

	for g, bx, by in zip(g, bx, by): #run through everything in the sub lists, keep them the same length
		if bx and by: #boolean check
			g.ShowBubbleInView(DatumEnds.End1,view) #in each view show if the end value is true
			g.HideBubbleInView(DatumEnds.End0,view)
		elif bx:
			g.HideBubbleInView(DatumEnds.End1,view)
			g.ShowBubbleInView(DatumEnds.End0,view)
		elif by:
			g.ShowBubbleInView(DatumEnds.End1,view)
			g.HideBubbleInView(DatumEnds.End0,view)	
		else:
			g.HideBubbleInView(DatumEnds.End0,view)
			g.ShowBubbleInView(DatumEnds.End1,view)
	
TransactionManager.Instance.TransactionTaskDone()

doc.Regenerate()

OUT = g

You’re still not looping properly. This is the same ideas as for ELEMENT in LIST: but you’re essentially writing for LIST in LIST:. You’re reducing the list variable to the same list variable when you need to define a new variable for the items within each list.

4 Likes

Nick is right… All this is so abstract, so I like to try and help myself…

gridList = UnwrapElement(IN[0])
headList = UnwrapElement(IN[1])
tailList = UnwrapElement(IN[2])
viewList = UnwrapElement(IN[3]) #unwrap everything in the list
for grid, head, tail in zip(gridList, headList, tailList): #run through everything in the sub lists, keep them the same length
	if head and tail: #boolean check
		grid.ShowBubbleInView(DatumEnds.End1,view) #in each view make the end show if the value is true

Hope that helps,

Mark

2 Likes

@Nick_Boyts

Ok, i have to loop views in list because i don´t have a single view anymore, i have a list of views.
Because i have a list of views, the grid list and bool list now turn into a L3 list with sublists. This is why i have to loop again to get items x,y,z in xList, yList, zList. Right?

@Mark.Ackerley

Code gets looking better and better, using proper names really helps! But still the same error.

gridList = UnwrapElement(IN[0])
headList = UnwrapElement(IN[1])
tailList = UnwrapElement(IN[2])
viewList = UnwrapElement(IN[3]) #unwrap everything in the list

TransactionManager.Instance.EnsureInTransaction(doc)

for view in viewList: #get each view in the viewList

	for grid, head, tail in zip(gridList, headList, tailList): #run through everything in the sub lists, keep them the same length
		if head and tail: #boolean check
			grid.ShowBubbleInView(DatumEnds.End1,view) #in each view show if the end value is true
			grid.HideBubbleInView(DatumEnds.End0,view)
		elif head:
			grid.HideBubbleInView(DatumEnds.End1,view)
			grid.ShowBubbleInView(DatumEnds.End0,view)
		elif tail:
			grid.ShowBubbleInView(DatumEnds.End1,view)
			grid.HideBubbleInView(DatumEnds.End0,view)	
		else:
			grid.HideBubbleInView(DatumEnds.End0,view)
			grid.ShowBubbleInView(DatumEnds.End1,view)
	
TransactionManager.Instance.TransactionTaskDone()

You only need an extra dimension to your grid lists if the grid list changes with each view. If the grids are the same for each view then you would still have just one list of grids and one list of views. They way that your code is written write now you loop through each view individually, and with each view you also loop through each grid in your list of grids. If you have separate grids for each view then you would need to zip them all together because each sublist corresponds with its paired sublists from the other lists.

3 Likes

For every view there is a sublist of grids and a sublist of bools. Different for every view.
These grids and bools have the same list structure. I´m zip´ing these grids and bools together.

So far so good.

Now each view loops through the full zip list of grids and bools and this is causing the error.
What i want is to loop each view with the right sublist. The Sublist with the same index as the view.

Am i right? :thinking: And how can i do that in Python?`

Kind Regards :slight_smile:

Right. So zipping lists together essentially means that your code will loop through them together. This is necessary when you have multiple items or sublists that have to be utilized specifically with their counterpart in a different list. You still have to loop through the items in a sublist when looping through zipped lists though. So your code would look something like this:

gridList = UnwrapElement(IN[0])
headList = UnwrapElement(IN[1])
tailList = UnwrapElement(IN[2])
viewList = UnwrapElement(IN[3])

for grids, heads, tails, view in zip(gridList, headList, tailList, viewList):
     for grid, head, tail in zip(grids, heads, tails):

The first loop goes through each subitem. For grids and booleans this is a sublist matched up with the view in the viewList. But from there you still need to go one more level to get the actual grid and boolean values so you loop one more time.

2 Likes

It really is amazing what i can achieve with visual programming and how lost I am at python :smiley:

So Sublists always require looping twice, check.

Now there is no error, but it´s also nothing happening, bubbles don´t change.

So in section views nothing happens if i select one view and nothing happens if i select more views.
BUT if i select a planview it works, if i select multiple ones it only works for one planview.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference("RevitServices")
import RevitServices

from RevitServices.Persistence import *
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

gridList = UnwrapElement(IN[0])
headList = UnwrapElement(IN[1])
tailList = UnwrapElement(IN[2])
viewList = UnwrapElement(IN[3]) #unwrap everything in the list

TransactionManager.Instance.EnsureInTransaction(doc)

for grids, heads, tails, view in zip(gridList, headList, tailList, viewList):

	for grid, head, tail in zip(grids, heads, tails):
		if head and tail: #boolean check
			grid.ShowBubbleInView(DatumEnds.End1,view) #in each view show if the end value is true
			grid.HideBubbleInView(DatumEnds.End0,view)
		elif head:
			grid.HideBubbleInView(DatumEnds.End1,view)
			grid.ShowBubbleInView(DatumEnds.End0,view)
		elif tail:
			grid.ShowBubbleInView(DatumEnds.End1,view)
			grid.HideBubbleInView(DatumEnds.End0,view)	
		else:
			grid.HideBubbleInView(DatumEnds.End0,view)
			grid.ShowBubbleInView(DatumEnds.End1,view)
	
TransactionManager.Instance.TransactionTaskDone()

doc.Regenerate()

OUT = viewList

You’ll probably have to upload an example file at this point.

2 Likes

While preparing a revit and dynamo sample file i found out the code is in fact working, for multiple sectionviews and for multiple planviews:

bubblefff

But it does not work if only a single view is selected.
I´m not shure if i need this code line anymore at the beginning?!

for view in viewList:

So i tried it with and without this line, these are the 2 error messages:

Next I tried if i need to make a list out of the single view:

So if we can solve this last piece then I’ll continue to find out why the code does not work in my other projects.

Revit and Dyn file attached:

Grid_Bubbles.rvt (476 KB)
Grid_Bubbles.dyn (22.0 KB)

Thanks for your

You need to make the main code work for lists since you could potentially have a list of views. To make it work with a single view you then just convert the single view to a list of 1 view.

1 Like

Thats what i did and this gives the “Grid is not itterable” error, i think because the grid list has only 2 levels if one view is selected.

You need to maintain the same list levels regardless of whether you have multiple views or one view. This is for all your lists/sublists. One view means one list of grids, but you need to convert that (as well as the booleans) to a list with sublists.

1 Like

Right, it works also for one view if I add that list level :slight_smile:

Unfortunately you can’t just convert the single item to a list like that because you would also be adding another list level to your multiple views. You need to use a conditional statement to only add a list level when dealing with a single view.

Many python scripts will check to see if an input is already a list or not and convert accordingly.

if isinstance(IN[0], list):
	views = UnwrapElement(IN[0])
else:
	views = [UnwrapElement(IN[0])]

You could also use a codeblock if you’re confident your views will always be a single item or flattened list.

i = List.Count(input)==1?0:1;
[[input],input][i];
3 Likes

I understand, but don´t know how to (in python) handle the Grids and Bools that are already lists .
For them I would have to check if input=list@level2 and if thats true to make a list@level3 out of it.

Regarding the views we got it workin :slight_smile:

gridList = UnwrapElement(IN[0])
headList = UnwrapElement(IN[1])
tailList = UnwrapElement(IN[2])

if isinstance(IN[3], list):
	viewList = UnwrapElement(IN[3])
else:
	viewList = [UnwrapElement(IN[3])]

You would assume that the view structure determines the grid and boolean structures as well. If the view input is a single item then it gets wrapped in a list and the grids and booleans also get wrapped in an extra list layer.

Python Code
if isinstance(IN[0], list):
	views = UnwrapElement(IN[0])
	grids = UnwrapElement(IN[1])
else:
	views = [UnwrapElement(IN[0])]
	grids = [UnwrapElement(IN[1])]
	
OUT = views,grids
1 Like

This works :slight_smile:

if isinstance(IN[3], list):
	viewList = UnwrapElement(IN[3])
	gridList = UnwrapElement(IN[0])
	headList = UnwrapElement(IN[1])
	tailList = UnwrapElement(IN[2])
else:
	viewList = [UnwrapElement(IN[3])]
	gridList = [UnwrapElement(IN[0])]
	headList = [UnwrapElement(IN[1])]
	tailList = [UnwrapElement(IN[2])]

full code:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference("RevitServices")
import RevitServices

from RevitServices.Persistence import *
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

if isinstance(IN[3], list):
	viewList = UnwrapElement(IN[3])
	gridList = UnwrapElement(IN[0])
	headList = UnwrapElement(IN[1])
	tailList = UnwrapElement(IN[2])
else:
	viewList = [UnwrapElement(IN[3])]
	gridList = [UnwrapElement(IN[0])]
	headList = [UnwrapElement(IN[1])]
	tailList = [UnwrapElement(IN[2])]

TransactionManager.Instance.EnsureInTransaction(doc)


for grids, heads, tails, view in zip(gridList, headList, tailList, viewList):

	for grid, head, tail in zip(grids, heads, tails):
		if head and tail: #boolean check
			grid.ShowBubbleInView(DatumEnds.End1,view) #in each view show if the end value is true
			grid.HideBubbleInView(DatumEnds.End0,view)
		elif head:
			grid.HideBubbleInView(DatumEnds.End1,view)
			grid.ShowBubbleInView(DatumEnds.End0,view)
		elif tail:
			grid.ShowBubbleInView(DatumEnds.End1,view)
			grid.HideBubbleInView(DatumEnds.End0,view)	
		else:
			grid.HideBubbleInView(DatumEnds.End0,view)
			grid.ShowBubbleInView(DatumEnds.End1,view)
	
TransactionManager.Instance.TransactionTaskDone()

doc.Regenerate()

OUT = viewList
1 Like