Profiling a FHIR Careplan for Immunizations

After the previous discussion on how to represent an Immunization plan, I had intended to talk about how to represent the Immunization protocol (or schedule), and how to apply that to a patients’ plan, but (as so often happens) I got a bit side-tracked, and thought we could first think about how we might create a Profile against the CarePlan resource to represent an immunization plan.

Now, we’ve talked about FHIR profiles before so I’m not going to repeat that here, other than to say that it is the profile that takes a standard resource (or resources) and makes them fit more precisely to a particular Use Case of some sort, so profiling CarePlan to support an Immunization plan seems a perfect fit!

There’s actually quite a lot to do to get a good profile (and I’m sure I haven’t got it completely correct), but at a high level, once you have your use cases you go through the resource and:

  • Alter multiplicity of elements (e.g. to make an optional element required or not used. Remember you can’t make a required element optional though)
  • Specify a particular terminology or codeset for a binding (and often you’ll define a ValueSet to hold the list of allowable codes)
  • Add a new element (as an extension) where it’s needed by the Use Case but not defined in the base resource

(There’s other things you can do as well, but that’s enough for our current needs).

Overall design

Here’s the structure of the Care Plan resource (Sorry about the image quality – its a screen scraping from my computer – here’s the original)

Screen Shot 2014-05-27 at 1.48.31 pm

How we’ll structure our profile overall is to use the goal element to list the diseases that this plan is intended to protect against (using an extension), then optionally link the activities back to the goals/diseases that are covered by that vaccine. That way we can say which activities contribute to protection against which disease. We’ll make this all optional, as not everyone will want to go to this level of detail (and, in truth, is probably a bit overkill). (btw – Another way of doing the same thing would be to add extensions to the activity directly to indicate the diseases being covered)

The activity will generally be the administration of a vaccine, however we’ll keep it a bit flexible to allow for, say, educational sessions as part of the plan. We’ll know which activity is an vaccination because the activity.simple.category will have the value ‘drug’.

We only need to profile the CarePlan resource for this Use Case.

For simplicity, we’ll put all the extensions in the same profile – in real life we might try to re-use existing extensions or to make some of ours a bit more general. This will really need common registries of profiles, which the FHIR team are working on at the moment…


So the following section lists the changes (in a textual format) that we’ve going to make to the CarePlan resource to allow it to hold the information required to represent an immunization plan. Each entry has the path to the element, followed by the multiplicity (which may not be the same as that in the base resource). If the entry is an extension (and remember that extensions can be at any level in a resource) then the path will end in a #{extensionDef code} and the data type will be displayed. Thus:

Careplan.goal#disease (0..1) CodeableConcept

means that this extension is against the goal element of the CarePlan resource, that it’s optional and there can only be one, and that the datatype is CodeableConcept.

If the values of the element (extension or base element) come from a ValueSet, then we’ll place the name of the ValueSet in square brackets at the end. Eg

Careplan.Activity.simple.code (1..1) [immunizationVaccines]

means that the value of the code (which is required in this profile) comes from the valueset whose name is immunizationVaccines. (Actually, this should really be a complete URI, but we’ll keep it simple to avoid cluttering the page). Note that this layout is just the one we’re using for this post – the formal representation will be the profile resource and maybe other artifacts that the core team is working on.  (Actually, I think the next connectathon is going to focus on profiles and conformance)

So, here we go. To minimize space, we’ll only include entries that are different to the base resource, or where there’s a particular comment to make.

We’ll also do this in 2 posts. This one will be more of a ‘design’ session – what we’re going to do and why. The next post will build the actual profile.

Items in the Profile

Careplan#protocolDescription (0..1) string

An extension where we can describe the protocol that this plan was drawn from.

Careplan#protocolUri (0..1) uri

A direct link to the protocol (if known).

CarePlan.patient (1..1)

You have to have a patient in our plan…

Careplan.patient#dob (0..1) date

The patients Date of Birth. This is a bit naughty as you should really retrieve the Patient resource and look up the Date of Birth from there. The reason to include it here as an extension is to allow us to be able to determine if an immunization is overdue just on the information in the plan. In reality, you probably woudn’t do this but, hey, its my blog and I’ll de-normalise if I want to

Careplan.period (0..1)

This would be the age range over which the immunization plan was active – eg from birth to 18 years

Careplan.modified (1..1)

This should be updated when the plan itself is changed – ie a new activity is added, to the status of an existing activity changed. The multiplicity is changed to make it required.

Careplan.concern (0..0)

As this plan is specifically about immunizations, the concern is not needed – i.e. the whole point is to avoid the patient getting those conditions. Change the multiplicity to 0..0 to remove it.

Careplan.goal#disease (0..1) codeableconcept

We’ll use the goal to list the diseases that this plan is intended to protect against, then optionally link the activities back to the goal. That way we can say which activities (immunizations) are protecting against which diseases. Note that there’s only a single disease per goal, but multiple goals per plan.

Careplan.goal.status (0..0)

The overall status of the plan is at the careplan level, not the goal.

Careplan.goal.concern (0..0)

Same notes as for careplan.concern.

Careplan.Activity#immunization (0..1) ResourceReference

An extension that references the Immunization reference. Should be populated when the vaccine is either given or offered and declined.

Careplan.Activity.goal (0..*)

To allow us to link this activity back to the goals (the diseases this vaccination is intended to protect against) if we want to.

Careplan.Activity.status (0..1)

Really the only codes that makes sense here are ‘completed’ and ‘cancelled’. However, this is a fixed code set in FHIR so we can’t change it. If due then we can either leave it blank, or we could use the value ‘not started’ or ‘scheduled’

Careplan.Activity.actionResulting (0..0)

Don’t want to record this in the plan

Careplan.Activity.detail (0..0)

The careplan.activity.notes can capture the level of detail that may be required, so this is not required.

Careplan.Activity.simple.category (1..1)

Fix the value as ‘drug’. We might want to suggest that ‘immunization’ be added as an option to the base resource.

Careplan.Activity.simple.code (1..1) [immunizationVaccines]

This will be the vaccine that is to be given so is mandatory. The value is drawn from the immunizationVaccines ValueSet

Careplan.Activity.simple.code#numberOfDoses (0..1) integer

The number of doses of this vaccine that are going to be given altogether

Careplan.Activity.simple.code#doseSequence (0..1) integer

The sequence number for this dose

Careplan.Activity.simple.timing (1..1) Period

Fix to use a period and make required. The ‘start’ property is required. ‘end’ is optional. This will be the period over which the vaccine must be given to be effective.

Careplan.Activity.simple.location (0..0)

No need to specify location in the plan

Careplan.Activity.Simple.product (0..0)

This information is in the code

Careplan.Activity.simple.dailyAmount (0..0)

 Not needed

Careplan.Activity.simple.quantity (0..0)

Not needed

So now that we have an idea about what our profile is going to look like, we can build the profile itself. That will be the topic of the next post!


About David Hay
I'm an independent contractor working with a number of Organizations in the health IT space. I'm an HL7 Fellow, Chair Emeritus of HL7 New Zealand and a co-chair of the FHIR Management Group. I have a keen interest in health IT, especially health interoperability with HL7 and the FHIR standard. I'm the author of a FHIR training and design tool - clinFHIR - which is sponsored by InterSystems Ltd.

One Response to Profiling a FHIR Careplan for Immunizations

  1. Pingback: Profiling a FHIR Careplan for Immunizations: part 2 | Hay on FHIR

Leave a Reply