Monthly Archives: September 2013

On the future of CDA

I’ve had several questions about my comments on the future of CDA in the Structured Documents working group (SDWG) this week, so I thought I’d clarify here.

The context of this work was a question from the CDA R3 team whether they should close down the existing CDA R3 work, and instead focus on FHIR as a vehicle for CDA R3.

I think there was some confusion about this – in no way should this idea be understood as “abandon CDA” or even “stop working on CDA R3”, which I heard it characterized as. It’s simply proposing that the underlying format for the next release of CDA will be based on the technical vehicle of FHIR rather than the technical vehicle of the RIM Based ITS(s). The same functional use cases get carried forward to the next version of CDA, and the same basic requirement applies: that there be a conversion process to go forward from CDA R2 to CDA R3, just as there was for CDA R1 to R2.

So this isn’t about stopping work on CDA R3 – it’s just about pursuing the same goals by a different technical route. But the technical route has quite an impact on how things unfold – it’s a big decision, not a small one.

Also, this decision doesn’t impact on existing CDA R2 based work that the SDWG is mainly engaged in now. That work proceeds on the same basis it does now, irrespective of the course that future releases of CDA take – at least until the future version of CDA is considered ready to come out of the skunk works, and become the basis for implementation guide development and actual implementation.

Choices for the future

We’ve been discussing the course to take for CDA R3 for at least 5 years. For all of that time, there’s been, roughly, 3 choices the SDWG could choose to take:

  1. We could choose to do nothing at all, and stick with CDA R2 for the foreseeable future
  2. We could choose to do a minimal upgrade that retains backwards compatibility, so that new documents are still safe to handle by existing infrastructure. I will call this “CDA R2.1”
  3. We could choose to break backwards compatibility. It’s not safe to handle new documents on existing infrastructure  – and it might not be easy to handle existing documents in new infrastructure written for the new version

If we choose option #3, we have a range of choices from a little change through to a big change. Each of these choices presents a different cost/benefit trade-off. For instance:

  1.  if we stick with the existing overall framework, but extend the header, and put in a new clinical statement in the CDA entries, then that’s not much change; implementers use the same approach on a new schema, and can still use the same tranforms. On other hand, the benefits are somewhat fractional – the principal advantage I think that this approach has is that we get a bunch of new entry relationship codes to design documents with. But we don’t get to harmonise models completely with the domain workgroups’ existing models, which was a stated goal of CDA R3
  2. if we stick with the existing framework, extend the header, and replace the clinical statement with the unconstrained RIM, then that’s additional change – the implementers get an even more abstract CDA to work with. This impacts on the approach for writing CDA a little, and the approach for reading data base out even more. It does mean that we can use the existing work group models, and have harmonised content between CDA and V3 messaging – one of the stated goals of CDA R3
  3. if we go further, and just use the RIM directly with some constraints… well, the means the existing transforms stop working, but we could use CDA for messages as well as data.. oh, hang on, that’s V3 messaging. We never considered this approach

There’s more choices that this – variations on these themes, but the 3 I’ve given illustrate the range for the purposes of this argument.

One of the central questions I’ve had is, who makes this decision? Or, perhaps, when we make this decision, what is the priority? Something that makes implementer’s lives easier? Or something that makes standards developers lives easier? I’ve always thought that we counted the second too high in the decision – that the implementers of CDA documents couldn’t care less about alignment between CDA documents and V3 messaging designs (except in a few specific domains), but would care greatly for backwards compatibility.

Nevertheless, we chose that CDA R3 would take the option #3b above, principally to allow alignment with domain models. What I argued this week is that the value proposition of this is falling:

  • A lot of design activity has moved to CDA R2 anyway (principally CCDA and EPSOS)
  • V3 messaging is obviously never going to gain much more market share (in fact, it’s starting to have the hallmarks of a toxic brand, whatever it’s technical merits)
  • The domain work group work was always going to have to be revisited anyway (due to issues related to trading between message context and explicit representation of status)

Making a choice

What I want to know is that the implementers want? Based on my experience with implementers here in Australia, there’s 2 things they want:

  • To be able to leverage the investment they’ve already made
  • To get something easier to work with

Note that these are basically incompatible – if it’s easier enough to make a difference, then you can’t leverage your investment quite as well. But this trade-off is quite different to the way the CDA R3 decision was taken in the past. And what I’ve learnt about this is that if the market doesn’t agree with the choice a standards organization makes, it will vote with it’s feet and go somewhere else. So I always thought that the existing CDA R3 decision was dead wrong, and it was part of the reason I resigned as co-chair of SDWG.

I always thought there was 2 real choices:

  • Do what you can while strictly conserving backwards compatibility.
  • Completely transform the approach, so that when you make people revisit their infrastructure, they get something really big in exchange for that. But this takes longer and delivers more slowly

That’s the point at which I went off and did FHIR – you can see how this connects with the ideas here; FHIR offers a completly different way to do documents. As well as being easier, it means that the section contents are the same structures you exchange in any other way in any other contexts. There’s a bang for your buck for implementers. Note, though, that this value proposition assumes that FHIR is widely adopted for other kinds of data exchange, so that means the payoff is further off in the future. So I’ve always intended FHIR to be positioned as the long term replacement for CDA R2 (but as CDA R3, noting my comments above about what CDA R3 is). So I endorse the idea that the SDWG consider using FHIR as CDA R3 (big surprise), but there’s a lot of work to be done before that’s a real proposal.

If it’s long term, then, what are you going to do in the meantime? well, obviously, I think that we should do what we can while being backwards compatible, and preserving existing investment – both ours (HL7s) and the implementers. And isn’t that what CCDA R2 actually is? That’s certainly what I see when I look at it – it’s a best practices for using CDA, with extensions where required. So that’s the rational thing to do in the near term – and we’re already doing it.

In fact, we could call this new consolidated CDA R2C to indicate that it’s the next version of CDA.

 

Clinical Safety: Mandatory Fields

This post is actually prompted by the FHIR ballot, where there’s a whole swag of ballots saying that the minimum cardinality of a field should be 1, not 0. But it’s a generally tough issue – when is it right to set a minimum cardinality of 1?

When you set an element/field/attribute/property/whatever to a minimum cardinality of one, you are saying that this item MUST have content. If, for some reason, a sender of content doesn’t have a value for this item, then they can’t communicate.

Note about v3: Actually, in v3  / CDA it’s more complicated than that, because even if the element has a minimum cardinality of 1, it may still allow a nullFlavor, so it’s not actually required. For the purposes of this discussion, then, we assume that for v3/CDA contents, not only are we setting minimum cardinality to 1, we’re also making the element mandatory.

It’s really tempting, when doing a design, to say, “of course there’ll be a value – how could there not?” Only, it turns out in real life (or at least, in clinical practice, since that may not be the same thing), things you thought would be always true turn out not to be sometimes for some weird edge case. And if you haven’t though of the weird edge case, what it supposed to happen when it comes up? I know what happens in the real world: people make things up. Yes, they lie. Either the programmers or the users, they figure out some acceptable un-risky lie, and go ahead and make it.

Perhaps calling it a “lie” is a little strong, but if the system makes people fill out a field to get through their workflow, they’ll put something there, even if it’s an outright mis-truth. (I recall one system where the doctors had to fill out a diagnosis for their patients, even when they didn’t have one. After a few weeks, one doctor was entering “generally unwell” for every patient – even the ICU ones.

So the lesson is, you have to be real sure that there’s just no possible way for an value to be unknown before you go and make it required. Obviously, the narrower your use case or implementation scope, the more confident you can be. So in an international standard, many fields that are logically always present are actually allowed to be missing to cater for edge cases (and in the case of FHIR, where the usual logic is that the resources support core/80% behaviour, minimum cardinality is an exception to this rule for exactly the reasons quoted here). Where as in a profile, for a particular project, quite a lot of items are going to be minimum cardinality of 1.

Another aspect of the problem is that people think about the which elements should be present in the primary use case – the natural workflow. But interoperability models are used in all sorts of secondary use contexts. A simple example here is that of course you would always have a patient name… unless the data has been de-identified.

An entirely better way to think about it is that you only make it mandatory if there’s no way to sensibly do anything with the contents of the resource if it’s missing – then you make it required. That’s how it is with FHIR.

Trading Partners that disagree

A different manifestation of this problem is when you have two systems exchanging data with each other. System A says that an element is mandatory – because the work flow it manages can’t proceed without it. Let’s say, the patient account status/type. The other system, it doesn’t use patient accounts at all, so it doesn’t make it mandatory, and the users don’t bother filling it out.

Fundamentally, this is a workflow problem – but the fact that this is a workflow problem is often lost beneath several layers of analyst and programmer, and it often emerges as a surprise late in testing the interface. My rule thumb here is that operational clerical staff are far better at testing the edges of your system than a tester ever will be, particularly in terms of creative ways to hack the data to support a perceived workflow (not documented, of course…)

 

 

FHIR ballot: Race and Ethnicity

This will be the first of several posts exploring issues raised by the FHIR ballot.

The FHIR Ballot, btw, so far as 922 line items – by far the biggest ballot I’ve ever worked on. It certainly shows that people care. And there’s no reason to think that these won’t be resolved and a DSTU posted, though timelines are currently unknown.

A number of balloters have made comments something like this:

Subject is defined as “Resource (Patient)”, but the Patient resource does not contain race and ethnicity. Both race and ethnicity should be added to the Family History resource.

It’s correct that patient does not contain race and ethnicity. This was discussed at length by the Patient Administration work group that owns the patient resource, and in the end, they declined to add either attribute. There are 3 drivers of the race/ethnicity problem:

  • HL7 has never offered a coherent definition of the concepts
  • How they are understood and used varies widely around the world
  • The only value sets offered for each of them are very US-centric

Definitions

Race Ethnicity
RIM A code classifying the person into a named category of humans sharing common history, traits, geographical origin or nationality A code classifying the person into a named category of humans sharing a common real or presumed heritage
V2 This field refers tothe patient’s race This field further defines the patient’s ancestry

I ask, what are real or assumed heritage, but common history, traits, geographical origin, or nationality? And what is ancestry but race?

I have no idea what the difference between the two is. Wikipedia offers some discussion, but it doesn’t help me understand what HL7 is trying to do here. I think this must be cultural, because my US friends look at me blankly, and tell me that the difference is obvious. But I think most non-US people don’t see it as obvious.

Value sets

V2 offers the following valuesets:

Race:

  • 1002-5 American Indian or Alaska Native
  • 2028-9 Asian
  • 2054-5 Black or African American
  • 2076-8 Native Hawaiian or Other Pacific Islander
  • 2106-3 White
  • 2131-1 Other Race

Ethnicity:

  • H Hispanic or Latino
  • N Not Hispanic or Latino
  • U Unknown

You can see that this doesn’t conform in any meaningful way to the definitions above, and the value sets are highly US specific.

In v3, we get this definition on the ethnicity code system (apologies for the annoying wrapping on the target link, I’ll have to fix it):

In the United States, federal standards for classifying data on ethnicity determine the categories used by federal agencies and exert a strong influence on categorization by state and local agencies and private sector organizations. The federal standards do not conceptually define ethnicity, and they recognize the absence of an anthropological or scientific basis for ethnicity classification. Instead, the federal standards acknowledge that ethnicity is a social-political construct in which an individual’s own identification with a particular ethnicity is preferred to observer identification. The standards specify two minimum ethnicity categories: Hispanic or Latino, and Not Hispanic or Latino. The standards define a Hispanic or Latino as a person of “Mexican, Puerto Rican, Cuban, South or Central America, or other Spanish culture or origin, regardless of race.” The standards stipulate that ethnicity data need not be limited to the two minimum categories, but any expansion must be collapsible to those categories. In addition, the standards stipulate that an individual can be Hispanic or Latino or can be Not Hispanic or Latino, but cannot be both.

And for Race, we get this definition from the race code system:

In the United States, federal standards for classifying data on race determine the categories used by federal agencies and exert a strong influence on categorization by state and local agencies and private sector organizations. The federal standards do not conceptually define race, and they recognize the absence of an anthropological or scientific basis for racial classification. Instead, the federal standards acknowledge that race is a social-political construct in which an individual’s own identification with one more race categories is preferred to observer identification. The standards use a variety of features to define five minimum race categories. Among these features are descent from “the original peoples” of a specified region or nation. The minimum race categories are American Indian or Alaska Native, Asian, Black or African American, Native Hawaiian or Other Pacific Islander, and White. The federal standards stipulate that race data need not be limited to the five minimum categories, but any expansion must be collapsible to those categories.

Note that everything about these definitions is US-centric, though the race code system appears a little more applicable outside USA.

 

So following the FHIR rules for design and extensibility, race and ethnicity should be defined as extensions – and so we should define standard ones for USA, since all this is is driven by US statistical reporting considerations.

Family History

But note that the original comment is made against FamilyHistory, were there are more considerations at play than just simple statistical reporting. I’d particularly like comments (here or privately by email) on the question of what racial information is collected for family history considerations around the world. Though note that there’s an open issue about family history right now – this is a clinical family history, not a genetic family history, and we have not yet resolved the question of whether these two things are simply unrelated resources, the same resource, or something in-between.

 

Clinical Safety: Trust between Humans and Machines

Great post by Bruce Schneier:

My point in telling this story is not to demonstrate how I beat the EEOB’s security — I’m sure the badge was quickly deactivated and showed up in some missing-badge log next to my name — but to illustrate how security vulnerabilities can result from human/machine trust failures. Something went wrong between when I went through the gate and when the person after me did. The system knew it but couldn’t adequately explain it to the guards. The guards knew it but didn’t know the details. Because the failure occurred when the person after me tried to leave the building, they assumed she was the problem. And when they cleared her of wrongdoing, they blamed the system.

This is about security, not safety, but they’re pretty much related. Clinical software users hack the system all the time – usually, the intent is not malicious from their point of view, but the consequences are often as confusing – and they further erode the user’s trust in the system. In the worst case, users will maintain an entirely separate system for some parts of their workflow – and this is made more likely due to the fact that in many cases, a back-up non-IT solution must be maintained for when the system is unavailable.

This same issue applies on machine to machine interfaces too. Typically, when an interface is first implemented, things are carefully crafted and tested to ensure that both sides fully understand each other. But as changes are introduced to one side or another as they are upgraded over the years, the synchronization tends to deteriorate, and system failures start to occur. These cases are very hard to trouble shoot, since they often are sourced from different assumptions about how workflow works, both of which are very nearly correct.

Question: What does an empty name mean?

I was recently asked whether this fragment is legal CDA:

 <patient>
   <name/>
 </patient>

The answer is that it’s legal, but I have no idea what it should be understood to mean.

It’s legal

Firstly, it’s legal. There’s a rule in the abstract data types specification:

invariant(ST x) where x.nonNull { 
   x.headCharacter.notEmpty;  
}

In other words: if a string is not null, it must have at least one character content in it. In a CDA context, then, this would be illegal:

 <material>
   <lotNumberText/>
 </material>

Aside: the schema doesn’t disallow this, and few schematrons check this. But it’s still illegal. It’s a common error to enounter where a CDA document is generated using some object model or an xslt – it’s not so common where the CDA document is generated by some xml scripting language a la PHP.

However the definition of PN (the type of <name/>) is not a simple string: it’s a list of part names, each of which is a string. PN = LIST<ENXP>. So while this is illegal:

 <patient>
   <name>
    <given/>
   </name>
 </patient>

– because the given name can’t be empty. This isn’t:

 <patient>
   <name/>
 </patient>

That’s because a list is allowed to be empty.

Aside: I don’t know whether this is legal:

 <patient>
   <name>
    <given> </given>
   </name>
 </patient>

 That’s because we run into XML whitespace processing issues. Nasty, murky XML. Next time, we’ll use JSON.

What does it mean?

So what does this mean?

 <patient>
   <name/>
 </patient>

Well, it’s a name with no parts that is not null. Literally: this patient has a name, and the name has no parts.

Note the proper use of nullFlavors:

  • The patient’s name is unknown: <name nullFlavor=”UNK”/>
  • We didn’t bother collecting the patient name: <name nullFlavor=”NI”/>
  • We’re telling you that we’re not telling you the patient name: <name nullFlavor=”MSK”/>(unusual – usually you’d just go for NI when suppressing the name)
  • The patient’s name can’t be meaningful in this context: <name nullFlavor=”NA”/> – though I find operational uses of NA very difficult to understand
  • The patient doesn’t have a name: <name nullFlavor=”ASKU”/> – because if you know that there’s no name, you’ve asked, and it’s unknown. Note that it would be a very unusual circumstance where a patient doesn’t have a working name (newborns or unidentified unconscious patients get assigned names), but it might make much more sense for other things like drugs

So this is none of these. It’s a positive statement that the patient has a name, and the name is… well, empty? I can’t think of how you could have an empty name (as opposed to having no name). I think that we should probably have a rule that names can’t have no parts either.

It’s not clear that this is a statement that the name is empty though. Consider this fragment:

 <patient>
   <name> 
    <family>Grieve</family>
    <given>Grahame</given>
   </name>
 </patient>

If you saw this in a CDA document, would you think that you should understand that I have no middle name (I do, though I have friends that don’t). We could be explicit about that:

 <patient>
   <name> 
    <family>Grieve</family>
    <given>Grahame</given>
    <given nullFlavor="ASKU"/>
   </name>
 </patient>

Though I  think that ASKU is getting to be wrong here – you could say that the middle name is unknown, but it would be better to say that the middle name count is 0 – it’s just that we didn’t design the name structure that way because of how names work in other cultures than the English derived one. (which, btw, means that some of this post may be inapplicable outside the english context).

The first case would be normal, so this means, we don’t say anything about middle names. So why would not including any given name or family name mean anything more than “we don’t say anything about the name”? And, in fact, that’s the most likely cause of the form – nothing is known, but the developer put the <name> element in irrespective of the fact that the parts weren’t known.

So it’s quite unclear what it should mean, it most likely arises as a logic error, and I recommend that implementations ensure that an empty name never appears on the wire.

Process for Conformance Checking a CDA Document

One of the things I’ve done a lot of this year is conformance checking CDA documents in several different contexts. Since someone asked, here’s my basic methodology for conformance checking a CDA document:

1. Read it by hand

In this step, I read the XML directly in an XML editor. I’m doing the following things:

  • Getting an overall sense of the content of the document
  • Checking for gross structural errors that might prevent automated checks
  • Checking that the document metadata (realm, templateId, id, code) makes basic sense

2. Validate the document

In this step I do the following things:

  • Check that the document conforms to the base CDA schema
  • Use appropriate schematrons (if available) to check the document against the applicable CDA IG (if there’s no schematron, then I’ll have to do a manual comparison)

For each error reported, the first thing to investigate is whether the error is a true error or not. There’s valid CDA documents that don’t conform to the schema, and whether that matters or not depends on the context. There’s always areas where the schematrons themselves may falsely report errors, so everything has to be checked.

If there are schematrons, I always double the document anyway, and check that it’s valid against the specification, since the schematrons cannot check everything. I particularly keep my eyes open for co-occurrence constraints, since these are often missed in schematrons

3. Check the data 

The next step is to manually review a number of specific types of data in the document:

  • Dates – are the document and event dates internally coherent? do intervals finish after they start? are the timezones coherent (they often aren’t).  Do the precisions make sense? (I particularly investigate any date times with 000000 for the time portion)
  • Codes – are the code systems registered? Are the codes valid? (Private codes can’t be checked, but public ones are often wrong – check code & display name). Check for display names with no codes, mismatches between codes and originalText. Check version information if provided. Some of these checks can be automated, but most can’t
  • Identifiers – do the root values make sense? Are the OIDs registered? Are UUIDs used properly? are any of the identifiers re-used in the document? should they be? (often the same participant gets different identifiers in different places in the document when they shouldn’t, or vice versa)
  • Quantities- are the UCUM units valid? (If they have to be)
  • RIM structural codes – are these correct?

I nearly always find errors in these areas – it’s real hard to get this stuff correct. This is useful: https://hl7connect.healthintersections.com.au/svc/ids

4. Extensions

Check for extensions. What extensions have been added? Are they valid against the rules laid down in the relevant IG? (there’s pretty much no rules in the CDA standard itself)

 

5. Check narrative

I render the document using an appropriate/applicable stylesheet. I check it for base coherence – one thing to particularly look for is information that is likely to come from pre-formatted ascii that hasn’t been appropriately styled. Test data is often short, whereas real clinical data is longer; this is easy to miss on the part of the developers. Then I systematically check the narrative twice:

  • I read the narrative, and ensure that the information in the narrative doesn’t disagree with the data in the entries
  • I read the entries, and check that the narrative agrees with the data

While I’m doing this, I make a list of information that’s in the narrative and not the data, or vice versa. It will depend on the IG and the rules it makes as to whether anything on this list is a problem or not

6. Review the Clinical Picture

Finally, I review the clinical picture described by the data in the document. Does it make sense at all? Very often, actually, it doesn’t, because the document is filled with test data that doesn’t match a real clinical picture. But in spite of that, this a very useful step – I’ve caught some fundamental errors in implementation or even understanding by querying things in the document that don’t make sense.