Patient Matching on #FHIR Event at HIMSS

In a couple of weeks I’m off to HIMSS at Los Vegas. I’m certainly going to be busy while I’m there (If you’re hoping to talk to me, it would be best to email me to set up a time). Before HIMSS, there’s several satellite events:

  • Saturday: Health Informatics on FHIR: Opportunities in the New Age of Interoperability (IEEE)
  • Sunday: Patient Matching on FHIR event (HIMSS)
  • Monday: First joint meeting between HEART/UMA & FHIR/SMART teams – if you want to attend this meeting, let me know by email (there’s a couple of places still open)

About the Sunday meeting, quoting from the announcement:

Previous work included a Patient Testing Matching Event on this idea was developed at an event in Cleveland, OH on August 14th, 2015 at the HIMSS Innovation Center.  The event covered a tutorial on FHIR along with sessions on patient matching.  A key takeaway from the event was that the healthcare community can advance interoperability by working on a standard Application Programming Interface (API) for master patient index software, commonly used to facilitate patient data matching.

In fulfillment of this vision, we are hosting this second Patient Matching on FHIR Workshop in conjunction with the HIMSS 16 Annual Conference in Las Vegas.  We invite:

─         Algorithm vendors
─         EMR vendors,
─         Developers and standards experts
─         All interested parties

So, here’s passing on the invitation – see you there!

ps. I’ll pass on information about the IEEE event when I get a link.

Possible alternative syntaxes for #FHIR extensions

At the last few HL7 working meetings, the FHIR core team has gathered on Thursday evening for a deep technical session. In Orlando, we talked about various open issues to do with profiling (and then we all went to Howl at the Moon). In Atlanta, we explored alternative syntaxes for extensions, which led to a proposal that we put to a fairly large committee meeting (~50 people), a combined cross-section of FHIR stakeholders in Orlando. That proposal died immediately – it got a very hostile reception, actually. A couple of the participants at the meeting thought that this was a reflection of insider bias, and asked me to present the proposal on my blog so that it gets a wider set of eyes looking at it. So here it is.

Current Situation

Here’s an example resource with several extensions:

<Patient xmlns="http://hl7.org/fhir">
 <id value="patient-example"/>
 <extension url="http://hl7.org/fhir/StructureDefinition/us-core-race">
   <valueCodeableConcept>
     <coding>
       <system value="http://hl7.org/fhir/v3/Race"/>
       <code value="2106-3"/>
     </coding>
   </valueCodeableConcept>
 </extension>
 <extension url="http://hl7.org/fhir/StructureDefinition/us-core-ethnicity">
   <valueCodeableConcept>
     <coding>
       <system value="http://hl7.org/fhir/v3/Ethnicity"/>
       <code value="2135-2"/>
     </coding>
   </valueCodeableConcept>
 </extension>
 <extension url="http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial">
   <extension url="clinicalTrialNCT">
     <valueString value="NCT01647425"/>
   </extension>
   <extension url="clinicalTrialPeriod">
     <valuePeriod>
       <start value="2012-04-01"/>
       <end value="2013-09-30"/>
     </valuePeriod>
   </extension>
   <extension url="clinicalTrialReason">
     <valueCodeableConcept>
       <coding>
         <system value="http://snomed.info/sct"/>
         <code value="254637007"/>
         <display value="NSCLC - Non-small cell lung cancer"/>
       </coding>
     </valueCodeableConcept>
   </extension>
 </extension>
 <extension url="http://hl7.org/fhir/StructureDefinition/patient-birthTime">
   <valueDateTime value="2012-06-07T06:12:45-05:00"/>
 </extension>

This is taken from one of the standard DAF examples, and excludes all the normal patient content (not related to this discussion). We – the core team – are not considering changing how extensions work, only how they are represented. Fundamentally, an extension is a pair: a URL to references a definition, and a value. But actually, on the wire, extensions are a triple: the URL, the value, and the type, so that parsers know how to parse the value without having to find the definition of the extension (and so that extensions can allow a choice of type for the value).

What we wanted to know was whether we could find a better syntax to represent extensions. What’s wrong with the current form? Well, feedback from implementers is consistent: the existing form is verbose, and the identity of the extension – the URL – is in an attribute, which is a step away from where you’d like it to be – in the element name.

Aside: it’s exactly the same issue in JSON as XML. And this blog entry will exclusively show XML, not JSON. That’s not because we don’t care about JSON – we do, greatly – but because as far as we are aware, the JSON issues are the same as XML, minus namespaces (yay!). So other than the namespace hacking option below, the same argument applies to JSON.

Prelude: XML Schema

The current approach to extensions is certainly the optimal approach to extensions if you want to use XML schema to describe the general wire format. As long as we want to support schema so that you can generate working code from the schema, then there’s no discussion to be had – we’re going to be sticking with the current extension format (at least in XML).  This whole discussion presumes that we might change that if there was compelling advantage from dropping it. And if there is an advantage, it would be here.

Option #1

So the first option we considered looked like this:

<Patient xmlns="http://hl7.org/fhir" definition="http://...qicore-patient">
 <id value="patient-example"/>
 <us-core-race>
   <coding>
     <system value="http://hl7.org/fhir/v3/Race"/>
     <code value="2106-3"/>
   </coding>
 </us-core-race>
 <us-core-ethnicity>
   <coding>
     <system value="http://hl7.org/fhir/v3/Ethnicity"/>
     <code value="2135-2"/>
   </coding>
 </us-core-ethnicity>
 <clinicalTrial>
   <NCT value="NCT01647425"/>
   <clinicalTrialPeriod>
       <start value="2012-04-01"/>
       <end value="2013-09-30"/>
   </clinicalTrialPeriod>
   <clinicalTrialReason>
     <coding>
       <system value="http://snomed.info/sct"/>
       <code value="254637007"/>
       <display value="NSCLC - Non-small cell lung cancer"/>
     </coding>
   </clinicalTrialReason>
 </clinicalTrial>

In this scheme, an applicable profile is declared on the root. The profile defines the wire format names for the extensions. In order to parse this, a parser needs to access the definition so it can parse the content. There’s several problems with this approach:

  • if you can’t get the definition, you can’t parse the (unknown) content
    • This can be an issue of networks, but also time. (E.g. Looking at a record 20 years later). It would essentially force systems to store the definition with the data
  • you have to pick one definition – one profile, and fall back to the old extension syntax for extensions defined in other profiles (and mixing profiles is a common thing to do)
  • if you do this, it’s basically a ‘local syntax’, and you have to have perimeter exchange methods, or use a reference implementation to read the content. The practical ramifications of this are less than ideal

Note: The idea of perimeter exchange methods comes from the idea that a group of implementers could form their own private club, and use FHIR just among themselves. In this scheme, they can assume that they know each other’s secrets, and take all sorts of short cuts. But as soon as resources leak outside their little club (as will almost certainly happen), the secrets won’t be known. Hence, on the perimeter of the club, the secrets have to be unwound. In this case, the secret is the ‘known’ definition profile.

In effect, then, this would be a local optimization of FHIR – green FHIR, if you want. That’s fine, but that’s not the solution we’re looking for.

Option #2:

<Patient xmlns="http://hl7.org/fhir">
 <id value="patient-example"/>
 <us-core-race xmlns="http://hl7.org/fhir/StructureDefinition/">
   <valueCodeableConcept>
     <coding>
       <system value="http://hl7.org/fhir/v3/Race"/>
       <code value="2106-3"/>
     </coding>
   </valueCodeableConcept>
 </us-core-race>

This option misuses the namespace technique in xml to inline the extension name (for JSON, you’d just inline the name by itself). We didn’t seriously talk about this for very long. The biggest problem is that names are variable because there’s no imposed uniqueness on them. Unless you ban using name clashes (which we have no ability to do, and we wouldn’t have any structure that we could use to prevent implementers getting caught between two uses of the same name, the names have to change depending on the local context. This is also the form that json implementers didn’t like (and, btw, there’s no way to deal with modifiers). This option just wasn’t a good idea. Namespaces aren’t the problem, and they’re not the solution either.

Option #3:

<Patient xmlns="http://hl7.org/fhir">
 <schema>
   <item name="us-core-race" 
     url="http://hl7.org/fhir/StructureDefinition/us-core-race" type="CodeableConcept"/>
   <item name="clinicalTrial" 
     url="http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial">
     <item name="clinicalTrialNCT" 
       url="clinicalTrialNCT" type="string">
     <item name="clinicalTrialPeriod" 
       url="clinicalTrialNCT" type="Period">
     <item name="patient-clinicalTrialReason" 
       url="clinicalTrialNCT" type="CodeableConcept">
   </item>  
 </schema>
 
 <us-core-race>
   <valueCodeableConcept>
     <coding>
       <system value="http://hl7.org/fhir/v3/Race"/>
       <code value="2106-3"/>
     </coding>
   </valueCodeableConcept>
 </us-core-race>
 <clinicalTrial>
   <clinicalTrialNCT value="NCT01647425"/>
   <clinicalTrialPeriod>
       <start value="2012-04-01"/>
       <end value="2013-09-30"/>
   </clinicalTrialPeriod>
   <clinicalTrialReason>
     <coding>
       <system value="http://snomed.info/sct"/>
       <code value="254637007"/>
       <display value="NSCLC - Non-small cell lung cancer"/>
     </coding>
   </clinicalTrialReason>
 </clinicalTrial>

This form starts with a manifest that declares the names, types, and urls for all the extensions. Then you just use the name on the wire.

The ramification of this is that you have to iterate the content twice when you write, so the schema can be complete upfront – and the names are still variable too. It’s also really hard to build with xslt or equivalent – you need serious logic to build the schema on the fly. This would impose that serious logic on anyone writing resources that included extensions. Also, if you were migrating content from one resource to another, you’d have to track the manifest, and potentially rename everything. And you could never use stable names for extensions in your code- you’d still end up accessing extensions by their URLs

Summary:

Well, by the time we got here, we were a bit glum. We hadn’t come up with any thing that was remotely a candidate alternative. None of these approaches represents a net benefit of the current approach – while they look good (or, at least, the extensions look better), the practical ramifications for readers and writers are unhappy.

Final option:

The final option we considered was radically different to the others. Here’s what it looks like:

<Patient xmlns="http://hl7.org/fhir">
 <id value="patient-example"/>
 <birthTime value="2012-06-07T06:12:45-05:00"/>
 <active value="true"/>
 <name>
   <use value="official"/>
   <family value="Lerr"/>
   <given value="Todd"/>
   <given value="G."/>
   <suffix value="Jr"/>
 </name>
 <telecom>
   <system value="phone"/>
   <value value="(555) 555 1212"/>
   <use value="work"/>
 </telecom>
 <telecom>
   <system value="email"/>
   <value value="person@example.org"/>
   <use value="work"/>
 </telecom>
 <gender value="male"/>
 <birthDate value="2012-06-07"/>
 <deceased type="boolean" value="false"/>
 <address>
   <use value="home"/>
   <line value="123 North 102nd Street"/>
   <line value="Apt 4d"/>
   <city value="Harrisburg"/>
   <state value="PA"/>
   <postalCode value="17102"/>
   <country value="USA"/>
 </address>
 <us-core-race type="CodeableConcept" list="true">
   <coding>
     <system value="http://hl7.org/fhir/v3/Race"/>
     <code value="2106-3"/>
   </coding>
 </us-core-race>
 <us-core-ethnicity type="CodeableConcept">
   <coding>
     <system value="http://hl7.org/fhir/v3/Ethnicity"/>
     <code value="2135-2"/>
   </coding>
 </us-core-ethnicity>
 <clinicalTrial>
   <clinicalTrial.NCT type="string" value="NCT01647425"/>
   <clinicalTrial.period type="Period">
     <start value="2012-04-01"/>
     <end value="2013-09-30"/>
   </clinicalTrial.period>
   <clinicalTrial.reason type="CodeableConcept">
     <coding>
       <system value="http://snomed.info/sct"/>
       <code value="254637007"/>
       <display value="NSCLC - Non-small cell lung cancer"/>
     </coding>
   </clinicalTrial.reason>
 </clinicalTrial>
</Patient>

You can tell that we liked this enough to consider it seriously because we went ahead and filled out the rest of the resource.

Note that there a second thing going on in this resource: we changed the way that choice types work. Instead of using value[x], and appending the type name to the element, we used a type attribute (of course, in practice, in spite of the difficulties it presents, if we actually did this, we’d use xsi:type in the XML. In JSON, you’d have a property named “type” or “dataType”. This is a basically separate notion, but is required to eliminate the “value” element.

This is a very nice representation for extensions. Sweet. But in order to make this work – e.g. to avoid name clashes – we would need a global registry that contained a list of wire format names, along with, for each name, the following information:

  • name – the name in the instance
  • url – the canonical url for the extension
  • modifier – whether this is a modifier
  • list – whether this is repeats or not
  • type[] – what types this name can be
  • path[] – where the name can appear
    • children[]
    • name
    • type
    • list
      • children[] (etc)

And this global registry would need to be very carefully curated so that the names are useful, and remain useful as it grows. That’s a tough challenge.

Implementations would take one of two approaches to reading the instances:

  • download a snapshot of the global registry occasionally, and use that snapshot when reading and writing resources (e.g. the reference implementations would do this)
  • download a snapshot of the global registry at design time, and generate schema / code / something etc for whatever tool/code reads and writes the resources

So, if we established such a registry, and made general purpose implementations (the ones that have to deal with multiple profiles) more complicated, we’d have simpler instances, and it would be easier for single purpose applications. Is that worth it? Well, that’s the question we put to the combined committee group at Orlando. Nearly everyone in the group – except for a small but keen minority – was strongly against this option, for the following reasons:

  • it complicates general purpose applications
  • Although most individuals start with single purpose applications, most will quickly migrate to multi-purpose applications (or even to general purpose applications)
  • Implementers like having a single general purpose schema.
  • Running the registry well – particularly with a good SLA on turn around – would be onerous and expensive

ok. So perhaps that group over-represented the general implementers, and didn’t represent the single-purpose implementers – though the room was weighted towards vendors and consultants who support single-purpose implementers extensively, so it possibly wasn’t as unbalanced as it first looked. So here’s a write up of the discussion so that participants not in the room can consider and have their say.

p.s. My own opinion is that I’d much prefer not to have the registry, since running it would be my concern. And it doesn’t sound like fun. Actually updating the reference implementations to use the global registry would be straight forward, but it does introduce a step to manage – downloading the latest definitions. I think it would be hardest for server authors who don’t use the reference implementations – sufficiently hard that I wonder whether it would become infeasible to write servers without the reference implementations. So in the end, my personal preference is to keep things as they are.

 

Example Batch Requests for Patient Summary (#FHIR)

Andy G from Mitre submitted this gForge task:

It is currently difficult for a FHIR client to create a summary display for a patient. For example, if a application wanted to display demographic information, encounters, vital signs and a problem list, medication list and allergies, it has the following choices:

1) It could make multiple requests to the FHIR server. It could request the Patient resource and then make repeated FHIR search requests against all of the different resource types it needs.

2) It could use the $everything operation. This will likely return more information than what is needed. Yes, it can be filtered by time, but more likely, the desire is to filter by data type.

3) It could perform a search on the Patient resource and use _revinclude to pull in additional resources. There appears to be no capability to filter the reverse included resources, which will almost certainly return more information than desired. In the pervious example, a client looking for vital signs would reverse include Observations. This could create a flood of information.

I would suggest modifying the $everything operation, or creating a new operation that allows for more advanced filtering of what is returned. One suggestion would be to add a resource parameter to the $everything operation. That, in conjunction with the time bounds would go a long way towards solving this issue.

Indeed, that’s an interesting problem. After discussion, we found that a batch operation was the best outcome, so Andy kindly contributed a couple of examples:

  • meds_and_allergies – Retrieve a patients medications, allergies, problems and immunizations (e.g. the Australian PCEHR shared health summary)
  • simple_summary – Retrieve a patient’s conditions, medication statements and blood pressure readings since a given date

And to help, I’ve attached my server’s response, based on the examples in the specification:

We plan to add these examples to the specification in the future.

 

Question: #FHIR Common Search Parameters

Question:

I am working on fhir based rest server. I have already implemented create, delete, read, update, and history services. I am working on search service and i have some difficulties to understand what exactly do parameters mean especially common parameters. For example _text,_content,_list,_query. Can you give me more specified examples please?

Answer:

_text:

GET [base]/Condition?_text=(bone OR liver) and metastases

This example from the specification shows how you could search the xhtml content of the narrative for the word ‘metastases’ and either ‘bone’ or ‘liver’. The expectation is that your server will pass the narrative to an indexing engine (typically, either Lucene, Solr, or Microsoft SQL Text Indexer) and that when a search specifies the _text parameter, the parameter value will be passed to the search engine as is. The trick is integrating the search engine with the other search parameters, but solving that is out of scope for my blog.

_content:

This is nearly the same as the _text resource, except instead of the narrative, it searches the entire text of the resource – that is, the xhtml and all the primitive values. You have to assemble this yourself somehow and pass it to the search engine. I don’t think many implementers have done this one.

_list:

This is a short cut to allow you to search for resources that are in some list. There’s 2 main use cases for this – when a list is being used to track an ad-hoc selection of resources, such as a clinically interesting patient list, the _list parameter lets you search through only the items in that list. The other use is for EHRs or other clinical systems that maintain ‘current lists’, such as ‘current medication list’ or ‘current problem list’ – a way to search those current lists only.

_query:

This is for when the server wants to define it’s own search that works differently to the normal search. If the server sees a _query parameter, it cannot ignore it, since the parameters may not have the normal meaning. When a server defines it’s own kind of query, it can use the rest of the parameters however it wants. The FHIR specification defines one of these, for MPI Search

Right-To-Left scripts in #FHIR

Today, I’m at Linux Conference Australia. I watched a hysterically funny and very interesting presentation by Moriel Schottlender on using Right-To-Left scripts, such as Hebrew, Arabic, Farsi, etc:

browsers have problems when deciding what to do when languages are mixed up, and that, my friends, is a recipe for really weird issues when typing and viewing bidirectional text.

Check the full presentation. And yes, Moriel showed us some really confusing stuff. She kept showing images like this:

This, btw, is your mind trying to process RTL issues (and how could I not post that image?). Moriel has a web site demonstrating some of this stuff (including the piece de resistance, an animated bmp).

Anyway, after the presentation, I asked Moriel whether she had any thoughts about RTL use in a RESTful interface (say, maybe, FHIR). She didn’t have any strong experience, but a combination of her presentation, and her comments after, led to the following advice:

  • If you’re using RTL script entirely, that should be pretty straight forward. The framework of a resource is all LTR ASCII, but the contents of the string primitives are RTL. That works fine
  • The tricky bit is where you mix scripts – e.g. an Arabic word mixed in with an english sentence

Actually, that’s not at all an unusual idea. You can see an example of this here on Wikipedia. And in a clinical environment, it would be a typical thing to happen in somewhere like Saudi Arabia, with a lot of foreigners working in the healthcare system, and mixing English and Arabic. You can watch Moriel’s presentations for fun with left, right, parentheses etc, and see how tricky that could be. Anyway, the basic advice is:

Anywhere you mix LTR and RTL scripts, make sure you use Unicode control characters to mark the edges of the direction changes.

And one more conclusion I drew:

  • There’s little prospect we’ll ever publish an IG that makes sensible use of RTL content

If anyone has experimented with RTL content in FHIR – I’d love to hear about it: we want to support that properly.

p.s. I’m here at LinuxConf to talk about the FHIR community as an open source project.

Question: #FHIR _format parameter

Question:

The FHIR specification says:

Servers SHOULD support the optional _format parameter to specify alternative response formats by their MIME-types. This parameter allows a client to override the accept header value when it is unable to set it correctly due to internal limitations.

If both _format and accept headers are present with valid but different values, which of them should take the precedence?

Answer:

_format is definitely an override, and always takes precedence if it’s present. It’s explicitly provided for where the user doesn’t have access to the Accept: header, but needs to specify what type to return. Typically, this is a user using a browser manually, or an XSLT web call, though I’ve heard of a few other cases.

Question: Entering the #FHIR Bandwagon

Question:

HL7 v1 came first, followed by V2, followed by CDA, V3. For newer entrants into Standards and Interoperability is the central dogma of S&I is something like Learn V2 first, then CDA, then V3 and then FHIR and then SMART on FHIR and then Newer or a person can just straightaway buy an FHIR textbok or Collect all FHIR blogs at one place and start reading from scratch?

Answer:

V2, CDA, FHIR+Smart on FHIR are all different approaches to solving various healthcare interoperability problems. If you’re deeply invested in the standards process, then learning all of v2, CDA, and FHIR will give you deeper perspective about what has and hasn’t worked, and what ideas last across the various specifications. But if you’re just solving a particular problem, then you just pick one, learn it, and give into the job.

Which one to learn? 

  • Actually, this is simple. If you have to use one, because of legal requirements, or because your trading partners have already chosen one – that’s by the far the most likely situation – then you don’t have to decide. Otherwise, you’d use FHIR

How to learn? From a previous post, these are the books I recommend:

None of these cover FHIR. But, in fact, Tim invited me to join with him for the forthcoming 3rd edition of his book, to cover FHIR, and this should be available soon. In the meantime, as you say, there’s the FHIR blogs.

Question: HL7 v2 message processing rules

Question

I have a question on patient registration message A04. We process the A04 message in the following way:

When our system receives A04 for processing, we contruct a QBP and send to MPI and wait for an RSP message response from the MPI. Based on the RSP response we either register the patient by sending an AA or reject by sending an AR.

We notice that sometimes this process may take up to 45 minutes to complete and within this time we receive mpi updates for this patient.

If our system received mpi updates for this patient while this patients registration is in process

  1. should we return patient not found as patient is not registered yet.
  2. should we Wait for the patient registration to complete before processing mpi update message.

Is the above requirement in any of the hl7 document?

Answer:

No. there is no specific rules about stuff like this in the base HL7 v2 standard. You have to get specific agreement on a site to site basis. Some specific national or vendor implementation guides do include specific messaging processing rules of this nature, but I’m not aware of any implementation guide that’s relevant to your question.

So you’ll have to make a decision based on customer desires. 45 minutes does sound like a really long time – that’s the kind of delay that clearly calls for business rules, and these are going to vary from installation to installation.

#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.