Scores or scales with mixed data types or explicit NULL values

We have probably had a lucky escape with this particular archetype since it does not compute a total score and therefore a 0 ordinal is probably safe but it would still be good to try to understand the blockers to making null_flavours more useable.

This example is clearly a good use of null_flavours but practically speaking, it is quite difficult to define their use clearly in archetypes and templates. They work well for integration cases where UI is not involved but it is quire difficult to incorporate them into UI and certa9nly form building.

Is this something that might benefit from a re-think or at least some suggestions about how it might all be easier to work with.

I’ll throw up a challenging strawman!!

  • what about if we allowed null_flavours and associated reason codes to ‘appear’ to be added to a Valueset. I say ‘appear’ because I think the underlying separation of ‘nulls’ from real data is correct but perhaps we could find a away to present the use of nulls in a more naturastic way (as seeming added terms as per the scale/score example ) in both archetype tooling and forms building.
1 Like

I like this thinking, and it aligns pretty well with what we were envisioning when we thought up option #1 above.

I agree with Sebastian though, that the null_flavours should be defined more thoroughly in the specs. Currently it’s often difficult to tell ‘not applicable’ from ‘no information’, and the possibility of applying a ‘masked’ flavour as a query result makes my head spin. I’m not sure the answer is to add more flavours - I’d prefer if we at least start by more clearly defining the ones we have.

Are you sure? I don’t understand how using 0 doesn’t make it difficult to distinguish “Not assessed” from “Normal”. Differentiate by the at-code?

ok ‘lucky-ish’ escape - it would have been much more problematic if there had been a computed score - at least the text e.g. ‘not assessesed’ will be visible when assessing the response.

1 Like

No more flavours than necessary, I agree…some from FHIR seem to be specialisations of the more generic ones that we already share between FHIR and openEHR.

2 Likes

We looked at the flavours in a discussion the other day and it suddenly appeared to me: Do we really need to distinguish the flavours in the RM?
When I read them I surely understand the differences from a logical and theoretical view. But will it be clear for an end-user in a specific entry situation? And what is the benefit of distinguishing them? Perhaps it would be good enough with a NULL_FLAVOR definition and some NULL_REASONS either as text or coded text?

Another perspective that came up in the discussion was about the masked flavour. Some thought this could be used to mask the real value in the data. Like “I have entered the value of some disorder but it is masked by the null flavour”. This would of course be meaningful in a client-server architecture where the client ask the server if it has information about the attribute. The server might say “yes I have some information but it is masked to you… give me some other credentials and I might give them to you…”

This is,AFAIK, not the intention with openEHR “masked”. It should be used to say that somewhere in the real world there exist some information but it’s not present in this EHR-system.

The question is:
Are there any known use of the NULL_FLAVOUR today? If yes - what’s your experiences using the different flavours? Is the current list of flavours good enough? Do you miss any flavours?

1 Like

Agree. I don’t know how this particular score is used, whether it’s only once and never again, or it’s repeated to give an idea of progression. If the latter, it’s not unreasonable to graph it. Then values of 0 would really be problematic. “Normal, or I don’t know - might be 3 if we scored.”

2 Likes

That’s not exactly what I meant. My thinking was that a null value could be returned on a query where the person or organisation running the query for some reason didn’t have access to the data. The null_flavour would be returned alongside the null value to explain the reason why there’s no data.

But yeah, I’d love for this kind of thing to be further clarified.

1 Like

Null flavours is a tough topic that has been discussed for a long time. @thomas.beale presents some excellent arguments in his blog:

We also have some infomation in the wiki:
https://openehr.atlassian.net/wiki/spaces/spec/pages/4915211/Null+Flavours+and+Boolean+data+in+openEHR

And also in Discourse:

I’m not sure which is the best way to discuss this and to try to reach an agreement in the community, but it will require some effort and dedication for sure.

Meanwhile, these are my two cents.

Maybe we should rethink which is the real meaning and value of having null flavours. I have been thinking on how the HTTP response codes work (4XX codes for client errors and 5XX for server errors) and that could be a good inspiration.

  • There are null flavors that will come from the server, during data recovery. For example, the no information and the masked nulls, meaning that the server is not able to serve that information due to a technical or logical reason. These should be generated automatically just to inform of the situation to the receiver of the data (being a human or another system) so it can react accordingly: show an error, retry later, retry with different credentials…
  • There are null flavors that will come from the user, from the person or system that is generating the data. This is the case of not applicable/evaluable, not asked… The difference here is that these null are provided during the data capture process, they are in some way also clinical data, that should be stored, processed and maybe be modified in the future. They could be also useful in the situation when an archetype defines a data point as mandatory but maybe that information cannot be recorded or it doesn’t exist. The user could select a null reason so he/she is able to, at least, store the composition without errors with all the other data. And that means that they could be archetyped.

At the end, we will probably end with more or less the same values of null, but I think that this approach of thinking helps in clarifying that the null flavour should not be understood just as a miscellaneous mess of codes.

4 Likes

These are formally two different vocabularies - the null_flavours is sourced from openEHR terminology, while reason text/codes are on a per archetype basis.

I’d suggest that we don’t want people being able to edit the null_flavours vocabulary in an uncontrolled way (this will wreck any computability). I can imagine however that AD and similar tools would make it easy to see the vocabulary and potentially post a change request.

Well it depends on how computable we want data marked with a null flavour to be. Not applicable is very different from Not available for example.

FYI - ‘masked’ originally was designed to be a NF that is set by a server when it hides (i.e. removes) some data item because it is ‘sensitive’, when it provides the data to some client system or application. Whether this still makes sense is an open question, since I don’t think we seriously envisage marking data as sensitive or not at the ELEMENT level.

Yes - this makes sense and I think it would be good to add this to some documentation/specification.

One use-case could be extract of openEHR data where it could make sense to mask free text (DV_TEXT). By using the masked code the server/routine could inform that some data exist or not.

As you write; data access control on ELEMENT level will be extremely hard to design and implement. If we want to follow this pattern of access controll (to filter data) we could visit the idea of a NULL_FLAVOUR on higher level structures. In some situations it could be relevant to mask an ENTRY or CLUSTER structure. Not that we have seen this in a concrete use-case yet. Still I have from a theoretical view seen this need.

That’s not what I was suggesting …

What if the tooling / visualisation / from build were to allow this visually

Mild
Moderate
Severe
Not applicable
Not asked

Essentially the ability to visually add ‘null’ type terms to a normal list, or as a pesudo alternative datatype.

Under the hood these would actually be Null reasons/ null_falvour codes

Mild
Moderate
Severe
Not applicable [Reason: Not indicated Null_flavour: not_applicable]
Not asked [Reason: Not asked Null_flavour: ]

which would be represented at run-time exactly as currently intended.

i.e Mild, Moderate, Severe → value
Not applicable → null.null_flavour = not_applicable, null.reason = “Not applicable”

I think we could probably do this with current ADL but I do wonder if this can cope with both ‘technical integration’ constraints (fall back for null data in integrations) and clinical null constraints, essentially specifying allowed null terms that can be entered.

2 Likes

That’s probably a step too weird for me (since it makes values and non-values look like one value space), but I now get what you are suggesting and can see some attraction in it, since normal people (including docs who design healthcare forms etc) often build this kind of mixed value list.

I think to make it work properly, you’d want some way of visually distinguishing the null values, e.g. in a different colour, and to get them added in the first place, you’d have some button for ‘add exception value’ or similar.

I do think it’s necessary to be able to present this visually as if both the ordinal values and the null values belonged to the same value set. But I don’t think it needs to be difficult to visually distinguish them from each other. The paper form screenshot I included in the initial post of this topic does this beautifully: the ordinal values are presented with their respective values to the left, and the null values are presented with, well, nothing :smile:

Agree. I have no problem with making it clear somehow both in tooling and end-user apps that these are nulls but I do think this is probably how they have to be handled to make them useable in archetyping/templating and UI. Under the hood, I 'm happy for these to resolve into the current RM approach. though not sure if anything needs to change to support constraints of null_flavour codes, along with one or more ‘Reason’ codes - this is a pattern quite similar to ism_transitions, I guess and I wonder if the RM might need to change to make constraining easier.

2 Likes

I wouldn’t agree with that: I think it’s reasonable that they can be made to appear that way (as you have shown), but to make them literally part of the same value set, when the 0-3 are values resulting from assessment, and the other two indicate that no assessment was done (or maybe ‘not evaluable’ is actually a kind of evaluation?), would greatly confuse any subsequent inferencing.

Essentially it is mxing values with non-values, which we humans are good at because we are cognitively very sophisticated, and we are abstracting over the difference. But computers just do what they’re told…

Conclusion for now, from the modellers perspective:

The published GOSE archetype uses the ordinal ‘99’ to indicate an unscored value, similar to NANO’s “not assessed” and “not evaluable”. This is similar to option #2, but makes it possible for business logic to tell the actual values apart from the unscored values from the ordinal value itself and not just from the at-codes. We’ll use this pattern for both NANO and NIHSS. Business logic will have to make sure any of the ‘99’s are excluded from any graphing or summing, but this is easier than extracting the numerical value from a string. The plan is to finish review of the archetype and then pause it waiting for the “proper” solution (option 1) to be implemented in tools.

Is there any progression in tooling development wrt how to solve this kind of issue? We’ve now gotten around to doing the NIHSS, which has a similar issue requiring both null_flavour and null_reason. These elements need to be constrainable on the archetype level, and possible to use/visualise through the CKM, in OPTs, in implementations/lowcode tools and renderers, and in CDRs.

@borut.fabjan @sebastian.garde @bna

I think the answer is no but perhaps we can get together as modellers and express a common clear requirement.

So I want to be able to specify, in both

  1. That null_flavours are explicitly available or explicitly not available on an ELEMENT.

  2. If they are available, which null_flavours are allowed ( we already have that)

Perhaps we can make this work already with the existing constraints.

i.e. If you want to permit a null_flavour, you need to make at least one of the null_flavours available, otherwise nulls are not allowed.

One issue to think about is whether as well as having a null reason comment, whether there is any value in allowing other types of term to be used instead of, or alongside the official null_flavours Perhaps a bit like current_state and careflow_step in ACTIONs.

Is it important that we stick absolutely to the current list for computational reasons? Personally I think not. Allowing local null_flavours would solve the problem as with this example

image

which expects 'Not assessed and ‘Not evaluable’ and not the current terms

Whatever, the tooling should (IMO) be able to show the visually combined lists of true valueset + allowed nulls., but agree with Thomas that these are not actually mixed into a single valueset.

1 Like

Not 100% sure why you need this, but would

null_flavour existence matches {0}

not do this from a specs point of view (tooling is a different issue of course)?

To me the spec is not 100% clear whether we can just use other codes as null_flavour:

4.1. Item Structure Package / Overview

Values from the openEHR null flavours vocabulary, including 253|unknown|, 271|no information|, 272|masked|, and 273|not applicable| are used to populate it. Only a small number of generic codes are defined, in order to avoid complex processing for most data instances, for which this simple classification of null is sufficient.

whereas

5.2.3. ELEMENT Class

null_flavour: DV_CODED_TEXT Flavour of null value, e.g. 253|unknown|, 271|no information|, 272|masked|, and 273|not applicable|.

The first seems to mandate or at least strongly encourage a fixed set of null_flavour codes, whereas the second uses “e.g.” to indicate that these are examples only (in my understanding).

Now I guess it depends on the value of having “computable” null_flavours. I suspect that very little can actually be done in terms of computation… If these generic null_flavours are not so useful anyway (due to problems like the ones already described by e.g. @thomas.beale, @bna and myself above already), we might just add custom ones?
If not, I think @ian.mcnicoll has suggested that we could think about custom null_flavours mapping to the core ones (roughly similar in spirit to what we have for ISM_TRANSITION), if I understood you correctly, @ian.mcnicoll? This of course is a somewhat bigger change.