diff --git a/src/ifcfm/ifcfm/__init__.py b/src/ifcfm/ifcfm/__init__.py index 8eaefb279b..5b81f02367 100644 --- a/src/ifcfm/ifcfm/__init__.py +++ b/src/ifcfm/ifcfm/__init__.py @@ -41,27 +41,21 @@ class Parser: self.file = None self.preset = preset self.categories = {} - self.get_category_elements = {} - self.get_element_data = {} + self.config = None self.get_custom_element_data = {} self.duplicate_keys = [] if isinstance(preset, str): module = importlib.import_module(f"ifcfm.{preset}") - self.get_category_elements = getattr(module, "get_category_elements") - self.get_element_data = getattr(module, "get_element_data") - elif isinstance(preset, dict): - self.get_category_elements = preset["get_category_elements"] - self.get_element_data = preset["get_element_data"] + self.config = getattr(module, "config") else: - self.get_category_elements = getattr(preset, "get_category_elements") - self.get_element_data = getattr(preset, "get_element_data") + self.config = preset def parse(self, ifc_file): - for category_name, get_category_elements in self.get_category_elements.items(): + for category_name, category_config in self.config["categories"].items(): self.categories.setdefault(category_name, {}) - for element in get_category_elements(ifc_file): - get_element_data = self.get_element_data[category_name] + for element in category_config["get_category_elements"](ifc_file): + get_element_data = category_config["get_element_data"] if isinstance(get_element_data, dict): data = {} @@ -71,7 +65,7 @@ class Parser: data = get_element_data(ifc_file, element) or {} get_custom_element_data = self.get_custom_element_data.get(category_name, lambda x, y: None) - if isinstance(get_element_data, dict): + if isinstance(get_custom_element_data, dict): custom_data = {} for key, query in get_custom_element_data.items(): custom_data[key] = ifcopenshell.util.selector.get_element_value(element, query) @@ -87,6 +81,15 @@ class Parser: self.duplicate_keys.append((self.categories[category_name][key], data)) self.categories[category_name][key] = data + def exclude_categories(self, names): + for name in names: + if name in self.config["categories"]: + del self.config["categories"][name] + + def exclude_element_data(self, category, names): + headers = self.config["categories"][category]["headers"] + self.config["categories"][category]["headers"] = [h for h in headers if h not in names] + class Writer: def __init__(self, parser): @@ -105,8 +108,9 @@ class Writer: empty = self.config.get("empty", empty) bool_true = self.config.get("bool_true", bool_true) bool_false = self.config.get("bool_false", bool_false) - for category, data in self.parser.categories.items(): - headers = self.config.get("categories", {}).get(category, {}).get("headers", []) + for category, config in self.config["categories"].items(): + data = self.parser.categories.get(category, None) + headers = config["headers"] if not data: self.categories[category] = {"headers": headers, "rows": []} diff --git a/src/ifcfm/ifcfm/basic.py b/src/ifcfm/ifcfm/basic.py index 5e3d81d3dd..f4ccb81ffd 100644 --- a/src/ifcfm/ifcfm/basic.py +++ b/src/ifcfm/ifcfm/basic.py @@ -228,26 +228,6 @@ def get_property(psets, pset_name, prop_name, decimals=None): return round(result, decimals) -get_category_elements = { - "Facilities": get_facilities, - "Storeys": get_storeys, - "Spaces": get_spaces, - "Zones": get_zones, - "ElementTypes": get_element_types, - "Elements": get_elements, - "Systems": get_systems, -} - -get_element_data = { - "Facilities": get_facility_data, - "Storeys": get_storey_data, - "Spaces": get_space_data, - "Zones": get_zone_data, - "ElementTypes": get_element_type_data, - "Elements": get_element_data, - "Systems": get_system_data, -} - config = { "colours": { "h": "dddddd", # Header data @@ -278,6 +258,8 @@ config = { ], "colours": "ppppreeeeesss", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_facilities, + "get_element_data": get_facility_data, }, "Storeys": { "headers": [ @@ -292,6 +274,8 @@ config = { ], "colours": "ppreeees", "sort": [{"name": "Elevation", "order": "ASC"}, {"name": "Name", "order": "ASC"}], + "get_category_elements": get_storeys, + "get_element_data": get_storey_data, }, "Spaces": { "headers": [ @@ -308,11 +292,15 @@ config = { ], "colours": "ppprreeess", "sort": [{"name": "LevelName", "order": "ASC"}, {"name": "Name", "order": "ASC"}], + "get_category_elements": get_spaces, + "get_element_data": get_space_data, }, "Zones": { "headers": ["Name", "SpaceName", "AuthorOrganizationName", "AuthorDate", "ModelSoftware", "ModelID"], "colours": "prreee", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_zones, + "get_element_data": get_zone_data, }, "ElementTypes": { "headers": [ @@ -333,6 +321,8 @@ config = { ], "colours": "pppreeeeesssss", "sort": [{"name": "ModelObject", "order": "ASC"}, {"name": "Name", "order": "ASC"}], + "get_category_elements": get_element_types, + "get_element_data": get_element_type_data, }, "Elements": { "headers": [ @@ -356,6 +346,8 @@ config = { ], "colours": "prrrreeeeesssssss", "sort": [{"name": "TypeName", "order": "ASC"}, {"name": "Name", "order": "ASC"}], + "get_category_elements": get_elements, + "get_element_data": get_element_data, }, "Systems": { "headers": [ @@ -369,6 +361,8 @@ config = { ], "colours": "pppreee", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_systems, + "get_element_data": get_system_data, }, }, } diff --git a/src/ifcfm/ifcfm/cobie.py b/src/ifcfm/ifcfm/cobie.py index 9eb6eb0d7c..6f385f1278 100644 --- a/src/ifcfm/ifcfm/cobie.py +++ b/src/ifcfm/ifcfm/cobie.py @@ -30,6 +30,8 @@ import ifcopenshell.util.classification # https://github.com/opensourceBIM/COBie-plugins/tree/master/COBieShared/src/org/bimserver/cobie/shared/serialization/util # Some settings are also defined here: # https://github.com/opensourceBIM/COBie-plugins/blob/master/COBiePlugins/lib/IfcToCobieConfig.xml +# Note that the following categories are not implemented in the BIMServer COBie-Plugins: +# Impact, Coordinate, Issue, Picklist def get_contacts(ifc_file): @@ -494,16 +496,16 @@ def get_type_data(ifc_file, element): pset_metadata = {} pset_mapping = { "manufacturer": {"Manufacturer"}, - "model_number": {"ModelNumber", "ArticleNumber", "ModelLabel"}, + "model_number": {"ModelNumber", "ArticleNumber", "ModelReference"}, "warranty_guarantor_parts": {"WarrantyGuarantorParts", "PointOfContact"}, "warranty_guarantor_labor": {"WarrantyGuarantorLabor", "PointOfContact"}, "warranty_description": {"WarrantyDescription", "WarrantyIdentifier"}, "replacement_cost": {"ReplacementCost", "Replacement Cost", "Replacement", "Cost"}, - "nominal_length": {"NominalLength", "OverallLength"}, - "nominal_width": {"NominalWidth", "Width"}, + "nominal_length": {"NominalLength", "OverallLength", "Length"}, + "nominal_width": {"NominalWidth", "OverallWidth", "Width"}, # https://github.com/opensourceBIM/COBie-plugins/blob/master/COBiePlugins/lib/IfcToCobieConfig.xml#L104 "nominal_height": {"NominalHeight", "Height"}, # Original has a typo "Heght" - "model_reference": {"ModelReference", "Reference"}, + "model_reference": {"ModelLabel"}, # I believe this is what the intention was, not "ModelReference". "shape": {"Shape"}, "size": {"Size"}, "color": {"Color", "Colour"}, @@ -1139,52 +1141,6 @@ def get_sheet_name(element): return "Resource" -get_category_elements = { - "Contact": get_contacts, - "Facility": get_facilities, - "Floor": get_floors, - "Space": get_spaces, - "Zone": get_zones, - "Type": get_types, - "Component": get_components, - "System": get_systems, - "Assembly": get_assemblies, - "Connection": get_connections, - "Spare": get_spares, - "Resource": get_resources, - "Job": get_jobs, - # "Impact": get_impacts, # Not implemented for some reason in BIMServer COBie-Plugins - "Document": get_documents, - "Attribute": get_attributes, - # Not implemented for some reason in BIMServer COBie-Plugins - # "Coordinate": get_coordinates, - # "Issue": get_issues, - # "Picklist": get_picklists, -} - -get_element_data = { - "Contact": get_contact_data, - "Facility": get_facility_data, - "Floor": get_floor_data, - "Space": get_space_data, - "Zone": get_zone_data, - "Type": get_type_data, - "Component": get_component_data, - "System": get_system_data, - "Assembly": get_assembly_data, - "Connection": get_connection_data, - "Spare": get_spare_data, - "Resource": get_resource_data, - "Job": get_job_data, - # "Impact": get_impact_data, - "Document": get_document_data, - "Attribute": get_attribute_data, - # "Coordinate": get_coordinate_data, - # "Issue": get_issue_data, - # "Picklist": get_picklist_data, -} - - config = { "colours": { "h": "c0c0c0", # Header data @@ -1225,6 +1181,8 @@ config = { ], "colours": "rrrrrreeeoooooooooo", "sort": [{"name": "Email", "order": "ASC"}], + "get_category_elements": get_contacts, + "get_element_data": get_contact_data, }, "Facility": { "headers": [ @@ -1253,6 +1211,8 @@ config = { ], "colours": "ririrriiiireeeeeeeoooo", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_facilities, + "get_element_data": get_facility_data, }, "Floor": { "headers": [ @@ -1269,6 +1229,8 @@ config = { ], "colours": "ririeeeooo", "sort": [{"name": "Elevation", "order": "ASC"}, {"name": "Name", "order": "ASC"}], + "get_category_elements": get_floors, + "get_element_data": get_floor_data, }, "Space": { "headers": [ @@ -1288,6 +1250,8 @@ config = { ], "colours": "ririrreeeoooo", "sort": [{"name": "FloorName", "order": "ASC"}, {"name": "Name", "order": "ASC"}], + "get_category_elements": get_spaces, + "get_element_data": get_space_data, }, "Zone": { "headers": [ @@ -1303,6 +1267,8 @@ config = { ], "colours": "ririreeeo", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_zones, + "get_element_data": get_zone_data, }, "Type": { "headers": [ @@ -1344,6 +1310,8 @@ config = { ], "colours": "riririiriririeeeooiorrroooooooooooo", "sort": [{"name": "ExternalObject", "order": "ASC"}, {"name": "Name", "order": "ASC"}], + "get_category_elements": get_types, + "get_element_data": get_type_data, }, "Component": { "headers": [ @@ -1369,6 +1337,8 @@ config = { {"name": "TypeName", "order": "ASC"}, {"name": "Name", "order": "ASC"}, ], + "get_category_elements": get_components, + "get_element_data": get_component_data, }, "System": { "headers": [ @@ -1384,8 +1354,10 @@ config = { ], "colours": "ririieeeo", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_systems, + "get_element_data": get_system_data, }, - "Assembly": { + "Assembly": { # Note that this is technically "not required" "headers": [ "Name", "CreatedBy", @@ -1401,8 +1373,10 @@ config = { ], "colours": "ririiiieeeo", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_assemblies, + "get_element_data": get_assembly_data, }, - "Connection": { + "Connection": { # Note that this is technically "not required" "headers": [ "Name", "CreatedBy", @@ -1421,6 +1395,8 @@ config = { ], "colours": "ririiiiiiieeeo", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_connections, + "get_element_data": get_connection_data, }, "Spare": { "headers": [ @@ -1439,6 +1415,8 @@ config = { ], "colours": "ririiieeeooo", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_spares, + "get_element_data": get_spare_data, }, "Resource": { "headers": [ @@ -1453,6 +1431,8 @@ config = { ], "colours": "ririeeeo", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_resources, + "get_element_data": get_resource_data, }, "Job": { "headers": [ @@ -1478,6 +1458,8 @@ config = { ], "colours": "ririiirriririeeeoii", "sort": [{"name": "TypeName", "order": "ASC"}, {"name": "TaskNumber", "order": "ASC"}], + "get_category_elements": get_jobs, + "get_element_data": get_job_data, }, "Document": { "headers": [ @@ -1499,6 +1481,8 @@ config = { ], "colours": "ririiiiirreeeoo", "sort": [{"name": "Name", "order": "ASC"}], + "get_category_elements": get_documents, + "get_element_data": get_document_data, }, "Attribute": { "headers": [ @@ -1518,6 +1502,8 @@ config = { ], "colours": "ririiirreeeoo", "sort": [{"name": "Category", "order": "ASC"}, {"name": "Name", "order": "ASC"}], + "get_category_elements": get_attributes, + "get_element_data": get_attribute_data, }, - } + }, }