forked from ArjanPeeters/IfcDashBoard
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIFCchecker.py
164 lines (148 loc) · 7.97 KB
/
IFCchecker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import ifcopenshell as ifc
import pprint as pp
import pandas as pd
import numpy as np
import os
import pathlib
import datachecks
import config
pd.set_option("display.max_rows", None, "display.max_columns", None, "display.max_colwidth", -1, "display.width", None)
props_to_check = ['LoadBearing', 'FireRating', 'IsExternal', 'AcousticRating', 'Phase']
ifc_files = []
for root, dirs, files in os.walk(config.file_directory): # get all IFC files in directory
for file in files:
if file.lower().endswith(".ifc"):
found_file = os.path.join(root.replace('/', '\\'), file)
print(found_file)
ifc_files.append(found_file)
print(ifc_files)
ProjectGlobalIds = {}
ifc_projects_df = pd.DataFrame()
ifc_buildingstoreys_df = pd.DataFrame()
ifc_elements_df = pd.DataFrame()
for file in ifc_files:
try:
ifc_file = ifc.open(file)
except OSError:
print(file)
project = ifc_file.by_type('IfcProject')[0]
if project.GlobalId in ProjectGlobalIds:
if ProjectGlobalIds[project.GlobalId] == os.path.basename(file):
print('File al gedaan:', project.GlobalId, os.path.basename(file), project.Name)
continue
ProjectGlobalIds[project.GlobalId] = os.path.basename(file)
print(project.GlobalId, os.path.basename(file), project.Name)
project_info = {
'ProjectGlobalId': project.GlobalId,
'ProjectName': project.Name,
'FileName': os.path.basename(file),
'ProjectApplicationName': project.OwnerHistory.OwningApplication.ApplicationFullName,
'ProjectOrganizationName': project.OwnerHistory.OwningUser.TheOrganization.Name
}
project_info_df = pd.Series(project_info) # turn dict into DataFrame Series
ifc_projects_df = ifc_projects_df.append(project_info_df, ignore_index=True) # add to DataFrame
# get all the stories!
building_stories = ifc_file.by_type('IfcBuildingStorey')
for storey in building_stories:
storey_info = {
'ProjectGlobalId': project.GlobalId,
'ProjectName': project.Name,
'StoreyGlobalId': storey.GlobalId,
'StoreyName': storey.Name,
'StoreyElevation': storey.Elevation
}
ifc_buildingstoreys_df = ifc_buildingstoreys_df.append(pd.Series(storey_info), ignore_index=True)
all_elements = ifc_file.by_type('IfcProduct')
for element in all_elements:
if element not in config.exclude_element_list:
PropertySets = {}
for check in props_to_check: # prepare a property dict with None elements
PropertySets['ElementProperty' + check] = None
for definition in element.IsDefinedBy:
if definition.is_a('IfcRelDefinesByProperties'):
if definition.RelatingPropertyDefinition.is_a('IfcPropertySet'):
if definition.RelatingPropertyDefinition.Name.lower().endswith("common"):
# check for properties in the Common PSets
for prop in definition.RelatingPropertyDefinition.HasProperties:
if prop.Name in props_to_check:
PropertySets['ElementProperty' + prop.Name] = prop.NominalValue[0]
if 'phas' in definition.RelatingPropertyDefinition.Name.lower():
# check for phasing PSets
PS = PropertySets['ElementPropertyPhase']
PropertySets['ElementPropertyPhase'] = '{Previous}{PName}:{PValue}'.format(
Previous=PS + "," if PS is not None else "",
PName=definition.RelatingPropertyDefinition.Name,
PValue=definition.RelatingPropertyDefinition.HasProperties[0].NominalValue[0]
)
# get classification associated with elements.
class_dict = {
'ClassificationName': None,
'ClassificationItemReference': None,
'ClassificationItemDescription': None,
'ClassificationAssessment': 'Niet gecodeerd'
} # start a dict with everything None
material_list = None # because an element might have more materials it can be a list
# Loop for getting associatetions for element
# Classifications and Materials
for has_associations in element.HasAssociations:
if has_associations.is_a('IfcRelAssociatesClassification'):
if has_associations.RelatingClassification.Name is not None:
class_dict = {
'ClassificationName': has_associations.Name,
'ClassificationItemReference': str(has_associations.RelatingClassification.ItemReference),
'ClassificationItemDescription': str(has_associations.RelatingClassification.Name),
'ClassificationAssessment': datachecks.rate_classification(
str(has_associations.RelatingClassification.ItemReference))
}
elif has_associations.is_a('IfcRelAssociatesMaterial'):
if has_associations.RelatingMaterial.is_a('IfcMaterial'):
material_list = has_associations.RelatingMaterial.Name
if has_associations.RelatingMaterial.is_a('IfcMaterialList'):
material_list = []
for materials in has_associations.RelatingMaterial.Materials:
material_list.append(materials.Name)
if has_associations.RelatingMaterial.is_a('IfcMaterialLayerSetUsage'):
material_list = []
for materials in has_associations.RelatingMaterial.ForLayerSet.MaterialLayers:
material_list.append(materials.Material.Name)
if isinstance(material_list, list) and len(material_list) == 1: # if only one item in list, discard list
material_list = material_list[0]
# Make Dict with info about the element
element_right_info = {
'ProjectGlobalId': project.GlobalId,
'ProjectName': project.Name,
'ElementGlobalId': element.GlobalId,
'ElementName': element.Name,
'ElementType': element.ObjectType, 'Type': element.is_a(),
'ElementMaterialName': material_list
}
element_right_info.update(class_dict) # append classification dict
element_right_info.update(PropertySets) # append propertysets dict
element_right_info_df = pd.Series(element_right_info) # turn dict into DataFrame Series
# append this row to the DataFrame
ifc_elements_df = ifc_elements_df.append(element_right_info_df, ignore_index=True)
# Setting indexes for the DataFrames
ifc_projects_df.set_index('ProjectGlobalId', inplace=True)
ifc_elements_df.set_index('ElementGlobalId', inplace=True)
ifc_buildingstoreys_df.set_index('StoreyGlobalId', inplace=True)
# print statements for viewing the data
print(ifc_elements_df)
print(ifc_elements_df.shape)
print(ifc_projects_df)
print(ifc_projects_df.shape)
print(ifc_buildingstoreys_df)
print(ifc_buildingstoreys_df.shape)
print(ifc_elements_df.ProjectName.value_counts())
print(ifc_elements_df.Type.value_counts())
print(ifc_elements_df.ClassificationName.value_counts())
print(ifc_elements_df.ClassificationItemReference.value_counts())
# write everything to excel.
filename = config.excel_file_name if config.excel_file_name.endswith('xlsx') else config.excel_file_name + '.xlsx'
if config.use_same_dir_for_output:
filename = config.file_directory + filename
writer = pd.ExcelWriter(filename, engine='xlsxwriter')
ifc_projects_df.to_excel(writer, 'projects')
ifc_elements_df.to_excel(writer, 'elements')
ifc_buildingstoreys_df.to_excel(writer, 'buildingstoreys')
writer.save()
print('____COMPLETE____')