nhapinet / nhapi Goto Github PK
View Code? Open in Web Editor NEWnHapi is the .Net port of the original Java project HAPI.
License: Mozilla Public License 2.0
nHapi is the .Net port of the original Java project HAPI.
License: Mozilla Public License 2.0
Given the following message:
MSH|^
&|XXX|LIFE|YYY|EFIL|20160804220502.3210+0100||OUL^R22^OUL_R22|HL7Gtw01565728BAF100|P|2.5||||||8859/115.478.857-3^^^CF^NNITA
PID|1||11^^^PK^PK15478857-3^^^CS^SS2000091931^^^LIS^LIS||TEST@PINO^TEST TEST||19880218|M|||||28888888^PRN^PH^^^^^^^^^28888888|||||15.478.857-3|15478857-3
PV1|1|I|100^^^^^^^^DiagnomedLab||||||||||||||||109101|||||||||||||||||||||||||20160804
SPM|1|2007402901||15^Suero|||||||||||||20160804000000
OBR|1|109101-1|20074029^DN^109101-20074029-201608040000|0302047^GLUCOSA^DN^0302047@1^^DN|||201608040000|||||||||admin241-1||||||||LAB-1|C||^^^201608040000
ORC|SC|109101-1|20074029^DN^109101-20074029-201608040000|109101^DN|CM||^^^201608040000||20160804160500|||admin241-1|||||||||DiagnomedLab^^^^^^FI^^^100
TQ1|1||||||201608040000||R
OBX|1|NM|0302047^GLUCOSA^DN^0302047@1^^DN||85^^Hexoquinasa^false|mg/dL|70 - 100|false||0302047|C|||20160804160300||Utente Demo^Sin RUT
SPM|2|2007402902||15^Suero|||||||||||||20160804000000
OBR|1|109101-2|20074029^DN^109101-20074029-201608040000|0302060^ALBUMINA^DN^0302060@1^^DN|||201608040000|||||||||admin241-1||||||||LAB-1|C||^^^201608040000
ORC|SC|109101-2|20074029^DN^109101-20074029-201608040000|109101^DN|CM||^^^201608040000||20160804160500|||admin241-1|||||||||DiagnomedLab^^^^^^FI^^^100
TQ1|1||||||201608040000||R
OBX|1|NM|0302060^ALBUMINA^DN^0302060@1^^DN||4.5^^BCP Mod.^false|g/dL|3.4 - 5|false||0302060|C|||20160804160300||Utente Demo^Sin RUT
OBR|2|109101-3|20074029^DN^109101-20074029-201608040000|0303024^HORMONA TIROESTIMULANTE^DN^0303024@1^^DN|||201608040000|||||||||admin241-1||||||||LAB-1|C||^^^201608040000
ORC|SC|109101-3|20074029^DN^109101-20074029-201608040000|109101^DN|CM||^^^201608040000||20160804160500|||admin241-1|||||||||DiagnomedLab^^^^^^FI^^^100
TQ1|1||||||201608040000||R
OBX|1|NM|0303024^HORMONA TIROESTIMULANTE^DN^0303024@1^^DN||4.1^^Quimioluminiscencia^false|uUI/mL|0.35 - 5.5|false||0303024|C|||20160804160300||Utente Demo^Sin RUT
OBR|3|109101-4|20074029^DN^109101-20074029-201608040000|0303027^TIROXINA (T4)^DN^0303027@1^^DN|||201608040000|||||||||admin241-1||||||||LAB-1|C||^^^201608040000
ORC|SC|109101-4|20074029^DN^109101-20074029-201608040000|109101^DN|CM||^^^201608040000||20160804160500|||admin241-1|||||||||DiagnomedLab^^^^^^FI^^^100
TQ1|1||||||201608040000||R
OBX|1|NM|0303027^TIROXINA (T4)^DN^0303027@1^^DN||13^^Quimioluminiscencia^false|ug/dL|4.5 - 12.5|false||0303027|C|||20160804160300||Utente Demo^Sin RUT
SPM|3|2007402903||14^Sangre|||||||||||||20160804000000
OBR|1|109101-5|20074029^DN^109101-20074029-201608040000|0301041^HEMOGLOBINA GLICOSILADA^DN^0301041@1^^DN|||201608040000|||||||||admin241-1||||||||LAB-1|C||^^^201608040000
ORC|SC|109101-5|20074029^DN^109101-20074029-201608040000|109101^DN|CM||^^^201608040000||20160804160500|||admin241-1|||||||||DiagnomedLab^^^^^^FI^^^100
TQ1|1||||||201608040000||R
OBX|1|NM|0301041^HEMOGLOBINA GLICOSILADA^DN^0301041@1^^DN||5.3^^HPLC-Tosoh G8^false|%|No Diab\X00E9\tico\X000D.sp\Diab\X00E9\tico bien controlado: <7.0\X000D\.sp\Diab\X00E9\tico medio controlado: 7.00 - 8.00\X000D\.sp\Diab\X00E9\tico mal controlado: >8.00|false||0301041|C|||20160804160300||Utente Demo^Sin RUT
I should get:
1 SPM with 1 ORDER
1 SPM with 2 ORDER
1 SPM with 1 ORDER
But i only get the last SPM and ORDER (hemoglobina)
Im parsing like this:
PipeParser parser = new PipeParser(); IMessage hl7Message = parser.Parse(data);
Then converting it to XML.
DefaultXMLParser xmlParser = new DefaultXMLParser(); string xmlAsString = xmlParser.EncodeDocument(hl7Message).InnerXml;
Im doing something wrong or there is a bug in the api ?
Thanks in advance
For any DFT message (e.g.)
MSH|^~&|CWM|FUJI|UNKNOWN|UNKNOWN|20160711080000||DFT^P03|976503|P|2.5|
EVN|P03|20160711080000
PID||12345^^^RIS|||Test^Patient||197206200000|F|||7 BOB AVEVENUE^^WENDYWOOD^^4309|||m0825123759|3|S|||23377|||||||||||N
PV1||I||||||999^Ref Doctor^||||||||N||A|160998675|||||||||||||||||||||||||20160701130000
GT1|1||EVERYMAN^ADAM^A||2222 HOME STREET^^ISHPEMING^MI^49849^""^|444-33 3333|555-555-2004||||SEL^SELF|444-33 3333||||AUTO CLINIC|2222 HOME STREET^^ISHPEMING^MI^49849^""|555-555-2004|
OBR|1||2015021000043|20310^CT of the soft tissues of the neck, with contrast^CT^4^CT Scan Machine|0|201502101124|201502101124|||||||||^ISMAIL^KHALEEL||||||||IMIL
FT1|1|E292252||201502101124||CG|00279519|F||1|||IMIL|PRIVATE^||||A1|||^ISMAIL^KHALEEL^^^||2015021000043^IMIL||20310^CT of the soft tissues of the neck, with contrast^CT^4^CT Scan Machine|CT
PR1|1|AQ|20310^CT of the soft tissues of the neck, with contrast^CT^4^CT Scan Machine||201502101124|D||||||||||CT|
PipeParser parser = new PipeParser();
IMessage m = parser.Parse(msg);
DFT_P03 dft = m as DFT_P03;
nHapi is unable to parse the GT1 segment, and instead creates a new one
GT1 gt1 = dft.GetGT1(0);
``with nulls instead of parsed values
I "think" this is an issue.
Thank you for maintaining a really excellent project
I am trying to extract the DG1 segments but looks like there is an issue with accessing repeated sections. I am getting null values for all the values in the DG1 segment. Given below is a test which shows what I am doing.
private const string message = @"MSH|^~&|ATHENANET|7598^IN - Ascension - Indiana|ABC::CHL7||201504292358||ADT^A01|109770208|P|2.5||||||||
EVN|A08|201504291158||||
PID||10002|10002||LASTNAME^FIRSTNAME^MIDDLENAME^||19520203|M||900^White|7650 Samsome Street^^San Francisco^CA^46250^UNITED STATES||(510)555-1439^||^|M|||174401788|||43^Not Hispanic or Latino||||||||
GT1|1||Sr^tadd05^M||Gianera ave^^Emeryville^CA^94608|||19560217|||SpouseDG1|1||001.0^General Diagnosis^I9|||Final
DG1|1||002.1^Diagnosis^I9|||FinalDG1|1||001.0^General Diagnosis^I9|||Final
DG1|2||002.1^Diagnosis^I9|||Final
IN1|1|new plan||||||||GP009890||||||||||||||||||||||||||MI0
";
[Test]
public void TestDG1Extract()
{
var parser = new PipeParser();
ADT_A01 regMessage = (ADT_A01)parser.Parse(message);
Assert.AreEqual("Diagnosis", regMessage.GetDG1().DiagnosisCodeDG1.Text.Value);
}
Hi,
There is no documentation at all of how should a user validate a message with this project.
Can someone assist ?
When processing a message with an unexpected segment it throws off the remaining segments from being processed correctly for the message. This seems to be due to the iterators getting to the end of a group and never walking back up to where the iterator was last. Upon the next segment being processed it starts from that point and continues forward, potentially being past the point where the matching segment was in the iterator.
Example:
MSH|^~&|EMR|Sending|Dest|Receiving|20150216152626||ORM^O01|1|P|2.3.1|||AL||||||
EVN|O01|20150216152626
PID||1|1||q^q|||F||||||||||||
In the above message getting Patient's name results in a null value.
Given the following message:
MSH|^~\&|EXACTDATA||ALL|ALL|20101217181500||RDE^O11^RDE_O11|EF010000000071000000_4|T^T|2.5.1
PID|1||7010566270^^^^DODID~EM010000008000000^^^^MR||ZZEDConner^Dean^J^^Mr.||19810611|MALE||WHITE^^HL70005|^^^^^USA^H||||ENGLISH^^HL70296|SINGLE^^HL70002||EF010000000071000000||||NOTHISPANICORLATINO^^HL70189|||||ACTIVEDUTY^^HL70172
PV1|1|OUTPATIENT|^^^MBCC^^AMBLOC||||1853210951^Pennington^Zachary|||MEDICINEGENERAL|||||||1853210951^Pennington^Zachary|||||||||||||||||||01|||||ACTIVE|||20101217181500|20101217184500||||||V
PV2|||V70.0^General medical examination^I9C|||||||||||||||||||||||||||||||||||||||||N
AL1|1|DRUG^^HL70127|70618^Penicillin^RXNORM|MODERATE^^HL70128|Dry Mouth|20100928
ORC|NW|101217-833651^ExD|||ORDERED
RXE|^^^20101217184500|54569-4888-0^Oseltamivir|1||75 mg||^po bid x 5d||N|10||0||||||||||||||||||||20101217184500
RXR|^Oral^HL70162
Since the RXR is following the RXE, it should not be parsed as part of the ORDER_DETAIL group. nHapi PipeParser incorrectly puts it there.
The problem seems to be because of the following lines in PipeParser.DoParse:
if (!name.Equals(lastSegmentName, StringComparison.CurrentCultureIgnoreCase))
{
// If the message iterator passes a segment that is later encountered the message object won't be properly parsed.
// Rebuild the iterator for each segment, or fix iterator logic in handling unexpected segments.
messageIter = new MessageIterator(theMessage, "MSH", true);
lastSegmentName = name;
}
where each search for the right spot to place segment data starts again at the top and looks for the first segment to match by name.
This approach forgets the position of previously placed data. In this scenario, the RXR can't possibly be considered to be a part of the ORDER_DETAIIL because it follows the RXE, and the RXE is not a part of the ORDER_DETAIL.
We've made changes that appear to fix the problem, and would love your review.
Looking at the HL7 standards, I see that the latest version of the HL7 standards is v2.7, which was published in 2011. It's ๐ฟ that nHapi doesn't support v2.7
Hi!
We found an issue with the regular expressions of the PrimitiveRuleBindings (in class DefaultValidation).
The regular expressions have no matching symbols for the start and ending of the string. This way, too many strings match the regular expressions. By adding the ^ and $ symbols at the beginning and ending of the regexs, only the proper strings are matched.
Thanks!
If there is white space after the version number it can cause the parser to be unable to find the proper message class from the class factory. When checking versions in IsValidVersion() method strips trailing/preceding white space using string.Trim() but it doesn't do this in other locations, so the dictionary look up ends up using "2.3 " instead of "2.3" and fails to find an entry for the key. There's also a package version check at some other point that will also fail due to "2.3 " not being equal to "2.3". Primarily if trimming white space is done in one location it probably should be done elsewhere, especially since the version is used as keys in dictionary look ups.
Hi ,
I found that the RelevantClinicalInformation OBR-13 is of type ST but as per HL7 standard it should be CE . http://hl7v2-lab-testing.nist.gov/mu-lab/.
To make it workable I have made it to CE and it worked for me . I am using version Nhapi 1.9. If it is fixed in latest release then please reply.
Thanks
Hi , I'm using this .Net library in one of my project to parse hl7 messages . But, when i try to parse i get this error. I checked the hl7 message that i send, it has the version 2.3.0. I believe the version is not matching with the complied package names. The package name is 2.3 but the version in my message is 2.3.0. Does anybody can tell how can i solve this issue ?
Thanks,
Bhupinder
Recognizing that some message classes are intended for use to implement other messages (e.g. A01 supports A04 and A08), can you please provide a wiki page to illustrate the decoding of an A04 or A08 message. When I parse a message of either type I get an instance of class NHapi.Base.Model.GenericMessage+V25 and this seems unlikely that my application should have to provide special handling to decode a standard message. Have I missed something?
Hi,
I have an issue where the nHapi PipeParser does not appear to be parsing the PID segment of an REF_I12 (Patient Referral) message. If I use the exact same PID segment in a different message (ADT_A01), the PID Segment is parsed. I'm using HL7 version 2.5
The following working code illustrates the issue:
using NHapi.Base.Parser;
using NHapi.Model.V25.Message;
using System;
public class MessageTester
{
public static void Test()
{
var parser = new PipeParser();
var adtMsg = new NHapi.Model.V25.Message.ADT_A01();
adtMsg.MSH.MessageType.MessageCode.Value = "ADT";
adtMsg.MSH.MessageType.TriggerEvent.Value = "A01";
adtMsg.MSH.MessageType.MessageStructure.Value = "ADT_A01";
adtMsg.MSH.FieldSeparator.Value = "|";
adtMsg.MSH.EncodingCharacters.Value = @"^~\&";
adtMsg.MSH.VersionID.VersionID.Value = "2.5";
adtMsg.PID.SetIDPID.Value = "1";
adtMsg.PID.CountyCode.Value = "ZAR";
var name = adtMsg.PID.GetPatientName(0);
name.PrefixEgDR.Value = "Mr";
name.FamilyName.Surname.Value = "LastName";
name.GivenName.Value = "FirstName";
name.NameTypeCode.Value = "L";
adtMsg.PID.AdministrativeSex.Value = "M";
// The following returns a value of "ZAR", as expected.
Console.WriteLine("Pre-Encoded ADT_A01 CountryCode: {0}", adtMsg.PID.CountyCode.Value);
// The following returns a value of 1, as expected.
Console.WriteLine("Pre-Encoded ADT_A01 PatientNameRepititionsUsed: {0}", adtMsg.PID.PatientNameRepetitionsUsed);
var encodedADT_A01 = parser.Encode(adtMsg);
var parsedADT_A01 = parser.Parse(encodedADT_A01) as ADT_A01;
// After parsing the encoded message the following returns a value of "ZAR", as expected.
Console.WriteLine("Parsed ADT_A01 CountryCode: {0}", parsedADT_A01.PID.CountyCode.Value);
// After parsing the encoded message the following returns a value of 1, as expected.
Console.WriteLine("Parsed ADT_A01 PatientNameRepititionsUsed: {0}", parsedADT_A01.PID.PatientNameRepetitionsUsed);
Console.WriteLine("----------------------------------------------------------------");
var refMsg = new NHapi.Model.V25.Message.REF_I12();
refMsg.MSH.MessageType.MessageCode.Value = "REF";
refMsg.MSH.MessageType.TriggerEvent.Value = "I12";
refMsg.MSH.MessageType.MessageStructure.Value = "REF_I12";
refMsg.MSH.FieldSeparator.Value = "|";
refMsg.MSH.EncodingCharacters.Value = @"^~\&";
refMsg.MSH.VersionID.VersionID.Value = "2.5";
refMsg.PID.SetIDPID.Value = "1";
refMsg.PID.CountyCode.Value = "ZAR";
name = refMsg.PID.GetPatientName(0);
name.PrefixEgDR.Value = "Mr";
name.FamilyName.Surname.Value = "LastName";
name.GivenName.Value = "FirstName";
name.NameTypeCode.Value = "L";
refMsg.PID.AdministrativeSex.Value = "M";
// The following returns a value of "ZAR", as expected.
Console.WriteLine("Pre-Encoded REF_I12 CountryCode: {0}", refMsg.PID.CountyCode.Value);
// The following returns a value of 1, as expected.
Console.WriteLine("Pre-Encoded REF_I12 PatientNameRepititionsUsed: {0}", refMsg.PID.PatientNameRepetitionsUsed);
var encodedREF_I12 = parser.Encode(refMsg);
var parsedREF_I12 = parser.Parse(encodedREF_I12) as REF_I12;
// After parsing the encoded message the following returns nothing, where "ZAR" is expected.
Console.WriteLine("Parsed REF_I12 CountryCode: {0}", parsedREF_I12.PID.CountyCode.Value);
// After parsing the encoded message the following returns a value of 0, where 1 is expected.
Console.WriteLine("Parsed REF_I12 PatientNameRepititionsUsed: {0}", parsedREF_I12.PID.PatientNameRepetitionsUsed);
}
}
Any help/pointers to where I may be going wrong will greatly appreciated.
Thank you
In order to point nHapi to custom models one needs to configure App.config to something like:
<Hl7PackageCollection>
<HL7Package name="MyNamspace.CustomModel." version="2.3"/>
</Hl7PackageCollection>
The problem is I cannot set version attribute to anything above like 2.4 or 2.5. Otherwise Parser generates generic messages without resolving to custom classes.
Some messages we process have the date/time of message in MSH formatted with the time zone offset from UTC/GMT. However there isn't a formatting string that matches enough for the ParseExact to work. We can provide a format string of yyyyMMddHHmmsszzz to parse the time zone offset properly.
Hello,
I am trying to parse this information and I cannot get any of the PID, PV1 or OBX information. Any help would be great!
Here is the code.
` message = "MSH|^~&|IDP-32|EPC|||201503080023||ADT^A04|36927017|P|2.2|||AL|NE|" & _
"EVN|A04|201503080022|||ZWALKA00^ZWBCD^FIRSTNAMEABCD^L|201503072341|" & _
"PID|1|EPCL0176469|M000481114|M273045|ZABCDEF^ABCD^M|ABCDE|12345|M||NY|123 MAIN ST^^BUFFALO^NY^14221||(111)111-1111|||S|NO|H00000000000|H00000000000|" & _
"PV1|1|E|ER|ER|||SMITHO00^SMITH^JOE^H^^^MD^^^^^^XX|||||||NONCLI||||ER||SP|||||||||||||||||||EPC||REG|||201503072341||||||||EMERDR^EMERGENCY^DOCTOR^^^^^^^^^^XX|" & _
"OBX|1|ST|1010.1^WEIGHT^CPT4||117.934017|kg|||||F|" & _
"OBX|2|ST|1010.3^HEIGHT^CPT4||182.880000|cm|||||F|" & _
"OBX|3|CE|ADM.ETHNIC^Ethnicity^ADM||NH^NON-HISPANIC||||||F|" & _
"OBX|4|TX|ADM.LANG^Language Spoken^ADM||ENG||||||F|" & _
"OBX|5|TX|VS.HTF^Height (Feet)^ADM||6||||||F|" & _
"OBX|6|TX|VS.WTP^Weight (Pounds)^ADM||260||||||F|" & _
"IN2|1|111-11-1111||||||||||||||||||||||||||||||||||||||||AA|A||||||||||||||||||||(123)123-1234|" & _
"UB2|1||||||11^20150307|"
Dim parser As New PipeParser()
Dim m As IMessage = parser.Parse(message)`
The ORU_R01_ORDER_OBSERVATION class for 2.51 is missing OBSERVATIONRepetitionsUsed property and GetOBSERVATION(int rep) method creating an issue for accessing multiple OBXs. This may be by design, but I am not sure.
When parsing a date/time including milliseconds (for example "19460408000000.000") CommonTM throws an exception on line 236:
float fract = Single.Parse(timeVal.Substring(6));
I can't figure out why exactly, since my OS is set to "en-US", but somehow the parsing of ".000" fails. This is solved by adding a InvariantCulture:
float fract = Single.Parse(timeVal.Substring(6), CultureInfo.InvariantCulture);
nHapi generates GenericMessage instead of proper custom one. It used to work from versions 2.4.0.0-2.4.0.7 but 2.4.0.8 breaks it.
It's pretty straightfoward to test with example "Invalid MSH-9 Example" from http://www.dib0.nl/code/478-nhapi-and-generic-messages-using-the-terser-or-custom-message-classes
I am parsing a 2.4 message and I try to parse the insurance information and it says it does not exist even though I see it in the message and the object knows about the insurance information because it shows INSURANCERepetitionsUsed = 1.
I try the code below and the the error shown:
NHapi.Model.V24.Segment.IN1 in1 = (NHapi.Model.V24.Segment.IN1)m.GetStructure("IN1");
IN1 does not exist in the group NHapi.Model.V24.Message.ADT_A01
Any ideas ?
Hello. I recently started using version 2.5.1 of the nHapi model for a project I'm doing. First of all, thanks to everyone for supporting this library. It is extremely helpful.
I have to create an INSURANCE segment dynamically based on 1..n segments. I had formerly used version 2.3.1 for this purpose. Using that version, I was able to use GetInsurance(index) where it would automatically create the multiple INS segments. With 2.5.1, I'm having trouble finding this functionality. We are OK with one segment but not more. We have also run the reverse scenario where an HL7 message with multiple IN1 and IN2 segments gets parsed into IN1, IN12, IN13, etc. We are trying to programmatically create the same structure. Is there an enhancement I can made to the 2.5.1 IGroup or is there a different way of achieving this functionality that I am not currently aware of?
Thank you.
-Tom
When processing this message:
MSH|^~&|INV|TEST123|FACILITY123|TEST|201503152359||ADT^A08|CHPFQP03|T|2.3
EVN|A08|201503152359
PID|1||30210546||DOE^JOHN^V||19450225|M||1|3001 BLAH RD^APT 430^VOORHEES^NJ^08043||(555)751-1600^PRN^^^^555^7511600|(555)751-1600^OTH^^^^555^7511600||||A1233848515|123-45-6789
PD1|||||||||||
NK1|0001|NAME1^NAME2|O||(555)339-6750^PRN^^^^555^3396750||1
NK1|0002|NOT EMPLOYED|3||||1
PV1|1|I|M^HAHAH^07^3||||035147^CONTTONK ,JOHN J|000000||MED|||||||035147^CONTTONK ,JOHN J|I||P^20150314||||||||||||||||||||||||201503142101
GT1|0001|123562492^^^MFJ^GN|DOE^JOHN^V||3001 BLAH RD^APT 430^VOORHEES^NJ^08043|(555)751-1600^PRN^^^^555^7511600||89450225|||S|123-45-6789||||NOT EMPLOYED
IN1|0001|P02||MEDICARE I/P ONLY|PO BOX 1234^^MECHANICSBURG^PA^123456789||(555)235-8048^PRN^^^^555^2358048|||||||NA|M|DOE^JOHN^V^^^^L|S|19450225|3001 BLAH RD^APT 430^VOORHEES^NJ^08043|||1||||||||HS||||||123562492A|||||||M||N
IN2||123-45-6789|^NOT EMPLOYED^^^^^^^^L||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||(555)751-1600^PRN^^^^555^7511600|||||||NOT EMPLOYED^L||
IN1|0002|Q04|22326|CHARITY 123 HEALTH|CLAIMS PROCESSING DEPT^PO BOX 1234^LONDON^KY^40742||(555)682-9091^PRN^^^^555^6829091|||||||NA|W|DOE^JOHN^V^^^^L|S|12350225|3001 BLAH RD^APT 430^VOORHEES^NJ^08043|||2||||||||HS||||||12302249|||||||M||N
IN2||123-45-6789|^NOT EMPLOYED^^^^^^^^L||||||||||||||||||||||12326||||||||||||||||||||||||||||||||||||||(555)751-1600^PRN^^^^555^7511600|||||||||
ACC|201503141800|I||||
the resulting structure contains segments (note "IN12"):
MSH
EVN
PID
PD1
NK1
NK1
PV1
GT1
IN1
IN2
IN12
IN22
ACC
(All the data inside IN12 and IN22 is valid, following the order in which they appear in the original message.)
The expected structure of the parsed message:
MSH
EVN
PID
PD1
NK1
NK1
PV1
GT1
IN1
IN2
IN1
IN2
ACC
Note that the other repeated segment, NK1, turns out just fine.
Looking through the code trying to figure out what's going on, but just thought I'd mention it. Will post any findings -- IF I do manage to solve it properly...
It's hard to create a message from scratch using nHapi, and it's almost impossible when it's necessary to fill repeatible fields (e.g. PID-3).
I managed to go on using the Terser like this (it seems that the repetition is created when necessary, but it's needed the strange repetition PID-3-1 and PID-3(1)-1).
terser.Set("/PATIENT/PID-3-1", "a");
terser.Set("/PATIENT/PID-3(1)-1", "bb");
terser.Set("/PATIENT/PID-3(2)-1", "ccc");
terser.Set("/PATIENT/PID-3(3)-1", "dddd");
terser.Set("/PATIENT/PID-3(4)-1", "eeeee");
The HAPI library already provides a better and easier set functionality:
http://hl7api.sourceforge.net/v231/apidocs/ca/uhn/hl7v2/model/v231/segment/PID.html
If you have a UNC string that contains a character that matches a special character (X,Z,C,M,H,N,S) immediately after a '' character the escape class treats this as you intended to have the special escaped special character there even if the third character in the sequence doesn't match. For example one special character encoding should be \S\ but if you have \Server\Share those shouldn't be flagged as special character because the next slash is not immediately following.
Should be to a maximum of 65536 characters, as used in NTE-3 for example.
Even if a message does not contain a segment, the repetitions used property can be still 1.
E.g. in the test called TestOBR5RepeatingValuesMessage (in ParserTest.cs), the ORU message does not contain NK1 segments, but adding the following assert fails the test:
Assert.AreEqual(0, oru.GetPATIENT_RESULT(0).PATIENT.NK1RepetitionsUsed);
I have the problem with all sort of messages (2.4 version too).
Failed processing messages with 2.1 version. All the DLLs were in place, so wasn't a config issue. The error text brought me to this line inside LoadBaseVersions method in NHapi.Base.PackageManager:
string[] versions = new string[] { "2.2", "2.3", "2.3.1", "2.4", "2.5" };
I added "2.1" to that array, and all started working.
Would hate to modify (and therefore having to maintain) your (original) code, so was wondering what were the reasons for pulling "2.1" from that list? (I'm assuming it was there at some point in the past...?)
Thanks
The 2.5.1 standard defines RSP_K21 twice. 3.3.56 allows RSP_K21_QUERY_RESPONSE to repeat. Can we have RSP_K21_QUERY_RESPONSE set to allow repeating?
3.3.56 Get Person Demographics (QBP) and Response (RSP) (Events Q21 andK21)
3.3.57 Find Candidates (QBP) and Response (RSP) (Events Q22 and K22)
Running with 2.4.0.11 DLLs, I'm seeing the following behavior:
Test message:
MSH|^~\&|MILL|EMRY|MQ|EMRY|20150619155451||ADT^A08|Q2043855220T2330403781X928163|P|2.3||||||8859/1
EVN|A08|20150619155451
PID|1|935307^^^EUH MRN^MRN^EH01|25106376^^^TEC MRN~1781893^^^CLH MRN~935307^^^EUH MRN~5938067^^^EMPI|1167766^^^CPI NBR^^EXTERNAL~90509411^^^HNASYSID~10341880^^^HNASYSID~50627780^^^HNASYSID~5938067^^^MSG_CERNPHR|BUCERO^HERL^CHRISTIN^^^^Cur_Name||19420211|F||WHI|123 PEACHTREE RD^UNIT 123^ATLANTA^GA^30123^USA^HOME^^Fulton||5558609917^HOME~5558609917^[email protected]^EMAIL|5558609917^BUS|ENG|M|OTH|12345665161^^^EUH FIN^FIN NBR^EH01|123454103|GA123450071||Non-Hispanic|||0|""|""|""||N
Parsing fails with:
'Can't get repetition 2 from field 4 - maximum repetitions is only 1 reps.: Segment: PID (rep 0) Field #4'
When the repetitions are removed from that field:
MSH|^~\&|MILL|EMRY|MQ|EMRY|20150619155451||ADT^A08|Q2043855220T2330403781X928163|P|2.3||||||8859/1
EVN|A08|20150619155451
PID|1|935307^^^EUH MRN^MRN^EH01|25106376^^^TEC MRN~1781893^^^CLH MRN~935307^^^EUH MRN~5938067^^^EMPI|1167766^^^CPI NBR^^EXTERNAL|BUCERO^HERL^CHRISTIN^^^^Cur_Name||19420211|F||WHI|123 PEACHTREE RD^UNIT 123^ATLANTA^GA^30123^USA^HOME^^Fulton||5558609917^HOME~5558609917^[email protected]^EMAIL|5558609917^BUS|ENG|M|OTH|12345665161^^^EUH FIN^FIN NBR^EH01|123454103|GA123450071||Non-Hispanic|||0|""|""|""||N
-- parsing succeeds.
Fields 3 and 4 both have CX type, so I'm not sure why 4 is having this trouble while 3 doesn't?
Now for the really interesting part: when I run with DLLs version 2.4.0.0, none of these issues exist! Both sample messages above work just fine.
Also noticed the same problems with PID 15 and 22 (I think the errors were that their values were required, whereas according to the HL7 spec they're not) -- there are maybe/probably others having similar issues that I just haven't noticed yet.
Just like with the field 4 error above, the PID 15 and 22 errors also did not happen when running with 2.4.0.0 version.
Any ideas or suggestions (aside from "just use the 2.4.0.0 version" :-))?
Thank you!
For example: when PipeParser.GetMessageStructureForEvent("ADT_A04", "2.5") is called, "ADT_A01" is expected, instead "ADT_A04" is returned.
Some debugging yields the following:
In method EventMapper.GetAssemblyEventMapping calling assembly.GetManifestResourceStream(package.EventMappingResourceName) returns null.
This is because EventMappingResourceName contains two dots: one from _packageName and one from the ".EventMapping.EventMap.properties" literal.
The fix could be to remove the first dot in the literal or to remove the trailing dot in the _packageName, but I don't know the impact of the latter.
Hi,
in the HAPI project I can see the DTM type starting from the version 2.4 but I cannot find it in the nHapi project.
The DTM (date and time) data type replaces TS. The TS data type consisted of 2 components. The second component of TS had the aim of conveying the precision of the date and time value contained in the first component.
The definition of DTM is equal to that of TS - without the second component. The DTM data type allows for a 4-digit year and optional 2-digit and further additional 2-digit day; further optional hours and minutes (n.b., not hours alone); further optional (fractional) seconds, with or without time zone.
Here is my implementation of the type ( I did it for the version 2.3.1):
using System;
using NHapi.Base.Model;
using NHapi.Base.Log;
using NHapi.Base;
using NHapi.Base.Model.Primitive;
namespace NHapi.Model.V231.Datatype
{
///<summary>
/// <p>The HL7 TS (time stamp) data type. Consists of the following components: </p><ol>
/// <li>time of an event (TSComponentOne)</li>
/// <li>degree of precision (ST)</li>
/// </ol>
///</summary>
[Serializable]
public class DTM : AbstractType, IComposite
{
private IType[] data;
///<summary>
/// Creates a TS.
/// <param name="message">The Message to which this Type belongs</param>
///</summary>
public DTM(IMessage message) : this(message, null) { }
///<summary>
/// Creates a TS.
/// <param name="message">The Message to which this Type belongs</param>
/// <param name="description">The description of this type</param>
///</summary>
public DTM(IMessage message, string description)
: base(message, description)
{
data = new IType[2];
data[0] = new TSComponentOne(message, "Time of an event");
}
///<summary>
/// Returns an array containing the data elements.
///</summary>
public IType[] Components
{
get
{
return this.data;
}
}
///<summary>
/// Returns an individual data component.
/// @throws DataTypeException if the given element number is out of range.
///<param name="index">The index item to get (zero based)</param>
///<returns>The data component (as a type) at the requested number (ordinal)</returns>
///</summary>
public IType this[int index]
{
get
{
try
{
return this.data[index];
}
catch (System.ArgumentOutOfRangeException)
{
throw new DataTypeException("Element " + index + " doesn't exist in 1 element DTM composite");
}
}
}
///<summary>
/// Returns time of an event (component #0). This is a convenience method that saves you from
/// casting and handling an exception.
///</summary>
public TSComponentOne TimeOfAnEvent
{
get
{
TSComponentOne ret = null;
try
{
ret = (TSComponentOne)this[0];
}
catch (DataTypeException e)
{
HapiLogFactory.GetHapiLog(this.GetType()).Error("Unexpected problem accessing known data type component - this is a bug.", e);
throw new System.Exception("An unexpected error ocurred", e);
}
return ret;
}
}
}
}
Which is causing invalid cast exception on line # 184 in NHapi.Base.Model.Varies
in fixOBX5 method...
foreach (IType repetition in segment.GetField(5))
{
Varies v = (Varies) repetition; <--- Invalid cast exception
...
}
We use method HL7Exception.populate
to populate the ERR-segment of an ACK-message when an HL7Exception has been caught.
Every time we call this method System.InvalidOperationException
('The ConnectionString property has not been initialized.') is thrown since we do not use a database to provide a value to ERR-1-4-2.
Is it possible to catch this exception in method HL7Exception.populate
for developers who do not (want to) use the database functionality? For now only a LookupException
is caught.
Hi all,
I have noticed that each segment is being parsed twice. Normally this is not a big issue but if the hl7 file contains a big embedded PDF as base64 string, it actually causes serious performance issues.
Are you aware of this problem? If needed I can provide more info about that.
Is there any reason that the V2.51 model is not in the latest NuGet package?
private void CreateOBX(ORU_R01_ORDER_OBSERVATION orderObservation)
{
var obr = orderObservation.OBR;
obr.SetIDOBR.Value = "1";
obr.PlacerOrderNumber.UniversalID.Value = [SOME VALUE];
obr.UniversalServiceID.Text.Value = "Document";
obr.ObservationEndDateTime.TimeOfAnEvent.SetLongDate(DateTime.Now);
obr.ResultStatus.Value = "F";
obr.PlacerOrderNumber.EntityIdentifier.Value = [SOME VALUE];
for (var i = 0; i < chunks.Count(); i++)
{
var idx = i + 1;
var ob = orderObservation.GetOBSERVATION(i);
var obx = ob.OBX;
obx.SetIDOBX.Value = idx.ToString();
obx.ValueType.Value = "ED"; //this assumes base64 encoding and mime type is read from obx5.2 and obx 5.3
obx.ObservationIdentifier.Identifier.Value = "PDFReport";
obx.ObservationIdentifier.Text.Value = "PDFReport";
obx.ObservationSubID.Value = idx.ToString();
Terser.Set(obx, 5, 0, 1, 1, "");
Terser.Set(obx, 5, 0, 2, 1, "PDF");
Terser.Set(obx, 5, 0, 3, 1, "PDF");
Terser.Set(obx, 5, 0, 4, 1, "Base64");
Terser.Set(obx, 5, 0, 5, 1, [SOME B64 ENCODED STRING VALUE];
}
}
When you look at the data in that field using Terser.Get(obx,5,0,5,1), the value what is what it should be, but when you try to generate an HL7 file, the data in that field is duplicated starting with ^PDF^PDF^Base64 which exists twice as part of the duplication.
When catching a DataTypeException the FieldPosition property is incorrect for the MSH segment. For other segments it represents the correct field position number.
E.g. when MSH-7 (Date/Time of message) contains value '20151301' DataTypeException.FieldPosition holds number 6. Expected is 7.
For PID-7 (Date/time of birth) the number is indeed 7.
I think it's because MSH-1 (Field separator) is not counted in when parsing this segment.
The ORM_O01_ORDER_DETAIL class for v2.5.1 is missing OBSERVATIONRepetitionsUsed property and GetOBSERVATION(int rep) method.
OBX should be optional and repeating in v2.5.1 for ORM_O01
HAPI OBX V2.5.1
I am trying to parse some V251 HL7 OBX lines with a datatype of ST. These are causing exceptions. I've narrowed it down to line 164 of
nHapi/NHapi20/NHapi.Base/Model/Varies.cs
Type c = factory.GetTypeClass(obx2.Value, segment.Message.Version);
This returns null when obx2.Value="ST"
If I change the namespace line in
nHapi/NHapi20/NHapi.Model.V251/Datatype/ST.cs
to
namespace NHapi.Model.V251.Datatype
the exceptions go away.
Hi ,
I am getting this Error While Parsing the message .
pipeparser.Parser(message) ---> It throws exception at this line.
Error : can't get repetition 2 from field 5 - maximum repetitions is only 1 reps.: segment: obx (rep 0) field 5
Message Version 2.2 and 2.3
Sample Message :
MSH|^&|LAB|SSS|RRRR1||201412080903||ORU^R01|2014342330808001||2.2FEW GRAM NEGATIVE BACILLI
PID||000000000^8|000000000^^^SSS^MR|||||F||1||||||||000000000^^^SSS^PN|000000000
PV1|0001|I|^^^SSS|||||||YYY||||||||IP|000000000|1|||||||||||||||||||SSS
ORC|RE|2051855|||CM||1^^^201412051855^^STAT|2051855|201412051855||||EMR||201412080903||SSS^SSS^L
OBR|1|2051855^2051855|339.01149|CULT WD^WOUND CULTURE^L|||201412051858|||Bal|||||WOUND&WOUND&L^WOUND|^CAL^CAR||||3||201412080903|||F||1^^^201412051858^^STAT||4659571
OBX|24|TX|TESTNM^TEST^L||WOUND CULTURE||||||C||260.00.295|201412051858
OBX|25|TX|SOURCE^SOURCE^L||WOUND||||||C||260.00.295|201412051858
OBX|26|TX|COLLDT^COLLECTION DATE/TIME^L||12/05/2014 18:58||||||C||260.00.295|201412051858
OBX|27|TX|PLTDT^PLATE DATE/TIME^L||12/06/2014 14:15||||||C||260.00.295|201412051858
OBX|28|TX|CULTST^CULTURE STATUS^L||Final||||||C||260.00.295|201412051858
OBX|29|TX|SPCMN^SPECIMEN NUMBER^L||339.01149||||||C||260.00.295|201412051858
OBX|30|TX|CLNSIG^CLINICAL SIGNIFICANCE^L||Significance Not Determined||||||C||260.00.295|201412051858
OBX|31|TX|GRAM STAIN^GRAM STAIN^L||MODERATE WHITE BLOOD CELLSFEW GRAM POSITIVE COCCI CLUSTERSOCCASIONAL GRAM POSITIVE COCCI IN PAIRS|||^N|||F|||201412051858|PM
OBR|2|2051855^2051855|339.01149|CULT WD^WOUND CULTURE^L|||201412051858|||Bal|||||WOUND&WOUND&L^WOUND|^CAL^CAR||||3^1||201412080903|||F|MORMOM^MORMOM|1^^^201412051858^^STAT||4659571
OBX|32|TX|ORG ID^ORGANISM ID^L|1|MODERATE MORGANELLA MORGANII SSP MORGANII|||^N|||C||260.01.285|201412051858|PM
OBR|3|2051855^2051855|339.01149|CULT WD^WOUND CULTURE^L|||201412051858|||Bal|||||WOUND&WOUND&L^WOUND|^CAL^CAR||||3^1||201412080903|||F|MORMOM^MORMOM|1^^^201412051858^^STAT||4659571
OBX|33|NM|AMPICILLIN^AMPICILLIN^L|1|>= 32|||R|||F||260.01.010|201412051858|PM
OBX|34|NM|AMIKACIN^AMIKACIN^L|1|<= 2|||S|||F||260.01.015|201412051858|PM
OBX|35|NM|CEFAZOLIN^CEFAZOLIN^L|1|>= 64|||R|||F||260.01.020|201412051858|PM
OBX|36|NM|CEFTRIAXONE^CEFTRIAXONE^L|1|<= 1|||S|||F||260.01.035|201412051858|PM
OBX|37|NM|CIPROFLOXACIN^CIPROFLOXICIN^L|1|<= 0.25|||S|||F||260.01.040|201412051858|PM
OBX|38|NM|GENTAMICIN^GENTAMICIN^L|1|<= 1|||S|||F||260.01.045|201412051858|PM
OBX|39|NM|NITROFURANTOIN^NITROFURANTOIN^L|1|128|||R|||F||260.01.060|201412051858|PM
OBX|40|NM|PIP/TAZO^PIPERACILLIN/TAZ^L|1|<= 4|||S|||F||260.01.065|201412051858|PM
OBX|41|NM|TOBRAMYCIN^TOBRAMYACIN^L|1|<= 1|||S|||F||260.01.070|201412051858|PM
OBX|42|NM|TRIMETHOPRIM/SULFA^TRIMETH/SULFA^L|1|<= 20|||S|||F||260.01.075|201412051858|PM
OBX|43|NM|AMP SULBACT^AMP/SULBACTAM^L|1|>= 32|||R|||F||260.01.080|201412051858|PM
OBX|44|NM|ERTAPENEM^ERTAPENEM^L^35801-0^Ertapenem Islt MIC^LOINC|1|<= 0.5|||S|||F||260.01.330|201412051858|PM
OBX|45|NM|AZTREONAM^AZTREONAM^L^18868-0^Aztreonam Susc Islt^LOINC|1|<= 1|||S|||F||260.01.335|201412051858|PM
OBX|46|NM|CEFEPIME^CEFEPIME^L^18879-7^Cefepime Susc Islt^LOINC|1|<= 1|||S|||F||260.01.360|201412051858|PM
OBX|47|NM|MEROPENEM^MEROPENEM^L^18943-1^Meropenem Susc Islt^LOINC|1|<= 0.25|||S|||F||260.01.430|201412051858|PM
Hi Duane,
Are there any plans to support HL 7 v2.6 and v2.7 specifications?
If so by what time?
Hi Everyone ,
When i am parsing the hl7 message, when segment is not present it gives the repetition count = 1 instead of 0.
HL 7 Message Grammar : {MSH},{EVN},{PID},{PD1},{NK1},{PV1},{PV2},{GT1},{IN1},{IN2}
Code :
IMessage parsedMessage = null;
PipeParser parser = new PipeParser();
parsedMessage = parser.Parse(message);
ADT_A01 a01 = messageParsed as ADT_A01;
As you can see in above image DB1, DG1, AL1, OBX are few segments which are not present still repetition count is 1
I am getting this problem with all other types of messages also .
Hi Everyone,
I am trying to load ORU_R01 lab result but its causing issue and observations are not loading .
We also generated OML_021 lab order with v 2.5.1 successfully
Only problem is ORU_R01 .
GetPATIENT_RESULT(0).ORDER_OBSERVATIONRepetitionsUsed is not going to set and also when debug the
GetPATIENT_RESULT(0) shows (_item prop) 2 structures one is ORU_R01_PATIENT and second ORU_R01_ORDER_OBSERVATION. But once we call
GetPATIENT_RESULT(0).GetAll("ORDER_OBSERVATION") return list with 0 items
ORU_R01_PATIENT is fine.
Please suggest
Thanks
Asghar
Using the following message I would expect two SPM segment after parsing.
MSH|^&|xxxx|homxtest_9||homxtest_9|20160205112211||OML^O33|000500006894|P|2.5|||NE|AL||8859/15lastname^^^Firstname||Lastname&&Lastname^Firstname^B L J^^^^L||19991231|M|||Firstname^37^BE^^1234AB^nl|||||||||||||Y||||||N
PID|1||1234567^^^Firstname
SPM|1|1602050005&xxxx||EDTA^Paarse dop^xxxx||||||||3^ml&ml&xxxx|||||20160205111800|||N|||||||01^01^xxxx^paars^01
ORC|NW|1602-0006^xxxx|||IP||^^^20160205111800^^R||20160205112211||||^^^^^^^^^^xxxx
OBR|1|1602-0006^xxxx||Na^Natrium^xxxx|||20160421114000||0^ml&ml&xxxx||||||EDTA^Paarse dop&xxxx|||||||20160205112211||A|I||^^^20160205111800^^S
SPM|2|1602050004&xxxx||Citrate^Blauwe dop^xxxx||||||||0^ml&ml&xxxx|||||20160205111800|||N|||||||08^08^xxxx^blauw^08
ORC|NW|1602-0006^xxxx|||IP||^^^20160205111800^^R||20160205112211||||^^^^^^^^^^xxxx
OBR|2|1602-0006^xxxx||Na^Natrium^xxxx|||20160421114000||0^ml&ml&xxxx||||||Citrate^Blauwe dop&xxx|||||||20160205112211||A|I||^^^20160205111800^^S
As a result I get only 1 SPM segment. When looking at the source in PipeParser.cs in function DoParse it seems to override the previously created SPM segment.
Using version 2.5.0.5 nuget.
It may be just me being blind, but I can't find any way to tell between the two, which makes things very inconsistent when presenting the results as a tree.
As a concrete example, I have a message starting with: "MSH|^~&|INV|FAC^BLAH|TESTAPP|..."
When traversing the IMessage
returned from PipeParser.Parse
method, a call to GetField(4)
for that segment (the "FAC^BLAH" value) returns Varies
object which Data
property is of type NHapi.Base.Model.GenericComposite
. Which is exactly what one would expect for data type 'HD', so all is well there.
However, with the test string of "MSH|^~&|INV|FAC|TESTAPP|...", a call to GetField(4)
returns Varies.Data
of type NHapi.Base.Model.GenericPrimitive
, which is indistinguishable from 'ST' or other non-composite types.
Is there any way to tell which type a field is, or to somehow instruct the parser to include that information in the output, regardless of whether a composite field value happens to have one or more parts? It looks like this information must be somehow available internally, since each DataType class is derived accordingly, e.g. "public class HD : AbstractType, IComposite
" vs. "public class ST : AbstractPrimitive
".
As a side note -- I see that IType
has 'TypeName' property, but it is always set to "UNKNOWN" in my tests... Don't know what its value is supposed to be, but just thought I'd mention it, in case it's somehow related to this problem.
Thanks in advance!
The object NHapi.Model.V251.Group.OUL_R22_ORDER have a Property "OBXTCDSIDNTE".
This property should not exist !
It seems it's a part of group "RESULT".
Hi ,
I am trying to create AD_A04 & ADT_A08 but these message types are not available in v2.5.1 . Please suggest. I can see that these message types are available in 2.3.1 . I am using little bit older version of library 1.x
Thanks in advance
I noticed that when trying to get the descriptions of each segment that the Description field is always null and the only way to get it is to use the method .GetFieldDescription(num). For instance I am using an ORM_O01 and to access PID.7 orm.PATIENT.PID.DateTimeOfBirth.Description is always null yet orm.PATIENT.PID.GetFieldDescription(7) gives me the value I am looking for.
If you have an 2.3 ORM^O01 and run it through PipeParser.Parse() it will return back a GenericMessage.V23 IMessage. It only happens for 2.3. It does however work if you pass in ORM^O01^ORM_O01 as the type. But this should not be required.
Java-based HAPI v2.2 has the ca.uhn.hl7v2.conf namespace dedicated to conformance profile support - parsing them and using them to validate messages. It would be helpful if this were ported to the .NET nHAPI.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.