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>

growth_chart_flat.json

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.