Announcement

Collapse
No announcement yet.

Grouping OBX by multiple OBRs

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

  • Grouping OBX by multiple OBRs

    I'm completely new to Mirth Connect and would really appreciate some pointers.

    I'm receiving lab results in hl7 format and need to output to html and pdf. I've created a channel which works for simple cases with a single OBR but I'm struggling with a more complex case with multiple OBRs.

    I'd like the output to look something like this:

    OBR 1 - Haematology
    - OBX1
    - OBX2
    - OBX3 ...

    OBR 2 - Biochemistry
    - OBX1
    - OBX2
    - OBX3 ...

    and so on.

    I'm currently using the following javascript to fill a results table:

    var results = new XML('<tbody></tbody>');
    var tr;

    for each (mOBX in msg..OBX) {

    tr = new XML('<tr></tr>');

    tr['td'][0] = '';
    if (mOBX['OBX.8']['OBX.8.1'].toString() != "N") {
    tr['td'][0]['img']['@src'] = '/mnt/media_b/mirth/red_flag.png';
    }
    // Test Name
    tr['td'][1] = mOBX['OBX.3']['OBX.3.2'].toString();
    // Result
    tr['td'][2] = mOBX['OBX.5']['OBX.5.1'].toString() + " "+ mOBX['OBX.6']['OBX.6.1'].toString();
    // Flag - Red if not N = normal
    tr['td'][3] = mOBX['OBX.8']['OBX.8.1'].toString();
    // Reference range
    tr['td'][4] = mOBX['OBX.7']['OBX.7.1'].toString() + " " + mOBX['OBX.6']['OBX.6.1'].toString();

    results[''] += tr;
    }

    channelMap.put("Results",results);
    I then use $Results in my destination HTML template to output the results table.

    How do I modify the above to create a separate table for each of the OBRs in my hl7 file? Each table should have a header with the test name (OBR 4.2). All the results tables are going to be written to the same file/document.

    I can provide an example hl7 file if that's useful.

    Many thanks in advance for your help - it's very much appreciated.

  • #2
    This should help. The trick is to iterate over the whole message.

    Code:
    var results = new XML('<tbody></tbody>');
    var tr;
    
    for each (seg in msg.children()) {
    	switch (seg.name().toString()) {
    		case "OBR":
    			tr = new XML('<tr></tr>');
    			break;
    		case "OBX":
    			tr['td'][0] = '';
    			if (seg['OBX.8']['OBX.8.1'].toString() != "N") {
    				tr['td'][0]['img']['@src'] = '/mnt/media_b/mirth/red_flag.png';
    			}
    			// Test Name
    			tr['td'][1] = seg['OBX.3']['OBX.3.2'].toString();
    			// Result
    			tr['td'][2] = seg['OBX.5']['OBX.5.1'].toString() + " "+ seg['OBX.6']['OBX.6.1'].toString();
    			// Flag - Red if not N = normal
    			tr['td'][3] = seg['OBX.8']['OBX.8.1'].toString();
    			// Reference range
    			tr['td'][4] = seg['OBX.7']['OBX.7.1'].toString() + " " + seg['OBX.6']['OBX.6.1'].toString();
    			results[''] += tr;
    			break;
    	}
    }
    channelMap.put("Results",results);
    Oops - I forgot the header. This can be done in the OBR branch of the switch-case
    Last edited by schillert; 08-02-2019, 06:10 AM.

    Comment


    • #3
      Many thanks for getting back to me it's much appreciated.

      I replaced my Javascript with what you provided but it didn't seem to split the output.

      An example of the HL7 message I'm trying to parse:

      MSH|^~\&|TDL Messaging|TDL|Receiving App|Receiving facility|201810021212||ORM^O01|20181002121215_ORDE RID|T|2.3.1|||AL|||||
      PID|||PATIENT||PATIENT^TEST`^^^||00010101|M|||^^^^ |||||||||||||||||||
      PV1|||GRAHAM^Graham Hogan||||||KERMITDAFROG||||||||||||||||||||||||||| ||||||||
      ORC|OK|ORDERID|0010T197770||IP>||||201810021212||| ||||||||
      OBR|1|ORDERID|0010T197770|^^WinPath||20110924|2011 0924|||||||||KERMITDAFROG^KERMITDAFROG||||||||TDL| I||||||||||||||||||||
      OBX|1|NM|HB^HAEMOGLOBIN^WinPath^HAEMATOLOGY^1^0||1 5.9|g/dL|13.0 - 17.0||||F|||||
      OBX|2|NM|MCHC^MCHC^WinPath^HAEMATOLOGY^2^5||32.3|g/dL| 30 - 35||||F|||||
      OBX|3|NM|RBGF^FASTING BLOOD GLUCOSE^WinPath^BIOCHEMISTRY^3^37||3.0|mmol/L| 3.9 - 5.8|L|||F|||||
      OBR|2|ORDERID|0010T197770|FBCX^FULL BLOOD COUNT^WinPath||20110924|20110924|||||||||KERMITDAF ROG^KERMITDAFROG||||||||TDL|I||||||||||||||||||||
      OBX|1|NM|HCT^HCT^WinPath^HAEMATOLOGY^1^1||0.492||0 .37 - 0.50||||F|||||
      OBX|2|NM|RBC^RED CELL COUNT^WinPath^HAEMATOLOGY^2^2||5.31|x10^12/L|4.40 - 5.80||||F|||||
      OBX|3|NM|MCV^MCV^WinPath^HAEMATOLOGY^3^3||92.7|fL| 80 - 99||||F|||||
      OBX|4|NM|MCH^MCH^WinPath^HAEMATOLOGY^4^4||29.9|pg| 26.0 - 33.5||||F|||||
      OBX|5|NM|RDW^RDW^WinPath^HAEMATOLOGY^5^6||13.1||11 .5 - 15.0||||F|||||
      OBX|6|NM|PLTS^PLATELET COUNT^WinPath^HAEMATOLOGY^6^7||174|x10^9/L|150 - 400||||F|||||
      OBX|7|NM|MPV^MPV^WinPath^HAEMATOLOGY^7^8||11.1|fL| 7 - 13||||F|||||
      OBX|8|NM|WBC^WHITE CELL COUNT^WinPath^HAEMATOLOGY^8^9||6.94|x10^9/L| 3.0 - 10.0||||F|||||
      OBX|9|ST|NEUT^ Neutrophils^WinPath^HAEMATOLOGY^9^10||54.6% 3.79|x10^9/L| 2.0 - 7.5||||F|||||
      OBX|10|ST|LYMP^ Lymphocytes^WinPath^HAEMATOLOGY^10^11||33.6% 2.33|x10^9/L| 1.2 - 3.65||||F|||||
      OBX|11|ST|MONO^ Monocytes^WinPath^HAEMATOLOGY^11^12|| 7.5% 0.52|x10^9/L| 0.2 - 1.0||||F|||||
      OBX|12|ST|EOSI^ Eosinophils^WinPath^HAEMATOLOGY^12^13|| 3.9% 0.27|x10^9/L| 0.0 - 0.4||||F|||||
      OBX|13|ST|BASO^ Basophils^WinPath^HAEMATOLOGY^13^14|| 0.4% 0.03|x10^9/L| 0.0 - 0.1||||F|||||
      NTE|1|All cell populations appear normal.|
      OBR|3|ORDERID|0010T197770|ESR^ERYTHROCYTE SEDIMENT RATE^WinPath||20110924|20110924|||||||||KERMITDAFR OG^KERMITDAFROG||||||||TDL|I||||||||||||||||||||
      OBX|1|NM|ESR^ESR^WinPath^HAEMATOLOGY^1^15||5|mm/hr| 1 - 20||||F|||||
      NTE|1|Note ref range raised in patients over 40|
      I'd like to split each OBR, OBX section into separate tables with a new header above each table.

      Many thanks again.

      Comment


      • #4
        Sorry for the complete and utter nonsense-code from my earlier post.
        I have tested the code below with your sample message and it works.

        Code:
        var results = <body/>;
        var workToDo=false;
        for each (seg in msg.children()) {
        	switch (seg.name().toString()) {
        		case "OBR":
        			if(workToDo) {
        				table.appendChild(tbody.copy());
        				results.appendChild(table.copy());
        				workToDo=false;
        			}
        			var table = <table/>;
        			var thead = <thead/>;
        			thead.appendChild(<tr><td colspan="5">{seg["OBR.4"]["OBR.4.2"].toString()}</td></tr>);
        			table.appendChild(thead.copy());
        			var tbody = <tbody/>;
        			break;
        		case "OBX":
        			workToDo=true;
        			var tr=<tr/>;
        			if (seg['OBX.8']['OBX.8.1'].toString() != "N") {
        				tr.appendChild(<td><img src="/mnt/media_b/mirth/red_flag.png"/></td>);
        			} else {
        				tr.appendChild(<td/>);
        			}
        			// Test Name
        			tr.appendChild(<td>{seg['OBX.3']['OBX.3.2'].toString()}</td>);
        			// Result
        			tr.appendChild(<td>{seg['OBX.5']['OBX.5.1'].toString() + " " + seg['OBX.6']['OBX.6.1'].toString()}</td>);
        			// Flag - Red if not N = normal
        			tr.appendChild(<td>{seg['OBX.8']['OBX.8.1'].toString()}</td>);
        			// Reference range
        			tr.appendChild(<td>{seg['OBX.7']['OBX.7.1'].toString() + " " + seg['OBX.6']['OBX.6.1'].toString()}</td>);
        			tbody.appendChild(tr.copy());
        			break;
        	}
        }
        if(workToDo) {
        	table.appendChild(tbody.copy());
        	results.appendChild(table.copy());
        }
        tmp=<html>{results}</html>;

        Comment


        • #5
          Brilliant - many thanks

          Comment


          • #6
            Forgive my ignorance but I’m slightly unclear on one aspect of your code and would be very grateful if you could explain it to me.

            When using appendChild to add nodes to the table, why do you need to use .copy()?

            Many thanks for your help.

            Comment


            • #7
              Originally posted by schillert View Post
              Sorry for the complete and utter nonsense-code from my earlier post.
              I have tested the code below with your sample message and it works.

              Code:
              var results = <body/>;
              var workToDo=false;
              for each (seg in msg.children()) {
              	switch (seg.name().toString()) {
              		case "OBR":
              			if(workToDo) {
              				table.appendChild(tbody.copy());
              				results.appendChild(table.copy());
              				workToDo=false;
              			}
              			var table = <table/>;
              			var thead = <thead/>;
              			thead.appendChild(<tr><td colspan="5">{seg["OBR.4"]["OBR.4.2"].toString()}</td></tr>);
              			table.appendChild(thead.copy());
              			var tbody = <tbody/>;
              			break;
              		case "OBX":
              			workToDo=true;
              			var tr=<tr/>;
              			if (seg['OBX.8']['OBX.8.1'].toString() != "N") {
              				tr.appendChild(<td><img src="/mnt/media_b/mirth/red_flag.png"/></td>);
              			} else {
              				tr.appendChild(<td/>);
              			}
              			// Test Name
              			tr.appendChild(<td>{seg['OBX.3']['OBX.3.2'].toString()}</td>);
              			// Result
              			tr.appendChild(<td>{seg['OBX.5']['OBX.5.1'].toString() + " " + seg['OBX.6']['OBX.6.1'].toString()}</td>);
              			// Flag - Red if not N = normal
              			tr.appendChild(<td>{seg['OBX.8']['OBX.8.1'].toString()}</td>);
              			// Reference range
              			tr.appendChild(<td>{seg['OBX.7']['OBX.7.1'].toString() + " " + seg['OBX.6']['OBX.6.1'].toString()}</td>);
              			tbody.appendChild(tr.copy());
              			break;
              	}
              }
              if(workToDo) {
              	table.appendChild(tbody.copy());
              	results.appendChild(table.copy());
              }
              tmp=<html>{results}</html>;
              hey just wondering how would incorporate NTE part of the message in this?

              thanks in advance

              Comment

              Working...
              X