Friday, 26 April 2013

HL7 Message Player


I was looking for something related to HL7 on Google & saw a link named HL7 Message Player. The name influenced me to follow the link.

It is a free utility by Caristix. I am bit confused on how to start because I do not want this article to look like product review or advertisement. These are couple of reasons that attracted me to write this small article.
  • It is free
  • A simple utility with interesting/innovative packaging. Can you imagine HL7 Message Player?

Well, the name and look of this utility are like media player but what is the role of player in HL7? This is where the curiosity starts and this curiosity made me to read about this utility.

When I started reading I found that I have used several other utilities that provide similar features. I have also developed some of these features for testing purpose. Almost every HL7 integration developer/tester uses this kind of solutions as part of their routine job for:
  • Testing a connection between HL7 interfaces
  • Receive & store/forward HL7 messages from other interface/system
  • Send HL7 messages to other interface/system

So what’s special about HL7 Message Player? HL7 Message Player does these things in much interesting way:
HL7 Message Player
  1. Record (like record button in audio/video tools)
    1. Starts receiving messages from external system on a port specified
    2. Stores the received messages
    3. I tested this feature by sending around 60K messages in one go & it recorded all & saved in a file in 12+ minutes.
  2. Play (like play button of media player)
    1. Starts sending the messages (recorded earlier) on ip:port specified
  3. Stop (like stop button in audio/video tools)
    1. Stops the current recording
    2. Saves the recorded messages in file

http://caristix.com/products/message-player/get-started-in-5-minutes/ This link will provide you more details about utility.
Many of us (interface developer/tester) would like a simple HL7 simulator & listener which sends/receives HL7 message on single click without doing much of the configurations.
I do not ask you to use this utility for your needs but this utility provides some interesting way to do your routine tasks. That’s what influenced me to write this small article.

Wednesday, 24 April 2013

HL7 Data Analysis Tool


HL7 Data Analysis Tool is a small utility used to analyze HL7 data, extract results based on criteria given and generate statistics report in spreadsheet format.

I developed this small utility for specific purpose. We had a requirement to analyze HL7 messages in specific way. I feel this should be shared to others who might have developed similar custom solutions or are in process to develop.

Problem

My team was using HL7 viewer application to analyze and calculate the data count of different HL7 components from messages based on a filtration criteria (e.g. filter criteria “MSH.5=3MLAB”). However, they were only able to select one category at a time and had to manually enter the totals on a spreadsheet. The same process has to be repeated for each category. This was time consuming.

Solution

A simple lightweight tool that reads HL7 messages from a file and analyze messages to generate statistical report in spreadsheet. You can configure the criteria for analysis in an XML file. For example you might want to all the counts and specific values for MSH.3 (Sending Application), MSH.4 (Sending Facility)

The Solution: Data Analysis Tool:

Data analysis tool provides a UI to the client, wherein the user can upload the HL7 file having multiple messages and then select multiple components and get complete statistical analysis of the data by generating spreadsheet on single click. Primary feature of the Data Extraction Tool are the configurable checkbox and filter textbox.
Checkboxes are loaded from an XML file where you can specify the components which require analysis.
Filter textbox provides you that way to specify criteria that should be satisfied to process the message during analysis. For example MSH.3=MLAB, so only messages having MLAB as sending facility will be processed.

Feature:

  • Select multiple HL7 messages from the single file.
  • Use filter criteria to filter the records
  • Filter criteria is generic and could be applied on any component of the HL7 message.
  • Select multiple components from checkboxes and extract statistical analysis for each component on excel.
  • Add multiple component checkboxes in UI by adding the simple entry in XML file.
  • Generated output is properly formatted and exported to the excel sheet.

Advantage of Tool:

  • Saves significant amount of time required in the manual analysis & recording of HL7 data.
  • Filter criteria is generic and helps to filter message from multiple feeds.
  • Tool is generic and we can use in multiple implementation for analysis of data.
Future upgrades of tool may help in many implementations for analysis and generating reports and to process the feed data as per requirement

User Guide


Step 1: Launch Application & click on "Browse" button
HL7 Data Analysis Tool - Select File

Step 2: Specify wether you want to process all messages of only those which satisfy some match criteria
HL7 Data Analysis Tool - Select Option

Step 3: Select the components which should be analyzed for count & values
HL7 Data Analysis Tool - Select Components

Step 4: Click on "Export To Excel" button to generate analysis report in spreadsheet
Output File is generated under “My Documents\Data Analysis Tool\Result Files” File Name: [Name of file selected in Step#1]_timestamp. For Eg: Test_20121121120405.xls
HL7 Data Analysis Tool - Report


Configure XML


HL7 Data Analysis Tool has a feature where we can add the checkbox (Component level filter criteria) by editing Data Analysis Tool.XML. This would add the checkboxes on the Data Analysis Tool UI.
Location of Data Analysis Tool.XML File: My Documents\Data Analysis Tool\Application Data\ Data Analysis Tool.xml
Each Item in XML represents a check box on UI
HL7 Data Analysis Tool - XML


Please write to me @ deepak30dec2006@gmail.com to get the source code or executable of this utility.

Download Requests

Name Date Comments
Michael Anrake (michael.anrake@gmail.com) 21st Jun 2013 I work with HL7 regularly and found your blog to be useful and informative. If it's still available, I'd like to download your HL7 analysis tool - it looks to be useful for several projects.
Frederic BUISSON (fredericbuisson@hotmail.com) 6th Jun 2013 I was very interested by this tool and try to undertsand how it works and practice a little to help me to supervise my HL7 connexion.
Huw Jones (Huw.Jones6@wales.nhs.uk) 4th Jun 2013 Am interested in your data analysis tool to process data segments in pathology messages to analyse their content within healthcare here in Wales.
Hans Monnig (hans_monnig@yahoo.com) 31st May 2013 I would like to review it.
Moses Rosario (moses.j.rosario@gmail.com) 4th May 2013 I recently viewed your tool for analyzing HL7 files and am very interested in using it. The current method I have is a homegrown spreadsheet app that accomplishes a few of the things you have done in your application.
Guillermo Zeller (gzeller@gmail.com) 25th Apr 2013 I saw your HL7 tool and I am very intersted in that. I am working in a Health Care project, and we need some tool to extract estadistics from the messages. Now a days, we are using excel files... but is not really productive.

Monday, 22 April 2013

HL7 over HTTP


There are few implementations of HL7 v3 around the world and many of CCD/CDA. Another promising standard FHIR – Fast Healthcare Interoperability Resources is on its way.

With all these movements in market, an integration analyst like me (who still loves HL7 v2) loves to see new initiatives on HL7 v2. One such initiative is HL7 over HTTP – specification available on HAPI project site.

When I first read about this about 2 weeks ago, I started exploring the ways to implement it. I had some technical challenges to use this API:
  • I don’t know java (a typical software developer excuse :)
  • I never had an opportunity to use nHAPI (a .NET version of HAPI) in any of my projects. But I found it very easy to learn & use for this exercise.
So I tried a simple implementation in C# for R&D and not to develop an API. I wish to spread this (initiative by HAPI project team) among people who do not know java.
Here is the implementation:

SimpleServer – This class uses System.net.HttpListener

This will listen for HTTP requests on specific URL like http://localhost:8889/
Members:

 public Dictionary<string, EndPoint> EndPoints;  

EndPoint – This class will serve as base class. We will derive this class to create end points.
For example, class ADTEndPoint : EndPoint
This will provide us ADTEndPoint, which will be accessible on http://localhost:8889/ADT
This way we can extend all the required end points from EndPoint class
We will override ProcessMessage() function of EndPoint class in each child class to provide end point specific processing of received HL7 message. Depending on our processing we will return HL7 ACK message or error message.
When we have implemented all the endpoints we will add these to the dictionary of SimpleServer

 server.EndPoints.Add("ADT", new ADTEndPoint());  
 server.EndPoints.Add("LAB", new LABEndPoint());  

server.start() will start the server & our server will listen for HTTP POST requests.

If we receive a request for endpoint which is not available in dictionary of SimpleServer, we will send HTTP 400 – Bad Request with ContentType: text/html.
Whenever server receives any request on ADT end point it will trigger ProcessMessage() function overridden in ADTEndPoint class to process that message and generate ACK for it.
  • If ACK is AA, we will send it with HTTP 200 - OK, ContentType: application-hl7-v2
  • If we encounter any error while processing the message, we will send HTTP 500 with error message - ContentType: text/html
Here is an exapmle of how to implement an End Point by extending EndPoint class

 class ADTEndPoint : EndPoint  
   {  
     public ADTEndPoint()  
     {  
       Name = "ADT";  
     }  
     /// <summary>  
     /// Process Message  
     /// </summary>  
     /// <param name="strMsg">HL7 message in string format</param>  
     /// <returns>HoHResponse</returns>  
     public override HoHResponse ProcessMessage(string strMsg)  
     {  
       HoHResponse resp = new HoHResponse(); //HoH response - contains ackCode, hl7 ack msg & error msg  
       Message msg = null;  
       IMessage hl7Message = null;  
       PipeParser hl7Parser = new PipeParser(); //nHAPI Pipe Parser  
       try  
       {  
         hl7Message = hl7Parser.Parse(strMsg);  
         msg = new Message(hl7Message);  
       }  
       catch (Exception ex) // Exception occured while parsing the message  
       {  
         resp.ackCode = "0"; // send response with custome ack code of 0 - means failure - HTTP 500 will be sent  
         resp.errMsg = "Unable to process incomming message, error: "; + ex.Message; // err msg  
         return resp;  
       }  
       //implement any custom logic to process the message here  
       //after processing the message, let's generate ack  
       IMessage ackMessage = null;  
       try  
       {  
         ackMessage = msg.generateACK(); //this will generate ack(AA) for the message..  
         //ackMessage = msg.generateACK("AE", new MyException("failed processing the message"); //this will generate ack(AE) for the message..  
         resp.ackCode = "AA"; // set response ack code  
         resp.ackMsg = hl7Parser.Encode(ackMessage); // set response ack message  
       }  
       catch (Exception ex)  
       {  
         resp.ackCode = "0"; // send response with custome ack code of 0 - means failure - HTTP 500 will be sent  
         resp.errMsg = "Unable to generate ACK, error: " + ex.Message; // err msg  
       }  
       return resp;  
     }  
   }  


Now, let's initialize our HTTP server & add this end point

 SimpleServer ss = new SimpleServer("http://localhost:8889/");  
 ss.EndPoints.Add("ADT", new ADTEndPoint()); // add ADT endpoint http://localhost:8889/ADT  
 ss.EndPoints.Add("LAB", new LABEndPoint()); // add LABendpoint http://localhost:8889/LAB  
 ss.start(); // start http server  

I do not have any mechanism to provide downloads here, those who are interested in full source code can request me by email. Other than exploring Hl7 over HTTP, this source code also provides ways to use HttpListener & HL7 message/ack creation using nHapi.

Download Requests

Name Date Comments
Ned Shah (nedshah@gmail.com) 3rd Jun 2013 I read your articles on your website re HL7 and found them very informative. I appreciate your help and contribution of your research work with the community. Do you mind share your HL7 Http code with me.
Maqbool Hussain (maqbool110@gmail.com) 25th Apr 2013 I have read your article "HL7 over HTTP", which is very interesting and I enjoyed lot. It's great work and is really helpful in my one of healthcare project. I would like to have complete source code of your sample, explained in article.
Nevin Brittain (nevin@healthnumeric.com) 23rd Apr 2013 I would like to see the .NET solution. Please send me the source code.

Monday, 8 April 2013

Patient Matching


A basic and sensitive need of HIEs today is to eliminate duplicate patient admissions. It is important to identify, link and locate correct patient record in HIE.

Let's walkthrough a very basic patient matching implementation. This shall provide you an overview of big picture.
HL7 Identifier Hierarchy plays important role in this.



A detailed explanation is available in this article Identifier Hierarchy
Let’s consider a sample HIE implementation, where HIE is connected with two source systems, Hospital A and Hospital B

Now suppose Patient John Smith is registered in Hospital A with following demographics

MRN First Name Last Name Gender DOB Street1 SSN Insurance Policy#
HA1234 John Smith M 07/21/1975 105th Ave 435-343-565 33253453

HL7 message will be sent to HIE from Hospital A. Let's assume this patient is new in our HIE, so HIE will create a patient and assign it a unique Person Identifier (EMPI) which will identify all the records of this patient across healthcare facilities participating in HIE. The entire demographics data will be stored in separate repository which will be used for patient matching.

Now suppose John Smith visits Hospital B and registered here with following demographics

MRN First Name Last Name Gender DOB Street1 SSN Insurance Policy#
HB76454 John Smith M 07/21/1975 105th Ave 435-343-565 33253453

HL7 message will be sent to HIE from Hospital B. Now, HIE will try to identify if this patient already exists. It will query its demographics repository. We will discuss matching functionality later in this article. For now let’s suppose we found the match and decided to link John Smith from Hospital B to existing EMPI (of John Smith from Hospital A). So HIE will now maintain two patients from two source systems but both of these will be mapped to single EMPI.
This way we can query John Smith’s all the data across healthcare facilities from HIE.
Now let’s discuss patient matching.
Before deciding to apply any match criteria, it is required to analyze data and decide which data elements can participate in matching.
Suppose, your source systems do not capture/send SSN then it is useless to include SSN in match criteria. Similarly let’s assume you receive SSN for very small percentage of the patient records then it is advisable to consider it with other strong match criteria and assign a very low weightage to SSN. This is one simple example and I just want to emphasize the importance of good data analysis for patient matching.

Master Repository

To start implementing patient matching, you need a repository where you will store demographics data of all the patient records. This repository should contain all the data fields that will participate in matching algorithm & will be decided in data analysis phase.
It is very important to maintain uniform formatting while storing data values in repository. For example:
  • Identify unique set of values for fields like Gender i.e. M,F
  • Identify standard formatting for fields like SSN, Phone, Insurance Policy Number etc.
  • Identify & exclude placeholder values like “UNKNOWN” for address, 1/1/1900 for DOB
  • Exclude any record with test/temporary patient
There could be many other things derived from your analysis. Please consider them all before storing a record in repository.

Normalize your inputs

Before you call your matching algorithm you will have to prepare input parameters for it. These inpur parameters will be used by algorithm to run the matching rules. So format of your input parameters must match the format stored in repository.
If you receive HL7 message with SSN as NNN-NNN-NNN and you store SSN in repository as NNNNNNNNN. In this case you will have to remove hyphens in SSN before you pass this value to algorithm.
We need to do this normalization on all the fields required for matching.

Data Exclusion

Similarly you also need to avoid dummy/placeholder values like
  • SSN: 000-000-000 or 111-111-111 etc.
  • DOB: 1/1/1900
  • Patient Name: Test
  • Street Address: HOMELESS, UNKNOWN
  • Phone: 000000, alphanumeric, Not 10 digits

Query Repository

After you have normalized all the data inputs, you will query the repository to find the match. This query should execute a set of rules in sequence to determine the best possible match for this patient.
Once executed all the rules, this query should return you the match if found else you will treat this as a new patient.

Matching Rules

There could be many rules defined based on the analysis. One important thing is to decide the order in which these rules will be executed. You should have stronger match criteria executed first then go for others.

Example Rules:

  • First Name + Last Name + Gender + DOB + Street + SSN
  • First Name + Last Name + Gender + DOB + Street + Home Phone + Insurance Policy
  • First Name + Last Name + Gender + DOB + Street + Home Phone

Here are few interesting cases that I want to discuss. All of these are related to Incorrect or Out-of-Date Data in repository and a better algorithm can help improving matching rate.
  1. Change in Address
    1. In this case we have receive an existing patient but there is a change in address, may be because patient has relocated
    2. Most of the data elements would be matching except the address. Home Phone can also differ in some cases.
  2. Change in Name
    1. This is a case of change in Family Name after marriage
    2. We have this patient registered in HIE (before marriage) but data in repository is incorrect now.
    3. In this case patient’s last name would be different. Also Address, Home Phone etc.
  3. Misspelled First Name
    1. In this case patient’s First Name would be different.
    2. A simpler solution is to use fuzzy matching on First Name.
    3. But using a fuzzy matching on first name can lead to confusion in case of twins. The probability of twins sharing similar first name is more and in this case most of other data elements would be same.
    4. Also this can lead to confusion in case of similar sounding First Names if not used with care.

To implement these scenarios and identify/link correct patient, you must have some very strong match elements like SSN, Insurance Policy Number and Driver’s License Number in your repository and HL7 feed.

Sample Immunization Records Blockchain using Hyperledger Composer

This is basic and sample Blockchain implementation of Immunization Records using Hyperledger Composer.  Source Code available at:  https...