Monthly Archives: June 2012

FHIR for CDA and v3 implementers

The previous post explaining FHIR for a v2 implementer generated some private comments which leads to me to post two more lists: FHIR for  CDA and V3 implementers.

CDA

Start with a Consolidated CDA document… and imagine….

  • we’ll give each section a URL to identify it (it can be a local reference if we want) – now we can handle them independently
  • we’ll use xhtml instead of the existing CDA narrative
  • we’ll take each section and rename the fields for the specific use it has (i.e. the CCDA template – which means we can get rid of templateId)
  • while we’re at it, we’ll simplify the xml and the definitions a little because the RIM-speak has been moved into the background
  • treat the header just like the sections – gets it’s own narrative
  • we’ll increase the control over the relationship between the narrative and data for people that use that
  • we’ll add an extension sub-section for extensibility, with a single schema
  • when we actually assemble a complete document from the pieces, we’ll bundle them together using an atom feed – lot’s of side benefits from that.
  • Call the sections “resources”

v3 Messaging

Explaining FHIR to a version 3 messaging person is a little bit more complicated, courtesy of the deeper stack that is v3.
Start with a v3 interaction, including all the RMIMs that are used to construct the message and imagine the following:

  • We’re going to begin by re-crafting the models as RMIM-specific domain analysis models (DAMs) – using business friendly names, and getting rid of all of the extra classCode, moodCode and deep nesting paths that RIM modeling requires
  • However, we’ll keep a mapping that identifies how each of the classes, attributes and associations from the DAM corresponds to the RIM that those who want to can still look at.
  • We’ll create roughly one DAM for each RMIM, though if we’ve got multiple variants of some CMETs (e.g. identified, identified confirmable, universal, etc.), we’ll create just one DAM for the combined set
  • We’ll also simplify where we can, only keeping those data elements we expect most systems to actually use.  We’ll handle all the special case stuff separately.
  • Take the model view of each of the DAMs and craft XML structures for them, using the business friendly names as tag names and ordering things in a way that makes sense to the average business user.
  • We’ll give a URL to each of the instances of these models so we can maintain instances of the various CMETs and payloads individually if we wish
  • We’ll also add an ability to have human readable text as xhtml for each of those models, similar to CDA
  • To handle all of those special cases we threw out earlier, we’ll give each resource an “extensions” section where those less common elements can be sent by those who need them, without breaking the schema or burdening all implementers with understanding them
  • We’ll call each of those simplified DAMs “resources”
  • To craft our message, we just collect all the resources and send them as an aggregation in an atom feed, starting with the resource that corresponds to our transport wrapper RMIM, which we’ll call Message

Thanks to Lloyd McKenzie for contributing the second list.

FHIR for a HL7 v2 person

It’s pretty easy to explain FHIR to a version 2 person.

Start with a v2 message… and imagine….

  • We’ll give each segment a URL to identify it (it can be a local reference if we want) – now we can treat them independently
  • We can put the segments on a server and get/update them independently now if we want
  • We’ll use XML to represent the segment – using field names
  • We’ll tack on an html representation of the segment for people using systems that don’t understand the segment (like CDA)
  • We’ll put a little z-section at the end of each segment – though you have to publish your extension definitions now
  • We can still exchange messages by tacking all the segments together in a row like a message, with the special message header first
  • Call the segments “resources”

There – done, that was easy. Of course, there’s a couple more things (not a small things):

  • Redefine the list of segments and their contexts because we learnt so much over the last 20 years
  • Strip them down to the parts that people actually use

Still, it’s easy to explain the general principles of FHIR to someone who’s well versed in version 2 in practice.

Rendering Attachments in CDA

Yesterday’s post about pathology attachments in NEHTA Clinical Documents generated two follow-up questions which are pretty general to CDA:

  • What’s the difference between linkHtml and renerMultiMedia?
  • How do you render these things?

Taking the first question first, CDA defines linkHtml and renderMultimedia, and then says the following two things about them:

<linkHtml> is a generic referencing mechanism, similar, but not identical, to the HTML anchor tag. It can be used to reference identifiers that are either internal or external to the document. Multimedia that is integral to a document, and part of the attestable content of the document requires the use of the ObservationMedia CDA entry, which is referenced by the <renderMultiMedia> element (see <renderMultiMedia> (§ 4.3.5.6 )). Multimedia that is simply referenced by the document and not an integral part of the document can use <linkHtml> (Section 4.3.5.2)

and

Multimedia that is simply referenced by the document and not an integral part of the document must use <linkHtml>. The expected behavior is that the referenced multimedia should be rendered or referenced at the point of reference. (Section 4.3.5.6)

It sounds as though the two are technically equivalent, and the only difference is whether they are attestable or not – but they’re rather different in form, the way that html’s <a> and <img> differ – not a small difference. So the intent of this is that you can only make something attested content if it’s visible inline – if it’s not, then it shouldn’t be visible – this maintains a clear separation between what is and isn’t attestable content for the author.

An implication of this is that content that isn’t rendered inline – such as attached laboratory reports in PDF – can’t be part of the attested content.

So given a CDA package – and you have to have some kind of package – either an explicit package per the way we do it in the NEHTA specifications, or an implicit package through naming and attachment rules, perhaps using an XDS repository that contains a mix of documents and attachments. Given a package like this, an xml document with a set of named attachments that aren’t directly referenceable by a URL, how do you handle this?

Rendering Links

How you render links, for either linkHtml or renderMultiMedia, depends on your application. There’s three general possibilities:

  1. You’re writing a web application, and you transform the CDA document to part of a web page (usually server side, but could potentially be done client side with javascript)
  2. You’re write a GUI application, and you transform the CDA document into a a web page, and present that in a hosted web browser library
  3. You load the CDA document into some other formatting control

I don’t know anyone other than me doing #3, and if you are doing #3, you know enough about this stuff not to bother reading a post on it. So I won’t consider #3 anymore.

Web Application

In a web application, you’re going to serve up the CDA document, transformed to html, and the transform has to convert the local references to server side references that the server knows how to convert to references back to the package. Generally, this goes something like this: The webserver is at http://acme.local/apps/docviewer and has the relative page /[id].htm (where id identifies the document) that addresses the document – i.e. this loads a page that contains the transformed CDA document inside it. In this case, you need the CDA -> XHTML transform to work the urls over so that:

  • internal urls to other narrative pieces stay as internal references
  • other internal urls become something like http://acme.local/apps/docviewer/images?id=[id]&ref=[ref] where [ref] is the internal reference
  • relative urls become something like http://acme.local/apps/docveiwer/attachments?id=[id]&name=[name] where name is the relative reference
  • absolute urls are not changed – unless they need to be to point to a reverse proxy or local facade/cache (depends on local arrangements whether this is needed)

Of course, the actual url arrangements will vary wildly depending on platform, policy, dev tools, etc. It doesn’t matter; the point is that the internal and relative references are resolved at a different time to the display of the document, and they need the id of the document (load the document, examine the internal link and the context of the document respectively when doing this.

Known variations:

  • In the NEHTA context, the id of the document is also the identifier of the context of the package – but this might not always be the case
  • For small images, you can embed them in the reference using a data: url. This works well – and fast for small images – but the size limit varies for different versions of different browsers (not good for clinical safety)
  • If you were really a masochist, you could ship the whole package to a javascript client, and unpack the package, and keep everything local…. like I said, if you really liked hard work…

GUI Applications using a Web Browser

Fundamentally, this is a variation of a web application – the rendering engine is a web browser, and you get to create a little mini-internet of your own for it to live in inside your application, so the general approach is the same. But there’s some variations.

If you include IE inside your application (on windows/dotnet, this is the easiest, because the dev tools generally have this built in, and because you don’t have to distribute it, though you get to subject to versioning issues), then you get the problem that you can’t prevent it from actually hitting the wire and trying to retrieve the content. I’ve spent hours hacking it and ploughing through stackoverflow etc, and it seems the only way to do this is to write a custom url scheme handler, which is really hard work. So the easiest way to handle it is to set up your own web server right inside your application, and you’re back to the first case for real.

Alternatively, you can include Chrome; this involves a lot more mucking around to set it up (libraries… distribution..), but once you have, it works a whole lot better because you get more control – you can feed it content directly, and control it’s behaviour more, and you distribute the version you tested with your application. In this case, you still get to do fun stuff with URLs like above, but you can make your own up  (much more fun).

I don’t know anything about including browser controls in *nix and OSX/iOS.

Other choices

I don’t think I’ve really answered the question well – it’s a tough one because there’s so much variation in application architecture. One option I haven’t really covered is to drop the whole content to the local temp directory, including all the images and any other attachments. This has obviously performance and security ramifications etc. – and there’s still some reprocessing of the URLs to make them work (i.e internal references to non-narrative content still need to be replaced with relative names in the directory, and you might have to re-sort paths in relative names to make sure that the local filing system is ok with the names).

So the one constant is that you’re most likely going to have to reprocess the URLs for your local system, according to your local requirements. This is one reason why the PCEHR doesn’t allow the author to send stylesheets that the renderer must execute – because how can you hope to transform the transform on the fly for this sort of stuff?

 

Link from a CDA narrative to another CDA document in an XDS repository

So, a use case has come up in the pcEHR for a CDA document that links to another CDA document in an XDS repository (Consolidated View, actually, for those who want to know). So how to do that?

Well, firstly, this use case corresponds relatively directly to the one described here:

For a variety of reasons, it is desirable to refer to the document by its identity, rather than by linking through a URL.

  1. The identity of a document does not change, but the URLs used to access it may vary depending upon location, implementation, or other factors.
  2. Referencing clinical documents by identity does not impose any implementation specific constraints on the mechanism used to resolve these references, allowing the content to be implementation neutral. For example, in the context of an XDS Affinity domain the clinical system used to access documents would be an XDS Registry and one or more XDS Repositories where documents are stored. In other contexts, access might be through a Clincial Data Repository (CDR), or Document Content Management System (DCMS). Each of these may have different mechanisms to resolve a document identifier to the document resource.
  3. The identity of a document is known before the document is published (e.g., in an XDS Repository, Clincial Data Repository, or Document Content Management System), but its URL is often not known. Using the document identity allows references to existing documents to be created before those documents have been published to a URL. This is important to document creators, as it does not impose workflow restrictions on how links are created during the authoring process.

h/t to Keith Boone for that link, btw. So that’s pretty much our use case: to link to a document that’s found in the pcEHR. And you can’t do that by URL, because there’s no URL that directly addresses an XDS getDocument call, and anyway, some background machinery to do with trust is required. So how to do that?

Firstly, in the structured data representation of the CDA, we need to assert that some entry is a reference to another document. For that, we use an external document reference:

This says that this entry is a reference (typeCode=”REFR”) to the external Document. And while we’re at it, we can use the code to indicate what type of document it is, and the templateId to indicate which particular implementation guide it conforms to. And the id of the document – that’s the id by which to request the document from the XDS repository (the pcEHR in this case).

<entry>
 <!-- snip -->
 <reference typeCode='REFR'>
  <externalDocument classCode='DOC' moodCode='EVN'> 
   <templateId extension="1.3" root="1.2.36.1.2001.1001.101.100.1002.120" />  
   <id root="d22de837-9d35-438d-933d-74f08d7657f5"/>
   <code code="60591-5" codeSystem="2.16.840.1.113883.6.1" displayName="Patient Summary" />
  </externalDocument>
 </reference>

So that’s the logical reference to the Shared Health Summary with id “d22de837-9d35-438d-933d-74f08d7657f5”. A clinical system encountering this knows that it needs to retrieve that document from it’s cache or the pcEHR or some other local repository as configured. But what about the narrative?

Linking to an external document from Narrative

The Consolidated view is delivered as a CDA document because.. what other standard way to do is there? Everything else is CDA anyway…. so we might as well use it, which means we need to have a narrative, and it needs to refer to the document. This, it turns out, is not so easy. We need to use <linkHtml> to refer to the other document:

 <text>
  <paragraph>
    <linkHtml href="..."/>Other document</linkHtml>
  </paragraph>
 </text>

The problem is what to put in the href attribute. The obvious thing to put in is an id reference (e..g. #a3) to the external document, which refers to the external document directly:

 <reference typeCode='REFR'>
  <externalDocument ID="a3" classCode='DOC' moodCode='EVN'>

But you can’t have an ID on the externalDocument, and anyway, the rules for an internal reference on linkHtml are:

The target of an internal reference is an identifier of type XML ID, which can exist on other elements in the same or a different narrative block, or XML ID attributes that have been added to the <section>, <ObservationMedia>, or <renderMultiMedia> elements

So that’s a dead end. The IHE page I referred to above which describes the problem nicely suggests a way to link the external reference to the linkHtml:

<text><paragraph><linkHtml ID="a3" href="..."/></paragraph></text>
<!-- snip -->
<entry>
 <!-- snip -->
 <reference typeCode='REFR'>
  <externalDocument classCode='DOC' moodCode='EVN'> 
   <templateId extension="1.3" root="1.2.36.1.2001.1001.101.100.1002.120" />  
   <id root="d22de837-9d35-438d-933d-74f08d7657f5"/>
   <code code="60591-5" codeSystem="2.16.840.1.113883.6.1" displayName="Patient Summary" />
   <text><reference value="#a3"></reference>
  </externalDocument>
 </reference>

Only, I don’t think that’s right. The contents of the external document are not the contents of the linkHtml element (which is what that precisely means), and it’s not even really right to say that the contents of the document are the target of the linkHtml, and anyway, we still haven’t resolved what that actually is – pointing something else to the linkHtml element doesn’t resolve what it points to in the href attribute. So while I think that IHE described the problem very nicely, I don’t think they’ve solved it.

This brings us back to the URL portion of linkHtml. It just happens to defined as an xs:string, with the rule: “It can be used to reference identifiers that are either internal or external to the document”. I guess this means that the right way to fill it for external references is with a logical identifier uri. And 3 come to mind:

<linkHtml href="oid:0.1.2.3.4.5.6.7.8.9..."/>
<linkHtml href="uuid:d22de837-9d35-438d-933d-74f08d7657f5"/>
<linkHtml href="hl7-att:root[:extension]"/>

The first two (and their logical variants urn:uuid:… and urn:oid:… – which of these to use is complicated but largely, in the end, irrelevant, because everyone’s going to have to cut code to support whatever goes in here anyway) are obvious places to look, since they are defined externally, but they both suffer the problem that what if the document identifier includes an extension? (and it’s allowed to). For this reason, the V3 data types R2 defined the protocol hl7-att as:

the form hl7-att:[II.literal], such as hl7-att:2.1.16.3.9.12345.2.39.3:ABC123. The scheme hl7-att is used to make references to HL7 Attachments. HL7 attachments may be located in the instance itself as an attachment on the Message class, or in some wrapping entity such as a MIME package, or stored elsewhere. ..[snip].. Attachments SHALL be globally uniquely identified. Attachment id is mandatory, and an ID SHALL never be re-used. Once assigned, an attachment id SHALL be accosiated with exactly one byte-stream as defined for ED.data.

The language there is that of the v3 data types, but the concepts are applicable in this case, and the ground rules are all applicable. Hence, this is the right way to do a reference from one CDA document to another by a logical identifier. To recap, in the structured data:

<entry>
 <!-- snip -->
 <reference typeCode='REFR'>
  <externalDocument classCode='DOC' moodCode='EVN'> 
   <templateId extension="1.3" root="1.2.36.1.2001.1001.101.100.1002.120" />  
   <id root="d22de837-9d35-438d-933d-74f08d7657f5"/>
   <code code="60591-5" codeSystem="2.16.840.1.113883.6.1" displayName="Patient Summary" />
  </externalDocument>
 </reference>

and in the narrative:

<text><paragraph><linkHtml href="hl7-att:d22de837-9d35-438d-933d-74f08d7657f5"/></paragraph></text>

Thanks to Keith Boone for assistance with this post.

p.s. Is it valid to use a URL scheme defined in data types R2 in CDA R2, which use data types R1?  Yes, it is, because it’s valid to use scheme’s defined anywhere else as well.

Add Pathology Report Attachments to NEHTA Clinical Documents

In previous posts, I’ve shown how to represent a pathology report in a NEHTA Clinical document, and how to convert the PIT format and the TX format into the CDA narrative format. I pretty much left it as an exercise for the reader to represent the pathology report as an attachment. This post explains how to do that.

Firstly, the Pathology report structure in a CDA document includes the logical field “Pathology Test Result > Test Result Representation” (defined in the SCS/SDT, which is the logical structure of the documents). The definition of this is:

“Rich text representation of the entire result as issued by the diagnostic service. Multiple formats are allowed but they must be semantically equivalent”

In other words, the CDA narrative contains a simple representation of the report (though simple does not mean unsafe), and the CDA structure may contain additional structured data to help with the interpretation (this can range from the diagnostic service – haem, biochem, etc – through to a fully structured Cancer Report Protocol). But whatever else that contains, it’s useful and important to carry the full representation of the original report as provided by the pathology service (usually as a PDF document, though other forms are sometimes encountered, including html and pdf).

I’ve been told that it’s unsafe to represent the report as anything but the original form in pdf – which is the version of the report that equates to the classic printed report pathology services have provided for several decades. But that would be a problem, because the pathology services themselves provide these alternative formats, and all we are concerned with here is presenting the alternative content they provide faithfully (and therefore, safely). AS 4700.2 provides for a structured and a text representation to be represented in a series of OBX segments, followed by the formal representation of the report in one or more display segments, and we are faithfully reproducing this structure in the CDA document. Here, we are concerned with reproducing the display segments in CDA.

So we’re going to assume that we have some attachment, with some known mime type (which, for the purposes of this post, we will assume to be application/pdf). We have to do three things:

  • Put the attachment in the CDA Package
  • Define the report formally in the structured data
  • Reference the attachment in the narrative

Attachment in the CDA Package

According the CDA, any clinical content that is inherently part of the document must be transported around with the document so that it is always available where ever the document is. (The pathology report probably fits the definition – at least, we’re going to treat it so, since it’s safer to do this). In order to ensure that images and attachments like this, and digital signatures, are always available, NEHTA clinical documents are always moved around in “packages” which are effectively IHE XDM packages, though without metadata in most applications (maybe that’s worth another post, but I’m not going to explain it here).

So a clinical document package is a zip archive that contains a CDA document, an XML signature file, and one or more attachments. The full spec is here – this is just a simplified description. Attachments are effectively “local” to the document – i.e. a relative URL. In order to ensure that the attachments from different documents don’t accidently run into each other in some context – though this really shouldn’t be allowed anyway – attachments should have a GUID as their name (and it’s.. polite.. to include a file extension to assist newbie developers to get this right).

So the first thing we do is ensure that the pathology report is included in the zip file with a name like 317dcda7-7e67-405e-802e-0430c208f354.pdf, which we will hereafter call [guid].pdf.

Link to the Report in the structured data

Next, we link to the report in the structured data. According to the CDA Implementation Guide, the content is supposed to go in entry[path_test_res]/observation/value:ED, which means that it would look like this:

<section>
 <code code="102.16144" codeSystem="1.2.36.1.2001.1001.101" 
    displayName="Pathology Test Result" />
 <title>Pathology Test Result</title>
 <text>..</text>
 <entry>
  <observation classCode="OBS" moodCode="EVN">
  <code code="[loinc code]" codeSystem="2.16.840.1.113883.6.1" displayName="[...]" />
  <value xsi:type="ED" mediaType="application/pdf">
   <reference value="[guid].pdf" />
  </value>
  <!-- other stuff... -->

There can be multiple values. Each value element is saying, “the value of this pathology report is… this fully formatted report”. (Why not use Observation.text? there can only be one of them, but there can be multiple values). And the content of the value is a reference to [guid].pdf – and since this is a local reference, it means, resolve this in the local CDA package, where we just put it.

Including the report in the narrative

In CDA, though, that’s not enough – if we actually want to add the attachment to the document as part of the content, we need to do that in the narrative. We can’t do that by actually dropping the content into the narrative – CDA doesn’t have an instruction to do that (i.e. something equivalent to iFrame) – and none of the software could easily do that anyway. So we’re going to provide a reference to it.

<section>
 <code code="102.16144" codeSystem="1.2.36.1.2001.1001.101" 
    displayName="Pathology Test Result" />
 <title>Pathology Test Result</title>
 <text>
  <!-- pathology text report - built from pit of html or whatever -->
  <paragraph>
   <linkHtml href="[guid].pdf">Original Pathology Report</linkHtml>
  </paragraph>
 </text>

So this says, when you render “Original Pathology Report”, make it a clickable link that points to [guid].pdf, which is the same local report. It’s up to the viewer software to enable this link (the requirement to do this is part of the base requirements described by the NEHTA CDA Rendering Guide that apply to all conformant renderers, so it can be relied on).

So this is how to include an original pathology report in a NEHTA Clinical Document.

 

Questions about FHIR

I have been keenly following your writings on HL7 for the past few years. I think that FHIR is a great idea and am  keen on taking this forward in XXX.
Two questions:
(1)Where can I get an implementer focused document on FHIR? (I know that it is a work in progress, but I am fine with that)
(2) What is HL7 International’s take on the FHIR? (Frankly speaking, though I like the way FHIR is forming up, I am concerned about taking up an idea that  may not get HL7 International’s  approval).

Thank you for asking.

(1) Implementer focused documentation

I think that FHIR itself is a very implementer focused document – that’s what we’re trying for, tough we’re always fighting a losing battle with complexity, of course. But anything we write about implementation, I’d like to add to the specification itself, if possible. What have you got in mind that we haven’t got?

One thing that early drafts contained, but don’t seem to have a place right now, is an explanation of how to use REST to implement solutions. The trouble with that seemed to be that we can’t get enough detail into the specification to make experienced REST practitioners happy without making newbies scared.

Otherwise – very keen to hear suggestions for what else we can provide to make implementing the specification easier

(2) FHIR reception at HL7 International

The reception for FHIR at HL7 international has been almost uniformly positive. The biggest single evidence of this is that the board agreed to make FHIR freely available to the public. This is a big deal. Certainly there’s some very reasonable nervousness about the overall impact of FHIR on the existing specifications and the organisation’s ongoing ability to support them. And there’s a few members who are very highly invested in the existing standards of one form or another who would much rather not see FHIR succeed. But the needs that it addresses are very real, and HL7 international is very aware of them.

Having said that, FHIR goes up for it’s first ballot in the next few weeks. If you like what FHIR represents, join the ballot and vote for it. There’s 2500+ voting members at HL7, and generally <40 people vote on the specification. that’s 2% – a very small sample size. it’s very easy to flood the ballot. I’d rather see it get flooded in approval than opposition 😉

I’ve always been concerned that FHIR represents too much change – a sea-change in direction. I know many other people share that concern – after all, our last big direction change (v2 -> v3) didn’t turn out too well in the end. But I’ve come to the conclusion that only a big change can solve the problems – I’ve spent 5 years working to improve the situation within the paradigm that is v3, and all I’ve managed to do is make it more confusing.

FHIR Connectathon

I haven’t been very active with the blog lately – I’ve had my head down preparing for the upcoming FHIR ballot and connectathon.

The connectathon is coming along great – we’ve now got an experienced IHE connectathon expert running the show – Mike Henderson – and his presence is going to make a huge difference to the professionalism of the day. We’re already getting a lot of interest – a lot more than we expected, so that’s great.

As part of the preparation, we holding an open call for vendors who are interested in participating later today. It’ll be a chance to ask questions of Mike and I and others who will be participating. Here’s the call details:

Looking forward to see you all there.

btw., one of the things that I’ve been doing is preparing sets of resources to help people prepare for the connectathon. There’s several hundred test resources at http://hl7connect.healthintersections.com.au/svc/fhir/ now, and you can use the browser to explore (though be forgiving, the server is still being developed, and particularly searching still has bugs)

 

Empty Address Use

I’ve been working on the premise that there’s never any empty attributes or tags in a CDA document.

So you never see anything like this:

 <element/>

or

  <element attr="">...

Well, it turns out that I’m wrong. For attributes with type = SET<CS> (abstract), or CS* (XML ITS) or list_<enum> (schema), they can be empty, like this:

<address use="">
  <etc...>
</address>

Now, to hunt down all the people I’ve told otherwise….

 

Representing Pathology reports in NEHTA Clinical Documents

This is the 3rd post in a series focusing on the representation of pathology reports in NEHTA clinical documents. The context of this work is that a clinical system is assembling a clinical document for some kind of summary report – a discharge summary, an event summary, or a referral – and document will include a set of pathology reports.

The context doesn’t include a clinical user quoting from a pathology report by copying and pasting into a clinical document, but where the system is assembling the document (usually following some human guidance). Also, the context of this is not for a lab generating the original reports – this is only about reuse for those systems that wish to do so. Finally, a note for my US readers: here in Australia, “Pathology” includes all clinical lab disciplines, not the narrower usage it has in USA.

It’s possible to properly and completely represent a pathology report in a NEHTA clinical document. In the previous posts (here, and here), I’ve explained how to convert common narrative formats to a CDA narrative. In this post, I deal with how to represent the full report safely. If the source pathology report is fully conformant to AS 4700.2 (the relevant Australian standard), then this is relatively straight forward. To the degree that the source deviates from AS 4700, then this is either more difficult, or not safe (any display/usage of the report is similarly affected).

Parts of a Pathology Report

There are four major parts to a pathology report in a NEHTA Clinical document:

  • Metadata – identifies the type of report etc
  • CDA representation – the report as represented in CDA narrative
  • Native representation – original content as provided by the lab (i.e. PDF)
  • Atomic data

The first two parts are mandatory. The other two are optional. This post doesn’t deal with atomic data at all – we’re going to ignore that part for now (if there’s enough interest, I’ll do a follow up post on that).

With regard to the two presentation formats, the CDA representation is required as part of CDA. The native format is provided because the CDA representation is never going to be able to reproduce the full page layout of the pathology lab report, and under some circumstances,a clinical system won’t be able to safely transform the pathology report into the limited capabilities of the CDA narrative. Alternatively, you might have a URL reference to where the report might be available to a suitably authorised user.

So it follows that the following combinations of presentation exist:

  • you don’t have a presentation format at all, and nor do you have a link. So there’s probably not a lot of point putting the report into the CDA document
  • you have a reference to where the report can be available. Build a CDA narrative with the link in it (<linkHtml>) and add it as a native representation with a reference
  • you have a CDA narrative (e.g. built from PIT) and there’s either no original format, or the original format offers nothing in addition to the CDA Narrative – so just use the CDA narrative
  • You have an original format – probably a PDF – and no CDA narrative. In this case, you include the original format, and a constructed narrative that is just a pointer to the original
  • you have both – a CDA narrative, and an original form. Put both in, and ensure that the CDA narrative contains a link to the native format.

See below for technical details of how to render these in CDA.For the reader of the document, this is relatively consistent: for the lab report, they get a display of it’s contents if one is available, and a link to click to get the full version of the report, if that is available.

The important point is that you only include the CDA narrative form of the report if you are confident that it’s correct. You can be confident it’s correct and safe if:

  • the lab provided a PIT or text representation (TX or FT) – you can transform these to CDA narrative with confidence
  • the lab provided a CDA Narrative form themselves (though none of them are doing that for now or the forseeable future)
  • the lab provided an HTML form, and you know that you can convert the html correctly for that lab

If the report is provided as PDF, or RTF, you can print the document to a TIFF image, and include the TIFF image as the narrative – but I recommend against that, since the TIFF image may be a multi-page one, and support for this is variable. For instance, it’s allowed in the pcEHR, but I doubt that the portal will provide a multi-page TIFF viewer, being as it depends on a browser (I haven’t actually checked).

If the report is provided as purely atomic data, you may be able to safely convert it to CDA narrative – it depends on whether you are able to safely display it to the user at all, which is not an easy problem. If you can, feel free to include this as the CDA narrative.

Metadata

The following table summarises the metadata that a report has:

Item Description Required? V2 Source
Report Name Identification of the pathology test performed, sometimes including specimen type yes OBR-4
Diagnostic Service The diagnostic service that performs the examination no OBR-24
Report Status The status of the pathology test result as a whole. yes OBR-25
Test Result Date Time The clinically relevant time of the pathology test yes OBR-7

The report actually has additional metadata around requesting and so forth, but it’s all optional, and I’ve left it out of this analysis. There are also a whole lot of additional fields related to atomic data which I’ve also left out, and that too is all optional.

So there’s 3 pieces of data that you have to provide: the name of the report – which may be a code, the status of the report, and the date time of the observation, which is usually when specimen was collected. These pieces of data should be easily extractable from the source pathology report.

Status might be a problem. The allowed values are:

Registered No result yet available
Interim This is an initial or interim result: data may be missing or verification has not been performed
Final The result is complete and verified by the responsible practitioner
Amended The result has been modified subsequent to being Final, and is complete and verified by the pathologist
Cancelled/ Aborted The result is not available because the examination was not started or completed

This is a subset of the options allowed for OBR-25, though it matches the list used by Australian laboratories. I’ve heard that not all pathology companies actually provide a status for their report. Perhaps you can assume that they are final – that might be possible in a particular context (but then how do they handle amended reports?). If the pathology report itself can’t be bothered to say what’s status is, then you’ll have to use a nullFlavor on the report status code in the CDA document.

CDA representation

So to properly represent a report in CDA, you need a CDA representation, and report name, status, and date/time. In addition, you might have a diagnostic service, a native representation, and/or a source link.

This CDA fragment shows what this looks like in the actual XML:

<component>
 <section>
  <code code="102.16144" codeSystem="1.2.36.1.2001.1001.101"
     displayName="Pathology Test Result" />
  <title>Pathology Test Result</title>
  <text>
   [CDA narrative]
  </text>
  <entry>
   <observation classCode="OBS"moodCode="EVN">
     <id [you need to put something here that will be same each time
     you reuse this same pathology result. It could be sourced from the
     pathology report identifiers]/>
    <code [report name, code or original text]/>
    <value mediaType="[media type of native representation or text/html for url]">
     <reference value="[either a full URL, or the name of the native 
        representation which is found in the package]" />
    </value>
    <entryRelationship typeCode="COMP">
     <observation classCode="OBS"moodCode="EVN">
      <code code="310074003" codeSystem="2.16.840.1.113883.6.96"
       displayName="pathology service" />
      <value xsi:type="CD" [diagnostic service code/text] />
     </observation>
    </entryRelationship>
    <entryRelationship typeCode="COMP">
     <observation classCode="OBS"moodCode="EVN">
      <code code="308552006" codeSystem="2.16.840.1.113883.6.96"
       displayName="Report Status" />
      <value xsi:type="CD" code="[report status]" displayName="[text]"
       codeSystem="1.2.36.2001.1001.101.104.16501" />
     </observation>
    </entryRelationship>
    <entryRelationship typeCode="COMP">
     <observation classCode="OBS"moodCode="EVN">
      <code code="103.16605" codeSystem="1.2.36.1.2001.1001.101"
       displayName="Pathology Test Result DateTime" />
      <effectiveTime value="[report date]"/>
     </observation>
    </entryRelationship>
   </observation>
  </entry>
 </section>
</component>

 

 

Transforming Pathology PIT reports into NEHTA Clinical Documents

This is the second of a series of posts dealing with representing pathology reports in NEHTA Discharge summaries. The first post dealt with the transforming the TX format into CDA. This post deals with the PIT
format. Follow up posts will deal with the FT format, and then with the general context of representing pathology reports in clinical documents.

The PIT format is an old format for sending pathology reports to the requesting doctor. It’s throughly outdated, everybody dislikes it, and no one is supposed to send it anymore. So, of course, you run into it all over the place. The documentation can be found here.

Here’s a sample of the core of a report (just the bits I’m interested in for this post):

301 ~SBLK~FINAL REPORT~EBLK~
301 ------------
301      Prothrombin Time    ~SBLD~ 17~EBLD~  seconds
301      I.N.R.              ~SBLD~1.6~EBLD~  (International Normalised Ratio)
301 __________________________________________________________________
301 Cumulative INR Report       Date        INR        Req.No.
301                          08/06/2010     ~FG05~1.4~FG15~        254084
301                          14/06/2010     2.0        259680
301                          28/06/2010     2.5        272727
301                          05/07/2010     ~FG04~4.8~FG99~        279365
301                          12/07/2010     3.0        286035
301                          19/07/2010     1.6        292225~DFLT~
301
301  ÚÄÄÄINRÄÄÄÂÄÄÄÄÄÄÄÄÄCONDITIONÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄLENGTH OF THERAPYÄÄ¿
301  ³ 2.0-3.0 ³ Atrial Fibrillation            ³    Long Term        ³
301  ³ 2.0-3.0 ³ Bioprosthetic Valve            ³    3 months         ³
301  ³ 2.0-3.0 ³ Acute Myocardial Infarction    ³ 3 months ( > if AF) ³
301  ³ 2.0-3.0 ³ Cardioembolic CVA, Rec. DVT/PE ³    Long Term        ³
301  ³         ³ Dilated Cardiomyopathy         ³                     ³
301  ³ 2.0-3.0 ³ Venous Thrombosis and PE       ³    3-6 months~EUND~       ³
301  ³ 2.5-3.5 ³ Mechanical Heart Valve         ³    ~SUND~Long Term~DFLT~        ³
301  ÀÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
309

The full PIT source is available here. The first part of the line is a number which tells you what the line means. The rest is text with formatting commands identified by tilde characters. Here’s a summary of the formatting commands:

  • BGnn    Specify a background color (see colour table below) The default colour is BG99, and the colour should always be reset at the end of the line
  • FGnn    Specify a text color (see colour table below) The default colour is FG99, and the colour should always be reset at the end of the line
  • SBLD/EBLD    Start and end bolding
  • SUND/EUND    Start and end underlining
  • SBLK, EBLK    Blinking – most targets do not support blinking
  • PIpp    Pitch control – meaning unclear
  • FOff    Meaning unknown
  • DFLT set everything to default

For further details, consult the PIT doco link above.

Converting PIT to CDA Narrative

In principle, the conversion process is relatively straightforward:

  1. Strip the leading number and spaces
  2. replace the old table border characters if they appear
  3. replace the formatting commands with CDA equivalents (see below)
  4. wrap the content with a CDA paragraph with style xPre

In practice, several things complicate the conversion process:

  • PIT formatting commands are not always paired. (They’re supposed to be, but most systems will overlook such errors, so they’re often not detected by the sender)
  • the commands do not need to be well formed (i.e. start underlining, then start bold, then stop underlining, then stop bold)
  • the DFLT command resets everything
  • Limitations around the CDA handling of narrative and whitespace

Step #1: leading spaces

The first task is to strip the line prefix (a 3 numeral line code prefix followed by a space):

~SBLK~FINAL REPORT~EBLK~
 ------------
 Prothrombin Time    ~SBLD~ 17~EBLD~  seconds
 I.N.R.              ~SBLD~1.6~EBLD~  (International Normalised Ratio)
 __________________________________________________________________
 Cumulative INR Report       Date        INR        Req.No.
 08/06/2010     ~FG05~1.4~FG15~        254084
 14/06/2010     2.0        259680
 28/06/2010     2.5        272727
 05/07/2010     ~FG04~4.8~FG99~        279365
 12/07/2010     3.0        286035
 19/07/2010     1.6        292225~DFLT~ 

 ÚÄÄÄINRÄÄÄÂÄÄÄÄÄÄÄÄÄCONDITIONÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄLENGTH OF THERAPYÄÄ¿
 ³ 2.0-3.0 ³ Atrial Fibrillation            ³    Long Term        ³
 ³ 2.0-3.0 ³ Bioprosthetic Valve            ³    3 months         ³
 ³ 2.0-3.0 ³ Acute Myocardial Infarction    ³ 3 months ( > if AF) ³
 ³ 2.0-3.0 ³ Cardioembolic CVA, Rec. DVT/PE ³    Long Term        ³
 ³         ³ Dilated Cardiomyopathy         ³                     ³
 ³ 2.0-3.0 ³ Venous Thrombosis and PE       ³    3-6 months~EUND~       ³
 ³ 2.5-3.5 ³ Mechanical Heart Valve         ³    ~SUND~Long Term~DFLT~        ³
 ÀÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Step #2: table border characters

Some PIT – not all – includes old ASCII tables based on old character sets from windows pages (or even DOS!). Old, but the systems sending PIT are old.

Here’s a lookup table for the old DOS OEM code page:

DOS Char Unicode Char
DA 250C
C4 2500
C2 252C
BF 2510
B3 2502
C0 2514
C1 2534
D9 2518

This table is missing some characters (for inner horizontal lines) – I’ll add them when I find them out (if I can).

After that, it looks like this in UTF-8. (I have no idea whether this will render in the blog for your browser, and I don’t know how to control how WordPress renders it):

~SBLK~FINAL REPORT~EBLK~
 ------------
 Prothrombin Time    ~SBLD~ 17~EBLD~  seconds
 I.N.R.              ~SBLD~1.6~EBLD~  (International Normalised Ratio)
 __________________________________________________________________
 Cumulative INR Report       Date        INR        Req.No.
 08/06/2010     ~FG05~1.4~FG15~        254084
 14/06/2010     2.0        259680
 28/06/2010     2.5        272727
 05/07/2010     ~FG04~4.8~FG99~        279365
 12/07/2010     3.0        286035
 19/07/2010     1.6        292225~DFLT~
 ┌───INR───┬─────────CONDITION──────────────┬──LENGTH OF THERAPY──┐
 │ 2.0-3.0 │ Atrial Fibrillation            │    Long Term        │
 │ 2.0-3.0 │ Bioprosthetic Valve            │    3 months         │
 │ 2.0-3.0 │ Acute Myocardial Infarction    │ 3 months ( > if AF) │
 │ 2.0-3.0 │ Cardioembolic CVA, Rec. DVT/PE │    Long Term        │
 │         │ Dilated Cardiomyopathy         │                     │
 │ 2.0-3.0 │ Venous Thrombosis and PE       │    3-6 months~EUND~       │
 │ 2.5-3.5 │ Mechanical Heart Valve         │    ~SUND~Long Term~DFLT~        │
 └─────────┴────────────────────────────────┴─────────────────────┘

Step #3: replace the format tags

In principle, the mapping table goes like this:

SBLD <content styleCode=”Bold”>
EBLD </content>
SUND <content styleCode=”Underline”>
EUND </content>
SBLK <content styleCode=”Bold Underline Italics xFgColour800000″>
EBLK </content>
FGnn <content styleCode=”xFgColourHHHHHH”> where the HHHHHH is taken from the table below
FG99 </content>
BGnn <content styleCode=”xBgColourHHHHHH”> where the HHHHHH is taken from the table below
BG99 </content>
PIpp  ignore
FOff ignore
DFLT  </content>

Comments:

  • There’s no support for blink in CDA/XHTML. Since the purpose of blink is to draw attention, we’ll have to settle for bold, underline, and italic, and Maroon (see note on use of colour below). That should make it stand out.
  • Because the control codes can be interlaced, the easiest way to manage the conversion process is to keep a set of flags for the various format options, start the paragraph with a <content> tag, and just lay down a </content><content styleCode=”…”> each time the styling changes, and then finish with a </content>. Not pure, but this is only for presentation. after all

Colour table:

n  name  html name  code
00  Black  Black  000000
01  Blue  Blue  0000FF
02  Green  Green  008000
03  Cyan  Cyan  00FFFF
04  Red  Red  FF0000
05  Magenta  Magenta  FF00FF
06  Brown  Brown  A52A2A
07  Light Grey  Light Grey  D3D3D3
08  Dark Grey  Dark Grey  A9A9A9
09  Light Blue  Light Blue  ADD8E6
10  Light Green  Light Green  90EE90
11  Light Cyan  Light Cyan  E0FFFF
12  Light Red  Salmon  FA8072
13  Light Magenta  Violet  EE82EE
14  Yellow  Yellow  FFFF00
15  White  White  FFFFFF

99 is the default colour, which means white for background, and black for text. However there’s no reason from the PIT specification that the colours shouldn’t be entirely backwards as would suit an old console display (I heard of that once, but I don’t know if it’s still ever done – so check. Just to make the point, in this example, FG15 means default, not white. Don’t get caught doing white on white or blank on black).

That gives the following content:

<content> </content><content styleCode="Bold Underline Italics xFgColour800000">FINAL REPORT</content><content>
 ------------
 Prothrombin Time    </content><content styleCode="Bold"> 17</content><content>  seconds
 I.N.R.              </content><content styleCode="Bold">1.6</content><content>   (International Normalised Ratio)
 __________________________________________________________________
 Cumulative INR Report       Date        INR        Req.No.
 08/06/2010     </content><content styleCode="xFgColourFF00FF">1.4</content><content>        254084
 14/06/2010     2.0        259680
 28/06/2010     2.5        272727
 05/07/2010     </content><content styleCode="xFgColourFF0000">4.8</content><content>        279365
 12/07/2010     3.0        286035
 19/07/2010     1.6        292225</content><content>
 ┌───INR───┬─────────CONDITION──────────────┬──LENGTH OF THERAPY──┐
 │ 2.0-3.0 │ Atrial Fibrillation            │    Long Term        │
 │ 2.0-3.0 │ Bioprosthetic Valve            │    3 months         │
 │ 2.0-3.0 │ Acute Myocardial Infarction    │ 3 months ( > if AF) │
 │ 2.0-3.0 │ Cardioembolic CVA, Rec. DVT/PE │    Long Term        │
 │         │ Dilated Cardiomyopathy         │                     │
 │ 2.0-3.0 │ Venous Thrombosis and PE       │    3-6 months</content><content>       │
 │ 2.5-3.5 │ Mechanical Heart Valve         │    </content><content styleCode="Underline">Long Term</content><content>        │
 └─────────┴────────────────────────────────┴─────────────────────┘

Step #4: wrap into CDA Narrative

This bit is easy: just a paragraph with style xPre:

  <text>
   <paragraph styleCode="xPre">
 <content> </content><content styleCode="Bold Underline Italics xFgColour800000">FINAL REPORT</content><content>
 ------------
 Prothrombin Time    </content><content styleCode="Bold"> 17</content><content>  seconds
 I.N.R.              </content><content styleCode="Bold">1.6</content><content>   (International Normalised Ratio)
 __________________________________________________________________
 Cumulative INR Report       Date        INR        Req.No.
 08/06/2010     </content><content styleCode="xFgColourFF00FF">1.4</content><content>        254084
 14/06/2010     2.0        259680
 28/06/2010     2.5        272727
 05/07/2010     </content><content styleCode="xFgColourFF0000">4.8</content><content>        279365
 12/07/2010     3.0        286035
 19/07/2010     1.6        292225</content><content>
 ┌───INR───┬─────────CONDITION──────────────┬──LENGTH OF THERAPY──┐
 │ 2.0-3.0 │ Atrial Fibrillation            │    Long Term        │
 │ 2.0-3.0 │ Bioprosthetic Valve            │    3 months         │
 │ 2.0-3.0 │ Acute Myocardial Infarction    │ 3 months ( > if AF) │
 │ 2.0-3.0 │ Cardioembolic CVA, Rec. DVT/PE │    Long Term        │
 │         │ Dilated Cardiomyopathy         │                     │
 │ 2.0-3.0 │ Venous Thrombosis and PE       │    3-6 months</content><content>       │
 │ 2.5-3.5 │ Mechanical Heart Valve         │    </content><content styleCode="Underline">Long Term</content><content>        │
 └─────────┴────────────────────────────────┴─────────────────────┘
   </content></paragraph>
  </text>

So we claim that this is all one paragraph. Strictly, it’s wrong to claim that all this is one paragraph with line breaks, but in practice, it doesn’t matter. You could spend days refining an algorithm for recognising the end of a paragraph (it’s never as simple as a double end of line), and who’s going to care? This is only ever going to be for display.

Note that we have used xPre, for text containing whitespace and carriage returns which may not be ignored. It would be possible to use xFixed, and add <br/> tags for line breaks. But the problem with xFixed and <br/> is that leading spaces – they will be lost, and you can’t use &nbsp; to preserve them, since &nbsp; is not defined for CDA. So xPre it is, and the conversion process has to be careful with whitespace. (Of course, in this example, the whitespace probably isn’t that big a deal, but it serves to make the point).

Conclusion

So there you go – that’s how to convert the PIT formatted report into a NEHTA CDA document without losing any formatting. Two things to note:

  • I’ve not dealt with the issue of line wrapping here – that’s just hard whether you’re displaying the PIT directly or whether it’s being displayed through CDA
  • these extra style codes starting with x are all defined in the NEHTA stylesheet, and aren’t in the normal HL7 stylesheet. Ensure that the documents will only be sent to NEHTA-conformant rendering systems for safety here.