Monday 23 May 2016

Custom Metadata in Mirth Connect

Have you ever wanted to see more details on Mirth's channel dashboard? It would certainly be handy if you could see the patients Id, but depending on the purpose of your channel there might be all sorts of relevant information - Visit ID, Referring Doctor, Etc.

Fortunately Mirth supports this with the feature they have called "Mirth Custom Meta Data".

clip_image001

It's also pretty easy to use, if a little non intuitive. In your channel, navigate to the summary tab and then add fields to the Custom Metadata section

clip_image002

Here I have added a Patients name variable to the existing two (these two are here by default when the channel is created - they can be removed if you don't like them).

The column name is how you would like it to be named on the dashboard. It is pretty restrictive on allowed characters, so don't expect to put in a space or anything like that - basically you are defining a database column in the D_MCMx table in Mirth's database.

clip_image003

The data type also correlates with the database type, so choose one that suits your data.

The Variable Mapping just creates a variable name. It doesn't accept expressions, so you will have to populate your variable elsewhere, most likely in your source transformer like so.

clip_image004

Here I am mapping the HL7 PID.3.1 to my PatientId variable.

That's it, I've done it. The best thing is that not only can I easily identify patients on my dashboard, but also searching for them is much faster (if you have ever run a search for text in the dashboard you will know how painfully slow it normally is).

Further, I can just as easily add any other fields I find useful.

Tuesday 17 May 2016

Converting a .NET date to a Mirth date

A colleague was having a problem in Mirth where they were trying to get a date sent in from a .NET app to a Web Service Listener. It was a patients date of birth, and it was formatted in the .Net WCF service way - ISO 8601.

yyyy-MM-ddTHH:MM:ss

They needed to convert it to a US date format. Here is what they had been trying:
DateUtil.convertDate('yyyy-MM-ddTHH:MM:ss', 'mm/dd/yy', msg['Correspondence']['MedicalDemographics']['Patient']['DateOfBirth'].toString());
This looks fine on the surface, but Mirth doesn't like that "T" sitting in the date. I've never found a workaround other than removing that "T". This is particularly easy to do here because date of birth doesn't have a need for the time anyway. So we just take the first 10 characters and convert with that.

DateUtil.convertDate('yyyy-MM-dd', 'mm/dd/yy', msg['Correspondence']['MedicalDemographics']['Patient']['DateOfBirth'].toString().substring(0, 10));
You can do the same for dates with times, but I will save that for another post.





Friday 13 May 2016

HL7 Message Types

HL7 Message Types are a key part of the HL7 specification as they inform us what a messages purpose is.  I thought it would be helpful to create a beginners guide to introduce the basics that you need to know as you get started out in HL7.

Firstly it’s important to know where to find the message type.  The first line of an HL7 message is always the MSH.  Count the number of |’s and the message type is always after the 8th |.

E.g.          image

The message type is broken into two parts by the ^ character.  The first one is the Message Code which categorizes what the message is for (Administration, Scheduling, Orders, etc.) and the second part is the Event Type that signifies what action is being taken (Add, update, delete etc.)

While researching this post I came across this video on HL7 Message Types which uses this very helpful HL7 tool called HL7 Soup.  You can just paste in your messages and it tells you the details of the message type – very helpful.  I’m using it for the screen shots in this post, so I thought I might share this little bag of goodies with you.

There are dozens of different message types available to be used, but you’ll find that there is just a handful that you will use often, so for the sake of simplicity I'm going to focus just on these.

image

HL7 Soup lists them all – look at the scroll bar to get an idea of how many Message types there are!

ADT:

The most common message type I work with is ADT which stands for Admission, Discharge, and Transfer.  The Event Types available for this are also very numerous, but they are well defined and therefore pretty easy to select

image 

Depending on your use case, the most common message will likely be the A04 for registering an outpatient.  This contains the basic administrative details of a patient, their primary health care provider, and details about the visit.

An A08 is sent to update these values, so is also another popular event type.

There is also an inpatient alternative to the A04, the A28.

SIU:

These are scheduling messages for people, equipment and rooms.  There aren’t too many Event types for this messages type, and I only ever seem to use a few of them (S12, S13, S14, S15, S17)

image

I have a little mnemonic for remembering SIU message; I call them See-You messages as they are often used for scheduling appointments with doctors.

ORM:

Order messages are used for all sorts of purposes, and you’ll probably have a need for them for something.  It really depends on what area/department you are in as to what the use case would be.  Radiology would use them for ordering X-rays, Pathology would use them for specimens etc.  The basic thing to keep in mind is that they are requesting something

There is only one Event Type I have ever used for an ORM, and that is the O01.

image

 

ORU:

These are providing results from one system to another.  All the Event Types are unsolicited, meaning that they are sent once a system produces the results e.g. When the x-rays been examined and a diagnosis has been made.

Within this message are the segments ORC, OBR, and OBX that are used to transfer information of the order about.

The ORC and OBR contain information about the order, while the OBX is the actual values being passed.  I’ve seen all sorts of OBX values, from a list of blood test results, to whole medical documents.

image

Once you have selected the Message Type you can then add each of the Segments you need.  Each Event Type has it’s own list of valid Segments that can be added.  It’s not uncommon for HL7 to be abused, and for Segments that are not valid for the selected Event Type to be included anyway, after all the HL7 format is very flexible.  But I suggest if the design of the message is under your control that you hunt for a different Event Type that better conveys the data you need to transfer.  HL7 has been about for such a long time that it’s pretty thorough and it is very unlikely that you are working on something in medical that hasn’t been done before.

When looking for the appropriate available segments the documentation on HL7 is very comprehensive, but it does take a bit of hunting to find exactly what you need.  Again I found an HL7 Soup feature that solved my problem.

With a message containing the Message Type you’d like to use, click on the header of the message, and you get a nice drop down that list all the Segments available for the current Event Type.  You can then just double click on an item to add one to your message with the correct number of ’|’s.

image

I like to create a follow up post on this one at some point looking either at more message types, or going into the details of particular ones.  I’ll look forward to your feedback.

Transforming repeat fields to single values in Mirth Connect

With HL7, repeat fields are always tricky to deal with. Often when I'm bringing in a repeat field I just want the first instances value for passing on to another system.
An obvious example of this is a patients phone number, where the receiving system in the integration only support a single phone number (or more likely one for home, and one for business).
If we create a default transformer variable in Mirth for the phone number it generates the code:
msg['PID']['PID.13']['PID.13.1'].toString()
As we don’t want this to error when the phone number is repeated we need to select only the first entry by adding an index pointer to the first item:
msg['PID']['PID.13'][0]['PID.13.1'].toString()
And there you have it - or so I thought - Welcome the next problem…
Because my patient is used in several destinations, I have this code as a source transformer. This means that the code is executed for every message coming in.  But not every message has a PID segment. The code without the 0 index works fine still, but my code that only gets the first instance starts showing errors in Mirth's Dashboard.
ERROR (transformer:?): TypeError: Cannot read property "PID.13.1" from undefined
It doesn't actually stop the channel from working, but nobody wants to see the dashboard filled with errors the whole time.
So now I have to change my code again. I added a check that makes sure that field actually exists, and only if it does will it attempt to get the first value.
(msg['PID']['PID.13'].toString() !='')? msg['PID']['PID.13'][0]['PID.13.1'].toString():null
There you have it. This is my recommended technique for handling repeat fields in Mirth. I recommend that every field you want a single value where HL7 supports repeated values should use this code.











Friday 6 May 2016

Personal Pronoun Case in Mirth

Why do older systems always seem to store every field value in capitals?  Why must John Smith be known as JOHN SMITH? - He's not an acronym!
Whatever the reason I'd like to convert these values into the proper personal pronoun casing, so it looks better in my system.
I use Mirth's transformers, so I prefer to do it in a single line of code too.
He's what I use:

msg['PID']['PID.5']['PID.5.2'].toString().toLowerCase().replace( /\b((m)(a?c))?(\w)/g, function($1, $2, $3, $4, $5) { if($2){return $3.toUpperCase()+$4+$5.toUpperCase();} return $1.toUpperCase(); })

Here I'm converting the first name of a patient with a little bit of regex so that the first character in a word will be a capital, and all the other characters are lower case.

It might seem a little overkill to just making the first character uppercase and the rest lower, after all the names each come in their own fields.  But in the case of a street name this fixes each word.
E.g.

Inbound

22 MAIN STREET
Becomes :

22 Main Street

Tuesday 3 May 2016

Adding minutes to appointment dates in Mirth Connect

Adding appointment duration to start date to get the end date

I've got an inbound HL7 appointment message that sends its appointments with a start date and a duration. However the system I'm integrating into needs to have a start date and an end date.

So, for you HL7 guys out there, that means I need to grab the start date from SCH-11.4 and add the duration mins in the SCH-9. It's probably worth noting here that the duration units in the SCH-10 is always going to be 'min' for me, so I can always treat the SCH-9 as the number of minutes - you might have to handle this too.

I've a .NET background, and if I had C# available this would be solved in a second, but as this is Mirth we're stuck with JavaScript.

After fiddling about for a bit I decided that doing this transformer in a Mapper's single line of expression was just too messy - it's possible, but the line is so long that it's impossible to work with. Instead I created a JavaScript Transformer step, basing it on a the mapper I started with as this provides me with all the try/catch syntax.

So first I grab out the appointment date and convert it from an HL7 string to a proper date type.

//Get the appointment startdate and convert it to a datetime
var appointmentDate = DateUtil.getDate("yyyyMMddHHmmss",msg['SCH']['SCH.11']['SCH.11.4'].toString());

Now I have a date I can manipulate it appropriately. I'll get the appointment duration as an integer too.

//Get the appointment length as an integer
var appointmentLength = parseInt(msg['SCH']['SCH.9']['SCH.9.1'].toString())

Online I found some very handy JavaScript functions for adding dates, GetMinutes and SetMinutes. They basically do what they say on the tin, but I did get tripped up there for a second. In my usual .NET coding I'd expect that dateVar.SetMinutes() would return the result of setting the minutes, but it actually just adds them to dateVar directly - no warnings or errors to help me through it, but I got their in the end.

//increase the start date by the appointment Length
appointmentDate.setMinutes(appointmentDate.getMinutes() + appointmentLength);

So that's it, I have the end date, now I just need to convert it back to and HL7 String (though you might not need too) and put it into a channel variable.

Here is the full transformer code.

var mapping;

try {
  //Get the appointment startdate and convert it to a datetime
  var appointmentDate = DateUtil.getDate("yyyyMMddHHmmss",msg['SCH']['SCH.11']['SCH.11.4'].toString());

  //Get the appointment length as an integer
  var appointmentLength = parseInt(msg['SCH']['SCH.9']['SCH.9.1'].toString())

  //increase the start date by the appointment Length
  appointmentDate.setMinutes(appointmentDate.getMinutes() + appointmentLength);

  //Convert the date back to an HL7 Formatted string.
  mapping = DateUtil.formatDate("yyyyMMddHHmmss", appointmentDate);
} catch (e) {
        logger.error(e);
        mapping = '';
}

//put the string into a channel varaiable.
channelMap.put('EndDate', validate( mapping , '', new Array()));