w3c / hcls-fhir-rdf

Sketching out an RDF representation for FHIR
39 stars 15 forks source link

ElementDefinition summary flags #133

Open tmprd opened 10 months ago

tmprd commented 10 months ago

Each property in the definition of a resource may be flagged with an Σ to indicate whether it's included in a summary of that resource. For exampe, name and birthDate are flagged but not maritalStatus on Patient. https://www.hl7.org/fhir/patient.html

In the R5 RDF the summary Σ flag corresponds to the object property isSummary, related to the class ElementDefinition https://www.hl7.org/fhir/elementdefinition-definitions.html#ElementDefinition.isSummary. Use cases:

This element is used to reduce the quantity of data returned in searches. Note that servers may pre-cache summarized resources for optimal performance. When a request is made with _summary=true, serializers only include elements marked as 'isSummary = true'

It would also be useful to display only the summary properties when displaying a list of patients in an application.

However, I can't find anything in the RDF that links, for example, Patient name to isSummary.

It would be nice to be able to know which properties are included in summaries of resources just from the RDF ontology alone. Is this within the scope of what the ontology should include? The easiest way to implement this might be an annotation property. Related to #32 .

ericprud commented 10 months ago

We extract a little bit of the StructureDefinitions to populate the "FHIR Ontology", but there's a lot of metadata in there. In principle, we have specs for them. Specifically, we have a StructureDefinition.shex so all that's required to make all that metadata available to RDF-heads is to script the generation of the .ttl analog of .profile.json files. Do we have motivating use cases to help us prioritize?

tmprd commented 9 months ago

Summarizing the discussion from 9/7 here just to make sure I'm understanding everything correctly. It sounds like this information could be available in RDF versions of the StructureDefinition profiles and examples, such as Patient.json, which do contain the "isSummary" flags. Here's an example of Patient.name, which would be an instance of ElementDefinition that's part of the profile.

 {
      "id" : "Patient.name",
      "path" : "Patient.name",
      "short" : "A name associated with the patient",
      "definition" : "A name associated with the individual.",
      "comment" : "A patient may have multiple names with different uses or applicable periods. For animals, the name is a \"HumanName\" in the sense that is assigned and used by humans and has the same patterns. Animal names may be communicated as given names, and optionally may include a family name.",
      "requirements" : "Need to be able to track the patient by multiple names. Examples are your official name and a partner name.",
      "min" : 0,
      "max" : "*",
      "base" : {
        "path" : "Patient.name",
        "min" : 0,
        "max" : "*"
      },
      "type" : [{
        "code" : "HumanName"
      }],
      "constraint" : [{
        "key" : "ele-1",
        "severity" : "error",
        "human" : "All FHIR elements must have a @value or children",
        "expression" : "hasValue() or (children().count() > id.count())",
        "source" : "http://hl7.org/fhir/StructureDefinition/Element"
      }],
      "mustSupport" : false,
      "isModifier" : false,
      "isSummary" : true,
      "mapping" : [{
        "identity" : "v2",
        "map" : "PID-5, PID-9"
      },
      {
        "identity" : "rim",
        "map" : "name"
      },
      {
        "identity" : "interface",
        "map" : "Participant.name"
      },
      {
        "identity" : "cda",
        "map" : ".patient.name"
      }]
    },

Generating an RDF version of the full Patient profile would mean creating an instance of the OWL class fhir:StructureDefinition. That makes sense if we're thinking of a profile as a piece of information. However, as an instance of fhir:StructureDefinition, the profile would have no formal connection to the OWL class fhir:Patient. Maybe a connection could be made if the profile contained the IRI for fhir:Patient, http://hl7.org/fhir/Patient.

Alternatively, this extra metadata could be added as an annotation property on fhir:Patient like this:

fhir:Patient  a owl:Class ;
rdfs:subClassOf [ a owl:Restriction ;
                  owl:allValuesFrom  fhir:HumanName ;
                  owl:onProperty     fhir:name ;
                  fhir:isSummary     true
                 ] ;

That might not be the appropriate place for metadata, but it would be easier to use. The only other annotation properties currently in the ontology are fhir:modifierExtensionClass and fhir:modifierExtensionProperty. This could also be added as an separate extension to the ontology, called something like fhir-metadata.ttl.

tmprd commented 9 months ago

Correction on how to serialize this as an annotation property:

[ rdf:type owl:Axiom ;
   owl:annotatedSource fhir:Patient ;
   owl:annotatedProperty rdfs:subClassOf ;
   owl:annotatedTarget [ a owl:Restriction ;
                         owl:allValuesFrom  fhir:HumanName ;
                         owl:onProperty     fhir:name .
                        ] ;
   fhir:isSummary true .
 ] .

I don't know how to refer to the same owl:Restriction this way without using a blank node identifier like _:genid7, so maybe this isn't worth overcomplicating the serialization.

tmprd commented 8 months ago

The consensus from recent meetings is to create a links between resource types (represented by classes) and the profiles (represented by instances of StructureDefinition) which define them, where the latter contain extra metadata about the resources. That would allow programmatic access to that metadata from the class. I don't think the use cases for this are high priority yet, but it would be nice to spell out how these are connected.

The link could be added to a profile using something like the object property prov:hadDerivation from PROV.

[] a fhir:StructureDefinition ;
        fhir:id [ fhir:v "Patient"] ;
        prov:hadDerivation fhir:Patient ; # <------ added
        fhir:url [ fhir:v "http://hl7.org/fhir/StructureDefinition/Patient"] ;
        fhir:version [ fhir:v "5.0.0"], [ fhir:v "5.0.0"] ;
        fhir:snapshot [
                fhir:element (
                     ...
                     [
                       fhir:id [ fhir:v "Patient.name" ] ;
                       fhir:isSummary [ fhir:v "true" ] ;
                       ...

Or it could be added to the class using the inverse property prov:wasDerivedFrom, or the annotation property rdfs:isDefinedBy. It looks like the IRI for the above profile is "http://hl7.org/fhir/StructureDefinition/Patient", so the link could look something like this:

fhir:Patient  a               owl:Class ;
        prov:wasDerivedFrom  [ fhir:v "http://hl7.org/fhir/StructureDefinition/Patient" ] ;  # <------ added
        rdfs:comment          "Demographics and other administrative information about an individual or animal receiving care or other health-related services." ;
        rdfs:label            "Patient" ;
        rdfs:subClassOf       fhir:DomainResource , w5:administrative.individual ;
        ...

Also:

dbooth-boston commented 4 months ago

@tmprd Are you able to carry this work forward, to get it implemented and tested?

tmprd commented 3 months ago

I won't be able to work on this anytime soon, but I think it's a low priority. I think this is a good example of something which could clarify the scope of what's included in the ontology vs other metadata. This can be closed for now if it helps organize other issues.