Terminology
Note
Access to a terminology service within openFHIR Engine is not included in the standard license. To check if you have access to it, you can check if you license.json includes “terminology” within “options”. Alternatively, you can do an HTTP GET /terminology/fhir/ConceptMap/123
to verify it.
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 many cases, something coded in openEHR is entirely different than what’s coded in FHIR. Similarly and perhaps even more problematic is when something coded in openEHR is of value not allowed in FHIR (i.e. Observation.status, where in FHIR is has fixed pre-defined values).
For this purpose, openFHIR Engine has a built-in terminology service according to https://build.fhir.org/terminology-service.html Implementation Guide. It works with FHIR ConceptMaps to translate from one coding to another.
Simplified inline translations
For simple inline translations (i.e. of enums), alternative to ConceptMap is providing a translation inline within model mappers.
Note
This is outside the scope of standard FHIR Connect specification (.model json schema). Additional properties (terminology section) is an extension to the standard json schema.
Example of an inline terminology mapping:
- name: "status"
with:
fhir: "$fhirResource.status"
openehr: "$openEhrArchetype.advance_care_directive.status"
type: "TEXT"
terminology:
type: "inline"
mappings:
- openehr: # openEhrFinal value from an openEHR Composition will be translated to "final" when doing a mapping to FHIR
code: "openEhrFinal"
fhir:
code: "final" # final value from an FHIR Resource will be translated to "openEhrFinal" when doing a mapping to an openEHR Composition
- openehr:
code: "openEhrPreliminary"
fhir:
code: "preliminary"
- openehr:
code: "openEhrActive"
fhir:
code: "active"
Terminology service
For more complex translations of Codings, CodeableConcepts, .. embedded (or remote, see: Integrations) terminology service can be used.
Note
This is outside the scope of standard FHIR Connect specification (.model json schema). Additional properties (terminology section) is an extension to the standard json schema.
Example of an terminology mapping:
- name: "type of directive"
with:
fhir: "$fhirResource.category.coding"
openehr: "$openEhrArchetype.advance_care_directive.type_of_directive"
type: "CODING"
condition:
targetRoot: "$fhirResource.category.coding"
targetAttribute: "system"
operator: "one of"
criteria: "[urn:oid:2.16.840.1.113883.2.4.3.11.60.40.4.14.1]"
terminology: # can be here within a specific mapping or even above in the header of the model.yml, in which case all CODEABLECONCEPT and CODING will try to be translated
type: "local" # local means that the embedded openFHIR terminology service will be used; alternatively, 'remote' is possible, see Integrations
conceptmap: "http://url-of-the-conceptmap" # ConceptMap.url
RESTful API
Note
Main purpose of the RESTful API of the embedded terminology service is to validate it’s state and how it does the translations. When you want to use this terminology as part of the mappings, you don’t need to use this RESTful API (apart from state configuration). All you need to do is reference ConceptMap from mappings (following the ‘terminology’ section syntax described above).
- POST /terminology/fhir/ConceptMap
Create a new ConceptMap that will be available for mappings. Alternative to POSTing it like this is to create it as part of the Bootstrapping, see State configuration
Example request:
POST /terminology/fhir/ConceptMap HTTP/1.1 Content-Type: application/json Body: <FHIR ConceptMap json>
- PUT /terminology/fhir/ConceptMap/(id)
Update an existing ConceptMap.
Example request:
PUT /terminology/fhir/ConceptMap/123 HTTP/1.1 Content-Type: application/json Body: <FHIR ConceptMap json>
- GET /terminology/fhir/ConceptMap/(id)
Read an existing ConceptMap.
Example request:
GET /terminology/fhir/ConceptMap/123 HTTP/1.1 Accept: application/json
- GET /terminology/fhir/ConceptMap?url=
Search an existing ConceptMap by ConceptMap.url.
Example request:
GET /terminology/fhir/ConceptMap?url=http123 HTTP/1.1 Accept: application/json
- POST /terminology/fhir/ConceptMap/(id)/$translate
Translate coding using a specific ConceptMap
Example request:
POST /terminology/fhir/ConceptMap/123/$translate HTTP/1.1 Content-Type: application/json Body: { "resourceType": "Parameters", "parameter": [ { "name": "sourceCode", #can also be sourceCoding or sourceCodeableConcept with the corresponding value type underneath "valueCode": "female" }, { "name": "system", "valueUri": "http://123.com" }, { "name": "targetSystem", "valueUri": "http://456.com" } ] }
- POST /terminology/fhir/ConceptMap/$translate
Translate coding using ConceptMap
Example request:
POST /terminology/fhir/ConceptMap/123/$translate HTTP/1.1 Content-Type: application/json Body: { "resourceType": "Parameters", "parameter": [ { "name": "sourceCode", #can also be sourceCoding or sourceCodeableConcept with the corresponding value type underneath "valueCode": "female" }, { "name": "url", "valueUri": "http://123.com" # ConceptMap.url that should be used }, { "name": "system", "valueUri": "http://123.com" }, { "name": "targetSystem", "valueUri": "http://456.com" } ] }
ConceptMap
Example ConceptMap
Note: when element.code is * and element.target.code is *, it means it will only translate systems.
{
"resourceType": "ConceptMap",
"url": "http://hl7.org/fhir/ConceptMap/101",
"group": [
{
"source": "OID: 2.16.840.1.113883.2.4.3.11.60.40.2.7.15.1",
"target": "urn:oid:2.16.840.1.113883.2.4.3.11.60.40.4.14.1",
"element": [
{
"code": "*",
"target": [
{
"code": "*"
}
]
}
]
},
{
"source": "urn:oid:2.16.840.1.113883.2.4.3.11.60.40.4.14.1",
"target": "OID: 2.16.840.1.113883.2.4.3.11.60.40.2.7.15.1",
"element": [
{
"code": "*",
"target": [
{
"code": "*",
"equivalence": "equivalent"
}
]
}
]
},
{
"source": "http://snomed.info/sct",
"target": "http://decor.nictiz.nl/fhir/ValueSet/2.16.840.1.113883.2.4.3.11.60.40.2.2.1.1--20171231000000",
"element": [
{
"code": "*",
"target": [
{
"code": "*",
"equivalence": "equivalent"
}
]
}
]
},
{
"source": "http://decor.nictiz.nl/fhir/ValueSet/2.16.840.1.113883.2.4.3.11.60.40.2.2.1.1--20171231000000",
"target": "http://snomed.info/sct",
"element": [
{
"code": "*",
"target": [
{
"code": "*",
"equivalence": "equivalent"
}
]
}
]
},
{
"source": "http://clinical.vitaly.parsek.com/codeable-concept/questionnaire-question-answer-code-simple",
"target": "",
"element": [
{
"code": "0",
"target": [
{
"code": "at0005",
"equivalence": "equivalent"
}
]
},
{
"code": "10",
"target": [
{
"code": "at0006",
"equivalence": "equivalent"
}
]
},
{
"code": "20",
"target": [
{
"code": "at0007",
"equivalence": "equivalent"
}
]
},
{
"code": "30",
"target": [
{
"code": "at0008",
"equivalence": "equivalent"
}
]
},
{
"code": "40",
"target": [
{
"code": "at0009",
"equivalence": "equivalent"
}
]
},
{
"code": "50",
"target": [
{
"code": "at0010",
"equivalence": "equivalent"
}
]
},
{
"code": "60",
"target": [
{
"code": "at0011",
"equivalence": "equivalent"
}
]
},
{
"code": "70",
"target": [
{
"code": "at0012",
"equivalence": "equivalent"
}
]
},
{
"code": "80",
"target": [
{
"code": "at0013",
"equivalence": "equivalent"
}
]
},
{
"code": "90",
"target": [
{
"code": "at0014",
"equivalence": "equivalent"
}
]
},
{
"code": "100",
"target": [
{
"code": "at0015",
"equivalence": "equivalent"
}
]
}
]
}
]
}