Files
IfcOpenShell/src/bonsai/scripts/classifications/brick_classifiction.py
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

109 lines
4.0 KiB
Python
Raw Normal View History

2023-08-11 12:30:39 -07:00
import ifcopenshell
from brickschema.graph import Graph
2024-07-26 12:19:21 +10:00
class Generator:
2023-08-11 12:30:39 -07:00
def __init__(self):
2024-07-26 12:19:21 +10:00
self.file = ifcopenshell.file(schema="IFC4")
2023-08-11 12:30:39 -07:00
self.schema = Graph()
2024-07-26 12:19:21 +10:00
self.schema.load_file("Brick.ttl") # stable 1.3 loaded from external file
2023-08-11 12:30:39 -07:00
def generate(self):
2024-07-26 12:19:21 +10:00
classification = self.file.create_entity(
"IfcClassification",
**{
"Source": "Brick",
"Edition": "August-11",
"EditionDate": "2023-08-11",
"Name": "Brick",
"Description": "",
"Location": "https://brickschema.org/schema/Brick",
"ReferenceTokens": [],
}
)
2026-02-27 11:15:30 +05:00
query = self.schema.query("""
2023-08-11 12:30:39 -07:00
PREFIX brick: <https://brickschema.org/schema/Brick#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT ?entity ?label ?definition WHERE {
{
?entity rdfs:subClassOf* brick:Equipment .
} UNION {
?entity rdfs:subClassOf* brick:Location .
} UNION {
?entity rdfs:subClassOf* brick:Collection .
} UNION {
?entity rdfs:subClassOf* brick:Alarm .
} UNION {
?entity rdfs:subClassOf* brick:Sensor .
}
FILTER NOT EXISTS {
?entity owl:deprecated true .
}
OPTIONAL {
?entity rdfs:label ?label .
?entity skos:definition ?definition .
}
}
GROUP BY ?entity
2026-02-27 11:15:30 +05:00
""")
2023-08-11 12:30:39 -07:00
# create references dictionary
references = {}
for row in query:
# location is the entity URI
location = row.get("entity")
2024-07-26 12:19:21 +10:00
2023-08-11 12:30:39 -07:00
# description is the entity's definition
description = row.get("definition")
if not description:
2024-07-26 12:19:21 +10:00
description = ""
2023-08-11 12:30:39 -07:00
# name is the entity's label if it exists, else the name in the URI
name = row.get("label")
if not name:
name = location.split("#")[-1].replace("_", " ")
# create the reference
2024-07-26 12:19:21 +10:00
ref = self.file.create_entity(
"IfcClassificationReference",
**{"Location": location, "Description": description, "Identification": name, "Name": name}
)
2023-08-11 12:30:39 -07:00
# get all parents of the entity
2026-02-27 11:15:30 +05:00
query = self.schema.query("""
2023-08-11 12:30:39 -07:00
PREFIX brick: <https://brickschema.org/schema/Brick#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?parent WHERE {
brick:{entity} rdfs:subClassOf ?parent .
}
2026-02-27 11:15:30 +05:00
""".replace("{entity}", location.split("#")[-1]))
2023-08-11 12:30:39 -07:00
# filter parents for the brick entity
for row in query:
parent = row.get("parent").toPython()
2024-07-26 12:19:21 +10:00
if "brickschema.org" in parent and parent in references.keys():
2023-08-11 12:30:39 -07:00
# some parents are not a brick type, so those should be ignored
# some entities have multiple parents that are a brick type
# since the query traverses down the graph, we can assume at least one parent has been seen, so pick that one
# if no parent is found, then it must mean it is the top level of what was queried
break
parent = None
2024-07-26 12:19:21 +10:00
# assign reference source
2023-08-11 12:30:39 -07:00
if parent:
ref.ReferencedSource = references[parent]
else:
ref.ReferencedSource = classification
# save this reference for future reference sources
references[location.toPython()] = ref
2024-07-26 12:19:21 +10:00
self.file.write("Brick.ifc")
2023-08-11 12:30:39 -07:00
generator = Generator()
2024-07-26 12:19:21 +10:00
generator.generate()