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.
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.
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.
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
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,
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.
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.
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.
clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
import System
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])
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.
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
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.