In this module you will learn how FHIR supports mapping and how you can use the FHIR mapping language.
The topics covered in this module are:
FHIR has, over time, acquired different mapping-related features to deal with various use-cases:
mapping
field in every element:
Here's a rough breakdown of them:
Concept | Use this to create |
---|---|
ConceptMap | mappings between codes in different ValueSets |
mapping field in every element |
traceability from FHIR elements to other standards |
FHIR Mapping language | transformations from one data format to another |
StructureMap | FHIR Mapping language transformations in resource form |
The ConceptMap resource defines a mapping from a set of codes (concepts) defined in a ValueSet to one or more codes defined in other ValueSets. For example, say you want to create a mapping of LOINC® codes to their equivalent SNOMED® codes - you'd use a ConceptMap for this. You could then publish your ConceptMap in an Implementation Guide (IG), use it for machine translation or codes, or include it in your FHIR mapping language transformation - see 1.2 below.
You might notice this field in Forge:
This comes from ElementDefinition.mapping, which is a free-text field that you use to create traceability to other standards within your FHIR profiles. For example, when you're mapping a national standard for prescriptions to FHIR, you'd mention the equivalent element(s) from the national standard in your mapping
field. This field is thus not related to the ConceptMap resource.
Data mapping is the process of defining how data from one data model maps to another data model, and the FHIR Mapping language is a transformation language to address that need (e.g. the conversion of HL7 version 2 or CDA to FHIR). Different technologies already exist to transform data from one data model to another - such as 3GL, XSLT - but given FHIR's unique position (open standard with XML and JSON support), none of the existing technology satisfied the requirements. To use the FHIR mapping language, you need at minimum to create a transformation map which will instruct the mapping engine on how to convert the elements in an instance of data from one model to another. That transformation map can make use of embedded ConceptMaps to transform codes within the data elements from one code to another.
The FHIR mapping language is not related to the mapping
field that's present in the profiles, as that is a free-text field you can use to provide traceability in your profiles.
A FHIR Mapping language transformation map can exist in two forms - as a declarative program ("concrete syntax") or as a StructureMap resource ("abstract syntax"). The StructureMap resource is thus just a resource form representation of a FHIR Mapping language transformation map.
You can use the ConceptMap resource to define mappings between codes from different ValueSets. Use the source
element to define the source of the concepts that you want to map. The target
element provides the target you want to map the concepts to. The group
element contains a list of concepts and the target concept(s) these should be mapped to. Below is an example from the mapping of the concept 'home' between HL7 version 3 and FHIR. In HL7 version 3 the code of this concept is 'H', while in FHIR the code of this concept is 'home'. In the XML code below you can see that the source concept 'home' is mapped to the target concept 'H' (both having the same display value).
<sourceUri value="http://hl7.org/fhir/ValueSet/address-use"/>
<targetUri value="http://hl7.org/fhir/ValueSet/v3-AddressUse"/>
<group>
<source value="http://hl7.org/fhir/address-use"/>
<target value="http://hl7.org/fhir/v3/AddressUse"/>
<element>
<code value="home"/>
<display value="home"/>
<target>
<code value="H"/>
<display value="home"/>
</target>
</element>
The ElementDefinition.mapping
element allows you to define a free text mapping for this element within your profile. This mapping is however harder to use when reusing profiles.
The mapping.identity
element refers to the mapping system that is used (the mapping systems should also be defined at a higher level in the StructureDefinition.mapping
element). The mapping.map
element defines the value that is mapped to the parent element. For example, the code below shows a mapping from the field PasientID
to the element Procedure.subject
.
<element id="Procedure.subject">
...
<mapping>
<identity value="helsevest">
<map value="PasientID"/>
</mapping>
The Procedure profile contains a definition of the mapping system in the mapping
element. The identity of the mapping system in this example is helsevest.
<mapping>
<identity value="helsevest" />
<name value="HV Architecture Document" />
</mapping>
In the core specification you find mappings from HL7 v3 RIM, LOINC, CDA and HL7 v2 to core FHIR resources (go to the Mappings
tab of a resource, e.g. https://hl7.org/fhir/patient-mappings.html).
The FHIR mapping language is purely declarative - this means that instead of giving concrete instructions on how to process data, you instead describe how the processed data should look like, and the engine figures out how to transform it. The FHIR mapping language addresses two very different kinds of transformations:
FHIR Mapping language transformation maps are also uni-directional: they map from the source structure to the target structure, and no reverse map is implied. Even if the reserve mapping is simple, and happens to run losslessly, it cannot be assumed that it is correct - there might be conditions on the reverse transformation would not have been applied.
The FHIR mapping language can be applied to any content that is a directed acyclic graph with metadata (DAG-M). A directed acyclic graph (DAG) is a graph that flows in one direction and no element can be a child of itself (there are no cycles). A DAG-M is a DAG with metadata (for example each element has a name, type and cardinality). The FHIR mapping language describes how one (set of) DAG-M(s) (an instance) are transformed to another (set of) DAG-M(s). The instances can be strongly typed (specifically when they have formal definitions represented as StructureDefinitions), but this is not required.
A Map has 6 parts:
The first part of the map contains a unique canonical URL to identify the map and a human readable name of the map. The syntax is as follows:
map "[url]" = "[name]"
Here below is an example of a map named exampleMap:
map "https://hl7.org/fhir/StructureMap/exampleMap" = exampleMap
You can (optionally) define a ConceptMap and embed it in your code. Note the differences with importing existing Maps as explained in paragraph 3.4
The syntax is as follows:
conceptmap "[name]" {
prefix [x] = "[url]"
prefix [y] = "[url]"
x:[sourcevalue] = y:[targetvalue]
x:[sourcevalue] = y:[targetvalue]
}
For example, let's define a ConceptMap called myConceptMap that maps FHIR codes for address use to HL7 version 3 codes for address use. In this example, the FHIR value 'home' is begin mapped to the HL7 version 3 value 'H'.
conceptmap myConceptMap {
prefix s = "http://hl7.org/fhir/ValueSet/address-use"
prefix t = "http://hl7.org/fhir/ValueSet/v3-AddressUse"
s:home = t:H
}
The next (optional) part of the map is a list of one or more StructureDefinitions that are used in the map and the way in which they are used (either as a source, target, queried or produced). The syntax is as follows:
uses "[url]" (alias name) as [mode]
For example, if you would like to list your own Patient profile (which you called myPatient) as a source and another Patient profile (suppose this one is called otherPatient) as a target, the required code would be as follows:
uses "https://hl7.org/fhir/StructureDefinition/myPatient" as source
uses "https://hl7.org/fhir/StructureDefinition/otherPatient" as target
You may choose to add an alias as well for these StructureDefinitions, so you can use these in the code later on, but it is not mandatory to do so.
The next (optional) part of the map is a list of additional maps that are used in this map. The syntax is as follows:
imports "[url]"
Below is an example of the import of a StructureMap called mapA and a ConceptMap called mapB.
imports "https://hl7.org/fhir/StructureMap/mapA"
imports "https://hl7.org/fhir/ConceptMap/mapB"
Each map should have at least one group of transform rules. A group is a set of related rules that share the same input and output variables defining exactly which instances are passed to mapping and by which name. The syntax is as follows:
group (for type) [group-name] (extends [other-group])
input [name] : [type] as [mode]
//rules go here
endgroup
For example, we can define a group called exampleGroup with input variable A and output variable B. We will show an example of how to define the rules in the next section.
group exampleGroup
input "source" : A as source
input "target" : B as target
//rules go here
endgroup
The for type
indicates if an instance should be mapped to a specified target data type.
Transform rules describe how source content is transformed into target content. Each rule has four main sections:
The syntax for defining transform rules is as follows:
name_of_rule: for src_context.field as new_variable where condition make tgt_context.field as new_variable = create([type]) then [details]
For example, let's say you want to keep identifier the same and copy its value from source to target without transformation. The syntax would be as follows:
"rule_1_copy_identifier" : for source.identifier as a make target.identifier = a
Let's say for maritalStatus, you have added the following category in myPatient: O = Other, but the otherPatient profile does not allow for other categories than the ones defined in the marital-status ValueSet. You need to map your category to one of the categories from the marital-status ValueSet. Although there is no mapping available that has the exact same meaning, you choose to map this category to the category UNK = Unknown. The syntax would be as follows:
"rule_2_transform_gender" : for source.maritalstatus as m where m="O" make target.maritalStatus = "UNK"
Your group is now composed of one rule that copies the value of identifier and one rule that transforms the value of maritalStatus:
group exampleGroup
input "source" : A as source
input "target" : B as target
"rule_1_copy_identifier" : for source.identifier as a make target.identifier = a
"rule_2_transform_gender" : for source.maritalstatus as m where m="O" make target.maritalStatus = "UNK"
endgroup
To learn more about the FHIR Mapping Language, have a look at the HL7 FHIR mapping tutorial.
The StructureMap is a Resource presentation of the FHIR mapping language. Use the group.rule
element to define (groups of) mapping rules. Below is an example of a mapping rule where the value of the source is copied to the target destination.
<group>
<name value="Examples"/>
<typeMode value="none"/>
<input>
<name value="test"/>
<mode value="source"/>
</input>
<rule>
<name value="rule1"/>
<source>
<context value="Source"/>
<variable value="t"/>
</source>
<target>
<context value="Destination"/>
<transform value="copy"/>
</target>
</rule>
</group>
Here below is an example of a ConceptMap from the core specification. This ConceptMap shows the mapping from the HL7 FHIR ValueSet administrative-gender to the HL7 version 2 ValueSet v2-0001. The equivalence
element defines how the concepts relate to one another. For example, Equal indicates that the source and target concepts have the exact same meaning and Wider indicates that the target concept is wider in meaning than the source concept.
Mapping from administrative-gender to HL7 v2 Value Set 0001
Source Concept | Equivalence | Destination Concept |
Code [http://hl7.org/fhir/administrative-gender] | Code [http://hl7.org/fhir/v2/0001] | |
male | :Equal | M |
female | :Equal | F |
other | :Wider | A |
unknown | :Equal | U |
The core specification also contains examples of using the FHIR mapping language. For example, the FHIR mapping language was used for the conversion of DSTU2 to STU3. In the R2 Conversions tab of a resource you can find examples of the use of the FHIR mapping language. For example, in the Patient resource the R2 Conversions tab describes StructureMaps for the conversion of R2 to R3 and the other way around.
Nictiz is the centre of expertise for standardization and eHealth in The Netherlands. HL7 Netherlands core and MedMij profiles are published on Simplifier. MedMij is a national project that aims to give Dutch citizens integrated access to all their health data in one personal health environment. FHIR is used as a standard to exchange health information between the involved parties. The profiles are based on standardized clinical building blocks called Health and Care Information Models (HCIM).
Below is an example of the use of elementdefinition.mapping
in the HCIM BloodPressure (scroll down to see the actual mapping).
In this exercise you will continue with the use case from the Start Profiling module. Use the Patient profile you created in this module or create a new Patient profile if you did not complete this exercise. Start by reading the case description. Here below are a couple of links that you may find useful during this exercise:
The mapping from FHIR to the data fields in their EHR is as following:
FHIR | EHR |
Patient.name.family | PatientAdmin.Surname |
Patient.name.given | PatientAdmin.Name |
Patient.gender | PatientAdmin.Gender |
Patient.birthDate | PatientExtra.Birthdate |
Patient.deceasedBoolean | PatientExtra.Died |
In addition, gender is stored as M (male), V (female) or U (unknown). These values need to be mapped to the administrative-gender ValueSet in FHIR.
group
element and a group.name
(for example 'EHR to FHIR mapping').group.input
element.group.rule
element to define each mapping rule. No additional transformations of the data are required, so you can choose the value 'Copy' for the transform
element.source
and target
elements to define the source
and target
of your mapping. Note that in this case there is no URL for the EHR data. You can use imaginary URLs.group.element
element to define each mapping.Patient.name.family
. Adjust the rule to make this happen.We are always looking for ways to improve our products. The Profiling Academy was built using our own IG-editor in Simplifier. If you have any feedback on this module or on our Profiling Academy in general, please leave a comment in the Issue Tracker of the project.
Most modules end with an exercise. Use Forge to start profiling yourself. Just contact us at simplifier@fire.ly if you need any help.
Follow one of our predefined or tailor-made courses. We will make sure you know FHIR inside-out.
Let us assist you with your FHIR use case. Visit our company website to know more about our services or get into contact with Rien Wertheim right away.
Powered by SIMPLIFIER.NET