################################################################################
# MiKaDo — operational vocabulary (so:)
#
# Leaf classes instantiated at export, under
# https://w3id.org/durair/ontology/situated-observation#
# Companion OWL/XML: mikado-schema.owl
#
# TBox only — no individuals. Pivot layer: ontology/mikado.ttl
################################################################################

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix schema: <https://schema.org/> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix so: <https://w3id.org/durair/ontology/situated-observation#> .

#################################################################
# Ontology metadata
#################################################################

<https://w3id.org/durair/ontology/situated-observation> a owl:Ontology ;
    rdfs:label "MiKaDo (Material integration of Knowledge and Digital observation) — fragment situated-observation"@en ;
    dct:title "MiKaDo ontology (situated-observation namespace)"@en ;
    dct:creator <https://orcid.org/0000-0001-7600-2273> ,
                <https://orcid.org/0000-0003-3724-4829> ,
                <https://orcid.org/0009-0001-3313-0587> ;
    dct:publisher [ a foaf:Organization ;
                    foaf:name "MAP — UPR 2002 CNRS" ;
                    foaf:homepage <https://www.map.cnrs.fr/> ] ;
    dct:rightsHolder "CNRS" ;
    schema:funder [ a schema:Organization ;
                    schema:name "European Research Council" ;
                    schema:alternateName "n-Dame_Heritage" ;
                    schema:identifier "101055423" ;
                    schema:url <http://www.ndameheritage.map.cnrs.fr/> ] ;
    rdfs:comment "Operational vocabulary for situated-observation graphs produced by field engines."@en ;
    owl:versionInfo "Aligned on dür.air export schema ≥ 107."@en .

<https://orcid.org/0000-0001-7600-2273> a foaf:Person ;
    foaf:name "Livio De Luca" ;
    foaf:mbox <mailto:livio.deluca@map.cnrs.fr> .

<https://orcid.org/0000-0003-3724-4829> a foaf:Person ;
    foaf:name "Anthony Pamart" .

<https://orcid.org/0009-0001-3313-0587> a foaf:Person ;
    foaf:name "Quentin Vogel" .

#################################################################
# Classes — documentary roots
#################################################################

so:MaterialEntity a owl:Class ;
    rdfs:label "MaterialEntity"@en ;
    rdfs:comment "Locatable material referent of an observation."@en .

so:DigitalEntity a owl:Class ;
    rdfs:label "DigitalEntity"@en ;
    rdfs:comment "Tangible digital representation (frame, audio, 3D, file)."@en .

so:KnowledgeEntity a owl:Class ;
    rdfs:label "KnowledgeEntity"@en ;
    rdfs:comment "Semantic interpretation of an observation (title, class, template, alignment)."@en .

#################################################################
# Classes — capture and media
#################################################################

so:CaptureFrame a owl:Class ;
    rdfs:subClassOf so:DigitalEntity ;
    rdfs:label "CaptureFrame"@en .

so:VoiceRecording a owl:Class ;
    rdfs:subClassOf so:DigitalEntity ;
    rdfs:label "VoiceRecording"@en .

so:AnnotationShape a owl:Class ;
    rdfs:subClassOf so:DigitalEntity ;
    rdfs:label "AnnotationShape"@en .

so:PointAnnotationShape a owl:Class ;
    rdfs:subClassOf so:AnnotationShape ;
    rdfs:label "PointAnnotationShape"@en .

so:RegionAttachment a owl:Class ;
    rdfs:subClassOf so:DigitalEntity ;
    rdfs:label "RegionAttachment"@en .

so:SessionPointCloud a owl:Class ;
    rdfs:subClassOf so:DigitalEntity ;
    rdfs:label "SessionPointCloud"@en .

so:PhotogrammetryReconstruction a owl:Class ;
    rdfs:subClassOf so:DigitalEntity ;
    rdfs:label "PhotogrammetryReconstruction"@en .

#################################################################
# Classes — structured knowledge and templates
#
# DiscursiveKnowledgeEntity: knowledge stated by a human.
# MetrologicalKnowledgeEntity: knowledge from intentional measurement.
# DerivedKnowledgeEntity is deprecated; computed facts live under DerivedFeature.
#################################################################

so:DiscursiveKnowledgeEntity a owl:Class ;
    rdfs:subClassOf so:KnowledgeEntity ;
    rdfs:label "DiscursiveKnowledgeEntity"@en .

so:MetrologicalKnowledgeEntity a owl:Class ;
    rdfs:subClassOf so:KnowledgeEntity ;
    rdfs:label "MetrologicalKnowledgeEntity"@en .

so:DerivedKnowledgeEntity a owl:Class ;
    owl:deprecated true ;
    rdfs:subClassOf so:KnowledgeEntity ;
    rdfs:label "DerivedKnowledgeEntity (deprecated)"@en ;
    rdfs:comment "DEPRECATED — superseded by so:DerivedFeature. Originally introduced as an intermediate root under so:KnowledgeEntity for computational artifacts (descriptors, similarity buckets), this class is now subsumed by the symmetric pivot so:DerivedFeature, which makes the conceptual distinction clearer: a *computed fact* is not a *knowledge statement about a feature* but a feature in its own right. Existing leaves (SpatialBucket, GeometricBucket, VisualBucket, SemanticBucket, GeometricDescriptorSnapshot, VisualDescriptorSnapshot) have been re-parented to so:DerivedFeature. The class itself is kept for backward compatibility with consumers that may have stored references to its IRI."@en .

# Discursive

so:AnnotationClass a owl:Class ;
    rdfs:subClassOf so:DiscursiveKnowledgeEntity ;
    rdfs:label "AnnotationClass"@en .

so:AnnotationTitle a owl:Class ;
    rdfs:subClassOf so:DiscursiveKnowledgeEntity ;
    rdfs:label "AnnotationTitle"@en .

so:AnnotationDescription a owl:Class ;
    rdfs:subClassOf so:DiscursiveKnowledgeEntity ;
    rdfs:label "AnnotationDescription"@en .

so:AnnotationDescriptionTemplate a owl:Class ;
    rdfs:subClassOf so:DiscursiveKnowledgeEntity ;
    rdfs:label "AnnotationDescriptionTemplate"@en .

so:TemplateFieldSlot a owl:Class ;
    rdfs:subClassOf so:DiscursiveKnowledgeEntity ;
    rdfs:label "TemplateFieldSlot"@en .

so:TemplateFieldValue a owl:Class ;
    rdfs:subClassOf so:DiscursiveKnowledgeEntity ;
    rdfs:label "TemplateFieldValue"@en .

# Metrological

so:QuantitativeMeasurement a owl:Class ;
    rdfs:subClassOf so:MetrologicalKnowledgeEntity ;
    rdfs:label "QuantitativeMeasurement"@en .

# Derived (deprecated parent)

so:GeometricDescriptorSnapshot a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "GeometricDescriptorSnapshot"@en ;
    rdfs:comment "Vector of geometric features (size, elongation, curvature, planarity, …) computed automatically from an annotation shape; used as input to so:GeometricBucket. Re-parented from so:DerivedKnowledgeEntity (deprecated) to so:DerivedFeature."@en .

so:VisualDescriptorSnapshot a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "VisualDescriptorSnapshot"@en ;
    rdfs:comment "Vector of appearance features (dominant color, gradient, texture structure, …) computed automatically from media bound to a feature; used as input to so:VisualBucket. Re-parented from so:DerivedKnowledgeEntity (deprecated) to so:DerivedFeature."@en .

so:SpatialBucket a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "SpatialBucket"@en .

so:GeometricBucket a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "GeometricBucket"@en .

so:VisualBucket a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "VisualBucket"@en .

so:SemanticBucket a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "SemanticBucket"@en .

#################################################################
# Classes — programme, actor, observation
#################################################################

so:Actor a owl:Class ;
    owl:deprecated true ;
    rdfs:label "Actor"@en .

so:ObservationProgram a owl:Class ;
    rdfs:label "ObservationProgram"@en .

so:InSituObservation a owl:Class ;
    rdfs:label "InSituObservation"@en .

so:InSituObservationSession a owl:Class ;
    rdfs:subClassOf so:InSituObservation ;
    rdfs:label "InSituObservationSession"@en .

so:InSituObservationAct a owl:Class ;
    rdfs:subClassOf so:InSituObservation ;
    rdfs:label "InSituObservationAct"@en .

so:ExSituObservation a owl:Class ;
    rdfs:label "ExSituObservation"@en .

so:ExSituObservationAct a owl:Class ;
    rdfs:subClassOf so:ExSituObservation ;
    rdfs:label "ExSituObservationAct"@en .

#################################################################
# Common root — so:MIKADOFeature
#
# ObservedFeature (observed fact) and DerivedFeature (computed fact).
# TBox-only: not emitted as @type at export time.
#################################################################

so:MIKADOFeature a owl:Class ;
    rdfs:label "MIKADOFeature"@en ;
    rdfs:comment "Common root of the two MiKaDo pivots: ObservedFeature (the observed fact, anchored on a human gesture chain) and DerivedFeature (the computed fact, anchored on a sub-graph derivation). TBox-only refinement, never emitted as @type at export time."@en .

so:ObservedFeature a owl:Class ;
    rdfs:subClassOf so:MIKADOFeature ;
    rdfs:label "ObservedFeature"@en .

#################################################################
# Symmetric pivot — so:DerivedFeature
#
# Computed facts (buckets, descriptors, profiles, provenance, coverage).
# Anchored to the input sub-graph by so:hasDerivationInput.
#################################################################

so:DerivedFeature a owl:Class ;
    rdfs:subClassOf so:MIKADOFeature ;
    rdfs:label "DerivedFeature"@en ;
    rdfs:comment "Computed fact emerging from a deterministic operation on a sub-graph (similarity bucketing, descriptor extraction, statistical profiling, provenance trace, comparative diff, coverage matrix, narrative digest). Anchored to its input sub-graph via so:hasDerivationInput (subproperty of prov:wasDerivedFrom). Symmetrical to so:ObservedFeature."@en .

#################################################################
# so:StatisticalProfile and so:CoverageMatrix
#################################################################

so:StatisticalProfile a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "StatisticalProfile"@en ;
    rdfs:comment "Aggregated counts and distributions computed at export time on the scope of an ObservationProgram (project profile) or an InSituObservationSession (session profile). Carries primitive counters (acts, features, regions, measurements, voices, frames, emitted buckets and descriptors, duration) plus a `statisticalProfileJson` literal that holds verbose distributions (per featureKind, per bucketFamily, top-N annotation classes). Anchored to its scope by `so:hasDerivationInput`."@en .

so:CoverageMatrix a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "CoverageMatrix"@en ;
    rdfs:comment "Documentary saturation matrix computed at export time on the scope of an ObservationProgram. Carries seven per-axis ratios (`coverageRatioWho`, `…Why`, `…What`, `…When`, `…Where`, `…How`, `…WithWhat`) plus an overall ratio. Decomposed into seven `so:CoverageDimension` sub-nodes (one per documentation axis) via `so:hasCoverageDimension`, and one `so:SpatialCoverage` sub-node via `so:hasSpatialCoverage`. The `taxonomicGapsJson` literal records under-represented SKOS concepts (curated v87 alignments) at the time of export."@en .

so:CoverageDimension a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "CoverageDimension"@en ;
    rdfs:comment "Per-axis breakdown of a `so:CoverageMatrix`. Identifies the documentation axis via `so:documentationAxis` (who, why, what, when, where, how, withWhat), counts of required vs. filled fields, computed ratio, and number of curated SKOS concepts cited on this axis. The full per-field listing is carried inline in `dimensionFieldsListJson`."@en .

so:SpatialCoverage a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "SpatialCoverage"@en ;
    rdfs:comment "Spatial saturation sub-node of a `so:CoverageMatrix`: count of distinct 1m grid cells visited (`spatialCellsVisitedCount`), bounding box volume in cubic meters (`spatialBoundingBoxVolumeM3`), and ratio of visited cells over the bounding box volume (`spatialDensityRatio`). Computed on the ARKit session world frame; decoupled from the seven documentation axes."@en .

#################################################################
# so:ProvenanceRecord and so:DerivationTrace
#################################################################

so:ProvenanceRecord a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:subClassOf prov:Entity ;
    rdfs:label "ProvenanceRecord"@en ;
    rdfs:comment "Reified provenance fact about another fact (observed or derived). Subclass of so:DerivedFeature (a provenance record is itself a computed fact, derived from a sub-graph) and of prov:Entity (it is the explicit anchor of a PROV lineage). Specialised at v90 by so:DerivationTrace (prov:Activity pivot — execution-side reification), at v91 by so:LineageRecord (prov:Entity pivot — structure-side reification), and at v92 by so:QualityScore (prov:Entity pivot — aggregate reliability score). Each materialised leaf is computed from the already emitted `@graph` and shares the same cardinality — one node per (project, derivationMethod) pair, up to eight nodes per export."@en .

so:DerivationTrace a owl:Class ;
    rdfs:subClassOf so:ProvenanceRecord ;
    rdfs:subClassOf prov:Activity ;
    rdfs:label "DerivationTrace"@en ;
    rdfs:comment "Reifies the execution of a derivation method on a project. One instance per (project, derivationMethod) pair: at v90, up to eight traces per export (six historical leaf families @v89 + StatisticalProfile @v88 + CoverageMatrix @v88). Carries the software agent version (`so:softwareAgentVersion`), the execution timestamps (`so:executionStartTime` / `so:executionEndTime`, sub-properties of `prov:startedAtTime` / `prov:endedAtTime`) and the SHA-256 hash of the parameter JSON (`so:parametersHashSha256`). The hashed JSON is itself emitted on the trace as `so:derivationParametersJson` (same literal as on each derived leaf, single source of truth). Aligned with `prov:Activity`."@en .

#################################################################
# so:LineageRecord
#################################################################

so:LineageRecord a owl:Class ;
    rdfs:subClassOf so:ProvenanceRecord ;
    rdfs:subClassOf prov:Entity ;
    rdfs:label "LineageRecord"@en ;
    rdfs:comment "Reifies the *structure* of the derivation chain shared by a family of so:DerivedFeature leaves: depth from the W7 root, types of root and direct inputs, number of leaves sharing the lineage. Cardinality: one instance per (project, derivationMethod) pair — symmetrical with so:DerivationTrace (a LineageRecord and a DerivationTrace coexist for each active method, one capturing the entity-side of provenance, the other the activity-side). Carries `so:lineageDepth` (xsd:integer, longest `hasDerivationInput` chain length to a primary source), `so:lineageLeafCount` (xsd:nonNegativeInteger, count of leaves sharing this LineageRecord), and `so:lineageRootInputTypes` / `so:lineageDirectInputTypes` (xsd:string, alphabetic `|`-separated list of so:-types of root and direct inputs). Linked to the corresponding so:DerivationTrace via `so:lineageGeneratedBy`. Aligned with `prov:Entity`."@en .

#################################################################
# so:QualityScore
#################################################################

so:QualityScore a owl:Class ;
    rdfs:subClassOf so:ProvenanceRecord ;
    rdfs:subClassOf prov:Entity ;
    rdfs:label "QualityScore"@en ;
    rdfs:comment "Aggregate reliability score for a family of DerivedFeature leaves that share a derivationMethod. One node per (project, method), aligned with prov:Entity."@en .

#################################################################
# so:ComparativeReport and so:ComparisonItem
#################################################################

so:ComparativeReport a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "ComparativeReport"@en ;
    rdfs:comment "Comparative knowledge between two archived MiKaDo exports (campaigns, observers or vocabulary profiles). Produced post-export, typically by SPARQL CONSTRUCT."@en .

so:ComparisonItem a owl:Class ;
    rdfs:subClassOf so:DerivedFeature ;
    rdfs:label "ComparisonItem"@en ;
    rdfs:comment "Per-method detail of a `so:ComparativeReport`: one node per derivation method present in at least one of the two compared exports. Carries the method identifier (`so:comparisonItemMethod`), the comparison status (`so:comparisonItemStatus`, one of `identical-parameters` / `divergent-parameters` / `only-A` / `only-B`), and optionally the two `parametersHashSha256` values from each side (`so:comparisonItemHashA`, `so:comparisonItemHashB`)."@en .

so:hasComparisonItem a owl:ObjectProperty ;
    rdfs:domain so:ComparativeReport ;
    rdfs:range so:ComparisonItem ;
    rdfs:label "hasComparisonItem"@en ;
    rdfs:comment "Links a so:ComparativeReport to one of its per-method so:ComparisonItem detail nodes."@en .

so:comparisonAxis a owl:DatatypeProperty ;
    rdfs:domain so:ComparativeReport ;
    rdfs:range xsd:string ;
    rdfs:label "comparisonAxis"@en ;
    rdfs:comment "Main axis of the comparison, one of `longitudinal-same-project` (same project, two successive exports), `cross-project-same-material` (two projects on the same MaterialEntity), `inter-actor` (two actors on the same protocol), `vocabulary-drift` (two SKOS profiles)."@en .

so:comparativeMethod a owl:DatatypeProperty ;
    rdfs:subPropertyOf so:derivationMethod ;
    rdfs:domain so:ComparativeReport ;
    rdfs:range xsd:string ;
    rdfs:label "comparativeMethod"@en ;
    rdfs:comment "Identifier (and version) of the comparative algorithm — format `durair.comparative-report@vXX`. Sub-property of so:derivationMethod (a comparative report is a derived feature whose method is the diff algorithm itself)."@en .

so:comparativeParametersJson a owl:DatatypeProperty ;
    rdfs:subPropertyOf so:derivationParametersJson ;
    rdfs:domain so:ComparativeReport ;
    rdfs:range xsd:string ;
    rdfs:label "comparativeParametersJson"@en ;
    rdfs:comment "Inline JSON literal of the effective parameters used by the comparative method (e.g. tolerance thresholds, axis weights). Sub-property of so:derivationParametersJson."@en .

so:parametersIdentityRate a owl:DatatypeProperty ;
    rdfs:domain so:ComparativeReport ;
    rdfs:range xsd:decimal ;
    rdfs:label "parametersIdentityRate"@en ;
    rdfs:comment "Fraction of derivation methods that share an identical `parametersHashSha256` between the two compared exports. Value in [0, 1]; 1 means every method present on both sides was run with strictly identical effective parameters."@en .

so:comparisonItemMethod a owl:DatatypeProperty ;
    rdfs:domain so:ComparisonItem ;
    rdfs:range xsd:string ;
    rdfs:label "comparisonItemMethod"@en ;
    rdfs:comment "Identifier of the derivation method whose parameters are being compared on this item (e.g. `durair.coverage-matrix@v88`)."@en .

so:comparisonItemStatus a owl:DatatypeProperty ;
    rdfs:domain so:ComparisonItem ;
    rdfs:range xsd:string ;
    rdfs:label "comparisonItemStatus"@en ;
    rdfs:comment "Outcome of the per-method comparison: `identical-parameters`, `divergent-parameters`, `only-A` (method present only in the left export), `only-B` (method present only in the right export)."@en .

so:comparisonItemHashA a owl:DatatypeProperty ;
    rdfs:domain so:ComparisonItem ;
    rdfs:range xsd:string ;
    rdfs:label "comparisonItemHashA"@en ;
    rdfs:comment "`parametersHashSha256` of the method on the left-hand export, when present (lowercase hex × 64)."@en .

so:comparisonItemHashB a owl:DatatypeProperty ;
    rdfs:domain so:ComparisonItem ;
    rdfs:range xsd:string ;
    rdfs:label "comparisonItemHashB"@en ;
    rdfs:comment "`parametersHashSha256` of the method on the right-hand export, when present (lowercase hex × 64)."@en .

#################################################################
# Class — export envelope
#################################################################

so:GraphSnapshot a owl:Class ;
    rdfs:label "GraphSnapshot"@en ;
    rdfs:comment "Reification of an RDF export (profile, schema version, described programme)."@en .

so:exportProfile a owl:DatatypeProperty ;
    rdfs:domain so:GraphSnapshot ;
    rdfs:range xsd:string ;
    rdfs:label "exportProfile"@en ;
    rdfs:comment "Stable export-profile identifier (e.g. durair.mikado-ontology-doc)."@en .

so:schemaVersion a owl:DatatypeProperty ;
    rdfs:domain so:GraphSnapshot ;
    rdfs:range xsd:integer ;
    rdfs:label "schemaVersion"@en ;
    rdfs:comment "Integer version of the operational export schema."@en .

so:describesObservationProgram a owl:ObjectProperty ;
    rdfs:domain so:GraphSnapshot ;
    rdfs:range so:ObservationProgram ;
    rdfs:label "describesObservationProgram"@en .

#################################################################
# Object properties — programme / session / material
#################################################################

so:involvesActor a owl:ObjectProperty ;
    owl:deprecated true ;
    rdfs:domain so:ObservationProgram ;
    rdfs:range so:Actor ;
    rdfs:label "involvesActor"@en .

so:concernsMaterial a owl:ObjectProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:ObservationProgram so:InSituObservationSession ) ] ;
    rdfs:range so:MaterialEntity ;
    rdfs:label "concernsMaterial"@en .

so:partOfObservationProgram a owl:ObjectProperty ;
    rdfs:domain so:InSituObservationSession ;
    rdfs:range so:ObservationProgram ;
    rdfs:label "partOfObservationProgram"@en .

so:hasSessionPointCloud a owl:ObjectProperty ;
    rdfs:domain so:InSituObservationSession ;
    rdfs:range so:SessionPointCloud ;
    rdfs:label "hasSessionPointCloud"@en .

so:hasPhotogrammetryReconstruction a owl:ObjectProperty ;
    rdfs:domain so:InSituObservationSession ;
    rdfs:range so:PhotogrammetryReconstruction ;
    rdfs:label "hasPhotogrammetryReconstruction"@en .

#################################################################
# Object properties — act sequence
#################################################################

so:followsInSituObservation a owl:ObjectProperty ;
    rdfs:domain so:InSituObservationAct ;
    rdfs:range so:InSituObservationAct ;
    rdfs:label "followsInSituObservation"@en .

so:followsExSituObservation a owl:ObjectProperty ;
    rdfs:domain so:ExSituObservationAct ;
    rdfs:range so:ExSituObservationAct ;
    rdfs:label "followsExSituObservation"@en .

so:hasFirstObservationAct a owl:ObjectProperty ;
    rdfs:domain so:InSituObservationSession ;
    rdfs:range so:InSituObservationAct ;
    rdfs:label "hasFirstObservationAct"@en .

so:hasFirstExSituObservationAct a owl:ObjectProperty ;
    rdfs:domain so:InSituObservationSession ;
    rdfs:range so:ExSituObservationAct ;
    rdfs:label "hasFirstExSituObservationAct"@en .

#################################################################
# Object properties — act to feature / frame
#################################################################

so:partOfEpisode a owl:ObjectProperty ;
    rdfs:domain so:InSituObservationAct ;
    rdfs:range so:InSituObservationSession ;
    rdfs:label "partOfEpisode"@en .

so:targetsObservedFeature a owl:ObjectProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:InSituObservationAct so:ExSituObservationAct ) ] ;
    rdfs:range so:ObservedFeature ;
    rdfs:label "targetsObservedFeature"@en .

# Super-property: range DigitalEntity. producesCaptureFrame remains the operational link.
so:relatesToDigitalContent a owl:ObjectProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:InSituObservationAct so:ExSituObservationAct ) ] ;
    rdfs:range so:DigitalEntity ;
    rdfs:label "relates to digital content"@en ;
    rdfs:comment "Semantic aggregate: digital outputs tied to the observation act (subproperty producesCaptureFrame; feature path via refersToDigitalEntityViaFeature). Explicit DigitalEntity range for TBox tools."@en .

so:producesCaptureFrame a owl:ObjectProperty ;
    rdfs:subPropertyOf so:relatesToDigitalContent ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:InSituObservationAct so:ExSituObservationAct ) ] ;
    rdfs:range so:CaptureFrame ;
    rdfs:label "producesCaptureFrame"@en ;
    rdfs:comment "Export **≥ 102**: for *ex situ* region / measurement / voice acts (`spatialAcquisitionContext`), this predicate is **not** emitted — acquisition was in situ; the `ObservedFeature` stays linked via `onCaptureFrame`."@en .

#################################################################
# Object properties — feature
#################################################################

so:onCaptureFrame a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:CaptureFrame ;
    rdfs:label "onCaptureFrame"@en .

so:hasDigitalManifestation a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:DigitalEntity ;
    rdfs:label "hasDigitalManifestation"@en .

# OWL 2 property chain: act → feature → digital entity.
so:refersToDigitalEntityViaFeature a owl:ObjectProperty ;
    rdfs:subPropertyOf so:relatesToDigitalContent ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:InSituObservationAct so:ExSituObservationAct ) ] ;
    rdfs:range so:DigitalEntity ;
    rdfs:label "refers to digital entity via feature"@en ;
    owl:propertyChainAxiom ( so:targetsObservedFeature so:hasDigitalManifestation ) .

so:hasKnowledge a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:KnowledgeEntity ;
    rdfs:label "hasKnowledge"@en .

so:hasAnnotationTitle a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:AnnotationTitle ;
    rdfs:label "hasAnnotationTitle"@en .

so:hasAnnotationDescription a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:AnnotationDescription ;
    rdfs:label "hasAnnotationDescription"@en .

so:hasAnnotationShape a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:AnnotationShape ;
    rdfs:label "hasAnnotationShape"@en .

so:belongsToClass a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:AnnotationClass ;
    rdfs:label "belongsToClass"@en .

so:hasGeometricDescriptor a owl:ObjectProperty ;
    rdfs:domain so:AnnotationShape ;
    rdfs:range so:GeometricDescriptorSnapshot ;
    rdfs:label "hasGeometricDescriptor"@en .

so:hasVisualDescriptor a owl:ObjectProperty ;
    rdfs:domain so:AnnotationShape ;
    rdfs:range so:VisualDescriptorSnapshot ;
    rdfs:label "hasVisualDescriptor"@en .

so:hasRegionAttachment a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:RegionAttachment ;
    rdfs:label "hasRegionAttachment"@en .

so:hasSpatialBucket a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:SpatialBucket ;
    rdfs:label "hasSpatialBucket"@en .

so:hasGeometricBucket a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:GeometricBucket ;
    rdfs:label "hasGeometricBucket"@en .

so:hasVisualBucket a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:VisualBucket ;
    rdfs:label "hasVisualBucket"@en .

so:hasSemanticBucket a owl:ObjectProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range so:SemanticBucket ;
    rdfs:label "hasSemanticBucket"@en .

#################################################################
# Object properties — templates and SKOS
#################################################################

so:usesAnnotationDescriptionTemplate a owl:ObjectProperty ;
    rdfs:domain so:AnnotationDescription ;
    rdfs:range so:AnnotationDescriptionTemplate ;
    rdfs:label "usesAnnotationDescriptionTemplate"@en .

so:hasTemplateFieldValue a owl:ObjectProperty ;
    rdfs:domain so:AnnotationDescription ;
    rdfs:range so:TemplateFieldValue ;
    rdfs:label "hasTemplateFieldValue"@en .

so:partOfAnnotationDescriptionTemplate a owl:ObjectProperty ;
    rdfs:domain so:TemplateFieldSlot ;
    rdfs:range so:AnnotationDescriptionTemplate ;
    rdfs:label "partOfAnnotationDescriptionTemplate"@en .

so:valueOfField a owl:ObjectProperty ;
    rdfs:domain so:TemplateFieldValue ;
    rdfs:range so:TemplateFieldSlot ;
    rdfs:label "valueOfField"@en .

so:annotationClassConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain so:AnnotationClass ;
    rdfs:label "annotationClassConcept"@en .

so:annotationTitleConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain so:AnnotationTitle ;
    rdfs:label "annotationTitleConcept"@en .

#################################################################
# SKOS exact-match aliases for curated fields
#################################################################

so:fieldValueConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain so:TemplateFieldValue ;
    rdfs:label "fieldValueConcept"@en .

so:appellationConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:MaterialEntity so:W7_What_MaterialObject ) ] ;
    rdfs:label "appellationConcept"@en .

so:typologyConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:MaterialEntity so:W7_What_MaterialObject ) ] ;
    rdfs:label "typologyConcept"@en .

so:materialConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:MaterialEntity so:W7_What_MaterialObject ) ] ;
    rdfs:label "materialConcept"@en .

so:acquisitionModalityConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:W7_How so:W7_How_AcquisitionProtocol so:ObservationProgram ) ] ;
    rdfs:label "acquisitionModalityConcept"@en .

so:acquisitionTypeConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:W7_How so:W7_How_AcquisitionProtocol so:ObservationProgram ) ] ;
    rdfs:label "acquisitionTypeConcept"@en .

so:disciplineConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:W7_How so:W7_How_AcquisitionProtocol so:ObservationProgram ) ] ;
    rdfs:label "disciplineConcept"@en .

so:affiliationConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain so:W7_Who ;
    rdfs:label "affiliationConcept"@en .

so:groupConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain so:W7_Who ;
    rdfs:label "groupConcept"@en .

so:roleConcept a owl:ObjectProperty ;
    rdfs:subPropertyOf skos:exactMatch ;
    rdfs:domain so:W7_Who ;
    rdfs:label "roleConcept"@en .

so:conformsTo a owl:ObjectProperty ;
    rdfs:subPropertyOf dct:conformsTo ;
    rdfs:domain so:AnnotationDescription ;
    rdfs:label "conformsTo"@en .

so:alignmentUri a owl:ObjectProperty ;
    rdfs:domain so:AnnotationDescriptionTemplate ;
    rdfs:label "alignmentUri"@en .

so:derivedFrom a owl:ObjectProperty ;
    rdfs:domain so:AnnotationDescription ;
    rdfs:range so:DigitalEntity ;
    rdfs:label "derivedFrom"@en .

#################################################################
# DerivedFeature — input sub-graph
#################################################################

so:hasDerivationInput a owl:ObjectProperty ;
    rdfs:subPropertyOf prov:wasDerivedFrom ;
    rdfs:domain so:DerivedFeature ;
    rdfs:label "hasDerivationInput"@en ;
    rdfs:comment "Anchors a so:DerivedFeature to its input sub-graph (an ObservationProgram, a Session, an Act, one or more ObservedFeature, or a collection of earlier DerivedFeature). Subproperty of prov:wasDerivedFrom for explicit W3C PROV-O alignment. Distinct from the historical so:derivedFrom (transcription)."@en .

so:derivationMethod a owl:DatatypeProperty ;
    rdfs:domain so:DerivedFeature ;
    rdfs:range xsd:string ;
    rdfs:label "derivationMethod"@en ;
    rdfs:comment "Identifier of the algorithm and software version used to compute the derived feature (e.g. 'durair.bucketing.spatial@0.6.5'). Read together with dct:created, gives a minimal provenance trace."@en .

so:derivationParametersJson a owl:DatatypeProperty ;
    rdfs:domain so:DerivedFeature ;
    rdfs:range xsd:string ;
    rdfs:label "derivationParametersJson"@en ;
    rdfs:comment "Inline JSON literal of the effective hyperparameters used to compute the derived feature (e.g. cell size, similarity thresholds, embedding model id). Note: starting v90, the formal prov:Activity node mentioned in earlier versions is materialised as `so:DerivationTrace` (linked via `so:hasDerivationTrace`) and the same parameter JSON is also carried by the trace itself, hashed in `so:parametersHashSha256`."@en .

#################################################################
# Operational provenance — so:DerivationTrace
#################################################################

so:hasDerivationTrace a owl:ObjectProperty ;
    rdfs:subPropertyOf prov:wasGeneratedBy ;
    rdfs:domain so:DerivedFeature ;
    rdfs:range so:DerivationTrace ;
    rdfs:label "hasDerivationTrace"@en ;
    rdfs:comment "Links a so:DerivedFeature to the so:DerivationTrace that reifies the activity which produced it. Subproperty of prov:wasGeneratedBy for explicit W3C PROV-O alignment. Cardinality: at most one trace per (project, derivationMethod) — leaves of the same family share a common trace."@en .

so:softwareAgentVersion a owl:DatatypeProperty ;
    rdfs:domain so:DerivationTrace ;
    rdfs:range xsd:string ;
    rdfs:label "softwareAgentVersion"@en ;
    rdfs:comment "Identifier of the software agent (and its version) that executed the derivation, in the format `dur.air@<bundleVersion>` (e.g. `dur.air@0.6.6`). Read together with `so:executionStartTime` / `so:executionEndTime` and `so:parametersHashSha256`, gives the full operational provenance signature."@en .

so:executionStartTime a owl:DatatypeProperty ;
    rdfs:subPropertyOf prov:startedAtTime ;
    rdfs:domain so:DerivationTrace ;
    rdfs:range xsd:dateTime ;
    rdfs:label "executionStartTime"@en ;
    rdfs:comment "ISO 8601 datetime captured at the very beginning of the export `build` (before any node is constructed). Subproperty of `prov:startedAtTime`."@en .

so:executionEndTime a owl:DatatypeProperty ;
    rdfs:subPropertyOf prov:endedAtTime ;
    rdfs:domain so:DerivationTrace ;
    rdfs:range xsd:dateTime ;
    rdfs:label "executionEndTime"@en ;
    rdfs:comment "ISO 8601 datetime captured just before the trace nodes are appended to the graph. Subproperty of `prov:endedAtTime`. The same end timestamp is shared by all traces of a given export (single export window)."@en .

so:parametersHashSha256 a owl:DatatypeProperty ;
    rdfs:domain so:DerivationTrace ;
    rdfs:range xsd:string ;
    rdfs:label "parametersHashSha256"@en ;
    rdfs:comment "Lower-case hexadecimal SHA-256 digest of the parameter JSON literal carried by `so:derivationParametersJson` on the trace. Provides a stable cryptographic fingerprint of the effective parameters across exports (a single byte change in the parameters yields a completely different hash)."@en .

#################################################################
# Structural provenance — so:LineageRecord
#################################################################

so:hasLineageRecord a owl:ObjectProperty ;
    rdfs:subPropertyOf prov:wasInfluencedBy ;
    rdfs:domain so:DerivedFeature ;
    rdfs:range so:LineageRecord ;
    rdfs:label "hasLineageRecord"@en ;
    rdfs:comment "Links a so:DerivedFeature to the so:LineageRecord that reifies the structure of its derivation chain (depth, root and direct input types, leaves count). Subproperty of prov:wasInfluencedBy for explicit W3C PROV-O alignment. Cardinality: at most one LineageRecord per (project, derivationMethod) — leaves of the same family share a common LineageRecord, symmetrical with the corresponding `so:DerivationTrace`."@en .

so:lineageGeneratedBy a owl:ObjectProperty ;
    rdfs:subPropertyOf prov:wasGeneratedBy ;
    rdfs:domain so:LineageRecord ;
    rdfs:range so:DerivationTrace ;
    rdfs:label "lineageGeneratedBy"@en ;
    rdfs:comment "Links a so:LineageRecord to the so:DerivationTrace that generated it (entity-side reification meets activity-side reification — both pivots are produced by the same export run for the same `(project, derivationMethod)` pair). Subproperty of prov:wasGeneratedBy."@en .

so:lineageDepth a owl:DatatypeProperty ;
    rdfs:domain so:LineageRecord ;
    rdfs:range xsd:integer ;
    rdfs:label "lineageDepth"@en ;
    rdfs:comment "Length of the longest `hasDerivationInput` chain from any leaf sharing this LineageRecord up to a primary source (a node without `derivationMethod`). At v91, equals `1` for the ten currently active families that consume the project's `ObservationProgram` directly, and `2` for `coverage-matrix@v88` because its `CoverageDimension` and `SpatialCoverage` sub-nodes consume the `CoverageMatrix` rather than the `ObservationProgram`. Increases naturally as derived-of-derived chains emerge in v92+."@en .

so:lineageLeafCount a owl:DatatypeProperty ;
    rdfs:domain so:LineageRecord ;
    rdfs:range xsd:nonNegativeInteger ;
    rdfs:label "lineageLeafCount"@en ;
    rdfs:comment "Cardinality of the so:DerivedFeature leaves (excluding so:DerivationTrace, so:LineageRecord and so:ProvenanceRecord nodes themselves) that point to this LineageRecord via `so:hasLineageRecord`. Recomputed at every export from the actually emitted graph (not stored in the source dur.air project)."@en .

so:lineageRootInputTypes a owl:DatatypeProperty ;
    rdfs:domain so:LineageRecord ;
    rdfs:range xsd:string ;
    rdfs:label "lineageRootInputTypes"@en ;
    rdfs:comment "Alphabetic, pipe-separated short names of the root input types reached by traversing hasDerivationInput to primary sources."@en .

so:lineageDirectInputTypes a owl:DatatypeProperty ;
    rdfs:domain so:LineageRecord ;
    rdfs:range xsd:string ;
    rdfs:label "lineageDirectInputTypes"@en ;
    rdfs:comment "Alphabetic, pipe-separated short names of the direct (first-hop) input types of the leaves that share this LineageRecord."@en .

#################################################################
# Aggregate reliability — so:QualityScore
#################################################################

so:hasQualityScore a owl:ObjectProperty ;
    rdfs:subPropertyOf prov:wasInfluencedBy ;
    rdfs:domain so:DerivedFeature ;
    rdfs:range so:QualityScore ;
    rdfs:label "hasQualityScore"@en ;
    rdfs:comment "Links a so:DerivedFeature to the so:QualityScore that reifies the aggregate reliability score for its derivation method on the current project. Subproperty of prov:wasInfluencedBy for explicit W3C PROV-O alignment. Cardinality: at most one QualityScore per (project, derivationMethod) — leaves of the same family share a common QualityScore, symmetrical with the corresponding `so:DerivationTrace` and `so:LineageRecord`."@en .

so:qualityScoreGeneratedBy a owl:ObjectProperty ;
    rdfs:subPropertyOf prov:wasGeneratedBy ;
    rdfs:domain so:QualityScore ;
    rdfs:range so:DerivationTrace ;
    rdfs:label "qualityScoreGeneratedBy"@en ;
    rdfs:comment "Links a so:QualityScore to the so:DerivationTrace that generated it (score-side reification meets activity-side reification — both pivots are produced by the same export run for the same `(project, derivationMethod)` pair). Subproperty of prov:wasGeneratedBy."@en .

so:qualityScoreValue a owl:DatatypeProperty ;
    rdfs:domain so:QualityScore ;
    rdfs:range xsd:double ;
    rdfs:label "qualityScoreValue"@en ;
    rdfs:comment "Aggregate reliability score in [0, 1] computed by the algorithm identified by `so:qualityScoreMethod`. At v92 the algorithm `durair.quality-aggregate@v92` applies a method-specific deterministic formula: W7 dimensions saturation for `coverage-matrix@v88` (saturated dimensions / 7), presence canary for `statistical-profile@v88` (1.0 if `totalActsCount > 0` ∧ `durationSeconds > 0`, else 0.0), saturation at ten buckets for `*-bucket@v89` (`min(1, leafCount / 10)`), snapshot-to-features ratio for `*-descriptor-snapshot@v89` (`min(1, leafCount / max(1, totalFeaturesCount))`). Formulas are simple and explainable on purpose — refining them requires bumping `qualityScoreMethod` to a new version."@en .

so:qualityScoreMethod a owl:DatatypeProperty ;
    rdfs:domain so:QualityScore ;
    rdfs:range xsd:string ;
    rdfs:label "qualityScoreMethod"@en ;
    rdfs:comment "Versioned identifier of the scoring algorithm that produced so:qualityScoreValue, using the same grammar as so:derivationMethod."@en .

so:qualityScoreNotes a owl:DatatypeProperty ;
    rdfs:domain so:QualityScore ;
    rdfs:range xsd:string ;
    rdfs:label "qualityScoreNotes"@en ;
    rdfs:comment "Short human-readable rationale for the score, in the export locale."@en .

so:qualityScoreLeafCount a owl:DatatypeProperty ;
    rdfs:domain so:QualityScore ;
    rdfs:range xsd:nonNegativeInteger ;
    rdfs:label "qualityScoreLeafCount"@en ;
    rdfs:comment "Cardinality of the so:DerivedFeature leaves (excluding so:DerivationTrace, so:LineageRecord, so:QualityScore and so:ProvenanceRecord nodes themselves) that point to this QualityScore via `so:hasQualityScore`. Recomputed at every export from the actually emitted graph — equal in practice to `so:lineageLeafCount` of the twin LineageRecord (canary check: a divergence between the two literals signals a graph emission bug)."@en .

#################################################################
# CoverageMatrix structure
#################################################################

so:hasCoverageDimension a owl:ObjectProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range so:CoverageDimension ;
    rdfs:label "hasCoverageDimension"@en ;
    rdfs:comment "Links a so:CoverageMatrix to one of its seven so:CoverageDimension sub-nodes (one per W7 axis: who, why, what, when, where, how, withWhat). Multi-valued (cardinality 7 in practice)."@en .

so:hasSpatialCoverage a owl:ObjectProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range so:SpatialCoverage ;
    rdfs:label "hasSpatialCoverage"@en ;
    rdfs:comment "Links a so:CoverageMatrix to its single so:SpatialCoverage sub-node (cell-grid saturation in the ARKit session world frame). Single-valued."@en .

#################################################################
# StatisticalProfile literals
#################################################################

so:profileScope a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:string ;
    rdfs:label "profileScope"@en ;
    rdfs:comment "Controlled literal: 'project' (one StatisticalProfile per ObservationProgram) or 'session' (one StatisticalProfile per InSituObservationSession). Determines the granularity of the statistical aggregation."@en .

so:totalActsCount a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:integer ;
    rdfs:label "totalActsCount"@en ;
    rdfs:comment "Total number of observation acts (in situ + ex situ) on the StatisticalProfile scope."@en .

so:totalFeaturesCount a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:integer ;
    rdfs:label "totalFeaturesCount"@en ;
    rdfs:comment "Total number of so:ObservedFeature on the StatisticalProfile scope."@en .

so:totalRegionsCount a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:integer ;
    rdfs:label "totalRegionsCount"@en .

so:totalMeasurementsCount a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:integer ;
    rdfs:label "totalMeasurementsCount"@en .

so:totalVoiceCount a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:integer ;
    rdfs:label "totalVoiceCount"@en .

so:totalFramesCount a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:integer ;
    rdfs:label "totalFramesCount"@en .

so:emittedBucketsCount a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:integer ;
    rdfs:label "emittedBucketsCount"@en ;
    rdfs:comment "Total number of so:DerivedFeature bucket nodes emitted in the export for this scope (Spatial + Geometric + Visual + Semantic)."@en .

so:emittedDescriptorsCount a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:integer ;
    rdfs:label "emittedDescriptorsCount"@en ;
    rdfs:comment "Total number of GeometricDescriptorSnapshot + VisualDescriptorSnapshot nodes emitted in the export for this scope."@en .

so:durationSeconds a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:double ;
    rdfs:label "durationSeconds"@en ;
    rdfs:comment "Total duration of the StatisticalProfile scope, in seconds. For 'session' scope, the difference between session end and start. For 'project' scope, the cumulated duration of all sessions."@en .

so:statisticalProfileJson a owl:DatatypeProperty ;
    rdfs:domain so:StatisticalProfile ;
    rdfs:range xsd:string ;
    rdfs:label "statisticalProfileJson"@en ;
    rdfs:comment "Inline JSON literal carrying the verbose distributions (per featureKind, per bucketFamily, top-N annotation classes, per W7 dimension) that don't justify a dedicated datatype property. Schema documented in mikado-export-reference.md §6 (StatisticalProfile)."@en .

#################################################################
# CoverageMatrix literals
#################################################################

so:coverageRatioWho a owl:DatatypeProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range xsd:double ;
    rdfs:label "coverageRatioWho"@en ;
    rdfs:comment "Saturation ratio for the W7 'who' axis: filled fields / required fields, in [0, 1]."@en .

so:coverageRatioWhy a owl:DatatypeProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range xsd:double ;
    rdfs:label "coverageRatioWhy"@en .

so:coverageRatioWhat a owl:DatatypeProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range xsd:double ;
    rdfs:label "coverageRatioWhat"@en .

so:coverageRatioWhen a owl:DatatypeProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range xsd:double ;
    rdfs:label "coverageRatioWhen"@en .

so:coverageRatioWhere a owl:DatatypeProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range xsd:double ;
    rdfs:label "coverageRatioWhere"@en .

so:coverageRatioHow a owl:DatatypeProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range xsd:double ;
    rdfs:label "coverageRatioHow"@en .

so:coverageRatioWithWhat a owl:DatatypeProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range xsd:double ;
    rdfs:label "coverageRatioWithWhat"@en .

so:coverageRatioOverall a owl:DatatypeProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range xsd:double ;
    rdfs:label "coverageRatioOverall"@en ;
    rdfs:comment "Overall saturation ratio across all seven W7 axes: total filled fields / total required fields, in [0, 1]."@en .

so:taxonomicGapsJson a owl:DatatypeProperty ;
    rdfs:domain so:CoverageMatrix ;
    rdfs:range xsd:string ;
    rdfs:label "taxonomicGapsJson"@en ;
    rdfs:comment "Inline JSON literal listing under-represented SKOS concepts: concepts cited only once, concepts present in the ascending closure but never directly cited, and dimension-keyed counts of curated v87 concepts. Schema documented in mikado-export-reference.md §6 (CoverageMatrix)."@en .

#################################################################
# CoverageDimension literals
#################################################################

so:documentationAxis a owl:DatatypeProperty ;
    rdfs:domain so:CoverageDimension ;
    rdfs:range xsd:string ;
    rdfs:label "documentationAxis"@en ;
    rdfs:comment "Controlled literal for the documentation axis: who, why, what, when, where, how, withWhat."@en .

so:dimensionFieldsRequired a owl:DatatypeProperty ;
    rdfs:domain so:CoverageDimension ;
    rdfs:range xsd:integer ;
    rdfs:label "dimensionFieldsRequired"@en ;
    rdfs:comment "Number of fields tracked for this W7 dimension (sum of project metadata fields aligned to this axis)."@en .

so:dimensionFieldsFilled a owl:DatatypeProperty ;
    rdfs:domain so:CoverageDimension ;
    rdfs:range xsd:integer ;
    rdfs:label "dimensionFieldsFilled"@en ;
    rdfs:comment "Number of fields actually filled (non-empty after trim) for this W7 dimension."@en .

so:dimensionRatio a owl:DatatypeProperty ;
    rdfs:domain so:CoverageDimension ;
    rdfs:range xsd:double ;
    rdfs:label "dimensionRatio"@en ;
    rdfs:comment "Saturation ratio for this W7 dimension: dimensionFieldsFilled / dimensionFieldsRequired, in [0, 1]."@en .

so:dimensionConceptsCited a owl:DatatypeProperty ;
    rdfs:domain so:CoverageDimension ;
    rdfs:range xsd:integer ;
    rdfs:label "dimensionConceptsCited"@en ;
    rdfs:comment "Number of curated v87 SKOS concepts (alias predicates declared rdfs:subPropertyOf skos:exactMatch) actually cited on this W7 dimension."@en .

so:dimensionFieldsListJson a owl:DatatypeProperty ;
    rdfs:domain so:CoverageDimension ;
    rdfs:range xsd:string ;
    rdfs:label "dimensionFieldsListJson"@en ;
    rdfs:comment "Inline JSON literal listing the field keys tracked for this dimension, with their filled/empty state. Schema documented in mikado-export-reference.md §6 (CoverageDimension)."@en .

#################################################################
# SpatialCoverage literals
#################################################################

so:spatialCellsVisitedCount a owl:DatatypeProperty ;
    rdfs:domain so:SpatialCoverage ;
    rdfs:range xsd:integer ;
    rdfs:label "spatialCellsVisitedCount"@en ;
    rdfs:comment "Number of distinct 1m cubic cells of the ARKit session world frame that contain at least one ObservedFeature centroid."@en .

so:spatialBoundingBoxVolumeM3 a owl:DatatypeProperty ;
    rdfs:domain so:SpatialCoverage ;
    rdfs:range xsd:double ;
    rdfs:label "spatialBoundingBoxVolumeM3"@en ;
    rdfs:comment "Volume in cubic meters of the axis-aligned bounding box of all ObservedFeature centroids in the ARKit session world frame."@en .

so:spatialDensityRatio a owl:DatatypeProperty ;
    rdfs:domain so:SpatialCoverage ;
    rdfs:range xsd:double ;
    rdfs:label "spatialDensityRatio"@en ;
    rdfs:comment "Density ratio: spatialCellsVisitedCount / spatialBoundingBoxVolumeM3, in cells per cubic meter. Equals 1.0 when every cell of the bounding box has been visited; lower values indicate sparser coverage."@en .

#################################################################
# Sample datatype properties
#################################################################

so:observationActKind a owl:DatatypeProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:InSituObservationAct so:ExSituObservationAct ) ] ;
    rdfs:range xsd:string ;
    rdfs:label "observationActKind"@en .

so:spatialAcquisitionContext a owl:DatatypeProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:InSituObservationAct so:ExSituObservationAct ) ] ;
    rdfs:range xsd:string ;
    rdfs:label "spatialAcquisitionContext"@en .

so:bucketScheme a owl:DatatypeProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:SpatialBucket so:GeometricBucket so:VisualBucket so:SemanticBucket ) ] ;
    rdfs:range xsd:string ;
    rdfs:label "bucketScheme"@en .

so:bucketFamily a owl:DatatypeProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:SpatialBucket so:GeometricBucket so:VisualBucket so:SemanticBucket ) ] ;
    rdfs:range xsd:string ;
    rdfs:label "bucketFamily"@en .

so:bucketSlot a owl:DatatypeProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:SpatialBucket so:GeometricBucket so:VisualBucket so:SemanticBucket ) ] ;
    rdfs:range xsd:integer ;
    rdfs:label "bucketSlot"@en .

so:descriptorSnapshotKind a owl:DatatypeProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:GeometricDescriptorSnapshot so:VisualDescriptorSnapshot ) ] ;
    rdfs:range xsd:string ;
    rdfs:label "descriptorSnapshotKind"@en .

so:digitalEntityKind a owl:DatatypeProperty ;
    rdfs:domain so:DigitalEntity ;
    rdfs:range xsd:string ;
    rdfs:label "digitalEntityKind"@en .

so:featureKind a owl:DatatypeProperty ;
    rdfs:domain so:ObservedFeature ;
    rdfs:range xsd:string ;
    rdfs:label "featureKind"@en .

so:spatialReferenceFrame a owl:DatatypeProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:ObservationProgram so:InSituObservationSession ) ] ;
    rdfs:range xsd:string ;
    rdfs:label "spatialReferenceFrame"@en .

#################################################################
# Export schema ≥ 107 — workspace and deskew lineage
#################################################################

so:acquisitionWorkspace a owl:DatatypeProperty ;
    rdfs:domain so:ObservationProgram ;
    rdfs:range xsd:string ;
    rdfs:label "acquisitionWorkspace"@en .

so:sessionPointCloudProvenance a owl:DatatypeProperty ;
    rdfs:domain so:SessionPointCloud ;
    rdfs:range xsd:string ;
    rdfs:label "sessionPointCloudProvenance"@en .

so:workspaceMeshContext a owl:DatatypeProperty ;
    rdfs:domain so:SessionPointCloud ;
    rdfs:range xsd:string ;
    rdfs:label "workspaceMeshContext"@en .

so:photogrammetryProvenance a owl:DatatypeProperty ;
    rdfs:domain so:PhotogrammetryReconstruction ;
    rdfs:range xsd:string ;
    rdfs:label "photogrammetryProvenance"@en .

so:pipelineProvenance a owl:DatatypeProperty ;
    rdfs:domain so:PhotogrammetryReconstruction ;
    rdfs:range xsd:string ;
    rdfs:label "pipelineProvenance"@en .

so:deskewedDocumentDerivative a owl:DatatypeProperty ;
    rdfs:domain so:CaptureFrame ;
    rdfs:range xsd:boolean ;
    rdfs:label "deskewedDocumentDerivative"@en .

so:deskewPostWarpQuarterTurnsClockwise a owl:DatatypeProperty ;
    rdfs:domain so:CaptureFrame ;
    rdfs:range xsd:integer ;
    rdfs:label "deskewPostWarpQuarterTurnsClockwise"@en .

so:deskewGeneralComment a owl:DatatypeProperty ;
    rdfs:domain so:CaptureFrame ;
    rdfs:range xsd:string ;
    rdfs:label "deskewGeneralComment"@en .

so:deskewDerivedFromCaptureFrameUuid a owl:DatatypeProperty ;
    rdfs:domain so:CaptureFrame ;
    rdfs:range xsd:string ;
    rdfs:label "deskewDerivedFromCaptureFrameUuid"@en .

# Remaining geom*/vis*/W7 field literals are documented in the export reference, not restated here.

#################################################################
# W7 documentation reification
#################################################################

so:W7_Documentation a owl:Class ;
    rdfs:label "W7_Documentation"@en .

so:W7_Subform a owl:Class ;
    rdfs:label "W7_Subform"@en .

so:W7_Who a owl:Class ;
    rdfs:subClassOf so:W7_Documentation ;
    rdfs:label "W7_Who"@en .

so:W7_Why a owl:Class ;
    rdfs:subClassOf so:W7_Documentation ;
    rdfs:label "W7_Why"@en .

so:W7_What a owl:Class ;
    rdfs:subClassOf so:W7_Documentation ;
    rdfs:label "W7_What"@en .

so:W7_Where a owl:Class ;
    rdfs:subClassOf so:W7_Documentation ;
    rdfs:label "W7_Where"@en .

so:W7_When a owl:Class ;
    rdfs:subClassOf so:W7_Documentation ;
    rdfs:label "W7_When"@en .

so:W7_How a owl:Class ;
    rdfs:subClassOf so:W7_Documentation ;
    rdfs:label "W7_How"@en .

so:W7_WithWhat a owl:Class ;
    rdfs:subClassOf so:W7_Documentation ;
    rdfs:label "W7_WithWhat"@en .

so:W7_Why_ResearchProject a owl:Class ;
    rdfs:subClassOf so:W7_Subform ;
    rdfs:label "W7_Why_ResearchProject"@en .

so:W7_What_MaterialObject a owl:Class ;
    rdfs:subClassOf so:W7_Subform ;
    rdfs:label "W7_What_MaterialObject"@en .

so:W7_What_Inventory a owl:Class ;
    rdfs:subClassOf so:W7_Subform ;
    rdfs:label "W7_What_Inventory"@en .

so:W7_Where_Patrimonial a owl:Class ;
    rdfs:subClassOf so:W7_Subform ;
    rdfs:label "W7_Where_Patrimonial"@en .

so:W7_Where_Enquiry a owl:Class ;
    rdfs:subClassOf so:W7_Subform ;
    rdfs:label "W7_Where_Enquiry"@en .

so:W7_How_AcquisitionProtocol a owl:Class ;
    rdfs:subClassOf so:W7_Subform ;
    rdfs:label "W7_How_AcquisitionProtocol"@en .

so:W7_How_SemanticData a owl:Class ;
    rdfs:subClassOf so:W7_Subform ;
    rdfs:label "W7_How_SemanticData"@en .

so:W7_WithWhat_Instrumentation a owl:Class ;
    rdfs:subClassOf so:W7_Subform ;
    rdfs:label "W7_WithWhat_Instrumentation"@en .

so:hasW7Who a owl:ObjectProperty ;
    rdfs:domain so:ObservationProgram ;
    rdfs:range so:W7_Who ;
    rdfs:label "hasW7Who"@en .

so:hasW7Why a owl:ObjectProperty ;
    rdfs:domain so:ObservationProgram ;
    rdfs:range so:W7_Why ;
    rdfs:label "hasW7Why"@en .

so:hasW7When a owl:ObjectProperty ;
    rdfs:domain so:ObservationProgram ;
    rdfs:range so:W7_When ;
    rdfs:label "hasW7When"@en .

so:hasW7How a owl:ObjectProperty ;
    rdfs:domain so:ObservationProgram ;
    rdfs:range so:W7_How ;
    rdfs:label "hasW7How"@en .

so:hasW7WithWhat a owl:ObjectProperty ;
    rdfs:domain so:ObservationProgram ;
    rdfs:range so:W7_WithWhat ;
    rdfs:label "hasW7WithWhat"@en .

so:hasW7What a owl:ObjectProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:ObservationProgram so:MaterialEntity ) ] ;
    rdfs:range so:W7_What ;
    rdfs:label "hasW7What"@en .

so:hasW7Where a owl:ObjectProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:ObservationProgram so:MaterialEntity ) ] ;
    rdfs:range so:W7_Where ;
    rdfs:label "hasW7Where"@en .

so:w7ActorRef a owl:ObjectProperty ;
    owl:deprecated true ;
    rdfs:domain so:W7_Who ;
    rdfs:range so:Actor ;
    rdfs:label "w7ActorRef"@en .

so:hasW7WhyResearchProject a owl:ObjectProperty ;
    rdfs:domain so:W7_Why ;
    rdfs:range so:W7_Why_ResearchProject ;
    rdfs:label "hasW7WhyResearchProject"@en .

so:hasW7WhatMaterialObject a owl:ObjectProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:W7_What so:MaterialEntity ) ] ;
    rdfs:range so:W7_What_MaterialObject ;
    rdfs:label "hasW7WhatMaterialObject"@en .

so:hasW7WhatInventory a owl:ObjectProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:W7_What so:MaterialEntity ) ] ;
    rdfs:range so:W7_What_Inventory ;
    rdfs:label "hasW7WhatInventory"@en .

so:hasW7WherePatrimonial a owl:ObjectProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:W7_Where so:MaterialEntity ) ] ;
    rdfs:range so:W7_Where_Patrimonial ;
    rdfs:label "hasW7WherePatrimonial"@en .

so:hasW7WhereEnquiry a owl:ObjectProperty ;
    rdfs:domain [ a owl:Class ; owl:unionOf ( so:W7_Where so:MaterialEntity ) ] ;
    rdfs:range so:W7_Where_Enquiry ;
    rdfs:label "hasW7WhereEnquiry"@en .

so:hasW7HowAcquisitionProtocol a owl:ObjectProperty ;
    rdfs:domain so:W7_How ;
    rdfs:range so:W7_How_AcquisitionProtocol ;
    rdfs:label "hasW7HowAcquisitionProtocol"@en .

so:hasW7HowSemanticData a owl:ObjectProperty ;
    rdfs:domain so:W7_How ;
    rdfs:range so:W7_How_SemanticData ;
    rdfs:label "hasW7HowSemanticData"@en .

so:hasW7WithWhatInstrumentation a owl:ObjectProperty ;
    rdfs:domain so:W7_WithWhat ;
    rdfs:range so:W7_WithWhat_Instrumentation ;
    rdfs:label "hasW7WithWhatInstrumentation"@en .
