Wednesday, April 20, 2022

Spoiled Rotten and Not Knowing It

When I was young and naive (about 20 years or so ago), I was responsible for leading up part of a development team who worked on a XML database product that ran on the early web and which could serve up XML content or HTML pages in response to requests.  One of the people on our staff had a masters (in mathematics or computer science, I cannot recall which), and was also working on his doctorate in the same.

Every Monday I would get a report about the product performance he wrote, and the changes in performance between this week and the last.  It was filled with estimates on the number N of requests needed of each type to verify performance improvements, and mathematics behind it, and then the design of the performance tests ... experiments he called them.  And they were carried out with that kind of experimental accuracy you'd expect from a scientist.  The results, the relative improvements (or dis-improvements), error bars, and the expected P values and all the rest the rest were in the summary report, about 10 pages, every week for weeks in a row, on my desk, Monday morning from the past week's performance run.

He set my expectations for performance testing in a way that would leave me almost forever disappointed for the rest of my career.  I was spoiled rotten for months and never knew it.  I miss him, and I wonder where he went.  He was only with us for a short period of time, I think on an internship.  If I was team captain, he was my Scotty, not just an engineer, but a true scientist.

That company was my introduction to standards development (in W3C), and gracefully self-disrupted at the outset of the .com bust in 2001, which led me to my career in healthcare, and eventually Health IT standards.





Thursday, March 24, 2022

SMEs know the right Keywords

Schmee
Somewhere in the course of my career, I spent a good bit of time working on "Information Retrieval" projects.  I think my first one was a search enhancer while working for a linguistic software company, but in reality, much of my earlier work experience was also related to building searchable repositories for information.  My Capstone project was also an Information Retrieval project.

And even before that, I was an expert at finding things in books because I could remember WHICH book had the answer, and how to find the right page using the index.

A recent Facebook post I ran across asks: "Badly explain your day job".  I should have responded with the image above.

I suppose part of it is translating questions into Google and Stacktrace queries, but it's not just "JFGI".  A lot of the time it's translating the querant's request into terms that Subject Matter Experts (SMEs) in a particular art would use to answer the question.  I'm not an expert so much of in terms of what I know, so much as in what I know how to find out.  Yes, I have encyclopedic memory of the CDA R-MIM, and a few other things, but I don't keep that on the top of my memory, instead, I know where to find what I need.

The CDA Book came about so that I'd have a list of those things that I need for my work in print form by my desk (and yours).  This blog came about for some of the same reasons.  I know I wrote something about that, where the heck did I put it.

If Web 2.0 is the Semantic web, and Web 3.0 is some Block chain related thing, Web 4.0 should be the translator of simple questions into expert answers, and if we get there, we will also have solved the Touring problem.  Because to do what I do as a significant part of my day job, is to get INSIDE the head of the querent, figure out what they are really trying to do or understand, and then, get the expert answer and translate it back into something that they'll understand ... the Freshman lecture version if possible.



Friday, February 25, 2022

Debugging Network Communications - For the Rest of the World


In one of my very early forays into IHE standards implementation, I had to implement TLS version 1.0 shortly after it became an IETF RFC, in Java, using Tomcat.  Thus began the ATNA FAQ.  Thiat document is now 15 years old, and is still being used (at least by me).  I started writing these kinds of things down so I don't forget them, which eventually resulted in this blog.

I'm still debugging TLS connections, and I have to admit that it's become a particular art form, but not so much as in finding out what when wrong, and figuring out the solution, but rather in explaining it to someone who is NOT versed in the ingredients of TLS connection sausages so that can a) find the right person to fix it, and b) communicate what needs to be fixed without c) further intervention from me.  That's high art.

I have a highly evolved tool set including:

  • DNS, Ping and TraceRt
  • WireShark
  • OpenSsl
  • JVM debugging arguments
Here's the problems these tools help me identify.  Each requires appropriate communication..
  1. My computer cannot get a good TCP/IP address for the supplied hostname.
    1. Either DNS is down somewhere, or the new DNS record is still propagating, or it simply does not exist.
  2. My computer cannot connect to the TCP/IP address that DNS gave it.
    1. The DNS change for your server may still be propagating
    2. That IP address is not connected to the Internet, is not within my reachable networks
      1. The sending computer sends a SYN, but no ACK is ever returned.
        1. Ping returns no response to that IP (may be blocked by a firewall).
    3. The firewall doesn't like the computer it is coming from.
      1. Same symptoms as above.  Firewalls and application gateways (Firewalls on steroids) and other interfacing technologies (e.g., AWS Lambdas or Azure Functions, gateways that have been weaned from Steroids) can mimic just about anything, but most often, they just hide your computer from mine.
    4. The computer is actively NOT listening to connections from that address.
      1. SYN goes out, but a RST comes back.  In other words, I'm listening to communications, just not to THAT port.
  3. The computers can connect (three way TCP SYN, ACK, SYN-ACK completed), but we cannot make a TLS connection.
    1. My client sent your computer a TLS version it didn't like. You server needs to enable support for TLS Version (1.2 or higher).
    2. My client sent your computer a set of encryption protocols it really doesn't care for.  Your server needs to enable the following encryption protocols ...  (RSA or DCHE Galois Cipher Mode[GCM]).  Cyclic block cyphers (CBC) are no longer considered to be secure.
    3. Your server sent my system a certificate it didn't like, it was:
      1. Expired, please renew it
      2. Revoked,  please replace it with a new certificate
      3. Not secure enough ... please use a certificate supporting at cipher strength of at least (2048 bits).
      4. Not signed by an entity trusted on my end
        1. Our system doesn't accept self-signed certificates, please get your certificate signed by (a commonly trusted CA, or a CA of my choosing)
      5. Prepared using an algorithm my server doesn't support.  Please use an certificate signed using (the RSA algorithm).
      6. For a server going by a different name (this one is rare.  Hostname matching is important in many circumstances, but in cases where the server that is supplying the certificate is three layers deep behind other network infrastructure, it has no clue, and so is often disabled.
    4. Your server required a client certificate from my system that it doesn't have.
      1. Here's our certificate chain, please trust someone in this chain - OR -
      2. Please supply me with the necessary client certificate and the instructions for the obtaining one (the administrative hoops that I have to jump through to get them).
The problem with this are:
  1. The tools are complicated and require either good training or documentation for folks who haven't needed to learn to use them.
  2. You actually have to understand how the Internet standards work to determine what tool to use and when.
  3. I don't scale.  We need me in a box (or more specifically, in a service).
So, I've resolved to work on a tool to do this sort of testing for me, with the details about what is wrong written in very user friendly language about what it finds about the problem.  It's an interesting bit of interface engineering.



Monday, February 21, 2022

Automating FHIR IG Generation from Non-FHIR Sources by cloning myself

An awesome lot of my FHIR IG development involves taking data in one structure and converting it to other structured formats required by the FHIR IG Development process.

That includes creating .fsh and .md files from structured data.

I do most of my FHIR IG development in Eclipse (because if it involves code or transforms, that's where my XML Editors plug in, or my Java transform code for other formats).  I've narrowed down my processes so that I can run Sushi, the FHIR Build or my "custom build script" from within eclipse with one of three external tool configuration scripts:

Here's my normal "Build" script, which just launches build.bat in the project root folder:

<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
    <stringAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_ENCODING" value="UTF-8"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LAUNCH_CONFIGURATION_BUILD_SCOPE" value="${project}"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\Windows\System32\cmd.exe"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="/c build.bat"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/></launchConfiguration>

Sometimes I just want to rebuild the IG, for that I can just call the IG Publisher:

<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
    <stringAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_ENCODING" value="UTF-8"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LAUNCH_CONFIGURATION_BUILD_SCOPE" value="${project}"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\jdk-11.0.2\bin\java.exe"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Xmx2G -jar ../publisher.jar -ig ig.ini -tx n/a"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>
</launchConfiguration>

And sometimes I just want to rerun Sushi alone, without running FHIR:

<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
    <stringAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_ENCODING" value="UTF-8"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\Program Files\nodejs\node.exe"/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="C:\Users\kboone\AppData\Roaming\npm\node_modules\fsh-sushi\dist\app.js fsh -o ."/>
    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc}"/>
</launchConfiguration>

Save any of these snipped to a file named your-file-name.launch and you should be able to import it as an external tool configuration.

I've even gone so far (finally) as to make this build process an automated part of my check-ins to the FHIR Repository (that way I don't need to be present to run the scripts when source material changes).  What I usually do is take the command line (Windows) script and convert it to Unix and run it in GitHub CI/CD.  For V2-to-FHIR, I just recently created a CI/CD workflow that updates the Sushi from CSV files downloaded from Google Sheets.  This is all for publication purposes.  For SANER, I had other tools to create the SANER IG from an XML file I've been using for IG creation for IHE profiles.  Effectively what I'm doing is cloning myself using GitHub CICD.  I'm not even the first person in the community to do this.  It's basically how build.fhir.org runs, essentially as Grahame in-a-box, but it scales and neither I nor Grahame do.

We were running that up until a few weeks before final publication, after which we did all edits to the files created by the automated process, and removed all the code that supported that process.  That's because the FSH and FHIR IG content in GitHub are the official sources for the IG, not the process inputs used to generate them, and I don't want to be on the hook for maintenance for life for my own tooling that I'm using MOSTLY to make my life easier.

I've build now about 5 different guides using automated FHIR IG (and FSH generation tools).  It's the only way to fly when you have to turn dozens of structured inputs into FHIR IG outputs.


Wednesday, January 12, 2022

Omicron: Questions but few Answers


As a member of the Health IT industry, I follow a lot of what is going on related to Healthcare, and as a result, many of my family members ask me for my opinions, advice, and guidance about healthcare issues. That includes where to go and who to talk to in order to resolve an issue in our Healthcare System [sic].

With Omicron, what I know well is fairly limited:

  1. Get Immunized / Boosted
  2. Stay Masked when you leave your house/car or enter any public space.
  3. Avoid Crowds / Stay in your bubble
But here are some of the questions I have:

You can be asymptomatic with COVID (even more likely with Omicron).  Should I be testing on a regular basis to be sure I don't have an asymptomatic + breakthrough infection?  If so, how frequently, and what kind of test (e.g., PCR or Antigen, and if the latter which brand or brands) should I be using?

If I become symptomatic, what should I do? Test? Isolate? Both?  If I test positive, what's my exit criteria from isolation and what are the risk factors I need to consider?  If I test negative, how likely is that to be a false negative?

If one needs to travel within the US, what should we know about that destination and how should it affect our behavior.  Are there destinations we should avoid right now?  Why?

Because the information I get is coming in so quickly, often has yet to be peer reviewed, or may be poorly reported, and is also often conflicting even from well known and respected authorities, who should I be listening to and trust?

I have a ton of Surgical Masks, a more limited supply of KN95 respirators.  I use the latter in places where I feel more exposed, the former in places with less exposure.  What kind of exposure criteria should I be considering?  Should I toss all my surgical masks and simply replace them with KN95 masks?

For me personally, I honestly think I'm at low risk of experiencing a serious adverse event due to COVID, because of the precautions I am taking.  But if I include in that "serious adverse event" that I also want to avoid being the cause of a serious adverse event for some other person (whether a member of my family, bubble or community), then I quickly become clueless.  

It's not that I don't know where to look or who to ask for myself, but rather, I have no good way to communicate to those I interact with what I know (or think I know).  

And oh, by the way, don't ask me anything about the next variant.  I have no clue what that will bring.  Does anyone?

If any of you out there reading this can do better, please provide feedback in comments below.



Friday, December 3, 2021

New Years Resolutions for 2022

It's been a while since I've posted anything related to Health IT Standards here.  I have three New Years Resolutions for 2022:

  1. Don't schedule or accept any meetings on Friday afternoon.
  2. Focus attention on Patient Administrative Burden (a phrase I read in a response to this recent rant thread from @HITPolicyWonk).
  3. Do more Deep work and report on it here.
I've been doing a bit of reading (of the non-fiction philosophical variety) lately.
  • Algorithms to Live By by Brian Christian and Tom Griffiths
    This is an awesome collection essays about the application of computer algorithms to various aspects of life, and what they have to teach us about the tasks we don't always involve computers in.  I think what I enjoyed most about this book was the creative links the authors made between algorithsm (most of which I know well), and everyday tasks and processes.
  • Thinking, Fast and Slow by Daniel Kahneman
    This book endeavors to explain how decisions get made and are influenced by the conscious and unconscious processes in our brains, and the various tendencies that are influenced by our intuitions, the biases that they introduce, and to some degree, methods by which one can eliminate some of those biases from our thinking.
  • The Most Human Human by Brian Christian
    I picked this one up because I've been interested in Artificial Intelligence since early college years, and the Turing test always amused me, and because I enjoyed an earlier book by the same author.  There are some interesting musings here that again cross between computing and everyday life.  Compared to Algorithms to Live By, this one wasn't quite AS interesting, but a fun read none-the-less.
  • Deep Work by Cal Newport
    I'm still ploughing through this one, but after 3 chapters, I'd heartily recommend it.  That's saying something because it's VERY hard to find a book I cannot finish over a weekend, but this one involves that kind of reading.  It's deep work to understand deep work.  I haven't been doing enough deep work lately, and it makes me sad.  Hopefully, I'll learn enough to fix that.
  • Clean Code by Robert C. Martin
    A classic, and one that I recently re-read, a decade + later.  I don't fully agree with everything said in this book b/c Robert misses a key point.  There's concepts and nuance and a whole language associated with so many programming frameworks, and in many of these, the frameworks are so large that even the best engineer can't keep them all available to them.  As part of a team that has a common approach, following the guidelines in this book are valuable.  But what the book won't do for teams is enable a new person to join the team without prior experience in the framework and be able to understand the code as written.  I recently read through several thousand lines of an application built by a very skilled engineer following the principles in this book, and because I know where to find the right stuff, was eventually able to understand it, but having never used one aspect of that framework in a production environment, found myself lost until I could go do some useful reading.  A simple comment describing the design pattern or framework in use would have made the code much easier to understand.  Do NOT underestimate the longevity of your code.  All too many times in my life I've encountered code where the person who wrote is no longer living, the person who took it over is retired, and basically, there's some grunt who can compile, build and occasionally fix bugs in the code, and the ideas, frameworks, thoughts and standards of two decades ago are completely unknown to the originators.  As developers, we live on internet time.  What is obvious to us today is forgotten 5 years from now because someone figured out a better way.  Be kind to them who have forgotten everything that is in the front of you mind and obvious (to you).  Still useful reading, but do so with a critical eye.  Like any other concept that is at least a decade old, there's some new thinking that has replaced some of these ideas.



Saturday, November 27, 2021

On Air: Part Three

  

I'm finally finished with my On Air lamp prototype.  The goal of this project was to build something that would indicate when I have the camera and mic rolling in my office without any intervention on my part (basically, all I need to do is start a meeting and it goes on, or end it and it goes off).  I've managed that.

It took me quite some time to figure out how to get Windows 10 to tell me when the microphone is in use.  The key is in the registry keys located in the registry hive for the current used found in SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone.

In this hive there is at the top level, a hive of keys for each Microsoft Store app, and beneath it, another hive of keys found in the NonPackaged hive.

If you inspect the registry with RegEdit, you will see that each hive under that key looks something like this:


The key (pun intended) key is LatUsedTimeStop. When this value is 0 for any application, that application is presently using the microphone.  When it's done, that value will be a Windows timestamp (the number of 100 nanosecond intervals since 1/1/1601 UTC).

I wrote a little Java program called OnAir that scans the registry, checks for the Microphone being in use, and sends the appropriate messages to the wireless controller to adjust the state of the lamp.

I tested it with almost all of my headsets (I have four in my office of various types), and it works with any of them, and with any application that uses a microphone.

To make this code work I needed to be able to access the registry from Java.  There's a lovely little Java package that does this called JNA.  The dependencies to include it are below.

<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.10.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId> <version>5.10.0</version>
</dependency>

I suppose I could have used this as an opportunity to write in .Net, but realistically, I was just looking to get the lamp off my desk, and to do that, I needed to finish the prototype.

There's so much more I could do to finish this. The application could use a UI to indicate the state of the lamp, and to activate/deactivate it for certain applications, and indicate which application is using the microphone.  The app itself should run as a service.  The electronics could be cleaned up so that I don't need two USB cables, and the wireless component could be mounted inside the lamp.  For now, it's good enough for what I wanted, so I'm calling it done, and declaring "Ship it!".