Book Read Free

HL7 for Busy Professionals

Page 6

by Rahul Bhagat


  When you are working with messages, you will be regularly checking their trigger event codes. MSH-9 is one place to check but there is another field that holds the trigger event code. It is the first field of the EVN segment (EVN-1). I personally prefer this field because it is easier to locate in a message. Just look for EVN segment and right after it you have the trigger event code. You can confirm this in the example message. The code is the same in both the fields - A04.

  Once you know the trigger event code, you know the information in the message. For example, since A04 is the trigger event code for patient registration, it implies the message contains information about a patient registration.

  Whenever you are reading an HL7 message, you are looking for specific information. No matter what information you are looking for, you will need to know the field in the message body where that information is. For that, you turn to the interface spec and look for the field that holds that information.

  Let’s take an example. Suppose you want to find out the patient who was registered at the hospital on October 20, 2013 at 3:00 PM. Your technical guys have narrowed down the search to a single message, the example message above, and now you want to confirm that this is the message that has the patient’s name.

  For that, you will first need to locate the field for date and time of registration and confirm that it is October 20, 2013 3:00 PM. After confirming it, you will look for the name of the patient.

  So where could be the date and time of registration in the message? Date and time – that sounds like meta-data. Let’s look in the control segments.

  There are two control segments in our example message - MSH & EVN. If you consult their attribute tables in the spec (HL7 or interface), you will notice that neither has a field for date and time of registration. Welcome to the world of HL7! Dealing with ambiguity is a prerequisite.

  We do have a couple of other date/time fields. MSH-7 (Date/Time of Message) holds date/time for when the message was generated and EVN-2 (Recorded Date/Time) holds the date/time for when the trigger event was fired. Generally, as in our example, these fields have the same value. But if there is a difference, then I’ll go with EVN-2. It sounds more like the date and time of patient’s registration.

  The value in EVN-2 is 201310201500. To interpret this, we again check the EVN attribute table and look for the data format of EVN-2. The format is YYYYMMDDHHMM, where Y is the year, M is the month, and so on. After parsing the content we get the year as 2013, the month as 10 (October), the day as 20 and the time as 1500 or 3PM. This is the message we are looking for.

  Ok, we have our message. Now, on to the second part – finding the patient’s name. Patient’s name is without doubt clinical data. It has to be in a data segment. There are five data segments in the message and that is where we will search for the patient’s name. The data segments are:

  PID – Patient Identification Segment

  NK1 – Next of Kin Segment

  PV1 – Patient Visit Segment

  PV2 – Patient Visit – Additional Info. Segment &

  AL1 – Allergy Information Segment

  It is not hard to guess just by looking at the names of the segments that patient’s name field probably is in the PID segment. Of course, there could be a situation where things are not as obvious (like the date/time field earlier). In that case we will have to search the interface spec for that field. It does get boring sometimes.

  To confirm our hunch we check the attribute table of the PID segment and sure enough the 5th field (PID-5) is the name of the patient. In the message, we count five pipes and the value after the fifth pipe, SEBELUS^KANSAS, is the patient’s name. We have successfully read the message and found that Kansas Sebelus was the patient who was registered at the hospital on October 20, 2013 at 3:00 PM.

  Writing a message is just the reverse of reading it. In the case of writing, you refer to the interface spec and build the message by populating fields with appropriate values. Patient name goes in PID-5, date of birth goes in PID-7 and so on.

  Creating a Message

  Now it’s time to create a message or to be precise, a message profile, where you define its exact structure. This is involved work and usually a business or interface analyst will be doing it full time.

  To create a message, you again start with the trigger event. If you are creating the profile for patient registration, you start with A04.

  A04, like every other trigger event, has its abstract message structure defined in the HL7 spec. The first task is to create a bare bones message structure by eliminating all the optional segments. A message structure made up of only the required segments, like below.

  MSH

  EVN

  PID

  PV1

  This, then, is the simplest message structure of an A04 message.

  Next, depending on additional information that has to be sent, you include other optional segments from the abstract message structure, at appropriate places within the bare bones message structure.

  The example message has three optional segments - information on family members (NK1), additional information about the visit (PV2) and allergy information (AL1). Inclusion of these segments at their appropriate locations changes the message structure.

  MSH

  EVN

  PID

  [{NK1}]

  PV1

  [PV2]

  [{AL1}]

  This then is the message structure of the example A04 message. After the message structure is defined, you customize the attribute table for each segment and the job is done. Another message has been defined. Others can read this information in the interface spec and they will know what an A04 message coming out of your system will look like.

  Segment Attribute Table

  We have talked a lot about the segment attribute table, so let’s take a moment to learn more about it. A segment attribute table contains the list of fields in a segment. It also includes other details such as which fields are optional, which can repeat, etc. All segment attribute tables in the interface spec are derived from the abstract tables in the HL7 spec.

  To customize a segment attribute table, the basic rule is that you can only constrain. You can add more conditions and rules but you cannot remove existing rules defined by HL7.

  What conditions can you add? Look at the columns in the segment attribute table below. Let’s use LEN (length) as an example. The table defines 250 characters as the length of the patient name field (5th field). You can reduce the field length to 50 characters. No problem. What you cannot do is increase field length to 300 characters. That will violate the rule of 250 character limit set by HL7.

  And, as you can see, the column headings of the segment attribute table are not exactly intuitive. So here is a description of what they stand for.

  SEQ: Sequence Number. This is just the position of the field in the segment. Set ID is the first field in the PID segment, Date of Birth is the seventh field, Sex is the eighth and so on.

  LEN: Maximum Length of the Field. Nothing to explain here.

  DT: Data Type. HL7 likes to control how the data is represented in the message and it does so through data types. This column defines the data type of the field.

  OPT: Optionality. This column tells you whether you are required to have a value in the field or if it is optional. A field can be Required (R), Optional (O) or Conditional (C). If it is conditional, it means the optionality is based on another field. For example, Blood Type is a conditional field. It is optional normally but if the patient is admitted for surgery then it becomes a required field.

  Another letter (B) can also be seen in this column. It is for backward compatibility. These fields are present only to support older versions of HL7. Unless you are supporting that version, you should leave those fields empty.

  RP #: Repetition (number). This column tells you if the field can repeat. If the field is blank or has an “N” then no repetition of the field is allowed. If the field has a “Y” then it c
an repeat one or more times. If it has a number, such as Y(3), then that field can repeat up to 3 times. Field repetition values are separated by a ~ (tilde) in the message.

  TBL #: Table Number. For some fields, HL7 only allows a specific set of values. For example, in the Administrative Sex field, only the first letter of patient’s gender (M, F, U) is allowed. You cannot put “Male” in this field. These valid values are defined in a table with a unique table number. If a field takes its values from a table then that table number is listed in this column, as is the case with the sex field.

  ITEM #: ID Number. This is a number that uniquely identifies every field in the HL7 specification document. Field “Date/Time of Birth” is at the seventh field position in the PID segment and its ID is 00110. The same field is at the sixteenth position in the segment NK1 but the ID is the same, 00110. Keep in mind the subtle difference in field names though. “Name” and “Patient Name” are different fields and they have different ID’s.

  ELEMENT NAME: Name of the Field. This is just a descriptive name of the field.

  8. Control Segments

  From the last chapter, if you remember the discussion about the anatomy of a message, control segments are the segments in the head of a message. They only carry meta-data information about a message.

  There are about a dozen control segments defined by HL7. They are all explained in chapter 2 of the HL7 spec. Fortunately, we only need to know about a few of them to account for the vast majority of cases. For example, there are control segments for breaking a very large message into smaller pieces and control segments for batching together a large number of messages. These control segments are not used that frequently and for a general understanding, you can skip them.

  There are five control segments that you really should know about – MSH, EVN, NTE, MSA & ERR. We will start with MSH, the ubiquitous control segment that every message begins with. It is the most important control segment. If you decide five is too many for your precious time and you are only going to read about one, then let this be the one.

  Message Header Segment (MSH)

  The message header segment (MSH) is the most important control segment. Every HL7 message starts with this segment. When an HL7 message is received by a system, it is the MSH that tells the receiving system where this message came from, the information it contains and how it is supposed to be acknowledged.

  This is a segment you want to know well.

  To get a better understanding of the contents of this segment, let’s use the MSH segment from our example A04 message and explore its contents.

  MSH|^~&|SENDER_APP|SENT_BY|RECEIVER_APP|RCVD_BY|201310201500||ADT^A04|MSG_ID001|P|2.5|||AL

  If you break the segment down into its separate fields, it gets easier to figure out the content. Remember | is used to separate fields.

  MSH-1: | (Field Separator)

  MSH-2: ^~& (Encoding Characters)

  MSH-3: SENDER_APP (Sending Application)

  MSH-4: SENT_BY (Sending Facility)

  MSH-5: RECEIVER_APP (Receiving Application)

  MSH-6: RCVD_BY (Receiving Facility)

  MSH-7: 201310201500 (Date/Time of Message)

  MSH-8:

  MSH-9: ADT^A04 (Message Type)

  MSH-10: MSG_ID001 (Message Control ID)

  MSH-11: P (Processing ID)

  MSH-12: 2.5 (Version ID)

  MSH-13:

  MSH-14:

  MSH-15: AL (Accept Acknowledgement Type)

  Note that some of the fields are empty (e.g. MSH-8). This is perfectly fine. Remember, not every field in a segment is required to have a value. If you refer to the segment attribute table of MSH, you can confirm that all missing fields are optional.

  Now, here is a little insider information. There are only a few fields in each segment that are really important and regularly used. That is why you see the usual pipe pattern (||||) in HL7 messages. The consecutive pipes are nothing but empty fields.

  So keeping with our tradition, and saving you precious time, we are going to discuss only the most important fields in a segment.

  In the MSH segment, owing to the fact that it contains most of the meta-data information, there are many important fields. It is the heaviest control segment. Some of these important fields are required and others are optional, but they almost always have a value.

  If you refer to the segment attribute table of the MSH segment, HL7 requires that the following fields always have a value.

  MSH-1: Field Separator

  MSH-2: Encoding Characters

  MSH-7: Date/Time Of Message

  MSH-9: Message Type

  MSH-10: Message Control ID

  MSH-11: Processing ID

  MSH-12: Version ID

  It is easy to find out which fields are required in a segment. Just go to the segment attribute table and look for the letter R in the optionality (OPT) column.

  Besides these required fields, there are some other fields (below) in MSH, which are optional but regularly used. They are important and I think you should know about them.

  MSH-3: Sending Application

  MSH-4: Sending Facility

  MSH-5: Receiving Application

  MSH-6: Receiving Facility

  MSH-15: Accept Acknowledgement Type

  MSH-16: Application Acknowledgement Type

  Keep in mind though that this is only my personal opinion. Others can argue that there are other optional fields that are important and some here are not. I’m not denying it. But from my experience, I believe these are the important fields in the MSH segment.

  Now let’s get familiar with these fields because the name of the field doesn’t tell you even one tenth of the story.

  MSH-1: Field Separator

  Usually, the first field in a segment is the field that follows the segment ID. So technically “encoding characters” should be the first field of MSH segment. But with MSH, there is an anomaly. The first field (MSH-1) always defines the symbol that will be the field separator (delimiter) for the entire message. If you remember the discussion about pipe delimiters in Chapter 6, | is the field separator in HL7 messages and therefore, the first field of MSH. But it doesn’t have to be. You can choose to have a comma (,) or any other symbol as the separator. If you choose to use a comma, the segment will look something like this.

  MSH,^~&,SENDER_APP,SENT_BY,RECEIVER_APP,RCVD_BY,201310201500,,ADT^A04, MSG_ID001,P,2.5,,,AL

  This would be a perfectly legitimate HL7 segment. However, | has become such a de facto standard that no one really uses anything but | as the field delimiter. But it’s good to know that we have the power to change it.

  MSH-2: Encoding Characters

  Encoding Characters are the four symbols ^ ~ & that HL7 reserves for message construction.

  These characters have special meaning, which allows applications reading an HL7 message to distinguish between components and subcomponents of a field, read repeating fields, and translate symbols.

  The encoding characters, in order, are - Component Separator (^), Repetition Separator (~), Escape Character () and Sub Component Separator (&). The position of each character is fixed in the field. First the component separator then the repetition separator and so on.

  By having these symbols in MSH-2, we are basically saying that in this HL7 message, ^ will be used to separate components, ~ will be used to separate multiple occurrences of a field, will be used for special characters and & will be used to separate sub components.

  But shouldn’t this be hardcoded in systems that read HL7 messages, instead of including it in every message?

  Good point. The reason encoding characters are included in every HL7 message is because these characters are customizable too, just like the field separator |.

  HL7 gives you the option of selecting your own encoding characters. If you don’t like ^ and would rather have # as the component separator in your messages then all you have to do is replace ^ with # in MSH-2. As a result, your encoding characters would be
#~&. The # symbol will now be the component separator.

  But this whole discussion is pointless! Over the years, these symbols have become a de facto standard. I’ll bet, many folks who have been working with HL7 for years, don’t know that you can change these symbols. I have never come across a message where a different set of symbols were used.

  Before we move to the next field, you need to know more about the other two encoding characters – the Repetition Separator (~) and the Escape Character ().

  Repetition Separator (~): This is the symbol that separates multiple values in a field. Remember the section on segment attribute table in chapter 7? Some fields are repeatable and they can have multiple values. ~ is the symbol that is used to separate those values in a field.

  In the MSH segment, field MSH-18 and field MSH-21 are repeatable. This means, whenever those fields have two or more values, the values will be separated by the ~ symbol. If a system reading the message comes across the ~ symbol, it will know right away that what follows is the next value of the field.

  Escape Character (): HL7 reserves encoding characters for message construction and they have a special meaning in the message. What happens if you need to use one of those special characters as part of the data? The application reading the message is going to be all confused!!

  In real world applications, the most troublesome of these special characters is the ampersand symbol (&). It is used for “and” (as in Ben & Jerry’s) and is also a commonly used symbol in programming languages like HTML (which could be embedded in an HL7 message). So, sooner or later, you are bound to come across the & symbol in the body of an HL7 message.

 

‹ Prev