Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Status: this page is in development.

Overview

NOTE: In this page, we use the term ‘decision logic module’ (DLM) for convenience, and it should not be taken to be a permanent name. Other names such as ‘computerised guideline module’ (CGM), ‘clinical practice guideline’ (CPG) etc are also common.

The problem

The aim of this page is to describe the form of a ‘decision logic module’ (DLM) that can be used in at least the following scenarios:

...

This achieves the same effect as the openEHR Element type, just in a simpler type system. This approach enables typical null-value rules to be defined, such that an expression such as ejection_fraction > 20% will not cause an exception even if the ejection_fraction raw value is null. Of course it is usually better to test for defined (ejection_fraction) first, if ejection_fraction was defined as Quantity?.

QUESTION: We might have to consider whether using the ‘?' declaration obscures the difference between a 'non-available’ variable (i.e. no value available from the outside world) and one that is simply null in the standard programming language sense. If we assume that the latter can happen within datasets and guidelines, we might want to allow both Type? and e.g. the use of the explicit type Data_item<T> to distinguish the two cases.

Effective time

Sometimes the clinically significant time of a data item needs to be accessed in rules. This can be done by the reference x.effective_time, e.g. ejection_fraction.effective_time returns when the ejection fraction measurement being used was taken. For a variable like is_diabetic, it means when the diagnosis was made.

...

Code Block
languagekotlin
class ProxyVarProxy_var <T> {
    name: String
    
    currency: Duration
    
    value: T {
        // get the value, e.g. by a call like 
        // subject_proxy.getValget_val(name, currency)
    }
}

class ProxyVarQuantityProxy_var_quantity extends ProxyVar<Quantity>Proxy_var<Quantity> {
    // map of named value ranges
    ranges: Map <CodedTerm<Terminology_code, Interval<Quantity>>
    
    // range in which the current value is
    range: CodedTermTerminology_code {
        // return which range in 'ranges' value is in
    }

    // range in which the current value is
    in_range (a_range: Terminology_code): Boolean {
        // return True if range = a_range
    }
}

In an expression such as platelets < 60 x 10^9/L , the platelets reference is understood as a call to ProxyVarQuantityProxy_var_quantity.value, which retrieves the actual value (it would require an internal reference to the Subject Proxy to do this). In an expression like platelets.in_range = (low) , the platelets.in_range() is a call to ProxyVarQuantity.range Proxy_var_quantity.in_range().

According to this scheme, the execution of the declarations of is_diabetic or platelets causes creation of ProxyVarXxx Proxy_var_xxx objects that have access to the Subject Proxy data cache by making calls like getValueget_value(“is_diabetic”) or perhaps typed calls like getQuantityValueget_quantity_value(“platelets”). How the Subject Proxy gets its data depends on the bindings of named variables like is_diabetic to back-end binding meta-data such as AQL queries (for openEHR access), HL7 FHIR calls/resources for FHIR, and whatever other methods are available for other kinds of data source.

When a ProxyVar Proxy_var object is created, it would need to register the named variable, type, currency and possible the ‘hint’ meta-data described earlier, in the Subject Proxy component, for the current patient.

...