This personal challenge started with a tweet from
@siljelb asking for tooling for transforming openEHR archetypes to FHIR profiles. This was something I've always wanted to prove, so why not turn this into a personal summer challenge?
FHIR to openEHR
My first thought was to generate an archetype from all the different components and extensions included in a FHIR profile. The rationale being that we already have systems capable of supporting arbitrary archetypes and archetypes have little problems when you want to include an unknown/big set of data values. After a little bit of profile analysis and a little trial and error I ended with a method that received an observation profile (with all the definitions of the extension it contained) and outputted a single observation archetype. As an example, here is the algorithm applied to the genomics profile.
|
Original genomics profile |
|
Output observation archetype |
(I would found later on that this particular example is not really accurate of how complex observations should be modeled in FHIR, but algorithm should stay more or less the same).
Although it seemed like a good idea at first, this transformation has a big issue: Two slightly different profiles will give us two different archetypes that will have to rely fully on terminology bindings to know they are talking about the same, which kind of goes against the philosophy of one archetype per concept. Archetypes are supposed to represent a universal use case (aiming to a max data
set instead of a 80/20). These FHIR to openEHR transformations could work well enough in isolation or a single project but
not a CKM-type environment. FHIR embraces local profiles and extensions, which could make their
governance quite an issue.
openEHR to FHIR
One important lesson to get from this first experience is that a set of profiles will transform into a single archetype, but also a single archetype will end as a set of profiles! So while the FHIR → openEHR way only generates a single archetype and doesn't need any further user input besides choosing the set of profiles, the openEHR → FHIR transformation needs more information. Specifically, we need to tell the algorithm three things:
- Select the Element that would go into the value part of the Observation profile (if any)
- Select the list of elements that will end as components (they can go without value, they can also be an empty list)
- Select which Elements of the original archetype are suitable to be transformed into extensions.
For first two, openEHR Clusters can give an idea of pieces of an observation that make sense as a group. So from there users should be able to choose what constitutes the value and what parts constitute the components. Clusters in Clusters are an interesting use case that probably needs that users choose directly how it should be generated. If we consider that every part in the archetype is equally important, then everything could end in profiles with values constraint to [0..0] and every archetype part modeled as components, which could make this process completely automatic.
For knowing what could be an extension, archetype slots provide an excellent indication. We could also analyze all archetypes in one go and create the different parts that could be reused as extensions (Can we create some default Protocol-like profiles? Do we need to take into account default parts from RM and always include them as extensions?)
Once we decide that, the generation of the Observation, Extension, and even ValueSet profiles is quite straightforward. For data types equivalences, I built this transformation based on the
openEHR wiki page about data types equivalence. For the moment only the most usual data types have been translated (namely DV_TEXT, DV_CODED_TEXT, DV_DATE_TIME and DV_QUANTITY), but adding new ones should be easy (with maybe the exception of DV_ORDINAL alternatives).
|
Snippet of State of Dress valueset |
The profile differences between STU3 and R4 aren't too many, so I've included support for both generations. User can choose which one generate as a parameter.
The generated profiles were adjusted thanks to the Hammer tool, so they should be correct for STU3. After a bit of tweaking I got rid of the unknown error that was preventing me to import them into Forge R4, so they should also be R4 compliant.
|
Weight profile from openEHR weight observation archetype |
What's next
- More testing!
- Do you have any archetype you want to test?
- Could be interesting to process all CKM in one go? (at least for ValueSets)
- Should we put all generated ValueSets in our FHIR terminology service?
- More data types!
- Some data types are still missing. I think that it is possible that some data types, such as openEHR Ordinals alternatives will provide bigger challenge if they have additional optional elements.
- Make it more configurable, e.g. change base uris, etc.
- Put the algorithm into LinkEHR Editor and provide a minimal user interface to ease the element selection process.
- Use the process to generate the mapping that will generate automatically a transformation program to generate the different FHIR Observation instances.
- Mapping seems that could be bidirectional, as it seems that all mappings are atomic.
Lessons learned
- It is feasible to create a semiautomatic translation from openEHR to FHIR. We can make global assumptions to make this process automatic.
- FHIR to openEHR transformation is straightforward, however to take advantage of the big amount of high quality clinical models already avaliable in openEHR it seems preferable to use openEHR archetypes as a basis and generate profiles for them.
- The differences in StructureDefinition between STU3 and R4 that matter to this transformation are manageable.
Bonus for those of you getting to the end, the good ol'
Blood pressure archetype as a FHIR observation profile