Logic Service Project GSoc 2007

Intern: Vladimir Mitrovic

Mentor: Burke Mamlin

Background

Medical data is extremely complex. While a dictionary-based system provides tremendous flexibility in collecting data, consuming the data for decision support, reporting, research question, or even for display within the web application can be increasingly difficult. For example, even answering a simple question like "is the patient HIV positive?" may require a complex algorithm that considers the results of multiple lab results, temporal relations of results, orders, and questionnaire responses. Ideally, this "business logic" is defined in one place and easily accessible to all aspects of the system — e.g., whether we're displaying HIV status on a web page, generating a PEPFAR report, or executing a decision support alert, the same algorithm should be used. We call this bit of business knowledge a "rule." The rules should be easily accessible and return predictable and flexible results.

Goal

Build a logic service for OpenMRS that can evaluate rules over 1-to-n persons and "normalize" the various data sources — e.g., the API, observations, orders, programs, etc. — into data-values pairs.

Non-Goals

  • The logic service is not responsible for parsing languages (e.g., Arden Syntax), but rather provides the foundation for such a parser to more easily create Java classes that can access and manipulate system data.

  • Writing rules is not part of the logic service. The logic service provides the interface and methods needed to define a rule, but most rules will be produced by other tools or, when necessary, could be written manually. Any rule that implements the defined interface could be registered under a token and evaluated using the logic service engine.

  • The alpha version of the logic service (for this project) is to provide very simple functionality while laying the flexible foundation for evolving into more complex decision support capabilities

Use Cases

  • Decision support — if <tt>HIV POSITIVE</tt> and not <tt>CD4 WITHIN 6 MONTHS</tt>, recommend a CD4 count be done.

  • Cohort building — get all patients with <tt>DIABETES RISK FACTORS</tt>

  • Reporting — return all <tt>CD4 COUNT</tt>s < 200 for a given cohort of patients

  • Web application — display <tt>GENDER</tt> and <tt>HIV STATUS</tt> on a web page

Design

Main article: Logic Service Technical Overview

Definitions

  • Logic Service
    Primary interface for the logic API. Provides the methods to create/retrieve/update/delete Rules by Token, get the list of available tokens, and evaluate Rules for patient(s) with optional criteria and/or arguments passed to the rule.

  • Token
    A string that references a Rule.

  • Logic Criteria
    Criteria and/or constraints placed on a particular data element — e.g., date range, comparisons, etc.

  • Rule
    A Java class that returns a Result for a given patient and criteria. Rules utilize the logic service to evaluate other rules or the logic data service to retrieve data from the system. Rules implement metadata methods to reports optional or required arguments, duration of result validity (when the result expires and must be re-calculated), etc.

  • Logic Data Service
    An internal service that provides a cached access to data sources.

  • Data Source
    A source of medical data — e.g., observations, programs, orders, person, etc. Data sources are specialized to the particular domain and can return a result of data "hits" given patient(s), a data source-specific "key," and optional criteria. For example, the person data source could be asked for "GENDER" or "FIRST NAME" where these "keys" are specific to the data source. The observation data source takes a concept as a key, returning observations for that particular question.

  • Result
    A set of date/value pairs of patient data, including convenience methods for treating the Result as a list or as a single item and to coerce the result into basic data types. Results contain a link to a java.lang.Object that represents a particular domain object — e.g., the actual Order, Program, etc. — where appropriate. The basic Result class is specialized for various data types (BooleanResult, CodedResult, DatetimeResult, ObsResult, StringResult).

Requirements

  1. Provide a list of available rules

  2. Allow rules to be added, removed, and updated

  3. Evaluate a rule for a single person or a cohort of persons

  4. Provide a flexible mechanism for constraining results by date, value, and relative values — e.g., limit to all results > 5.0 that occurred within 6 months after an initial encounter

  5. Allow for arguments to be passed to rules

  6. Return all results as a <tt>org.openmrs.logic.Result</tt> object, which can contain 0..n results, is loosely typed and can easily be coerced into string/boolean/number/etc, and maintains a reference to domain objects when available

  7. Allow rules to be interrogated as to their arguments — i.e., so tools like the cohort builder can create a dynamic user interface to constrain a chosen token

Schedule

  • July 15th
    Logic service skeleton in place, sufficient documentation on wiki to solicit input/suggestions/concerns from developers.

  • July 22nd
    Proof of concept with at least one (e.g., observation) data source working and able to execute our first rule — e.g., "CD4 COUNT < 200" (support at least "less than" for criteria and simplest of Result methods for coercing result into value, date, boolean, or numeric value). Plan show & tell with development team.

  • July 29th
    Expand on data source capabilities; add at least one additional data source (e.g., person demographics). Expand on result and criteria capabilities.

  • August 7th
    Further DAO testing and tweaking finished, with a couple of Rules implemented. (Writing all necessary Rules is not our SoC goal - rather, these will be written in time by various people, and/or an Arden-to-Java parser will be constructed.)

  • August 20th
    Initial version (alpha) of logic service is released with basic functionality and a clear path for adding additional criteria and data source capabilities.

Sample Rules

CD4 COUNT

Returns CD4 COUNT observation data.

HIV POSITIVE

Returns the date for which supporting data indicate the patient is HIV POSITIVE; otherwise nothing.

*firstHivDiagnosis = the first PROBLEM ADDED answered with any of the following concepts:

*viralLoad = first HIV VIRAL LOAD

*viralLoadQual = first HIV VIRAL LOAD, QUALITATIVE

*cd4Count = first CD4 COUNT < 200

  • : (not a valid diagnostic criteria, but useful for our example)

  • : (again, using age in this to bring in demographic information)

Expectations

  • The result should be a single value that contains the earliest item that qualified the patient as HIV POSITIVE

  • The calling routine should be able to treat it as boolean with either result.exists() or result.asBoolean() to tell if the patient is HIV positive or not

  • The calling routine should be able to derive the date on which the patient was determined to be HIV positive with result.getDate()

Resources