Count the number of times all Family's have been placed

Hello all,

Do any of you have or know of a better way to count how many instances there are of all the project families? I am trying to figure out what our most used families are. I can get all of the placed elements but this takes forever and is not really needed. If you look at the graph below All Elements of Type and Family types of family take less than a second to cull there data but All elements of Family Type took about 10 minutes. I don’t actually need the Elements just want to know how many there are.

I was looking through the API but did not see anything useful. Still new to it.

Thanks for any help you can provide,

Steven

Ok I know my code is nowhere close to being correct but I think I am on the right track. Not sure how fast python can collect and match all of the elements vs All Elements of Family. This is the closest stuff in the API I could fine.

Idea for the code was taking from All Instances from Element Type.

This is what I want to do but I just want a count of all the instances. Sorry for my pore coding.

import clr
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument

elemtype = UnwrapElement(IN[0])
cat = UnwrapElement(IN[1])

if not isinstance(IN[0], list): elemtype = [elemtype]
allelem = FilteredElementCollector(doc).OfCategory(cat)

count = []

for type in elemtype:
	for x in allelem:
		if x.FamilyType.GetType() == type:
			count.append(x)
			

OUT = FilteredElementCollector(count).GetElementCount()

There’s really no way to count the number elements without getting the elements. However, you likely don’t need to check EVERY family in the project.

You can probably determine your most used categories for any give project type. Start there and check the family types for families within those specific categories instead of all families in a project. Depending on how accurately you can narrow down your top categories, you should save some time. It is possible that your top 5 categories or so make up the majority of families in your model though, so efficiency could vary.

Just my two cents…

Thanks Nick,

That is actually really helpful. I was thinking about filtering out curtain walls because of the amount of panels. I think I will dive deeper into the categories though because I know I am collecting stair nose families as well as many other unneeded families that are also slowing down the process.

Do you know if there is a faster though? Regardless of how much I narrow down the list it will still take time on large projects. I will embed the whole process into code block and see how much that helps as well.

I just know Zero Touch > Python > Code blocks > Dynamo nodes >>>>> Revit. I guess I am hoping for any time improvement over what I have developed.

Thanks for taking a look and providing some input.
Steven

I’ve found element collecting with Python to be noticeably faster than through code blocks and nodes. I would definitely start there.

Ok thats what I was thinking.

Do you know the equivalent of All Elements of Family Type in the API? I could not find anything.

What I was trying to achieve above was to collect all elements of the input elements category and then see if those element type matched the input element.

Or should I start by collecting all elements then getting the type then the family? This second way seems like it might be faster.
Thanks,

They do the same thing here: https://forums.autodesk.com/t5/revit-api-forum/select-elements-of-a-category-order-by-type-and-family/td-p/7454368

I’m not sure how good your Python is, but you should be able to translate that to Python.

My Python is not great but I will give it a go. May take some time but that is what I needed so thank you. I have been searching everywhere trying to find something.

Thanks Nick,

I would just create a multi-category schedule to count the families.

Bimorph has some useful nodes for exporting the schedule if that is what you want

5 Likes

That could work. I will look into it. Create the schedule then remove it after or it can just be left. Maybe it could be a template standard too. Should not add that much to a file.

Thanks Andrew,

Edit:
Looked into it a little more. Multi category Schedules do not supply Detail Items or annotations. Took roughly 15 seconds to set up though and reported 20,000 elements. This would be a great way to significantly reduce the amount of elements being called in dynamo. Great work around for what I am trying to do.
image

Trying a basic approach.
Almost there but I need some python wizard to chime in to finish it off, if possible…:face_with_raised_eyebrow:

Alternative workflow.
Big thanks the team and to @john_pierson for some inspirational code.
Uses the OST Categories to list all elements in RVT files in a directory.
Some additional list management may be necessary as this just totals the elements across all files.


OST_Categories.txt (19.7 KB)

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 DocumentManager
from RevitServices.Transactions import TransactionManager
import System

uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

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

items = IN[0]
cats = IN[1]

bics = System.Enum.GetValues(BuiltInCategory)

elements, categories = ,

for i in items:
doc = app.OpenDocumentFile(i)

t1, t2 = ,
for cat, bic in [(cat, bic) for cat in cats for bic in bics]:
if cat == bic.ToString():
t1.append(FilteredElementCollector(doc).WhereElementIsNotElementType().OfCategory(bic).ToElements())
t2.append(bic)

for z in range(len(t1)):
if t1[z]:
elements.append(t1[z])
categories.append(t2[z])

OUT = elements, categories

3 Likes

Thanks @Ewan_Opie Ewan,

I tried what you posted but it is not working. It just keeps exporting an empty list. The formatting was off a little bit in your code so I added the appropriate tabs and such. I have confirmed there are doors in the open project and and the project I specified to open as well as feeding the door category.

Do you see anything wrong?

Elements_3.dyn (10.1 KB)

I tried to modify your code to work on the open document (I think I got it correct) My 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 DocumentManager
from RevitServices.Transactions import TransactionManager
import System

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

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


cats = IN[0]

bics = System.Enum.GetValues(BuiltInCategory)

elements, categories = [], []


t1, t2 = [], []
for cat, bic in [(cat, bic) for cat in cats for bic in bics]:
	if cat == bic.ToString():
		t1.append(FilteredElementCollector(doc).WhereElementIsNotElementType().OfCategory(bic).ToElements())
		t2.append(bic)

for z in range(len(t1)):
	if t1[z]:
		elements.append(t1[z])
		categories.append(t2[z])

OUT = elements, categories

Your code with my formating

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 DocumentManager
from RevitServices.Transactions import TransactionManager
import System

uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

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

items = IN[0]
cats = IN[1]

bics = System.Enum.GetValues(BuiltInCategory)

elements, categories = [], []

for i in items:
	doc = app.OpenDocumentFile(i)

t1, t2 = [], []
for cat, bic in [(cat, bic) for cat in cats for bic in bics]:
	if cat == bic.ToString():
		t1.append(FilteredElementCollector(doc).WhereElementIsNotElementType().OfCategory(bic).ToElements())
		t2.append(bic)

for z in range(len(t1)):
	if t1[z]:
		elements.append(t1[z])
		categories.append(t2[z])

OUT = elements, categories

Your code in the Python node is fine.:+1:
Its just a bit picky, and wants to have lists as inputs not single elements. :wink:

I am smart I promise. Thanks for the help with the code and laps in thought.

The code you provided is a defiant solution to collecting all the data. Collected over 300,000 elements in about two minutes. Now I will just need to manually cull through the Categories list to see what all I actually need.

Thanks @Ewan_Opie for a great solution.

1 Like