Skip to content
Uniform metadata schema for buildings
Branch: master
Clone or download
jbkoh Merge pull request #58 from jbkoh/remove-sample
Remove examples from the schema file
Latest commit 458dfe2 Aug 15, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
tests change a filename more readable Aug 15, 2019
.gitignore augment gitignore with Python Aug 9, 2019
.gitmodules Remove tools directory Feb 1, 2017
Brick.ttl Update links (#54) Aug 8, 2019
LICENSE adding LICENSE Apr 30, 2019 Merge remote-tracking branch 'brick-owl-dl/master' into merge-brick-o… Aug 8, 2019 Introduce Parameter TagSet (#5) Jun 27, 2019 Introduce Parameter TagSet (#5) Jun 27, 2019 Introduce Parameter TagSet (#5) Jun 27, 2019 Update to v1.1.0 (#17) Aug 8, 2019 Update links (#54) Aug 8, 2019 Update to v1.1.0 (#17) Aug 8, 2019 Introduce Parameter TagSet (#5) Jun 27, 2019
requirements.txt Introduce Parameter TagSet (#5) Jun 27, 2019 more defs Jul 6, 2019 Introduce Parameter TagSet (#5) Jun 27, 2019 Introduce Parameter TagSet (#5) Jun 27, 2019 Update to v1.1.0 (#17) Aug 8, 2019 Introduce Parameter TagSet (#5) Jun 27, 2019


Brick is an open-source, BSD-licensed development effort to create a uniform schema for representing metadata in buildings. Brick has three components:

  • An RDF class hierarchy describing the various building subsystems and the entities and equipment therein
  • A minimal, principled set of relationships for connecting these entities together into a directed graph representing a building
  • A method of encapsulation for composing complex components from a set of lower-level ones

The official Brick website,, contains documentation and other information about the Brick schema.

This repository tracks the main schema development of Brick.


Discussion takes place primarily on the Brick User Form:!forum/brickschema

Questions and Issues

If you have an issue with Brick's coverage, utility or usability, or any other Brick-related question:

  1. First check the Brick user form and the Brick issue tracker to check if anyone has asked your question already.
  2. If you find a previously submitted issue that closely mirrors your own, feel free to jump in on the conversation. Otherwise, please file a new issue or submit a new thread on the forum.

How To Contribute


Ontology Implementation


Almost everything we are using falls under OWL Lite with the exception of the owl:hasValue property which we use to define a 1-1 mapping between sets of tags and names of classes. Because of this, the current solution falls under OWL DL.

This also means that we need a reasoner, but thankfully not one that supports OWL Full :). OWL-RL is a nice choice that works with RDFlib.

# G is our RDFlib Graph

# apply reasoning to expand all of the inferred triples
import owlrl

# get namespaces

G.query("SELECT ?x WHERE { ?x brick:hasTag tag:Equip }")

We can serialize the expanded form of the graph to disk if we need to use a SPARQL query processor that does not support reasoning.


  • The Brick class namespace is
  • Classes belong to owl:Class and are arranged into a hierarchy with rdfs:subClassOf
  • Equivalent classes (the members of the classes are the same) are related with the owl:equivalentClass property
  • Definitions given with skos:definition
  • We are eliminating equipment-flavored classes where it makes sense
    • e.g. brick:AHU_Average_Exhaust_Air_Static_Pressure_Sensor is just a Average_Exhaust_Air_Static_Pressure_Sensor that is a point of an AHU.
  • Classes are equivalent to a set of tags (see below)

The root classes we have defined are:

  • Equipment
  • Location
  • Point
  • Tag
  • Substance
  • Quantity


(Relationships are the Brick term for owl ObjectProperties between instances of classes)

At the surface level, relationship work the same as they did in the original Brick. All the same relationships still exist (where I remembered to define them), and they have their inverses defined using owl:inverseOf.

Domains and ranges are defined in terms of classes. Stating that the rdfs:range of a relationship is of class brick:Equipment means that the object of the relationship should be an instance of the brick:Equipment class.

This prototype includes sub-relationships in addition to relationships. Sub-relationships can be used in place of the super-relationship to add more detail to the nature of that relationship. The only example so far is feedsAir being a subproperty of feeds.

Something to figure out is how we could infer the feedsAir relationship; maybe if the two endpoint equipment have the air tag and a feeds relationship? This may be something that needs to be explicitly specified rather than inferred.


  • Tag ontology namespace is
  • We use Haystack tags and define our own set including them
  • Tags should have definitions, but this is not included yet
  • Sets of tags have a 1-1 mapping with a class name
  • definitions given using the skos:definition property

This is accomplished by declaring a Brick class (e.g. Air_Temperature_Sensor) as equivalent to an anonymous class, which is an owl:Restriction that is the intersection of entities that have certain tags.

# in turtle format
brick:Temperature_Sensor a owl:Class ;
    rdfs:subClassOf brick:Sensor ;
    owl:equivalentClass [ owl:intersectionOf (
                            [ a owl:Restriction ;
                                owl:hasValue tag:Sensor ;
                                owl:onProperty brick:hasTag
                            [ a owl:Restriction ;
                                owl:hasValue tag:Temperature ;
                                owl:onProperty brick:hasTag
                        ) ] .

The first owl:Restriction is the set of all classes that have tag:Sensor as the value for one of their brick:hasTag properties.

This means that a temperature sensor :ts1 could be defined in two different ways and the reasoner would infer the other triples:

# using classes
:ts1   a   brick:Temperature_Sensor

# using tags
:ts1    brick:hasTag    tag:Temp
:ts1    brick:hasTag    tag:Sensor


Brick now defines a hierarchy of substances ( and a hierarchy of quantities ( Substances and quantities can be related to equipment and points.

Not all of this is implemented. In the current prototype, sensors are related to substances and quantities through the brick:measures relationship.

:ts1    a       brick:Temperature_Sensor
:ts1    brick:measures      :Air

# this implies the following
:ts1    a       brick:Air_Temperature_Sensor

We can further subclass substances to provide system- or process-level context to their definitions:

:ts1    a       brick:Sensor
:ts1    brick:measures      brick:Return_Air
:ts1    brick:measures      brick:Temperature

# implies...

:ts1    a       brick:Return_Air_Temperature_Sensor

Brick uses OWL restrictions to refine classes based on such relationships. For this example, because :ts1 measures Air (specifically the brick:Air class), OWL infers our sensor as a brick:Air_Temperature_Sensor.

Here's what that the definition looks like in turtle:

brick:Air_Temperature_Sensor a owl:Class ;
    rdfs:subClassOf brick:Temperature_Sensor ;
    owl:equivalentClass [ owl:intersectionOf ( [ a owl:Restriction ;
                        owl:hasValue brick:Temperature ;
                        owl:onProperty brick:measures ] [ a owl:Restriction ;
                        owl:hasValue brick:Air ;
                        owl:onProperty brick:measures ] ) ] .

Note: we are using classes as values here, which is different than the rest of Brick. This is called "punning". This is to avoid having to create instances of substances for our sensors to measure and so on, but reserves the possibility to implement this in the future. Instances of substances can model regions/chunks of "stuff" in a stage of a process, e.g. the water entering a chiller or the mixed air region of an air handling unit.

Python Framework

Rather than getting lost in the Sisyphean bikeshedding of how to format everything as YAML, we're just using Python dictionaries so we don't have to worry about any (well, not that much) parsing logic.

definitions = {
    "Lighting_System": {
        "tagvalues": [   # Lighting_System class is equivalent to the Lighting tag
            (BRICK.hasTag, TAG.Lighting),
            # if you have more required tags add them as their own tuple in the list
        # defining subclasses. This can be nested ad-infinitum
        "subclasses": {
            "Lighting": {
                "subclasses": {
                    "Luminaire": {},
                    "Luminaire_Driver": {},
            "Interface": {
                "subclasses": {
                    "Switch": {
                        "subclasses": {
                            "Dimmer": {},
                    "Touchpanel": {},
define_subclasses(definitions, BRICK.Equipment)

For now, the code is the documentation. Look at,, etc for examples and how to add to each of the class hierarchies.

You can’t perform that action at this time.