Example 6: Situations

A patient health record -- tracking change with gufo:Situation and its five subclasses

gufo:Situation gufo:QualityValueAttributionSituation gufo:TemporaryInstantiationSituation gufo:TemporaryParthoodSituation gufo:TemporaryConstitutionSituation gufo:TemporaryRelationshipSituation gufo:broughtAbout gufo:contributedToTrigger

What you'll learn

Plain OWL assertions are timeless: :Nora a :OverweightPerson says Nora is (tenselessly) overweight, with no way to say when. Most of the facts a health record needs to track -- a patient's weight, a transient diagnosis, which heart is currently theirs -- are exactly the kind that hold for a while and then stop holding. gUFO's gufo:Situation and its five subclasses reify "this held, during this period" as an individual in its own right, giving you somewhere to attach a begin and end point. This example walks through all five, on one patient's record.

The domain

Nora Whitfield's health record: her weight over two years, a period in which she counted as overweight, a heart transplant, a dental crown re-made in a different material, and a comparison with another patient at intake. (Patient names are fictional.)

The common shape

Every pattern below follows the same "qualified relation" shape: the endurant stands in a situation via a standsInQualified... property; the situation itself is further described with concerns... properties (identifying what the situation is about) and, like any concrete individual, with gufo:hasBeginPointInXSDDate/gufo:hasEndPointInXSDDate.

Step by step

1. Quality value attribution: a value that changes

Rather than a single gufo:hasQualityValue assertion (as in example 3, for a quality that does not change), each value Nora's weight has taken becomes its own situation:

:NoraWeighs82KgIn2023 a gufo:QualityValueAttributionSituation ;
    gufo:concernsQualityType :Weight ;
    gufo:concernsQualityValue "82.0"^^xsd:double ;
    gufo:hasBeginPointInXSDDate "2023-01-10"^^xsd:date ;
    gufo:hasEndPointInXSDDate "2023-06-30"^^xsd:date .

:NoraWeighs75KgIn2024 a gufo:QualityValueAttributionSituation ;
    gufo:concernsQualityType :Weight ;
    gufo:concernsQualityValue "75.0"^^xsd:double ;
    gufo:hasBeginPointInXSDDate "2024-01-15"^^xsd:date .

:Nora gufo:standsInQualifiedAttribution :NoraWeighs82KgIn2023 , :NoraWeighs75KgIn2024 .

:Weight here is just a plain subclass of gufo:Quality, used as the object of gufo:concernsQualityType -- note this is a different use of "Weight" than instantiating it with a reified quality individual (as Gemstone1Mass was in example 3): here the class itself is what is pointed to, since gufo:concernsQualityType's range is gufo:EndurantType, not gufo:Quality. This is OWL 2 punning again -- the same mechanism used throughout example 1 and example 7, except here it happens implicitly: simply using :Weight as the object of a property whose range is gufo:EndurantType is enough for a reasoner to type it accordingly, without an explicit :Weight a gufo:Kind triple.

2. Temporary instantiation: a phase held for a while

Instead of a plain, tenseless :Nora a :OverweightPerson, the period during which the phase applied is recorded explicitly:

:NoraWasOverweightUntilJune2023 a gufo:TemporaryInstantiationSituation ;
    gufo:concernsNonRigidType :OverweightPerson ;
    gufo:hasBeginPointInXSDDate "2020-03-01"^^xsd:date ;
    gufo:hasEndPointInXSDDate "2023-06-30"^^xsd:date .

:Nora gufo:standsInQualifiedInstantiation :NoraWasOverweightUntilJune2023 .

Note the end date lines up with when her weight (tracked above) drops below the overweight threshold -- the two situations are about the same change in the world, recorded from two different angles (a quality's value, and a phase's applicability).

3. Temporary parthood: a heart transplant, and what caused it

A part that can be swapped out -- like a heart, once transplant surgery exists -- should not be linked to its whole with a plain gufo:isComponentOf assertion (which example 2 used for a car's engine, treating the link as essentially permanent). Instead, each parthood episode is its own situation:

:NoraHadNativeHeart a gufo:TemporaryParthoodSituation ;
    gufo:concernsTemporaryWhole :Nora ;
    gufo:hasEndPointInXSDDate "2024-03-05"^^xsd:date .
:NoraNativeHeart gufo:standsInQualifiedParthood :NoraHadNativeHeart .

:NoraHasDonorHeart a gufo:TemporaryParthoodSituation ;
    gufo:concernsTemporaryWhole :Nora ;
    gufo:hasBeginPointInXSDDate "2024-03-05"^^xsd:date .
:DonorHeart881 gufo:standsInQualifiedParthood :NoraHasDonorHeart .

What caused the second situation to start? The surgery itself, and gUFO has a property just for "an event brought this situation about":

:NoraHeartTransplant20240305 a :HeartTransplantSurgery ;
    gufo:hasBeginPointInXSDDate "2024-03-05"^^xsd:date ;
    gufo:broughtAbout :NoraHasDonorHeart .

4. Temporary constitution: same crown, different material

Nora's dental crown keeps its identity across a repair, even though what it is made of changes -- exactly the kind of case gufo:TemporaryConstitutionSituation is for (mirroring the Venus de Milo example in the gUFO usage guide, which loses its arms without losing its identity):

:NoraCrownWasPorcelain a gufo:TemporaryConstitutionSituation ;
    gufo:concernsConstitutedEndurant :NoraCrown ;
    gufo:hasEndPointInXSDDate "2022-11-20"^^xsd:date .
:OriginalPorcelainBatch gufo:standsInQualifiedConstitution :NoraCrownWasPorcelain .

:NoraCrownIsResin a gufo:TemporaryConstitutionSituation ;
    gufo:concernsConstitutedEndurant :NoraCrown ;
    gufo:hasBeginPointInXSDDate "2022-11-21"^^xsd:date .
:ReplacementResinBatch gufo:standsInQualifiedConstitution :NoraCrownIsResin .

5. Temporary relationship: a comparison that can flip

Finally, a relationship between two patients that depends on a quality that changes -- "heavier than" -- is qualified the same way, with the relationship type itself declared a gufo:ComparativeRelationshipType derived from the Weight quality, exactly as the usage guide recommends:

:heavierThan a owl:ObjectProperty , gufo:ComparativeRelationshipType ;
    rdfs:domain :Patient ; rdfs:range :Patient ;
    gufo:isDerivedFrom :Weight .

:NoraHeavierThanMiguelOn20240115 a gufo:TemporaryRelationshipSituation ;
    gufo:concernsRelationshipType :heavierThan ;
    :concernsLighterPatient :Miguel ;
    gufo:hasBeginPointInXSDDate "2024-01-15"^^xsd:date ;
    gufo:hasEndPointInXSDDate "2024-01-15"^^xsd:date .

:Nora :standsAsHeavierPatient :NoraHeavierThanMiguelOn20240115 .

Bonus: a weaker link, gufo:contributedToTrigger

gufo:broughtAbout (step 3) links an event to a situation it is sufficient to explain. Sometimes a situation only plays a part in causing an event, without being sufficient on its own -- gUFO's gufo:contributedToTrigger is for that weaker claim, going the other direction (situation → event):

:NoraWasFebrileOnAdmission a gufo:TemporaryInstantiationSituation ;
    gufo:concernsNonRigidType :FebrilePatient ;
    gufo:hasBeginPointInXSDDateTimeStamp "2024-02-02T08:00:00Z"^^xsd:dateTimeStamp ;
    gufo:hasEndPointInXSDDateTimeStamp "2024-02-02T14:00:00Z"^^xsd:dateTimeStamp ;
    gufo:contributedToTrigger :SepsisAlert20240202 .

Nora's fever, by itself, does not guarantee the alert fires (other vitals matter too) -- it merely contributed. This mirrors example 5's gufo:historicallyDependsOn, but at the situation, rather than event-to-event, level.

Going further: gufoevents

This example only says that each pair of situations replaced one another -- it never models the event in between that changed things (the transplant surgery is the one exception, via gufo:broughtAbout). The gufoevents extension supplies dedicated event classes for exactly these transitions, each already axiomatized to bring about the right kind of situation: gufoevents:QualityValueChange for step 1's change in Nora's weight, gufoevents:Declassification/Reclassification for step 2's phase change, gufoevents:PartReplacement for step 3's heart transplant (a single complex event composed of the separation of the native heart and the incorporation of the donor heart), and gufoevents:ConstituentSubstitution for step 4's crown re-made in a different material. Reaching for gufoevents is worthwhile whenever an ontology needs to reason about the change itself -- not just about the before-and-after situations it connects.

The full ontology

See ontology.ttl for the complete file.

How this is checked

Each situation subclass carries its own qualified cardinality restrictions (e.g. TemporaryConstitutionSituation requires exactly one gufo:concernsConstitutedEndurant value that is a gufo:Object, and exactly one endurant standing in it via the inverse of gufo:standsInQualifiedConstitution) -- these are exactly the kind of thing a DL reasoner checks well.

cd examples/tests
.venv/bin/pytest -v -k 06-situations