Skip to content

Commit

Permalink
Use ref-schema instead of old internal Brick relationships (#384)
Browse files Browse the repository at this point in the history
* add ref-schema

* removing old ref definitions and replacing with ref-schema

* fix definition in example

* update ref schema

* re-add ifc attributes

* add new ref-schema; fix issues

* update ifc linking example
  • Loading branch information
gtfierro authored Apr 26, 2022
1 parent 99ee808 commit ab464a7
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 206 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.PHONY: format

Brick.ttl: bricksrc/*.py bricksrc/*.ttl bricksrc/definitions.csv generate_brick.py
Brick.ttl: bricksrc/*.py bricksrc/*.ttl bricksrc/definitions.csv generate_brick.py support/*.ttl
mkdir -p extensions
python generate_brick.py
cd shacl && python generate_shacl.py
Expand Down
3 changes: 0 additions & 3 deletions bricksrc/definitions.csv
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,6 @@ https://brickschema.org/schema/Brick#hasPart,The subject is composed in part of
https://brickschema.org/schema/Brick#hasPoint,The subject has a source of telemetry identified by the object. In some systems the source of telemetry may be represented as a digital/analog input/output point,
https://brickschema.org/schema/Brick#hasQUDTReference,Points to the relevant QUDT definition,
https://brickschema.org/schema/Brick#hasTag,The subject has the given tag,
https://brickschema.org/schema/Brick#hasTimeseriesId,The unique identifier (primary key) for this TimeseriesReference in some database,
https://brickschema.org/schema/Brick#hasUnit,The QUDT unit associated with this Brick entity (usually a Brick Point instance or Entity Property),
https://brickschema.org/schema/Brick#isAssociatedWith,The tag is associated with the given class,
https://brickschema.org/schema/Brick#isFedBy,,
Expand All @@ -1133,5 +1132,3 @@ https://brickschema.org/schema/Brick#isPointOf,The subject is a source of teleme
https://brickschema.org/schema/Brick#isRegulatedBy,,
https://brickschema.org/schema/Brick#isTagOf,,
https://brickschema.org/schema/Brick#regulates,The subject contributes to or performs the regulation of the substance given by the object,
https://brickschema.org/schema/Brick#storedAt,A reference to where the data for this TimeseriesReference is stored,
https://brickschema.org/schema/Brick#timeseries,Relates a Brick point to the TimeseriesReference that indicates where and how the data for this point is stored,
156 changes: 1 addition & 155 deletions bricksrc/entity_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Entity property definitions
"""
from rdflib import Literal
from .namespaces import BRICK, RDFS, SKOS, UNIT, XSD, SH, BSH, BACNET, IFC
from .namespaces import BRICK, RDFS, SKOS, UNIT, XSD, SH, BSH, REF

# these are the "relationship"/predicates/OWL properties that
# relate a Brick entity to a structured value.
Expand Down Expand Up @@ -535,157 +535,3 @@
},
},
}

digital_representation_props = {
BRICK.hasExternalReference: {
SKOS.definition: Literal("A digital reference of the entity"),
RDFS.domain: BRICK.Point,
},
BRICK.hasBACnetReference: {
RDFS.subPropertyOf: BRICK.hasExternalReference,
SKOS.definition: Literal("BACnet metadata"),
RDFS.domain: BRICK.Point,
RDFS.range: BRICK.BACnetReference,
},
BRICK.hasIFCReference: {
RDFS.subPropertyOf: BRICK.hasExternalReference,
SKOS.definition: Literal("IFC metadata"),
RDFS.domain: BRICK.Entity,
RDFS.range: BRICK.IFCReference,
},
BRICK.timeseries: {
SKOS.definition: Literal("Metadata for accessing related timeseries data"),
RDFS.subPropertyOf: BRICK.hasExternalReference,
RDFS.domain: BRICK.Point,
RDFS.range: BRICK.TimeseriesReference,
},
BRICK.hasCSVReference: {
RDFS.subPropertyOf: BRICK.timeseries,
SKOS.definition: Literal("Metadata for accessing CSV data"),
RDFS.domain: BRICK.Point,
RDFS.range: BRICK.CSVReference,
},
}

digital_representation_shapes = {
BRICK.CSVReference: {
"properties": {
BRICK["fileLocation"]: {
SKOS.definition: Literal(
"Location of the CSV file defining the project"
),
"datatype": XSD.string,
},
},
},
BRICK.IFCReference: {
"properties": {
IFC["hasProjectReference"]: {
SKOS.definition: Literal(
"Reference to an IFC Project object, containing the project ID"
),
SH["class"]: IFC.Project,
},
IFC["globalID"]: {
SKOS.definition: Literal(
"The global ID of the entity in the IFC project"
),
"datatype": XSD.string,
},
IFC["name"]: {
SKOS.definition: Literal("Name of the entity in IFC"),
"datatype": XSD.string,
"optional": True,
},
},
},
IFC.Project: {
"properties": {
IFC["projectID"]: {
SKOS.definition: Literal("The ID of the project"),
"datatype": XSD.string,
},
IFC["fileLocation"]: {
SKOS.definition: Literal(
"Location of the IFC file defining the project"
),
"datatype": XSD.string,
"optional": True,
},
},
},
BRICK.BACnetReference: {
RDFS.subClassOf: BACNET.Object,
"properties": {
"or": [
{
BACNET["object-identifier"]: {
"import_from": "support/bacnet.ttl",
"datatype": XSD.string,
# TODO: is this correct?
# SH["pattern"]: Literal("^[A-Za-z0-9-]+:[0-9]+$"),
},
BACNET["object-name"]: {
"import_from": "support/bacnet.ttl",
"datatype": XSD.string,
SH["minLength"]: Literal(1),
"optional": True,
},
BACNET["object-type"]: {
"import_from": "support/bacnet.ttl",
"datatype": XSD.string,
"optional": True,
},
BACNET["description"]: {
"import_from": "support/bacnet.ttl",
"datatype": XSD.string,
"optional": True,
},
BRICK["read-property"]: {
"datatype": XSD.string,
"optional": True,
SH["defaultValue"]: Literal("present-value"),
},
},
{
BRICK["BACnetURI"]: {
"datatype": XSD.string,
"optional": True,
SKOS.definition: Literal(
"Clause Q.8 BACnet URI scheme: bacnet:// <device> / <object> [ / <property> [ / <index> ]]"
),
},
},
],
BACNET["objectOf"]: {
"import_from": "support/bacnet.ttl",
SH["class"]: BACNET.BACnetDevice,
SH["minCount"]: Literal(1),
},
},
},
BRICK.TimeseriesReference: {
SKOS.definition: Literal(
"Metadata describing where and how the data for a Brick Point is stored"
),
"properties": {
BRICK.hasTimeseriesId: {
"datatype": XSD.string,
SKOS.definition: Literal(
"The identifier for the timeseries data corresponding to this point"
),
},
BRICK.storedAt: {
"optional": True,
"datatype": XSD.string,
SKOS.definition: Literal(
"Refers to a database storing the timeseries data for the related point. Properties on this class are *to be determined*; feel free to add arbitrary properties onto Database instances for your particular deployment"
),
},
},
},
}

# merge the dictionaries
entity_properties.update(digital_representation_props)
shape_properties.update(digital_representation_shapes)
2 changes: 2 additions & 0 deletions bricksrc/namespaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
BRICK = Namespace("https://brickschema.org/schema/Brick#")
TAG = Namespace("https://brickschema.org/schema/BrickTag#")
BSH = Namespace("https://brickschema.org/schema/BrickShape#")
REF = Namespace("https://brickschema.org/schema/Brick/ref#")
SH = Namespace("http://www.w3.org/ns/shacl#")
XSD = Namespace("http://www.w3.org/2001/XMLSchema#")
OWL = Namespace("http://www.w3.org/2002/07/owl#")
Expand Down Expand Up @@ -38,6 +39,7 @@ def bind_prefixes(g):
g.bind("sosa", SOSA)
g.bind("sh", SH)
g.bind("brick", BRICK)
g.bind("ref", REF)
g.bind("tag", TAG)
g.bind("vcard", VCARD)
g.bind("bsh", BSH)
Expand Down
19 changes: 10 additions & 9 deletions examples/bacnet/bacnet.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,33 @@
@prefix bacnet: <http://data.ashrae.org/bacnet/2020#> .
@prefix unit: <http://qudt.org/vocab/unit/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ref: <https://brickschema.org/schema/Brick/ref#> .

bldg:sample-device a bacnet:BACnetDevice ;
bacnet:device-instance 123 ;
bacnet:hasPort [ a bacnet:Port ] .

bldg:ts1 a brick:Zone_Air_Temperature_Sensor ;
brick:hasUnit unit:DEG_C ;
brick:BACnetRepresentation [
ref:hasExternalReference [
bacnet:object-identifier "analog-value,5" ;
bacnet:object-name "BLDG-Z410-ZATS" ;
bacnet:objectOf bldg:sample-device ;
] ;
brick:timeseries [
brick:hasTimeseriesId "756e1623-914f-4415-9000-b1b10ce8f5c9" ;
brick:storedAt "postgres://1.2.3.4:5432/mydata" ;
ref:hasExternalReference [
ref:hasTimeseriesId "756e1623-914f-4415-9000-b1b10ce8f5c9" ;
ref:storedAt "postgres://1.2.3.4:5432/mydata" ;
] ;
.

bldg:ts2 a brick:Zone_Air_Temperature_Sensor ;
brick:hasUnit unit:DEG_C ;
brick:BACnetRepresentation [
brick:BACnetURI "bacnet://123/analog-value,5/present-value" ;
ref:hasExternalReference [
ref:BACnetURI "bacnet://123/analog-value,5/present-value" ;
bacnet:objectOf bldg:sample-device ;
] ;
brick:timeseries [
brick:hasTimeseriesId "4245c136-f95c-4ef5-a0d9-a7d04f1d97f9" ;
brick:storedAt "postgres://1.2.3.4:5432/mydata" ;
ref:hasExternalReference [
ref:hasTimeseriesId "4245c136-f95c-4ef5-a0d9-a7d04f1d97f9" ;
ref:storedAt "postgres://1.2.3.4:5432/mydata" ;
] ;
.
28 changes: 15 additions & 13 deletions examples/ifc/ifc-with-new-reference.ttl
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
@prefix bldg: <urn:example#> .
@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix brickifc: <https://brickschema.org/extension/ifc#> .
@prefix ref: <https://brickschema.org/schema/Brick/ref#> .

bldg:space a brick:Space ;
brick:hasIFCReference [ brickifc:globalID "123" ;
brickifc:hasProjectReference bldg:ifc_project ;
brickifc:name "Example Space" ] .
ref:hasExternalReference [ a ref:IFCReference ;
ref:hasIfcProjectReference bldg:ifc_project ;
ref:ifcGlobalID "123" ;
ref:ifcName "Example Space" ] .

bldg:space2 a brick:Space ;
brick:hasIFCReference [ brickifc:globalID "124" ;
brickifc:hasProjectReference bldg:ifc_project ;
brickifc:name "Example Space" ] .
ref:hasExternalReference [ a ref:IFCReference ;
ref:hasIfcProjectReference bldg:ifc_project ;
ref:ifcGlobalID "124" ;
ref:ifcName "Example Space" ] .

bldg:space3 a brick:Space ;
brickifc:hasIFCReference [ brickifc:globalID "abc123" ;
brickifc:hasProjectReference bldg:ifc_project ] .
ref:hasExternalReference [ a ref:IFCReference ;
ref:hasIfcProjectReference bldg:ifc_project ;
ref:ifcGlobalID "abc123" ] .


bldg:ifc_project a brickifc:Project ;
brickifc:fileLocation "file://./building.ifc" ;
brickifc:projectID "abc" .
bldg:ifc_project a ref:ifcProject ;
ref:ifcFileLocation "file://./building.ifc" ;
ref:ifcProjectID "abc" .
26 changes: 14 additions & 12 deletions examples/ifc/ifc.ttl
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
@prefix bldg: <urn:example#> .
@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix brickifc: <https://brickschema.org/extension/ifc#> .
@prefix ref: <https://brickschema.org/schema/Brick/ref#> .

bldg:ifc_project a brickifc:Project ;
brickifc:projectID "abc" ;
brickifc:fileLocation "file://./building.ifc" ;
bldg:ifc_project a ref:ifcProject ;
ref:ifcProjectID "abc" ;
ref:ifcFileLocation "file://./building.ifc" ;
.

bldg:space a brick:Space ;
brick:hasIFCReference [
brickifc:hasProjectReference bldg:ifc_project ;
brickifc:globalID "123" ;
brickifc:name "Example Space" ;
ref:hasExternalReference [
a ref:IFCReference ; # can be inferred
ref:hasIfcProjectReference bldg:ifc_project ;
ref:ifcGlobalID "123" ;
ref:ifcName "Example Space" ;
] .

bldg:space2 a brick:Space ;
brick:hasIFCReference [
brickifc:hasProjectReference bldg:ifc_project ;
brickifc:globalID "124" ;
brickifc:name "Example Space" ;
ref:hasExternalReference [
a ref:IFCReference ; # can be inferred
ref:hasIfcProjectReference bldg:ifc_project ;
ref:ifcGlobalID "124" ;
ref:ifcName "Example Space" ;
] .

# link.py in this folder programatically adds the IFC reference to this entity
Expand Down
12 changes: 6 additions & 6 deletions examples/ifc/link.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import brickschema
from brickschema.namespaces import Namespace, BRICK
from brickschema.namespaces import Namespace, BRICK, REF, A
from rdflib import Literal

BLDG = Namespace("urn:example#")
BRICKIFC = Namespace("https://brickschema.org/extension/ifc#")

g = brickschema.Graph()
g.load_file("ifc.ttl") # our example file

# get project
project = list(g.query("SELECT ?proj WHERE { ?proj a brickifc:Project }"))[0][0]
project = list(g.query("SELECT ?proj WHERE { ?proj a ref:ifcProject }"))[0][0]

link = {
"brick": BLDG["space3"],
Expand All @@ -19,10 +18,11 @@
g.add(
(
link["brick"],
BRICKIFC.hasIFCReference,
REF.hasExternalReference,
[
(BRICKIFC.hasProjectReference, project),
(BRICKIFC.globalID, Literal(link["ifc"])),
(A, REF.IFCReference),
(REF.hasIfcProjectReference, project),
(REF.ifcGlobalID, Literal(link["ifc"])),
],
)
)
Expand Down
4 changes: 3 additions & 1 deletion generate_brick.py
Original file line number Diff line number Diff line change
Expand Up @@ -781,8 +781,10 @@ def add_definitions():
for ttlfile in glob.glob("bricksrc/*.ttl"):
G.parse(ttlfile, format="turtle")

logging.info(f"Brick ontology compilation finished! Generated {len(G)} triples")
# add ref-schema definitions
G.parse("support/ref-schema.ttl", format="turtle")

logging.info(f"Brick ontology compilation finished! Generated {len(G)} triples")

extension_graphs = {"shacl_tag_inference": shaclGraph}

Expand Down
Loading

0 comments on commit ab464a7

Please sign in to comment.