Monday, December 9, 2013

Surface + Inking = Amazing

Well, I’ve been using the Microsoft Surface for pretty much everything lately and I have to say; Microsoft has hit the nail on the head for business users on a tablet.

If anyone has to choose between an iPad or a Surface Pro, 100% confident that the Surface Pro is a much better investment for one reason (actually two but they’re closely related): Inking and Office.

Anyone who has used inking in Office will instantly know what I’m talking about. The digitizer on the Surface Pro is amazing! It has pinpoint accuracy, and is pressure sensitive. I’ll go into detail about some of the great ways this can be used with Office applications.

OneNote

OneNote is amazing on the Surface Pro! Because the Windows can tell the “difference” between a stylus, a finger and the mouse you can do really cool things to take notes efficiently in OneNote. Need more paper? Just drag your finger anywhere to pan to some empty spot, and continue to use stylus to draw.

PowerPoint

Anyone who has to give PowerPoint presentations would greatly benefit from using the stylus on the Surface. You can simply press CTRL+P and start to draw right on the PowerPoint! Notice a mistake? Just ink your correction and PowerPoint will save the inking you make during your presentation as annotations (you know exactly where to go back and edit!).

I find it especially helpful when you have a tough question from an audience member and need a whiteboard. Just press the “W” key and bam, you have an instance whiteboard to answer the questions.

Word

As a part-time instructor grading paper submissions usually causes a large amount of physical “dead” trees. Even “paperless” submissions will result in printing of the submissions only to hand back physical copies to the students.

This semester I went completely paperless. My students submitted their labs as Word documents to our Learning Management System (LMS) where I could download the submission, turn the submission to a PDF and re-upload my feedback! No paper, and the students loved getting a digital copy of their assignment.

Closing Thoughts

In closing, I’d have to say the best investment ever made was incorporating the Surface Pro and Office into my daily routine at work. It has now replaced my laptop and tablet; one device for all my use cases. Because it runs a full copy of Windows, I can use all my windows apps including Visual Studio, and Hyper-V (many people are amazed when I run a VM on a tablet).

Will I buy a Surface Pro 2? Although the 512 GB SSD with 8 GB of RAM is tempting, I’ll stick to my original model Surface Pro until I have to upgrade.

Friday, November 15, 2013

Everest Developer’s Handbook 2nd Edition Out

With the release of Everest 1.2 and Everest Framework for Java I’ve had an urge to update the developer’s handbook. To keep it current, as well as ensure that any common questions I get can be fed into it.

Well, the wait is over! Developer’s handbook 2nd edition is out. New in this edition are:

  • Discussion about the Java Edition of the Framework
  • Java samples (where applicable)
  • Updated .NET documentation around some of the new features of Everest
  • Discussion of the mobile components of the Everest Framework

All that adds up to about 60 more pages of content. The new version is available on Lulu as an eBook (http://www.lulu.com/shop/justin-fyfe/advanced-everest-developers-handbook-ebook/ebook/product-21278619.html;jsessionid=91BF5A0F7EF1D9B19919BB7912F441E5) or Hard Cover (http://www.lulu.com/shop/justin-fyfe/advanced-everest-developers-handbook/hardcover/product-21300345.html). As always, proceeds will continue to go toward continued development of the Framework (or at very least some coffee for our development team).

Monday, September 16, 2013

FHIR / PIX Interoperability

Well, its been a while since I’ve written about FHIR, and after lots of interesting exercises in trying figure out “where that goes” I have a working FHIR interface on the Client Registry. I’d thought about sharing some of the interesting use cases I’ve been able to test, and which I hope can be demonstrated at the FHIR CAT this weekend.

FHIR Registration with PIX Registration to XDS Registry

This was the first use case I tested. Basically registering a simple patient record via a POST to http://cr.marc-hi.ca:8080/fhir/0.11/Patient results in an ITI-44 to our XDS registry. This allows an iPad app to create a patient which is then propagated to an affinity domain (i.e. you can have FHIR interface notify another PIX manager)

FHIR Query of an ADT (ITI-8) Registration from an HIS

The second demonstration that I’ve tried is sending an ADT^A01 to the PIX manager and retrieving that data using the FHIR query. I’ve also been able to update the information via FHIR and retrieve the changes via a QBP^Q22 message.

Additionally, the business logic of a client registry (auto/manual-merging, fuzzy matching, auditing, etc.) triggered on the FHIR interface as well.

I’ll post more updates as they are available. Our plan is to take the software to the FHIR CAT and the IHE CAT in January. FHIR may be useful in mobile IHE profiles and this provides a good POC and can identify gaps (it is great to see how a system like this might behave).

Interfaces are available publicly:

FHIR: http://cr.marc-hi.ca:8080/fhir/0.11/
PDQ/PIX Version 2: llp://cr.marc-hi.ca:2100
PIXv3: http://cr.marc-hi.ca:8080/PIXManager
PDQv3: http://cr.marc-hi.ca:8080/PDQSupplier
HL7v3 (CA): http://cr.marc-hi.ca:8080/cr

Sunday, July 14, 2013

Extending Code Lists in Everest

Someone asked a really great question on the Everest forums. I am paraphrasing but the gist of the question was: “How do I add a code to an enumerated vocabulary?”. In order to answer the question I’ll dive a little into how Everest generates code lists.

When generating the RMIM assemblies, GPMR will parse the vocabulary MIF files and keep an internal representation of the value sets, code systems and concept domains that properties are bound to. When generating C# or Java GPMR will determine the best way of representing the value set in code.

  • If the Value Set or Code System is not complete (i.e. is marked partial) then any properties bound to said value set carry a type of CS<String>, CV<String>, etc.
  • If the property or Value Set is marked CWE (extensions allowed) then the the property is bound to String as well.
  • If the Value Set is made up of an expression and not all expression components can be found (i.e. intersect X and Y where Y is not available) then the property is bound to String
  • Otherwise, enumerate the literals in the value set and bind the property to an Enumeration (or IEnumeratedVocabulary in Java)

That last bit is usually the sticky point. Some jurisdictions ignore the CWE strength and add codes of their own (I have seen custom realm codes, custom null flavors, all kinds of weirdness in our travels).

In order to overcome this Everest (and jEverest) provide a relatively easy mechanism for assigning “non standard” codes to properties. For this example, let’s say we want to assign a custom ProcessingID of “Sample” (a bit contrived but it illustrates the process). To assign our ProcessingID of “S” we’d do this in .NET:

PRPA_IN101103CA sample = new PRPA_IN101103CA();
sample.ProcessingCode = Util.Convert<CS<ProcessingID>>("S");

In Java the process is a little easier as jEverest uses IEnumeratedVocabulary so we can just add the code:

PRPA_IN101103CA sample = new PRPA_IN101103CA();
sample.setProcessingCode(new ProcessingID("S", null));

The result is a (non standard) XML instance carrying our custom code:


<processingCode code=”S”/>

Saturday, July 6, 2013

Setting the Client Registry on FHIR–First impressions

I recently had an opportunity to explore HL7 FHIR in more detail (thanks to a lighter workload this week), and as a developer felt a need to actually write something.

Many of the FHIR implementations I’ve seen publicly hosted are greenfield reference implementations that demonstrate the resource based paradigms of this new messaging standard being developed by HL7. So, I did something novel, I tried to put FHIR atop an existing software implementation. But what to write? The answer was simple, I’d add FHIR to our client registry.

This post is just a rambling of some of the experiences I’ve had with FHIR as it pertains to our client registry reference implementation. I will share some opinions about how FHIR can be improved in a future blog post.

Getting Started

The first thing I did was reach out to http://hl7.org/fhir and download the C# reference classes for  FHIR. After opening the solution I found that they weren’t annotated with .NET serialization attributes, rather you had to use the supplied serializers provided in the class library. While this is great for getting started on the client side I had trouble figuring out a way to integrate them with the WCF REST stack (not a complaint, I have this same issue with Everest and extended WebServiceHost serialization formatters is not a trivial task).

So I decided instead of piggy-backing on the existing FHIR classes provided by HL7, I’d write some XmlSerializer annotated classes from scratch (I’m only supporting XML for the client registry). This was a good way for me to learn the resources and class models.

Case Based Design

One thing that immediately popped out at me about FHIR was the fact that it was case based software design. Each resource, although linked to common data types and other resources, is like an island and the style of data representation isn’t necessarily common between them. Some resources use “code” to identify themselves, other use “identifier” or “name”.  Coming from a v3 implementation background this was quite new to me.

For example, a Patient resource can have zero or more associations named “contact” with a  class named “Contact” describing a relationship. When implementing the Patient resource I created a class named “Contact” and assigned a property on Patient of that type. However, the Organization resource also has zero or more associations named “contact” with a class named “Contact” … Only the Contact class in the Patient resource and the Contact class in the Organization resources are different (well, almost the same). Of course, that should not be confused with the FHIR data type “Contact” which represents a telecommunications object.

There are lots of examples of this in FHIR where there are several classes, conveying similar concepts, yet they are completely different. Something that could’ve been solved easily using …

Inheritance

Another thing that bugs me about FHIR (from an implementation standpoint) is the lack of object inheritance. Admittedly this was abused in HL7v3 (supporting extension and restriction), but used properly it could be of benefit to FHIR. Take again, for example, the “Contact” class (from either Patient or Organization). Would it not make sense to have a common ancestor, say “Person” containing properties “name, telecom, address, gender” and then extend that for use in the “Patient” or “Organization” resources. Even Patient or Practitioner could extend “Person” as they too carry those attributes.

True, deep object hierarchies are a bad thing but some level of inheritance can do quite a bit of good. It is the equivalent to saying “operator overloads could be abused so we just don’t support them” .. True, but when not abused it is a very useful tool (apologies for the Java bash there).

Extensions

I used to hate extensions in FHIR, but after implementing FHIR on the client registry I see why they’re present. There are lots of times (especially on the CR) where data provided from a patient feed (either PIXv3, PIXv2, or the pan-Canadian HL7v3 implementation) can’t be appropriately mapped to FHIR, or where FHIR is too limited in some respect.

For example, consider a PIX feed (v2 or v3) where a mother’s information is provided (http://cr.marc-hi.ca:8080/fhir/0.09/Patient/@27423 provides an example where Edna Brown is Patricia Brown’s mother). In FHIR I can represent this relationship via a “contact” association and a “RelationshipKind” of “parent” however I’ve lost data fidelity (the real relationship is “Mother”, but might have been “Step Mother” in either case “parent” is an applicable mapping). FHIR handles this quite nicely as I can simply extend the RelationshipKind element to add the original relationship code (if you look at the source document you’ll see that).

Personally I would have liked to seen extensions take the form of the WS-* extensions (new namespace, and well defined element structure etc.) however because the FHIR standard supports JSON in addition to XML this isn’t possible, so I think they’ve come up with a flexible enough structure for resources.

Changes … Frequently

I understand that FHIR is an evolving standard, however it would be nice to have more structured changes being posted. For example, I started implemented FHIR 0.09 on June 26th, was nearly finished by July 2nd. At that time there was an association on the Patient resource named “Details” pointing to a class called “Demographics”. On July 3rd (or 4th I can’t recall) I was nearly ready to deploy my solution and was just cleaning up some code, verifying resources, etc. However when I got around to the Patient resource, the Details association was gone and there was no longer a class called “Demographics”. Wait a minute! Was I dreaming?! Did I just hallucinate an entirely new class?

Turns out I didn’t, although the spec still read “FHIR 0.09” the structure of some of the resources changed. This is more of a version management / tagging issue than anything but still should be something to beware of.

Paradigm Shift

This last one isn’t a complaint about FHIR, it is a REST based standard. This last point speaks more to the pains of putting a REST based interface on an RPC based system. It was however, the most challenging part of the project (it still isn’t complete). REST is a paradigm shift from the event based (read RPC) model on which our client registry is designed. This follows the paradigm that HLv3 and HLv2 use where an event is processed and stored (patient was admitted, patient was merged, etc.). For this project I had to somehow map those events to RESTful CRUD operations.

It isn’t too bad for querying and reading (the only operations currently supported) as we can simply pluck contents out of the patient table however we do lose some data fidelity and context (at least in our implementation). It will cause us some grief as I move to extend the FHIR interface to support creation, update, and merge operations.

For example, it is possible on an admit (or register in v3) to specify the “custodian” of the data, or the location where data was entered, etc. All of which are used by many facilities including business rule enforcement and auditing. The registry has some context as to the event that occurred which resulted in the new record being created, updated, etc. In FHIR this context is a little more difficult to attain. To the FHIR interface (as with any REST system) we’re stuck with CRUD operations on the resource (to be fair extensions and/or the Transaction resource can be used to facilitate this, but then we’re just stuck putting RPC atop REST).

Final Thoughts

All-in-all, the FHIR implementation for the CR wasn’t too bad. It took about a week of effort to get read, version read, version history and query on the ValueSet (another discussion on its own), Profile, and Patient resources. When I have more time I’ll get to work on the create and update operations.

The final product is quite impressive. Assuming I’ve interpreted the FHIR documentation correctly; we now have a PIX manager that can accept v2, and v3 patient identity feeds and allow clients to query using rest (you can try it here : http://cr.marc-hi.ca:8080/fhir/0.09). There are approximately 15,000 patients in the registry (all randomly generated of course).

To assist in your exploring, here are some patients of note:

  • Justin Fyfe (lots of versions as the result of Merge operations)
  • Patricia Brown (has a relationship with her mother)

I will post more about this adventure as it progresses.

Friday, May 31, 2013

Emitting XML Comments from Everest

A great question came to me the other day. How does one pretty-up the XML output generated by Everest so that humans can read the XML? Of course there are the old tricks of indentation and formatting the output however that only gets us so far.
Wouldn’t it be great if Everest had the capacity to emit comments in the XML instances. Sadly this isn’t a use case for vanilla Everest however there is a way to easily do this in the upcoming 1.2 release of Everest (being released on June 5th BTW).
Lets say I want to emit a comment that annotates the <acceptAckCode> element, something like this:
<?xml version="1.0" encoding="utf-8"?>
<PRPA_IN101301UV02 ITSVersion="XML_1.0" xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:hl7-org:v3">
  <id root="F043D3BF-02C4-48BF-8C7E-6FFEE7D75B52" />
  <creationTime value="20130531171954.939-0400" />
  <interactionId root="2.16.840.1.113883.1.18" extension="PRPA_IN101301UV02" />
  <processingCode code="T" />
  <processingModeCode code="A" />
  <!--The acknowledgement code—>
  <acceptAckCode code="AL" />
</PRPA_IN101301UV02>
The way I would do this is to add an extension method to IGraphable to allow users to add commnents: public static class CommentExtension
{

    private static List<KeyValuePair<IGraphable, String>> s_comments = new List<KeyValuePair<IGraphable, string>>();
    private static Object s_syncLock = new object();
    public static void AddComment(this IGraphable me, string comment)
    {
        lock (s_syncLock)
                s_comments.Add(new KeyValuePair<IGraphable, String>(me, comment));
    }

    public static string GetComment(this IGraphable me)
    {
        return s_comments.Find(o=>o.Key == me).Value;
    }
}

We can then extend the XmlIts1Formatter and override the WriteElementUtil method to emit the comment added prior to serializing the element:
public class XmlIts1FormatterWithComments : XmlIts1Formatter
{
    public override void WriteElementUtil(System.Xml.XmlWriter s,
               string elementName,
               MARC.Everest.Interfaces.IGraphable g,
               Type propType,
               MARC.Everest.Interfaces.IGraphable context,
               XmlIts1FormatterGraphResult resultContext)
    {
        String comment = g.GetComment();
        if (comment != null)
            s.WriteComment(comment);
        base.WriteElementUtil(s, elementName, g, propType, context, resultContext);
    }
}

Then, using this new formatter we can simply add the comment and format!


PRPA_IN101301UV02 test = new PRPA_IN101301UV02(
    Guid.NewGuid(),
    DateTime.Now,
    PRPA_IN101301UV02.GetInteractionId(),
    ProcessingID.Training,
    ProcessingMode.Archive,
    AcknowledgementCondition.Always);
test.AcceptAckCode.AddComment("The acknowledgement code");

var formatter = new XmlIts1FormatterWithComments();
formatter.GraphAides.Add(new DatatypeFormatter());
formatter.Graph(Console.OpenStandardOutput(), test);
Console.ReadKey();

Hope that helps anyone else with the same problem!

Saturday, April 13, 2013

Client Registry Reference Implementation

After nearly two years of development, the Mohawk College Registry Reference Implementation is available for download via the Technology Exchange (http://te.marc-hi.ca/release.aspx?project=67fa30913b01414aaa20399f65e6b406).

This is a copy of the client registry software that the College runs in our reference implementation infrastructure. Currently, the software supports:

  • IHE PIX HL7v3
  • IHE PDQ HL7v3
  • IHE PIX HL7v2
  • IHE PDQ HL7v2
  • pan-Canadian Client Registry Messaging R02.04.02

Note that none of the IHE stuff has undergone connect-a-thon testing yet (though it has been integrated with several packages that have been verified at CAT). The client registry is open source (as is all our software) under the Apache 2 license.

Using this client registry reference implementation, you can easily setup an IHE affinity domain on windows leveraging the Microsoft XDS.b Solution Accelerator (http://ihe.codeplex.com), the client registry, and OpenATNA. The PIX manager has been tested as a patient identity feed to the solution accelerator and as an audit source to OpenATNA.

More to come on this exciting addition to the Tech Exchange!