Question: Binding choices

Question:

A question regarding “Standard” codes vs. Customized codes: To my understanding, if I want to exchange FHIR resource, any property in that resource can be filled by either of the following options:

  • Using the standard clinical coding system for relevant clinical properties (for example, SNOMED CT code for MedicationOrder>Medication>code
  • Using the HL7 FHIR administrative coding system for relevant administrative properties (for example, http://hl7.org/fhir/ValueSet/medication-order-status for MedicationOrder>Status)
  • Using customized, in-house, coding system, but for that I need to define it as appropriate ValueSet, bounded into appropriate Profile.

Answer:

So this answer (and the question, really) applies to any property in a resource that has a type of Coding or CodeableConcept. In principle, any property of a resource that has a type can be filled by any one of those choices – a SNOMED CT code (or RxNorm, or LOINC, or …), a FHIR defined code, or a locally defined code. However for all these properties, we ‘bind’ them to a value set, and that value set makes a rule about what kind of codes can be used.

Element <– (binding) –> ValueSet

So if the property is bound to SNOMED CT, then you have to use a code from SNOMED CT. But note that if the type is CodeableConcept, which can have more than 1 coding, then this means that one of the codings has to come from SNOMED CT – for the others, you have can use anything at all that you like.

Further, the binding itself has an important property – the ‘strength‘ of the binding. This key property tells you how to interpret the binding:

required You have to use one of the specified codes
extensible You have to use one of the specified codes, unless there isn’t an appropriate one. Then you can use whatever you like
preferred This is the sort of codes you should use – and this value set really is a good idea to use
example This is the sort of codes you should use

So the last 2 binding strengths are not, well, binding: you can ignore them as you see fit. So what you can actually use in a resource property depends on the strength of the binding, and the value set it references. But, sadly, most of the really interesting properties in most resources have a binding strength of ‘example’ – precisely because they are most interesting, we have no way to get consensus on the right coding system (let alone the right set of concepts). A great example is Condition.code:

. code 1..1 CodeableConcept Identification of the condition, problem or diagnosis
Condition/Problem/Diagnosis Codes (Example)

An example binding to a large set of SNOMED CT codes….

Finally, some notes on your choices:

  • Standard clinical coding system: we always recommend that you use one of these. But these can be hard to use. We introduced the terminology service to make this easier, and this is a concept that’s just about in the goto-market phase
  • FHIR code systems are mostly defined for the fixed properties like status where you have to use one of the fixed codes we defined, but sometimes we define a code system to be used with Coding/CodeableConcept. We generally try pretty hard to not overlap with the standard terminologies, so it’s usually a choice of one or the other
  • When you use a customised in house coding system, you don’t actually have to define it using a value set, but doing so allows you to tell everyone else in a computable fashion what you are doing, so it’s a good idea, yes.

 

 

Question: How do profiles fit into the overall conformance picture

Question:

How are Conformance Resource and Implementation Guide (IG) resources are linked? I understand usage of both but how both will be linked to create Profiling.  Not clear about using both of them, what scenario or use case would be that?

Answer:

Well the conformance resource includes server capability or client desire for server capability and also includes what all actual Resources are supported, and links to what profiles are (or should be) supported on the system. So the conformance statement ‘creates’ profiling by making it clear what profiles the system supports.

ImplementationGuide is a primarily a publishing thing – publishing a group of conformance statements and profiles, with their supporting value sets etc, in a single logical group, with a single identifier.  The implementation guide may – and commonly does, but not always – include one of more conformance statements as examples, or requirements. So it ‘creates’ profiling by allowing for publication of  group of conformance statements and profiles. So it’s primary function is to establish logical groups of profiles.

Most uses of Implementation Guide will be publishing national standards, or project agreements (projects such as argonaut) rather than server level publishing.

 

 

 

Question: where did the v2 messages and events go in FHIR?

Question:

I’m relatively new to the HL7 scene having implemented a few V2 messaging solutions (A08 , A19, ORU) and the V3/CDA work on PCEHR.  I am trying to get my head around FHIR.  So far I am stumped in how I would go about for example implementing the various trigger/messages I have done in V2.  Is there any guidance?  I cant find much.  Is that because the objective of FHIR is implementers are free to do it anyway they like?  If you could send me some links that would be a good starting point that would be great

Answer:

Most implementers of FHIR use the RESTful interface. In this approach, there’s no messaging events: you just post the Patient, Encounter etc resources directly to the server. The resources contain the new state of the Patient/Encounter etc, and the server (or any system subscribed to the server) infers the events as needed.

A few implementers use the messaging approach. In this case, the architecture works like v2 messaging, with triggers, and events. However, because the resources are inherently richer than the equivalent v2 segments (e.g. see Patient.link), we didn’t need to define a whole set of A** messages, like in V3. Instead, there’s just “admin-notify” in the event list.

For XDS users (HIE or the PCEHR in Australia), see IHE’s Mobile Health Document Specification.

 

#FHIR in China

For the last few days, I’ve been in China for the China Health Information Network Conference 2016. I’d like to thank HL7 China and Professor Li (Chair, HL7 China) for inviting me – I really enjoyed the trip.

sdr

Simon Gong from Orion Health introducing me for the HL7 China technical session.

I was really keen to make this trip, because China is a really important potential stakeholder for FHIR. Not only is it a really large market, by many reports, Chinese medical practice can sometimes be quite different to western medicine, and I’ve worried that if China sits out the development stage of FHIR, and only gets involved late in the process, it might be too late for valid input to be heard.

I enjoyed my time in China immensely. I found a community struggling with the same things that challenge everyone. In fact, every time someone said to me, “What’s different about China, is that X is a problem”, I’d think to myself, yes, X is something that everyone struggles with to some degree or other. Interoperability is all about the people, and it’s the same in China just like anywhere else. But I think that what distinguishes China is the scale of the problem – China is vast, the healthcare system operates at a huge scale, modernization is happening so quickly, the economic factors that make it hard for vendors to collaborate are stronger, and the government’s ability to influence things (for good or bad) is stronger, etc.

Like many other countries, China is trying to figure out what to do about FHIR. Getting involved early in the process has it’s own costs, but gives you more influence over the final outcome, but sitting the process out avoids the cost of change and preserves your existing investment. I hope that my presence, my presentations, and my comments in discussion with Professor Li and others helped the Chinese community figure this out.

On other hand, several implementers described systems – including production systems – built using FHIR APIs – population surveillance, and clinical data repositories – just as real as anything built elsewhere. Some of these implementers I had already met, or even people who’ve contributed to FHIR (e.g. translations) – it was great to meet them in person. But others were new to me.

After my formal presentations, the HL7 China Technical Steering Committee (which is chaired by old friend JD Li), invited me to talk  with them about how to create an active FHIR community in China. They decided to plan a FHIR Connectathon for sometime in the period Oct – Nov, which we’re working on planning now. Also, by their request, I created a Chinese stream at chat.fhir.org. We also talked at length about translation plans, which is a significant issue in China. We didn’t make any solid plans in that regard, but the TSC will be working on that.

Hopefully we can build on the interest and commitment that already exists, and seed an active community that can catalyse wider uptake of FHIR in China.

Finally, I’d like to thank Sean Xie from Orion Health, who translated my presentations for me – Sean did a great job, and I really appreciated his excellent work.

Update: Chinese translation of this post from Linforest (thanks) (and with improved photos including Prof Li owning the floor while questioning me!).

#FHIR and the Gartner Hype Cycle

As FHIR product director, I get plenty of comments about the hype associated with FHIR. And there is plenty of hype. Here’s the Gartner hype curve:

Where are we on that curve, people want to know? Well, my answer is that as far as I can tell, the rate of increase of hype is still increasing, so it seems as though we’re still in the initial rocket phase.

What’s the hype?

For me, hype is beyond enthusiasm – it’s when people make wildly inflated claims about what is possible, (wilfully) misunderstand the limitations of the technology, and evangelise the technology for all sorts of ill judged applications (about where block chain in healthcare is right now).

So what things do I see that I think are hype? Well there are many symptoms, but one fundamental cause: there’s an apparently widely held view that “FHIR will solve interoperability”.

It’s not going to.

FHIR is 2 things: a technology, and a culture. I’m proud of both of those things. I think both of those will make a huge contribution towards solving the problems of interoperability in healthcare. But people who think that problem will be solved anytime soon don’t understand the constraints we work under.

HL7 is an IT standardisation Organization. We have severely limited ability to standardise the practice of healthcare or medicine. We just have to accept them as they are. So we can’t provide prescriptive information models. We can’t force vendors or institutions to do things the same way. We can’t force them to share particular kinds of information at particular times. All we can do is describe a common way to do it, if people want to do it.

FHIR is good for sharing information out of an EHR – but confirming to FHIR doesn’t prove anything; there’ll have to be some policy layer above that. More generally, if you have 2 teams (departments, vendors, governments, whatever) that don’t see eye to eye, forcing them to adopt FHIR as a technology isn’t going to change anything. Getting them to adopt the FHIR culture – that will. But you cannot impose that.

So what can we do about that?

What we – the FHIR team – can do is to make sure the fundamentals are in place. Good governance, solid processes, well tested specifications, an open and inclusive engagement framework. If we can get that right – and it’s a work in process – then the trough of despair won’t be as deep as it might, and we can focus on our task: getting the standards out of the way of solving problems in people’s healthcare.

Follow up: have you read my 3 laws of interoperability?

 

BlockChain is the new XML

There’s an amazing amount of noise running around the healthcare about Blockchain.

Blockchain! Blockchain! Yay for Blockchain! 

Blockchain is a great solution for a set of hard problems to solve. But I’m not entirely sure which of those problems is related to healthcare. But that doesn’t seem to matter – BlockChain!

So I’m holding a contest – please make suggestions for useful ways to leverage Blockchain in healthcare. I’ll award a whole Blockchain to the person who makes the most outrageous use.

Question: Searching by extensions in #FHIR

Question:

My concern relates to search resources by extensions. I have read a lot about extensions and profiles, but the processing I have never seen.

If I need a new field on patient, like eye color, I’ve the option to extend the standard patient resource and add the new property. Persisting and loading via ID is quite easy. But how is the best way to realize a searching for patients with the new eye color value? Is there ever a solution?

Btw: I’m using the awesome HAPI from James Agnew.

Answer:

This is a question that comes up occasionally because the answer is buried in the spec. When you search a resource, you nominate one or more parameters to search by. In the specification, we define a basic set of search parameters, the ones we think will come up in practice. Servers can decide which of these to support, and define their own additional ones.

Note that the parameters are not direct queries into the resource – they are a name that identifies a path into the resource. The idea is that you can use some kind of map-reduce approach to generate the indexes, or map to an existing index you already have. So for patient, the search parameter “given” is actually a search onto the path Patient.name.given. The ‘path’ there is actually a fluent path expression – and finally, in the latest version of the spec, we have all the ducks in a row to make that formal and explicit.

So to search an extension, the server defines a name – say, ‘eyecolor’ in your case – and generates the index based on the expression Patient.extension(“your-extension-url”). It’s completely transparent to the client where the search parameter refers to unless the server publishes it’s search parameter definitions, and the client processes them.

Oh – but you’ll want to know how to actually do that in HAPI – you’ll have to ask on the HAPI support forum. Btw, yes, both HAPI and James are awesome 😉

Mapping between CCDA and FHIR

Across the board, many FHIR implementers have the same challenge: mapping between some other format, and a set of FHIR resources. Right now, the pressing issue is mapping between CCDA and FHIR (in both directions). At the HL7 Orlando meeting in January 2016, we held a Birds of a Feather session about mapping. At this meeting, there was general consensus that we – the FHIR community – would like to have a mapping framework that

  • allows us to exchange maps that express detailed transforms from one format to another (in terms of a previous post, executional maps)
  • means that the transforms are portable e.g. the same transform can be run on multiple different system
  • can be shared through a FHIR repository
  • allows to move data into and out of FHIR resources (or between them)

While we were at it, we noted that it would be pretty cool if the language could be used for transforms that didn’t involve FHIR either. And we decided that we’d focus on CCDA <-> FHIR as a primary use case, since that’s an operational issue for so many people. Also, we noted that there’s no existing standard that meets these requirements, or that can easily meet them. MDMI was brought forward as a candidate, but it’s not clear that MDMI solves the problems we usually encounter.

After the meeting, I sat down with Keith Duddy, one of the editors of the other leading candidate specification, which is QVT. After a long discussion about what we were trying to do, and a review of the possible candidates, Keith and I designed a mapping language for FHIR that is very much based on QVT, but leverages a number of design features and philosophies from the existing FHIR work. The work includes an abstract syntax (which is a resource, the StructureMap resource), and a concrete syntax, and a transform host API that delegates implementation specific transformation actions to the host engine. In addition, we’ve prototyped it in the context of CCDA –> FHIR Mapping. Btw, this arrangement means that Keith can take all the credit for the good parts, and I can get the blame for all the other parts.

So this mapping language is published, and open for community review. I expect that there will be robust discussion: is it rich enough? too complex? why do we need to do this? can’t we just use [insert name here]. And maybe there’s some candidate out there we haven’t found… so to help with the evaluation, we’re working on the transform from CCDA to FHIR for the Montreal connectathon.

So here’s an initial contribution to get discussion going:

Download all these, and then you can execute the validator jar with the following parameters:

 ccd.xml -transform -defn validation-min.xml.zip 
   -txserver http://fhir2.healthintersections.com.au/open 
   -folder [cda structure definitions=] -folder [map files folder] 
   -map http://hl7.org/fhir/StructureMap/cda 
   -output bundle.xml

The transform will produce bundle.xml from the CCDA input files. Alternatively, if you want the java source, see org.hl7.fhir.dstu3.utils.Transformer in the FHIR svn

Transform Pseudo Code

To help other implementations along, here’s a bunch of pseudo code for the transform engine (it’s actually pretty simple!). Note that to use this, you need to two things:

Object model – both the source object model, and a target object model express the same meta-level API, which has the following features:

  • – list children (name) returns list of Value : given a name, return all the children that have the given name
  • – make child (name) returns Value: create the appropriate object, and return it (can’t be used if the object is polymorphic)
  • – create (typename) returns Value: create an object of the specified type name (type name comes from the mapping language)
  • – set property(name, Value): set the property name to value. if name is cardinality 0..*, add to the list

And then you need a FluentPath engine that compiles and evaluates fluent path expressions:

  • – parse(string) returns expression: parse the string expression
  • – evalute(expression, Value) returns boolen: apply the expression to a value, and see whether it is true or not

Here’s the logic for the structure map transform

 transform(Value src, StructureMap map, Value tgt)
   create new variables 
   add src as new variable "src" in mode source to variables 
   add tgt as new variable "tgt" in mode target to variables 
   run transform by group (first group in map)
 
 transform by group(group, variables)
   transform for each rule in the group
 
 transform by rule(rule, variables)
   clone the variables (make us a new copy so changes don't propagate backwards)
   check there's only one source (we don't handle multiple sources yet)
   for each matching source element (see logic below - a list of variables)
     - for each target, apply the targets
     - for each nested rule, transform by rule using the variables
     - for each dependent rule, apply the dependent rule
 
 processing dependent rules
   look through the current map for a matching rule (by name)
   look through all the other known maps (in the library) for a matching group (by name)
   if match count != 0, it's an error
   check the variable cont provided matches the variable count expected by the group (and check whether they are source or target)
   make a new variables
   for each parameter, get the variable given the name, and add it to the new variables (in order)
   transform by the group using the new variables
 
 Finding Match Source Elements(source, variables)
   get the source variable with the name "source.context"
     - check it's not null (error if it is)
   if there's a condition, get the fluent path engine to check it against the source variable
     - if it fails, return an empty list
   if there's a check, get the fluent path engine to check it against the source variable
     - if it fails, blow up with some error message

   if there's a source.element
     get a list of the children with the name source.element from the source variable
   else
     turn the source variable into a list
 
   for each element in the list from the previous step, 
     clone source variables
     if there's a source.variable, add the element as to the cloned variable list using the source.element name
     add the closed variable list to the results
   return the results
 
 Apply a target(target, variables)
   get the target variable with the name "target.context"
     - check it's not null (error if it is)
   check there's an element (todo: support this)
   if there's a transform 
     value = run the tranform
     set the given name on the target variable to the value
   else
     value = make the given name on the target variable
 
 Run the transform(parameters, vars)
   depends on the transform:
   create: ask the object API to create an object of the type in parameter 1
   copy: return the value of parameter 1 (see below)
   evaluate: use the fluent path engine to execute aginst the p value of 
     parameter 1 using the string value of parameter 2 as the expression
   pointer: return the correct URL to reference the object that is the value of parameter 1 
     - which is right is a deployment decision

 The value of a parameter
   if it's an id (e.g. not a constant, just a word)
     then it's a reference to the named variable
   else 
     it's some kind of constant 

New #FHIR Vital Signs Profile

Over on the official FHR product blog, I just announced a new release. I wanted to expand on one of the features in the new version here

A new profile to describe vital signs (note: this is proposed as mandatory to enable better data sharing)

One of the emerging themes in many countries is sharing data with patients. And one of the broad set of things called ‘health data’ that is easiest to share is what is loosely called ‘vital signs’. It’s simple data, it’s easy to share with the patients, and we’re starting to see monitoring devices available in mainstream consumer technology. But it’s more than just patients that care – vital signs data is widely shared through the healthcare provision system, and there’s lots of interesting decision support and surveillance that can usefully be done with them.

But if every different part of the healthcare system, or different jurisdictions, represent basic vital signs differently, there’ll be no way to easily share decision support and survelliance systems, nor will patients be able to share their healthcare data with common data management tools – which are cross-jurisdictional (e.g. things like healthkit/carekit).  With this in mind, we’ve defined a vital signs profile in the new draft of FHIR, and said that all vital signs must conform to it. It doesn’t say much:

  • The common vital signs must be marked with a common generic LOINC code, in addition to whatever other codes you want to give them
  • There must be a value or a data absent reason
  • There must be a subject for the observations
  • Systolic/Diastolic must be represented using components
  • The units must be a particular UCUM unit

This is as minimal a floor as we can get: defining a common way to recognize a vital sign measurement, and a common unit for them. None of this restricts what else can be done, so this is really very minimal.

For FHIR, this is a very gentle step towards being proscriptive about how healthcare data is represented. But even this looks likely to generate fierce debate within the implementer community, some of whom don’t see the data sharing need as particularly important or near in the future. I’m writing this post to draw everyone’s attention to this, to ensure we get a good wide debate about this idea.

Note: it’s a proposal, in a candidate standard. It has to get through ballot before it’s actually mandatory.