Skip to content

Commit

Permalink
Class-based shapes (#240)
Browse files Browse the repository at this point in the history
* init class shapes

* Fix Nightly Builds (#241)

* try renaming file

* trying a different release package

* Amending QUDT Definitions (#239)

* change owl:sameAs to brick:hasQUDTReference

* fix Grains -> GrainsOfMoisture

* update QUDT

* simplify generation code

* fix test to reflect new implementation

* include units, even those without a symbol

* do not make Brick Quantities also QUDT Quantity Kinds

* fixing Dimensionless reference, correcting sameAs for power

* fix typos, remove undefined QUDT units

* follow steves recommendation for ontology metadata

* updating uris

* Update Ontology Metadata (#245)

* update ontology metadata to include publisher, issued, modified and use owl.versionInfo rather than dcterms.version (which does not exist)

* make publisher a blank node

* use date of publication as release date

* remove old logic for shacl test

* amend definition for isPointOf (#251)

* Adding quantities, sensor classes for air quality (#247)

* adding quantities, sensor classes for air quality

* add air quality example file + graph

* fix CO2 tags now that it is outside of particulate matter

* add definitions

* use brick value, not brick area inside the entity property (#254)

* Regenerate air quality sensor example (#255)

* use brick value, not brick area inside the entity property

* regenerate file

* fix typo

* implement disjoint classes & add tests

* clean up code

* init class shapes

* remove old logic for shacl test

* fix typo

* implement disjoint classes & add tests

* clean up code

* update shacl

* add shacl messages

* use brickschema

Co-authored-by: Gabe Fierro <[email protected]>
  • Loading branch information
jbkoh and gtfierro authored Apr 26, 2021
1 parent a55570d commit addf9b3
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 39 deletions.
113 changes: 113 additions & 0 deletions shacl/BrickEntityShapeBase.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix bsh: <https://brickschema.org/schema/BrickShape#> .
@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 vcard: <http://www.w3.org/2006/vcard/ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .


bsh:LocationShape a sh:NodeShape ;
sh:targetClass brick:Location ;
sh:not [
sh:or (
[sh:class brick:Point;]
[sh:class brick:Equipment;]
[sh:class brick:Substance;]
[sh:class brick:Quantity;]
);
sh:message "Location is an exclusive top class."
];
sh:property [
sh:path brick:hasPart;
sh:class brick:Location;
sh:message "A Location's parts should be always Locations."
];
sh:property [
sh:path brick:isPartOf;
sh:class brick:Location;
sh:message "A Location's parts should be always Locations."
];
sh:property [
sh:path brick:isFedBy;
sh:class brick:Equipment;
sh:message "Locations can be fed only by other Equipment."
];
sh:property [
sh:path brick:hasPoint;
sh:class brick:Point;
sh:message "A Location may have associated Points"
];
.

bsh:EquipmentShape a sh:NodeShape ;
sh:targetClass brick:Equipment ;
sh:not [
sh:or (
[sh:class brick:Location;]
[sh:class brick:Point;]
[sh:class brick:Substance;]
[sh:class brick:Quantity;]
);
sh:message "Equipment is an exclusive top class."
];
sh:property [
sh:path brick:hasPart;
sh:class brick:Equipment;
sh:message "A piece of Equipment's parts should be always other Equipment."
];
sh:property [
sh:path brick:isPartOf;
sh:class brick:Equipment;
sh:message "A piece of Equipment's parts should be always other Equipment."
];
sh:property [
sh:path brick:hasLocation;
sh:class brick:Location;
sh:message "A piece of Equipment can be located only at a Location"
];
sh:property [
sh:path brick:feeds;
sh:or (
[ sh:class brick:Equipment ]
[ sh:class brick:Location ]
) ;
sh:message "A piece of Equipment can be located at a Location"
];
sh:property [
sh:path brick:hasPoint;
sh:class brick:Point;
sh:message "A piece of Equipment may have associated Points"
];
.

bsh:PointShape a sh:NodeShape;
sh:targetClass brick:Point;
sh:not [
sh:or (
[sh:class brick:Location;]
[sh:class brick:Equipment;]
[sh:class brick:Substance;]
[sh:class brick:Quantity;]
);
sh:message "Point is an exclusive top class."
];
sh:property [
sh:path brick:isPointOf;
sh:or (
[ sh:class brick:Location ]
[ sh:class brick:Equipment ]
);
sh:message "A Point can be associated with Locations or Equipment."
];
.

bsh:hasLocationShape a sh:Nodeshape;
sh:targetSubjectsOf brick:hasLocation;
sh:not [
sh:class brick:Point;
];
sh:message "Points are a virtual concept and always belonging to a physical device, represented by Equipment. Thus, it cannot have a Location alone."
.

37 changes: 37 additions & 0 deletions shacl/BrickShape.ttl
Original file line number Diff line number Diff line change
@@ -1,11 +1,44 @@
@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix bsh: <https://brickschema.org/schema/BrickShape#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix unit: <http://qudt.org/vocab/unit/> .
@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

bsh:EquipmentShape a sh:NodeShape ;
sh:not [ sh:or ( [ sh:class brick:Location ] [ sh:class brick:Point ] [ sh:class brick:Substance ] [ sh:class brick:Quantity ] ) ] ;
sh:property [ sh:class brick:Equipment ;
sh:path brick:hasPart ],
[ sh:class brick:Equipment ;
sh:path brick:isPartOf ],
[ sh:class brick:Location ;
sh:path brick:hasLocation ],
[ sh:or ( [ sh:class brick:Equipment ] [ sh:class brick:Location ] ) ;
sh:path brick:feeds ],
[ sh:class brick:Point ;
sh:path brick:hasPoint ] ;
sh:targetClass brick:Equipment .

bsh:LocationShape a sh:NodeShape ;
sh:not [ sh:or ( [ sh:class brick:Point ] [ sh:class brick:Equipment ] [ sh:class brick:Substance ] [ sh:class brick:Quantity ] ) ] ;
sh:property [ sh:class brick:Location ;
sh:path brick:hasPart ],
[ sh:class brick:Location ;
sh:path brick:isPartOf ],
[ sh:class brick:Equipment ;
sh:path brick:isFedBy ],
[ sh:class brick:Point ;
sh:path brick:hasPoint ] ;
sh:targetClass brick:Location .

bsh:PointShape a sh:NodeShape ;
sh:not [ sh:or ( [ sh:class brick:Location ] [ sh:class brick:Equipment ] [ sh:class brick:Substance ] [ sh:class brick:Quantity ] ) ] ;
sh:property [ sh:or ( [ sh:class brick:Location ] [ sh:class brick:Equipment ] ) ;
sh:path brick:isPointOf ] ;
sh:targetClass brick:Point .

bsh:hasAddressDomainShape a sh:NodeShape ;
sh:class brick:Building ;
sh:message "Property hasAddress has subject with incorrect type" ;
Expand Down Expand Up @@ -40,6 +73,10 @@ bsh:hasLocationRangeShape a sh:NodeShape ;
sh:path brick:hasLocation ] ;
sh:targetSubjectsOf brick:hasLocation .

bsh:hasLocationShape a sh:Nodeshape ;
sh:not [ sh:class brick:Point ] ;
sh:targetSubjectsOf brick:hasLocation .

bsh:hasOutputSubstanceRangeShape a sh:NodeShape ;
sh:property [ sh:class brick:Substance ;
sh:message "Property hasOutputSubstance has object with incorrect type" ;
Expand Down
2 changes: 2 additions & 0 deletions shacl/generate_shacl.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
rangeShapeDict = {}
subpropertyDict = {}

# Add base Entity shapes
G.parse('BrickEntityShapeBase.ttl', format='turtle')

# Make shape for expectedDomain property
def addDomainShape(propertyName, expectedType):
Expand Down
39 changes: 0 additions & 39 deletions tests/test_generate_shacl.py

This file was deleted.

61 changes: 61 additions & 0 deletions tests/test_shapes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import sys
from bricksrc.namespaces import A, OWL, RDFS, SKOS, BRICK, SH, BSH, bind_prefixes
import brickschema

schema_g = brickschema.Graph().load_file('shacl/BrickShape.ttl')
bind_prefixes(schema_g)

prefixes = """
@prefix brick: <https://brickschema.org/schema/Brick#> .
@prefix : <http://example.com#> .
"""

base_data = prefixes + """
:equip a brick:Equipment.
:point a brick:Point.
:loc a brick:Location.
"""

def test_no_relations():
data = base_data
data_g = brickschema.Graph().parse(data=data, format='turtle')
conforms, r1, r2 = data_g.validate([schema_g])
assert conforms

def test_equip():
valid_data = base_data + """
:equip brick:hasLocation :loc.
"""
valid_g = brickschema.Graph().parse(data=valid_data, format='turtle')
conforms, _, _ = valid_g.validate([schema_g])
assert conforms

invalid_data = base_data + """
:equip brick:hasLocation :point.
"""
invalid_g = brickschema.Graph().parse(data=invalid_data, format='turtle')
conforms, _, _= invalid_g.validate([schema_g])
assert not conforms


def test_type():
invalid_data = base_data + """
:loc a brick:Point.
"""
invalid_g = brickschema.Graph().parse(data=invalid_data, format='turtle')
conforms, _, _= invalid_g.validate([schema_g])
assert not conforms


def test_point():
invalid_data = base_data + """
:point brick:hasLocation :loc.
"""
invalid_g = brickschema.Graph().parse(data=invalid_data, format='turtle')
conforms, _, _= invalid_g.validate([schema_g])
assert not conforms




0 comments on commit addf9b3

Please sign in to comment.