Friday, December 9, 2011

Moving...

Well, after a good long run at 5933 Baum Blvd(thanks Mark and Skip), we are moving to our new digs at 5530 Penn Ave.  We'll probably have fewer happy hour/creative thinking sessions at BRGR, and more at Salt of the Earth, and Verde.  And we get WINDOWS!!!

Thursday, October 27, 2011

AMIA Conference and Paper

So, I went to my first academic conference as an author.  The American Medical Informatics Association's Annual Symposium in Washington, DC.  I had submitted a one page paper describing the results of our NIH SBIR Phase I study, and they accepted it for the Tuesday poster session.
At the session, I had a pretty good turn out.  I had lot of people ask me questions, and got a lot of good feedback.  Big thanks to Maggie for creating a very attractive poster!



Here is the paper, now that it is published - AMIA Annu Symp Proc. 2011 Oct 25 ;2011:1710.



Automated creation of clinical progress notes with machine learning
Michael Cham, CTO, Raymond Benza, MD, Jaime Carbonell, PhD
BlenderHouse, Pittsburgh, PA; Allegheny General Hospital, Pittsburgh, PA; Carnegie Mellon University, Pittsburgh, PA

Abstract
The goal of this project was to demonstrate that our machine learning approach could mimic individual physician’s diagnostic and care planning abilities by learning from clinical progress notes.  Using 500 notes from 3 physicians, we were able to achieve accuracies in excess of 97%.  This technology will be embedded in a product that can improve clinical efficiency and patient safety through electronic medical records and clinical decision support systems.
Introduction
Electronic medical records (EMR) systems and clinical decision support (CDS) systems have the potential to address preventable readmissions and medical errors problems in the U.S., but are missing key pieces of functionality or aren’t well integrated enough into the clinical workflow to help.  Additionally, EMRs are actually introducing new kinds of medical errors and negatively impact the productivity of clinical staff.
The goal of the study was to prove that the technology at the core of our product, CompleteNoteTM, could learn to mimic individual physician’s diagnostic and patient care planning abilities, learned from actual electronic clinical progress notes. Adding this capability to EMR and CDS systems would improve the efficiency and accuracy of documentation and provide customized, patient-centric decision support.
Methods
We obtained 500 de-identified clinical progress notes from the Heart Failure, Heart Transplant and Pulmonary Hypertension Clinic at Allegheny General Hospital.  Three different physicians composed the notes. The notes were in Microsoft Word format, directly from a dictation/transcription service. The notes were then parsed and stored into a MySQL database, breaking down the notes into logical sections, vitals, problem lists, medications lists, lab results, diagnoses, and care plans.  
We utilized our proprietary, support vector machine-based, multi-statement prediction approach and generated eight statistical models.  There are two models for each of the three physicians, one for predicting patient diagnoses, and the other for predicting care plans.  For each physician model, we only used notes that they created.  We also created models for the union of all three physicians, which effectively blends the abilities of all the physicians.  The union models used all the notes from all physicians.  All of the models were restricted to predicting statements that appeared in at least 2% of the notes, in order to produce significant results.  We achieved the best results using linear kernels, but did test Polynomial, Sigmoid and RBF kernels.
Results
The prediction accuracy results are shown in Figure 1, calculated using a 5-fold cross-validation on linear kernels:
Prediction modelAccuracyPrediction ModelAccuracy
Physician #1 Diagnosis97.65%Physician #1 Plans97.86%
Physician #2 Diagnosis97.94%Physician #2 Plans97.88%
Physician #3 Diagnosis97.51%Physician #3 Plans97.52%
Consolidated Diagnosis97.94%Consolidated Plans97.95%

Figure 1. Prediction Accuracy results
Conclusion
We conclude that it is feasible to predict diagnosis and care plan information learned from progress notes using the CompleteNote technology.


Monday, September 26, 2011

vistarpc4r Tutorial 3: Lists (part one)

So now we have a running system, we can configure some basic elements, and we can add providers and patients.  What's next?
Well, VistA has a ton of data already loaded for you, so let's check it out.

Most things(objects) in VistA have an internal and external representation.  Basically this means each object has an internal id and a value.  The internal id is generally a positive integer(often referred to as an IEN or IFN or DFN).  The value is generally a human readable string.
Lists are returned as an array of string.
Here are the first bunch with Ruby code:

Providers
array = broker.call_a("ORQPT PROVIDERS")
puts array[0]  # outputs providerIEN^providername  e.g. 42^ USER,PHYSICIAN


Locations
Clinics - Outpatient
array = broker.call_a("ORWU CLINCLOC", ["", "1"])
puts array[0]  # outputs locationIEN^locationname e.g. 15^CARDIOLOGY


Wards - Inpatient
array = broker.call_a("ORQPT WARDS")
puts array[0] # outputs locationIEN^locationname e.g. 2^MED/SURG


Patients - There are many ways to get lists of patients.  Some examples:
By Ward
array = broker.call_a("ORQPT WARD PATIENTS", [wardIEN])
puts array[0] # outputs patientIEN^patientname  e.g. 17^SMITH,BETTY


All Patients
array = broker.call_a("ORWPT LIST ALL", ["", "1"])

This call returns a preset number of patients out of the list.  You need to use this call in a loop where you call the RPC additional times using the last array entry from the previous call as the first argument until it returns an array of size 0.

You can also get lists of patient by provider, appointment dates, teams, and others.  Let me know if you need help finding the RPCs

Problems
Problems use a search approach.
array = broker.call_a("ORQQPL PROBLEM LEX SEARCH", ["hypertension", "100", "", "0"])

Argument 1 is the term you are looking for
Argument 2 is the maximum number of matches
Argument 3 is something to do with view...leaving it blank
Argument 4 is the date to use for determining when problems were valid in the VistA system.
puts array[0]  # problemIEN^problemname^codename^codeIEN^code source
# for example:  60339^Hypertension *^401.9^2477^ICD-9-CM


Up next...medication lists, procedure lists, and other order lists.



Sunday, September 11, 2011

vistarpc4r Tutorial 2: Users, Locations, Patients, Dates

This second tutorial continues where we left off in tutorial #1, and assumes you have an OpenVistA system setup on Ubuntu.  
Many of the VistA RPC calls you can make though vistarpc4r require either a patient, provider, location or date.  In some cases, all of them.  Most VistA flavors come with some sample patients, providers or locations, but if you are developing software to work with VistA, you probably need to create some of your own.  

However.....standard VistA does not include a RPC to create ANY of them.  There are a variety of reasons, many non-technical ones regarding politics surrounding Federal software development can be read at the Hardhats google group.  I prefer to think it is because the actual users of CPRS aren't the ones creating the patients, and user accounts, so no need, no build.  

But....I have at least one work around.

So first, users, or usually referred to as providers.

User creation
For user creation, it's terminal time(although I believe Astronaut has a user config tool)
I need super providers for my development sandbox.  By that I mean, they have the ability to do just about everything in the VistA GUI.  For me that means a provider that can sign orders containing narcotics.  
I prefer Fileman to create users so:

$ openvista open
OPEN> D P^DI               # start Fileman
Login as man,sys
Select Option 1:  Add/Edit Entries
Select the NEW PERSON file
Edit All Fields                   # which is painful, but you won't miss anything
Select NEW PERSON NAME  - type in your new users name in LAST,FIRST format
You will then start going through fields.  ? and ?? give good answers as to what is expected.  
But some key fields:
ACCESS:  basically your login name
VERIFY:   a password
KEYS:  PROVIDER, ORES    # these are necessary to sign orders
SECONDARY MENU OPTIONS:  OR CPRS GUI CHART
PRIMARY MENU OPTION:  RGWBMAIN
CPRS TAB: RPT
CPRS TAB: COR

AUTHORIZED TO WRITE MED ORDERS:  YES

DEA: 2 letters, followed by 7 numbers, but there is an algorithm
ELECTRONIC SIGNATURE CODE:  A string the user types in to verify its them.  like JSMITH

Once you create one, you can clone it!
Go into EVE, which is D ^ZU, instead of D P^DI
Select User management
Select Grant access by profile 
Use your existing user as a template, and create new users!
Don't forget to change for each user: Access, verifyDEA, Signature

Add Locations(no RPC for this either)
Adding a location is a similiar experience to adding your first user. In this case edit file 44, the location file. Fill out what makes sense. Again ? and ?? will show you fairly good help.

Add Patients
So I have a RPC for this, but I don't feel good about. VistA does not come with one out of the box, but the Astronaut folks have created one. For my purposes, I needed to be able to add a lot of patients in bulk(but very few providers and locations). So I jammed the Astronaut modification into my plain vanilla OpenVista.
KIDS is the name of VistA's patching capability. People can bundle up their code changes as KIDS builds and distribute them for people to patch their system. In this case, I grabbed the KIDS build out of the Astronaut source tree installed it.

Grab kids.ov.tar.gz from

From that archive, we need the 0.8-2/TMG1-1.0-2d.KIDS file. Make sure it is on the OpenVistA server.
From the archive, I followed the commands in the file 0.8-2/TMG1-1.0-2d.TOY.sh
First we load the new code into the instance:

$ openvista open
OPEN> S DUZ=1,DUZ(0)="@"
OPEN> D ^XPDIL
# enter the path and filename for the KIDS file
# answer YES
OPEN>  h  # to halt

Then we install the code so that it runs and is available
$ openvista open
OPEN> S DUZ=1,DUZ(0)="@"
OPEN> D ^XPDI
TMG1*1.0*2
NO
NO
OPEN> h

During this installation process, you WILL GET ERRORS.  Wierd, nasty looking errors.  That is the part I don't feel good about.  But the add patient RPC works!!!!  

To use:
broker.call_s("TMG ADD PATIENT", [ [ 
    ["\"COMBINED NAME\"", "Test,Patient"],
    ["\"DOB\"", "12/1/68"],
    ["\"SEX\"", "M"],
    ["\"SS_NUM\"", "000000000"]
    ]]
The RPC returns the DFN, or internal identifier(which is an integer), for this new patient. 

For bulk loading, our experience is that the RPC breaks after a number of consecutive calls.  It looks like a timing bug.  Surrounding the call with the usual BEGIN/RESCUE/END, and resetting the connection works. 

Fileman Dates
Lastly, most of the RPCs that require dates for their arguments need them in Fileman format. Fileman format means take your usual YYYYMMDD.HHMMSS format and subtract 17000000.  For example, 20110911.090123 would be entered as 3110911.090123

Well, that gives you some basic infrastructure.  Enjoy.
Up next will be reviewing some specific RPCs that give you lists of stuff.



Monday, September 5, 2011

vistarpc4r Tutorial 1: Setting up an OpenVistA instance and database sandbox

This is a tutorial to help you set up a Medsphere OpenVistA system that you can use to play with vistarpc4r, our gem that provides Ruby access to VistA.  It is a pretty barebones setup, just enough for our own product development.  
For our needs, we decided to rely on Amazon Web Services' EC2 stuff.  

1.  Create Amazon EC2 instance. We used AMI ami-ccf405a5, which is an plain vanilla Ubuntu install, but for Maverick Meerkat, since that seems to be the latest version of Ubuntu that Medsphere supports. You get a default user 'ubuntu'

2. Update APT and download the OpenVistA package - Follow the instructions at https://medsphere.org/docs/DOC-1722.
3. Add the user 'ubuntu' to the gtm and openvista groups
  1. $sudo adduser ubuntu gtm
  2. $sudo adduser ubuntu openvista
4. More or less follow the instructions from https://medsphere.org/docs/DOC-1511
  1. $ sudo ovinstanceadd open               # creates an OpenVistA instance in GT.M
  2. Download the OpenVistA MUMPS code and globals.  This is the code, written in MUMPS, that is VistA.  The globals are the initial data to populate the database, like ICD-9 codes, medications lists, and some sample patients and providers.  Get the code from https://medsphere.org/download/project/openvista-server
  3. Unzip the files you get from Medsphere(may need to install unzip with APT)
  4. sudo ovimport -r <directory containing routines> -g <directory>globals.zwr open # loads the code and data into your OpenVistA instance
  5. /opt should now contain some directories that have all of the code and globals
5. $openvista open # Fires up your instance

6. OPEN> D P^DI # Fires up Fileman, log in as man,sys

7. When you are done having fun with Fileman, enter "h" at the OPEN> prompt to halt back to the shell

8. $ /etc/init.d/openvista start             # start up the RPC Broker

Now you have a working instance of OpenVista.  You can point the CPRS or CIS GUI at this instance and see the sample data that Medsphere has loaded for you. 


Or, of course, you can point vistarpc4r at it!!!!!!

Next:  Tutorial 2:  How do you add users and patients with vistarpc4r?  

Monday, July 11, 2011

VA VistA Open Source Custodial Agent

The U.S. Department of Veterans Affairs has selected their open source Custodial Agent to develop and manage an open source community around their VistA electronic health record system.
The Information Applications Group, www.tiag.net, has been selected as the prime contractor. They have set up a provisional website at http://osehrca.org.

It will be interesting to watch this Custodial Agent be set up(or stood up in DC parlance).
It looks from the contract that it will be busy 60 days for tiag and the VA, with by-laws, licensing terms, code repository, website, community engagement plans, and certification function to all be set up in that time period.

Some interesting tidbits---
  • "VA believes that in order to efficiently maintain VistA’s high performance, it must make significant improvements to the component integration process, and that this would be best accomplished in an open source framework."
    You better believe it. That is why I developed the Ruby integration gem vistarpc4r. It isn't pretty under the hood. I plan on getting vistarpc4r to be some part of this process
  • "Organizations and commercial vendors can build proprietary products and technologies and have them certified"
    I can't wait to see how the certification process works.
  • "VA might initiate a project request to the CA for codebase refactoring"
    Good! Like I said, it isn't pretty under the hood.
  • "The contract shall be for a one (1) year base period of performance."
    What will the next one be for?
  • "...the Contractor shall provide, within forty-five (45) days after award, a draft Community Enablement Plan capturing the mission and objectives of the Custodial Agent including a statement of CA resources required. Concurrent with the activation of the Custodial Agent, the CA shall release draft plans to the open source community for comment."
    Hmmm...we went to a conference where I got to hear some comments about open sourcing VistA...should be entertaining.
  • "Performance metrics"
    Part of the performance evaluation for tiag is measuring source code contribution, code downloads, number of certification requests, and number of members. I'm glad to see these are included. Hopefully this information will be posted for all to see.
A open source custodial agent model is pretty innovative for the US government to embrace. I hope it works.

I'm also curious what this means for Medsphere's OpenVista, WorldVista and DSS's vxVista. Will their enhancements to FOIA VistA be contributed to CA VistA. Or will they switch from using FIOA VistA to CA VistA as their underlying source and keep their existing models.

Wednesday, June 29, 2011

Releasing vistarpc4r gem

Our new gem, vistarpc4r, is finally ready for other people to play with. It's pretty bare-bones, but it works.

vistarpc4r is a Ruby gem that provides RPC-style API calls to any of the VistA-variant servers that support the RPCBroker(of which they all do, unless disabled). VistA is the Veteran's Adminstration electronic health record system that it released to the public. We have tested vistarpc4r on Medsphere's OpenVista, but it should work on WorldVistA, vxVistA, and the others.

We developed this gem to support our own work developing our new product CompleteNote, which is a clinical decision support and documentation application.

This gem is free to download and use.

Feel free to bug me about additional functionality you would like to see, or contributions you would like to make.

The gem is available through rubygems.org: https://rubygems.org/gems/vistarpc4r

Installation
$ gem install vistarpc4r

Usage
VistA is an old-school stateful session server. It follows the standard RPC model of creating a tcp connection to a server, providing user credentials, and then calling named RPC functions with arguments, and receiving status and data responses in a synchronous manner.

vistarpc4r provides a ruby class called RPCBrokerConnection.
RPCBrokerConnection has 6 primary methods:
  • new(server, port, userid, password, debug) - string server, number port, string userid and password, and true or false to turn on debug statements(default = false)
  • connect - initiate the connection(addresses and usernames are passed in at object creation)
  • setContext('context') - In VistA, function calls are controlled by assigning them to contexts and giving the user access to that context. In most cases the desired context is 'OR CPRS GUI CHART'. There is a logical reason for that, but I won't get into it right now.
  • close - It wouldn't be a good RPC connection library without a close method
  • call_s('rpcname', [Ruby Array of arguments]) - Call a VistA RPC function with an array of arguments, expecting a single string value in return.
  • call_a('rpcname', [Ruby Array of arguments]) - Call a VistA RPC function with an array of arguments, expecting a Ruby Array of return values.
So, now what? What are the RPC functions I can call? That is the eternal question when it comes to VistA. There are hundreds, if not thousands, of RPC functions. While the VA decided to release VistA to the public, it didn't come with great documentation, or I should say, the source code is the documentation. Medsphere.org, hardhats.org and the VA site all offer clues.

I will publish my findings for good RPC functions as I am cruising the source code myself. The source code that offers the best insight is written in Delphi, MUMPS, Java and C#.

Example
Fortunately, Medsphere has created a public demo Openvista server that is always available(and resets its content in the middle of the night) Information about it is available here --> https://medsphere.org/docs/DOC-1003

But lets try this out...

Fire up irb or script/console or whatever your preference is...
broker = VistaRPC4r::RPCBrokerConnection.new('openvista.medsphere.org', 9201, 'PU1234', 'PU1234!!')
broker.connect
broker.setContext('OR CPRS GUI CHART')
wardsarray = broker.call_a("ORQPT WARDS")
wardsarray.each do |ward|
a = ward.split("^")
puts "Ward:" + a[1]
wardarray = broker.call_a("ORQPT WARD PATIENTS", [a[0]]) # ward ien
wardarray.each do |patient|
b = patient.split("^")
puts b[0] + ":" + b[1]
end
end


This example displays a list of wards and the names and internal ids of patients on those wards.
^ is used as a sort of field separator when multiple values are returned in the same string.

I have code in the examples directory in this gem that will give you other examples of fetching other data as well as writing and deleting data on the server.

Future features
  • Ruby classes for VistA data objects. Patients, Providers, Problems, Vitals, Orders, etc....
  • ActiveRecord interface for VistA. Won't be easy but seems doable from what I've seen.
  • Connection management. An obvious thing for us Railers is to incorporate VistA into a web application(I didn't need it yet). Given the stateful server and authentication model it isn't straightforward, but certainly doable.
Enjoy. Updates as I make progess.

Monday, June 27, 2011

First research publication

We had our very first research paper ever accepted for presentation and publication! The American Medical Informatics Association's Annual Symposium, held this October in Washington, DC. It is titled "Automated creation of clinical progress notes with machine learning", and details the results of our NIH Phase I SBIR research grant.

As the primary investigator and lead author, I get to hang out at a poster session for a while answering people's questions about the work.

After the conference, it will be published in the conference proceedings, and I'll make it available on the Blenderhouse website.

This research forms the basis for our clinical decision support and documentation product, CompleteNote.

Friday, May 13, 2011

Ruby RPCBroker interface for VA's VistA EMR

As part of our ongoing product development for our first healthcare software product CompleteNote, we have created a Ruby library which offer the ability to make API calls into the Veteran's Administrations electronic medical record system. The API in this case the RPC Broker mechanism that the existing GUI clients use. We have tested it with Medsphere's OpenVistA, and will be testing it with WorldVistA. Once it is ready, we will release it to the open source community as a gem.
It's pretty cool. We are able to use the power of Ruby to quickly pull data out of and push data into VistA.

Apple iOS is coming soon....

Healthcare direction

We were awarded a Small Business Innovation Research Grant from the NIH to conduct the principal research behind our first healthcare software product, CompleteNote!!
We were extremely pleased with our results, that being demonstrating the capability of replicating a physician's ability to diagnose and treat patients using our machine learning algorithms. Using actual clinical care notes as a source, we achieved a 97% prediction accuracy!

We have submitted our Phase II grant application to the NIH and hope to get good news at the end of summer.

More updates coming....