Referrals, Orders and FHIR

One of the resources that didn’t make the DSTU was a resource to represent Referrals – and this is something that the Working Group is starting to address. However, the concept of referrals is something that crosses a number of concepts in FHIR, so I thought I’d make a few notes here before we get started. (and to give credit where it is due, I’ve had some pointers from Lloyd about the best fit within FHIR – I take responsibility for the errors!.)

Lets start by thinking what we mean by a referral – and what we would expect of a system managing referrals.

Fundamentally, referrals are a formal way of asking some other person to become involved in a patients care. A couple of examples:

  • A primary care clinician (ambulatory care) has a patient with severe osteoarthritis and refers her to an Orthopaedic Surgeon for consideration of hip replacement.
  • The same clinician sees another patient with raised HBA1c and other symptoms of diabetes and refers him to the local diabetes clinic for management.
  • A patient in hospital for a routine procedure has symptoms suggestive of angina, and is referred to the Cardiac team for assessment.
  • A patient is referred for physiotherapy after a stroke.

And there are lots of other examples of course (and I’ve glossed over some important things like responsibility for care).

So there are a number of ‘parts’ to the referral:

  • There’s the general workflow stuff – there’s a sender and a recipient. It’s about someone (and that could be the sender in a self referral for that matter). The sender wants to know that the referral was received, and is being actioned.
  • Then there’s more specific workflow that’s related to referral management. It’s common for multiple people to examine a referral – to triage it, put it in waiting lists, create appointments, and possibly re-direct it to other recipients. One referral might lead to another being made or to other orders (like radiology and laboratory investigations) being made. The sender should be aware of all these activities. This workflow can be specific to the recipient.
  • There’s clinical information about the referral – what is the reason for the referral. What is the urgency (from the view of the sender/patient). What are the expectations of the sender. What is the clinical information that is directly pertinent to the referral (such as the raised HBA1c in the example above).
  • And finally there’s the other clinical content that is not (perhaps) directly related to reason for referral, but is nevertheless important that the recipient know about. Usual medications, co-morbidities and allergies are examples of common clinical information that are almost always included in referrals regardless of the reason.

 

In FHIR, there are already a number of resources that manage some of these (and we hate duplication don’t we?).

There’s the Order and the OrderResponse resources that are intended to manage the workflow aspects of healthcare.  If we have workflow requirements that are not met by these resources, then we should enhance them rather than duplication in our referral. (For example, a likely requirement is going to be the ability for one referral to reference another – we might want to know all the actions that were associated with a referral for costing purposes – so we might want a ‘relatedTo’ reference on an Order).

And we often think of a referral as if it were a document – in fact, in manual systems a referral is often written on a predefined template supplied by the recipient to ensure they receive the information they need to properly manage the referral. So we have the Questionnaire as a mechanism for defining that template, and the Composition if we do want to represent the referral as a formal, signed & asserted document.

And if we do go down a document paradigm, then we might want to use the DocumentReference resource as a way being able to refer to the document (perhaps we wish to display the referral with other documents in the patient record, or find similar/related referrals)

And finally there are all the clinical resources that may be included.

(Which of these resources are actually needed in any specific implementation will depend on the overall system design and architecture, but we do want to be sure that they have been designed to work together and not overlap in terms of functionality.)

So what belongs in the referral resource?

Well, as a strawman proposal lets start with:

  • Sender, Patient and recipient. These are going to be duplicated in Order, but they are fundamental to a referral and so probably belong here as well. (And both DiagnosticOrder and MedicationPrescription which are similar have them, so we’re in good company).
  • The reason for the referral. This could be a CodeableConcept or a string – we possibly want both, one for analysis and automated management and the other for humans (though the CodeableConcept has a text property, so a separate property may be overkill)
  • Details of the referral. Clinicians commonly like narrative in a referral.
  • The Priority and Urgency
  • The actions we wish the recipient to perform. This might be a ‘please see and advise’ through to a ‘please perform this action’
  • Supporting clinical information. Likely the clinical impression that led to the referral will be mentioned in the details – here is where the other important stuff like medications and co-morbidities can go.
  • Attachments.
  • Possibly a direct link to a Careplan resource since careplans can indicate when a referral is required (as can a Protocol – when we have one).

Lets finish this off by working through a real scenario – with a given architecture – and see how all this might work. Note that this is only one possible design…

We’ll go with a document based metaphor and assume there is a document repository that can hold the referral and the referral templates, and an orders management system that holds the Order resource. These could be native FHIR servers, or existing components with a FHIR façade.

referrals

  1. The sender locates and downloads the questionnaire resource that has the referral requirements of the recipient
  2. The sender assembles a document that contains the referral resource, a composition and the clinical data plus attachments. The document is submitted to the registry/repository (there is probably a DocuemntReference resource in there as well).
  3. The sender creates a Order which has a reference back to the referral document and submits that to the Orders Management system
  4. The recipient has a ‘pub/sub’ feed from the Orders management, and so retrieves the order and from that the reference to the referral document.
  5. They download the document (Or, hopefully, process it ‘in place’).
  6. Over time, the recipient performs whatever processing is required, creating OrderResponse resource as appropriate. The sender has a pub/sub feed monitoring those resources and so is aware of the status of the referral at any time. (And can make direct queries at any time).

Although not explicit,  because Referral and Order are in repositories, other authorised people – including the patient – are able to review the progress at any time.

So to sum up, we’ve got a fair bit of work to do – but a lot of the bits are in place, and the art is going to be deciding what should go where!

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.

 

 

FHIR Profiles: an overview

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:

  • Start with a set of requirements (Use cases, user stories, story boards etc).
  • Define the behaviours and the data models you’re going to need. (Behaviours – e.g. queries, workflow, updates, services etc. are outside the scope of this post – but you’d document them in the Conformance resource).
  • Once you have the data model (and these may be in a form like openEHR archetypes – or just a simple table), you then need to map these to the FHIR resources. It’s at this point that you’ll likely find:
    • There are some things you want to exchange that aren’t in the current resources
    • The resources have elements that you don’t want to use.
    • You will want to be more specific about some aspects of the resource – e.g. use a specific terminology for an element, or make an element required rather than optional
    • There might even be models for which no resource can be found. Again this is a bit outside the scope of what we’re talking about here – an option is to use the Other resource (originally known as the resource-with-no-name) and define everything as extensions in a profile.

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:

  • Adapting the core resource structures to meet your requirements
  • Defining extensions on resources – extra properties needed for your use case.

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.

  • If we are a server then a client can read our conformance resource, which will list the profiles we support (and provide a link to them).
  • If we are a client, we can tell a server that we conform to a profile (the server will probably still check).
  • If we receive a resource with an extension we don’t recognise, it will point to the profile in which it is described so we can decide what to do with it.

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.

Adapting the core resource structure

Each element in a resource can have a number of characteristics

  • Its name
  • One or more datatypes
  • Multiplicity (how many there can be in a resource)
  • Possibly a binding to a terminology (which may or may not be defined in the spec)

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.

DataType

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

Multiplicity

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.

0..0
(Not used)
0..1
(optional)
0..n
(optional, many)
1..1
(required)
1..n
(at least 1)
0..1 yes yes no yes no
0..* yes yes yes yes yes
1..1 no no no yes no
1..* no no no yes yes

In summary:

        • If it’s already optional then you can make it required or not used.
        • If it’s already required then you can’t make it optional
        • If more than one is allowed, then you can restrict the number (this is called ‘slicing’ – refer to the spec for details)
        • If only 1 is specified, then you can’t make it many.

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>

Terminology

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>

Default Values

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.

Extensions

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.

Last Word

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.

Extending fixed code sets – revisited

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:

  •        It is defined in a Profile (in the <extensionDefn> element)
  •        It is used in an instance using the <extension> element (or <modifierExtension> if it modifies the meaning.

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:

  •        to the whole instance (in which case it is at the top of the instance)
  •        to a specific property (in which case it is represented with the property)
  •        or to a datatype (in which case it is represented with the value)

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:

  •        the extension is defined in the Profile to be found at wwww.fhir.orionhealth.com/Profile/nma
  •        it has the name of ‘original-code’
  •        it is of the datatype ‘code’.

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!

 

 

REST headers in FHIR

One thing that came up today during some development that we are doing here concerns the use of HTTP headers when a client is making REST calls on a FHIR server. They are all clearly documented in the spec,  – and there’s also a nice summary, but I’m just pulling them out here so I don’t waste so much time the next time I forget them (and Richard – who is developing the FHIR server –  said I should – kind of like writing lines on the blackboard I suspect – “I will not forget to set the correct headers” repeated 20 times)…

  • When making a query, to specify what format you want the server to return data in, use the Accept header. The value should either be application/json+fhir or application/xml+fhir (Though a bundle is slightly different with application/atom+xml  for xml). The Server will set a Content-Type header to tell the client the format of the response (It doesn’t have to honour the Accept)
  • When sending data to a server, use the Content-Type header to indicate the format. Same mime-type options as above.
  • If updating a resource, it’s a good idea to put the current version-specific id in the Content-Location header. If the server is enforcing optimistic locking then it will need it – otherwise they will be ignored.

(you can also put the mime-type in an _format parameter if you can’t get at the headers).

So. There it is. Now…

I will not forget to set the correct headers again

I will not forget to set the correct headers again

I will not forget to set the correct headers again

FHIR Profile Videos

Rene just sent this note to the FHIR list with some videos on profiles that Ewout has done:

FYI: The ‘advanced’ FHIR profiling video (profiling extensions and slicing) can be found at https://vimeo.com/88235048 , the ‘introduction to profiling’ video (which was released a while ago) can still be found at https://vimeo.com/87074652 . Both are presented by Ewout Kramer.

So I don’t loose them…

Profiles and ValueSets in FHIR

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.

Update: Rene Spronk has commented about a video tutorial given by Ewout Kramer that can be found here. This gives a nice overview of profiles and is well worth a read…

Before we get into too much detail, lets talk about a couple of related resources – Conformance and ValueSet.

Conformance

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:

  • a particular Questionnaire resource (questionnaire.name / questionnaire.identifier)
  • that the questionnaire author must be a Practitioner
  • that the subject is required and so forth

(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).

ValueSet

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.

  • First, we create the ValueSet resource. In this case we’ll define the values directly in the ValueSet (we could also refer terminologies like SNOMED or LOINC if that were appropriate) and give it an appropriate identifier. Here is what it might look like
<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>

  • Next we create a profile with an ID of ‘medadmin’ (so we can easily refer to it in a URL) and in that profile we’ll create an extension definition (ExtensionDef). We’ll give the extension a code of ‘onTimeOrNot’. In the definition of the extension we indicate that the datatype of the extension is a code, and that the value of this code must come from the ValueSet we just created (this is called a binding) – by including a reference to the ValueSet in the extensionDef element. Here’s an example (assuming that the ID of the ValueSet was 100):
<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…

profile-1 (1)

Profile

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.

  • The profile is how you ‘constrain’ one or more resources to meet your particular Use Case.
  • It is also where you define the extensions you are going to need (and you almost certainly will need some).
  • You can also define custom queries here
  • It contains both computable artifacts and human documentation.
  • It can get complex! – for example one profile can refer to another

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.