Question: NEHTA CDA & GP referrals

Question

Is there any example of NEHTA compliant CDA document that I can look at from a perspective of a GP referral form ( http://nhv.org.au/uploads/cms/files/VIC%20-%20GP%20Referral%20(March%202013).rtf )? Is there a tool that can be used to navigate and generate the CDA from a HL7 v2 message?

Answer

There’s been a lot of discussion over the last decade or so about creating a CDA document for these kind of referral forms. I saw a pretty near complete set of functional requirements at one point. But for various reasons, the project to build this has got any funding, either as a NEHTA project, or a standards Australia project (it’s actually been on the IT-14-6-6 project list for a number of years, mostly with my name on it).

So right now, there’s no NEHTA compliant document. As a matter of fact, I don’t know of anything quite that like that from any of the national programs, though no doubt one of my readers will – please comment if you do. There is a project investigating this in the US National Program (S&I framework( but they’re not using CDA.

On the other part of the question, no, unfortunately not. NEHTA provides both C# and java libraries that implement the NEHTA described CDA documents, but it’s an exercise left to the implementer to convert from a v2 message to a CDA document. That’s primarily because there’s so much variability between v2 messages that there’s no safe way to write a single converter

I tried to do that with just AS 4700.2 messages, which are much more constrained than the general case, and it wasn’t really successful; the PITUS project is working on the fundamental alignment needed to get ti right in the future.

#FHIR Connectathon 7, Chicago Sept 13-14

We will be holding the next FHIR connectathon in Chicago on Sept 13/14 associated with the HL7 Plenary Meeting. Once again, anyone interested in implementing FHIR is welcome to attend.

This connectathon, we have 4 tracks (we’re expanding!):

  1. Our standard introductory Patient Track. This is generally the one that’s appropriate for first time attendees
  2. A new track focusing on the conformance resources (Profile and ValueSet), testing interoperability between the various tools and users that are starting to see these used in anger now
  3. Our standard experimental track, focusing on the cutting edge. This time, we’re doing something quite different: we’re going to be testing a basic SMART on FHIR EHR/plug-in scenario
  4. A joint track with DICOM exploring interoperability between the DICOM RESTful services and the FHIR API

What’s really exciting about these is that we’re starting to move into real world interoperability contexts now, focusing more on how FHIR is used in practice than exploring areas of the standard.

There’s full details about the connectathon on the HL7 wiki, with registration details.

I’ll look forward to seeing you there!

License Restrictions on Terminologies

One of the things that we can do in FHIR that can make a significant contribution to interoperability in FHIR is to describe how to use common terminologies in a common fashion. Interoperability is a waste of time if the way one organization uses a code system is different to way another one does. And I’ve learnt, through my implementation experience, that it’s not just enough to say “use this code system”, or “this is the namespace for the code system”. There’s a lot more to say, about what valid  codes are, how versions should be identified consistently, how to exchange information about subsets – which relates heavily to agreeing how to use the code system, etc.

But the terminologies themselves seem hell-bent on making this impossible by their licenses. The problem is that the licenses divide the world into three categories: the provider of the terminology, the creators of implementation systems, and the rest: unlicensed entities who have no rights to the code system.

HL7 and it’s specifications don’t fit into the first two, so end up in the 3rd category. Consider these two license statements:

Licensee is prohibited from distributing the [tx] or subsets of it, except (a) as an integral part of computer applications developed by Licensee for a purpose other than redistribution of vocabulary sources contained in the [tx] and (b) as also subject to (additional rules)…

and this one:

The Licensed Materials may be used only internally at a single entity within your  facilities in the United States or its territories, only by you, your employees, or agents

You may not sell, sublicense, assign or transfer the Agreement or the Licensed Materials or any copy, modification or merged portion or version of the Licensed Materials to any party

With licenses like these, it’s not possible for HL7 to say some really important things about how code systems are used, or to provide examplar information. Or sometimes, to even mention their existence.

And also, btw, there is no way to seek assistance from some external provider of specialist advice. I know that goes on all the time anyway, despite the license, but when you’re writing an open public specification, that’s not really an option.

So for the meantime, the FHIR specification will not be able to describe to it’s user’s how to interoperably use a set of useful and important code systems. Because remember, corporate control over licensed materials (even if they are free) is more important than making things work well in the real world.

 

 

Joint openEHR/FHIR review of Allergy/Intolerance

I previously announced that:

we’re going to do a joint review of the FHIR resources for Allergy/Intolerance (AllergyIntolerance and AdverseReaction), and the openEHR archetype for the equivalent content (openEHR-EHR-EVALUATION.adverse_reaction.v1). The review is going to be done on the openEHR CKM, on a newly prepared archetype that shows the essential content models of the existing archetypes and resources (they’re quite different)

Well, the review is now open on the openEHR CKM, and will close on 28th July. We invite all interested parties – clinicians, programmers, systems analysts, etc, to contribute to the review. Even if all you contribute is a list of what fields you presently support in your existing system, this is a valuable contribution.

This blog post has some further details to help the FHIR/HL7 community with this process.

The archetype that is being reviewed is the result of a thorough review of both the FHIR and openEHR content, informed by the HL7 Allergy DAM and the joint NHS/Microsoft CUI documents.

There are 3 sections below:

  • Discussion of specific issues that arose during the editorial preparation
  • Map between the review archetype and the existing FHIR resources
  • Notes about the review process for the FHIR community

Specific Issues for the Review

1. Who is invited to participate

The review of this archetype is open to everyone, whether they are HL7 members, members of the openEHR community, the FHIR community, or otherwise unengaged. We would like as many people as possible to review the content. Although the content is primarily clinical, and for this reason clinical review is the main focus of this review, we are also very much interested in review from technical people (developers, analysts, standards folks), particularly in regard to whether there are obstacles in this design that would make it difficult to represent existing legacy content (whether in databases or some exchange format) using this logical model.

2. Split between AllergyIntolerance/AdverseReaction

The FHIR archetype is split into 2 parts; the AllergyIntolerance resource that represents the notification of a risk of reaction, and the AdverseReaction that describes specific past reactions. The allergy intolerance resource references 0..* past reactions. This means that you can describe an adverse reaction event without providing an overall assessment of risk.

This proposed archetype does not allow for this separability, and the reaction event details can only be used in the context of the evaluation/notification of the risk. The editorial team expects that there will be a need for an Adverse Event report content model, but that this will need a different content model to the one for reaction event details in this archetype.

This raises design questions about the other resources that currently use AdverseReaction. We are seeking comment about this issue, and there will be further discussion of this on the FHIR and Patient Care mailing lists.

3. Collapsing Exposure

The FHIR AdverseReaction allows for a single event with multiple possible causative agents. This archetype doesn’t. This is related to the previous issue, in that we are reporting issues with substances here, not reporting of Adverse Events. We are seeking comment as to whether existing systems do or should allow for multiple causative agents in the context of evaluating a propensity to a reaction.

4. Element Names

The names of the fields in the archetype are not valid FHIR element names. In the Archetype, these names have UI implications, where they do not necessarily do so in the FHIR resource. Reviewers should assume that the archetype field names will be converted to valid (and sometimes shorter) element names in the resulting FHIR resource, so extensive comment on this is not needed.

5. Core (or 80/20)

OpenEHR and FHIR have different models for extensibility. This influences the way that openEHR and FHIR handle assessment of core. This archetype includes some specific elements that were not part of the FHIR resources. Some of them may become core elements of the FHIR resources, while others might be relegated to extensions. We are interested in comment on this. In particular, we are seeking comment/input from both clinicians and technicians as to which fields in this archetype that existing systems support/collect/(could) populate, as this will help guide this decision.

6. Exposure Category

This is a common feature in many models, but the editorial team is not sure why, and proposes to remove it. We are interested in both clinical arguments for and against its presence, as well as input as to whether existing systems populate it, and if so, how.

Map between the review archetype and the existing FHIR resources

This table provides a basic map between the review archetype and the existing FHIR resources, to assist FHIR reviewers to make their comments.

Open EHR Existing FHIR Resources
Header Scope and Use
Data:

 Substance

 Status

 Seriousness

 Reaction Type

 Comment

 Reaction Event

  Specific Substance

  Certainty

  Manifestation Details

   Manifestation

   Severity

  Reaction Description

  Onset of Reaction

  Duration of Reaction

  Severity of Reaction

  Reaction Details

  Duration of Exposure

  Exposure Category

  Initial Exposure

  Exposure Description

  Exposure Details

  Clinical Management Description

  Reporting Details

  Multimedia

  Information Source

  Reaction Comment

FHIR:

AllergyIntolerance.substance (.code)

AllergyIntolerance.status

AllergyIntolerance.criticality

AllergyIntolerance.sensitivityType

n/a

AdverseReaction / AllergyIntolerance.reaction

AdverseReaction.exposure.substance

AdverseReaction.exposure.causalityExpectation

AdverseReaction.symptom

AdverseReaction.symptom.code

AdverseReaction.symptom.severity

n/a

AdverseReaction.date

n/a

n/a

AdverseReaction.extension

n/a (nearest is AdverseReaction.exposure.date)

AdverseReaction.exposure.type

AdverseReaction.exposure.date

n/a

AdverseReaction.exposure.extension

n/a

AdverseReaction.exposure.extension

n/a

~AdverseReaction.recorder + Provenance

n/a

 

Protocol:

 Date Recorded

 Supporting Clinical Record Information

 Reporting Details

 Reaction Reported?

 Report Comment

 Adverse Reaction Report

 FHIR Record Provenance

 Subject

 Identifier

 Recorder

FHIR

AllergyIntolerance.recordedDate

AllergyIntolerance.sensitivityTest + .extension

 

n/a

n/a

AllergyIntolerance.extension

 

AllergyIntolerance.subject

AllergyIntolerance.identifier

AllergyIntolerance.recorder

Note: all the fields labelled as “n/a” in the second column have no direct equivalent in FHIR. Maybe they should, or perhaps they should just be extensions? The fields that are directly mapped to extensions in the table above are where the archetype fields are openEHR extensibility points, and it wouldn’t make sense to define FHIR elements for them.

The following Resource contents have no direct equivalent in the new archetype. If you think they are still needed, you can make a comment about this in the general comments section of the review.

  • AdverseReaction.identifier (not needed if event is not a separable model)
  • AdverseReaction.didNotOccur (when would this be used?)

Notes about the review process for the FHIR community

We highly recommend that you read the HL7 Allergy and Intolerance DAM (http://wiki.hl7.org/images/1/1b/Allergy_and_Intolerance_INFORM_2013_MAY.pdf), and the MSCUI Allergies documentation (www.mscui.net/DesignGuide/DisplayingAllergies.aspx + www.mscui.net/DesignGuide/RecordingAllergies.aspx) prior to participating in the review.

Also, in the review, remember to review all 3 sections – Header, Data, and Protocol.

To sign up to participate in the review, Go to http://www.openehr.org/ckm/#. You’ll get this page:

sign1

Click on the Sign-up link on the top right:

sign2

Fill it out, and submit:

sign3

Then you get a confirmation Email:

sign4

Click on the Activate your account, and you get this:

sign5

Now, sign in (top right), and then find the FHIR/OpenEHR adverse reaction:

sign7

Double click on it, and you get this:

sign8

The content of the archetype is divided into 4 sections:

  • Header: the scope, purpose, use etc for the archetype, along with a set of references
  • Data: the core clinical content of the archetype
  • Protocol: data elements that relate to how the evaluation was performed
  • Reference Model: underlying content that isn’t important for the review process

 

Exchanging Codes with Translations in practice

All the mainstream clinical coding data types across HL7 (v2, v3, FHIR) and elsewhere (openEHR, IHE, DICOM to a lesser degree) allow for a translations of codes. These are provided because institutions are often not able to get consistency over which terminologies are in use. On the other hand, actually exchanging translations of codes is not that common in my experience. I’ve seen it in the following cases:

  • Coding for lab tests and panels (typically, a combination of local, LOINC, and Snomed codes)
  • Translations for medication codes in the Australian PCEHR (from one system only)

That’s the cases where I’ve seen it in practice. Where else have you actually seen it used? Can we gather some specific cases where it *has* been used (not where it might be a good idea, since complexity always sounds like a good idea at first).

If you have, make a comment on this post, please

Explaining the v3 II Type again

Several conversations in varying places make me think that it’s worth explaining the v3 II type again, since there’s some important subtleties about how it works that are often missed (though by now the essence of it is well understood by many implementers). The II data type is “An identifier that uniquely identifies a thing or object“, and it has 2 important properties:

root A unique identifier that guarantees the global uniqueness of the instance identifier. The root alone may be the entire instance identifier.
extension A character string as a unique identifier within the scope of the identifier root.

The combination of root and extension must be globally unique – in other words, if any system ever sees the same identifer elsewhere, it can know beyond any doubt that this it is the same identifier. In practice, this fairly simple claim causes a few different issues:

  • How can you generate a globally unique identifier?
  • The difference between root only vs. root+extension trips people up
  • How do you know what the identifier is?
  • What if different roots are used for the same thing?
  • The difference between the identifier and the identified thing is an end-less source of confusion
  • How to handle incompletely known identifiers

How can you generate a globally unique identifier? 

At first glance, the rule that you have to generate a globally unique identifier that will never be used elsewhere is a bit daunting. How do you do that? However, in practice, it’s actually not that hard. The HL7 standard says that a root must be either a UUID, or an OID.

UUIDs

Wikipedia has this to say about UUIDs:

Anyone can create a UUID and use it to identify something with reasonable confidence that the same identifier will never be unintentionally created by anyone to identify something else. Information labeled with UUIDs can therefore be later combined into a single database without needing to resolve identifier (ID) conflicts.

UUIDs were originally used in the Apollo Network Computing System and later in the Open Software Foundation‘s (OSF) Distributed Computing Environment (DCE), and then in Microsoft Windows platforms as globally unique identifiers (GUIDs).

Most operating systems include a system facility to generate a UUID, or, alternatively, there are robust open source libraries available. Note that you can generate this with (more than) reasonable confidence that the same UUID will never be generated again – see Wikipedia or Google.

Note that UUIDs should be represented as uppercase (53C75E4C-B168-4E00-A238-8721D3579EA2), but lots of examples use lowercase (“53c75e4c-b168-4e00-a238-8721d3579ea2″). This has caused confusion in v3, because we didn’t say anything about this, so you should always use case-insensitive comparison. (Note: FHIR uses lowercase only, per the IETF OID URI registration).

For people for whom a 10^50 chance of duplication is still too much, there’s an alternative method: use an OID

OIDs

Again, from Wikipedia:

In computing, an object identifier or OID is an identifier used to name an object (compare URN). Structurally, an OID consists of a node in a hierarchically-assigned namespace, formally defined using the ITU-T‘s ASN.1 standard, X.690. Successive numbers of the nodes, starting at the root of the tree, identify each node in the tree. Designers set up new nodes by registering them under the node’s registration authority.

The easiest way it illustrate this is to show it works for my own OID, 1.2.36.146595217:

1 ISO OID root
2 ISO issue each member (country) a number in this space
36 Issued to Australia. See http://www.alvestrand.no/objectid/1.2.36.html – you can use your Australian Company Number (ACN) in this OID space
146595217 Health Intersections ACN

All Australian companies automatically have their own OID, then. But if you aren’t an Australian company, you can ask HL7 or HL7 Australia to issue you an OID – HL7 charges $100 for this, but if you’re Australian (or you have reasons to use an OID in Australia), HL7 Australia will do it for free. Or you can get an OID from anyone else who’ll issue OIDs. In Canada, for instance, Canada Health Infoway issues them.

Within that space, I (as the company owner) can use it how I want. Let’s say that I decide that I’ll use .1 for my clients, I’ll give each customer a unique number, and then I’ll use .0 in that space for their patient MRN, then an MRN from my client will be in the OID space “1.2.36.146595217.1.42.0″

So as long as each node within the tree of nodes is administered properly (each number only assigned/used once), then there’ll never be any problems with uniqueness. (Actually, I think that the chances of the OID space being properly administered are a lot lower than 1-1/10^50, so UUIDs are probably better, in fact)

Root vs Root + extension

In the II data type, you must have a root attribute (except in a special case, see the last point below). The extension is optional. The combination of the 2 must be unique. So, for example, if you the root is a GUID, and each similar object simply gets a new UUID, then there’s no need for a extension:

<id root="53C75E4C-B168-4E00-A238-8721D3579EA2"/>

If, on the other hand, you’re going to use “53C75E4C-B168-4E00-A238-8721D3579EA2″ to identify the set of objects, then you need to assign each object an extension:

<id root="53C75E4C-B168-4E00-A238-8721D3579EA2" extension="42"/>

You’ll need some other system for uniquely assigning the extension to an object. Customarily, a database primary key is used.

With OIDs, the same applies. If you assign a new OID to each object (as is usually done in DICOM systems for images), then all you need is a root:

<id root="1.2.840.113663.1100.16233472.1.911832595.119981123.1153052"/> <!-- picked at random from a sample DICOM image -->

If, on the other hand, you use the same OID for the set of objects, then you use an extension:

<id root="1.2.840.113663.1100.16233472.1.911832595.119981123" extension="1153052"/>

And you assign a new value for the extension for each object, again, probably using a database primary key.

Alert readers will now be wondering, what’s the difference between those two? And the answer is, well, those 2 identifiers are *not* the same, even though they’re probably intended to be. When you use an OID, you have to decide: are sub-objects of the id represented as new nodes on the OID, or as values in the extension. That decision can only be made once for the OID. So it’s really useful how only about 0.1% of OIDs actually say in their registration (see below for discussing registration). So why even allow both forms? Why not simply say, you can’t use an extension with an OID? The answer is because not every extension is a simple number than can be in an OID. It’s common to see composite identifiers like “E34234″ or “14P232344″ or even simply MRNs with 0 prefixed, such as 004214 – none of these are valid OID node values.

Note for Australian readers: the Health Identifier OID requires that IHIs be represented as an OID node, not an extension, like this: 1.2.36.1.2001.1003.0.8003602346555520. Not everyone likes this (including me), but that’s how it is.

The notion that root + extension should be globally unique sounds simple, but I’ve found that it’s real tricky in practice for many implementers.

Identifier Type

When you look at an identifier, you have no idea what type of identifier it is:

<id root="53C75E4C-B168-4E00-A238-8721D3579EA2" extension="42"/>

What is this? You don’t know either what kind of object it identifies, or what kind of identifier it is. You’ll have to determine that from something else than the identifier – the II is *only* the identifier, not anything else. However it might be possible to look it up in a registry. For instance, the IHI OID is registered in the HL7 OID registry. You can look it up here. That can tell you what it is, but note two important caveats:

  • There’s no consistent definition of the type – it’s just narrative
  • There’s no machine API to the OID registry

For this reason, that’s a human mediated process, not something done on the fly in the interface. I’d like to change that, but the infrastructure for this isn’t in place.

So for a machine, there’s no way to determine what type of identifier this is from just reading the identifier – it has to be inferred  from context – either the content around the identifier, or reading an implementation guide.

Different Roots for the same thing?

So what stops two different people assigning different roots to the same object? In this case, you’ll get two different identifiers:

<id root="53C75E4C-B168-4E00-A238-8721D3579EA2" extension="42"/>
<id root="1.2.3.4.5.6.7.8" extension="42"/>

Even though these are same thing. What stops this happening?

Well, the answer is, not much. The idea of registering identifiers is actually to try and discourage this – if the first person registers the identifier, and the second person looks for it before registering it themselves, then they should find it, and use the same value. but if they’re lazy, or the description and/or the search is bad, then there’ll be duplicates. And, in fact, there are many duplicates in the OID registry, and fixing them (or even just preventing them) is beyond HL7.

Difference between identifier and identified thing

In theory, any time you see the same object, it should have the same identity, and any time you see the same identifier, it should be the same object. Unfortunately, however, life is far from that simple:

  • The original system might not store the identifier, and it’s just assigned on the fly by middleware. Each time you see the same object, it’ll get a new identity. Personally, I think this is terrible, but it’s widely done.
  • The same identifier (e.g. lab report id) might be used for multiple different representations of the same report object
  • The same identifier (e.g. Patient MRN) might be used for multiple different objects that all represent the same real world thing
  • The same identifier (e.g. lab order number) might be used for multiple different real world entities that all connect to the same business process

R2 of the datatypes introduced a “scope” property so you could identify which of these the identifier is, but this can’t be used with CDA.

Incomplete identifiers

What if you know the value of the identifier, but you don’t know what identifier it actually is? This is not uncommon – here’s two scenarios:

  • A patient registration system that knows the patient’s driver license number, but not which country/state issued it
  • A point of care testing device that knows what the patient bar-code is, but doesn’t know what institution it’s in

In both these cases, the root is not known by the information provider. So in this case, you mark the identifer as unknown, but provide the extension:

<id nullFlavor="UNK" extension="234234234"/>

Note: there’s been some controversy about this over the years, but this is in fact true, even if you read something else somewhere else.

FHIR: Useability vs Reusability

I regularly get requests to look at a RESTful API for healthcare data from some company out there. Generally, people ask me one of 3 questions:

  • Should this company use FHIR?
  • Is this compatible with FHIR?
  • Why is FHIR not as simple as this API?

Whenever I look at one of these API’s , 3 basic themes stand out:

  1. These APIs solve a single problem
  2. These APIs can be changed
  3. These APIs are unsafe

1. A single Problem

The first is the biggest point; the company has designed the API to do exactly what they want, and it is perfectly tailored to their solution to that problem. They don’t need to ask painful questions like “what if the institution uses a different coding system?”, or “what if information is structured differently in some cases?”. Companies generally can simply decide what to do, and do it. So their APIs will always be simpler than the equivalent FHIR API, where we have to confront the need to deal with these things. Compared to FHIR, the companies API will be more usable. Well, actually, it will look more useable – and if you write denovo code to integrate with it (e.g. a greenfields client) then it will actually be easier – that’s actually ‘operability’. But if you have an already existing system with a different set of assumptions, it will get very difficult really quickly, or may even be impossible. FHIR, on the other hand, spreads the pain around (as equally as we can) – this means that everyone pays a higher price, but ‘interoperability’ is possible. In this way, the FHIR interface is much more reusable across multiple systems and use cases, at the cost of being less easy to use.

Here’s an example. A company doing diabetes monitoring might say, for instance, that a set of vital signs consists of the following JSON:

{
  "HBA1C" : "[value as %]",
  "CrCl" : "[value as mL/min]"
}

But that FHIR could never adopt this kind of approach – it serves only that single use case, and not a more general one involving lab results.

2. Dealing with Change

Part of the reason that companies can make these APIs simple is because if it turns out that the API is insufficient, they can just decide to extend it. That will work varyingly well for them, depending on how tightly the partner applications are linked to the host application life cycle. The slower it is to upgrade the clients (perhaps you have a 4 week app store cycle to deal with, or a 15 month institutional upgrade approval process to deal with), the less you can rely on fixing things as you go, and the more you have to get it right in advance.

As a standard, FHIR changes much more slowly than that again; that’s both it’s great strength and it’s weakness. So FHIR will be more reusable over time too, but this also must come at the cost of not being as easy to use.

3. Unsafe APIs

This is my final theme. Again and again I see that the underlying clinical content model is too simple; it doesn’t deal with the exceptional clinical cases. 99% of patients – the mainstream – will fit the simply model just fine, but the other 1% – either they cannot use the API, or they have to provide flawed or fictional data, or the data is too simple and subsequent analysis services the company claims to provide will be misleading. FHIR can’t afford to do that – the underlying clinical content model has to be robust.

The single most common way that this appears is in the codes – typically, a company will only allow a simple code system, with no exceptions for text, for instance. I understand this – dealing with text exceptions is one of the most painful parts of dealing with H7  content.

I suppose most of these companies will say that the problems I am concerned about simply don’t arise in practice, and if they did, they can respond by changing their API (see #2), but often, the patients affected are the most sick and most needy, and also the least able to express their position. However, as connected health information and the mobile/social web for health becomes more pervasive, this will become a political issue about access, like disabled access (which is relevant to the apps, but not the APIs). In the meantime, the FHIR API has to work in all these cases; this means that it has to be more complex for the simple case.

Usability and Re-usability are very often in conflict with each other.

p.s. FHIR is known for it’s core data element philosophy (sometimes described as it’s 80% philosophy), and so some readers might think my comments above are surprising. But no, this is an important part of the core rule – while we say that we do what 80% of systems do, we never think in terms of 80% of clinical cases. All clinical cases will flow across FHIR interfaces. (When I write operational clinical systems, my rule of thumb is: “1 in a million cases happen every week” in the systems, since roughly a million cases flow across them every week)

 

Question: v2 Referrals

Question:

A typical scenario of tele-consultation is as follows. A patient comes to his nearest hospital. He is assigned to an initially assigned physician (IAP). All the relevant medical information are collected. IAP wants to consult with a specialist physician from a different hospital. So he sends the patient records to the referred hospital.

I assume hospitals are equipped with these EMR systems and they communicate via HL7 V2 messages. How patient medical records can be sent to the referred EMR? Which event to be triggered? What should be the message type? I could not find any HL7v2 message type that could hold all kind of patient records. How to handle such a situation with HL7v2? CDA has that capability. Many revisions are done for HL7v2. Is that already addressed?

Answer

The message type you are looking for is a referral – the IAP is referring the patient to the specialist. Note that some clinicians use the word “referral” strictly in the sense of a full transfer of care, not just a consultation, while others use the term more loosely. The HL7 referral message is suitable for both uses.

The message you are looking for is an REF/RRI message (event I12, chapter 11). It includes the following kinds of information:

  • Referral details
  • Contact and Provider information
  • Observations, and Diagnostic reports
  • Procedures, Problem lists, Allergy Lists
  • Encounter details

Alternatively, there’s the MDM messages in chapter 9 that deal with transfer of medical records – though they leave open the question of what format to use. In your use case, the natural choice would be CDA as the format, but if you want to avoid that, well, you come back to the REF message.

Error in R2 Datatypes

Today, Rick Geimer and Austin Kreisler discovered a rather egregious error in the Data Types R2 specifications. The ISO data types say:

This specification defines the following extensions to the URN scheme:

hl7ii – a reference to an II value defined in this specification. The full syntax of the URN is urn:hl7ii:{root}[:{extension}] where {root} and {extension} (if present) are the values from the II that is being referenced. Full details of this protocol are defined in the HL7 Abstract Data Types Specification

Reference: Section 7.6.2.7 of the ISO Data types

However, if you look through the Abstract Data Types R2 for information about this, you won’t find anything about hl7ii. But there is this, in section 4.13.1.1:

The scheme hl7-att is used to make references to HL7 Attachments. HL7 attachments may be located in the instance itself as an attachment on the Message class, or in some wrapping entity such as a MIME package, or stored elsewhere.

The following rules are required to make the hl7-att scheme work:

  1. Attachments SHALL be globally uniquely identified. Attachment id is mandatory, and an ID SHALL never be re-used. Once assigned, an attachment id SHALL be accosiated with exactly one byte-stream as defined for ED.data.
  2. When receiving an attachment, a receiver SHOULD store that attachment for later reference. A sender is not required to resend the same attachment if the attachment has already been sent.
  3. Attachment references SHALL be resolved against all stored attachments using the globally unique attachment identifier in the address.

(p.s. references are behind HL7 registration wall, but are free)

These are meant to be the same thing, but they are named differently: urn:hl7ii:… vs hl7-att:…

I guess this will have to be handled as a technical correction to one of the two specifications. I prefer urn:hl7ii:.

Comments welcome.

#FHIR + Open ID Connect

I’ve upgraded my FHIR server to support OpenID Connect tokens as part of it’s OAuth based login. This is part of implementing IHE’s IUA profile, though I’m not yet sure whether I’m going to finish that off – I’m still discussing the way that works with the IHE authors.

What this means is that as part of the server login process, my server provides a signed openID Connect token with user identification included in it. There’s now a standard Open ID Connect discovery document available here. Josh Mandel and I would like to make it standard for any FHIR server that uses OAuth, that the URL

[fhir-base]/.well-known/openid-configuration

either returns an OIDC discovery document describing the OAuth part of the server, or redirects to the appropriate location (OIDC puts it on the root of the server, so that would be best place for it).

I added this to help understand how hard it is to support the tokens, since they’re part of the Smart-On-FHIR framework. And the answer’s kind of split – the JSON/identification bits are relatively straight-forward (so far). But the crypto bits – they’re screamingly hard. Because my server is written using Delphi, my choice of crypto libraries is somewhat limited – especially since my code is open source – and in the end I had to go with openSSL. It’s astounding how hard this crypto stuff is. At least half the problem is because of openSSL (see, “openSSL is written by monkeys” – my experience matched that). But it’s not all openSSL – basic crypto is harder than it should be – a myriad of closely related counter-intuitive terms, barely differentiated but incompatible file formats, conflicting or wrong advice, etc. And then it either works, or it doesn’t, and mostly all you get is “didn’t work” as an error (e.g. the signature didn’t verify). But I got nearly there in the end (I still have to work though the hard bits of this) (and thanks to Josh for support).

Anyway, the upshot of all this is the first (as far as I know) open source Delphi implementation of JSON Web Tokens and their associated stack of things (JWK, JWS). This might be useful for other delphi programmers, so:

  • JWT.pas – the core implementation of JSON Web Tokens
  • JSON.pas – the json library it uses
  • libeay32.pas – extensions to the standard Indy OpenSSL headers (the next version of delphi will include these in the standard header file; these are extensions to the XE5 version)

And there’s some tests too. Also, there’s a bunch of other library stuff in Github there that those units depend on.