Inline terminology
Note
A whole tutorial referenced here is available in the following Postman collection: https://documenter.getpostman.com/view/1515623/2sBXcLex64
Note
If running against a public sandbox.open-fhir.com, don’t forget to include Authorization header of type Basic.
An important aspect to successful mappings between FHIR and openEHR is a service able to translate codings, enums, terminologies from one to the other.
In this specific example, within the openEHR template, growth_chart/body_weight/any_event:0/state_of_dress is coded
in the archetype’s local terminology with values such as at0013 (Naked), at0011 (Lightly clothed/underwear)
or at0010 (Fully clothed, including shoes) — something unknown to FHIR. The HL7 Vital Signs with Qualifying
Elements IG models the state of dress on a body weight Observation
as the AssociatedSituation extension (http://hl7.org/fhir/us/vitals/StructureDefinition/AssociatedSituationExt)
whose valueCodeableConcept comes from the Body Weight Associated Situation value set — SNOMED CT 248160001
(Undressed) and Solor temporary codes for street clothes with/without shoes. This is why you need a terminology
mapping from one coding to the other.
A simple terminology mapping is to provide the mapping inline, within a specific model.yaml.
Adding mapping of this data point (no terminology yet)
Mapping of the state_of_dress data point wasn’t included in the original mappings. Let’s add it, following a
similar approach as in the previous step when we added Observation.note.text — but first without any terminology
mapping, to see why one is needed.
Get an ID and trigger a PUT of the body weight mapper. You need to add the following mapping within mappings:
- name: "state of dress"
with:
fhir: "$resource.extension"
openehr: "$archetype/data[at0002]/events[at0003]/state[at0008]"
fhirCondition:
targetRoot: "$resource.extension"
targetAttribute: "url"
operator: "one of"
criteria: "http://hl7.org/fhir/us/vitals/StructureDefinition/AssociatedSituationExt"
followedBy:
mappings:
- name: "value"
with:
fhir: "value"
openehr: "items[at0009]"
- name: "url"
with:
fhir: "$fhirRoot"
openehr: "$archetype"
manual:
- name: "url"
fhir:
- path: "url"
value: "http://hl7.org/fhir/us/vitals/StructureDefinition/AssociatedSituationExt"
This will add value from growth_chart/body_weight/any_event/state_of_dress
(data[at0002]/events[at0003]/state[at0008]/items[at0009]) to the IG’s AssociatedSituation extension on the body
weight Observation, and vice-versa.
If you now run $tofhir with the same flat composition as before, you’ll see the openEHR local code leak into FHIR
untranslated — structurally valid, but not a code from the IG’s value set (a profile validator flags exactly this):
"extension": [
{
"url": "http://hl7.org/fhir/us/vitals/StructureDefinition/AssociatedSituationExt",
"valueCodeableConcept": {
"coding": [
{
"system": "local",
"code": "at0013",
"display": "Naked"
}
],
"text": "Naked"
}
}
]
Adding the inline terminology
To fix that, extend the state of dress mapping with an inline terminology that translates between the archetype’s
local code and SNOMED CT 248160001 (Undressed) from the IG’s Body Weight Associated Situation value set:
- name: "state of dress"
with:
fhir: "$resource.extension"
openehr: "$archetype/data[at0002]/events[at0003]/state[at0008]"
fhirCondition:
targetRoot: "$resource.extension"
targetAttribute: "url"
operator: "one of"
criteria: "http://hl7.org/fhir/us/vitals/StructureDefinition/AssociatedSituationExt"
terminology:
type: "inline"
mappings:
- openehr:
code: "at0013"
system: "local"
display: "Naked"
fhir:
system: "http://snomed.info/sct"
code: "248160001"
display: "Undressed"
followedBy:
mappings:
- name: "value"
with:
fhir: "value"
openehr: "items[at0009]"
- name: "url"
with:
fhir: "$fhirRoot"
openehr: "$archetype"
manual:
- name: "url"
fhir:
- path: "url"
value: "http://hl7.org/fhir/us/vitals/StructureDefinition/AssociatedSituationExt"
With the inline terminology, anything in openEHR coded as at0013 in system local will be mapped to SNOMED CT
248160001 (Undressed) when creating a FHIR Resource.
In the other direction, an AssociatedSituation extension coded as http://snomed.info/sct|248160001 will result in
an openEHR code of at0013.
Validating behavior of the inline terminology
Use the same example of openEHR as in previous steps:
- POST http://localhost:8080/$tofhir?templateId=Growth chart&patient=Patient/lina-weber
POST http://localhost:8080/$tofhir?templateId=Growth%20chart&patient=Patient/lina-weber HTTP/1.1 Content-Type: application/fhir+json Body: <Parameters resource wrapping the flat json below>
Within the result, you should see the extension value translated to the SNOMED CT code:
"extension": [
{
"url": "http://hl7.org/fhir/us/vitals/StructureDefinition/AssociatedSituationExt",
"valueCodeableConcept": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "248160001",
"display": "Undressed"
}
],
"text": "Naked"
}
}
]
Going in the other direction ($toopenehr), a Bundle whose AssociatedSituation extensions are coded with SNOMED CT
248160001 results in a properly openEHR-coded at0013 in the resulting Composition:
"growth_chart/body_weight/any_event:0/state_of_dress|code": "at0013",
"growth_chart/body_weight/any_event:0/state_of_dress|terminology": "local",