Convert your FHIR JSON -> XML and back here. The CDA Book is sometimes listed for Kindle here and it is also SHIPPING from Amazon! See here for Errata.

Thursday, July 20, 2017

Date queries as offsets from now in FHIR

It's fairly common to ask questions about time in relationship to now.  Have you had a mammogram in the last 12 months?  What medications was the patient given today?  What are the labs for the last 30 days.  Can we schedule a visit for a month from now?

When a date query is expressed in the form of a simple quantity, there are two pieces of information given: A value, and a unit of measure in duration.  When expressed as FHIR queries, a date and a simple quantity are quite readily discernible.  Dates have -, : or T punctuation in them.  Simple quantities have units and | punctuation.

So I decided to try this out mentally.  One of the challenges is dealing with precision.  If someone asks me what I've did last month, I'm thinking June.  If they ask me what I've done in the last month, mentally I'm thinking July and the end of June, because I mentally translate to 30 days or so.  But then if they ask me what I was doing more than a month ago, I go back to thinking in one month chunks, so before June.

I decided that units specified in the query would also specify the units of precision.

I adopted the convention that a date query parameter named "date" would have an alternate way of specifying it using the name "date-fromnow".

So, if you query from date-fromnow=le-1||a what you would be asking is "what happened in the year before the last one." That's equivalent to date=le2016.  If you wanted more precision, you could ask in months or days (weeks are a bit messy, so I didn't deal with them).  Thus, date-fromnow=le-12||mo means date=le2016-07.  And date-fromnow=le-365||d means date=le2016-07-05.

Good enough.  Time to go implement this and see how it pans out.


P.S. For what it's worth, this is quite useful to implement some of the guidance in the Relevant and Pertinent work that was done=-1||a.

Wednesday, July 19, 2017

How do you write a blog?

I get asked this question a lot.  The answer of late is that I haven't been, but I'm getting back into it. This is my fourth post in five days, back up to my previous rhythm when I was at top of form.

There are three big issues:

  1. Time
  2. Topics
  3. Trepidity (bordering on Terror)


Where do you get time to write?  A lot of the topics I write about are things I'm already spending time on.  Taking what I'm working on and turning into a blog post is a lot easier than writing a post specifically for this blog.  It takes 10-15 minutes, and in the end, I have more clear thinking AND a blog post.  
Allocating time to write is critical.  It doesn't need to be at a fixed time each day (or week or whatever frequency) is important.  It takes discipline.  Make the commitment, and then execute. 

After you've been repeatedly writing a post on a regular rhythm, you will find it takes much less time. When I first started this blog, I might have spent an hour or even two on a post.  These days, it takes much less time.

In summary, use what you are already doing, make the commitment, and give it time to improve.


I get my topics a number of ways: Standards projects, mailing lists (a good e-mail response to a list group can also be a good starting point for a blog post), news articles, my Ask Me a Question page, and sometimes, just staring at a blank screen.  When a good topic comes to mind, I write it down for future use.  I don't have a big future pipeline, maybe one or two ideas at most.

Yesterday's post on Building Blocks was essentially me thinking out loud about my position on interop building blocks.  I took an item I was already working on for my own needs and repurposed it for something else.  The post on vocabulary started from an email on an HL7 list.  This post today started from a question someone asked me that I've had asked before (always a good sign that a blog post might be warranted).

That blank screen is is a challenge.  Some days you'll be in that time for writing a post, and have NO topics.  I just start writing and see where the flow takes me (those are usually tagged Rambling).


Not really a big issue for me, never was.  But I understand performance anxiety, and writing a blog is kind of like performing. The basic issue is that you need to finish strong. In any performance, the audience may notice a small bobble, but the reality is that if you finish well, few will remember your mistake, and most will remember your finish.  Don't be afraid to make a mistake. That's how you learn.  Fix it and move on. People will remember the good stuff.  If you write a terrible post, write a better one next time.  If you stop writing because of a terrible post, the first thing people will see is that post on your blog.  Write another one.

A blog doesn't need to be great, it just needs to consistently good. The best way to get there is to do it.

Tuesday, July 18, 2017

Building Blocks

If you are like me, you probably had a number of different "construction" toys growing up.  I had Tinker Toys, Lego blocks, Lincoln Logs and an Erector set.  In fact, I still have the Lego and Erector set, although they don't get much use any more.  Mostly because I get enough time to construct cool stuff for my day job.

I ran across this video this morning.  You can probably relate.

These are my building blocks today:

  • CDA Templates
  • FHIR Resources (and Argonaut Profiles of them)
  • IHE Cross Enterprise Document Sharing Family of Profiles
    • XCA, XDS, XDR and XDM
  • IHE Mobile Access to Health Documents (MHD) [Basically a FHIR replacement for the above]
  • OAuth2
  • TLS
  • FHIR Audit Resource
I've done CDA to FHIR transformation and visa versa, CDA to XD*, XD* to MHD and MHD to XD*, and mapped ATNA to the FHIR Audit Resource.

I have the "adapter kit", and I've also built some adapters for X12 and HL7 V2 (a whole chapter of the CDA Book is devoted to V2 to CDA transformation, and I've also done the reverse).

Each of these "building block kits" has a slightly different way of doing things, but since they were built incrementally, usually with knowledge of at least one predecessor, there's some clear backward compatibility built in [although not exposed to those unfamiliar with the history of these works].

If you want to put wheels on something, there's a Lego way to do that, or a Tinker toy way, or an Erector set way (I haven't really figured out how to do it with Lincoln logs yet), and the same is true for my "adult set" of toys.  And just because I can do the same thing with both, the amount of effort invested varies.

FHIR is extremely promising as a way forward, because it continues to incorporate the learnings from previous efforts.  But we aren't all the way there yet.  I have a significant investment in Lego, and it's wickedly cool and easy to put together.  But it doesn't quite have the strength to span long distances with great weight reliably and at the same cost per piece the way that an erector set does (but I suspect it will get there).

  1. Will we get there?  Eventually I think we will.  
  2. But we've also had Highlander for 30 years.  Have we reached only one yet?  No.
  3. Is it going to happen soon?  Yes.  
  4. Soon enough to make everyone happy? Surely not, because that would have meant we had reached that point a decade ago.

Monday, July 17, 2017

The Vocabulary of Vocabularies for the non-Vocabularist

In informatics and health IT standards circles we talk about Ontology in a way that assumes that everyone understands what that means.  Yet the ontology of ontologies is rather complex and confusing, in part because definitions are in some ways, rather "meta".

What follows are my own definitions, written to be intelligible to a software engineer without informatics or health IT standards training.

TermA word or phrase describing a thing, and associated with a concept (see Concept)
Preferred TermDifferent words or phrases can be used to describe the same thing.  A heart attack can also be described as a myocardial infarction.  The preferred term is the term for that thing that is preferred above all others.  Preferred terms are often those with the most "crisp" meaning (e.g., Myocardial infarction in the above example).
ConceptThe abstract idea associated with a thing.  This is the idea that is (intended to be) brought to mind when one uses a term to describe a thing.  A good concept has a definition associated with it that allows a user to understand the meaning of it.  In my not so humble opinion, the position of a term in an ontology is an insufficient definition because it is only intelligible to those well versed in the structure of the ontology.
CodeAn identifier associated with a concept.  It is a string of symbols (usually digits, but also can include letters and punctuation) that uniquely identifies the concept within the system using that code (see system below).  Codes can be meaningless (e.g., as used in LOINC), or can also express structure (usually hierarchy) as in ICD or the Healthcare Provider Taxonomy.
Check DigitA digit or character in the code used to enable verification that the string used as a code is valid and is not the result of some sort of data entry error.  Check digits prevent various kinds of data entry errors including deletion, insertion, and transposition.  LOINC uses MOD10, and SNOMED uses Verhoeff algorithms to compute check digits.
VocabularyA collection of terms describing things.  A good vocabulary has both the terms, and associated definitions of what those terms mean in a way that the users of that vocabulary can understand the meaning.
Value SetA managed collection of terms describing related things and associated with some sort of identifier so that it can be referenced. A value set most often contains terms from the same vocabulary system, but might include terms from multiple vocabulary systems.
HierarchyAn arrangement of things into a tree structure, such that each item (except the top-most) has exactly one parent.
Poly-HierarchyAn arrangement of things into a directed graph structure without loops, such that each item in the graph (except the top-most) has at least one, and can have more than one "parent". There may be multiple top-most items.
ClassificationA vocabulary that describes all the different things that can happen such that the description of any one thing fits into one and only one bucket.
TaxonomyA hierarchical classification; A classification that also has a tree structure associated with it.
TerminologyCustomarily, a terminology is a collection of vocabularies that can describe multiple related things.
SystemA phrase appended to code, vocabulary, classification, taxonomy, terminology or sometimes ontology.  The word system implies a process or method associated with the work. When this word is used, it implies a degree of formality associated with the development of the work.
OntologyIn this context, an ontology is a classification system that describes not only a collection of things, but can also describe the parts of itself.  Under this definition, SNOMED CT is an ontology, and so is LOINC (because some LOINC parts describe LOINC itself), but ICD is not.

Friday, July 14, 2017

Wearing Many Hats

When I first started working with ANSI/HITSP over a decade ago, one of the things I remarked upon to several people was the outstanding ability of John Halamka to wear many hats, and to make it clear which hat he was wearing when he was speaking, and his general ability to be wearing the right hat for the right audience.

It's a tricky challenge, and quite a juggling act.  I don't do it nearly as well as John does, but have been doing it a great deal over the last 18 months.  These are just a few of them in approximate rank order based on time investment (though not necessarily personal preference):
  1. Patient Advocate
  2. Architect Owner
  3. Product Owner
  4. Subject Matter Expert [Health IT Standards & Regs]
  5. Informaticist
  6. Software Developer
  7. Engineering Manager
  8. Thought Leader
  9. Student
  10. Teacher
  11. HL7 Board Member
  12. HL7 Member
  13. IHE Member
  14. Document Writer

I often find my various hats being at war with each other.  My software developer side wants to argue with my SME side, or sometimes I find my IHE side needs defending from one of my HL7 roles or ...

When that happens, it is very challenging to understand how to resolve the problem.  The pragmatist and the purist at war is not pretty.  Purism has its place, as does pragmatism.  Perfect is the enemy of the good goes to battle against applying the time to do it right as compared to the time to do it over.

How do I resolve this?  I've begun to discover that the final hidden role is that of customer advocate. That jumps to number 2 on my list.  Where Patient Advocate cannot break the tie or bring peace, Customer Advocate often can.

What roles do you play?  How do you reconcile them?

Friday, June 23, 2017

Thanks to That Person

In my first computer class, we entered our programs using a line editor, and unless we were unlucky, had a CRT to work with (although the unlucky still go stuck with the linotype).  We had a text book, some well thumbed compiler manuals on a bookshelf that were shared among the many students, and there was always, somewhere, that guy (or less often but still present, that girl), who soaked it up and knew the answers to the real tricky stuff.

As I moved into the workplace, we had CRTs still, but some had graphics capabilities, there were still tons of manuals on our shelves (and for most of us, we each had our own copy).  If you were one of the lucky ones, you got graphics.  The manuals were less well thumbed, and somewhere in the office, there was that guy (or more frequently, that gal) who knew how to find the answers.

Later, we all got to move up to 16, then 256, then 16384 colors, with 640 x 480 resolution, and then 800 x 600, and if you were one of the lucky ones, 1024 x 800 displays.  Email came to the fore. Manuals were still handy, yet there was still that person.  Sometimes they'd be in another office. You'd pick up the phone, or send them an email.  After two or three forwards and days, or more depending upon the challenge, the e-mail would come back with the answer.  And because that person had email, if they didn't know the answer, they at least knew who did.

And then came the Internet, and CD drives.  Instead of a shelf of books and a file drawer full of disks you saved because you just might need them again, there was the almighty CD.  And books were fewer.  And if you were one of the lucky ones, you had INTERNET!  And that guy or gal might be a half-continent away, and e-mail was reliable and you'd only need to way a few hours.  And he or she probably had Internet, at least at home, because they still sucked it all in, and knew where to find the answer, on the Internet, or on the CD.  Of course, you still had a drawer full of CDs, but at least it was a normal one instead of a file drawer.

Now we have StackTrace, and web sites, and volumes of data.  You can ask Google or Bing. Training is online, complete with slides and audio. that person has a blog, and a twitter account or a linked in, or all three. You no longer need to be lucky to have a laptop, though if you have a touch screen or tablet, you can probably to count yourself among the lucky.  You can read what that person has to say daily, or even listen to them or better yet watch them. That person now has fans.

I'm a fan of lot of people out there.  You know who you are.  I couldn't this person without you being that person.  Thanks.

-- Keith

Tuesday, June 20, 2017

Handling Extra OAuth2 Authentication Parameters

I'm deep into spec'ing out an OAuth 2 implementation, which means that I have to give all the detailed rules about what to do with parameters sent to the authorization endpoint of an OAuth2 server.  The question arose, what do we do with parameters that aren't recognized.  Fortunately, OAuth2 clearly resolves this issue for us (and for you):

In the section describing the OAuth2 Authorization endpoint, what OAuth2 says is
"The authorization server MUST ignore unrecognized request parameters."
There's a very good reason for this.  It allows profilers of OAuth2 to add parameters with additional specified behaviors.  You won't find the SMART on FHIR "launch" parameter anywhere in the OAuth2 spec. For those endpoints that do recognize it, they can do something useful with it.

The same thing works for unrecognized scopes.  If you don't recognize it, it isn't an error, just ignore it and it should go away (the application that sent it should be expected to behave correctly when it is ignored).

Postel's law rules.