Stream: terminology
Topic: Concept maps referencing HL7 value sets
Liam Barnes (Apr 22 2020 at 08:59):
Hi. We have concept maps between local value sets and HL7(FHIR) value sets. I’ve found out that the HL7 value set compositions can change between fhir versions to include concepts from different code systems while still maintaining the same URI.
Our concept maps refers to the value sets using the elements sourceUri and targetUri. Would it be advisable/correct to move to using sourceCanonical and targetCanonical and include the version when referencing HL7 value sets since backwards incompatible changes can occur with them?
E.g. http://hl7.org/fhir/valueset-immunization-status.json.html vs http://hl7.org/fhir/stu3/valueset-immunization-status.json.html
And our concept map: https://healthterminologies.gov.au/fhir/ConceptMap/immunization-act-status-v3-to-immunization-status-codes-fhir-1
Thanks
Robert McClure (Apr 22 2020 at 14:41):
@Liam Barnes I am not an expert on ConceptMap (@Rob Hausam - help here) but I believe there are a couple of issues with your example but let me go through some issues in general also.
- ValueSet expansions can change over time because you can change the CLD - content logical definition (the compose) to refine the set of concepts to be included _as long as the result stays consistent with the original scope, usually as reflected in the description element. When you make such a change the value set business version SHALL be changed. Expansions can also change simply based on the fact that the compose can define an "expression" that will bring different concepts into the expansion because the code system used changes between expansion events (IE, with _no_ change in the value set CLD so no change in the version of the value set).
- Because a conceptMap describes concept-level maps and the expansion can change what is in both the source and the target, I would agree that you should capture the version of the source and target value set.
- But remember that even with that, the expansion can change based on what code system version was used to generate the expansion. So your conceptMap might have issues if it is used with a different code system version in addition to a different value set version.
- I do think you should be using the canonical reference.
- I see you used ConceptMap.group element which is restricted to source and target _in the same code system_ yet your example does not do that. I'm not an expert on this resource so perhaps Rob H can help us here and I know this resource has been under review.
Liam Barnes (Apr 23 2020 at 02:51):
Thanks for the reply @Robert McClure . Some great info there. I have understood that an expansion can change due to variances in versions of the code system/s in the CLD (unless versions are stated in the CLD). What I've misunderstood is that the CLD can have backwards incompatible changes and that is reflected by a change in the business version but not URI. I had always considered concept enumerations in a CLD to be brittle because of this.
My interpretation of ConceptMap.group is you can have a number of groups but each group should have source concepts from the same source code system and also target concepts from the same target code system, but the source and target systems would be different. Is that what you mean?
Michael Lawley (Apr 23 2020 at 04:05):
I think a take-away here is that where ValueSets have the same governance and life-cycle as the CodeSystems that they reference, they should explicitly target the relevant CodeSystem version (and the same would apply to ConceptMaps that share the same governance and life-cycle as the ValueSets they reference).
Liam Barnes (Apr 23 2020 at 06:13):
@Michael Lawley I'm not sure I follow. By that logic are you saying that HL7 value sets should include code system versions in the compose/CLD if those code systems are also HL7 and have the same governance?
This has now made me wonder, why the datatype choice (uri and canonical) even exists? If you don't have a version, you can just put the uri in a canonical datatype.
Michael Lawley (Apr 23 2020 at 06:18):
For the HL7 ValueSets that are part of the spec, yes.
Liam Barnes (Apr 23 2020 at 06:42):
I think for our value sets and concept maps, we will now explicitly state versions for any reference to HL7 code systems or value sets.
For references to our own value sets and code systems, I don't think versions will be necessary. Our value set definitions will not have backwards incompatible changes without a URI change. Similarly for our code systems as we maintain concept permanence in those.
Robert McClure (Apr 23 2020 at 16:38):
@Liam Barnes @Michael Lawley
First let me clarify that I was incorrect on how ConceptMap.group is used - source and target can be from two different code systems That will actually be happening almost all the time, the wording on the resource is confusing at best.
Like most things FHIR, there is lots of wiggle room in the base spec. To be a well formed value set, there is no need to specify the code system version to be used in the CLD. It is certainly important to understand how value sets work and that the CLD can change (even a change in code system used,) and when it does it SHALL result in a new business version but SHALL stay consistent with the specified intended scope, usually noted in the ValueSet.description. As you've noted, the expansion will be guaranteed to not change for that business version only if the code system version is specified in the compose OR the value set (as most do not) has the ValueSet.Compose.lockedDate is populated. Both of those approaches result in a version of the valueset that is "Locked" resulting in one and only one expansion. Remember that a new version of the valueset can change this. For all of these reasons I think it's best to try to manage conceptmap version integrity in the conceptmap resource instance, and to not push that back into the value set unless you own it. That means using canonical(valueset) with the version appended as your identifier for source and target BUT we have a gap it seems with this in that you can not also specify the code system version you want to say your source and target are to use to generate the needed expansion. Without this you are correct that the only way to be sure, is to force the value business version to be a form of "Locked" so you can be sure the map does not have to deal with different expansion members. @Rob Hausam I think this is a gap and we need to come up with a way to allow Conceptmap to state both valueset version and the code system version to be used.
Grahame Grieve (Apr 23 2020 at 21:05):
well, it can: ConceptMap.source/target vs ConceptMap.group.source/target
Michael Lawley (Apr 23 2020 at 23:48):
I take issue with the idea that ValueSet.Compose.lockedDate fixes or otherwise results in a deterministic expansion. The problem is that the scope of interpretation of lockedDate is not fixed -- it could be "the versions of the CodeSystems available in a specific terminology server on the specified date" or "the latest version of the CodeSystem available anywhere on the specified date" (only released versions or also draft versions?). Also, there may be several versions associated with a given date -- either in the SNOMED case, or because of rapid updates.
Michael Lawley (Apr 23 2020 at 23:52):
Note that you can always wrap a ValueSet to fix the CodeSystem(s) version(s) and then reference the wrapping ValueSet.
Lloyd McKenzie (Apr 24 2020 at 00:10):
The intention of lockedDate is that it fixes things. The reality is that changes in technical availability of information, changes in software, etc. could negatively impact the reproducability
Rob Hausam (Apr 24 2020 at 02:42):
As Grahame pointed out, I don't believe that there is any actual gap in being able to specify and fix the versions of both the code system and value set, as that is necessary. There may well be an issue with what we can and can't do with lockedDate (when compared with the intention for that element, as Lloyd mentions - "fixes things" doesn't seem exactly specific enough). So some further discussion (and clarification, if nothing else) in Vocab seems needed.
Liam Barnes (Apr 24 2020 at 03:42):
Is there a way to fix to just the major version of a value set or code system (if semantic versioning is used in those)? Now that we've found versionless references can introduce unintended/breaking changes, by stating specific versions we will create a maintenance overhead updating our resources in line with updates to the fhir spec terminology.
Michael Lawley (Apr 24 2020 at 04:06):
@Liam Barnes I think one of the keys there goes back to the naming scheme for the URIs -- the "major" version should be part of the URI because changing the major version is a signal of breakage -- you need clients to explicitly opt in to the change.
The patch version indicates minor unimportant changes / bug fixes etc. You want these to be picked up automatically and thus they shouldn't really trigger the rules for a Business Version change (they're conceptually at the level of a technical version change), thus patch version does not belong in the version string.
This leaves us with minor version, and that is the thing that you might want to fix to.
Summary:
- Major version goes into the URI
- Major.minor goes into the version
- Patch is omitted (or in a server with full history, can be considered as .../_history/[patch])
Robert McClure (Apr 24 2020 at 15:04):
@Michael Lawley @Liam Barnes Even if semantic versioning of terminology (value sets or code systems, how about concept maps?) artifacts was understood, and I'm not aware that it is, I am not aware of any major sources for these artifacts that use semantic versioning. So for me, discussing how to use it in a url seems premature. Perhaps you can show me how that opinion is mistaken?
Robert McClure (Apr 24 2020 at 15:10):
@Grahame Grieve @Rob Hausam Can you explain exactly how the source element/target content would be structured to state the code system version to be used for a specific value set version to get a specific expansion. It would help to have that example here in zulip so we can have it documented here. I assume you are saying you can do it in both the spots noted?
Grahame Grieve (Apr 24 2020 at 21:42):
yes
Grahame Grieve (Apr 24 2020 at 21:45):
actually, sort of:
<?xml version="1.0" encoding="UTF-8"?> <ConceptMap xmlns="http://hl7.org/fhir"> <id value="103"/> <sourceCanonical value="http://acme.org/ValueSet/condition-codes|234"/> <targetCanonical value="http://acme.org/ValueSet/diagnoses-billing|2020-04-10"/> <group> <source value="http://snomed.info/sct"/> <sourceVersion value="March 2015 US Edition"/> <target value="http://hl7.org/fhir/sid/icd-10-us"/> <targetVersion value="2015"/> </group> </ConceptMap>
Michael Lawley (Apr 25 2020 at 04:00):
@Robert McClure That's what I was trying to do, at least from a technical perspective.
I'm starting from the perspective that the goal is to capture the common compatibility/substitutability semantics of the semver pattern, then showing how the conceptual major.minor.patch parts could map into existing parts and semantics of FHIR to achieve the same essential compatibility/substitutability semantics.
What I didn't address in detail was the content-end of the picture -- under what circumstances should a given change to a CodeSystem, ValueSet, or ConceptMap be considered a change to major, minor, or patch. There is obviously some low-hanging fruit in the patch space, and also in the major space.
But, some of it will depend on the use-cases a ValueSet, for example, is intended. e.g., a ValueSet that is designed to specify what's valid to enter into a diagnosis field vs one designed for cohort identification vs one defined for validation.
Robert McClure (Apr 26 2020 at 18:45):
@Grahame Grieve
It would be nice to have some example maps in your ConceptMap example. As it stands, it's a bit incomplete. But I take this to mean something that is not clear in the spec: that when a group specifies a code system version, that version is intended to generate an expansion. When I looked at the spec, it seems to indicate the code system version used for the code in the map. To the OP issue - this does not say "this map is for this expansion" and importantly one could assume that it simply says these are valid mapping for a specific versioned code in a versioned value set independent of the expansion it is found in.
I think we could improve ConceptMap to make more clear a ConceptMap may be tied to a specific expansion (value set version + code system version). I think this very immature resource could be improved to make such a thing clear. That said, @Liam Barnes , do you think what Graham has described is sufficient?
Robert McClure (Apr 26 2020 at 18:49):
@Michael Lawley I agree that semver for terminology artifacts would be useful. I don't agree that what you call "the content-end of the picture" is universally agreed upon low hanging fruit. I'd be very happy for you to make such a proposal and bring that forth as an HL7 project to make determinations of what is major, minor, patch consistent so we can promote this far and wide. Start with UTG which is trying to do this. Then perhaps get SNOMED CT to agree. Then perhaps we have a platform to begin, otherwise I don't see this going very far and to suggest otherwise and make other decisions based upon that assumption is dangerous.
Grahame Grieve (Apr 26 2020 at 20:17):
if you really wanted to say that your mapping is only for a particular expansion, then produce a new value set with the expansion and it's own id or version, and then reference that directly. I agree that that example I should is
code system version used for the code in the map.
Not the version of the expansion. I think that's how it should be, btw
Michael Lawley (Apr 26 2020 at 22:37):
I said there is _some_ low hanging fruit in the "content" space. I was not saying the content space _is_ low hanging fruit. Also I was not talking about just the CLD, but no matter.
Consider a CodeSystem that has no inactive codes, then changing the value of ValueSet.compose.inactive to true could be considered a patch change. Wholesale changes to the compose such as switching from one CodeSystem to another would be a major change.
Other things, like adding the explicit inclusion (exclusion) of a code that currently already matches (doesn't match) existing filter conditions is less clear.
I don't have anything specific to propose here - there's too much context to account for, not least of which is the intended use of a ValueSet or ConceptMap. What might help is documenting particular examples to help others make consistent judgement calls.
Liam Barnes (Apr 27 2020 at 02:13):
I can try to explain the issue that we are experiencing better and see if that helps. Apologies for the length of post.
We have concept maps and value sets that reference terminology from the FHIR spec. To date we have included those as versionless references. It is apparent that for one/some of our use cases that is not stable enough and ultimately ambiguous. One of our existing concept maps demonstrating this is as follows:
{ "resourceType": "ConceptMap", "id": "immunization-act-status-v3-to-immunization-status-codes-fhir-1", "url": "https://healthterminologies.gov.au/fhir/ConceptMap/immunization-act-status-v3-to-immunization-status-codes-fhir-1", "version": "1.0.1", "sourceUri": "https://healthterminologies.gov.au/fhir/ValueSet/immunization-act-status-hl7-v3-1", "targetUri": "http://hl7.org/fhir/ValueSet/immunization-status", "group": [ { "source": "http://hl7.org/fhir/v3/ActStatus", "target": "http://hl7.org/fhir/medication-admin-status", "element": [ { "code": "completed", "target": [ { "code": "completed", "equivalence": "equivalent" } ] }, { "code": "nullified", "target": [ { "code": "entered-in-error", "equivalence": "equivalent" } ] }, { "code": "aborted", "target": [ { "equivalence": "unmatched" } ] } ] } ] }
The change to http://hl7.org/fhir/ValueSet/immunization-status to include values from a different system means the map is not suitable for anyone using R4. So our option is to now produce this:
{ "resourceType": "ConceptMap", "id": "immunization-act-status-v3-to-immunization-status-codes-fhir-2", "url": "https://healthterminologies.gov.au/fhir/ConceptMap/immunization-act-status-v3-to-immunization-status-codes-fhir-2", "version": "2.0.0", "sourceCanonical": "https://healthterminologies.gov.au/fhir/ValueSet/immunization-act-status-hl7-v3-2", "targetCanonical": "http://hl7.org/fhir/ValueSet/immunization-status|4.0.1", "group": [ { "source": "http://terminology.hl7.org/CodeSystem/v3-ActStatus", "sourceVersion": "2018-08-12", "target": "http://hl7.org/fhir/event-status", "targetVersion": "4.0.1", "element": [ { "code": "completed", "target": [ { "code": "completed", "equivalence": "equivalent" } ] }, { "code": "nullified", "target": [ { "code": "entered-in-error", "equivalence": "equivalent" } ] }, { "code": "aborted", "target": [ { "equivalence": "unmatched" } ] } ] } ] }
My concern is that, if the target value set and system increment by patch or minor version, we will need maps for each of those. I would like to be able state relationships between concepts in systems (and value sets) and have those relationships valid for a range of versions of systems/value sets unless something significant happens to them.
Hope that was clear.
Rob Hausam (Apr 27 2020 at 03:14):
This seems quite clear, @Liam Barnes. It seems to me that what you would like to be able to do is to specify a range of target versions (e.g. min and/or max) for which the map applies. Using targetCanonical and group.targetVersion doesn't provide a way to do that. So if you stay with that approach then it seems that you will have to create a separate map for each current and future published version of the FHIR spec. That's probably not a huge number of versions over time, but it does require maintenance which would be preferable to avoid. So my other thought is this. You could continue using sourceUri and targetUri (without versions) as in the first map. And then you could have two groups with different group.target values for the two different code systems, one which is used for the FHIR spec versions <= 3.0.2 and another for > 3.0.2 (and not using group.targetVersion). Then you would distinguish between those maps for a particular source code using dependsOn. I haven't thought of a specific way to represent the spec version ranges using the dependsOn property/value element pairs. There is quite a bit of flexibility with that, but it may not be sufficient for it to be fully computable (if that's what you need). So maybe you would end up needing to also add an extension, but that doesn't seem necessarily too bad in order for it to work using a single map.
Liam Barnes (Apr 27 2020 at 04:05):
That sounds interesting @Rob Hausam. If we were to leave the new EventStatus target versionless, there's still the possibility a mapping will be made invalid due to a backwards incompatible change in the system. I must admit I'll have to do some research for dependsOn to see how that might work and maybe that addresses this.
If we create separate maps for each fhir version, the maintenance extends to ensuring implementation guide versions and maps don't drift apart. All possible, just a pain.
Thanks
Rob Hausam (Apr 27 2020 at 04:17):
Yes, I agree there could still be a future backwards incompatible change to the underlying code system. But actually following this change that was made for R4 I think that seems relatively unlikely, and with decreasing likelihood as the Immunization resource matures.
Michael Lawley (Apr 27 2020 at 04:20):
It's interesting that this text https://www.hl7.org/fhir/resource.html#versions explicitly says:
For the kind of resources that have canonical URLs, this specification recommends that implementers follow the Semantic Versioning principles, but does not require this. Implementers should consider, however, making the MAJOR version part of the canonical URL rather than putting it in [Resource].version.
But the FHIR spec itself doesn't do this.
Liam Barnes (Apr 27 2020 at 04:36):
Yeah there are some terminology resources you get the vibe are stable and others aren't. Immunization status is an example but we have several different concept maps (and value sets) dependent on fhir content so would be good to have something predictable.
Grahame Grieve (Apr 27 2020 at 09:38):
The normative parts of the FHIR specification will do that
Last updated: Apr 12 2022 at 19:14 UTC