Announcement

Collapse
No announcement yet.

Multiple ORC-OBR-OBX iterations

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Multiple ORC-OBR-OBX iterations

    Mirth Connect v5.3.0.8232

    How do you loop thru the multiple combinations of ORC/OBR/OBX segments in a result message?
    I have a result similar to the following:

    MSH|^~\&|LAB|Merge||EMR Partner|201008201704||ORU^R01|082017045701|P|2.3|| |NE|NE
    PID|1||M1302^^^MR||TEST^PATIENT^T^^||19670101|M||| 123 8th street^apt.22b^long beach^CA^90802^||(714)555-1212|(714)222-5555||||873lfif|4441113||||||||||
    PV1|1|O|RGH^^^RGH^^^^||||999999^TEST^TEST^^^^^L||9 999^TEST^DOCTOR^^^^^L||||||||288^ALBRIGHT^MD^^^^^L ||V4735|||||||||||||||||||||||||201008201648|
    ORC|RE||15175|||||||||288^ALBRIGHT^MD^^^^^L|
    OBR|1||15175|CBC^COMPLETE BLOOD COUNT^L|R|201008201650|201008201648|||BB^RGH^^^^^^ ^^^^^^RGH||||201008201648|B|288^ALBRIGHT^MD^^^^^L| |||||20100820170246|||F|^|||||100.0||||||||||||||G A
    OBX|1|NM|WBC^WBC^L||4.0|10\S\3/MM\S\3|3.6-11.1||||F|||201008201652|RGH|ADM
    OBX|2|NM|RBC^RBC^L||5.10|10\S\6/MM\S\3|4.50-5.90||||F|||201008201652|RGH|ADM
    OBX|3|NM|HGB^HGB^L||12.5|g/dL|12.0-18.0||||F|||201008201652|RGH|ADM
    OBX|4|NM|HCT^HCT^L||38.3|%|37.0-54.0||||F|||201008201652|RGH|ADM
    OBX|5|NM|MCV^MCV^L||78|um\S\3|77-99||||F|||201008201652|RGH|ADM
    OBX|6|NM|MCH^MCH^L||25.5|PG|25.2-32.7||||F|||201008201652|RGH|ADM
    OBX|7|NM|MCHC^MCHC^L||32.0|g/dL|31.0-36.8||||F|||201008201652|RGH|ADM
    OBX|8|NM|PLT^PLT^L||145|10\S\3/MM\S\3|130-400||||F|||201008201652|RGH|ADM
    OBX|9|NM|LYMPH%^LYMPH %^L||36.0|%|25.0-50.0||||F|||201008201652|RGH|ADM
    OBX|10|NM|MONO%^MONO%^L||2.0|%|2.0-10.0||||F|||201008201652|RGH|ADM
    OBX|11|NM|NEUT%^NEUT %^L||55.0|%|50.0-80.0||||F|||201008201652|RGH|ADM
    OBX|12|NM|EOS%^EOS%^L||4.1|%|0.0-5.0||||F|||201008201652|RGH|ADM
    OBX|13|NM|BASO%^BASO%^L||2.0|%|0.0-2.0||||F|||201008201652|RGH|ADM
    OBX|14|NM|LYMPH#^LYMPH#^L||1.00|10\S\3/MM\S\3|1.00-5.00||||F|||201008201652|RGH|ADM
    OBX|15|NM|MONO#^MONO#^L||1.00|10\S\3/MM\S\3|0.10-1.00||||F|||201008201652|RGH|ADM
    OBX|16|NM|NEUT#^NEUT #^L||2.00|10\S\3/MM\S\3|2.00-8.00||||F|||201008201652|RGH|ADM
    OBX|17|NM|EOS#^EOS #^L||1.50|10\S\3/MM\S\3|0.00-0.40|H|||F|||201008201652|RGH|ADM
    OBX|18|NM|BASO#^BASO #^L||0.10|10\S\3/MM\S\3|0.00-0.20||||F|||201008201652|RGH|ADM
    OBX|19|NM|RDW^RDW^L||10.0|%|13.0-16.0|L|||F|||201008201652|RGH|ADM
    OBX|20|NM|MPV^MPV^L||7.6|um\S\3|7.4-10.4||||F|||201008201652|RGH|ADM
    OBX|21|ST|COM 1:^COMMENT1:^L||*** Unable to give accurate Platelet count due to clumping.||||||F|||201008201652|RGH|ADM
    OBX|22|ST|COMT1^COMMENT:^L||NOT SUITABLE FOR ANALYSIS||||||F|||201008201652|RGH|ADM
    ORC|RE||15175|||||||||288^ALBRIGHT^MD^^^^^L|
    OBR|2||15175|ALC^ALCOHOL,ETHYL^L|R|201008201650|20 1008201648|||BB^RGH^^^^^^^^^^^^RGH||||201008201648 |B|288^ALBRIGHT^MD^^^^^L||||||20100820170246|||F|^ |||||||||||||||||||GA
    OBX|1|NM|ALC^ALCOHOL (ETHANOL)^L||36|mg/dL|0-32|H|||F|||201008201650|RGH|ADM
    ORC|RE||15175|||||||||288^ALBRIGHT^MD^^^^^L|
    OBR|3||15175|A1C^A1C^L|R|201008201650|201008201648 |||BB^RGH^^^^^^^^^^^^RGH||||201008201648|B|288^ALB RIGHT^MD^^^^^L||||||20100820170246|||F|^|||||||||| |||||||||GA
    OBX|1|NM|HBA1C^HBA1C^L||5.0|%|4.2-6.3||||F|||201008201650|RGH|ADM

    I have attached my attempt at a Channel to handle this message. The outbound message template is fashioned after this message.
    I have many questions about the processing of the data thru a channel. msg --> tmp. At this point I'm just trying to understand why the only output I can get is a copy of the message template. None of the data from the inbound msg is passed on to the outbound.
    Inside the iterations of the ORC and OBR and OBX, do I need to have javascript that will move the field/component values from msg to tmp? Such as:
    tmp['ORC'][i]['ORC.1']['ORC.1.1'] = msg['ORC'][i]['ORC.1']['ORC.1.1'].toString();

    thanks
    Mirth Newb, with a lot to learn
    Attached Files

  • #2
    If you just define the outbound data type as HL7 and leave the template blank, it will be sent with the changes you did in the transformer.

    You need to use getSegmentsAfter() code template from here
    http://www.mirthcorp.com/community/f...4608#post24608

    which will give you an XML list of what follows after the ORC, until the next ORC is found. So that's your outer loop. And again on the inside, to get all OBX after the OBR.
    HL7v2.7 Certified Control Specialist!

    Comment


    • #3
      Here is the code I added for looping thru ORC/OBR/OBX segments.

      // for each ORC
      for (var i = 0; i < getArrayOrXmlLength(msg['ORC']); i++) {
      // find all OBR's after the ORC's
      var obrGroup = getSegmentsAfter(msg, msg.ORC[i], 'OBR', false);
      for (var j = 0; j <= obrGroup.length-1; j++) {
      // for each OBR, find all the OBX's
      var obxGroup = getSegmentsAfter(msg, msg.OBR[j], 'OBX', false);
      for (var k = 0; k <= obxGroup.length-1; k++) {
      // process each OBX
      logger.error("Lab Result: ORC " + i + " processed");
      logger.error("Lab Result: OBR " + j + " processed");
      logger.error("Lab Result: OBX " + k + " processed");
      }
      }
      }
      logger.error("Lab Result: is complete ###################");

      I also removed the outbound template.
      I reran the message thru and I am getting the following error:

      Transformer error
      ERROR MESSAGE: Error evaluating transformer
      com.mirth.connect.server.MirthJavascriptTransforme rException:
      CHANNEL: Lab Results
      CONNECTOR: Destination 1
      SCRIPT SOURCE: TRANSFORMER
      SOURCE CODE:
      151:
      152: // field by field mappings for MSH segment
      153:
      154:
      155: // Sending System
      156: tmp['MSH']['MSH.3']['MSH.3.1'] = msg['MSH']['MSH.3']['MSH.3.1'].toString();
      157:
      158: // Sending Facility
      159: tmp['MSH']['MSH.4']['MSH.4.1'] = msg['MSH']['MSH.4']['MSH.4.1'].toString();
      160:
      LINE NUMBER: 156
      DETAILS: ReferenceError: "tmp" is not defined.
      at 3805d9c6-9ed7-4631-820d-622101a22963:156 (doTransform)
      at 3805d9c6-9ed7-4631-820d-622101a22963:332 (doScript)
      at 3805d9c6-9ed7-4631-820d-622101a22963:334
      at com.mirth.connect.server.transformers.JavaScriptFi lterTransformer$FilterTransformerTask.doCall(JavaS criptFilterTransformer.java:154)
      at com.mirth.connect.server.transformers.JavaScriptFi lterTransformer$FilterTransformerTask.doCall(JavaS criptFilterTransformer.java:119)
      at com.mirth.connect.server.util.javascript.JavaScrip tTask.call(JavaScriptTask.java:113)
      at java.util.concurrent.FutureTask.run(Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor.runWorker( Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run (Unknown Source)
      at java.lang.Thread.run(Unknown Source)


      Without an outbound template, how do I process the message from msg to tmp? Does it inherently use the inbound template and the only mapping necessary would be for fields that will actually need to be manipulated?

      Such as needing to suppress zeros on the Patient Account number for the destination system.

      Thanks in advance, again.
      Rob

      Comment


      • #4
        You could blank the fields in your outbound HL7 message and use that as a template. Meaning only the structure and order of the segments, but no values in them.

        What I told you is actually applicable when you apply transformation only on the incoming message, like changing the location of PID.3 to PID.4 and stuff like that. Sorry about that.
        HL7v2.7 Certified Control Specialist!

        Comment


        • #5
          So, if you only have a few fields to transform across the inbound message, how does it get to the outbound side? Do you just leave off the outbound template and manipulate the msg, then the outbound is pulled in from the msg? If that is true, that would be interesting.

          It is probably obvious, but I'm just learning this Mirth Connect engine on my own. Haven't taken a class yet. But, I have many years of experience in health care integration and HL7 v2x.

          Comment


          • #6
            I removed the outbound template (only the inbound template exists and it is all blanked out - just defines structure of message). I have my loop code in place as my only transformer. I am changing the OBX.2 values, just to manipulate something in the message.

            I am receiving no errors, but my output is just the template. None of the data from the inbound message is making it to the outbound side. What am I missing?
            Do I add a final transformer that is "tmp=msg" to send the message out?

            I'm confused. I've attached my current copy of the channel.
            Attached Files

            Comment


            • #7
              Your code had some minor problems having big effects.
              For starters, You were not checking properly for equality. (x =='y' is the correct syntax)

              This is an XML node ->msg['OBX'][k]['OBX.2']['OBX.2.1']
              This is the value at that XML node -> msg['OBX'][k]['OBX.2']['OBX.2.1'].toString()

              When you want to compare values, you should use the second. This was missing.
              When you want to set the value of the XML node, you should use the first, which you correctly did in your code.

              Here is updated code, check the encoded message tab for result.
              Code:
              // for each ORC
              for (var i = 0; i < msg['ORC'].length(); i++) {
              	// find all OBR's after the ORC's
              	var obrGroup = getSegmentsAfter(msg, msg.ORC[i], 'OBR', false);
              	for (var j = 0; j <= obrGroup.length-1; j++) {
              		// for each OBR, find all the OBX's
              		var obxGroup = getSegmentsAfter(msg, msg.OBR[j], 'OBX', false);
              		for (var k = 0; k <= obxGroup.length-1; k++) {
              			// process each OBX
              			if (msg['OBX'][k]['OBX.2']['OBX.2.1'].toString() == "NM") {
              				msg['OBX'][k]['OBX.2']['OBX.2.1'] = "CD";
              			}
              			if (msg['OBX'][k]['OBX.2']['OBX.2.1'].toString() == "ST") {
              				msg['OBX'][k]['OBX.2']['OBX.2.1'] = "TX";
              			}
              			logger.error("Lab Result:  ORC " + i + " processed");
              			logger.error("Lab Result:  OBR " + j + " processed");
              			logger.error("Lab Result:  OBX " + k + " processed");
              			
              		}
              	}
              }
              logger.error("Lab Result: is complete ###################");
              Last edited by siddharth; 08-02-2017, 01:53 AM. Reason: foo
              HL7v2.7 Certified Control Specialist!

              Comment


              • #8
                OK.
                The code you sent back works but only for the first ORC/OBR/OBX(s) combination. The second and third combos are ignored. I made a change and the ORC loop is now:

                i=0;
                for each(orc in msg.ORC)
                i++;

                and this seems to pulling all three ORCs just fine. The following in the loop for the OBR's:

                var obrGroup = getSegmentsAfter(msg, msg.ORC[i], 'OBR', false);
                for (var j = 0; j <= obrGroup.length-1; j++)

                And it only processes the OBR[0] under each ORC. Is it possible my getSegmentsAfter routine is not processing the [i] iteration of the ORC and it only sees the ORC[0]?

                That is what I'm seeing in the logger.errors that I have posted. Any suggestions?

                Thanks in advance.

                Comment


                • #9
                  Here is my sample ORU result message I have been testing with:
                  MSH|^~\&|LAB|Merge||EMR Partner|201008201704||ORU^R01|082017045701|P|2.3|| |NE|NE
                  PID|1||M1302^^^MR||TEST^PATIENT^T^^||19670101|M||| 123 8th street^apt.22b^long beach^CA^90802^||(714)555-1212|(714)222-5555||||873lfif|4441113||||||||||
                  PV1|1|O|RGH^^^RGH^^^^||||999999^TEST^TEST^^^^^L||9 999^TEST^DOCTOR^^^^^L||||||||288^ALBRIGHT^MD^^^^^L ||V4735|||||||||||||||||||||||||201008201648|
                  ORC|RE||15175|||||||||288^ALBRIGHT^MD^^^^^L|
                  OBR|1||15175|CBC^COMPLETE BLOOD COUNT^L|R|201008201650|201008201648|||BB^RGH^^^^^^ ^^^^^^RGH||||201008201648|B|288^ALBRIGHT^MD^^^^^L| |||||20100820170246|||F|^|||||100.0||||||||||||||G A
                  OBX|1|NM|WBC^WBC^L||4.0|10\S\3/MM\S\3|3.6-11.1||||F|||201008201652|RGH|ADM
                  OBX|2|NM|RBC^RBC^L||5.10|10\S\6/MM\S\3|4.50-5.90||||F|||201008201652|RGH|ADM
                  OBX|3|NM|HGB^HGB^L||12.5|g/dL|12.0-18.0||||F|||201008201652|RGH|ADM
                  OBX|4|NM|HCT^HCT^L||38.3|%|37.0-54.0||||F|||201008201652|RGH|ADM
                  OBX|5|NM|MCV^MCV^L||78|um\S\3|77-99||||F|||201008201652|RGH|ADM
                  OBX|6|NM|MCH^MCH^L||25.5|PG|25.2-32.7||||F|||201008201652|RGH|ADM
                  OBX|7|NM|MCHC^MCHC^L||32.0|g/dL|31.0-36.8||||F|||201008201652|RGH|ADM
                  OBX|8|NM|PLT^PLT^L||145|10\S\3/MM\S\3|130-400||||F|||201008201652|RGH|ADM
                  OBX|9|NM|LYMPH%^LYMPH %^L||36.0|%|25.0-50.0||||F|||201008201652|RGH|ADM
                  OBX|10|NM|MONO%^MONO%^L||2.0|%|2.0-10.0||||F|||201008201652|RGH|ADM
                  OBX|11|NM|NEUT%^NEUT %^L||55.0|%|50.0-80.0||||F|||201008201652|RGH|ADM
                  OBX|12|NM|EOS%^EOS%^L||4.1|%|0.0-5.0||||F|||201008201652|RGH|ADM
                  OBX|13|NM|BASO%^BASO%^L||2.0|%|0.0-2.0||||F|||201008201652|RGH|ADM
                  OBX|14|NM|LYMPH#^LYMPH#^L||1.00|10\S\3/MM\S\3|1.00-5.00||||F|||201008201652|RGH|ADM
                  OBX|15|NM|MONO#^MONO#^L||1.00|10\S\3/MM\S\3|0.10-1.00||||F|||201008201652|RGH|ADM
                  OBX|16|NM|NEUT#^NEUT #^L||2.00|10\S\3/MM\S\3|2.00-8.00||||F|||201008201652|RGH|ADM
                  OBX|17|NM|EOS#^EOS #^L||1.50|10\S\3/MM\S\3|0.00-0.40|H|||F|||201008201652|RGH|ADM
                  OBX|18|NM|BASO#^BASO #^L||0.10|10\S\3/MM\S\3|0.00-0.20||||F|||201008201652|RGH|ADM
                  OBX|19|NM|RDW^RDW^L||10.0|%|13.0-16.0|L|||F|||201008201652|RGH|ADM
                  OBX|20|NM|MPV^MPV^L||7.6|um\S\3|7.4-10.4||||F|||201008201652|RGH|ADM
                  OBX|21|ST|COM 1:^COMMENT1:^L||*** Unable to give accurate Platelet count due to clumping.||||||F|||201008201652|RGH|ADM
                  OBX|22|ST|COMT1^COMMENT:^L||NOT SUITABLE FOR ANALYSIS||||||F|||201008201652|RGH|ADM
                  ORC|RE||15175|||||||||288^ALBRIGHT^MD^^^^^L|
                  OBR|2||15175|ALC^ALCOHOL,ETHYL^L|R|201008201650|20 1008201648|||BB^RGH^^^^^^^^^^^^RGH||||201008201648 |B|288^ALBRIGHT^MD^^^^^L||||||20100820170246|||F|^ |||||||||||||||||||GA
                  OBX|1|NM|ALC^ALCOHOL (ETHANOL)^L||36|mg/dL|0-32|H|||F|||201008201650|RGH|ADM
                  ORC|RE||15175|||||||||288^ALBRIGHT^MD^^^^^L|
                  OBR|3||15175|A1C^A1C^L|R|201008201650|201008201648 |||BB^RGH^^^^^^^^^^^^RGH||||201008201648|B|288^ALB RIGHT^MD^^^^^L||||||20100820170246|||F|^|||||||||| |||||||||GA
                  OBX|1|NM|HBA1C^HBA1C^L||5.0|%|4.2-6.3||||F|||201008201650|RGH|ADM

                  Here is the code I put together with your help that finally processed all the segments in the message:
                  // i is index for ORC/OBR, k is index for OBX
                  i = 0;
                  k = 0;
                  // for each ORC
                  for each(orc in msg.ORC)
                  {
                  // change ORC.1 from RE to ZZ for testing purposes
                  if (msg['ORC'][i]['ORC.1']['ORC.1.1'] == "RE") {
                  msg['ORC'][i]['ORC.1']['ORC.1.1'] = "ZZ";
                  }
                  logger.error("ORC #" + i + " ** " + msg.ORC[i]);

                  // change OBR.25 from F to Z for testing purposes
                  if (msg['OBR'][i]['OBR.25']['OBR.25.1'] == "F") {
                  msg['OBR'][i]['OBR.25']['OBR.25.1'] = "Z";
                  }

                  // for each OBR, find all the OBX's
                  logger.error("OBR #" + i + " ** " + msg.OBR[i]);
                  var obxGroup = getSegmentsAfter(msg, msg.OBR[i], 'OBX', false);
                  for each(obx in obxGroup)
                  {
                  // process each OBX
                  if (msg['OBX'][k]['OBX.2']['OBX.2.1'] == "NM") {
                  msg['OBX'][k]['OBX.2']['OBX.2.1'] = "CD";
                  }
                  if (msg['OBX'][k]['OBX.2']['OBX.2.1'] == "ST") {
                  msg['OBX'][k]['OBX.2']['OBX.2.1'] = "TX";
                  }
                  logger.error("Lab Result: OBX " + k + " processed");

                  // increment to the next OBX - this should continue loop to loop
                  k++;
                  }
                  // increment to the next ORC/OBR in msg
                  i++;
                  }
                  logger.error("Lab Result: is complete ###################");


                  I had to treat the ORC & OBR as a pair and use the same index to identify both. Then I used the getSegmentsAfter routine to find the OBXs after each of the OBRs. I used a separate running index for the OBXs and it works. This of course only works if the result has both ORC and OBR as a combo. I'll try other results next and see where this all breaks.
                  Thanks for your help.

                  Comment


                  • #10
                    Happy to help!
                    HL7v2.7 Certified Control Specialist!

                    Comment


                    • #11
                      siddharth,

                      I'm curious how far off of best practices I am at this point for an easy Lab Orders interface and a Results interface. I'm attaching both Channels and would like to know if I can make some improvements for best practices, before I move on to other types of interfaces.
                      I do have a couple transformers included that are just to test handling multiple segments of the same kind, such as OBX's.

                      Thanks again in advance for your expertise and advice.
                      Attached Files
                      Last edited by rkMC; 08-03-2017, 08:05 AM. Reason: forgot to include a detail

                      Comment


                      • #12
                        There are certain areas of improvements in the work that you did. However, I would suggest you go through the new and improved User guide to improvise on the basic things such as mappers.

                        https://www.mirthcorp.com/community/...d.php?t=217379
                        HL7v2.7 Certified Control Specialist!

                        Comment


                        • #13
                          Thanks for the tip. I went back to the results transformers and I added two mappers to remove the prefix on the MRNs. I used the string replacement to do the job:

                          reg-exp = 'ECW*'
                          rep-wth = ''

                          It works. It is much easier than coming up with the javascript code.
                          Is this along the lines of what you were saying for improvements?
                          Thanks

                          Comment


                          • #14
                            Mostly yes. What I did find was you used a mapper and javascript combination to set a value in the outbound message(say PID.3), which you could do in a single step using Message Builder. If you are not comfortable in javascript, I suggest you use message builders instead to do the maps.
                            HL7v2.7 Certified Control Specialist!

                            Comment


                            • #15
                              In Mirth 3.11, I am trying to create a Document Writer destination that will write out certain parts of the OBR and OBX lines into a table. Using the above HL7 message as a source template (https://forums.mirthproject.io/forum...3477#post93477), how are you supposed to create a variable that you can then output onto the document writer? I see that you can use the #foreach ($result in $list) in the document writer but I am brain farting on how to best create those variables. Also if someone has already created this I would be very thankful if someone can point me to it, I can't seem to find anything searching myself, though I'm sure its been done a million times.

                              Comment

                              Working...
                              X