ConceptMap terminology
Note
A whole tutorial referenced here is available in the following Postman collection: https://documenter.getpostman.com/view/1515623/2sAXqqbhKp
A more complex terminology mapping than described in Inline terminology can be provided with ConceptMaps.
openFHIR Engine has a full terminology service built-in. That terminlogy service provides a $translate operation as per the FHIR IG of the terminology service (https://build.fhir.org/terminology-service.html).
Add ConceptMap
- POST http://localhost:8080/terminology/fhir/ConceptMap
POST http://localhost:8080/terminology/fhir/ConceptMap HTTP/1.1 Content-Type: application/json Body: { "resourceType": "ConceptMap", "id": "e1a90f56-4773-44a6-8004-0ef178ce85a8", "url": "http://open-fhir.com/DemoConceptmap", "description": "A test mapping", "group": [ { "source": "local", "target": "http://loinc.org", "element": [ { "code": "at0013", "display": "Naked", "target": [ { "code": "9999-9", "equivalence": "equivalent" } ] } ], "unmapped": { "mode": "fixed", "code": "hardcodedcode-inloinc" } }, { "source": "http://loinc.org", "target": "local", "element": [ { "code": "9999-9", "target": [ { "code": "at0013", "display": "Naked", "equivalence": "equivalent" } ] } ], "unmapped": { "mode": "fixed", "code": "at0013" } } ] }
Reference ConceptMap in the model mapping
ConceptMap created above needs to be referenced from a specific model mapper so the engine picks it up when doing a translation from openEHR<>FHIR.
To do this, we need to add terminology tag within a mapping as such:
terminology:
type: "local" # local when using the embedded terminology service, could also be 'inline' and 'remote'
conceptmap: "http://open-fhir.com/DemoConceptmap" # concept map canonical URL as provided when creating it
Full payload when updating a model mapper should look like:
- PUT http://localhost:8080/fc/model/(id of the model mapper)
PUT http://localhost:8080/fc/model/(id) HTTP/1.1 Body: <yaml below>
format: "0.2.0"
version: "0.0.2"
fhirConfig:
# For this Resource: https://www.hl7.org/fhir/observation-example.json.html
resource: "Observation"
condition:
- targetRoot: "$fhirResource"
targetAttribute: "category.coding.code"
operator: "one of"
criteria: "[weight]"
openEhrConfig:
# For this Archetype: https://ckm.openehr.org/ckm/archetypes/1013.1.2960
archetype: "openEHR-EHR-OBSERVATION.body_weight.v2"
mappings:
- name: "weight"
with:
fhir: "$fhirResource.value"
openehr: "$openEhrArchetype.body_weight.any_event.weight"
type: "QUANTITY"
condition:
targetRoot: "$fhirResource"
targetAttribute: "code.coding.code"
operator: "one of"
criteria: "[$loinc.29463-7, $snomed.27113001]"
- name: "time"
with:
fhir: "$fhirResource.effective"
openehr: "$openEhrArchetype.body_weight.any_event.time"
type: "DATETIME"
- name: "comment"
with:
fhir: "$fhirResource.note.text"
openehr: "$openEhrArchetype.body_weight.any_event.comment"
type: "STRING"
- name: "state of dress"
with:
fhir: "$fhirResource.component.value"
openehr: "$openEhrArchetype.body_weight.any_event.state_of_dress"
type: "CODEABLECONCEPT"
condition:
targetRoot: "$fhirResource.component"
targetAttribute: "code.coding.code"
operator: "one of"
criteria: "[$loinc.9999-9]"
terminology:
type: "local"
conceptmap: "http://open-fhir.com/DemoConceptmap"
Testing the embedded terminology service
Use the same example of openEHR as in previous steps:
- POST http://localhost:8080/openfhir/tofhir?templateId=Growth chart
POST http://localhost:8080/openfhir/tofhir?templateId=Growth%2Cchart HTTP/1.1 Content-Type: application/json Body: <json below>
Within the result, you should see a new FHIR element mapped from openEHR:
"component": [
{
"code": {
"coding": [
{
"code": "9999-9"
}
]
},
"valueCodeableConcept": {
"coding": [
{
"system": "http://loinc.org",
"code": "9999-9"
}
]
}
}
]
Going in the other direction, you should see 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"
You can also test what happens when providing a code that’s not within the ConceptMap. A fallback would be used with the “unmapped” entry of the ConceptMap, as per the ConceptMap’s purpose.