Pictorial representation of FHIR resouces

We’re been talking about the best way of representing how FHIR resources relate to each other. It’s reasonably easy to do this for technical people – they’re familiar with the idea of tools like UML models and XML / XML Schema, but not so easy for clinicians and other non-technical folk.

FHIR is based the concept of resources that can relate to each other – a term I’ve heard used is that they represent a ‘web’ of resource connections, which is quite a nice analogy. It’s exactly how the World Wide Web works – and everyone knows how to use the web, but fewer are familiar with the standards and constructs that underlie how all this works.

A resource (as you doubtless know by now) represents a particular ‘thing’ that makes sense as a separate entity. Examples are patient, practitioner, condition (problem), encounter, allergy etc. A resource contains a collection of properties (like name, date of birth, address), and these properties either have a value (and the structure of that value can be complex – that’s the datatype) or is a reference to another resource (hence the concept of the web of resources).

We thought it might be interesting to represent these connections as a connection of nodes, where each node is a resource (the other properties of the resource aren’t shown in these diagrams).

Note that this is a ‘specification’ view – it shows the connections that are defined in the spec, not necessarily how you’d represent them in a real instance. For example, where a single property could be linked to different types of resource then both links are shown. Also in a real situation you’d probably put the patient in the centre and there would be multiple instances of many of the resources.

And also links (references) can be added using extensions…

So here are some diagrams for some of the clinical concepts – just to see if they are useful (Note that the colours of the resources don’t have any significance).

First up is the Condition resource (earlier known as the Problem resource)

fhir_condition

 

Next are medications. These are a wee bit more complex as we have

  •        Medication (a drug)
  •        MedicationPrescription (what the patient should be taking)
  •        MedicationAdministration (a single administration of a dose of a drug)
  •        MedicationDispense (medications dispensed to a patient)
  •        MedicationStatement (a record that a patient is taking a medication)

So we’ll use a couple of diagrams.

One based on the MedicationPrescription (and including details of the Medication)

fhir_meds

 

And another for MedicationAdministration

 

medicationadministration

 

And finally lets think about allergies. There are a couple of key resources here – AllergyIntolerance (which records what the allergy is to and who recorded it), and AdverseReaction – which records the actual reaction that occurred.

 

allergy

 

 

Well, that’s all I’m going to do at the moment – I’m not 100% sure how valuable these representations are, if you like them and want me to do more then leave a comment!

And remember – these relationships are just what the core spec refines. They can be adjusted and augmented to meet your own business cases using Profiles and Extensions.

 

 

Saying ‘No’ with FHIR: The List resource

Was cruising the Stack Overflow site looking at FHIR questions (as you do) and I came across this question about how to indicate that a person has no known allergies. It was answered by Lloyd who stated that you should use the List resource to do so.

This is such a common requirement in healthcare that I thought it was worth a short post on.

And, to be explicit I’m referring to requirements like being able to state:

  • No known allergies
  • No usual medications
  • No problems known

And not the issue of ‘incomplete’ data that the ‘nullFlavor’ attribute of v3 was supposed to address. This is a complex – and controversial – topic that Grahame has addressed in this post. FHIR has taken the perspective that the complexities of  nullFlavor outweights its value ‘for the 80%’. When it is important, then a resource can either define a specific property (e.g. ‘Date of Birth not known’) or an extension could be used.

Now we’ve already talked about the use of a List when representing a list of Medications where we discussed the advantages that a List gives over a simple query of resources, but we didn’t talk specifically about its value when wanting to explicitly state that the person was not on any regular medications.

The List property that you use is called ‘emptyReason’, and it’s a CodeableConcept which has the following possible values:

  • nilknown
  • notasked
  • withheld
  • notstarted
  • closed

(refer to the spec for a description of what these mean, though it’s pretty obvious… Incidentally, the type of this property is incomplete – which means that there is a set of values that most people agree is correct, but it is permissible to use other codes if needed).

You can only use the emptyReason if the list itself is empty (which makes sense).

The List has particular value in a Document as many of the sections will actually be lists of things (like lab tests, family medications, interventions etc), so it’s very helpful to be able to indicate ‘no known <resource>’. For other resources that don’t use Lists – like the Family History or relevant past history – then you’d need to use an extension. For example, you might want to add an extension to a document section that points to the same binding as the emptyReason so you could state, for example, no known family history.

The FHIR DocumentReference resource

In the previous FHIR-XDS post we discussed how a document source actor (ie a system that creates a document) could create a document and DocumentReference resource and send them to the Repository server. (Actually, we described a couple of ways that this could be done – and there are a few subtleties yet to discuss about server behaviour – but we’ll hold that for later).

However, we didn’t have a lot of time to talk about the DocumentReference resource itself. This resource represents the metadata about the document and allows a consumer to search the registry (or any server hosting these resources) to retrieve matching documents. From these results, a consumer can then generate a list of documents so that a consumer can select one to view.

The documents themselves can be of any allowed type (CDA, PDF, FHIR document, text etc) and can be stored on any server accessible via HTTP – and they do not need to be FHIR servers. It is quite legitimate for a DocumentReference resource to refer to a static document on any server (or, for that matter, a URL that generates a document ‘on the fly’, though you’d want some way to persist the generated document for medico-legal reasons as described in the ‘IHE on-demand document‘ profile). And, if one is being particularly pedantic, then even HTTP is not really required – you could use FTP or any other supported protocol.

It is important to note that although the DocumentReference resource was developed to support some of the requirements of an XDS infrastructure, it is not restricted to that purpose and can be used in any situation where the business requirement is to create a ‘list of available documents’, from which one or more can be chosen for viewing.

In fact, the FHIR specification defines a specific XDS profile that describes how the DocumentReference resource is to be used in the context of an XDS installation – for example some fields that are optional in the resource, are required when acting as a proxy to XDS. The link also gives guidance for mapping between XDS and FHIR elements, including fields required for XDS that are not in the DocumentReference and so represented by extensions.

The following description refers to the generic DocumentReference resource. Note that there are a number of properties whose value should come from a ValueSet defined by the governance body that oversees the overall installation (an Affinity Domain in XDS-speak – though the affinity domain covers much more than just code sets). We will talk a bit more about ValueSet’s after this list.

  • The masterIdentifier is the identifier of the document as created by the source. It is version specific – i.e. a new one is required if the document is updated (We’ll talk about updating documents in a separate post).
  • There can be any number of other document identifiers that make sense. For example, there might be a version independent identifier here.
  • The subject is who the document is about. Generally this is a patient, but the specification also supports a Practitioner, a Group or a Device.
  • The type and class indicate what kind of document this is- (eg a discharge summary). A ValueSet should be defined for each. (Note that ‘class’ has been called ‘sub-type’ in some versions of this resource)
  • There is at least one author, which is a Practitioner.
  • There can be an Organization which is the custodian of the document – responsible for maintaining the document
  • There’s a policyManager link to a URL that describes the access policies to the document.
  • The authenticator of the document can be an Organization or a Practitioner.
  • The created date is when the document was created (not necessarily related to the period of the service that the document may describe – this is in the context.period element).
  • The indexed date which is when the DocumentReference resource was created.
  • The status allows minimal workflow of this DocumentReference resource (NOT the underlying document). Options are current, superseded or error. We’ll talk more about this status when we talk about updating a document in a later post.
  • The docStatus and supercedes allow a document to be updated (superseded) or otherwise have it’s status changed. This is a CodeableConcept, and so can accommodate a specific workflow defined by the affinity domain such as preliminary, final, amended or whatever, as documented in the ValueSet.
  • The description is the title of the document. If you’re displaying list of documents then this would be a good property to use.
  • The Confidentiality property allows a privacy policy to control the access to a document. The policy can also use the generic tags functionality in FHIR.
  • The PrimaryLanguage element indicates exactly that – no surprises here. It is a code, and is bound to the IETF Language tag.
  • mimeType and format indicate how the document is represented – eg xml, pdf, msword etc.
  • Size allows a client to estimate download time of the document, and the hash can ensure integrity.
  • The Location is a URI that indicates from where the document can be downloaded. This does not need to be a FHIR server. The client will (generally) not know what this is when creating the resource as it will be related to the ID that the server assigns. However, either it or the service property is required, so it may be necessary to create a ‘dummy’ resource using the cid: prefix so the server knows it is not real – or define a service. You would define a local policy to describe this, which could be identified in the policyManager link above.
  • The service is used if the location is not known. You would use this if you weren’t using simple FHIR REST, so for the moment we’ll ignore it.
  • The context allows you to specify the clinical context of the document – at least the context that is useful in searching or displaying the document list. The period that the document refers to and the facility type are present, but you can add codes that make sense here as well.

For reference, the following fields need to have their options defined by the governing body using a ValueSet. These can either be defined directly in the ValueSet or be a sub-set of an external Terminology like LOINC or SNOMED.

  • type
  • subtype
  • docStatus
  • confidentiality
  • mimeType
  • format
  • context.code
  • context.facilityType

The recommended way to document this is to create a Profile resource that describes the implementation, and refers to the appropriate ValueSets – with the whole lot being saved in FHIR server/s so that they can be easily located. The option below shows a minimal profile that sets the ValueSet for the confidentiality property.

<Profile xmlns="http://hl7.org/fhir">
     <text>
         <status value="additional"/>
         <div xmlns="http://www.w3.org/1999/xhtml">Minimal profile for confidentiality codes in DocumentReference</div>
     </text>
     <name value="Elbonian XDS Profile"/>
     <status value="draft"/>
     <structure>
         <type value="DocumentReference"/>
         <name value="XDSDocumentReference"/>
         <element>
             <path value="DocumentReference.confidentiality"/>
             <name value="ConfidentialityOptions"/>

             <definition>
                 <short value="Confidentiality Code options"/>
                 <formal value="Confidentiality Code options"/>
                 <min value="1"/>
                 <max value="1"/>
                 <isModifier value="false"/>
                 <binding>
                     <name value="List of confidentiality options"/>
                     <isExtensible value="false"/>
                     <referenceResource value="/ValueSet/ConfidentialityOptions"/>
                 </binding>
             </definition>
         </element>
     </structure>
 </Profile>

and the ValueSet that it references could look like:

<ValueSet xmlns="http://hl7.org/fhir">
     <text>
         <status value="additional"/>
         <div xmlns="http://www.w3.org/1999/xhtml">The value set for confidentiality codes in the elbonian document sharing
         project. The codes are defined directly by the valueset, rather than references to an external terminology</div>
     </text>
     <name value="ConfidentialityOptions"/>
     <description value="ConfidentialityOptions"/>
     <status value="draft"/>
     <!-- Define the  options in the resource rather than an external terminology-->
     <define>
         <system value="http://fhir.moh.elbonia.com/confidentiality"/>
         <concept>
             <code value='N'/>
             <display value="Normal"/>
             <definition value="That the document is of normal confidentiality - is able to be viewed for any authenticated user"/>
         </concept>
         <concept>
             <code value='H'/>
             <display value="High"/>
             <definition value="Then the document is Highly confidential - eg Mental health - and can only be viewed by people authorized to access documents at that level"/>
         </concept>
     </define>
 </ValueSet>

Finishing up…

In the previous post I promised that I would talk about the DocumentManifest resource. This is a new addition to the FHIR family, and has been introduced to support the ability for a document source to submit a collection of documents in a single batch as XDS does.

In truth, I’m not entirely clear how this resource should be used. It does have the recipient element, which provides the basis for a notification system, but beyond that the main value would seem to be that there can be more than a single document in a batch submission to the Repository server. I’ll update the post when I learn more.

So, we have saved a document in the repository and updated the registry. In the next post, we’ll switch our attention to the Document Consumer and discuss how to query the registry for documents, and to get the actual document itself.

FHIR Connectathon: The conformance resource for a client

The planning for the 5th FHIR connectathon is underway, with an announcement yesterday on the FHIR list server encouraging people to review the registration site, and to register as soon as the registration is open (which I absolutely encourage you to do). This will be the first connectathon that I won’t be at – which is kind of sad, but had to happen at some point.

Although I’m in the middle of a series of posts on FHIR & XDS (and a bit behind to tell the truth – work has got in the way of the fun stuff), I thought that it might be of interest to discuss some ‘connectathon-related’ topics – starting with the conformance resource. We’ve talked about this before in the context of a server using it to indicate to a potential consumer what it’s capabilities are (and been quite good in actually producing examples in our discussions), but it has also been designed for use by a client to indicates what it requires of a server.

In the case of connectathon, we encourage clients to create a Conformance resource to indicate what they need of a server as they fulfill the scenarios.

The conformance resource itself has some ‘header’ information (eg description, FHIR version and so forth) and then entries for REST, Document and Messaging. We will focus on the REST entry. There are entries that indicate:

  • Whether the conformance resource is describing a client or a server
  • Which resources the server supports or a client requires
  • Which profiles are supported/required
  • Security considerations
  • For each resource:
    • what operations are supported/required – CRUD
    • whether history is supported/required
    • the search parameters supported/required

A client will set the Conformance/rest/mode/@value  value to ‘client’ to indicate that it is specifying a requirement rather than a capability – and the other parts of the resource mean the same thing that they to for a server.

As an example, suppose that I want to complete scenario 1.4 of connectathon (search for a patient on name)  – the following conformance resource would indicate my requirements to a prospective server:


<Conformance xmlns="http://hl7.org/fhir">
     <text>
         <status value="generated"/>
         <div xmlns="http://www.w3.org/1999/xhtml">
             <p>A conformance statement detailing the client requirements for a sever in implementing scenario
             1.4 on connectathon#5 - search for a patient by name. Note that this only for 1.4 - we'd need
             to update if we were supporting any other scenario</p>
         </div>
     </text>
     <identifier value="68D043B5-9ECF-4559-A57A-396E0D452311"/>
     <version value="20130510"/>
     <name value="Connectathon Conformance requirements"/>
     <publisher value="HayCorp"/>
     <telecom>
         <system value="email"/>
         <value value="user@haycorp.com"/>
     </telecom>
     <description value="This is the FHIR conformance statement for the haycorp team at connectathon #5"/>
     <date value="2013-11-12"/>
     <software>
         <name value="HC-Client"/>
         <version value=".01"/>
     </software>
     <fhirVersion value="0.12-1911"/>

     <!--   doesn't really apply for a client, but is required   -->
     <acceptUnknown value="false"/>

     <!--   we only do XML -->
     <format value="xml"/>

     <rest>
         <mode value="client"/>
         <resource>
             <type value="Patient"/>
             <operation>
                 <code value="read"/>
             </operation>
             <searchParam>
                 <name value='name'/>
                 <type value="string"/>
                 <documentation value="Search by patient name"/>
             </searchParam>
         </resource>
         <operation>
             <code value="search-system"/>
         </operation>
     </rest>

 </Conformance>

A couple of notes:

  • The conformance resource is not – necessarily – used for machine processing, but rather as a uniform way that servers and clients can indicate and match capability & requirements. For example, they are very useful in the planning stages of a project when clients and servers are being located and/or designed.
  • As a FHIR resource, a conformance statement can be stored in a FHIR server, and has the same versioning capabilities as any other FHIR resource. This makes an excellent choice for locatable documentation once the systems are in operation.
  • And its resource nature also supports the concept of a searchable registry. This is more applicable to a server than a client, but does support the idea of providing UDDI like functionality…

Manipulating a single FHIR Patient Resource

Following on from the previous post about REST in general, let’s dig in a bit more and start manipulating a single resource in FHIR. We’ll read an existing resource, update it and create a new one.

First task is to set up the tools we’re going to need to experiment. There are at least 2 sets of tools you’ll need to do this properly:

  • Something to send and receive HTTP requests. This will to allow you to specify the content, the HTTP method and request headers, and also to view the response headers, Status Code and any response body that the server returns. (refer to my previous post if these terms are new to you)
  • Something to create and view XML and JSON resources. You might also want to download the FHIR schema files from the spec (look for the link that says ‘FHIR Schema & Schematrons).

Depending on your environment, there are many options for both of these. To keep thing simple I’m going to use a chrome browser extension (Postman) for making the HTTP requests, and the Oxygen XML editor for the XML/JSON stuff, but you choose what works for you. I’m going to assume that you know how to use these tools – or are at least willing to find out!

Reading an existing resource

Before we start – an important message about the ‘@’ symbol. Currently, the FHIR specification uses the ‘@’ symbol in a URI to make it clear which part of the URI is the ID for the resource. This is going to change in the next version of the spec, and it will be removed, however it might take some time for the test servers to be modified. If you get weird errors when trying the instructions below, then remove the ‘@’ and see if that helps.

To read an existing resource when you know its URI (i.e. the server location and ID on that server) you use an HTTP GET request. I’m using Grahames’ server for this example which is a public server that anyone can change, so the details may be different for you.

Here’s what I got using Postman to retrieve the Patient resource with an ID of 2:

Screen Shot 2013-10-16 at 8.50.37 PM

Note that:

  • The full URI to that resource on Grahams’ server is http://hl7connect.healthintersections.com.au/svc/fhir/Patient/@2
  • I asked the server to return the resource in the XML format, by setting a request header – Accept – to ‘application/xml+fhir. I could have set the Accept header to ‘application/json+fhir to get a JSON formatted resource – try it! Here is a bit more on these mime-types.
  • The Status Code was 200 – which means that everything worked OK.

In Postman, I can also look at the response headers – which the server sets – as shown below:

get with headers

Notes:

  • The Content-Location header has the value http://hl7connect.healthintersections.com.au/svc/fhir/patient/@2/history/@2 . This is a ‘version specific’ URI – it specifies not only the resource Id, but also the specific version of this resource – in this case it’s the second version.
  • The content-type header tells us that this is an XML format.
  • There are a number of other useful headers that we won’t go into right now.

Updating a resource

Lets update this resource. What we’ll do is to copy the resource we just retrieved into our XML editor, make some changes, paste them back into Postman and PUT them to the server. Optionally, we’ll validate the updated resource using the FHIR schema before we send it to the server.

Step 1: Copy the resource you just downloaded

Step 2: Paste the resource into your XML editor

Step 3: Change the file – for example you could add a new name just after the existing name, like so:

...
<!-- Original Name -->
<name>
    <use value="official"/>
    <family value="SASHA"/>
    <given value="BOJICIC"/>
</name>
<!-- New Name -->
<name>
    <use value="usual"/>
    <family value="As"/>
    <given value="Otherwise known"/>
</name>
...

If you want to, you can check that this is valid against the FHIR schema by associating the updated file with the correct XML schema (it will be Patient.xsd in whatever folder you downloaded the schema to) and clicking the ‘validate’ button in your editor.

Step 4: Copy the changed resource

Step 5: In Postman, change the GET to a PUT and paste the updated resource into the body of the request (the raw tab is the best)

Step 6: press the Send button.

All going well, the server should accept the changed resource, and return a response with a status code of 200. The Content-Location header should show that the version has been incremented. Here’s what I got:

Updated after PUT

Notes:

  • The spec does not require that version numbers are sequential ones – although Grahames server does do this. Others (like Ewouts) use a different scheme – all that matters is that a new version of a resource gets a new version number.
  • We used PUT and not POST because we knew the full URI (including the resource ID). POST would have indicated that we wanted to create a new resource – as we’ll do in a minute.
  • If you PUT to a URI, and there is no existing resource at that URI then it will still be saved, but the status code that is returned will be 201 rather than 200.
  • At the moment, when you update (or create) a resource, then the FHIR server will return the resource it saved. This behaviour will be changed to be more consistent with the HTTP spec in the next FHIR version, and the resource will no longer be returned.

And before we move off the topic of updates – and versions:

  • You can always retrieve a specific version of a resource using the version specific URI that was returned when the resource was updated – eg http://hl7connect.healthintersections.com.au/svc/fhir/patient/@2/history/@3
  • You can get a list of all the versions that exist for a resource (if any) by appending the term ‘history’ to the URI of the resource – eg  http://hl7connect.healthintersections.com.au/svc/fhir/patient/@2/history
    • (Note that this will return a list of resources in a bundle – I’ll cover bundles in the next post when I discuss searching)

Creating  new resource

So, that’s getting an existing resource and updating it – what about creating an entirely new one? Well that’s easy – and you can do it right now. All you have to do is:

  • Use the POST method instead of the PUT method
  • Send the request to the root for that resource on the server – e.g. http://hl7connect.healthintersections.com.au/svc/fhir/Patient in the case of Grahames’ server – rather than to a URI (after all, you don’t know what ID the server is going to assign to the new resource yet).

All you have to do is to change the URL in POSTMan (get rid of the /@2 at the end of the line), change the method to POST and press <Send>.

The server will process the request and return a response. This time the status code will be 201 – indicating a new resource was created. The actual URI for the resource will be in the Content-Location header (and it will, of course, be a version specific URI).

How hard is that?

A question that came up from the previous REST post was about who creates the resource ID’s. In particular, can a client create the ID rather than the server?

It is certainly possible for the client to assign the ID – in FHIR, if a client PUT’s a resource to a URI (i.e. includes the ID) and there is no resource already there, then the server will create the resource using that ID (it returns a 201 status to indicate that this has happened). The issue with this of course is in potential ID collisions – what prevents 2 clients using the same ID for different resources?

However, FHIR takes the view that this is a deployment decision, and is up to the implementers and trading partners using the server. They could insist on GUID’s as the IDs for example.

Do play around with reading, creating and updating Patient resources. You can try creating entirely new resources in your editor (and don’t forget to use the schema validation so you know you have a valid resource). Read the documentation for the Patient resource to find out what properties you can add, and don’t forget to look at the examples that are in the spec (in a tab at the top of the page).

The next post in this series will start to explore the topic of searching – how do you find a resource when you don’t know its URI  – and where we’ll be introduced to a new construct – the resource bundle.

Cheers…

FHIR Contained Resources

I’ve been meaning to write a blog for some time.

In fact I started one a year or so back which I let drop (a common occurrence I suspect). I’ve also had some pressure from my colleagues at Orion Health (Thanks Mark & Sandra) and it was them that suggested this title – due to my passion for the new HL7 FHIR standard. When I mentioned the possible title to Grahame Grieve (the originator of FHIR), he started laughing – apparently in the old days when convicts were deported from England to Australia for relatively trivial offenses, word came back that Australia was a rather better place to live than England was at the time, so being deported there was a *good thing*. However, there was a fine line between being deported, and being hung (which is a *bad thing*). Turns out that the safest way was to set a hay stack on fire – and then ensure that you were caught. So the title has stuck…

Read more of this post