CCHIT - Clinical Decision Support

bradymiller wrote on Tuesday, December 22, 2009:

cool.

Just continue to keep us in the loop. This stuff is pretty exciting and will have a relatively large impact on patient care(compared to the other MU’s). Also, don’t feel inclined to follow my recs; I’m just thinking out loud and am a relative novice in mysql. I’ll be especially interested in what your DBA’s thoughts are when you start coding.

-brady

sunsetsystems wrote on Wednesday, December 23, 2009:

Thomas, regarding messages, the “Patient Notes and Authorizations” panel appears on login and also when you select that item (Miscellaneous menu).  It is intended to be the “messages box” that you describe.  Of course I’m sure there are better ways to implement it, and I believe the interface refactoring project is already doing something about that.

Rod 
(http://www.sunsetsystems.com/)

anonymous wrote on Wednesday, December 23, 2009:

Hi Brady,

Here’s the feedback from our DBA based on his initial assessment:

"What Brady suggested is workable. But it has 1 basic limitation:
It will apply for all patients that matches the assigned criteria. If some or any particular patient(s) does not require/allow for the rule, then the structure needs to be there to disable it selectively.

Brady is right in saying that once the structure & algorithm is in place, the popup is easy as it only serves to display the message while the algorithm take cares of the logic.

I think it is complex as the algorithm needs to match up a few criteria:
1. rules
2. plan
3. group assignment
4. patients
5. frequency

I still have no idea how to tide the 5 together. I think this is more on code logic. Once the algorithm is figured out, the database structure can be build to match."

He will work on it some more.

anonymous wrote on Wednesday, December 23, 2009:

Hi Rod,

I have seen the new GUI as well. It’s the same Miscellaneous item. Can I propose to have it renamed to Messages and moved to a high position in the menu tree?

- Calendar
- Messages
- Patient/Client
- Fees
- Administration
- Reports
- Miscellaneous
 
__

The reason is that it will become more important and frequently used as we link it up with decision support, lab, and other MU items.

sunsetsystems wrote on Wednesday, December 23, 2009:

Yes I think the navigation area will need some rearranging, for various reasons.

Rod 
(http://www.sunsetsystems.com/)

bradymiller wrote on Wednesday, December 23, 2009:

Thomas,

Regarding the per-patient granularity of rules, I’ve been thinking about that also recently. My proposal would be to keep this information in a new column (clinical\_reminders) in the patient\_data table. This is where could keep list of categories/sub-categories to include/exclude on a per patient level. Implicitly, seems would be easiest to include every patient in the ‘preventative health’ category. If wanted to remove all preventative health then would have something like below:

    !preventative health

But if want to just remove paps (ie. women has had complete hysterectomy), then would have something like below

    !preventative health:womens health:pap

If she’s diabetic and this is set, then the field could look like:

    !preventative health:womens health:pap:::diabetes

If we don’t want to do yearly feet exams for the diabetes, then it would look something like

    !preventative health:womens health:pap:::diseases:diabetes:::!diseases:diabetes:podiatry

I’m not sure of the best syntax to use to delimit this information, above are just examples.

The logic would then proceed as follows if filtering a specific patient:

1. Query the patient\_data table to collect the info in the clinical\_reminders column.
2. March through the reminder_categories table (using data from 1 to filter which ones are applicable to patient). If one is applicable, then:
3. Follow to the rule(where ‘name\_reminder’ is same as ‘name’ in clinical\_reminder)
4. If rule is globally set to active, then collect entry in ‘rules’ column:
5. If ‘rules’ is true, then you have a hit. Then it will be displayed/outputted sythesizing info from applicable clinical\_reminder\_map table entries and the frequency setting in the rule.

I think it would be best to stay away from mapping via id numbers, and instead use the string identifier of the rule. So, every rule name would need to be unique (UNIQUE KEY?).

The key algorithms are likely gonna be setting and dealing with the information contained in the ‘rules’ column (where would have filtering for age, sex, and disease) and the information contained in the clinical\_reminder’s column in the patient\_data table.

-brady

bradymiller wrote on Wednesday, December 23, 2009:

hey,

It just hit me that using above mechanisms (clinical\_reminder column in patient\_data and using the string identifier of the rule for mapping), can markedly simplify my approach:

database structure (give exmples in quotes, 1st is flu shot for diabetes and 2nd is smoking cessation):
<pre><code>
clinical_reminder {
id (note this is not used for mapping)
category (‘disease’)(‘preventative health’)
sub_category (‘diabetes’)(‘smoking’)
name (‘flu shot’) (‘smoking cessation’) used for mapping
active (‘1’) (‘1’)
sex_filter(’’)(’’)
age_low_filter(’’)(’’)
age_high_filter(’’)(’’)
map_filter(’’)(‘history_patient::smoking_current::YES’)
frequency (‘12’)(‘12’)
age (’’)(’’)
}

clinical_reminder_map {
id (this is not used for mapping)
name_reminder (‘flu shot’)(‘smoking cessation’) (name from clinical_reminder table)
id_patient (id from patient_data table)(id from patient_data table)
date (timestamp here) (timestamp here)
result (’’)(‘told patient to quit, he laughed at me’)
}
</code></pre>

This way can avoid the ‘rules’ algorithm, and the filtering (age and sex) can be done in the sql-query. Data in the clinical\_reminder\_map will also stay discrete since mapping to the string identifier of the rule. So the only heavy algorithm would be in reading and setting the patient\_data table clinical\_reminder column.

-brady

bradymiller wrote on Wednesday, December 23, 2009:

Sorry about the above formatting, here’s another try at the database structure in above message:
<pre><code>clinical_reminder {
id (note this is not used for mapping)
category (‘disease’)(‘preventative health’)
sub_category (‘diabetes’)(‘smoking’)
name (‘flu shot’) (‘smoking cessation’) used for mapping
active (‘1’) (‘1’)
sex_filter(’’)(’’)
age_low_filter(’’)(’’)
age_high_filter(’’)(’’)
map_filter(’’)(‘history_patient::smoking_current::YES’)
frequency (‘12’)(‘12’)
age (’’)(’’)
link (lcoation to default popup)(location to smoking cessation popup)
}</code></pre>
<pre><code>clinical_reminder_map {
id (this is not used for mapping)
name_reminder (‘flu shot’)(‘smoking cessation’) (name from clinical_reminder table)
id_patient (id from patient_data table)(id from patient_data table)
date (timestamp here) (timestamp here)
result (’’)(‘told patient to quit, he laughed at me’)
}</code></pre>

-brady

tmccormi wrote on Thursday, December 24, 2009:

We have not addressed the navigation menu on purpose in the prototype.  Ideally that should be somewhat configurable by the end user and otherwise very context sensitive.

I guess it’s time to post some screen shots at least, since we’ve been outed on the UI design effort  :slight_smile:

Tony

anonymous wrote on Tuesday, December 29, 2009:

Hi Brady,

One of the things we really like about your approach is the use of column fields  to cut down the number of tables.

(‘historypatient::smokingcurrent::YES’)

Another thing we like is the use of popup link.

We will apply both.

After much analysis and benchmarking, we came up with 5 tables.

See

They are different from yours because of the following considerations:

> A patient reminder will be based on a plan action. For each health plan, a patient can have multiple goals and actions.

> There are a number of requirements for sending a patient reminder. So we thought that it’s best to separate it from the health plan fields.

> We also take CMS Quality Reporting into consideration. See the MU requirements .

Please review and see if they make sense.

  : http://www.openmedsoftware.org/mw/images/f/f3/Proposed_CDR_Tables.pdf
  : http://www.openmedsoftware.org/wiki/CMS_Quality_Reporting

bradymiller wrote on Wednesday, December 30, 2009:

hey,

Seems a bit overly complicated (redundant and inflexible) to start with, why not do this in pieces?

Confused on your naming. for your flu shot shouldn’t it be category->health maintenance sub-category->vaccinations plan_name->flu shot. Why map with the id? Why not use the name to avoid problems when users customize stuff and to data is discrete (ie. there will also be a flu shot for diabetes).

Also, why hard-code all of the possible code columns? (what happens if user wnats to use a SNOMED code) When not just make a ‘code’ column and put them all there (cpt:??? icd:???) etc…

Also question all the patient_history and lab_abnormal columns? Can’t this simply be added later after you get the basics working (at that point another mechanism may make more sense).

Also, where are the target frequency or age columns in this table?

I’m also confused why patient’s need to enroll in plans, if your gonna have all the inclusions/exclusions, then might as well make every rule pertinent to every patient. As a physician, we shouldn’t need to to enroll patients (should be automatic via database data, icd9 codes etc.)

Also seems better to focus on the rules portion before creating the reminder/messages part. With a good rules database structure and simple algorithm you can spit out the reminders in real-time (in the patient summary screen) and have a real-time mechanism to deal with them. You can then take advantage of this algorithm in your message/reminder stuff.

My suggestion would be to focus on simply getting the rules and real time reminder algorithm to work and then move on to the other stuff.

-brady

anonymous wrote on Wednesday, December 30, 2009:

Seems a bit overly complicated (redundant and inflexible) to start with, why not do this in pieces?

> Basically, we are addressing CDR as one integrated module so that we can take care of the relationships between different parts. We have worked with much bigger systems, so this is not complicated at all. We are breaking down the module into different pieces of work.

Confused on your naming. for your flu shot shouldn’t it be category->health maintenance sub-category->vaccinations plan_name->flu shot.

> We are using your suggestion in clinicalreminder table. The items highlighted in blue are the same examples as yours.

Why map with the id? Why not use the name to avoid problems when users customize stuff and to data is discrete (ie. there will also be a flu shot for diabetes).

> There are a number of reasons. For patients, we know that the mapping cannot be done using patient names. Some tables don’t have names. So the first reason is to be consistent in our mapping. From a database perspective, the smaller the key, the better the efficiency. That’s the second reason.

Also, why hard-code all of the possible code columns? (what happens if user wnats to use a SNOMED code) When not just make a ‘code’ column and put them all there (cpt:??? icd:???) etc…

> The reason is that there will be multiple entries in each code column. If we attempt to mix the 5 different code fields (together with their multiple entries), it will be much harder to manage.

Also question all the patienthistory and lababnormal columns? Can’t this simply be added later after you get the basics working (at that point another mechanism may make more sense).

> Patient history is where Smoking Cessation comes in. So we are addressing it here. It’s the same idea as yours. As for lababnormal, this is included because we are also working on Lab Test Results. Obviously, it can be separated too. It’s included because we are looking at the work as an integrated module. This helps us avoid missing critical components. We won’t and can’t code everything at the same time.

Also, where are the target frequency or age columns in this table?
> The target frequency is not needed because each reminder is for a specific plan action. So the frequency is built into the action. A plan without an action doesn’t do any good. As for the age columns, see age_from and age_to. We like to match table field names with the corresponding GUI labels. They can be renamed.

I’m also confused why patient’s need to enroll in plans, if your gonna have all the inclusions/exclusions, then might as well make every rule pertinent to every patient. As a physician, we shouldn’t need to to enroll patients (should be automatic via database data, icd9 codes etc.)

> I think the patient has a right to accept or refuse a plan. So yes, the system can default every patient to a number of health plans. But each patient can opt out due to a number of reasons. There will always be exceptions.

Also seems better to focus on the rules portion before creating the reminder/messages part. With a good rules database structure and simple algorithm you can spit out the reminders in real-time (in the patient summary screen) and have a real-time mechanism to deal with them. You can then take advantage of this algorithm in your message/reminder stuff.

> We are addressing CDR as an integrated module but will work on the different parts according to their priorities. In this case, we will start coding for the rules first.

bradymiller wrote on Wednesday, December 30, 2009:

hey,

Are you able to be more specific with what systems you have worked with? From that, I could gather more of an idea of where your going with this.

My input on the physicians reminder box is that it should not be static (ie. read from a reminder table, so would only see items that have been cronned to the table). The best thing for us to see is every single health item that is pertinent to the patient, with it’s status(completed/due date)/results and easy link to page that can deal with the issue (this is what I mean by real-time). Just seems like if you had this working then there would be no need for a reminders table (ie. your daily script could print the letters to patients and send the inter-clinic notes leveraging the real-time algorithm)

Again, just seems a bit complicated…   I’ll wait for the code, then I’ll have a better idea where your going with this.

-brady

sunsetsystems wrote on Wednesday, December 30, 2009:

Lots to digest here.  Thomas I’d like to see your table structures but openmedsoftware.org seems to be down right now.  Could you email that pdf to me?

Rod 
(http://www.sunsetsystems.com/)

anonymous wrote on Saturday, January 09, 2010:

The coding work for Health Plans has been completed for the Administrator section. It’s not fully functional because coding for patient reminders is still in progress. The Include and Exclude rules can only use ICD-9 and CPT-4 codes at this time. We will add NDC sample codes (for medication) and Patient History/Lifestyle (e.g. Tobacco Use) soon.

Please review the codes posted in the tracker. You can also try use it at www.medbloom.com. Use “test1” as both the username and password.

bradymiller wrote on Saturday, January 09, 2010:

hey,

Here’s my review of health plan code. Overall, coding looks really good. Note I didn’t really test it much (used your site demo some); this is mostly just review from reading through your code.

interface/main/left_nav.php
**Internaionalize word ‘Letter’

interface/patient_file/health_plan/health_plan_admin.php
***Get rid of ffescape(). Your correctly using formdata.inc.php instead.
***use the sex list from admin->list, and make empty item set to Both.
***Also seems like should have “empty” options for age filters. So if field is empty the filter is turned off.
***Try to make the number of free text input boxes as small as possible (ie. easier to maintain data and internationalize if chosen from lists) (example is day inputs in the action plans, and the action items themselves, Patient History, Lab Abnormal Result))
***What about plans that happen as certain age once. For example a 15 month MMR vaccination
***Why is the frequency in the plan (which can consist of multiple action. ie. diabetes getting a1c, eye exam; doesn’t frequency need to be associated with each action item?)
***In includes/excludes would be nice to have a database mapping entry (ie. I can select places anywhere in database(not free text, but real-time database walk-through), and if data is set to something it would flag, this would be optimal for things like AD and smoking status reminder, and would be flexible to allow doing almost anything the user needs)
***Make reminder/followup method a list in admin->lists (more generic name like contact methods or something)
***would be better to standardize all patient age and frequency to smaller increments such as months (storage in database) to allow more detailed plans in future (chemotherapy protocols etc.) just thinking out loud

interface/patient_file/health_plan/manage_categories.php
***Get rid of ffescape(). Your correctly using formdata.inc.php instead.
***I’m still not clear what purpose these categorization categories fulfill, will wait and see.

For database scripts:
Add stuff to database.sql
In the upgrade sql script add to sql/3_2_0-to-3_3_0_upgrade-messages.sql
****Place the health_plan_categories rows insertions within the IfNotTable health_plan_categories entry

-brady

bradymiller wrote on Saturday, January 09, 2010:

hey, error in above add upgrade sql stuff to:
3_2_0-to-3_3_0_upgrade.sql

sunsetsystems wrote on Sunday, January 10, 2010:

Looks nice.  First, a couple of comments on the administration GUI.

Combining the list of existing plans in the same page with the add/edit form seems a bit unwieldy.  Not a biggie, and yeah I know other places in OpenEMR do that, but they are unwieldy too.  :slight_smile:

Nobody’s going to like a simple list box for selecting from the thousands of CPT or ICD codes.  See interface/patient_file/encounter/find_code_popup.php as an existing tool for selecting one or more codes from the list, and click Diagnosis in the Add/Edit Issue form to see it in action.  Didn’t I mention this earlier?

Code comments to follow.

Rod
www.sunsetsystems.com

sunsetsystems wrote on Sunday, January 10, 2010:

Regarding table definitions, don’t use DEFAULT NULL without a good reason.  Null fields require special handling in some types of queries.  Where possible, default to an empty string or a 0 numeric value.  A null date can be useful to indicate no date has been entered.

In health_plan_admin.php:

Why the unset() statements near the top?

Don’t be stingy with spaces before and after operators; write “count($icd\_include) > 0”, not “count($icd\_include)>0”.  Readability of PHP code is more important than saving a few characters.

There are virtually no comments in this code.  Makes it hard to follow, and hard for me to evaluate.  Be kind to yourself and others - put in explanations of what’s going on.

Try to use meaningful variable/function names.  What is $icd_include_temp?

This line needs the quote escaped:

      $alertmsg = xl(‘Cannot delete this entry because it’s being used!’);

You seem to be defining an awful lot of top-level variables.  Perhaps some arrays or objects could be useful?

Rod
www.sunsetsystems.com

sunsetsystems wrote on Sunday, January 10, 2010:

Regarding manage_categories.php:

I see where you got this code from, but perhaps a better model would be a tree view, since the categories are hierarchical.

Rod
www.sunsetsystems.com