Groups of patients in FHIR

I was approached by one of the Dev teams here at Orion Health for some help in ‘FHIR-enabling’ a patient selection service that they have been asked to build. My initial reaction was that we could model this directly as a restful query against /Patient, but after talking to them, the requirements were a bit more complex.

Read more of this post

Connectathon 7: A Dummies Guide

As Grahame has said, the planning for the 7th FHIR connectathon to be held at the September Working Group Meeting in Chicago is well under way. This time we’ve got 4 separate tracks (you can check the link for the details), but in this post let’s have a look at track 1 – the Patient track.

This is intended to be a simple track for those new to FHIR – a way to get your feet wet (so to speak) and show just how simple basic interoperability with FHIR really is. You do need to write some code, but given the tools available these days, that’s not hard to do, so the barrier to entry is pretty low (and remember, the FHIR test servers are always available so you can do the basic learning in the privacy of your own home before you come!)

Using FHIR is actually made even easier by using one of the freely available client libraries. There are a number of them, but the 2 most well known are the .net library (from Furore – one of the earliest companies to support FHIR) and a Java one from the HAPI team – who have had a well regarded library for HL7 version 2 for many years.

In this post I’m going to use the .net libraries – but the java one will work just as well – in fact the two libraries (not co-incidentally) share a common approach.

I’d like thank my colleague Peter Jordan from HL7 New Zealand  for the code snippets in this post – I’ve adapted them a bit so I’ll take responsibility for any errors!

You’ll probably want to start with a copy of Visual Studio Express (which is free), so down load the version that suits your purpose (ie whether you’re writing a web or a desktop application).

You’ll need to download the .net FHIR libraries – they are in github, but the easiest way to get them is by using NuGet and searching for the FHIR libraries there. (The github reference has more information including links to documentation and a NuGet reference)

Now, you can create a project in Visual Studio. (btw I’m not an expert in Visual Studio – and as I use a mac it’s a bit fiddly for me to use it so this is not a step by step guide – there are a ton of tutorials on the web so it should be easy to get more detailed instructions if you need them). An alternative you can use is Xamarin which does run on the Mac.

First you need to include references to the c# FHIR libraries (and a couple of others)

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using Hl7.Fhir.Model;
using Hl7.Fhir.Rest;

In order to use the library, you first instantiate a new FhirClient object, passing in the base URL of the FHIR Server. Then, you can call the required methods on that library which will issue the required REST calls – and throwing exceptions when errors occur.

In the example below, the FhirClient is initialized against the Orion Health ‘Blaze’ server, and the Conformance resource read and saved to a file.

var client = new FhirClient(@"https:/fhir.orionhealth.com/blaze/fhir/");
var confStat = client.Read<Conformance>("metadata");
string TestFile = "c:\temp\" + Guid.NewGuid().ToString() + ".html";
File.WriteAllText(TestFile, confStat.Summary);

So how do you find a patient? Well…

var client = new FhirClient(@"https:/fhir.orionhealth.com/blaze/fhir/");
List<string> searchCriteria = new List<string>();
searchCriteria.Add("name='eve'");
var bundle = client.Search<Patient>(searchCriteria.ToArray());
foreach (ResourceEntry entry in bundle.Entries) {
   // create a Patient Object from the Entry Resource
   Patient patient = (Patient)entry.Resource;
   // ... do something with patient, it's a c# object representing the patient resource ...
}

You want to create a new patient?

var client = new FhirClient(@"https:/fhir.orionhealth.com/blaze/fhir/");
// create new Patient object
Patient newPat = new Patient();

// create identifier list item and add it to the new patient
Uri uri = new Uri("http://nhi.health.nz")
Identifier id = new Identifier { System = uri, Value = "PRP1660", Label = "NHI" };
newPat.Identifier = new List<Identifier>();
newPat.Identifier.Add(id);

// create a human name list item and add it to the new patient
List<string> famName = new List<string>();
famName.Add("Jones");
List<string> givName = new List<string>();
givName.Add("Indianna");
HumanName hn = new HumanName { Family = famName, Given = givName };
newPat.Name = new List<HumanName>();
newPat.Name.Add(hn);

// add DOB and gender
newPat.BirthDate = "1955-12-16";
newPat.Gender = new CodeableConcept { Text = "M" };
client.Create<Patient>(newPat);

So there you have it – that’s half of the scenario done for you! How hard can it be?

See you in Chicago…

FHIR XDS: revisiting the patient identity.

While at the HINZ conference this year, I was at dinner with Grahame and ‘Friendly FHIR’ (your identity is safe with me), and we were talking about the roles of the Identity Source and XDS Registry in the context of a FHIR XDS implementation. In previous posts I had indicated that the Identity Source could simply expose a FHIR Patient endpoint – and that is still an option for general use – but in the case of the XDS Registry, Grahame pointed out 2 issues with that approach:

  • If the XDS infrastructure is heavily used, then the load on the Identity Source is going to be high
  • Merged patients are an issue because DocumentReference resources in the registry will continue to have references to patients that have been merged with another and it needs to return all references to all merged patients when responding to a query for a single patient.

So, the registry really does need to maintain it’s own store of patients – though this is really a specialized ‘cache’ that is only updated by the Identity Source. This also means that there is really no need for a Document Consumer to access the Identity Source directly – at least in the XDS context – which is a bonus.

We’ve talked before about how FHIR represents merged patients (Actually, just checking the specs I note that there is now a link type property that must be set to ‘replace’ to indicate the merge), so I won’t repeat that here, but it is worth thinking about how this could all work in the context of an Identity Source needing to update an XDS Registry.

The requirement is that when there are changes to patient information at the identity source, then that needs to be communicated to the XDS registry somehow. We don’t need all the patient details all of the time – the more we store then the greater the volume of updates –  but we probably want the ID, the links, the identifier information and the basic name/Date of Birth/Gender stuff. We would want to be notified about:

  • new patients
  • changes to the patient data we are storing
  • any merges

The XDS registry then needs to maintain an internal data store of some sort that maintains those links between patients so that when a document consumer queries the registry, all the DocumentReference resources for that patient and any patients merged to it are returned as well. (And note that each DocumentReference resource will continue to refer to the Patient it was associated with at creation time – it is the patient that is merged and not the other resources that refer to it).

There are a couple of ways we could do this:

  • Either the Identity Source could push changes to the XDS registry as they occur (a ‘push’ model)
  • Or the Registry could periodically request changes from the Identity Source. (a ‘pull’ model).

Lets consider the push model first.

When the Identity Source merges a patient with another, there are 2 Patient resources to change:

  • The Primary resource (the one you want to keep) has a reference to the secondary resource (that is being replaced) with a link type of ‘replace’.
  • The Secondary resource has a link back to the primary (also with a type of replace) and has it’s ‘active’ property set to false.

As these really need to be managed as a transaction, then the Identity Source places the two resources in a bundle and either:

  • Posts it to the root of the XDS registry
  • Or (and this is probably more explicit) the XDS registry exposes a service (maybe /service/patient/merge) that takes the bundle of resources

In either case, the registry updates its data store. It might return an OperationOutcome resource to indicate the outcome.

So that is the push from the Identity Source to the XDS registry – how would the pull model work?

Well, because FHIR is built using standard internet type technologies, there’s a pre-existing standard that is intended for communicating changes and updates between systems, and that is the Atom feed – which we’ve seen used as the bundling mechanism when we want to move multiple resources around.

In this use, we’re implementing a ‘pub/sub’  architecture where the client (the XDS registry) subscribes to a feed of changes published by the Identity Source. Reviewing the spec, we note that the history operation allows a server to publish changes for a specific resource, a type of resource, or all resources on that server. In our use case, we’d go for the middle option – we want a feed from the Identity Source that publishes all changes for any Patient resource.

So what happens is something like this:

Periodically the XDS registry issues a GET request to the Identity Source like this:

GET /identityServer/Patient/_history?_since=<dateLastQueried>

This will return a bundle containing all the changed resources since the last request. The registry can then process the Patient resources in that bundle and update it’s internal data store as required.

So which pattern to choose? Well, that depends on your implementation.

The ‘classical’ XDS way is the push from Identity Source to Registry, and that is probably the simplest  (though in practice you might want to put an integration engine in the middle so the Identity Source doesn’t need to be concerned with communication issues – and could support other systems that maintain patient caches).

However the pull feed option might be useful if there are multiple clients needing updates, of if that technology is already supplied by the Identity Source.

Hopefully that finishes off XDS stuff for a while, because I’d like to start thinking about FHIR documents…

Using FHIR to expose a Patient Identity Registry lookup service – part 1

Now that we’ve covered a bit of the theory and background to FHIR, let’s look at a concrete example of where we might apply these principles. The Use Case we’re going to look at is to provide a REST based lookup service in front of a patient Identity Server.

Some notes before we start:

  • We assume that there is already an existing registry that we are providing a front end for. It handles all the assigning of identifiers, managing merges & un-merges and such like. In other words this is a read-only service (at the moment).
  • Every patient will have a single identifier (although that may change over time). We’re going to assume that this has national scope so we’ll call it a National Health Identifier – or NHI. This won’t apply in all domains of course, but it simplifies the issue for now.
  • So that we can create full URL’s, we need a server name. We’re also going to need some namespaces (more on that shortly) so, in a nod to Dilbert, we’re going to assume that the country we are building this for is elbonia.

The scenarios we will support are:

  • Retrieving a list of matching patients based on criteria such as Name, Gender, Date of Birth and such like – what you’d use if you were wanting to find someones NHI.
  • If we do have an NHI identifier, retrieving the resource (or resources) that have that NHI.

This is going to be a rather long post, so I’ll split it into 2 separate posts:

  • In this one we’ll talk in some detail about the resource, and cover the special importance of the datatype of the properties of the resource, and how to manage merging where we have duplicates.
  • In the second post, we’ll talk about the behavior of our registry service.

First, which resource to use? Well, the obvious candidate is the patient resource. It has the base demographics we need, plus an identifier (in fact multiple identifiers).

This is the first time that we’ve looked at a resource in any depth so it’s worth spending a bit of time on it. Each resource has a specific page in the spec, and each page has a number of sections:

  • A description of what the resource is intended to represent. The size and content varying according to the complexity of the resource.
  • A UML representation of the resource – a class diagram – containing the core properties with the property name, multiplicity and datatype. The datatype of the property is especially interesting as it can range from a single string to a more complex structure – an object in its own right. We will see more of this structure as we explore the patient resource, but it’s important to realize that the datatypes are the same for all resources.
  • A XML representation of the properties with the same information as the class diagram – with the addition of a brief description of each property. The name is hyperlinked to a formal description, and the datatype/s hyperlinked to the detailed description of the datatype. (Many resource properties allow multiple datatypes – you choose which one is the most appropriate when creating – or updating – the resource).
  • The terminology bindings for those properties that are bound to a code set or terminology.
  • Other constraints – generally those that cannot be represented by XSD schema.
  • Any other comments of note.
  • The specific search parameters defined for that resource.

Each resource will also have a specific XML schema and schematron file – these can  all be downloaded from the spec in a single zip file.

Of the main representations, I find the XML format the easiest to follow, so let’s look at some of the properties for the patient resource (at least those that have special points to discuss).

Patient.identifier

First up is the identifier property. This will hold our NHI identifier (though it can have others as well – e.g. a drivers license). If you look at the XML, you will see that the datatype is also called Identifier (it is in a green font, and is a hyperlink). Click on that link – it will take you to the description of what an identifier datatype is, and what properties it has.

There are a few that are of interest to us (and note that it is extensively hyperlinked to get more information as you need it).

  • The use property describes how this identifier is going to be used. We’re the official registry so ‘official’ seems most appropriate – but we note with interest that ‘temp’ or temporary might also apply in some scenarios.
  • The label is for humans – so let’s use NHI for that
  • The system needs to define the namespace within which the actual identifier value is valid – and unique. It’s a URI, so let’s base it on the address for the Elbonian Ministry of Health – so we get http://nhi.moh.elbonia.govt (Note that this doesn’t have to be a ‘real’ address, so long as it is globally unique).
  • The actual value of the identifier – eg PRP1660, or whatever we choose to use. FHIR makes no comment about the format of the identifier – that’s up to the implementation. We might decide, for example, to incorporate a checksum digit to help with error checking.
  • The period over which the identifier is valid. That could be useful if we have to ‘retire’ an identifier, but for now we’re going to assume that if our service returns an identifier it is currently valid and is intended to remain so, so we won’t use it for now.
  • We could use the assigner to give more data about the organization that maintains the registry.

Patient.name

Next property is the name of the patient. It has a datatype of HumanName, and contains properties such as family name, given name and use. There is also a text property that can be used for the complete name. Whether the text property and/or the individual items are used is at the discretion of the resource author, although profiles can be used to control usage to some extent.

This is a good place to mention that you could – if you needed to – use extensions to add other properties to datatypes. For example, you might want to add a salutation to the name. I’ll talk more about extensions in another post.

Patient.gender

This has the datatype of codeableconcept. Codeableconcept is an incredibly important datatype as it represents coded data and is extensively used within FHIR. It deserves its own post, so for the moment I’ll just point out that there is a particular set of codes that can be used here (if you look in the terminology bindings section you will see a reference to the set).

Patient.link

Patient identification is a critical part of recording healthcare information – and one that is prone to error, for example a single person being registered multiple times. The link property in FHIR us used to assert that two (or more) patient resources are, in fact the same person.

And now is a good time to describe the difference between resource ID and the identifier.

As described in previous posts, all resources have an ID – the resource ID – which  along with the server and resource type comprise the unique URI of the resource. The resource ID cannot change, and so something like the registry identifier is not a good candidate for the resource ID because it can change. You should think of the resource ID like a database primary key – let the server assign it, and attach no semantic meaning to it. (A client can also assign the ID – though you need to be careful if doing this).

An example might help.

Suppose you create 2 patient resources. One has the ID of 100 with an identifier of PRP1660, and the other has an ID of 200 with an identifier of WER4568. After storing clinical data against these resources (and using the resource ID as the linking mechanism) you discover that they are actually the same person. You determine that the identifier you wish to keep is PRP1660, and wish to ‘shift’ all the records currently pointing to WER4568 to point to PRP1660, and inactivate WER4568. You cannot (or should not) change the ID in the resource reference of all the other resources that currently point to WER4568. The correct action is to set the link of each patient resource to the other one (thus they point to each other), and set the active property of WER4568 to false. This should be done in a transactionally safe manner.

In this way it is obvious to any subsequent view of the record what has happened, and which is the correct resource.

Before merging

Identifier ID Active link
PRP1660 100 True (or absent)
WER4568 200 True (or absent

After merging:

Identifier ID Active link
PRP1660 100 True (or absent) 200
WER4568 200 False 100

(Note that the link is actually a resource reference, and so has a slightly more complex format than a single string)

And while we’re talking about errors, what do you do if – rather than having duplicated patients, you just set the subject link of another resource (say a condition resource) to the wrong patient? Well, that is what the versioning facility in FHIR is for – you create an updated version of the condition resource with the ID of the correct patient resource, thus maintaining the history of change.

The other properties are all important but I won’t talk any further about them here, as their meaning and use should be evident from their description and from the discussion above.

It’s also worth pointing out that in a real scenario, if there were properties that we needed and weren’t in the FHIR specification (for example the reason for a merge, or to store realm specific information like iwi), then we can always use the extension mechanism to add them.

Well, that is all we’re going to say about patient – next post will describe how we use the patient resource in our registry REST service