Personal tools

Clinical Decision Rules

From OpenEMR Project Wiki

Jump to: navigation, search


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:


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)

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
    • GUI QA and Bug Fixes - (ownership: Ensoftek:) - QA done 3/5, fixing cycle started

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)
  • Fully supporting Reporting Method A and partially supporting Reporting Method E. Will likely turn off Method E option for production as long as not necessary for NIST.

Project 7 and 8: Build the Clinical Quality Measures and Automated Measure Calculations. Because these are complicated and need to remain robust, these will be hard-coded into the codebase (unlike the standard rules, which are in the database). The class that will hold these rulesets is here: library/classes/rulesets/ruleSet.class.php . Note that a skeleton function has been created for each required rule in this class. For example, the "Hypertension: Blood Pressure Measurement (NQF 0013)" can be found at the rule_htn_bp_measure_cqm() function within this class. This mechanism will allow multiple developers to build these rules simultaneously without breaking the core CDR engine. For developers. to test your rule sets use the report at Reports->Clinic->Quality Measures(Select Rule Set->'Official Clinical Quality Measures (CQM) Rules' and then click 'Submit'). Here is the commit that added this functionality (in official rules_develop branch):

a. Hypertension: Blood Pressure Measurement (NQF 0013) DONE
  • rule_htn_bp_measure_cqm(); DONE
b. Tobacco Use Assessment (NQF 0028a)
  • rule_tob_use_assess_cqm();
c. Tobacco Cessation Intervention (NQF 0028b)
  • rule_tob_cess_inter_cqm();
d. Adult Weight Screening and Follow-Up (NQF 0421) (PQRI 128)
  • rule_adult_wt_screen_fu_cqm();
e. Weight Assessment and Counseling for Children and Adolescents (NQF 0024)
  • rule_wt_assess_couns_child_cqm();
f. Influenza Immunization for Patients >= 50 Years Old (NQF 0041) (PQRI 110)
  • rule_influenza_ge_50_cqm();
g. Childhood immunization Status (NQF 0038)
  • rule_child_immun_stat_cqm();
h. Pneumonia Vaccination Status for Older Adults (NQF 0043) (PQRI 111)
  • rule_pneumovacc_ge_65_cqm();
i. Diabetes: Eye Exam (NQF 0055) (PQRI 117)
  • rule_dm_eye_cqm();
j. Diabetes: Foot Exam (NQF 0056) (PQRI 163)
  • rule_dm_foot_cqm();
k. Diabetes: Blood Pressure Management (NQF 0061) (PQRI 3)
  • rule_dm_bp_control_cqm();
l. Maintain an up-to-date problem list of current and active diagnoses. 170.302(c)
  • problem_list_amc()
m. Maintain active medication list. 170.302(d)
  • med_list_amc()
n. Maintain active medication allergy list. 170.302(e)
  • med_allergy_list_amc()
o. Record and chart changes in vital signs. 170.302(f)
  • record_vitals_amc()
p. Record smoking status for patients 13 years old or older. 170.302(g)
  • record_smoke_amc()
q.Incorporate clinical lab-test results into certified EHR technology as structured data. 170.302(h)
  • lab_result_amc()
r. The EP, eligible hospital or CAH who receives a patient from another setting of care or provider of care or believes an encounter is relevant should perform medication reconciliation. 170.302(j)
  • med_reconc_amc()
s. Use certified EHR technology to identify patient-specific education resources and provide those resources to the patient if appropriate. 170.302(m)
  • patient_edu_amc()
t. Use CPOE for medication orders directly entered by any licensed healthcare professional who can enter orders into the medical record per state, local and professional guidelines. 170.304(a)
  • cpoe_med_amc()
u. Generate and transmit permissible prescriptions electronically. 170.304(b)
  • e_prescribe_amc()
v. Record demographics. 170.304(c)
  • record_dem_amc()
w. Send reminders to patients per patient preference for preventive/follow up care. 170.304(d)
  • send_reminder_amc()
x. Provide patients with an electronic copy of their health information (including diagnostic test results, problem list, medication lists, medication allergies), upon request. 170.304(f)
  • provide_rec_pat_amc()
y. Provide patients with timely electronic access to their health information (including lab results, problem list, medication lists, medication allergies) within four business days of the information being available to the EP. 170.304(g)
  • timely_access_amc()
z. Provide clinical summaries for patients for each office visit. 170.304(h)
  • provide_sum_pat_amc()
aa. The EP, eligible hospital or CAH who transitions their patient to another setting of care or provider of care or refers their patient to another provider of care should provide summary of care record for each transition of care or referral. 170.304(i)
  • send_sum_amc()

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

Distributed Development Guideline

Code is now in the official sourceforge codebase. See the git for dummies OpenEMR guide to set up and maintain a development repository.

Here is a updated listing of the commits related to the CDR Module.

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 - 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 - 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 - 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)
  • I wonder where the message should come from for the email reminder. There is a reminder_message column in the rule_action_item table, but it's all empty on my system. For now, I wrote a query that will get the rule category and rule action titles for a given category/item combo in patient reminders, and automatically generate message text.--Ken Chapple 23:40, 23 February 2011 (UTC)
  • I'm assuming that you are working within the send_reminders() function in library/reminders.php. Note that the fetch_reminders() call at the beginning of the send_reminders() function will return the action category and action item. The following would then convert these to their corresponding titles (note this is done in the patient_reminder_widget() function):
$category_title = generate_display_field(array('data_type'=>'1','list_id'=>'rule_action_category'),$reminder['category']);
$item_title = generate_display_field(array('data_type'=>'1','list_id'=>'rule_action'),$reminder['item']);

(As an aside, the 'reminder_message' column in rule_action is merely a potential future feature (note the fetch_reminders() function would need a little modification (sql statement would need to join in the rule_action_item table)) Note this part of the code was created in theory (since not working), so feel free to suggest mods in database that may improve this (for example, may be better to use dates rather than a flag in the *_status columns since may want to track each sending modality separately).

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 - 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:
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 - 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 - 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: --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 - 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 - 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 - 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 - 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 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 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 - 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