TP+P Method

latest update 2022-11-06  

Introduction

The use of templates has as advantage that these can precisely define the semantics. BUT... they require an equally precise way of modeling, and that skill appears to be in short supply.

Customary relational data models are easier, because adding a data element does not require much more than a textual definition (at best). Templates define the semantics of that data element in terms of the ISO 15926-2 upper ontology, so in all necessary detail.

The alternative approach, dubbed the TP+P Method (Temporal Part + Predicate), is explained in this topic, It allows for the re-use of those as-is data elements and placing them in the 4D framework of ISO 15926.

Discussion

In an earlier version of ISO 15926-2 we had "Associations" that got a time stamp. In the IS (International Standard) version these have been replaced with "Relationships" without such a time stamp. Instead the time stamp was given to the temporal part(s) that are related by such a Relationship.

In Part 7 the templates do include the temporal parts, but these had to be made implicit, because there is no commercial software that can handle temporal parts. For that reason they could not be explicitly included in the template signature and we had to address the temporal whole and by convention the temporal part, valid at the valEffectiveDate of the template instance.

The basic model of the alternative TP+P approach is as follows, using the assembly of an impeller in a centrifugal pump:

To further show the alternative approach a small relational table, from the CFIHOS data model, the TAG PROPERTY table, will be mapped:

Most data elements are fairly easy to map to templates, but something like 'Tag property margin' takes some serious modeling, because it is a value that results from Process Engineering/Mechanical Engineering where for technical reasons a markup is defined.

Before representing this table in the alternative approach some remarks are required about the way these data are collected:

Here is the representation after mapping from the P&ID, where it is assumed that there isn't a declaration for the Tag yet:

@prefix ex: <http://www.example.org/> . # the namespace for plant data of the Example org
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix dm: <http://data.15926.org/dm/> . # the ISO 15926-2 entity types
@prefix lci: <http://data.15926.org/lci/> . # additional entity types
@prefix pred: <http://data.15926.org/pred/> . # definition of generic predicates
@prefix tpl: <http://data.15926.org/tpl/> . # the ISO 15926-7 template specifications
@prefix rdl: <http://data.15926.org/rdl/> . # the ISO 15926-4 reference data
@prefix cfihos: <http://www.example.org/cfihos/> . # the local RDL extension for a CFIHOS data set
@prefix meta: <http://data.15926.org/meta/> . # meta data

# Declaration of the "wholelife" Tag (the "anchor")

ex:9d3bf126-afda-4246-8704-c8292fef963c
       rdf:type lci:InanimatePhysicalObject, dm:WholeLifeIndividual, lci:NonActualIndividual, rdl:RDS297539 ; # CONTROL VALVE
       rdfs:label "600-036FV001" ;
       meta:valEffectiveDate "2022-08-19T14:23:00Z"^^xsd:dateTime .

# Declaration of a temporal part, where the typing is being specialized

ex:714be95d-d51b-48a4-8aa5-9e5901b4815b
       pred:temporalPartOf ex:9d3bf126-afda-4246-8704-c8292fef963c ;
       rdf:type rdl:RDS5767330 ; # GLOBE CONTROL VALVE (since that symbol was shown on the P&ID at time of data extraction)
       rdfs:label "600-036FV001_2022-08-19T14:23:00Z" ; # tag number + effective date (or any other modifier)
       meta:valEffectiveDate "2022-08-19T14:23:00Z"^^xsd:dateTime .

Later a mapping is done from above relational data base table:

# Declaration of a temporal part and related predicates
ex:ef6f6e73-e8ca-4451-afb7-5cda196069d1
       pred:temporalPartOf ex:9d3bf126-afda-4246-8704-c8292fef963c ;
       rdfs:label "600-036FV001_2022-09-15T14:30:00Z" ;
       meta:valEffectiveDate "2022-09-15T14:30:00Z"^^xsd:dateTime .

ex:ef6f6e73-e8ca-4451-afb7-5cda196069d1 cfihos:tagPlantCode ex:2497f34d-05b8-43c7-9112-ddcb5261376c . # fetched via "600"
ex:ef6f6e73-e8ca-4451-afb7-5cda196069d1 cfihos:tagProcessActivityCode ex:84b20fa3-0a78-487a-808e-400858d21ee0 . # fetched via "PROC_07"
ex:ef6f6e73-e8ca-4451-afb7-5cda196069d1 cfihos:tagProcessStreamCode ex:b947a964-1816-4055-9350-82da37c502cc . # fetched via "MS-07"
ex:ef6f6e73-e8ca-4451-afb7-5cda196069d1 cfihos:tagNormalOperatingPressureMargin-barg "0.6"^^xsd:decimal . # see Note 2
ex:ef6f6e73-e8ca-4451-afb7-5cda196069d1 cfihos:tagNormalOperatingPressure-barg "10.3"^^xsd:decimal . # see Note 2

NOTE 1 - The UUID of the WholeLife range object is to be found via the given label (presumably that has already been declared); then create a temporal part with a valEffectiveDate of the given dateTime and use that UUID. The temporal parts at both sides of a predicate, such as 'tagPlantCode', shall have the same valEffectiveDate and no valDeprecationDate.
NOTE 2 - The selection of the proper predicate depends on the given 'Property name' and 'Unit of measure code'. In a relational database these are implied because in the same row.
NOTE 3 - the NormalOperatingPressure shall be attributed to the referred Stream.

The above table instance is represented in N-triples:

<http://www.example.org/ef6f6e73-e8ca-4451-afb7-5cda196069d1> <http://www.w3.org/2000/01/rdf-schema#label>          "600-036FV001_2022-09-15T14:30:00Z" .
<http://www.example.org/ef6f6e73-e8ca-4451-afb7-5cda196069d1> <http://data.15926.org/pred/temporalPartOf>           <http://www.example.org/9d3bf126-afda-4246-8704-c8292fef963c> .
<http://www.example.org/ef6f6e73-e8ca-4451-afb7-5cda196069d1> <http://www.example.org/rdl/tagPlantCode>             <http://www.example.org/2497f34d-05b8-43c7-9112-ddcb5261376c> .
<http://www.example.org/ef6f6e73-e8ca-4451-afb7-5cda196069d1> <http://www.example.org/rdl/tagProcessActivityCode>   <http://www.example.org/84b20fa3-0a78-487a-808e-400858d21ee0> .
<http://www.example.org/ef6f6e73-e8ca-4451-afb7-5cda196069d1> <http://www.example.org/rdl/tagProcessStreamCode>     <http://www.example.org/b947a964-1816-4055-9350-82da37c502cc> .
<http://www.example.org/ef6f6e73-e8ca-4451-afb7-5cda196069d1> <http://data.15926.org/meta/valEffectiveDate>         "2022-09-15T14:30:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
  
<http://www.example.org/47159a42-4dc3-4344-8e39-9914f0772b40> <http://www.w3.org/2000/01/rdf-schema#label>          "600-036FMS_07_2022-09-15T14:30:00Z" .
<http://www.example.org/47159a42-4dc3-4344-8e39-9914f0772b40> <http://data.15926.org/pred/temporalPartOf>           <http://www.example.org/b947a964-1816-4055-9350-82da37c502cc> .
<http://www.example.org/47159a42-4dc3-4344-8e39-9914f0772b40> <http://www.example.org/rdl/tagNormalOperatingPressureMargin-barg>  "0.6"^^<http://www.w3.org/2001/XMLSchema#decimal> .
<http://www.example.org/47159a42-4dc3-4344-8e39-9914f0772b40> <http://www.example.org/rdl/tagNormalOperatingPressure-barg>        "10.3"^^<http://www.w3.org/2001/XMLSchema#decimal> .
<http://www.example.org/47159a42-4dc3-4344-8e39-9914f0772b40> <http://data.15926.org/meta/valEffectiveDate>         2022-09-15T14:30:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> .

This requires some standardization work
Once-only local declaration of Predicates, required to avoid misunderstandings

cfihos:plantCode
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf  pred:locatedIn ;
       skos:definition "The UUID of the Plant where the domain is located"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range rdl:RDS7151797 . # PLANT (a specialization of the range object of pred:locatedIn) 

cfihos:tagPlantCode
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf  pred:plantCode ;
       skos:definition "The UUID of the Plant where the domain Tag is located"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range rdl:RDS7151797 . # PLANT

cfihos:quantitativePropertyName
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf  pred:hasPropertyType ;
       skos:definition "The RDL identifier of the applicable Quantitative Property"@en ;
       rdfs:domain dm:PossibleIndividual ;
       rdfs:range cfihos:00000070 .

cfihos:tagQuantitativePropertyName
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf  cfihos:quantitativePropertyName ;
       skos:definition "The RDL identifier of the applicable Quantitative Property for a Tag"@en ;
       rdfs:domain cfihos:00000028 ; # Tag
       rdfs:range cfihos:00000070 .

cfihos:qualitativePropertyName
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf  pred:hasPropertyType ;
       skos:definition "The RDL identifier of the applicable Qualitative Property possessed by the domain "@en ;
       rdfs:domain dm:PossibleIndividual ;
       rdfs:range cfihos:00000071 .

cfihos:tagQualitativePropertyName
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf  pred:hasPropertyType ;
       skos:definition "The RDL identifier of the applicable Qualitative Property possessed by the domain "@en ;
       rdfs:domain cfihos:00000028 ; # Tag
       rdfs:range cfihos:00000071 .

cfihos:processActivityCode
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf  pred:participatesAsRoleIn ;
       skos:definition "The UUID of the Activity or Process in which the domain PhysicalObject is involved in some Role"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range  cfihos:00000118 . # PROCESS DESIGN ACTIVITY

cfihos:tagProcessActivityCode
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf  pred:processActivityCode ;
       skos:definition "The UUID of the Activity or Process in which the domain Tag is involved in some Role"@en ;
       rdfs:domain cfihos:00000028 ; # TAG
       rdfs:range  cfihos:00000118 . # PROCESS DESIGN ACTIVITY

cfihos:processStreamCode
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:contains ;
       skos:definition "The UUID of the process stream that is related to the domain in some way"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range cfihos:00000120 ; # PROCESS STREAM .

cfihos:tagProcessStreamCode
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:processStreamCode ;
       skos:definition "The UUID of the process stream that is related to the domain Tag in some way"@en ;
       rdfs:domain cfihos:00000028 ; # TAG
       rdfs:range cfihos:00000120 ; # PROCESS STREAM .

cfihos:tagPropertyMargin-uom
       rdf:type owl:DatatypeProperty ;
       rdfs:subPropertyOf pred:userDefinedDatatypeProperty ;
       skos:definition "The total margin that has been applied on the value of the applicable tag property, possessed by the domain Tag,
            as compared to what was evaluated as the process stream property;
            Note that this is *not* a ratio"@en ;
       rdfs:domain cfihos:00000028 ; # TAG
       rdfs:range xsd:decimal .

cfihos:tagNormalOperatingPressureMargin-barg
       rdf:type owl:DatatypeProperty ;
       rdfs:subPropertyOf pred:tagPropertyMargin-uom ;
       skos:definition "A tagNormalOperatingPressureMargin-barg is the total margin that has been applied on the value of the NormalOperatingPressure, mapped to the BAR GAUGE Scale, 
			possessed by the stream contained in the Tag, as compared to what was evaluated as the process stream NormalOperatingPressure"@en ;
       rdfs:domain cfihos:00000120 ; # PROCESS STREAM
       rdfs:range xsd:decimal .

cfihos:tagNormalOperatingPressure-barg
       rdf:type owl:DatatypeProperty ;
       rdfs:subPropertyOf pred:pressure-barg ;
       skos:definition "The tagNormalOperatingPressure-barg is the numeric value of a NormalOperatingPressure, mapped to the BAR GAUGE Scale, possessed by the stream contained in the Tag"@en ;
       rdfs:domain cfihos:00000120 ; # PROCESS STREAM
       rdfs:range xsd:decimal .

# where reference is made to the following standardized generic Predicates:
 
pred:userDefinedDatatypeProperty
       rdf:type owl:DatatypeProperty ;
       skos:definition "An 'userDefinedDatatypeProperty' predicate generically relates the domain PossibleIndividual with some Literal; It is user-defined"@en ;
       rdfs:domain dm:PossibleIndividual ;
       rdfs:range [ rdf:type owl:Class ; owl:unionOf ( xsd:string xsd:decimal xsd:float xsd:boolean ) ] .

pred:coUserDefinedDatatypeProperty
       rdf:type owl:DatatypeProperty ;
       skos:definition "An 'coUserDefinedDatatypeProperty' predicate generically relates members of the domain ClassOfIndividual with some Literal; It is user-defined"@en ;
       rdfs:domain dm:ClassOfIndividual ;
       rdfs:range [ rdf:type owl:Class ; owl:unionOf ( xsd:string xsd:decimal xsd:float xsd:boolean ) ] .

pred:userDefinedObjectProperty
       rdf:type owl:ObjectProperty ;
       skos:definition "An 'userDefinedObjectProperty' predicate generically interrelates two instances of PossibleIndividual that shall exist in the same Possible World; It is user-defined"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range dm:PhysicalObject .

pred:coUserDefinedObjectProperty
       rdf:type owl:ObjectProperty ;
       skos:definition "An 'coUserDefinedObjectProperty' predicate generically interrelates members of two instances of ClassOfIndividual which members shall exist in the same Possible World; 
			It is user-defined"@en ;
       rdfs:domain dm:ClassOfIndividual ; 
       rdfs:range dm:ClassOfIndividual ; .

pred:individualInterrelationship
       rdf:type owl:ObjectProperty ;
       skos:definition "An 'individualInterrelationship' predicate generically interrelates two instances of PhysicalObject that shall exist in the same Possible World"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range dm:PhysicalObject .

pred:coIndividualInterrelationship
       rdf:type owl:ObjectProperty ;
       skos:definition "An 'coIndividualInterrelationship' predicate generically interrelates members of two instances of ClassOfPhysicalObject."@en ;
       rdfs:domain lci:ClassOfPhysicalObject ;
       rdfs:range lci:ClassOfPhysicalObject .

pred:locatedIn
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:individualInterrelationship ;
       skos:definition "A 'locatedIn' predicate refers to the range PhysicalObject in which the domain PhysicalObject is physically located"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range dm:PhysicalObject .

pred:coLocatedIn
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:coIndividualInterrelationship ;
       skos:definition "A 'coLocatedIn' predicate refers to members of the range ClassOfPhysicalObject in which members of the domain ClassOfPhysicalObject are physically located"@en ;
       rdfs:domain lci:ClassOfPhysicalObject ;
       rdfs:range lci:ClassOfPhysicalObject .

pred:hasQuantifyableCharacteristic
       rdf:type owl:ObjectProperty ;
       skos:definition "A 'hasQualifyableCharacteristic' predicate refers to a numerical value that represents the magniture of a specialization of ClassOfQuantifyableCharacteristic 
			(ClassOfProperty, ClassOfIndirectProperty, or ShapeDimension),  that is possessed by the domain PossibleIndividual"@en ;
       rdfs:domain dm:PossibleIndividual ;
       rdfs:range xsd:decimal .

pred:coHasQuantifyableCharacteristic
       rdf:type owl:ObjectProperty ;
       skos:definition "A 'coHasQualifyableCharacteristic' predicate refers to a numerical value that represents the magniture of a specialization of ClassOfQuantifyableCharacteristic 
			(ClassOfProperty, ClassOfIndirectProperty, or ShapeDimension),  that is possessed by all members of the domain PossibleIndividual"@en ;
       rdfs:domain lci:ClassOfIndividual;
       rdfs:range xsd:decimal .

pred:hasQualifyableCharacteristic
       rdf:type owl:ObjectProperty ;
       skos:definition "A 'hasQualifyableCharacteristic' predicate refers to the range string, Boolean, or URI that defines a QualifyableCharacteristic of the domain PossibleIndividual"@en ;
       rdfs:domain dm:PossibleIndividual ;
       rdfs:range [ rdf:type owl:Class ; owl:unionOf ( xsd:string xsd:boolean xsd:anyURI ) ] .

pred:coHasQualifyableCharacteristic
       rdf:type owl:ObjectProperty ;
       skos:definition "A 'hasQualifyableCharacteristic' predicate refers to the range string, Boolean, or URI that defines the QualifyableCharacteristic of all members of the domain 
			ClassOfIndividual"@en ;
       rdfs:domain dm:ClassOfIndividual ;
       rdfs:range [ rdf:type owl:Class ; owl:unionOf ( xsd:string xsd:boolean xsd:anyURI ) ] .

pred:participatesAsRoleIn
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:individualInterrelationship ;
       skos:definition "A 'participatesAsRoleIn' predicate refers to the range ClassOfActivity in which the domain PhysicalObject participates in a Role defined by the applicable subProperty"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range dm:Activity .

pred:participatesAsPerformerIn
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:participatesAsRoleIn ;
       skos:definition "A 'participatesAsRoleIn' predicate refers to the range Activity in which the domain PhysicalObject participates in the Role of PERFORMER"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range dm:Activity .

pred:participatesAsSubjectIn
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:participatesAsRoleIn ;
       skos:definition "A 'participatesAsRoleIn' predicate refers to the range Activity in which the domain PhysicalObject participates in the Role of SUBJECT"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range dm:Activity .

pred:coParticipatesAsRoleIn
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:coIndividualInterrelationship ;
       skos:definition "A 'coParticipatesAsRoleIn' predicate refers to members of a range ClassOfActivity in which members of the domain ClassOfPhysicalObject participate in a Role 
			defined by the applicable subProperty"@en ;
       rdfs:domain lci:ClassOfPhysicalObject ;
       rdfs:range dm:ClassOfActivity .

pred:coParticipatesAsPerformerIn
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:coIndividualInterrelationship ;
       skos:definition "A 'coParticipatesAsRoleIn' predicate refers to members of a range ClassOfActivity in which members of the domain ClassOfPhysicalObject participate in the 
			Role of PERFORMER"@en '
       rdfs:domain lci:ClassOfPhysicalObject ;
       rdfs:range dm:ClassOfActivity .

pred:coParticipatesAsSubjectIn
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:coIndividualInterrelationship ;
       skos:definition "A 'coParticipatesAsRoleIn' predicate refers to members of a range ClassOfActivity in which members of the domain ClassOfPhysicalObject participate in the 
			Role of SUBJECT"@en '
       rdfs:domain lci:ClassOfPhysicalObject ;
       rdfs:range dm:ClassOfActivity .

pred:contains
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:individualInterrelationship ;
       skos:definition "A 'contains' predicate refers to the range PhysicalObject that is contained in the domain PhysicalObject"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range dm:PhysicalObject .

pred:coContains
       rdf:type owl:ObjectProperty ;
       rdfs:subPropertyOf pred:coIndividualInterrelationship ;
       skos:definition "A 'coContains' predicate refers to the range ClassOfPhysicalObject members of which can be contained in members of the domain ClassOfPhysicalObject"@en ;
       rdfs:domain lci:ClassOfPhysicalObject ;
       rdfs:range lci:ClassOfPhysicalObject .

pred:pressure-barg
       rdf:type owl:DatatypeProperty ;
       rdfs:subPropertyOf pred:hasQuantifyableCharacteristic ;
       skos:definition "A 'pressureInBarg' predicate refers to the range numerical value of some form of PRESSURE, possessed by the domain PhysicalObject, that is mapped to the 
			BAR GAUGE Scale"@en ;
       rdfs:domain dm:PhysicalObject ;
       rdfs:range xsd:decimal .

pred:coPressure-barg
       rdf:type owl:DatatypeProperty ;
       rdfs:subPropertyOf pred:coHasQuantifyableCharacteristic ;
       skos:definition "A 'coPressureInBarg' predicate refers to the range numerical value of some form of PRESSURE, possessed by members of the domain ClassOfPhysicalObject, 
			that is mapped to the BAR GAUGE Scale"@en ;
       rdfs:domain lci:ClassOfPhysicalObject ;
       rdfs:range xsd:decimal .

Graph

The above triples for the given instance of the TAG PROPERTY table can be shown in a graph:

Optional precise definition of semantics

Optionally each Predicate can be precisely defined with one or more specialized instances of a Part 7 Template, so in fact a mapping to templates in disguise, be it that in this case each mapping has to be done only once and by a standardization body (please don't hold your breath for this).

This can be done by using the rdfs:isDefinedBy predicate.

One random example:

Validating with SHACL

The instances of declarations and predicates can be validated with SHACL "shapes", as described in the topic 'Validating RDF data with SHACL' (which, btw, needs an update).

It is conceivable that the SHACL code can be derived from the predicate definitions. That still has to be determined (contributions are welcome!)

Epilog

The advantages of the TP+P Method vs the customary method with templates are:

  1. Users can design their own predicates, as a specialization of standardized generic predicates, that can be defined with specialized templates, thus becoming 15926-compliant;
  2. Modeling can be done by engineers (with some training);
  3. Less 'outlandish' for RDF experts;
  4. Easier to query;
  5. Less verbose,
  6. Easier to develop software because highly generic and repetitive.
  7. One disadvantage: It is impossible to attribute metadata, such as 'status', other than valEffectiveDate and valDeprecation date.