Interpreting RIM Objects Safely (Exclusion Statements)
Oct 30, 2012One of the most difficult parts of the RIM based content models - including CDA - is how to interpret and/or query them safely. In the past I volunteered to write something about this:
Grahame: As mentioned in Q1 MnM this morning, I volunteered to do this in the past. I agree that we need to progress this
I did spend some time on this, and it’s rather complicated (which meant I never finished it). In addition to being asked about the status of this earlier in the week, I was reminded of this forcefully when I saw Keith’s post about exclusion statements, which was in response to my earlier post about them.
Keith proposes to represent the assertion of a lack of allergies like this:
<observation classCode="OBS" moodCode="EVN" **negationInd="true"**>
<code code="ASSERTION" codeSystem="2.16.840.1.113883.5.4"/>
<statusCode code="completed"/>
<value xsi:type="CD" code="419199007"
codeSystem="2.16.840.1.113883.6.96" displayName="Allergy to Substance"/>
</observation>
I have stripped out the templateId, id, and effectiveTime attributes, since they are not relevant to the subject at hand. On the other hand, I left statusCode in, since it’s relevant. This compares with the NEHTA representation of the same concept:
<observation classCode="OBS" moodCode="EVN">
<code code="103.16302.120.1.1" codeSystem="1.2.36.1.2001.1001.101"
displayName="Global Statement" />
<value code="01" codeSystem="1.2.36.1.2001.1001.101.104.16299"
displayName="Nil Known" xsi:type="CD" />
</observation>
These are rather different approaches. I don’t believe that either is wrong, though I admit that the representation Keith proposes is more aligned with general HL7 thinking. The NEHTA approach works differently because it is constrained to be an implementation of a solution to this problem based on an entirely independent definitional stack that starts from the definitions in openEHR. This has both strengths and weaknesses. The primary weakness is that it’s hard to be well aligned with the CCDA community. The strength is that you get a simpler solution. In this case, the exclusion statement, which was defined by the clinical consultation process is represented as “I observe (observation) that there are no allergies (global statement) because there are ‘nil known’ (value)” whereas Keith’s representation is “I observe (observation) that I can assert (Assertion) that the patient has allergies (value) NOT (negationInd)”.
The first note with regard to querying/interpreting RIM statements, then, is that you can say pretty much the same thing in completely different ways. This is a widely made observation, but worth repeating here. The RIM is essentially the grammar for a constrained language. Like all useful languages, there’s more than one way to say the same thing. You can say the same thing in several different ways. The same thing can be said in multiple forms. I don’t think that it’s possible to strip the RIM down to the point where there’s only one way to say things without removing the ability to say many things that need to be said. In particular, I don’t think that removing the flexibility to choose between structure and terminology - the source of much of this variation - is possible or useful.
The second note is that you can’t really start to understand RIM statements until you understand the terminologies. This is no different to saying that you can’t understand English until you know what the words mean. But implementation is still highly focused on the structures, and formal terminology support in applications lags far behind. Safe interpretation of RIM statements depends on solid and correct interpretation and usage of the terms. I won’t pursue this further in this post other than to say, this is a hard thing to get right.
In NEHTA, the clinicians are very insistent about the limited scope of the negation statement: they are never claiming that the patient does not have any allergies - only that none are known. This is pretty important to clinicians. But there’s a common language substitution that happens, between “We (patient and clinician) don’t know of any allergies” and “there are no allergies”. This same substitution happens in the RIM, and is evident in Keith’s example. I’m sure that Keith would be happy to confirm that there is no intent to claim that there is certain knowledge that the patient has no undiscovered allergies - but that’s actually what the RIM statement he offers claims. Generally, my view is that the RIM is weak on negation - there’s often a scope limitation on negation and the RIM doesn’t really capture that. (In the same way, the RIM is weak around uncertainty. Note though, that both these things are tremendously hard to describe).
But there’s some much simpler things that Keith’s example brings up
Be careful interpreting RIM Statements
Consider the difference in Keith’s xml between an assertion that a patient does have allergies, and that none are known:
<observation classCode="OBS" moodCode="EVN">
<code code="ASSERTION" codeSystem="2.16.840.1.113883.5.4"/>
<value xsi:type="CD" code="419199007"
codeSystem="2.16.840.1.113883.6.96" displayName="Allergy to Substance"/>
</observation>
and
<observation classCode="OBS" moodCode="EVN" **negationInd="true"**>
<code code="ASSERTION" codeSystem="2.16.840.1.113883.5.4"/>
<value xsi:type="CD" code="419199007"
codeSystem="2.16.840.1.113883.6.96" displayName="Allergy to Substance"/>
</observation>
An important consequence of this is that whenever you look at an observation, you have to check whether it’s been negated. I’m sure that most implementers of CCDA aren’t checking whether the observations as described in CCDA are negated or not, since CCDA doesn’t say that they can be - but since they can be, you have to check. Painful, and I’m sure that this is going to prove to be the source of a number of adverse patient outcomes.
Note that the first example is that the patient is allergic to a substance, but with no substance. In practice, who’s ever going to say that, or try to read it without an error? So, at least in this context, the negationInd doesn’t stand alone. But consider a system that wanted to claim that the patient wasn’t allergic to tree nuts (my daughter is allergic to tree nuts, so this example comes naturally):
<observation classCode="OBS" moodCode="EVN" **negationInd="true"**>
<templateId root="2.16.840.1.113883.10.20.22.4.7"/>
<code code="ASSERTION" codeSystem="2.16.840.1.113883.5.4"/>
<value xsi:type="CD" code="282100009" codeSystem="2.16.840.1.113883.6.96"/>
<participant typeCode="CSM">
<participantRole classCode="MANU">
<playingEntity classCode="MMAT">
<code code="FFY6MYO89N" displayName="TREE NUT"
codeSystem="2.16.840.1.113883.4.9"/>
</playingEntity>
</participantRole>
</participant>
</observation>
The only way to pick is to explicitly read the negationInd. So, you must always consult the negationInd. I doubt that many implementers mining data from (C)CDA documents know that this is possible, or remember to do it every time. Aside: this is not allowed in NEHTA documents. If an element is not explicitly described in the implementation guide, it cannot be used if it’s not safe to ignore. Clearly, negationInd is not safe to ignore. CCDA seems to allow it anywhere - it never says it is not allowed, which makes rules like “MAY contain zero or one [0..1] @negationInd” rather confusing. (oh, if a CCDA template is closed, then it can’t have a @negationInd, but there was only one of those as of the last ballot).
Keiths’s second example is this:
<observation classCode="OBS" moodCode="EVN" **nullFlavor="NI"**>
<code code="ASSERTION" codeSystem="2.16.840.1.113883.5.4"/>
<value xsi:type="CD" code="419199007"
codeSystem="2.16.840.1.113883.6.96" displayName="Allergy to Substance"/>
</observation>
This one is very subtle - there’s a nullFlavor on the observation, which means that all the content in the observation pertains to the thing that we don’t have any information about. It can be difficult to to interpret the scope of the NI - is the assertion that we have no information about? or the value? here, it’s probably not much difference. But not in other places. But the point is, you have to check the nullFlavor on the observation.
In a later post, I’ll get to the really complicated question (what my original intent was) - to what degree you have to walk up the heirarchy looking for @nullFlavor, @negationInd, and other things?
Unknown / Default Information
Keith’s example includes statusCode, with a status of completed. We eliminated this from the NEHTA representation because it’s just irrelevant to an implementer - what would it mean for the observation to be aborted? cancelled? suspended? Only one possible value makes sense, which is completed, so we eliminated this from the XML as just random noise that would confuse the implementers. But eliminating it leaves open the question, what is the value, and would it matter? It depends on context. But CDA itself eliminates uncertaintyCode, so you can never be sure whether an observation is uncertain or not - unless you are aware of any applicable guidance from the implementation guide.
So a final point (for this post) about interpreting RIM statements: it can only safely be done in partnership with good knowledge of the rules that were applied where the instance was generated. If you don’t know what these are, you won’t know how to intepret the content.