Decomposing a FHIR document

Scenario 2.3 of Connectathon talks about a server ‘decomposing’ a FHIR document. This is another of those huge topics, as it is all about using the document as a ‘carrier’ for information that is used by a recipient to update their own data stores, rather than simply storing it as a ‘blob’ to be displayed to a user on request.

The issue is not so much a technical one – that’s relatively straightforward (though one of the more complex in FHIR) – but rather relates to the purpose of a document as a ‘summary at a point in time’ – or as a ‘snapshot’, rather than a mechanism to ‘transfer state’.

Read more of this post

Server processing of FHIR documents: Connectathon

In this post we’re going to think a bit about how the server might process a document that it receives. This is a massive topic, and certainly not one that can be covered in a single post – or by any one individual! Apart from anything else, there are lots of different possibilities – all legitimate in specific circumstances.

This is an important concept for FHIR – it doesn’t seek to drive any particular design or architecture – rather it attempts to support how data is moved around now, and how it may be done the future. It’s up to individual implementations to decide the details, but using common ‘building blocks’.

Read more of this post

Creating a FHIR document for the January Connectathon

I had intended to talk in some detail about the Composition resource next, as this is one of the key resources for a FHIR document, but because the January connectathon is getting close I’m going to do a series of posts to directly support people attending connectathon, and wanting to experiment with the document track. I’m planning 4 posts in this series:

  • How a client would create a FHIR document (incidentally for the remainder of this series, I’m going to refer to a FHIR document just as  ‘document’, so when you see this, I’m NOT talking about CDA. Later posts will talk more about the relationship between the two).
  • How a server could process a document. There are a few possibilities…
  • How to find the document on the server later, and render it to the client.
  • A wrap up on the Composition resource and anything else left over.

I do intend to spend a lot more time on FHIR & CDA, but this should at least cover the basics.
Read more of this post

FHIR: meet #CDA

CDA (Clinical Document Architecture) is undeniably the most successful HL7 version 3 standard. It’s being used very widely around the world for representing clinical data, and is one of the core standards for many jurisdictions – like Meaningful Use in the US. Obviously, if FHIR is to succeed, then it needs to have some way of doing what CDA does now (and including all the good thinking that has gone into CDA).

Another reason to start thinking about CDA is that the next FHIR connectathon at the January Working Group Meeting next year is going to have FHIR documents as one of the themes, so it makes sense to start thinking about how this all works.
Read more of this post

More thoughts on notifications in FHIR

I’ve been thinking a bit more about notifications since my last post about wanting to alert the patients usual GP (General Practitioner) that there is a document generated as a result of an ambulance visit for them to review. In particular, I’ve been thinking about other scenarios where a sender not only wants to inform a recipient that there is a document for them, but also that there is some action that needs to be performed for the patient. There’s a relationship of some sort to Tasks as well…

Looking at some sample scenarios where the recipient is a GP:

  • The ambulance visits a patient after a fall and delivers them to hospital where they are admitted. The notification to the GP is just an FYI (for your information), and there is no expectation of action.
  • The ambulance visits a patient with asthma and nebulizes them. They do not need to go to the hospital, but should be reviewed the following day.
  • A hospital discharges a patient having started them on warfarin. The GP is requested to repeat an INR in 5 days and adjust the dose if required.
  • A patient visits a private ‘after hours’ service with a lacerated hand. The service sutures the wound and asks the GP to review the patient in 5 days to remove the sutures.
  • A patient is seen by an out-patient clinic and their anti-hypertensive medication adjusted. The GP is requested to monitor the Blood Pressure to endure that they don’t become hypotensive.
  • While in hospital for a routine appendicectomy, an elevated Glucose blood result is noted. The GP is asked to follow up to investigate the possibility of diabetes.
  • A District Nurse visits a patient to dress a wound, and notes that the Blood Pressure is high.

In many (but not all) of these scenarios, there is an expectation by the sender that the recipient GP is going to do something. So in those cases the sender really needs some way of knowing whether:

  • The GP has received the request and will perform the requested action
  • The GP has received the request and will not perform the requested action (maybe it was the wrong GP)
  • The GP never received the request at all.

(I appreciate that this overlaps with some other important concepts like ‘Transfer of Care’, ‘Care Plan’ or ‘Tasks’, but for the sake of this discussion I’m going to keep it simple and just focus on the interaction between sender and recipient).

So let’s extend the simple concept of a Notification and add a few more properties:

  • Expected action. This is optional – if not present then the Notification is an FYI. We’ll make this a CodeableConcept so we can define common set of actions if we want to, which might be good for reporting, but also supports plain text, which will be the most likely early on. We’ll make this multiple to cover the situation where there is more than one thing needed to do by the recipient. If there were multiple actions my different recipients, then we’d use separate Notifications for each recipient.
  • Date due. This only makes sense when there is an expected action, but gives the recipient some idea of when the requested follow-up should occur.
  • Recipient Status. This will be used to manage the state of the Notification – I’ll talk about this in a moment. It will be a code datatype, with a fixed set of values.
  • Recipient Status Comment. A General comment field.

That takes care of the properties of the Notification, but we need to figure out how to manage the workflow aspects of the process – as described above, how can the sender be sure that the GP will carry out the requested actions (or not)?

We’ll use FHIR’s versioning capacity – plus the Provenance resource – to do this. (There may well be better ways, but let’s see how this plays out). It’ll work something like this:

  1. The sender will create the Notification resource (actually an e Other resource, as there is no specific FHIR resource for notifications yet) , setting the recipient details plus the expected action and date due. The recipientStatus will be ‘waiting’
  2. The recipient will periodically poll for Notifications with a recipientStatus of waiting – This will be slightly different from the version in the last post, because it will always return waiting notifications. Note also that we are using th
GET [server]/Other?code='notification'&recipient={gp}&recipientStatus=waiting
  1. The recipient can then update the Notification resource, setting the recipientStatus to ‘accepted’ or ‘declined’. They can use the RecipientStatusComment for any comment they may need to make – e.g. the reason why the GP declined to accept the action. If it is necessary to be more explicit about the person making the change, then they can create a provenance resource that has that information (the easiest way to do this is to put the updated Notification & Provenance resources in a bundle as discussed in previous posts)
  2. Optionally, once the action has been completed, the RecipientStatus can be updated to completed.

The sender can then monitor the status of the notifications as required.

Notifications where the recipient has declined the action:

GET [server]/Other?code='notification'&author={sender}&recipientStatus=declined

Notifications that have not been reviewed by the recipient yet

GET [server]/Other?code='notification'&author={sender}&recipientStatus=waiting&dateCreated< {yesterday}

To get a full picture of all changes to a Notification, we will need 2 queries:

The history of changes to the Notification resource

GET [server]/Other/{id}/_history

The Provenance resources that are associated with the Notification

GET [server]/Provenance?target={notificationID}

Of course, if we were being a nice server, we’d bundle both of these into a simple service that would make the calls internally and return a bundle of resources that would contain all the versions of the Notification resource, plus any Provenance resources associated with them.

GET [server]/Service/Notification/{notificationID}/_history

This pattern might not be suitable for a more fully featured task management solution, but it would seem the be sufficient for the simple use cases that we identified above.

So the complete list of properties for our improved Notification resource is (and remember that this is actually an Other resource at this stage, and all the properties are extensions):

  • Code
  • Subject
  • Author
  • Date Created
  • About
  • Recipient (was Target)
  • Expected action
  • Date due
  • Recipient Status
  • Recipient Status Comment

Comments welcomed!

FHIR and the Ambulance: Notification of XDS documents

We had an interesting discussion today about how to ‘notify’ clinicians that there is a document in a repository for a patient that they are looking after.

The documents in question will be clinical summaries of ambulance visits, and will be held in a highly available repository hosted by the ambulance service, from which authorized users (including the patient) may view them. This repository will be part of an XDS style implementation, so the repository will create a metadata resource (DocumentReference) and send that to the Registry (which we’re terming a ‘Record Locator’ service).

Once there, clinicians and patients will be able to locate and view the documents in the ways that we’ve already discussed.

In addition to storing the document, we also want to be able to create a notification to the patients usual General Practitioner (Primary Care Provider to you US folk) so that they know that an ambulance visit has occurred and there is a new Transfer of Care document for them to review.

The reason for this is that it is very useful for the GP to know that their patient has been seen by the ambulance service, in case follow up is required. In many cases – particularly when the ambulance call does not involve a hospital visit – and hence there is no hospital discharge summary to the GP – they have no way of knowing that the visit occurred. An example of this is where the patient has an asthmatic attack and is nebulized successfully at home.

So the workflow will go something like this:

  1. The Ambulance system creates the document (likely a CDA) and saves it directly in its repository – along with all the other required metadata. (This is the integrated document source/repository actor in XDS).
  2. The Repository will generate a DocumentReference resource, and send that to the Registry.
  3. The Registry will save the DocumentReference resource, and also generate a new resource – the Notification resource – that is directed to the patients usual GP (which will be in the Patient.careProvider property). There’s nothing to stop it creating multiple notifications – eg to a patients care team – if there are business reasons for doing so.

Once this is done, GP’s will be able to receive the notification by means of an RSS feed querying the Notification resource like this:

GET [host]/Other?code='notification'&target=<GP>&_since=<lastQueryTime>

which will return a bundle (Atom feed) of Notification resources for that GP. They can then use the Notification (specifically the DocumentReference property) to retrieve the actual document for viewing.

So what is this Notification Resource? Well, it doesn’t actually exist yet. To implement notifications we need to use the Other resource, which has been specifically designed for situations like this: we need a resource that is not yet defined (or maybe won’t be). It has a simple structure:

  • Code – the type of resource. This will indicate that it is a notification resource.
  • Subject – the patient
  • Author – in this case the ambulance system
  • Created – the date of creation

And then you add as many other properties (as extensions) that you want. We’ll probably need:

  • Type – the type of Notification – eg that there is a new document for them. We could get fancier if we want to…
  • About – the DocumentReference reference
  • Target – a Provider resource reference to the GP

Why have we specified a separate resource for the notification, rather than just storing the GP as an extension to the DocumentReference resource and querying on that? Well:

  • A tight coupling in this way would mean that the ‘notification’ is for DocumentReference resources only, and we may want to support other Use Cases – such as a notification that a patient has been admitted into hospital.
  • More complex workflow – like the ability to record that the notification has been viewed and accepted (or declined) would be tricky. (Actually this is more Task type behaviour – but then, a Notification could be thought of as a type of task)
  • It feels like we’re binding together behaviour that doesn’t belong together.

Some other notes:

  • We’ll probably get the registry to provide a special service for this ‘save metadata and create notification’ functionality – eg POST /service/DocumentReference/saveAndNotify that takes the DocumentReference resource and does the rest. (I’ve grown rather fond of these services since Keith suggested them!)
  • Because the  notification query is based on an extension, the server needs to map the ‘target‘ query parameter to the target extension. We really want to be able to search on the identifier property of the Practitioner resource that is the target property of the Notification, so we’ll need to set up the profile accordingly.

And finally, in our particular situation there are a couple of wrinkles:

  • The delivery timeframe of the project is before the Record Locator service is likely to be in place
  • This design requires that the vendors of Practice Management Systems that the GP’s use need to implement the RSS/Atom query mechanism

For the first wrinkle, the RSS/Atom lookup will initially be provided directly by the Ambulance Repository application. Then, when the remainder of the infrastructure is in place the consumers will simply need to change URL’s to switch to the Record Locator/Registry and the system will otherwise work unchanged.

In the second case, there are a number of portal applications in use in New Zealand – we’ll add the display of notifications to those portals so that when GP’s and patients log into the Portals they will receive the notifications in the same way as they would from within their GP PMS. Hopefully, this will allow the PMS vendors to see the value of this approach, and implement the functionality directly (it’s not that hard for a consumer after all!)

Since writing this post, I’ve written another one, further extending the concept of Notifications, thinking about how to manage workflow.

FHIR versioning with a non-version capable back end

As I’ve mentioned before, FHIR has the concept of versioning baked into it. Providing that the server supports versions, then any resource can be versioned, and older versions retrieved. However, particularly when using FHIR as a proxy server to a back end system, this might not always be the case – as we discovered at Orion during a project to provide FHIR interfaces to an existing product.

However, there are a number of areas where a ‘version specific’ ID is required – for example in the ‘self-link’ of a bundle containing the resource. (The self-link is optional, but desirable). It took a bit of fiddling – and a trip to Grahame via the skype implementers chat – to get this working correctly, so I thought I’d document where we got to (so I can remember next time!).

  • We store the ‘last-modified’ time of the ‘resource’ in the system (eg the last time that the patient was updated). This timestamp becomes the version we expose.
  • If we need to use a version specific reference (like the self-link) then we use the timestamp  – eg: /Patient/100/_history/201301011300
  • In our conformance statement for this resource we set:
    • Read: supported
    • Vread: supported
    • Update: supported
    • Delete: not supported
    • History: not supported
  • When we are returning a resource via a GET (read), then we set the ‘last-modified’ date to the timestamp

Now that we have that:

  • An ‘ordinary’ read will return the current version of the resource
  • If a client does a vread using the current version (e.g. /Patient/100/_history/201301011300) then there is no problem (and this will be what appears in any bundle we return).
  • Should a client have cached an older version, and attempt to vread on that, then we return an error indicating that the older resource version is not available.

In this way our system is compatible with a version-aware client, even though the back end does not support versions.

Simple!

FHIR server exploration tools

Just found this cool tool for exploring a FHIR server. It is hosted by Furore – the guys who also host a public test server, and allows you to view the conformance resource of any publicly accessible server, and then has a simple query builder that assembles a query, and returns all matching resources – displaying the text property.

Grahames test server has a similar facility – in fact allows you to view the resources directly, in XMl & JSON etc – but only operates against his server.

Both are cool tools if you’re starting out…

btw – there are other tools mentioned on the Furore site – a profile editor and a server test tool that you can request from furore…

FHIR XDS – updating a document

It’s not uncommon for a document to need to be updated after it has been posted to a repository and registry. Sometimes new information has come to hand that affects the document, or there may be normal workflow where a ‘draft’ document is saved, and is subsequently updated or finalized, or maybe the original was just plain wrong and needs to be retracted.

None of these are unique to a document of course, but there are some ‘quirks’ – for want of a better word – to the DocumentReference resource for a couple of reasons:

  • It is a resource whose main role is to refer to another entitity – so there are 2 lifecycles to consider.
  • Documents are often summaries of clinical care (e.g. Discharge Summaries, Progress notes, Clinic notes) and it’s very common for clinical decisions to be made on the contents. Keeping an easily accessible (to the end user) ‘audit trail’ of changes is very important for medico-legal reasons.

When thinking about changes to a document, there are 2 ‘types’ of change to consider:

  • Changes to the metadata (e.g. the document type was incorrect)
  • Changes to the content of the document itself.

We’ll consider these separately.

Changes to the metadata

If the change is only to the metadata – the contents of the DocumentReference resource itself, then it can be updated it in the usual way – i.e. retrieve the existing version, make the changes, and PUT the document back. The standard FHIR versioning process will manage the update of the resource. (Resource versioning is not required by FHIR – but highly recommended). There are some caveats to this approach, as mentioned in a minute…

Changes to the document.

This is more tricky. What we need to do is:

  • Update the document in it’s location (e.g. as a binary resource on a FHIR /Binary endpoint)
  • Update the existing DocumentReference resource that points to it, setting the status property to ‘superseded’
  • Create a new DocumentReference resource that references the updated document (and if it’s a FHIR server that we may want to make this a version specific reference), setting the relatesTo.code to ‘supercedes’, and the relatesTo.target as a reference to the original DocumentReference resource
  • We might also want to create a provenance resource to indicate who has made the change.

Because this needs to be managed as a transaction, we’ll use a FHIR bundle and we’ll use the same pattern as when we submitted the document in the first place – i.e. have the repository server manage the updating process. (Other patterns are possible of course).

So our bundle will contain:

  • The updated document as a base-64 encoded binary resource. It will have a real ID so the server knows to update it
  • The original DocumentReference resource, with updated status. It will also have a real ID so the server knows to update it
  • The new DocumentReference resource – largely a copy of the original with the relatesTo property set. It will have a ‘cid:’ ID so the server knows to add it as new.
  • Optionally a provenance resource with the details of who made the change – and when. The provenance resource refers to the resource being changed (not the other way around) so it will have 2 targets – the 2 DocumentReference resources that are effected in this transaction. It also has a cid: ID.

The repository server will process the bundle as described above.

Although this second approach is more complex, it does make it quite obvious that a significant change has occurred. For this reason, some metadata changes – such as a change of subject or author – might be better managed this way rather than a simple update to the DocumentReference resource. It’s up to you…

All of this does raise an interesting point that we didn’t think about when considering how to query the registry for documents (i.e. a query against /DocumentReference) – the response will include DocumentReference resources that have been superseded as well as current ones.

If we don’t add the status parameter in the query, then we will get back all DocumentReference resource’s – so we will need to check this value when assembling the list of documents for the consumer (Of course, we may want to do this anyway so that we can place some visual indication in the display that changes have occurred – it’s up to the implementer, as it should be…)

Otherwise we can be explicit that we only want current documents, so the examples we gave in the previous post becomes:

GET  http://registryserver/DocumentReference?subject= 100&status=current&period > 2013-01-01

and

GET  http://registryserver/DocumentReference?subject= 100&status=current&type= http://loinc.org|34108-1

And as a last word, and following on from the post that Keith Boone made about task orientated services, we may choose to define specific service end points for this functionality (and even for the ‘add document’ scenario), perhaps:

  • /service/document/new
  • /service/document/update

both of which receive the bundles we’re described.

Task orientated Services in FHIR

Last year New Zealand published a number of documents that were distilled from the Interoperability Reference Architecture we published the previous year. One of them was about the utility services that we envisaged would be needed to support the National strategy around health information interoperability, and the following diagram was included to show how we described a service based layer (we called it an HIE – which has a different meaning in the US) providing access to regional data repositories for shareable clinical data.

HIE

I’ve always believed that FHIR was an excellent candidate for this layer – and so I was especially pleased to see this  post from Keith Boone describing how FHIR could support Task orientated services as well as Entity services – just as we had envisaged (though I’d have different examples for the entity services these days)!

It will be interesting to see if the FHIR core team look at standardizing the common interfaces (like the admission services that Keith mentioned), or whether that will be left to individual implementers…