Monthly Archives: January 2016

#FHIR and HTTP Patch

At the last connectathon, we had a stream testing support for PATCH using JSON patch. A number of us participated in the stream, and some of us got JSON patch working fine.

But it’s not clear that JSON Patch is the solution we’re looking for.  JSON Patch has some advantages:

  • It’s an external standard – we like that
  • It’s pretty simple – we like that too
  • There’s existing libraries, and set of test cases – we really like that

But. The problem is that JSON patch is based on JSONPointer – when you specify changes in a list of objects, you specify the list by the numerical offset of the object in it. This means that in order to make a set of changes to a set of JSON objects, you must know exactly what the existing content is. So in order to use JSON patch, you must first query a resource for it’s latest state, determine the changes that you wish to make, and apply them using a version specific  update.

Sure, that sequence works. But it doesn’t really deliver on the 2 key use cases that people have identified for using PATCH in FHIR:

  • Save a client from fetching an entire resource to make updates to it
  • Manage more effectively updates when the client doesn’t have access to all the parts of a resource

The second case is interesting. The problem is that when a server gets an update from the client, to figure out how to use it, it must determine what the client has access to; if the client hasn’t get access to it, it can’t delete content that the client hasn’t mentioned in the update. Tricky. But because JSON Patch using list index offsets, it turns out that the basic processing logic isn’t any different – the server must determine what the client has access to in order to figure that out.

There’s one other problem with the JSON Patch approach – it doesn’t support XML, and there’s lots of FHIR implementers using XML.

FHIR Patch

There’s an alternative approach that might be better. Instead of using index based offsets, allow a general query. And use the FHIR parameters infrastructure, to support both JSON and XML.

I would propose a smaller set of operations, but they have different parameters:

  • Add – content to add
  • Remove – selection query (using FHIRPath)
  • Replace – selection query (using FHIRPath) + content to add
  • Test – query that must evaluate to true

Note: I’ll be making another blog post shortly about where FHIRPath is up to. 

This is more capable than the JSON patch approach – you can specify a change to make without first having to get the resource. For instance, you could say, if the patient doesn’t have this phone number, then add it.

But this has some disadvantages too:

  • there’s no external libraries support for this
  • it needs FHIRPath. while I think that everyone will eventually need to support this, so far, there’s no particular need to for a lot of implementers
  • It’s much more complex to test

There was some discussion around this during the connectathon, but there was no clear preference amongst the participants. None of use like these disdvantages, but we don’t really like the limitations either. Comments are welcome.

 

Question: #CDA – how to handle Observation Component code

Question:

I’m unpacking a Summarizations of Episode Note” CDA document. The section “Relevant diagnostic test and/or laboratory data” has an organizer classCode=”BATTERY”, and followed by many component.observation elements.  All of these have valid values (eg, type=PQ value=86 unit=mg/dl), but *all* have the observation.code element containing nullFlavor=”UNK”.

The <text>…</text> data does have both the test descriptions and results for display formatting, however.

Here’s an example snip:

  <component>
   <observation classCode="OBS" moodCode="EVN">
    <templateId root="2.16.840.1.113883.10.20.22.4.2" />
    <code nullFlavor="UNK" />
    <text>
      <reference value="#ID0EFTDIABA" />
    </text>
    <statusCode code="completed" />
    <effectiveTime value="20151208091900" />
    <value xsi:type="PQ" value="86" unit="mg/dL" />

Are these component.observation segments constructed correctly?  If so, can you direct me to some literature to make sense of this apparent list of values with no codes?

Answer:

Well, technically, I think are conformant. What the template identified by 2.16.840.1.113883.10.20.22.4.2 says is:

SHALL contain exactly one [1..1] code (CONF:13908), where the @code SHOULD be selected from (CodeSystem: 2.16.840.1.113883.6.1 LOINC)

Well, it contains a code, not taken from LOINC. So ‘correct’ in that it meets that rule.

But it’s not really correct. As you’ve found, it’s not possible to interpret an observation without a code, unless the context is crystal clear – which it isn’t, because it could only be clear in the template – about the inferred code (that’d be bad practice anyway). I certainly think that the committee that wrote that rule above never intended for an implementer to use a nullFlavor on the code, though there’s always edge cases where maybe it’s valid

So, no, not correct. But my experience is that you’ll have to live with it, and ignore the data or infer meaning manually or something. See Rick’s ongoing series on “CDA in the Wild” – you’re lucky!

Announcement: #FHIR publishing plans

At the Orlando meeting, the FHIR Management Group (FMG) made an important decision around the future plans for the FHIR specification.

In March 2015, the FMG decided to publish DSTU2 that covered the base infrastructure, and to plan to release a DSTU 2.1 that left the infrastructure unchanged, and filled out additional details around the Financial and workflow resources, for ballot in the May ballot.

We’ve been following that plan until the meeting in Orlando, but it was evident that we needed to reconsider our plans. There were two reasons why:

  • Resolving the issues around the workflow resources was taking longer than we hoped, and sticking to our plan would mean no connectathon testing of the redesign
  • There was ongoing pressure to make changes to resources that were frozen for DSTU 2.1

After consulting with as many stakeholders as we could, and considering the ramifications of waiting until the September ballot, FMG decided that we will no longer publish a DSTU 2.1 version. We will instead plan to ballot DSTU 3 in September, with a likely publication date late this year.

At this stage, we don’t know all of what is planned for DSTU3. It certainly will include:

  • Significant changes to the financial resources
  • A total redesign of the workflow related resources
  • A set of new resources to support clinical reasoning and decision support

There will be other changes; I’ll discuss these later as the process continues.

Note: this is really an official FHIR Product Director Announcement; I’ll move it to the HL7 Product Director blog once that’s set up.

#FHIR Product Director

While in Orlando last week, HL7 appointed me The “FHIR Product Director”. This is a new position that has been created by HL7 in accordance with the HL7 BAM (“Business Architecture Model” – can you tell that HL7 likes acronyms and ‘models’?). For HL7, appointing me to FHIR Product Director role achieves two important goals:

  • It’s a step on the path towards sustainability for the FHIR project
  • It formalises HL7’s business arrangements around the FHIR project

Sustainability

The FHIR project has done amazingly well – that is, I’m astonished at how well it’s done. The growth of the community is an order of magnitude bigger than our most confident projections when we started working on it. While we’re obviously delighted about that, it’s brought some challenges with it, principally around scaling up the team that develops the specification, and supports the implementation community. That direct FHIR team includes a lot of people (>100) playing a variety of roles:

  • Evangelism
  • Requirements gathering
  • Standards design and Consensus building
  • Editing the specification
  • Developing implementation tools and libraries
  • Answering Implementer questions
  • Arranging connectathons
  • Developing Implementation Guides
  • Using FHIR in prototype and production applications

All of these roles are critical, and greatly appreciated. But it’s just not feasible to continue running with a team this size, having the impact it’s having, without some formal arrangements for management and co-ordination in the team. Appointing an HL7 Product Director is a part of that, though more will be required.

HL7 Business Arrangements

Obviously, FHIR is a critical part of HL7’s future business plans. Like any business (HL7 is a business, though a not-for-profit one), HL7 has to do normal product management – continuity, managing, planning, building relationships etc. We’ve been doing those things, but the FHIR Product Director position creates a formal basis for these, and offers HL7 the opportunity to define the formal and informal arrangements around the project.

Product Director Role

Several people asked me exactly what it means for the FHIR project. The position of “FHIR Product Director” is new, so we don’t really know the answers. What I agreed with the HL7 Executive Committee is that I will be accountable for the following:

  • Liaise with all parts of the FHIR community (including committees, HL7 management, stakeholders, members) to ensure continued development of FHIR product and community
  • Work with existing management and governance structures to build FHIR product and community
  • Work with TSC to formalize the role and develop a job description
  • Run the FHIR balloting and publishing process, and ensure business continuity around these arrangements (including documenting FHIR processes and procedures)
  • Work with HL7 and the FHIR community to create the FHIR Foundation (http://fhir.org)
  • Produce a monthly report documenting FHIR Product Director activities, issues and concerns

There’s one item in this list that will be new for a lot of people: the FHIR foundation. I’ll blog about this in the near future.

Generally, from the perspective of the FHIR project, formalising the role of the FHIR Product Director doesn’t really change very much. In terms of formal management, I’ve resigned from the FHIR governance board, and will instead join both the governance board and the management group as a non-voting member in an ex-officio role. Further, a few activities around documenting policies and procedures that hadn’t been getting timely attention will be addressed.

In addition, I’ll be creating a FHIR Product Director blog to address the public side of some of these. I’ll continue to blog here for anything that’s not official Product Director business.

Note: The Product Director is a part time position. I’ll continue to work for my existing customers helping them to integrate healthcare systems, and to make the best use of HL7 and other standards.

Use of CDA Observation.value

CDA has an all important element Observation.value:

cda-observation-snapshot

Observation.value is a really important element because it contains the really key clinical data – laboratory and clinical measurement. It can be any type – any of the CDA types, that is – and it can repeat. So, two questions:

  • What types actually get used in Observation.value?
  • What about repeats – does that happen?

What types actually get used in Observation.value?

We’ve seen the following types get used in CDA Observation.value:

  • PQ + IVL_PQ
  • ST / SC
  • BL
  • INT
  • RTO (RTO_INT_INT for Titres and Trisomy / Down Syndrome risk assessment results)
  • CE / CD / CV
  • TS + IVL_TS (see LOINC for IVL_TS usage)
  • CO
  • ED
  • SLIST_PQ

It’s not that other types aren’t allowed to be used, but these are the ones we’ve seen used; this list may help implementers to prioritise their work.

This type cannot be used: CS

Do repeats get used?

We’ve seen repeats used a few times, for things like Pulse Oximetry. We’ve never seen repeats where they have different types (to me, that sounds like a really bad idea – I think you should not do that).

Thanks to Rick Geimer, Alexander Henket, Diego Kaminker and Keith Boone for input to this one.

#FHIR Implementer’s Safety Checklist

One topic that comes up fairly often when I talk procurers and users of interoperability is ‘clinical safety’. Everyone knows why it’s important, but it’s much harder to pin down what it is, and how to measure it, or how to ‘be safe’. With this in mind, the FHIR specification includes an implementer safety checklist. All developers implementing FHIR should run through the content of this safety checklist before and after the implementation process. But the lack of feedback I get about it suggests to me that not many people read it.

With this in mind, I’ll be asking participants in this weekend’s connectathon in Orlando to fill it out. I’m sure we’ll get comments from that. Here’s the safety checklist, with my comments, but first:

Almost all interoperability developments occur in a limited context with one to a few trading partners, and relatively well controlled requirements. In this context, safety consists of testing the known functionality, but all too often, ignoring all the other things that might happen. However experience shows that over time, new participants and new requirements will creep into the ecosystem and safety features that appeared unnecessary in a well controlled system turn out to be necessary after all. These safety checks below are mostly chores, and are easily ignored, but a warning: you ignore them at your peril (actually, it’s worse than that- you ignore them at other people’s peril).

Production exchange of patient or other sensitive data will always use some form of encryption on the wire.
This is a fairly obvious thing to say in principle, but it’s extremely common to find insecure exchange of healthcare data in practice. FHIR does not mandate that all exchange is encrypted, though many implementers have commented that it should. There are some valid use cases not to use encryption, such as terminology distribution etc. Implementers should check that their systems are secure.

For each resource that my system handles, I’ve reviewed the Modifier elements.
In resource definitions, a number of elements are marked as modifying elements. Implementers are not required to support these elements in any meaningful fashion. Instead, implementers are required to ensure that their systems do not inappropriately ignore any of the possible values of the modifier elements. This may be achieved by:

  • Ensuring that these values will never occur through proper use of the system (e.g. documenting that the system only handles human patients)
  • Throwing an exception if an unsupported value is received
  • Ignoring the element that contains the modifier element (so that the value is irrelevant anyway)

Note that applications that store and echo or forward resources are not ‘processing the resources’. Processing the resources means extracting data from them for display, conversion to some other format, or some form of automated processing.

My system checks for modifierExtension elements.

Modifier Extensions are only seen rarely, but when they exist, they mean that an implementer has extended an element with something that changes the meaning of the element, and it’s not safe to ignore the extension. For safety purposes, implementers should routinely add some kind of code instruction like this:

Assert(object.hasNoModifiers, “Object at path %p has Unknown modifier extensions”)

This should be done for each object processed. Of course, the exact manifestation of this instruction will vary depending on the language. Performing these checks is a chore, so it’s frequently not done, but it should be done for safety purposes. Note that one cheap way to achieve this is to write a statement in the documentation of the application: “Do not send this application any modifier extensions”. Like all cheap ways, this is likely to not be as effective as actually automating the check.

My system supports elements labelled as “must-support” in the profiles that apply to my system.

Implementation Guides are able to mark particular elements as ‘must-support’. This means that although the element is optional, an application must be able to populate or read the element correctly. What precisely it means to do this correctly varies widely, so Implementation Guides must indicate exactly what they mean when marking an element as ‘must-support’, and applications that claim to conform need to do whatever is prescribed.

For each resource that my system handles, my system handles the full Life cycle (status codes, record currency issues, and erroneous entry status). Many resources have a life cycle tied to some business process. Applications are not required to implement the full business life cycle – they should implement what is needed. But systems need to fail explicitly if the life cycle they expect does not match the content of the resources they are receiving

A common and important area where applications fail to interoperate correctly is when records are created in error, or linked to the wrong context, and then must be retracted. For instance, when a diagnostic report is sent to an EHR linked to the wrong patient. There are a variety of ways to handle this, with different implications for the record keeping outcomes. Failure to get this right is a well-known area of clinical safety failure.

The FHIR specification makes some rules around how erroneous entry of resources is indicated. Applications should ensure that they handle these correctly.

My system can render narratives properly (where they are used).
The general theory of text vs data is discussed here and here. Resources can contain text, data or both. Systems are not obliged to be able to display the narrative; they can always choose to process the data. But in many cases, it’s a good idea to offer the user a choice to see the original narrative of the resource (or resources, in many cases), particularly for clinical resources. This might be described as ‘see original document’ in a user relevant language.

The FHIR specification makes no explicit requirements in this regard, since the correct behaviour is so variable. Implementers should judge for themselves what is appropriate in this regard.

My system has documented how distributed resource identification works in its relevant contexts of use, and where (and why) contained resources are used.
Many of the clinical safety issues that arise in practice arise from misalignment between systems around how identification and identifiers work. In the FHIR context, this risk is particularly acute given how easy it is to develop interfaces and connect systems together. Any applications that assign identifiers or create resources with an explicit identity should document their assumptions and processes around this. This is particularly important where there is the prospect of more than two trading partners.

The same applies to contained resources: a system should refrain from using contained resources as much as possible, and where it necessary, document the usage.

My system manages lists of current resources correctly.
One important use of the List resource is for tracking ‘current’ lists (e.g. Current problem list). Current lists present a challenge for the FHIR API, because there’s no inherent property of the list that marks it as ‘current’: there may be many ‘medication lists’ in an application, but only a few(or one)  of them are the ‘current’ list. What makes a list current is it’s context, how it used, not an inherent property of the list. The FHIR API defines an operation that can be used to get a current list for a patient:

GET [base]/AllergyIntolerance?patient=42&_list=$current-allergies

The FHIR specification defines several list tokens for use with this operation but there’s a long way to go before these concepts are well understood and exchangeable. If the system has current lists, it must be clear how to get the correct current list from the system and how to tell the lists that are not.

My system makes the right Provenance statements and AuditEvent logs, and uses the right security labels where appropriate.
Provenance and AuditTrail are two important and related resources that play key roles in tracking data integrity. Provenance is a statement made by the initiator of an update to the data providing details about the data change action and AuditTrail is a statement made by the data custodian about a change made to the data. On a RESTful API, the provenance statement is made by the client, and the AuditTrail is created by the Server. In other contexts, the relationships may not be so simple

My system checks that the right Patient consent has been granted (where applicable).
Patient consent requirements vary around the world. FHIR includes the ability to track and exchange patient consent explicitly, which is a relatively new integration capability. Various jurisdictions are still feeling out how to exchange consent to meet legislative and cultural requirements.

When other systems return http errors from the RESTful API and Operations (perhaps using Operation Outcome), my system checks for them and handles them appropriately.
Ignoring errors, or not handling them properly, is a common operational problem when integrating systems. FHIR implementers should audit their system explicitly to be sure that the http status code is always checked, and errors in OperationOutcomes are handled correctly

My system publishes a conformance statement with StructureDefinitions, ValueSets, and OperationDefinitions, etc., so other implementers know how the system functions.
While servers have no choice but to publish a conformance statement, the degree of detail is up to the implementer. The more detail published, the easier it will be for systems to integrate. Clients should also publish conformance statements too, but there is much less focus on this – but the computable definition of system functionality will be just as important.

My system produces valid resources.
It is common to encounter production systems that generate invalid v2 messages or CDA documents. All sorts of invalid content can be encountered, including invalid syntax due to not escaping properly, wrong codes, and disagreement between narrative and data.

In the FHIR ecosystem, some public servers scrupulously validate all resources, while others do not. It’s common to hear implementers announce at connectathon that their implementation is complete, because it works against a non-validating server, and not worry about the fact it doesn’t work against the validating servers.

Use the validation services to check that your resources really are valid, and make sure that you use a DOM (document object model) or are very careful to escape all your strings

Check for implicitRules.
All resources can carry an implicitRules pointer. While this is discouraged, there are cases where it is needed. If a resource has an implicitRules reference, you must refuse to process it unless you know the reference. Remember to check for this.