Templates#
Templates are functions which generate RDF graphs.
How to Define Templates#
YAML Format#
The most common way of defining a Template is as a YAML document. Several Templates can be expressed in the same YAML file. A YAML template has several components:
the name of the template is the top-level key of the YAML document
a template must have a body key, whose value is an RDF graph (see below for details on the graph)
a template may have an optional key, whose value is a list of parameter names
a template may have a dependencies key, whose value is a list of dependency dictionaries (see below for details on dependencies)
The body of a template is an RDF graph. Parameters are nodes/edges in the graph which exist in the urn:___param___#
namespace (this can be bound to any prefix, but is commonly bound to P
or p
).
When a template is evaluated, the parameters are replaced with the provided bindings.
The parameters of a template are exactly those which appear in the RDF Graph body.
The other elements of a template’s definition – optional
, dependencies
, etc – refer to the name of a parameter without the urn:___param___#
prefix.
For example, a parameter would be defined in the body as P:sensor
or urn:___param___#sensor
(these are equivalent, provided there is a @prefix P: <urn:___param___#>
line), but the other elements of the template would refer to this parameter simply as sensor
Here is an example of two YAML templates.
vav-cooling-only:
body: >
@prefix p: <urn:___param___#> .
@prefix brick: <https://brickschema.org/schema/Brick#> .
p:name a brick:VAV ;
brick:hasPoint p:ztemp, p:occ, p:co2, p:dat ;
brick:hasPart p:dmp ;
brick:feeds p:zone .
optional: ['occ', 'co2']
dependencies:
- template: damper
args: {"name": "dmp"}
- template: https://brickschema.org/schema/Brick#HVAC_Zone
library: https://brickschema.org/schema/1.3/Brick
args: {"name": "zone"}
- template: https://brickschema.org/schema/Brick#Zone_Air_Temperature_Sensor
library: https://brickschema.org/schema/1.3/Brick
args: {"name": "ztemp"}
- template: https://brickschema.org/schema/Brick#Occupancy_Sensor
library: https://brickschema.org/schema/1.3/Brick
args: {"name": "occ"}
- template: https://brickschema.org/schema/Brick#CO2_Level_Sensor
library: https://brickschema.org/schema/1.3/Brick
args: {"name": "co2"}
- template: https://brickschema.org/schema/Brick#Discharge_Air_Temperature_Sensor
library: https://brickschema.org/schema/1.3/Brick
args: {"name": "dat"}
damper:
body: >
@prefix P: <urn:___param___#> .
@prefix brick: <https://brickschema.org/schema/Brick#> .
P:name a brick:Damper .
SHACL Shapes#
BuildingMOTIF can also infer a template from certain SHACL shape definitions.
This happens when a Library is loaded into BuildingMOTIF that contains an RDF graph; this can happen by loading the RDF graph directly (via Library.load(ontology_graph="path to graph")
)
or by loading in a directory that contains RDF graphs (via Library.load(directory="directory with .ttl files")
).
Given an RDF graph, BuildingMOTIF will create a template for each instance of sh:NodeShape
provided that it is also an instance of owl:Class
.
In the following RDF graph, BuildingMOTIF would create a tempalte for vav_shape
but not sensor_shape
:
@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix unit: <http://qudt.org/vocab/unit/> .
@prefix : <urn:shape1/> .
:vav_shape a sh:NodeShape, owl:Class ;
sh:targetClass brick:VAV ;
sh:property [
sh:path brick:hasPoint ;
sh:qualifiedValueShape [ sh:node :sensor_shape ] ;
sh:qualifiedMinCount 1 ;
] ;
.
:sensor_shape a sh:NodeShape ;
sh:class brick:Temperature_Sensor ;
sh:property [
sh:path brick:hasUnit ;
sh:hasValue unit:DEG_C ;
] ;
.
BuildingMOTIF will create a name
parameter for the shape automatically. It will create a parameter for each Property Shape on the input Node Shape if
that Property Shape has one of sh:class
, sh:node
or sh:datatype
inside; use of sh:qualifiedValueShape
is permitted.
Only Property Shapes with a sh:minCount
or sh:qualifiedMinCount
greater than 1 will be included.
If the Property Shape contains a sh:name
parameter, the string value of sh:name
will be used as the name of the parameter; otherwise, BuildingMOTIF
ll invent a new name (P:pX
where X is an incrementing integer).
The name of the template is the IRI of the SHACL Node Shape.
Template Dependencies#
Dependencies between templates can be done explicitly (for YAML-based templates) or implicitly (for SHACL-based templates).
Remember to load libraries containing dependencies before loading in libraries containing the dependents. For example, it is generally recommended to import your base ontologies (Brick, ASHRAE 223P, etc) before any application libraries, as the application libraries will depend on concepts defined in the ontologies.
Explicit Template Dependencies#
A template dependency is a dictionary with the following keys:
template
(required): the name of the templatelibrary
(optional): the name of the Library from which to load the templateargs
(required): a key-value dictionary mapping the dependency parameter names to this template’s (the depndent’s) parameter names. Values bound to the dependent’s parameter will also be bound to the dependency’s corresponding parameter; we call this “binding” the dependent’s parameter to the dependency’s parameter
When depending on another template, it is not necessary to bind all of the parameters. This affects how inlining works.
The template in the example below has two dependencies. The first dependency is on another template called damper
in the same Library as vav-cooling-only
. The name
parameter
of the damper
template will be bound to the value of the dmp
parameter in the vav-cooling-only
template.
The second dependency is on the HVAC Zone template in the Brick ontology (this template is inferred automatically from the brick:HVAC_Zone
Node Shape when the Brick library is loaded).
The name
parameter of the HVAC zone template will be bound to the zone
parameter in the vav-cooling-only
template.
vav-cooling-only:
body: >
@prefix p: <urn:___param___#> .
@prefix brick: <https://brickschema.org/schema/Brick#> .
p:name a brick:VAV ;
brick:hasPoint p:ztemp, p:occ, p:co2, p:dat ;
brick:hasPart p:dmp ;
brick:feeds p:zone .
optional: ['occ', 'co2']
dependencies:
- template: damper
args: {"name": "dmp"}
- template: https://brickschema.org/schema/Brick#HVAC_Zone
library: https://brickschema.org/schema/1.3/Brick
args: {"name": "zone"}
Implicit Template Dependencies#
BuildingMOTIF will add dependencies to a template inferred from a Node Shape in each of the following cases.
if a Property Shape on the Node Shape refers to a Node Shape through
sh:class
(the Node Shape dependency will probably also be anowl:Class
)if a Property Shape on the Node Shape refers to a Node Shape through
sh:node
if the Node Shape refers to another Node Shape through
sh:node
The template inferred from the vav_shape
Node Shape below will have 2 dependencies.
The first dependency is on the :Air_Flow_Sensor
template, also defined in this library.
The invented parameter name for the first property shape (probably p1
) will be bound to the name
parameter of the inferred :Air_Flow_Sensor
template.
The second dependency is on the brick:Air_Temperature_Sensor
template which is defined in the Brick ontology.
The temp_sensor
parameter of the vav_shape
template will be bound to the name
parameter of the inferred brick:Air_Temperature_Sensor
template.
BuildingMOTIF will search all of the graphs in owl:imports
for definitions of Node Shapes if they are not defined in the current library.
Because :Air_Flow_Sensor
is defined in the same graph as vav_shape
, BuildingMOTIF can find its definition easily.
Because brick:Air_Temperature_Sensor
is not defined in the graph below, BuildingMOTIF searches the imported graph https://brickschema.org/schema/1.3/Brick
for
the definition.
@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix unit: <http://qudt.org/vocab/unit/> .
@prefix : <urn:shape/> .
: a owl:Ontology ;
owl:imports <https://brickschema.org/schema/1.3/Brick> .
:vav_shape a sh:NodeShape, owl:Class ;
sh:targetClass brick:VAV ;
sh:property [
sh:path brick:hasPoint ;
sh:qualifiedValueShape [ sh:node :Air_Flow_Sensor ] ;
sh:qualifiedMinCount 1 ;
] ;
sh:property [
sh:path brick:hasPoint ;
sh:name "temp_sensor" ;
sh:qualifiedValueShape [ sh:node brick:Air_Temperature_Sensor ] ;
sh:qualifiedMinCount 1 ;
] ;
.
:Air_Flow_Sensor a sh:NodeShape, owl:Class ;
sh:class brick:Air_Flow_Sensor ;
sh:property [
sh:path brick:hasUnit ;
sh:hasValue unit:DEG_C ;
sh:minCount 1 ;
]
.
Template Inlining#
Coming soon…
Template Evaluation#
Coming soon…