【Ontology】【Brick】py-Brick简明教程

参考资料
Brick——A uniform metadata schema for buildings

目录

1. Brick简介

Brick is an open-source effort to standardize semantic descriptions of the physical, logical and virtual assets in buildings and the relationships between them. Brick consists of an extensible dictionary of terms and concepts in and around buildings, a set of relationships for linking and composing concepts together, and a flexible data model permitting seamless integration of Brick with existing tools and databases. Through the use of powerful Semantic Web technology, Brick can describe the broad set of idiosyncratic and custom features, assets and subsystems found across the building stock in a consistent matter.
Brick是一个开源项目,旨在对建筑中的物理、逻辑和虚拟资产以及它们之间的关系进行标准化的语义描述。Brick包含一个可扩展的词汇和概念字典、一组用于将概念链接和组合在一起的关系,以及一个允许Brick与现有工具和数据库无缝集成的灵活数据模型。通过使用强大的语义Web技术,Brick可以在一致的问题上描述跨建筑库存中发现的广泛的特殊和自定义特性、资产和子系统。

2. py-brickschema

py-brickschema
项目github地址——py-brickschema
案例中使用的本体文件——soda_hall

2.1 环境安装

pip install brickschema

要求Python版本在3.60以上。py-brickschema内置了推理机,如owlrl、 Allegro推理机(使用pip install brickschema[allegro]进行安装)和 reasonable Reasoner(使用pip install brickschema[reasonable]进行安装,目前仅支持Linux和MacOS)。

2.2 本体模型的相关操作——brickschema.graph module

【Ontology】【Brick】py-Brick简明教程

在py-brickschema中,本体的创建和相关操作由Graph()模块完成该模块也继承了rdflib中的Grpah()进行开发,所以rdflib.Graph()的相关方法均可使用。

from brickschema import Graph

g = Graph() # 创建一个新的空本体模型
g.parse("soda_hall.ttl", format = "ttl")
outfile = "out.ttl"
g.serialize(outfile,format='turtle')  # 默认以'ttl'格式存储

brickschema.Graph()有三个参数:

  • load_brick——默认为False。如果为True,则载入Brick Ontology。
  • load_brick_nightly——默认为False。如果为True,则载入最新的Brick Ontology(要求联网)。
  • brick_version——默认为1.2。

也就是说,下面这段代码可以得到BrickSchema V1.2的Ontology模型。

from brickschema import Graph

g = Graph(load_brick = True)
# g.parse("soda_hall.ttl", format = "ttl")
outfile = "out.ttl"
g.serialize(outfile,format='turtle') 

2.3 模型的加载

可以通过g.load_file()加载本体模型。

from brickschema import Graph

g = Graph()
g.load_file("soda_hall.ttl")

也可以通过URL——g.parse()来加载:

from brickschema import Graph

g = Graph()
g.parse("https://www.brickschema.org/ttl/ghc_brick.ttl", format="ttl")

2.4 三元组的创建和添加

三元组的创建和添加通过g.add()来实现。

from brickschema import Graph
from rdflib.namespace import Namespace

g = Graph()

# 绑定命名空间
soda_hall = Namespace("https://brickschema.org/schema/1.0.2/building_example#")
brick = Namespace("https://brickschema.org/schema/Brick#")
g.bind("soda_hall", soda_hall)
g.bind("brick", brick)

# 添加新的三元组
g.add((soda_hall['ahu'], brick['isLocationOf'], soda_hall['exhaust_fan_E12']))

outfile = "out.ttl"
g.serialize(outfile,format='turtle') 

输出的本体文件为:

@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix soda_hall: <https://brickschema.org/schema/1.0.2/building_example#> .

soda_hall:ahu brick:isLocationOf soda_hall:exhaust_fan_E12 .

此外,还可以通过g.from_triples()来添加一系列三元组。

from brickschema import Graph
from rdflib.namespace import Namespace

g = Graph()

# 绑定命名空间
soda_hall = Namespace("https://brickschema.org/schema/1.0.2/building_example#")
brick = Namespace("https://brickschema.org/schema/Brick#")
g.bind("soda_hall", soda_hall)
g.bind("brick", brick)

# 添加新的三元组
triples = []
triples.append((soda_hall['ahu'], brick['isLocationOf'], soda_hall['exhaust_fan_E12']))
triples.append((soda_hall['ahu'], brick['isLocationOf'], soda_hall['exhaust_fan_E13']))
g.from_triples(triples)

outfile = "out.ttl"
g.serialize(outfile,format='turtle') 

输出文件为:

@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix soda_hall: <https://brickschema.org/schema/1.0.2/building_example#> .

soda_hall:ahu brick:isLocationOf soda_hall:exhaust_fan_E12,
        soda_hall:exhaust_fan_E13 .

可以通过g.nodes来获取模型中的节点。

from brickschema import Graph
from rdflib.namespace import Namespace

g = Graph()

# 绑定命名空间
soda_hall = Namespace("https://brickschema.org/schema/1.0.2/building_example#")
brick = Namespace("https://brickschema.org/schema/Brick#")
g.bind("soda_hall", soda_hall)
g.bind("brick", brick)

# 添加新的三元组
g.add((soda_hall['ahu'], brick['isLocationOf'], soda_hall['exhaust_fan_E12']))

print(g.nodes)
print(len(g.nodes))

输出为:

{rdflib.term.URIRef('https://brickschema.org/schema/1.0.2/building_example#exhaust_fan_E12'), rdflib.term.URIRef('https://brickschema.org/schema/1.0.2/building_example#ahu')}
2

2.5 模型的补全

模型的补全会调用brickschema.inference模块,通过g.expand()来实现,主要通过内置的推理方法补充和完善本体模型。该方法有三个主要的参数——profilebackendsimplifysimplify的默认值为True,旨在删除一些冗余的三元组。

profile backend
【Ontology】【Brick】py-Brick简明教程 【Ontology】【Brick】py-Brick简明教程

【Ontology】【Brick】py-Brick简明教程

例子:

from brickschema import Graph
from rdflib.namespace import Namespace

g = Graph()

# 绑定命名空间
soda_hall = Namespace("https://brickschema.org/schema/1.0.2/building_example#")
brick = Namespace("https://brickschema.org/schema/Brick#")
g.bind("soda_hall", soda_hall)
g.bind("brick", brick)

# 添加新的三元组
g.add((soda_hall['ahu'], brick['isLocationOf'], soda_hall['exhaust_fan_E12']))
g.expand(profile="rdfs")

outfile = "out.ttl"
g.serialize(outfile,format='turtle')

输出:

@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix soda_hall: <https://brickschema.org/schema/1.0.2/building_example#> .

soda_hall:ahu a rdfs:Resource ;
    brick:isLocationOf soda_hall:exhaust_fan_E12 .

rdf:type a rdf:Property ;
    rdfs:subPropertyOf rdf:type .

rdfs:subPropertyOf a rdf:Property ;
    rdfs:subPropertyOf rdfs:subPropertyOf .

soda_hall:exhaust_fan_E12 a rdfs:Resource .

brick:isLocationOf a rdf:Property ;
    rdfs:subPropertyOf brick:isLocationOf .

可以看到,这里自动补充了对soda_hall:ahusoda_hall:exhaust_fan_E12brick:isLocationOf的一些定义。如果使用g.expand(profile="owlrl"),则得到更完整的本体模型定义如下:

@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 soda_hall: <https://brickschema.org/schema/1.0.2/building_example#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

rdf:HTML a rdfs:Datatype .

rdf:LangString a rdfs:Datatype .

rdf:PlainLiteral a rdfs:Datatype .

rdf:XMLLiteral a rdfs:Datatype .

rdfs:Literal a rdfs:Datatype .

rdfs:comment a owl:AnnotationProperty .

rdfs:isDefinedBy a owl:AnnotationProperty .

rdfs:label a owl:AnnotationProperty .

rdfs:seeAlso a owl:AnnotationProperty .

xsd:NCName a rdfs:Datatype .

xsd:NMTOKEN a rdfs:Datatype .

xsd:Name a rdfs:Datatype .

xsd:anyURI a rdfs:Datatype .

xsd:base64Binary a rdfs:Datatype .

xsd:boolean a rdfs:Datatype .

xsd:byte a rdfs:Datatype .

xsd:date a rdfs:Datatype .

xsd:dateTime a rdfs:Datatype .

xsd:dateTimeStamp a rdfs:Datatype .

xsd:decimal a rdfs:Datatype .

xsd:double a rdfs:Datatype .

xsd:float a rdfs:Datatype .

xsd:hexBinary a rdfs:Datatype .

xsd:int a rdfs:Datatype .

xsd:integer a rdfs:Datatype .

xsd:language a rdfs:Datatype .

xsd:long a rdfs:Datatype .

xsd:negativeInteger a rdfs:Datatype .

xsd:nonNegativeInteger a rdfs:Datatype .

xsd:nonPositiveInteger a rdfs:Datatype .

xsd:normalizedString a rdfs:Datatype .

xsd:positiveInteger a rdfs:Datatype .

xsd:short a rdfs:Datatype .

xsd:string a rdfs:Datatype .

xsd:time a rdfs:Datatype .

xsd:token a rdfs:Datatype .

xsd:unsignedByte a rdfs:Datatype .

xsd:unsignedInt a rdfs:Datatype .

xsd:unsignedLong a rdfs:Datatype .

xsd:unsignedShort a rdfs:Datatype .

owl:backwardCompatibleWith a owl:AnnotationProperty .

owl:deprecated a owl:AnnotationProperty .

owl:incompatibleWith a owl:AnnotationProperty .

owl:priorVersion a owl:AnnotationProperty .

owl:versionInfo a owl:AnnotationProperty .

soda_hall:ahu brick:isLocationOf soda_hall:exhaust_fan_E12 .

owl:Nothing a owl:Class ;
    rdfs:subClassOf owl:Nothing,
        owl:Thing ;
    owl:equivalentClass owl:Nothing .

owl:Thing a owl:Class ;
    rdfs:subClassOf owl:Thing ;
    owl:equivalentClass owl:Thing .

我们可以看一下扩展之后的三元组的对比:

from brickschema import Graph

bldg = Graph(load_brick=True)
bldg.load_file('soda_hall.ttl')
print(f"Before: {len(bldg)} triples")
bldg.expand("rdfs")
print(f"After: {len(bldg)} triples")

输出为:

Before: 29383 triples
After: 64127 triples

如果想要同时完成两个扩展,只要用+连接起来就行。例如g.expand(profile='shacl+rdfs'),这意味着先实现g.expand(profile='shacl'),再实现g.expand(profile='rdfs')

Extensions provide additional class definitions, rules and other augmentations to the Brick ontology.

可以通过g.get_extensions()获得扩展器(extensions)列表。

from brickschema import Graph

g = Graph()
g.load_file("soda_hall.ttl")
print(g.get_extensions())

输出:

['shacl_tag_inference']

接下来,可以通过g.load_extension('shacl_tag_inference')来加载相应的扩展器。

2.6 从HayStack数据中生成Brick模型

HayStack案例模型——https://project-haystack.org/example/alpha

from brickschema import Graph
import json

g = Graph()
haystackModel  = json.load(open("bravo.json"))
g.from_haystack(namespace = "http://project-haystack.org/bravo#", model = haystackModel)

首先先将Haystack模型导入,然后使用g.from_haystack()方法完成。

2.7 模型的验证

# validate your Brick graph against built-in shapes (or add your own)
valid, _, resultsText = g.validate()
if not valid:
    print("Graph is not valid!")
    print(resultsText)

也可以使用自己定义的shape文件进行验证:

from brickschema import Graph

g = Graph(load_brick=True)
g.load_file('myBuilding.ttl')

# validating using externally-defined shapes
external = Graph()
external.load_file("other_shapes.ttl")
valid, _, report = g.validate(shape_graphs=[external])

2.8 模型的对齐

Alignments define the nature of Brick’s relationship to other RDF-based ontologies. For example, the Building Topology Ontology defines several location classes that are similar to Brick’s; the alignment between BOT and Brick allows graphs defined in one language to be understood in the other.

from brickschema import Graph

g = Graph()
# returns a list of alignments
g.get_alignments()
# => ['VBIS', 'REC', 'BOT']

# loads the contents of the alignment file into the graph
g.load_alignment('BOT')
# good idea to run a reasoner after loading in the extension
# so that the implied information is filled out
g.expand("owlrl")

案例:

from brickschema import Graph

g = Graph()
g.load_file("soda_hall.ttl")
g.load_alignment("BOT")

outfile = "out.ttl"
g.serialize(outfile, format = "ttl")

可以看到经过和BOT本体之间对齐之后,本体内增加了一些新的内容:

【Ontology】【Brick】py-Brick简明教程

上一篇:mvc添加安全。


下一篇:java数组02-数组声明和创建