This came up while making archetype-local terminology reachable over FHIR, and I cannot find the answer in the specifications.
If you derive FHIR resources from an archetype, the at-codes become a CodeSystem and an ac-code becomes a ValueSet. FHIR requires both of those to carry a canonical URL: a globally unique, preferably resolvable identifier that every other resource uses to reference them. openEHR gives me an HRID for the archetype itself, org.openehr::openEHR-EHR-EVALUATION.problem.v1.3.5, and nothing at all for the value sets inside it.
Archetype Identification has a section reserved for exactly this question, A Reliable URI for Knowledge Resources, and the entire content of that section is “To Be Continued”.
So for now whoever produces the resources mints a URL out of the archetype id, and my server reads it as an opaque string. That works, but it means two deployers publishing the same archetype under their own domains give the same value set two different identities, and nothing can tell that they are the same thing.
Has anyone settled on a shape for these already? @SEC
I agree with your assessment of how atCodes map into FHIR Codesystems/ Valuesets, though there are some challenges where Valuesets are differently constrained in cloned nodes in templates. ADL2 will, I think, make this much easier to manage
My approach has been const formatCodeSystemUrl = (node : TemplateNode) : string => 'http://openehr.org/archetypes/${node.archetype_id}/CS'
I’m not in any way wedded to this,
I’m sure @yampeku@grahamegrieve@Brett_Esler@jbuch would be happy to offer alternatives. I think we should probably ‘adopt’ ADL2 principles for this, especially as under the hood AD templates already use ADL2 constructs which are then flattened out to 1.4 opt.
Maybe an interesting place ot start exploring ADL2/ Opt2/ Web template2 for extended tooling, rather than just focussed on CDR validation.
What is your interest? ferroEHR is a really interesting project and I’d love to see some of the ways of working applied to the tooling side.
I think you should consider what publishing the same archetype under their own domains means for the archetype itself before thinking about the sameness/equality of something in that archetype. The obvious point of namespaces is to avoid collision but they also imply the concept’s semantics is whatever ontology that namespace’s owner defines/uses:
This specification takes the point of view that the concept part of a managed knowledge artefact identifier must come from an ontology corresponding to the namespace of the identifier, in other words, an ontology maintained by a Custodian Organisation or some higher authority
Therefore my view is that once the published domain names diverge, the archetype’s concept can no longer be assumed to mean the exact same thing, so I would not assume the archetype-local value sets can be the same thing, since they’re not necessarily local to the same thing anymore.
What would make sense to me therefore is to assume they’re not the same. They are not necessarily different, but when there is no guarantee they’re the same, I take the safer semantics.
Happy to be corrected if my reading of the spec is wrong here.
I was treating “two domains, two URLs, no way to tell they are the same” as a gap. You are right that it is the safe reading: different namespace, different concept, so different value set until someone proves otherwise.
That IMO is exactly correct. Sometimes people have criticised that e.g. the blood pressure and pulse archetypes have different codesystems/ valuesets for what seems like duplicative terms but in practice the body sites are quite specific t other observation, so the valuesets will be different and the advantage of a common parent codesystem or valueset is more limited than may expect - has anyone ever wanted to query for ‘left arm’ across different observations? So I’m happy that current atCodes are what FHIR would regard as ‘contained’ Codesystems. There is some convenience ot using e.g common SNOMED terms, particularly if translations exist but it is often just convenience not semantics - Severe in ‘Severe heart failure’ has a different meaning to Severe in ‘Severe blisters’
There are, of course, other cases where cross-domain Codesystems/valuesets have real value but that’s where we can take advantage of the FHIR TS ecosystem as an alternative to atCodes.
Correct. The ‘concept’ part of an archetype id is relative to its namespace. This might seem far from ideal, but if you think about it, ‘bp_measurement’ in an openEHR archetype id really means ‘openEHR-EHR-OBSERVATION.bp_measurement’, i.e. ‘blood pressure observation result data items’ or similar. It’s a pretty specific idea of BP data points - ontologists would treat it as a ‘contingent’ entity, i.e. it could have been different - that’s because it’s a model of possible data items, not an ontic one. This is not the case with true ontological description of ‘blood pressure’ which can fairly easily have a single agreed formal description (‘pressure in some artery at moment of systole/diastole in cardiac cycle’ or similar).
It’s always worth remembering we are dealing with the doing of medicine here, and like anything else, there are contingent reasons for how many things are observed and recorded - e.g. what is cheap and easy, non-invasive etc, is preferred over difficult/expensive/painful. So archetypes express the truth of that, not the deep truth of what ‘blood pressure’ really is.
The concept part of the id is therefore assumed to be relative to some namespace, which could default to org.openEHR (realistic for BP measurement), but could easily be nl.nictiz (anything a bit NL-specific, or even just commonly culturally used by NL doctors for some historical reason) or whatever else.
The title of this thread is about “the canonical URL of an archetype-local value set”. Ian provided his URL as http://openehr.org/archetypes/${node.archetype_id}/CS. Subsequent posts discussed the archetype’s namespace, not the archetype’s local value set URL.
Does the marked solution answer the original question?
True but Ruben did ask a related question about the challenge of seemingly related/duplicative Codesystems/Valuesets in seemingly overlapping archetypes with different identifiers. Helpful clarification in getting back to the main issue - how to create a url for atCode internal codesystems and related internal valuesets.
For clarification, I would now inject the original_namespace into the archetype_id but probably not the minor and revision numbers .. so
in ADL2 templates we also have to consider atCodes in the root template specialisation and slotted archetype overlays.
More tricky is where a particular node is cloned and each node has a different constrined Valueset from the parent. I found it hard to construct a url as it was really path-dependent and might be quite long. It’s easy to generate a url manually, of course, so perhaps we just need to keep that as a fallback
@borut.jures yes, that was me clicking the wrong button. Seref answered the side question about two namespaces and I marked it without thinking. I’ve undone it. The URL question is still open.
@ian.mcnicoll the namespaced version makes sense to me. Keeping only the major version in the URL and putting the full archetype version in the FHIR version element is how I would do it too.
What I still don’t know is how the ac-codes get their URL. Same base with /VS/ac0001 at the end? And for the cloned node case I’d rather have a long derived URL than a hand-made one, otherwise two tools converting the same template come out with different URLs and nobody notices. ADL2 already has a form for that, [archetype_id]/path in ADL2 4.3.7.2, and the same thing in ADL 1.4 5.3.6, so the path part doesn’t have to be invented and works for the templates people run today.
I agree re avoiding handcrafted Urls if possible but I suspect this might be tricky - I had envisaged the manual overwrite being handled as a template annotation, so that it would still power automatic generation - I guess some kind of ‘slug’ that avoids a painfully long path-based url. But if we can achieve that alogorithmically good job. It might be much less of an issue with ADL2 and overlays, since the parent archetypeId is reset part-way down the tree and the path from there might be much shorter.
@ian.mcnicoll I think it can be done algorithmically. The whole scheme:
http://openehr.org/archetypes/org.openehr::openEHR-EHR-OBSERVATION.blood_pressure.v2 the archetype
.../v2/cs the at-codes as a CodeSystem
.../v2/vs all codes (LOINC does the same with http://loinc.org/vs)
.../v2/vs/ac0001 a local value set, ADL2
.../v2/vs/at0008 the same in ADL 1.4, named by the node it constrains
.../v2/vs/at0008/at1000,at1001 a template narrowing: the kept codes, sorted, comma joined
The id part is the interface HRID reference the Identification spec already uses for references at major version, so nothing new gets defined there. The full archetype version goes in CodeSystem.version and ValueSet.version, so |2.1.3 works as FHIR intends.
The cloned node case is the last line. The URL is built from the kept codes only. Two clones that keep the same subset are one value set, two that differ are two, and two converters get the same URL from the same template. Template id and paths go in the description. Longest URL in my test: 116 characters. FHIR calls this an implicit value set and says a code system publisher may define such patterns, so a server holding the CodeSystem can expand these without a stored ValueSet at all.
I checked :: and , are legal in a path segment (RFC 3986 3.3). Proof of concept: a synthetic archetype and a template with three clones, derived by two independent scripts, diffed, loaded into FerroTERM. $lookup, $expand, $validate-code and the versioned search all answer. It is in Python, so anyone can run and check it out. Code and results: openehr-canonical-url-poc.zip (20.5 KB)
Full disclosure: I asked Claude (Fable 5.1) to work out whether this could be done algorithmically and to build the proof of concept against my FerroTERM server. The scheme and the test run are its work, checked by me, so read it with that in mind.
Where it should live in the spec is a question for @SEC.
Makes perfect sense in ADL2 but currently the acCodes get flattened out of .opt1.4 and webTemplates, even though they are in the underlying AD native.json.
Useful conversation, as it makes me think that .opt2 will be required much more immediately as a tooling artefact, than for CDRs. It certainly makes these node-clone issues easier to deal with.
I’m nervous about the comma separation, even if it is legal in RFC. Might be needed as an absolute backstop but something like
etypes/org.openehr::ovl.openEHR-EHR-OBSERVATION.blood_pressure.v2/ac0.3 should handle most cloned/adapted valuesets. An associated human name would be helpful possibly generated from the specialised node atCode would also be useful.
Not sure how much, if any, this is flattened out of .opt2
That is the primary form. The comma list stays only as the backstop for OPT 1.4 and web templates, where no ac-code survives, and you can tell the two apart from the URL alone.
On flattening: an OPT2 keeps component_terminologies keyed by archetype id (AOM2 OPERATIONAL_TEMPLATE), so the overlay’s ac-codes survive into the operational form. That is the difference from opt 1.4.
Human name: yes, ValueSet.title from the rubric of the specialised node, name computed from it. The URL stays codes only.
I added an overlay with ac0.1 to the proof of concept. Both scripts still agree and the server expands it at the overlay’s own version. Updated zip: openehr-canonical-url-poc-v2.zip (20.2 KB)
I was assuming we were trying to establish what form of the id would be needed to act as a vocabulary root id for contained terminology terms and value sets. We probably didn’t quite address the original problem:
In the spec, section 3.2 it says: ‘The namespace above is the publisher organisation reverse domain name’. Here ‘publisher’ means in the ‘releasing’. For historical reasons, we have used the term ‘publish’ to mean release. So two deployers probably are not ‘publishing’ the ‘same archetype’ in that sense; they may be serving them in distinct CDR environments, but the ids will not change, assuming we are talking about the same archetypes (e.g. from org.openEHR). If on the other hand you really do mean ‘releasing’, then we are not talking about the same archetypes, even if both organisations happen to have chosen the same concept id (‘bp measurement’ or similar).
The other thing is that codes and value sets should be identified based on the archetype in which they were defined, not the final using template. But if the template introduces new codes, then it is the ‘defining archetype’.
None of this is ideal. In my view, the future version of archetype coding is in a separated, controlled terminology, which requires a fair bit more in terms of machinery and tooling.
From a specifications point of view, I would advocate for somewhere else. I think you’re discussing the FHIR semantics of an openEHR concept here, so that’s somewhere in the mapping (languages), HL7-openEHR collaboration efforts territories.
also, nowadays my main concern with openEHR identifiers is that they are too long (usually >50 chars) which makes difficult to include them in some sql secondary use storages