Monthly Archives: May 2013

Question: IHE PIX v3 Acknowledgement


I am working on a PIX v3 feed implementation. Have taken pains to understand the v3 messaging structure. I have been following IHE norms for PIXv3. Currently am working on sample AcceptAck message. The sample message that I created looks like this:

<MCCI_IN000002UV01 ITSVersion="XML_1.0" xmlns="urn:hl7-org:v3" 
  <id extension="34236" root="2.16.578."/>  
  <creationTime value="20080607154128"/>   
  <versionCode code="NE2008"/>
  <interactionId extension="MCCI_IN000002UV01" root="2.16.840.1.113883.1.6"/>
  <processingCode code="P"/>
  <processingModeCode code="T"/>
  <acceptAckCode code="NE"/>
  <receiver typeCode="RCV">
    <device classCode="DEV" determinercode="INSTANCE">
      <id extension="408" root="2.16.578.1.34.1"/>
  <sender typeCode="SND">
    <device classCode="DEV" determinerCode="INSTANCE">
      <id extension="871" root="2.16.578.1.34.1"/>
    <typeCode code="AE"/>
      <id extension="0806071541103" root="2.16.578."/>
      <text>Record not found.</text>

Is something missing in this message which is mandatory? Do we need to add Agent and Organization component in this ack message? IHE has mentioned them but not made clear as to whether they are mandatory or not? Can you shed light on this aspect?


Well, this is taken from the standard HL7 v3 transmission subject, found here (if you are not a registered user of, you’ll get a link saying you must be a paid user to get that content, but you only have to sign up, not pay).

The relevant content description is best summarised in the applicable RMIM design:




Everything that this says is required is populated in the message, so it’s valid as far as HL7 is concerned. As shown in this diagram, the Agent and Organization parts are optional.

Nothing in the IHE documentation tells me that these are required, and I can’t think of any valid reason for them to be required for PIX/PDQ.  So it looks fine to me.

Updated Indy IdHL7

And while I’m on the subject of Indy and updating old libraries, several people have asked me about whether there’s a current copy of IdHL7.pas.

This was a pascal implementation of HL7’s Lower Layer Protocol (LLP) that was once part of the Indy open source library but fell out when Indy was rewritten for Unicode etc.

Since I’m on a roll with Delphi XE3, and Indy, here’s an updated version of IdHL7.pas  – with it’s unit tests as well – that compiles against either Indy 9 or 10 and works in Unicode and non-unicode versions of Delphi.



p.s. This version has an addition that’s for my own debugging purposes – either define UNPRIVATE, or drop the references to ThreadSupport.


IndySoap lives Again

Many years ago, I wrote an web services library for Delphi called “IndySoap”. It took a WSDL and generated delphi code that could then be used to implement a client or a server, and was published as open source. For me, it was a real learning process, both in terms of http, xml, and web services, and also – because we dynamically generated machine code, and I thought that was risky  – we wrote a very thorough test suite. It was my first exposure to TDD.

A couple of years after it matured, a new version of delphi was released that changed the base string type from pure ansi (byte = char) to full Unicode. I tried to update IndySoap for that, but was stymied by some weird problem in the compiled code that I couldn’t figure out – and I got very few requests for a unicode version anyway. So IndySoap moved into the background – something I used for remote procedure invocation and interoperability, but gradually to be phased out as people switched over to REST – REST really is much simpler, and even the services built using “REST” are simpler than simple SOAP, let alone SOAP in it’s full glory.

Then, a couple of months ago, an IndySoap user with a depth of commitment to the code and with an architecture built on it contacted me and asked to me to update the code for the latest version of Delphi, and laid money on the table to make it happen (thanks).

So today I’m glad to announce a new version of IndySoap has been released through SourceForge ( This version compiles and passes all tests under both Delphi XE3 and Delphi 5. Versions of Delphi prior to Unicode should still be supported, and XE2, and probably XE4.

I don’t know how many people are still using SOAP, but IndySoap still has the same advantages it always offered over the out of the box Delphi choice:

  • Runs on any version of Delphi (not just the expensive ones)
  • Much more flexible and manageable than the Delphi one
  • Much more thoroughly tested, and easier to fix (instant fixes, no waiting for an overloaded programming team to get to fix old issues)
  • Deeper support for the web services stack (extending the web service stack is the #2 voted request for Delphi… IndySoap doesn’t have them but they can be added)

The old functionality tests we wrote were a wonderful aid to updating the code to use Unicode. There’s so many places where that could go wrong, and the functional tests made such a big difference. Long Live TDD (and, btw. down with SOAP!)

I’d like to thank Server Informatica for sponsoring the IndySoap work.




ACIR Codes (for OID

The OID is registered for Australian Vaccine Code. The description is:

OID that identifies item codes defined in the Australian Childhood Immunisation Register Vaccine, as managed and published by the Australian Department of Health and Ageing. The version of the code system should be conveyed along with the code, and the version should be in the form YYYYMM which corresponds  to the official month of the medicare schedule that the code is taken from

Note: The OID is a leaf node – it is used in a coded data element to indicate that the accompanying code in the coded data element identifies an Australian Childhood Immunisation Register Vaccine. The OID is not an arc that can be extended by adding OIDs below it

So, where is this published then? The only candidate I’ve been able to find is this pdf file:

Vaccine codes are available for software vendors to build into software products that can send immunisation claims to the Australian Childhood Immunisation Register (ACIR) through Internet Data Interchange (IDI). The vaccine code field is a maximum of six alphas. It should be left justified and blank filled. The table below lists the allowable codes for this field.

Actually, this list is only some of the defined codes. DHS does not publish the full list, so here is the list, as of May 2013:

Code Display Name Description Antigens
AGRPAL Agrippal Influenza Influenza
AVAXM Avaxim Hepatitis A Hepatitis A
BCG BCG Tuberculosis Tuberculosis
CDT CDT Diphtheria, tetanus Diphtheria, Tetanus
CMX COMVAX Hib, hepatitis B Hib Hepatitis B
DTP Triple Antigen Triple Antigen Diphtheria, Tetanus, Pertussis
DTPA DTPa DTPa Diphtheria, Tetanus, Pertussis
ENGP Engerix B B Hepatitis B (paediatric) Hepatitis B
FLRIX Fluarix Influenza Influenza
FLUVAX Fluvax Influenza Influenza
FLVRN Fluvirin Influenza Influenza
FVXJNR Fluvax Junior Junior Influenza Influenza
GNDIP Diphtheria Diphtheria Diphtheria
GNFLU Influenza Influenza Influenza
GNHEP Hepatitis B Hepatitis B Hepatitis B
GNHPA Hepatitis A Hepatitis A Hepatitis A
GNJEN Japanese Encephalitis Japanese Encephalitis Japanese Encephalitis
GNMEA Measles Measles Measles
GNMEN Meningococcal C Meningococcal C Meningococcal C
GNMUM Mumps Mumps Mumps
GNPNE Pneumococcal Pneumococcal Pneumococcal
GNPOL Polio Polio Polio
GNROX Rotavirus Rotavirus Rotavirus
GNRUB Rubella Rubella Rubella
GNTET Tetanus Tetanus Tetanus
GNVAR Varicella Varicella Varicella
HATWNJ Twinrix Junior Junior Hepatitis A & B Hepatitis A
HAVAQ Vaqta Paed/Adol Paediatric/Adolescent formulation Hepatitis A Hepatitis A
HAVJ Havrix Junior Junior Hepatitis A Hepatitis A
HBV HBV HBV Hepatitis B
HBVP HBVAX II II Hepatitis B (paediatric) Hepatitis B
HBX Hiberix Hib Hib
IFHX Infanrix Hexa Hexa Diphtheria, tetanus, pertussis, inactivated polio, Hib, hepatitis B Diphtheria, Tetanus, Pertussis, Hepatitis B, Polio, Hib
IFIP Infanrix-IPV IPV Diphtheria, tetanus, pertussis, inactivated polio Diphtheria, Tetanus, Pertussis, Polio
IFPA Infanrix Penta Penta Diphtheria, tetanus, pertussis, hepatitis B, inactivated polio Diphtheria, Tetanus, Pertussis, Hepatitis B, Polio
IFX Infanrix Diphtheria, tetanus, pertussis Diphtheria, Tetanus, Pertussis
IFXB InfanrixHepB -Hep B Diphtheria, tetanus, pertussis, hepatitis B Diphtheria, Tetanus, Pertussis, Hepatitis B
INFLUV Influvac Influenza Influenza
IPV IPOL Inactivated polio (injection) Polio
JEVAX JE-VAX -VAX Japanese encephalitis Japanese Encephalitis
MENJUG Menjugate Meningococcal C (conjugate) Meningococcal C
MENTEC Meningitec Meningococcal C (conjugate) Meningococcal C
MENUME Menomune Meningococcal A,C,W135 & Y (polysaccharide) Meningococcal
MENVAX Mencevax ACWY ACWY Meningococcal A,C,W135 & Y (polysaccharide) Meningococcal
MMR MMR MMR Measles, Mumps, Rubella
MMRCSL MMR II II Measles, mumps, rubella Measles, Mumps, Rubella
MMRSKB Priorix Measles, mumps, rubella Measles, Mumps, Rubella
MNTRX Menitorix Meningococcal C (conjugate), Hib Meningococcal C, Hib
NEISVC NeisVac-C -C Meningococcal C (conjugate) Meningococcal C
OPV Polio Sabin (Oral) Oral polio Polio
P Pertussis Pertussis Pertussis
PANVAX Panvax Influenza Influenza
PDCL Pediacel Diphtheria, tetanus, pertussis, inactivated polio, Hib Diphtheria, Tetanus, Pertussis, Polio, Hib
PLCL Poliacel Diphtheria, tetanus, pertussis, inactivated polio, Hib Diphtheria, Tetanus, Pertussis, Polio, Hib
PNEUMO Pneumovax 23 Pneumococcal (23vPCV) 23 Pneumococcal
PRPD ProHIBit ProHIBit Hib
PROQAD ProQuad Measles, mumps, rubella, varicella Measles, Mumps, Rubella, Varicella
PRPOMP PedvaxHIB Hib Hib
PRVNR Prevenar 7 7 Pneumococcal (7vPCV) Pneumococcal
PRVTH Prevenar 13 13 Pneumococcal (13vPCV) Pneumococcal
PRXTEX Priorix-Tetra -Tetra Measles, mumps, rubella, varicella Measles, Mumps, Rubella, Varicella
QDCL Quadracel Diphtheria, tetanus, pertussis, inactivated polio Diphtheria, Tetanus, Pertussis, Polio
ROTRIX Rotarix Rotavirus Rotavirus
ROTTEQ Rotateq Rotavirus Rotavirus
SYNFLX Synflorix Pneumococcal (11vPCV) Pneumococcal
TCL Tripacel Diphtheria, tetanus, pertussis Diphtheria, Tetanus, Pertussis
VAXGRP Vaxigrip Influenza Influenza
VGRJNR Vaxigrip Junior Junior Influenza Influenza
VLRIX Varilrix Varicella Zoster Varicella
VRVAX Varivax Varicella Zoster Varicella

Several notes to make about this list:

  • It will become out of date after May 2013
  • I will take it down in the future when a more authoritative list is published
  • The codes given in the reference above are the codes from this list that can be used for billing purposes. The list here includes additional other codes that may be appear in PCEHR documents.
  • Although the reference given above says that the codes are space padded with blanks to a length of 6 characters, this does not apply to CDA, where only the non-space characters are used
  • This list only includes immunizations that are recommended for use with children (it’s the Australian Childhood Immunization Registry). So immunizations such as BOOSTRIX don’t get a code (see page 2 of the reference, and ignore what it says on page 1)

Question: Act-relationship for Pathology Dissection


Pathology resident performs a gross dissection examination of the tissue submitted from a surgical procedure performed by a doctor to remove a patient’s gallbladder.

What is the ActRelationship?


Well, that’s kind of difficult. If I was doing this for real, I’d ask a lot of questions, but here’s a tentative outline:

  • Pathology Resident (role/entity)
  • performs (Participation type = performs)  
  • a gross dissection examination (Procedure [1])
  • of the tissue (role/entity participating as subject or specimen)
  • submitted (act-relationship from specimen role, typeCode =product)  
  • from a surgical procedure (Procedure [2])
  • performed by a doctor (performer to procedure [2])
  • to remove a patient’s (subject of procedure [2])
  • gallbladder (targetSiteCode of procedure [2])

That shouldn’t be taken as final. Some variations of this are possible, depending on the answer to the questions. (e.g. I swept the submission under the carpet in this outline. I don’t know whether the act of submission is interesting and/or relevant or not)

Here be Dragons

Keith’s got a post up entitled “Here be Dragons“:

Where the real dragons are is in MAY, or PERMITTED content.  In this, danger abounds.  Because it says MAY, people are free to ignore it.  The MAYs in a specification are the places where you can do cool stuff, and where new capabilities can be explored.

I was reminded of this post’s title when I was looking at a proposed conformance requirement for using SNOMED-CT (taken from somewhere, the source doesn’t matter):

If the spplication supports displaying Snomed-CT concepts that have been received from another system, it shall display the Original Text associated with the code in order to be faithful to the original semantic context. If the originalText  is not available, it shall display the displayName instead. When the application displays both displayName and originalText, it shall be clearly labelled so that the user can clearly distinguish between the Original Text and the Preferred Term.

Background: All of the code representation types defined by HL7 (v2, CDA, etc) allow for either code+displayName and/or original text (and increasingly, the terminology experts are coming to agree to this). What this means is that there is both human and computer versions of the same information. That’s interesting, because that dichotomy between human and computer information is at the heart of CDA – and people discuss this as if it’s new in CDA – but it’s not, it’s core in v2 too.

Anyway, why would the application display both displayName and originalText? Well, the primary use case that springs to mind is when a system receives content that is displayed to the user directly, and also is used by a decision support system. And so the user may need to know both things – what the human-human communication says, and also what the computer is basing it’s decision support on.

The fascinating thing here is that the end-user must be the one that can – actually, must – differentiate between these two things. It’s actually kind of hard to get my head around the standard user getting their heads around that differentiation. But the problem is that if you’re going to use decision support in practice, then users are going to have to be aware of it’s limitations, and one of the primary limitations is the quality of the information going in….

There’s no easy solutions in this area.

NEHTA: Guidance relating to Clinical Document Presentation

I am pleased to be able to draw your attention to a newly released document from NEHTA entitled “Supplementary Notes for Implementers Relating to Clinical Document Presentation“. Quoting from the document:

This document recommends a set of presentation guidelines for CDA document authors. It complements the CDA Rendering Specification and the CDA implementation guides by describing:

  • how to ensure that the data is properly, consistently and safely represented in the presentation
  • the recommended order of the sections in a document

The guidance actually addresses an important issue that the clinical document specifications do not resolve:

The CDA implementation guides (IGs) specify the content of the header and the data at considerable length, but have little to say about the presentation. All the IGs contain an Appendix A, which describes the presentation, but fundamentally the presentation of the document is currently left to the discretion of the user (“There is no canonical markup for specific CDA components”, where canonical means, ‘the correct way to do things’). Two basic rules are given in the IGs:

  •  The presentation “SHALL completely and accurately represent the information encoded in the Section” – but complete and accurate in what sense? How is this defined and/or tested?
  • “The narrative contents SHALL conform to the requirements specified in the CDA Rendering Specification” – which means that the presentation can only use the features (capabilities) described in the rendering specification, but that specification makes no rules concerning what the presentation must be

So the presentation is currently left to the discretion of the implementer within the bounds established by these general rules.

Additionally, while the CDA IGs describe the sections of the document in a particular order, the IGs don’t specify any order of sections; IG conformant authors are free to order the sections in any way they see fit, as long as the section logical structures are maintained (i.e. Section B must be a child of Section A). Note that renderers are obliged to follow the order of the sections as provided by the author; they are not permitted to re-order the sections.


Given that the clinical user sees the narrative, and not the data, this has proven a substantial issue in practice. The advice contained in the document cannot be considered timely, but late is better than never, and all implementers of NEHTA based CDA documents are recommended to read the document carefully.

Some notes about the document:

  • It doesn’t cover NPDR / ETP (where the same issue applies). I’m presently extending it to make recommendations regarding the Prescription and Dispense. The recommendations will align with present practice in the NPDR (they will just formalise that)
  • It doesn’t cover any of the PCEHR views, and won’t – they have their own specifications
  • This advice is only guidance. It’s written as a specification to which applications can choose to conform, and to which conformance can be tested (i.e. conformance points) but there is nowhere that presently requires conformance to this document (nor will it be retrospectively applied to any existing CDA specifications)
  • I’m currently working on updating the Rendering Specification (through Standards Australia IT-014-06-06) and a subsequent release of this document, so feedback is welcome – here or in private by email (at grahame at healthintersections…)

Note that both documents referred to here are behind licensing gates – you have to register and sign the license to get access, but they are free (you can sign up even if you’re not Australian too)

Question: Positional location of OBX-3 codes and AS 4700.2


I have LOINC codes in OBX.3-1, OBX.3-2, OBX.3-3 for most of my results and then I have a result that I have no LOINC code for. Do I place a local code in OBX.3-1, OBX.3-2, OBX.3-3 or do I leave them blank and put it in OBX.3-4, OBX.3-5, OBX.3-6?

e.g. usually it would be this:


and should I have





OBX-3 is of type CE. in v2.4 (AS 4700.2 is based on v2.4), the CE data type definitions says:

Components 4..6 are defined analogously to components 1..3 for the alternate or local coding system. If the alternate text component is absent, and the alternate identifier is present, the alternate text will be taken to be the same as the text component. If the alternate coding system component is absent, it will be taken to mean the locally-defined system

OBX-3, on the other hand, says:

When local codes are used as the first identifier in this field we strongly encourage sending a universal identifier as well to permit receivers to equivalence results from different providers of the same service (e.g., a hospital lab and commercial lab that provides serum potassium to a nursing home). LOINC® is an HL7 approved code system for the Observation identifier.

That’s kind of a dollar each way then, as to whether the locally defined code system goes in 1-3 or 4-6. In the context of AS 47002, this is cleared up by the implementation handbook, which says:

LOINC: |6300-8^Glucose^LN| ‘LN’ is the HL7 indicator code for LOINC
Local: |Na^Sodium^NATA1234| 1234 is the NATA# for a laboratory.
Local: |Na^Sodium^NATA1234-7| Ditto except using version 7 method or format
Laboratories may provide both the local and the LOINC codes and descriptions.

Important: Where a code is available from a public terminology such as LOINC or SNOMED-CT and a local code the public terminology should come first as in the example above. Where both a LOINC and SNOMED code is sent then the LOINC code has to be in the 1st triplet. Where two codes are sent they must be codes for the same concept. (from 13.21)

So the answer is definitely to place the local code in components 1-3 when there is no LOINC code.


Outcomes from Atlanta HL7 Meeting for FHIR

Well, I’m now nearly home from the long week that is the HL7 Working Group meeting. It now goes for 7 long days from Saturday morning through to Friday afternoon. This meeting was held in Atlanta – I’d like to make some comment about Atlanta but the only time I got out of the hotel was to go to Dave Shaver’s Corepoint Party (thanks Dave).

This post is a summary of the progress that occurred at the meeting for FHIR.


Two years ago, I conceived of something that has grown into FHIR. Since then, I’ve watched the ripples of our work expand – from just a narrow community in HL7, to include all of HL7 and the wider standards community, and then out into the middleware vendors. Now, the EMR vendors are starting to pay attention. The process is accelerating too – I never expected the EMR vendors to start paying attention to our work until at least after we had completed the DSTU phase (ballot for a “Draft Standard for Trial Use”). And as the ripples spread, the community of people working on FHIR or excited about it grows, and our growth accelerates. This creates it’s own firestorm.

(Oh, and yes, I’m now starting to come to terms with the never-ending FHIR jokes and puns).


For FHIR, this meeting commenced with the 3rd FHIR Connectathon. This Connectathon continued on the linear progress that we’ve been making, with more participants, more structure, and more success. We continue to have people turning up to do a cold start, where they have had their interest ignited, but have done no reading or code prior to the day. As usual, the participants are exchanging resources by the end of the first day.

Other participants have established code bases, and perhaps have attended Connectathons previously, and are honing the breadth of their implementations and working on their conformance.

Each Connectathon, we collect a list of issues – things that are broken in the specification, or where the decisions we’ve made make things harder than they should be. Also, each Connectathon, the list gets shorter and more about the corners of specification, which shows that the Connectathon process is really paying off.

The next Connectathon will (probably) be focused on PHR access to EMRs, and promises to be bigger and better (and some new participants are planning to bring physical devices that talk FHIR to the Connectathon, which should be cool).


Our major focus right now is on preparing the specification for ballot. In order to be ready for ballot, there’s a bunch of things that we need to do around ensuring that the basic structures and quality assurance processes are in place that ensure that the resources really are useful. Like all such processes, the depth of detail that goes into this preparation is necessary but not of interest to the implementers. But it’s all going well, I think. And my particular thanks to the 30-40+ people from vendors, governments, consultants, and academics who are now working on the under-appreciated task of bringing the breadth of their experience to bear on the design of the resources.

Right now, out focus is on rounding out the resource definitions by mid-July so we can do quality assurance prior to opening the DSTU ballot in Mid-August.

There’s still some outstanding issues that we haven’t cracked yet. I’ll be making some blog posts on these in the future to solicit input from outside the community.

There’s been a little talk about FHIR having teething difficulties – and certainly there’s lots of heated discussion inside HL7 over design, approach, and so on. I’m not worried about this – these things need to happen and they bring value to the standard (see Establishing Compromise). It’s a dialectic thing.


We made some real progress on the question of what the FHIR specification needs to say about security at this meeting. There’s a draft security page on this now – please look at this and comment.

Note that while the page says that it’s not really HL7’s business to develop the resources to administer the security engine, we’ve had a number of requests to do exactly that – given enough pressure from the users, it might happen, though if it does, we’ll have to find the right group of people to work on that.

Positioning & Marketing

One thing that we’re now going to have to start working on is how to position (and then market) the specification. As the specification has rounded out, it’s become quite fully featured, and a full fledged implementation is now quite a bit of work – not that simple. I’m not really concerned, though, because few systems will need to implement all the features that we’ve defined (this is a classic problem with standards).

But I’m starting to hear people express the belief that maybe FHIR isn’t quite as simple as they thought. Well, it’s never going to be simple – FHIR is going to be a standard for exchanging information about healthcare, not a simple cookbook for REST to be adapted to healthcare applications in a bespoke manner (why do that? there’s already plenty of advice and examples out there). The re-usability of FHIR, and the fact that it grapples with difficult things like patient linking/merging, for instance) means that it’s necessarily more complicated than a simple single application API, but also worth while. Still, I think that some people are thinking it’s more complicated than it is.

Part of the solution to this is to start working on a use-case based view of the specification: given a particular problem, how do I use FHIR to solve it? Some initial work is here. Contributions to this page are welcome. We’ll be doing other things as well, so watch this space. The FHIR Button is coming at you!

Using FHIR outside HL7

One big issue was resolved at this meeting. We’ve been having this running discussion about how to use FHIR outside the scope areas that HL7 plans to cover. I’ve blogged about this before. At this meeting we agreed that people will use the FHIR methodology to define their own resources, whether we want them to or not (and, indeed, we in the core team are all doing that ourselves).

So we’ve agreed that we’re going to define a process for people to do this, and work on enhancing the tooling and the public servers to support this process, and to work on ways to bring this work back towards HL7.


Finally, our partnerships outside HL7 are going well. We’re going to be balloting resources in partnership with DICOM, IHE and the ISO Healthcare Devices Community. There’s still some open process issues around quite how these are going to work, but the actual design is coming along well.

A commonly asked question is whether ONC is going to start using FHIR. ONC have been interested in FHIR from the start, but they are driven by their requirements to deliver working standards in very short time frames. ONC won’t be able to use FHIR in their work until it’s a DSTU, and even then they will have to take things on a case by case basis. Pretty much the same applies to other national programs – some things they need to do will lend themselves to FHIR, and they’re looking hard at what it might become, but you don’t lightly change direction of such a big and expensive ship.

IP Rules & the HL7 community

HL7 is starting to wrestle with a number of difficulties caused by the decision to make it’s IP freely available for implementation. The community is still trying to figure out exactly how free free is, how unencumbered free actually is, and what the consequences are for HL7 structure, revenue and expenditure. Maybe revenue will go up, maybe it will go down – we don’t know yet.

FHIR, on the other hand, remains truly free, open and unencumbered, and will continue to do so. FHIR is already driving new participation at HL7 – people who haven’t been able to take part before (or haven’t been interested). I’d like to think that this will make a significant contribution, but whether it does or not, FHIR is starting to really take off.