hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
gender = hl7msg.getField("PID", 8)
if gender in ['m', 'M', 'Male', 'male']:
hl7msg.setField('Male', "PID", 8)
elif gender in ['f', 'F', 'Female', 'female']:
hl7msg.setField('Female', "PID", 8)
else:
print >> engine.logwarn,'Execution cancelled due to incorrect patient gender.'
engine.cancel()
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)
MSH|^~\&|LAB|101|||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM
MSH|^~\&|LAB|101|||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|Female
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHO
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
eventType = hl7msg.getComponent("MSH", 9, 2)
patientId = hl7msg.getField("MRG", 1)
mrgField2Rep3 = hl7msg.getField("MRG", (2, -1))
if (eventType == "A06") and (int(patientId) > 1000) and (mrgField2Rep3 == "z"):
hl7msg.setComponent("xyz", "MRG", (3, 2), 4)
else:
engine.cancel()
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)
MSH|^~\&|1.5|101|||20110915124025||ADT^A06||P|2.3.1
EVN|A06|20130530||
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
MRG|1001|x~y~z|1~a^^^||||
MSH|^~\&|1.5|101|||20110915124025||ADT^A06||P|2.3.1
EVN|A06|20130530||
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
MRG|1001|x~y~z|1~a^^^xyz||||
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
while hl7msg.numSegmentsWithId('NK1') > 0:
hl7msg.removeSegment('NK1')
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
while hl7msg.numSegmentsWithId('NK1') > 1:
hl7msg.removeSegment(('NK1', -1))
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)
def removeOBXsWithBlankField5(hl7msg_):
segIdx = 1
while segIdx <= hl7msg_.numSegmentsWithId('OBX'):
if hl7msg_.getField(('OBX', segIdx), 5) == "":
hl7msg_.removeSegment(('OBX', segIdx))
segIdx -= 1
segIdx += 1
# After removing some of the OBX segments, there might be gaps in the indexes in OBX-1 -
# that is, the message might look like this:
# OBX|1|ST|...
# OBX|2|CE|...
# OBX|4|TX|...
# OBX|6|TX|...
# Note that '3' and '5' are skipped. This function will set those indexes to 1, 2, 3, 4.
def fixOBXsIds(hl7msg_):
segIdx = 1
while segIdx <= hl7msg_.numSegmentsWithId('OBX'):
hl7msg_.setField(str(segIdx), ('OBX', segIdx), 1 )
segIdx += 1
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
removeOBXsWithBlankField5(hl7msg)
fixOBXsIds(hl7msg)
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|1|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
OBX|2|CE|88304|1|T57000^GALLBLADDER^SNM
OBX|3|CE|88304|1|||
OBX|4|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
OBX|5|TX|88305|1|||
OBX|6|TX|88304|1|ORDER DATE: 20110815|
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|1|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
OBX|2|CE|88304|1|T57000^GALLBLADDER^SNM
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
OBX|4|TX|88304|1|ORDER DATE: 20110815|
def insertMultipleNTEs(hl7msg_, pos_, origNTESeg_, comments_):
for i in range(len(comments_)):
newNTESeg = origNTESeg_.clone()
newNTESeg.setField(comments_[i], 3)
hl7msg_.addSegment(pos_, newNTESeg)
pos_ = pos_ + 1
def splitNTEsByCommentWidth(hl7msg_, width_):
for segIdx in range(hl7msg_.numSegments(), 0, -1): #iterate in reverse
hl7seg = hl7msg_.getSegment(segIdx)
if hl7seg.getSegmentName() == 'NTE':
origNTESeg = hl7seg
comment = origNTESeg.getField(3)
comments = util.splitTextByWidth(comment, width_)
hl7msg_.removeSegment(segIdx) #remove orig NTE
insertMultipleNTEs(hl7msg_, segIdx, origNTESeg, comments)
return hl7msg_
def fixNTEsIds(hl7msg_):
idx = None
for segIdx in range(1, hl7msg_.numSegments() + 1):
hl7seg = hl7msg_.getSegment(segIdx)
if hl7seg.getSegmentName() == 'NTE':
if idx == None:
idx = 1
hl7seg.setField(str(idx), 1)
idx = idx + 1
else:
idx = None
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
newHl7msg = splitNTEsByCommentWidth(hl7msg.clone(), 40)
fixNTEsIds(newHl7msg)
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', newHl7msg)
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
NTE|1|20|The
erythrocyte sedimentation rate (ESR), also called a sedimentation rate
or Westergren ESR, is the rate at which red blood cells sediment in a
period of one hour.
NTE|2|20| is the rate at which red blood cells sediment in a period of one hour.
OBX|21|CE|88304|1|T57000^GALLBLADDER^SNM
NTE|1|21|In
vertebrates the gallbladder (cholecyst, gall bladder, biliary vesicle)
is a small organ that aids mainly in fat digestion and concentrates
bile produced by the liver.|FT
OBX|22|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
NTE|1|20|The erythrocyte sedimentation rate
NTE|2|20|(ESR), also called a sedimentation
NTE|3|20|rate or Westergren ESR, is the rate at
NTE|4|20|which red blood cells sediment in a
NTE|5|20|period of one hour.
NTE|6|20| is the rate at which red blood cells
NTE|7|20|sediment in a period of one hour.
OBX|21|CE|88304|1|T57000^GALLBLADDER^SNM
NTE|1|21|In vertebrates the gallbladder |FT
NTE|2|21|(cholecyst, gall bladder, biliary |FT
NTE|3|21|vesicle) is a small organ that aids |FT
NTE|4|21|mainly in fat digestion and |FT
NTE|5|21|concentrates bile produced by the |FT
NTE|6|21|liver.|FT
OBX|22|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
In addition to the getField / getComponent (and setField / setComponent) functions described above, there is an alternate syntax based on two functions: "get" and "set". For example, consider this HL7 message:
MSH|^~\&|LAB||||20170915124025||ORU^R01||P|2.6
PID|201||1200^^^other~1201^^^self~1202^^^hosp||PARRISH^JESSICA||1960/11/21|F
OBX|1|CE|Volume||30|mm3
OBX|2|CE|Mass||37|mg
OBX|3|CE|Score^^ScoringSystem1||1.3|
OBX|4|CE|Score^^ScoringSystem2||5.7|
To retrieve simple fields and components:
hl7msg.get('MSH-3') returns 'LAB'
hl7msg.get('MSH-9-2') returns 'R01'
hl7msg.get('PID-3') returns '1200^^^other~1201^^^self~1202^^^hosp'
To specify field repetitions numerically:
hl7msg.get('PID-3[2]') returns '1201^^^self'
hl7msg.get('PID-3[2]-1') returns '1201'
To specify field repetitions based on a component value:
hl7msg.get('PID-3[^4=self]-4') returns '1201'
To specify segment repetitions numerically:
hl7msg.get('OBX[2]-3') returns 'Mass'
To specify segment repetitions based on a field value:
hl7msg.get('OBX[|3=Score^^ScoringSystem2]-5') returns '5.7'
To specify segment repetitions based on a component value:
hl7msg.get('OBX[|3-3=ScoringSystem2]-5') returns '5.7'
To set a value, using any of the "get" syntax above:
hl7msg.set('PID-3[^4=self]-4', 'zzz')
path = r'c:\cygwin\tmp\lookupFile.csv'
# Note: The "createLookupTable" line can go here, in the "Run" script, but for better performance,
# put it in the "Load" script of your Custom Task.
lookup = util.createLookupTable(path, valuecolumn = 3)
bedNum = lookup.getValue('Richard')
print bedNum # Will print '403' to the MD Link logs
print lookup.getValue('Jessica') # Will print '115'
print lookup.getValue('Maria') # This will fail the execution, because 'Maria' is not in the table.
lookup = util.createLookupTable(path, valuecolumn = 3, defaultvalue = 'XYZ')
print lookup.getValue('Maria') # This will now print 'XYZ'.
# It will no longer fail the execution, because we provided a default value in the "createLookupTable" line.
lookup = util.createLookupTable(path, valuecolumn = 3, defaultaction = 'passthrough')
print lookup.getValue('Maria') # This will print 'Maria', because we specified 'passthrough' as the default action.
lookup = util.createLookupTable(path, ignorecase = True, valuecolumn = 3)
print lookup.getValue('richard') # Will print '403'
print lookup.getValue('JESSICA') # Will print '115'
lookup = util.createLookupTable(path, keycolumn = 3, valuecolumn = 1)
print lookup.getValue('115') # Will print 'Jessica'
print lookup.getValue('320') # Will print 'Steve'
MD Link Jython API provides several functions for managing date and time values:
currentDate = util.getCurrentDateTime('yyyyMMdd') # Will set 'currentDate' to, for example, '20130530'.
timeFromMsg = "2011/10/23-09:34:50:123"
msgDate = util.convertDateTimeFormat(timeFromMsg, 'yyyy/MM/dd-HH:mm:ss:SSS', 'yyyyMMdd') # Sets msgDate to '20111023'
print util.dateIsGreaterThanOrEqualTo(msgDate, currentDate) # Prints 'False'
newMsgDate = util.addToDate(msgDate, 'YEAR', 3) # Sets newMsgDate to '20141023'.
print util.dateIsGreaterThanOrEqualTo(newMsgDate, currentDate) # Prints 'True'.
currentTime = util.getCurrentDateTime('HHmmssSSS') # Sets currentTime to, for example, '051425893'.
msgTime = util.convertDateTimeFormat(timeFromMsg, 'yyyy/MM/dd-hh:mm:ss:SSS', 'HHmmssSSS') # Sets msgTime to '093450123'.
if util.timeIsGreaterThanOrEqualTo(msgTime, currentTime):
print 'Timestamp in message is in the future.' # (Or, technically, in the present millisecond.)
else:
print 'Input msg time is in the past.'
newMsgTime = util.addToTime(msgTime, 'HOUR', -6) # This sets 'newMsgTime' to 'msgTime' minus 6 hours.
# For example, if msgTime was '093450123' (9:34 AM) then newMsgTime will be '033450123' (3:34 AM).
today = util.getCurrentDateTime('yyyyMMdd') #20110322
yesterday = util.addToDate(today, 'DAY', -1)
today = util.convertDateTimeFormat(today, 'yyyyMMdd', 'MM/dd/yyyy')
yesterday = util.convertDateTimeFormat(yesterday, 'yyyyMMdd', 'MM/dd/yyyy')
engine.outputDom = util.makeXMLDocument('TaskData')
util.addXMLElement(engine.outputDom, 'startDate', yesterday)
util.addXMLElement(engine.outputDom, 'endDate', today)
<?xml version="1.0" encoding="UTF-8"?>
<TaskData>
<startDate>03/21/2011</startDate>
<endDate>03/22/2011</endDate>
</TaskData>
engine.outputDoms.add(engine.inputDom)Outputting three copies of the input message is not very useful, so here is an example of implementing a more practical requirement. This example takes a single HL7 message with multiple OBX segments as input, and it outputs one message for each OBX segment:
engine.outputDoms.add(engine.inputDom)
engine.outputDoms.add(engine.inputDom)
def createSingleOBXMessage(hl7msg_, obxId_):
newHL7msg = util.makeHL7Message()
for segIdx in range(1, hl7msg_.numSegments() + 1):
hl7seg = hl7msg_.getSegment(segIdx)
if hl7seg.getSegmentName()!='OBX':
newHL7msg.addSegment(hl7seg)
else:
newHL7msg.addSegment(hl7msg_.getSegment(('OBX', obxId_)))
return newHL7msg
def outputMultipleSingleOBXMessages(hl7msg_):
for obxId in range(1, hl7msg_.numSegmentsWithId('OBX')+1):
newHL7msg= createSingleOBXMessage(hl7msg_, obxId)
engine.outputDoms.add(util.makeXMLDocumentFromHL7Message('TaskData', newHL7msg))
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
outputMultipleSingleOBXMessages(hl7msg)
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|1|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
OBX|2|CE|88304|1|T57000^GALLBLADDER^SNM
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
OBX|4|TX|88304|1|ORDER DATE: 20110815|
Message 1:
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|1|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
Message 2:
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|2|CE|88304|1|T57000^GALLBLADDER^SNM
Message 3:
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
Message 4:
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|4|TX|88304|1|ORDER DATE: 20110815|
Manipulating a string (that is, a sequence of characters) is a common requirement, and the Jython language provides ample facilities for string manipulation. Below are some examples.
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
sendingApp = hl7msg.getField('MSH', 3) # Using the input message below as reference -
# This line sets 'sendingApp' to 'LAB101'.
hl7msg.setField(sendingApp[:3],'MSH', 3) # Sets MSH-3 to 'LAB'.
hl7msg.setField(sendingApp[-3:],'MSH', 4) # Sets MSH-4 to '101'.
# Remove whitespace at beginning and end of PID-7:
hl7msg.setComponent(hl7msg.getComponent('PID', 7, 1).strip(), 'PID', 7, 1)
# Remove whitespace at beginning of OBR-16-2 (the 'l' in 'lstrip' is for 'left'):
hl7msg.setComponent(hl7msg.getComponent('OBR', 16, 2).lstrip(), 'OBR', 16, 2)
# Remove whitespace at end of OBR-16-3 (the 'r' in 'rstrip' is for 'right'):
hl7msg.setComponent(hl7msg.getComponent('OBR', 16, 3).rstrip(), 'OBR', 16, 3)
# Remove any asterisk characters from the beginning and end of OBR-7:
hl7msg.setField(hl7msg.getField('OBR', 7).strip('*'), 'OBR', 7)
# Remove any 'plus sign' characters from the end of OBR-3:
hl7msg.setField(hl7msg.getField('OBR', 3).rstrip('+'), 'OBR', 3)
# Remove any asterisk characters from anywhere in OBR-4-2:
hl7msg.setComponent(hl7msg.getComponent('OBR', 4, 2).replace('*',''), 'OBR', 4, 2)
# Truncate OBX-5 to 20 characters. That is, if the input is more than than 20 characters long,
# remove the 21st character onward:
hl7msg.setField((hl7msg.getField('OBX', 5))[:20], 'OBX', 5)
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)
MSH|^~\&|LAB101||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA|| 1960/11/21 |F
OBR|1||+2080904050+++|34908^lower part *****gall bladder**^L|||*20110815124025**|||||||||^ Dr.Wang^Lucy |||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHOWS HISTOLOGICALLY NORMAL GALLBLADDER TISSUE
MSH|^~\&|LAB|101|||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F
OBR|1||+2080904050|34908^lower part gall bladder^L|||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|3|TX|88304&MDT|1|MICROSCOPIC EXAM SHO
The above section shows how to do simple search and replace in strings, with the 'replace' function. To do more advanced search and replace in strings, the best way is usually to use 'regular expressions'. Regular Expressions allow you to write more advanced search-and-replace operations using a compact syntax for matching characters in the input string.
import re
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
phoneNumber = hl7msg.getField('PID',13)
hl7msg.setField(re.sub(r'[^\d]', '', phoneNumber), 'PID', 13)
# ^^^^^^^^ This is the 'regular expression'.
# The [] define a 'character class' (that is, group of characters),
# The \d specifies all 'digits' (that is, numbers 0 to 9),
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F|^^^^^||3000 BLOOR E^^TOR^ON^X0X 0Y0|1811|(416) 555 - 5555||E|M|DECL|AC06464/01
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21 |F|^^^^^||3000 BLOOR E^^TOR^ON^X0X
0Y0|1811|4165555555||E|M|DECL|AC06464/01
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
import re
hl7msg = util.makeHL7MessageFromXMLDocument(engine.inputDom)
inputAddress = hl7msg.getComponent('PID', 11, 1)
outputAddress = re.sub(r'\s+', ' ', inputAddress)
# In the above regular expression, the \s specifies all whitespace characters - whether that is a regular
# space, a tab, or a newline. The + sign quantifies the whitespace character part, and it specifies
# more than one.
hl7msg.setComponent(outputAddress, 'PID', 11, 1)
engine.outputDom = util.makeXMLDocumentFromHL7Message('TaskData', hl7msg)
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21|F|^^^^^||3000 BLOOR E^^TOR^ON^X0X 0Y0|1811|(416) 555-5555||E|M|DECL|AC06464/01
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||
MSH|^~\&|LAB||||20110915124025||ORU^R01||P|2.4
PID|201||1200||PARRISH^JESSICA||1960/11/21 |F|^^^^^||3000 BLOOR E^^TOR^ON^X0X
0Y0|1811|(416) 555-5555||E|M|DECL|AC06464/01
OBR|70||2080904050||||20110815124025|||||||||^Dr.Wang^Lucy|||||||
OBX|20|ST|2012_34^ERYTHROCYTES|1|4.00|T/l|3.35-7.00|N|||F|||||||||