Category Archives: FHIR

#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?

 

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.

 

(When) Will #FHIR replace HL7 v2 messaging?

Question:

I’m working in the healthcare domain and has been hearing the FHIR developments for a while. In my hospital setting, we typically have a Patient Registration System, a EMR system, a LIS and RIS system, and some machine interface (Vital Signs, BMI). We are communicating with each other using HL7 V2 standard and is working fine.

My question is, how does the development of FHIR helps in existing interfaces? Do we need to eventually replace these interfaces with FHIR? If yes, all vendors of the respective systems needs to be FHIR ready.

I like to believe that FHIR is for a future expansion packs, and not a move to replace all existing interfaces. Meaning HL7 V2 are expected to stay.  Another question: In HL7, we dealt with messaging in asynchronous mode. But the FHIR standards, we are moving from the messaging world?

Answer:

This is a pretty frequently asked question – I got it fairly often at HIMSS last week. My standard answer is:

You don’t fix what isn’t broken, so initially, no one will replace v2 messaging interfaces with FHIR interfaces. Instead, institutions will use FHIR on their perimeter, for integration between enterprises.

I say that because FHIR is able to leverage all sorts of web standards, so it’s naturally a better choice than v2 from that point of view alone, and also because this is where all the action currently is, and why would you use v2 now? Most people I hear from are using FHIR in preference to v2 even though FHIR is still a moving target.

But once that’s in place, institutions will increasingly find that what they can do on the perimeter interfaces is constrained by what the internal services can provide – and then they’ll start gradually replacing their v2 interfaces with FHIR interfaces.

 

Using #FHIR Observations for User fitness data

In a question on stack overflow, an implementer asks about using Observation for user -gathered fitness data:

While there is the Observation resource, this still seems best fit (!) for the EHR domain. In particular the user fitness data is not collected during a visit and is not human-verified.

The goal is to find a “standardized FIHR way” to model this sort of data.

Use an Observation (?) with Extensions? Profiles? Domain-specific rules? FHIR allows extraordinary flexibility, but each extension/profile may increase the cost of being able to exchange the resource directly later. An explanation on the appropriate use of a FHIR resource – including when to Extend, use Profiles/tags, or encode differentiation via Coded values – would be useful.

There’s no need to use extensions, but there is a need for domain specific rules. Use an observation that looks like this:

{
  "resourceType": "Observation",
  "text": {
    "status": "generated", 
    "div": "<div>[name] : [value] [hunits] @ [date]</div>"
  },
  "status": "final",
  "category": {
    "coding": [
      {
        "system": "http://hl7.org/fhir/observation-category",
        "code": "fitness",
        "display": "Fitness Data"
      }
    ]
  },
  "code": {
    "coding": [
      {
        "system": "http://loinc.org",
        "code": "[lcode]",
        "display": "[...]"
      },
      {
        "system": "http://snomed.info/sct",
        "code": "[scode]",
        "display": "[...]"
      }
    ]
  },
  "subject": {
    "reference": "Patient/[xxx]"
  },
  "effectiveDateTime" : "[when]",
  "valueQuantity": {
    "value": [value],
    "unit": "[hunits]",
    "system": "http://unitsofmeasure.org",
    "code": "[units]"
  }
}

Some notes about this:

  • A couple of the measurements need an effectivePeriod instead of an effectiveDateTime
  • it might not be necessary SNOMED CT and LOINC codes, but it’s probably useful to have both (where they’re defined)
  • [name], [scode], [lcode] and [units] come from a row in the table below. other values [value], [hunits], [when] come from the data source
  • the category code is new. I’ll create a task to add it to the specification
Description SNOMED CT Code LOINC Code UCUM Units
Ambient temperature 250825003 60832-3 Cel; [degF]
Blood Glucose 365812005 77145-1 / 74774-1 mmol/L or mg/dL
Blood Pressure 75367002 55417-0
   Systolic 271649006 8480-6

standing: 8460-8
sitting:8459-0
supine:8461-6

mm[Hg]
   Diastolic 271650006 8462-4

standing: 8454-1
sitting: 8453-3
lying downlying down: 8455-8

mm[Hg]
Body Fat % 248300009? 41982-0 %
Body Height 50373000 8302-2 m; cm; [in_i]
BMI 60621009 39156-5 kg/m2
Body Temperature 386725007 8310-5 Cel; [degF]
Body Weight 363808001 29463-7 kg; [lb]
Breath CO 251900003 (none) [ppm]
Calories Burned (none) 41981-2 kcal; J
Expiratory Time 250820008 65819-5 s
Heart Rate 78564009 8867-4

standing: 69001-6
sitting: 69000-8
lying down: 68999-2

{beats}/min; /min
Inspiratory Time 250819002 60740-8 s
Minutes of Moderate Activity (none) (none)
Minute Volume 250811004 20142-6 (use duration) L
O2 Saturation 431314004 20564-1 %
Respiratory Rate 86290005 9279-1 {breaths}/min; /min
Sleep Duration 248263006 n/a h
Step Count n/a 55423-8

If you’re looking for additional rows not in the table, send me a data element name and a definition, and I’ll add it to the table. I’ll also propose adding this table to the FHIR specification

Announcement: #FHIR Code-a-thon Washington DC April 1/2

An announcement from CMS/HHS Entrepreneur-in-Residence and FHIR community member Mark Scrimshire:
I wanted to let you know that we are preparing a FHIR Code-a-thon in Washington DC on Friday April 1st and Saturday April 2nd. We have Susannah Fox opening the event and the Code-a-thon will see the first public access to a prototype CMS Blue Button on FHIR data API. We are busy readying a synthetic data set to make available through the API.
It would be great if you could let fellow Argonauts, and other interested parties, know about our event. Advanced registration is required. People can sign up at http://HealthCa.mp/onfhir/signup
The winners of the FHIR Code-a-thon will receive tickets to the Health Data Palooza where they will have the opportunity to demonstrate their winning solution.

 

I’d say that I’d see you there, but I’m afraid I’ll be surfing in Samoa on those days  – sorry.

Question: Locating the #FHIR end-point

Question:

I have been trying to develop FHIR app using your API. The url “http://fhir2.healthintersections.com.au/Patient” doesnt return me list of patients. Am i hitting the right URL?

Answer:

No. and in fact, this trips lots of people over for lots of servers. Very often, the link provided to the server is a reference to a web page that describes the various end-points the server offers, and the security details for them. For instance, my server offers 2 end points – http://fhir2.healthintersections.com.au/open, which anyone can use, and https://fhir2.healthintersections.com.au/closed, which requires authorization via Smart on FHIR.

So the url you’re looking for is http://fhir2.healthintersections.com.au/open/Patient

 

Question: #FHIR conformance requirements

Question:

  • status has a cardinality of 0..1 , but it is mentioned as required under Description.
  • Similarly, rest/resource/searchParam/modifier  has cardinality of 0..* which means optional, but it is mentioned as required under Description.

Should I go by the cardinality of these elements?

Answer:

Conformance Status does have a cardinality of 0..1. None of us know why it’s 0..1 not 1..1 like all the other conformance resources. See gForge task 9581.

But the ‘required’ under description for all of these elements refers to the value set binding – if you have one of these elements, it is required to come from one of the specified codes in the valueset. So, yes, you should go by the stated cardinality.

IEEE Event: Health Informatics on #FHIR

Health Informatics on FHIR: Opportunities in the New Age of Interoperability

A half day, pre-HIMSS Workshop on Saturday February 27th from 9:30 – 12:30 Westin Las Vegas Hotel, Casino & Spa

Organizers: Professors May Wang, PhD Professor (maywang@bme.gatech.edu) and Mark Braunstein, MD Professor of the Practice (mark.braunstein@cc.gatech.edu – Georgia Tech

Keynote: Charles Jaffe, MD, PhD, CEO of HL7: Toward a Global Health Interoperability Standard (30 minutes)

Panel 1: The FHIR Standard (90 minutes – Moderator: Mark Braunstein) + Panel Discussion / Q&A

  • Grahame Grieve, HL7 FHIR Project Leader: Toward Global Interoperability through the FHIR Standard
  • Josh Mandel, MD Lead Architect for the SMART on FHIR project, Harvard Boston Childrens Hospital: FHIR as a Universal App Platform
  • Charles Jaffe: The Argonaut Project

Panel 2: Healthcare in the Age of Interoperability (90 minutes – Moderator: May Wang) + Panel Discussion / Q&A

  • Robert A Greenes, MD, PhD, Professor, Biomedical Informatics, Arizona State University (co-author Aziz Boxwala, MD, PhD, Meliorix Inc, and mWorksHealth, Inc, La Jolla, CA): Enabling Patient-Centered Care by Liberating Data.
  • Jimeng Sun, PhD, Associate Professor, School of Computational Science and Engineering, Georgia Tech: FHIR-based Clinical Decision Support: An Epilepsy Case Study.
  • Paula Braun, MS Data Science Entrepreneur, CDC: FHIR and Public Health: Death Reporting Case Study
  • Gil Alterovitz, PhD, Harvard/MIT Health Sciences and Technology Division Children’s Hospital Informatics Program: SMART on FHIR Genomics

In addition, there will be up to five poster presentations available to the audience.

See IEEE page for  registration