Clinical Decision Rules

From OpenEMR Project Wiki

MU Requirements

Clinical Decision Support

NIST Test 170.304(e)
(1) Implement rules. Implement automated, electronic clinical decision support rules (in addition to drug-drug and drug-allergy contraindication checking) based on the data elements included in: problem list; medication list; demographics; and laboratory test results.
(2) Notifications. Automatically and electronically generate and indicate in real-time, notifications and care suggestions based upon clinical decision support rules.

Patient Reminders

NIST Test 170.304(d)
Enable a user to electronically generate a patient reminder list for preventive or follow-up care according to patient preferences based on, at a minimum, the data elements included in: Problem list; Medication list; Medication allergy list; Demographics; Laboratory test results.

Summary for the Clinical Decision Rule Engine

Engine by Brady Miller, summary by Aron Racho

In clinical_rules.php, function test_rules_clinic() collects either all a provider's patients, a specific patient, or all the patients in the clinic, then iterates through each rule (from table clinical_rules) for each patients, checking whether or not the rule applies to that patient.

The way it does that is that it uses the function test_targets() is what retrieves the data in openemr tables/columns relevant to the rule being tested and the patient. It ends up checking table rule_target.value for the expression relating to the openemr table. For example:

   ::immunizations::immunization_id::eq::20::ge::1

This string appears to describe that the particular rule must look into the immunizations table for the given patient to see whether or not the rule applies.

test_rules_clinic() is used in places such as the patient reminders widget and the cqm report. The patient reminders widget (from the demographics page) uses test_rules_clinic() to determine, for the currently selected patient, which rules apply (eg. which patient needs a pap smear or new blood test today), and and persists reminders relating to these rules in table patient_reminders if they are not already persisted.

Similarly, cqm.php (the CQM report, available from the Admin -> Reports nav) uses test_rules_clinic to report on patients who need actions (eg. have triggered a rule) across the clinic.

In summary: studying the flow from update_reminders.php (which is called by the patient reminders widget) to test_rules_clinic will show you how reminders are persisted for patients. The CQM report (cqm.php) and the patient reminders widget will show you how persisted rule 'hits' per patient are consumed.

Projects Overview

Project 1:

  • CDR Activation Manager - Functional Spec for GUI w/ screen mock ups: (ownership: MI2) - Target Date: 12-29 Done
  • Code Dev and QA: (ownership: EnSofttek/MI2)
  • CODE SUBMITTED TO ARON FOR INTEGRATION With Project 4 ON 1/24/2011:

Project 2:

Project 3:

Project 4: Build a fully functional admin gui that allows making/editing new rules, filters, targets, actions.

  • Research and document specifics on how the list_options items are used by the CDR Engine: (ownership: EnSofttek/MI2) Target: 12/31
  • Rules Engine Admin GUI Functional Spec w/ screen mock ups: (ownership: MI2) - Complete Date: 01/15/2011
    • Development of GUI - (ownership: MI2/Aron:) - Target Date: 02-01-2011, ready to start QA 2/16
    • GUI QA and Bug Fixes - (ownership: Ensoftek:) - Target to start 2/17

Project 5: Get the email,SMS and voice reminder code to work.

Project 6: PQRI XML Output Reports Clinical Quality Measures

  • PQRI XML Output for CQM (ownership: Ensoftek/MI2)
  • Database schema extended to support pqri codes and measure groups. CQM reports output format extended. Admnin->Globals section extended to add the 'PQRI Registries' tab.
  • PQRI 2009 XML being generated with the available data. Still need date-range(a must) and meaure-group-stats(not sure if this is a must).

Project 7: (ownership: bradymiller) Get the Automated Measure Calculations functional. The skeleton rules and report are entered in, but not functional. Will likely need to incorporate a date range (rather than a target range) for this feature. Then will simply be a matter of working out the rules.

Project 8: (ownership: bradymiller) Get the Clinical Quality Measures functional. The skeleton rules and report are entered in, but not functional. These are all rather complicated rule sets for each quality measure, so will likely require some customized functions (called by rule engine) to deal with some of these (to avoid overburdening the core rules engines with a bunch of confusing implementations).

Overall QA and Testing (ownership: Ensoftek/MI2) CDR Project QA/Testing - Track results and issues on this page

Distributed Development Guideline

[Brady] will maintain the official github branch for this code (I know you guys are functioning as the project managers of this module, but better to let me manage the repo, since it's now easy for me, and can then avoid wasting your billable hours on this) at http://github.com/bradymiller/openemr/commits/rules_develop. As the 'master' and 'rel-320' are, this branch should also be treated as a sacred branch (ie. you should do all development in branches derived from this and only update it by pulling the branch from my repository).

So, to set up this branch in your local repo do following:

   git remote add brady git://github.com/bradymiller/openemr.git
   git fetch brady
   git checkout brady/rules_develop (you get a long sort of warning message)
   git checkout -b rules_develop (you now have a local rules_develop branch)
   git push github rules_develop (you now have a published rules_develop branch; not needed but helps if have any problems in the future)

Keep your local rules_develop updated by frequently pulling from the official rules_develop branch on my repo:

   git checkout rules_develop
   git pull brady rules_develop

Treat the official rules_develop branch and your local rules_develop branch as sacred branches(like the 'master' and 'rel-320' branches). So, develop CDR module code in branches derived from your local rules_develop branch, but don't ever add to or modify your local rules_develop branch (ie. as above, only update your local rules_develop branch from the official branch). When ready to add to the official rules_develop branch then publish it on github in another branch and ask me to commit it to the official rules_develop branch on my repo. Then you'll pull your code into your local repo by updating from the official repo. I hope this makes sense. Following this will avoid any merging/conflict issues of developers collaborating on the CDR module (and will keep the history relatively clean for when we're ready to merge this code into the sourceforge codebase). Also, this will allow us to easily keep the code updated (merge in 'master') when needed in a controlled manner (ie. I'll merge in master into the official rules_develop branch, and then you'll get the merge by updating your local branch from this).

Here is a updated listing of the commits on the official rules_develop branch.

Notes and Issues

Please add your issues, comments and suggestions and rember to use the 'signature' tag to sign and date the entry.

1. Permissions levels for each part of the process need to be clearly defined --Tony - www.mi-squared.com 00:26, 30 December 2010 (UTC)
Agreed, need to ensure basic acl's are set up (for now, only people that are allowed to see clinical stuff on patient should be able to see these widgets in the patient sumamry screen. --Bradymiller 19:12, 31 December 2010 (UTC)
2. Patient Reminders work list may be better in Miscellaneous than administration. It is similar in function to 'BatchCom' for patient communications. --Tony - www.mi-squared.com 00:26, 30 December 2010 (UTC)
After all the pieces and links are in place, then would start thinking about the best place to put them. --Bradymiller 19:12, 31 December 2010 (UTC)
3. On patient summary/demographic.php the patient reminders and clinical reminders widgets contain the nearly same information in different sort orders. Is in necessary to have two widgets for reminders or would we be better with one that indicates the difference between the two or combines information? --Tony - www.mi-squared.com 00:44, 30 December 2010 (UTC)
Yes, it is necessary, because they do different things. The clinical reminders widget is for real time indicators (and activated by the active_alert_flag in clinical_rules mysql table) (very high utility for a clinical encounter, which is why at the top right). The patient reminders widget is for sending/tracking reminders to the patient (and activated by the patient_reminder_flag in clinical_rules mysql table). The same clinical_rules entry can be activated to do both (which is now set for most during development) but in real life, many of the rules will be set for only as a real time indicator or as a patient reminder; and these mechanisms will be even more powerful when the per patient customization gui's are set up. In the end, the clinical reminders widget (real time indicators) edit/list button screen will also be the perfect place to put plan (ie. diabetes, HTN, ..) stuff (but don't want to get to far ahead of ourselves). --Bradymiller 19:12, 31 December 2010 (UTC)
4. What is the difference between a rule target and a rule filter? As far as I can tell, they are both involved in determining whether or not a rule applies to a patient; it is not clear to me from the code. Please help us understand the difference, as I believe the admin gui utility for configuring the rules engine may have to mess with these.--Aron Racho 22:58, 3 January 2011 (UTC)
The flow of the rule engine is as follows. Lets say were looking at patient 'Bill'. We look at the first rule 'rule_A'. In 'rule_A' we first grab the associated filter set (note only one filter set per rule, for now) and test the filter set to patient 'Bill'. If Bill passes the filter set (he is now part of the group being tested), he then moves on to the next test (the target). So, we now grab the associated target set(s) for the rule 'rule_A' (note there is a mechanism for multiple target sets per rule), and test them to the patient 'Bill'. If 'Bill' does not pass the target set, then the action (associated with failed target set from 'rule_A') happens (or in the case of cqm, it is used in the calculation). To get further differentiation of filters vs targets, check out the functions test_filters() and test_targets(); note how many more features are required to be dealt with in test_filters() than test_targets().--Bradymiller 08:08, 4 January 2011 (UTC)
  • The flow is not the actual question: What is a Target? and What is a Filter?. How do they differ to the USER? We are trying to create a UI that users can understand and configure, so we need clear definition of the terms themselves and how they are applied. The flow in the code itself is fairly obvious, and not the issue at hand. --Tony - www.mi-squared.com 18:40, 5 January 2011 (UTC)
  • The filter is to select the population that you want to run the test (ie. check for the target) on. For example, lets use a pap smear. The filter would be for women only over a certain age. The target is the pap smear itself. This is important, because the filter defines the population of patients that are pertinent to the rule (this is used as denominator in cqm rules and in the future to auto-report results in the clinical reminder widget even if the target is true (ie. show the hgba1c result even if it is up to date)). I hope this helps.--Bradymiller 18:55, 5 January 2011 (UTC)
5. We are proposing that the rule admin GUI will allow you to define, per rule, where the source of the filtering criteria. For example, rule_dm_bp_control_cqm wants to source its targets from form_vitals, bps and bpd, etc. columns. We want to present an human language 'nice title' for things like form_vitals (which really can be any developer form table, or other source such as CUSTOM:act_cat_assess). There doesn't appear to be a linkage from the rules_target or rules_filter table to any such table that could provide this friendlier name. Any suggestions on how we surface this friendlier name?--Aron Racho 00:49, 4 January 2011 (UTC)
Several things here. First, the actions categories (ie. act_cat_assess) do have list_options lists; for example act_act_assess is Assessment. And CUSTOM basically means the data is stored in the 'rule_patient_data' table, which in actuality is simply a garbage bin to hold data points that do not yet exist within the OpenEMR; as procedures and other openemr code is developed more for MU, less and less things will be stored in this table; nonetheless it will still always be an important mechanism that will add another nice option for customization. For example, lets say I want to track yearly fingernail length in some weirdo clinic; they could simply create the rule in the clinical rule admin GUI, use the CUSTOM method, and not need to worry about creating a sql data container or form for this information. On to the more pressing question; how to create user friendly constants (and translations) for stuff such as bps form_vitals etc. This is actual gonna be quite simple, since the actual number of terms that are used is not that big, and can be added to as more places in the database are used. Basically a simple list_options list(s) will suffice and can be done as building the admin gui.--Bradymiller 08:22, 4 January 2011 (UTC)
6. I'm trying to understand what the purpose is of group_id in rule_target. From inspecting the code, I gathered that you were using group_id to pick up rule_target(s) associated with a given rule (from clinical_rules) to test against a given patient. I interpreted this to mean that any given rule has multiple targets. Is this correct?
From brady: This is done when a rule has more than one action associated with it. So, in the rule_wt_assess_couns_child, there are two separate actions (Weight and Education;so will create two separate entries in the clinical widget and two separate rows in the CQM report). However the rule_htn_bp_measure is only linked to one action (ie. Blood Pressure). As an aside, in the future there will be a potential group_id instituted in the rule_filter table to allow separate filters per rule (since may be needed for some of the more complicated CQM rules).
7. How do we handle foreign key relationships such as the one in:
    ::immunizations::immunization_id::eq::30::ge::1
The column immunization_id is actually a foreign key to a list options entry. The value must be looked up somewhere else. Can we make the assumption that if the column is *_id (eg ends in _id), we can try to look up the appropriate value in the list_options table? Because obviously we can't simply indicate on the gui that 'immunization_id' must be 30! It should be 'Influenza 1'.
From brady: This is gonna require table/method specific operations (note many of these types of mechanisms are built into the rules engine already; such as procedures, where to get pid, date etc.). While building the gui, I'd rec. just focusing on the raw data, and can then further customize mechanism as needed as the examples require. Note, this was basically the strategy in building the rules engine (ie. started with simple rules and the engine then underwent changes, sometimes drastic, as more rules sets were added). My guess is that you'll rely on raw data for most (such as form_vitals stuff), and then will catch and put other things, such as immunizations through a different if/case statement (could even put into a function to further abstract it like the interval,date,patient_id functions). Once you have the raw mechanism in place, these further customizations shouldn't be that difficult (ie. icing on the cake).
8. CQM/PQRI reports require the PQRI Measure #, however there are several reports that only have NQF #. Is is safe to assume we use the PQRI # in preference and NQF if it does not exist? --Tony - www.mi-squared.com 18:16, 25 January 2011 (UTC)
I don't know. Somebody should research this. A safe option for us would be to also create a column in clinical_rules to hold the PQRI number also. --Bradymiller 02:04, 26 January 2011 (UTC)
  • There is only one XML tag, so we can't use both elements, the specs say the PQRI #, they don't mention NQF numbers at all. --Tony - www.mi-squared.com 05:53, 27 January 2011 (UTC)
  • I'm not saying to send both via xml; just saying we could easily store both in the clinical_rules table by adding a PQRI column. Then we'll be flexible for whatever requirement is needed in the future. --Bradymiller 09:08, 27 January 2011 (UTC)
  • Added a commit that allows inclusion of the PQRI in the clinical_rules table, and updated the current CQM rules with the applicable numbers. This was straighforward, so put it in the rules_develop official branch: http://github.com/bradymiller/openemr/commit/6057eb0335fa2d29ccf3162479af1f0473db3bd9 --Bradymiller 09:34, 3 February 2011 (UTC)
9. Should we log the fact that a report PQRI has been submitted somewhere in the system? Seems like a relevant audit step since incentive money is dependent on this action. --Tony - www.mi-squared.com 18:16, 25 January 2011 (UTC)
Sounds like a good idea. Could run it through the log engine (ie. using same function that records login, logout, etc.). --Bradymiller 02:06, 26 January 2011 (UTC)
10 One element of the requirements is "care suggestions based upon clinical decision support rules". We don't seem have any structures in place for that. Or the data to feed it with, thoughts. --Tony - www.mi-squared.com 05:53, 27 January 2011 (UTC)
Please provide a quick example (Wouldn't a indicator to remind the physician to check a blood pressure, weight, INR, diabetes care, etc. all fall under this? These are the "actions".). --Bradymiller 09:11, 27 January 2011 (UTC)
  • There are no examples that I can find, you may be right, I'm not a doctor so I can't be the judge of that. This partial sentence "...and care suggestions based on the clinical decision support rules" is the only reference to this in the test procedure. --Tony - www.mi-squared.com 23:07, 27 January 2011 (UTC)
  • I think we're good. --Bradymiller 08:57, 28 January 2011 (UTC)
11. CQM/PQRI reports: Some high level thougths on the database schema extension to support this: --Rammohan 21:32, 30 January 2011 (UTC)
  • We'll need a new table for the “registry”.
  • What columns/data do we need to store in the "registry" table? --Bradymiller 11:38, 1 February 2011 (UTC)
  • registry-name, registry-id, submission-method--Rammohan 13:02, 1 February 2011 (UTC)
  • Another simply option is putting this in Adminsitration->Globals for now.
  • Let's do that now and we can adjust if needed later. --Tony - www.mi-squared.com 22:39, 3 February 2011 (UTC)
  • Seems like some of the “measure groups” are already being captured in the ‘clinical_rules’ table. The table may need to be extended to capture the “id” of the measure groups(such as (A = Diabetes Mellitis)
  • What is a "measure group"? --Bradymiller 11:38, 1 February 2011 (UTC)
  • Please see the Wiki at http://www.openmedsoftware.org/wiki/PQRI_XML_Output_for_CQM for some information about the measure groups. Also, checkout the sample XML.--Rammohan 13:02, 1 February 2011 (UTC)
  • Thanks for the link. Can add this column to the clinical_rules table along with above PQRI measure id number column (I'll plan to do this when I have time to start working on the cqm rules).
  • Seems like the 'measure-group' section is more involved than I figured. So, there are 7 measure-groups and each measure group could have multiple 'pqri-measure' sections. Each pqri-measure has a unique 'pqri-measure-number'. The XML to be generated has to drill-down to the individual pqri-measure. Also, if there are multiple providers, this information has to be gathered per provider. So, in essence: "For Each 'Measure-Group', For Each Provider(in the measure group), Get data per pqri-measure". YIKES. I've attached a PDF I found at http://www.openmedsoftware.org/wiki/File:PQRI_Simplified_2009.pdf It has a very detailed explanation of PQRI 2009. Of interest are pages 8-10.--Rammohan 18:36, 2 February 2011 (UTC)
  • I think this can be dealt with by adding a clinical_plans table and modifying the test_rules_clinic a bit. I'll play around with this and see if I can get what we need. To help me clarify, a measure groups is simply a collection of rules (ie. a plan), and it is not a group of physicians, correct? --Bradymiller 09:38, 3 February 2011 (UTC)
  • Yes. That's how I understand it.--Rammohan 13:15, 3 February 2011 (UTC)
  • I'm beginning to think the people writing these policies have no clue what their asking. The problem is majority of the CQM core measures don't have a corresponding PQRI (and hence don't belong to a measure group). So, how exactly can they even be sent via the PQRI method if they do not belonging to a measure group. Do you think the CQM report and the PQRI send should be showing different data and calculations (would be nice if a head to head analysis was done on what the NIST CQM calculations are asking for and whether these are even the same as the calculations asked by PQRI. --Bradymiller 13:21, 3 February 2011 (UTC)
  • Agreed. Very confusing. Wonder if PQRI and NQF codes can be used interchangeably ?--Rammohan 22:20, 3 February 2011 (UTC)
  • I think so, in one explanation I read they used "NQF 034" as the PQRI #. --Tony - www.mi-squared.com 22:35, 3 February 2011 (UTC)
  • My confusion lies in the measure groups, though. Only several of the CQM core rules are mapped to a measure group. Hence, if you send a PQRI report by measure group, most of the core rules won't even be included in the report. --Bradymiller 22:56, 3 February 2011 (UTC)
  • Page 9 of the 'PQRI_Simplified_2009.pdf' file says: "PrimaryData recommends selecting a PQRI Measure Group that best meets the needs of your practice,patients and physicians." I'm wondering if this means that the physician/practice makes the mapping(CQM core rules to measure groups).--Rammohan 03:52, 4 February 2011 (UTC)

Effected Code, Tables, etc

In addition to meeting the MU requirements here, we also take into consideration of the CMS Quality Reporting MU requirements.

Owner and Status

Consortium of: Brady Miller, Medical Information Integration, LLC and EnSoftek, LLC Brady has been working on the low level design MI2 and Ensoftek launch collaborative development starting 12/11/2010.

  • Original design and work done as of 2/4/2010: was rejected as not robust enough

Links