January 4, 2015 Leave a comment
I’ve posted an update to the Extension Viewer that I’ve been working on over the holidays.
Thoughts and comments on the emerging HL7 FHIR standard, from a FHIR Evangelist
March 26, 2014 8 Comments
I’ve been spending a lot of time recently looking at Profiles (we’re building a tool to help manage the ones we’re creating at the moment).
As we start to implement FHIR interfaces in real systems, we’ve come to appreciate just how important profiles are going to be. The reason is that FHIR is essentially a set of basic building blocks (health-IT lego if you will) and some rules around how to manipulate them. The specification is deliberately very flexible to allow the blocks to be used in lots of different scenarios, both in terms of interoperability paradigms (document, message, REST, service) but also in different countries that can have vastly different requirements in terms of content, terminology, privacy and the like.
Furthermore, and again by very deliberate design, the ‘core’ contents of resources are limited to those elements that are currently being used by most implementers world-wide. This is to keep them manageably sized – the so-called ‘80%’ rule (which, unfortunately, has caused a lot of confusion as my colleague Edward has complained about). From a FHIR perspective there is no difference between core and extension properties – it’s just that the core properties are more common. (Perhaps we should have called extensions ‘special’ elements rather than ‘extensions’…)
What all this means is that in practice when you start to use FHIR for real, you’re likely going to need to adapt the resources to suit your own requirements, and that is where profiles come in.
A sample process might be:
It’s the profile that allows you to define these differences in a way that the people with whom you are interoperating can understand what you’re trying to say.
So what can you do with a profile? Broadly there are 2 things that you use them for:
And there’s a third category – metadata. Metadata is all about describing what the purpose of the profile is (what requirements it fulfils) and discoverability.
It’s important to appreciate that a single resource instance can have extensions from many different profiles, hosted by many different servers (a profile is just a resource after all – anyone can store them). And also important to appreciate that a profile cannot change the definition of a resource in such a way that it cannot be processed without referring to the Profile – this is the reason behind some of the thing you can’t do with profiles.
And when you design – and use – profiles, you really need to be thinking about re-usability – as Lloyd commented on the previous post, it’s better to have a generic profile/extension that can be used in multiple places than a specific extension that can only be used in one. Or even better, use one that someone else has defined – discoverability of ‘prior art’ is something that we really need to work on, which will be facilitated by the availability of public registries for profiles, and better searching – codes, tags – that sort of thing.
Anyway, on with some more detail on Profiles.
Each element in a resource can have a number of characteristics
Apart from the element name, the Profile can be used to constrain any of these characteristics – within limits. The following sections describe the most common things you might want to use a profile for.
You can specify that for your Use Case, the datatype must be a specified sub-set (or just one) of those defined. For example, Observation.subject can be a Patient, Group, Device or a Location, but in your use case, it might only make sense to be a Patient. Note that you cannot specify a datatype that is not already one of the options (or a recipient that didn’t know about your profile wouldn’t know what to do).
The following table shows how you can alter the multiplicity, with the rows being the multiplicity in the spec and each column being a multiplicity you can specify in the Profile.
(at least 1)
The following snippet shows how we’ve restricted the datatype of ‘asNeeded’ in the MedicationPrescription resource to Boolean, and also made it required, by setting both min and max to 1.
<structure> <type value="MedicationPrescription"/> <name value="asNeededConstraint"/> <element> <path value="MedicationPrescription.dosageInstruction.asNeeded"/> <definition> <short value="Only support boolean in the 'asNeeded' property"/> <formal value="Only support boolean in the 'asNeeded' property"/> <min value="1"/> <max value="1"/> <type> <code value="boolean"></code> </type> <isModifier value="true"/> </definition> </element> </structure>
Many of the elements can refer to a code-set, a terminology or a ValueSet. These elements generally have the datatype of coding or codeableConcept. In most cases the spec doesn’t say which terminology to use (though there will often be examples or recommendations). You can use a Profile to specify a terminology or ValueSet you want to use.
(Note that the code datatype is generally bound to a fixed set of values than cannot be altered in a Profile. These are reserved for elements that are generally used in workflow scenarios – ‘status’ elements are the most common).
The following snippet shows how we’ve restricted the code values that can be used for medications to those defined in a ValueSet of ULM (Universal List of Medicines) codes that a GP (Ambulatory care) clinician can prescribe. We could also have used a direct reference rather than the ValueSet, but the ValueSet allows us to filter the list.
<structure> <type value="Medication"/> <name value="medicationCodeConstraint"/> <element> <path value="Medication.code"/> <definition> <short value="GP ULM Codes only"/> <formal value="Specify that the medication code must come from the NZ ULM codeset"/> <min value="0"/> <max value="1"/> <isModifier value="false"/> <binding> <name value="List of medications GP's can prescribe"/> <isExtensible value="false"/> <referenceResource> <reference value="http://www.nzgovt/fhir/ValueSet/ulm-gp"/> </referenceResource> </binding> </definition> </element> </structure>
You can’t set a default value. The reason for this is that if you could, then it wouldn’t be safe to process a resource without referring to the Profile – which would severely impact on usability.
As we’ve discussed previously, we use extensions where we have some data that we wish to exchange that is not currently in the FHIR resource. We’ve talked about extensions before and made some notes about them when thinking about code sets, so we won’t go over that again but everything that you can do to a structure (core element) you can do with an extension – in fact much of the definition in the profile is the same for both.
As I hope you agree, the profile is an important resource to get your head around – and to use. When the public registries become available, re-use of profiles and extensions is going to become a lot easier – but in the mean time you can practise using Grahames or Ewouts server.
And remember that the enforcing of the constraints described in the profile is completely up to you. FHIR gives you the mechanics to describe these constraints in and easy to use, computable way. It’s up to you to adhere to / validate those constraints.
March 25, 2014 5 Comments
We’ve talked previously about the options available when you are building a FHIR interface (a façade) to an existing system, and there is a resource property with a fixed code set whose values are not the same as the ones in the existing system.
One of the options we discussed was to map the codes in the existing system to those in the spec, using extensions where existing codes ‘meant’ the same – just added more detail.
For example – in our existing system we have the concept of ‘for review’ prescriptions – the prescription has been issued, but local policy dictates that the prescription must be reviewed by a pharmacist (perhaps this must occur if the patient is on many medications) so it is not yet ready for dispensing/administration.
The MedicationPrescription.status field has ‘on hold’ as one of its values which is close enough for us to use. After all, a MedicationPrescription in a ‘for review’ status is, effectively on hold until the pharmacist has approved it (or not – as the case may be).
So we have a solution – but we are losing some data. Clients that only understand the spec won’t be affected, but clients that are familiar with our existing system (like the one we’re building) could use that in the display to give the user more information.
So, let’s build an extension.
Remember that there are 2 parts to an extension:
So we have a few decisions to make.
First, is this a modifierExtension? Well, we’ve already determined that it is safe to represent a MedicationPrescription in the status of ‘for review’ as if it were in the status of ‘on hold’, so it can be an ordinary extension (which is a relief – modifierExtensions are to be avoided if possible).
Next, what’s the scope of this extension? What resources can it be applied to, and does it only apply to specific properties of that/those resource/s? I suspect that this is always going to be a bit more of an art than a science – ideally we want to have reusable extensions (and I have a post planned on that), but we do need to be careful that it ‘makes sense’ to do so.
In this case, we’re going to assume that ‘for review’ really only makes sense for a MedicationPrescription, and further that it only makes sense to use it in the MedicationPrescription.status property (after all – a ‘reason for prescription’ of ‘on hold’ doesn’t make a lot of sense).
So, now that we’re got an extension scoped to a single property of an instance of MedicationPrescription, how are we going to represent that in the instance? And what will the definition look like in the profile?
I find it easier to start with the instance.
Recall that an extension in an instance can apply:
Clearly this is the second option – the extension will be with the property.
So instead of:
<status value="on hold"/>
we will have
<status value="on hold"> <extension url="wwww.fhir.orionhealth.com/Profile/nma#original-code"> <valueCode value='for review'/> </extension> </status>
Not too hard! Note the url in the extension:
Now for the definition.
We’ve already decided on the Profile and the name of the extension – how do we define it (including the set of possible values) – and, in particular, how do we state that it should only be used for the MedicationPrescription.status property?
Well, to define the set of possible values we create a ValueSet that defines the codes (they will almost certainly be in our own local system) and then create a binding to that valueset from the extensionDefn element in Profile
To indicate that the extension should only be used by the MedicationPrescription.status property, we simply set the value of extensionDefn.contextType to resource, and the context value to MedicationPrescription.status property.
So the complete definition will look like this:
<extensionDefn> <code value="original-code"/> <contextType value="resource"/> <context value="MedicationPrescription.status"/> <definition> <short value="Detailed status codes used by the HIS"/> <formal value="These are the mode detailed codes used by the HIS system for MedicationPrescription status and mapped to the standard codes."/> <min value="0"/> <max value="1"/> <isModifier value="false"/> <binding> <name value="Valid values for original code"/> <isExtensible value="false"/> <referenceResource> <reference value="ValueSet/nmaStatusCodes"/> </referenceResource> </binding> </definition> </extensionDefn>
One thing we haven’t done is to define the actual mappings between the two code systems – that will be up to the application to do so. However, there is a proposed resource – the concept map – that we could use for this, which would make the mappings explicit. And incidentally, this is one of the reasons that we created the ValueSet as a separate resource, rather than just containing it in the profile. Containing resource seems easier, but does significantly reduce options downstream so should only be done when there are no other options.
So, we’re good to go!
March 11, 2014 5 Comments
I’ve been meaning to talk about Profiles and ValueSets for a little while now. They’ve come up from time to time in this blog – this post was a comment from Grahame about the use of Profiles for specific Use Cases, and we’ve have a number of discussions about extensions such as this one which are defined in profiles.
Profiles are actually a ‘big thing’ for FHIR. You can think of the base FHIR structures (Resources, Extensions, Bundles, Tags, Queries etc.) as the common building blocks that you can use to build a solution – the Profile is where you can say how these blocks are used in your particular application – and what are the extra data items (represented as extensions) that you need. And this can be both computable and as documentation for humans.
Before we get into too much detail, lets talk about a couple of related resources – Conformance and ValueSet.
The Conformance resource is used to describe the capabilities of a particular server. This can either be about an actual server (it can be downloaded by a query to the server root like this: http://fhir.healthintersections.com.au/open/metadata – or using the OPTIONS verb) or it can be used when creating specifications for a server – what a client expects a server to be able to do.
As well as specifying the ‘standard’ resources and queries, the conformance resource can reference the profiles that it supports.
Suppose, for example, that we defined a profile for an antenatal visit. The profile might specify:
(we’ll talk about how to do this later). We’ll give this profile an identifier that we’ll call ‘antenatal’ in this post.
A server that supported this profile – i.e. it could check that a particular questionnaire had the right identifier, has a subject and a Practitioner author etc. would then add this profile to its conformance statement – if it receives a questionnaire claiming to conform to the antenatal profile, then the server can check that it does – rejecting it if not (and ideally including an OperationOutcome in its response to say why it failed.) Actually – to be correct the spec doesn’t state that the resource should be rejected – that’s up to the implementation to decide.
Now suppose that we have a client application that can create a questionnaire that conforms to this profile. All it needs to do is to POST the questionnaire to the servers Questionnaire endpoint, including a profile tag HTTP Header in the request that contains the antenatal profile. The server recognizes the tag, loads the profile and checks that the submitted resource does, in fact, meet the requirements of the profile. (Again, the details of this are up to the implementation)
In this way, the server can apply business level validation to resources to ensure compliance with business rules.
Finally, a single server can support multiple profiles (Indeed, a single resource could also be compliant with multiple profiles).
A ValueSet is simply a set of codes. It is used where you want to specify that the value for a particular code in a resource is drawn from a pre-defined set of codes. (It can get quite a lot more complex than that of course, but that description will do for now)
For example, suppose we are recording medicationAdministrations, and want to be able to indicate whether a particular administration was given on time, was early or was late. MedicationAdministration does not have this property so we create an extension definition (in a profile) to represent it. We actually have 2 steps to do in setting this up.
<ValueSet xmlns="http://hl7.org/fhir"> <identifier value="onTimeOrNot"/> <name value="medsontime"/> <description value="Were medications given on time"/> <status value="draft"/> <!-- Define the options in the resource rather than an external terminology--> <define> <system value="http://fhir.orionhealth.com/fhir/ns/onTimeOrNot"/> <concept> <code value='early'/> <display value="Early"/> <definition value="The medication was given early"/> </concept> <concept> <code value='on-time'/> <display value="Early"/> <definition value="The medication was given on time"/> </concept> <concept> <code value='ate'/> <display value="Late"/> <definition value="The medication was given late"/> </concept> </define> </ValueSet>
<extensionDefn> <code value="onTimeOrNot"></code> <contextType value="resource"/> <context value="MedicationAdministration"/> <definition> <short value="Was the medication given on time"/> <formal value="Was the medication given on time"/> <min value="0"/> <max value="1"/> <type> <code value="code"/> </type> <isModifier value="false"/> <binding> <name value="Set of coded values"/> <isExtensible value="false"/> <referenceResource> <reference value= "http://fhir.orionhealth.com/fhir/ValueSet/100"/> </referenceResource> </binding> </definition> </extensionDefn>
Both resources get saved on our (or someone else’s) server.
When we want to create a MedicationAdministration resource that can record whether the medication was given on time, we simply include an extension in the resource like so:
<extension> <url value = 'http://myserver/profiles/medadmin#onTimeOrNot'/> <valueCode value = 'early'/> </extension>
(If we need to, we can GET the profile, then GET the ValueSet to display a list to the user – though we’ll often have that in our application anyway).
If a recipient receives our resource and doesn’t know what ‘onTimeOrNot’ means, they can follow the url to the Profile which will describe the extension, and to the ValueSet which has the options. Of course, as this was an ‘ordinary’ extension we can safely ignore it if we don’t understand it – had it been a modifierExtension then it wouldn’t have been safe to do so.
The following diagram shows the relationships between these resources and note that they are all ‘instance’ resources with a ID – an fact the Profile & ValueSet resources could form the basis for a registry…
So we’re now ready to start talking about the Profile – and we’ve pretty much used up the space. Just a summary then, and the next post will go into more detail.
One last thing to point out is what profiles can’t do, and that is to change a resource in such a way that a recipient must understand the profile to safely process the resource. This is an absolute no-no in FHIR. For example, you can’t specify a default in a profile, or require the recipient to download the profile before processing.
If you do need to specify something that must be understood then create an extension setting the ‘isModifier’ to true. A resource instance will use the modifierExtension element to hold this data – and a FHIR recipient must always understand modifierExtensions to safely process resources.
March 6, 2014 23 Comments
Hi, my name is Edward and I am a FHIR extension.
David has let me write this short post on his blog, because there seems to be an understanding by those new to FHIR (and possibly those old to FHIR) that extensions are in some way ‘less’ than ordinary resource properties. Nothing could be further from the truth! It is me and my associates that will make FHIR the easiest healthcare interoperability standard to use.
Let me explain.
In the beginning there was HL7 Version 2, which was wildly successful. It’s used all other the place, and most of the time worked really well. But there is a problem, and that is that the core v2 standard doesn’t cover all the things that people need to exchange with each other (and remember – it’s all about the exchange, not about how the data is stored inside a system), so people added their own elements to the messages. Over time this means that there was a good chance that you could receive a message with elements in it that you didn’t understand – and no easy way of finding out what they meant without going back to the sender to ask them.
So, the folk at HL7 designed a new standard – version 3 – that had a common ‘model’ (a way of representing information) that both sender and recipient had to use. In that way both sides would be understand every part of a message. Problem was that because everything that anyone anywhere in the world wanted to send had to be in the model, over time the model (and the messages) became very large and unwieldy and implementers didn’t like it.
So when FHIR was invented by a team led by a clever Australian (originally a New Zealander I believe), they created the idea that each resource would have of a common ‘core’ set of properties that most people in the world included when they exchanged those resources – and a way for different people to easily add the extra stuff that they needed, but others didn’t. And that’s where I come in!
See, without me, FHIR resources would just get bigger and bigger and bigger until they were just like v3 messages, and just as hard to implement! And you don’t want that – do you…
In my opinion, the problem is that when the FHIR team say that something has to be in ‘the 80%’ – i.e. that most implementers are already exchanging that type of information – before it is included in the core, people take that to mean that the 20% is in some way inferior – second class citizens – and that’s just not true! We are going to be what makes FHIR work!
After all, you can use me to represent anything that you want to – using all of the other cool parts of FHIR (like the simplified datatypes, JSON & XML). I can be nested and queried. I am described in a standard way (in a Profile) and when I am in any instance of a resource, there’s a pointer to that Profile so you will always know what I stand for! You can even tell when I change the meaning of a resource (like when something DIDN’T happen).
I’m easy to use – for example here I am giving a persons eye colour:
<extension url="http://spark.furore.com/fhir/Profile/demo#eyecolour"> <valueString value="blue"/> </extension>
or if I change the meaning of a resource:
<modifierExtension url="http://spark.furore.com/fhir/Profile/demo#drugGiven"> <valueBoolean value="false"/> </modifierExtension>
and in both cases, if you don’t know what I mean the description is just a click away! (Actually I made the URL’s up – but you see what I mean).
I’m going to be especially useful when the experts from other standards – like openEHR – start to use FHIR. Rather than getting into big arguments about what should be in the core and what shouldn’t – just create an extension and you’re done! (Plus a profile of course…)
So in conclusion, please don’t ignore me when you’re starting to use FHIR. I’m just the same as the ‘core’ properties – and so much more flexible…
Thank you for your time, and I look forward to helping you with your interoperability work!
To define a search query for eye colour, you would define that in the profile like this:
<query> <name value='findByEyeColour'/> <documentation value="Allows a caller to find all patients based on eye colour"/> <parameter> <name value="eyecolour"/> <type value="string"/> <documentation value="The eye colour to search on. "/> <target value="Patient"/> </parameter> </query>
The implementation would be dependent on the server, though a standardized method may be defined in the future.
January 31, 2014 2 Comments
One of the common use cases for FHIR is going to be to create a ‘proxy’ or ‘façade’ FHIR server that provides a FHIR interface against an existing data source – and this is what we are doing at Orion Health in front of our Patient Administration System. (We’re actually building a rather cool mobile medication administration app – hope I’m allowed to say that!).
The problem we are facing is that in the ‘back end’ system, this field is a configurable set of values – and it often won’t match the values defined in FHIR. This is bad enough for optional properties, but even worse when the property is a required one – such as MedicationAdministration.status.
Now there are very good reasons why the workgroup that designed these resources have made the codes a fixed set – they are important properties that a recipient must understand to safely use the resource – and we are about interoperability after all. But it’s still a problem we need to solve.
I can think of a few possibilities for us.
Option 1 is to change the codeset in the backend system to that defined in the FHIR resource – perhaps a bit unlikely…
Option 2. Ideally, every value in the back end system can be mapped to one of the values from the fixed code set – with an acceptable loss of fidelity. Then, you can create an extension to hold the original value. In this way a recipient who doesn’t understand your custom codeset can still safely process the resource (using the defined property) but internal clients can apply whatever extra logic is supported by the enhanced set in the extension.
For example, the MedicationPrescription resource has a status property of which one of the values is ‘on-hold’. If the backend system has a number of values that could mean this (on-hold due to an operation, on-hold due to other therapy, on-hold because the pharmacy has run out) then you can set the status value to on-hold, and the extension can contain the more precise value. Incidentally, this might be one of the few places where a Coding datatype is appropriate.
Option 3. If you have values that simply cannot be mapped in this way then you can use a modifierExtension on the property itself to carry the extra value. This severely reduces the interoperability of your resource of course, as a recipient must be able to understand and process your custom value – and should reject the resource if it cannot.
(It may not have been obvious that resource properties can have extensions as well as the resource themselves – check out the spec for more details. In fact, it’s possible to extend a datatype if you need to!)
If you do find yourself in this position, it would pay to ask a question through one of the various FHIR support channels – you might get advice about a value you can use, or if your use case is compelling enough the codeset can be extended in FHIR itself.
So there you go. A price of being interoperable is that you have to conform to a set of agreed behavior and content – and sometimes that means compromise. Hopefully there will always be some way to achieve the business requirements, and especially in this DSTU phase of FHIR changes to the spec are quite possible – if there is a good enough reason.
January 6, 2014 Leave a comment
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:
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:
(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.