Decision Language specification
Issuer: openEHR Specification Program | |
---|---|
Release: PROC Release-1.6.0 |
Status: DEVELOPMENT |
Revision: [latest_issue] |
Date: [latest_issue_date] |
Keywords: expressions, rules, guidelines |
© 2020 - 2021 The openEHR Foundation | |
---|---|
The openEHR Foundation is an independent, non-profit foundation, facilitating the sharing of health records by consumers and clinicians via open specifications, clinical models and open platform implementations. |
|
Licence |
Creative Commons Attribution-NoDerivs 3.0 Unported. https://creativecommons.org/licenses/by-nd/3.0/ |
Support |
Issues: Problem Reports |
Amendment Record
Issue | Details | Raiser, Implementer | Completed |
---|---|---|---|
PROC Release 2.0.0 (unreleased) |
|||
SPECPROC-41. Add Decision Language specification. |
T Beale |
1. Preface
1.1. Purpose
This document specifies the openEHR Decision Language, in both abstract syntax form and as a related model. The latter defines the semantics of a first order predicate style logic that can be used to write Decision Logic Modules (DLMs) containing rule-sets that may be used standalone or with a Process / Plan oriented system such as openEHR Task Planning.
The intended audience includes:
-
Standards bodies producing health informatics standards;
-
Academic groups using openEHR;
-
Solution vendors.
1.2. Related Documents
Prerequisite documents for reading this document include:
Related documents include:
1.3. Status
This specification is in the DEVELOPMENT state. The development version of this document can be found at https://specifications.openehr.org/releases/PROC/latest/decision_language.html.
Known omissions or questions are indicated in the text with a 'to be determined' paragraph, as follows:
TBD: (example To Be Determined paragraph)
1.4. Feedback
Feedback may be provided on the process specifications forum.
Issues may be raised on the specifications Problem Report tracker.
To see changes made due to previously reported issues, see the PROC component Change Request tracker.
1.5. Conformance
Conformance of a data or software artifact to an openEHR specification is determined by a formal test of that artifact against the relevant openEHR Implementation Technology Specification(s) (ITSs), such as an IDL interface or an XML-schema. Since ITSs are formal derivations from underlying models, ITS conformance indicates model conformance.
2. Overview
The openEHR Decision Language (DL) and model defines a formalism for expressing decision logic and rules used by process-oriented healthcare information systems, active forms and so on. Decision logic usually sits within a larger environment of plans, guidelines and data sources such as the EHR, as described in the openEHR Process and Planning Overview. The primary encapsulation of DL is within a Decision Logic Module (DLM).
Within the openEHR ecosystem, Task Plans and GDL3 guidelines both require a way of expressing rules and declaring input variables. Guidelines additionally need a way of declaring output variables. These needs are achieved with the flexible use of a single kind of multi-section module called a decision logic module (DLM).
The Decision Language is a high-level language in which modules containing the following elements may be written:
-
reference data: domain constants;
-
input variables: data items representing external variables relating to the subject (i.e. patient);
-
conditions: Boolean-returning domain-specified criteria;
-
rules: domain-specified rules structures based on condition/action structures, which may return any type;
-
rule-sets: related sets of rules in various forms, including decision tables;
-
outputs: computed results of rule invocations, including logic trace information;
All symbolic elements, including constants, variables and rules may be treated as codes for which a translation terminology is supplied, enabling a DLM to be translated and presented in any natural language.
2.1. Requirements
The requirements of openEHR Decision Language fall into a number of categories, described below.
TBD: this section only very rough for now.
2.1.1. Caller Interaction
-
the ability to capture the reasoning chain for presentation to a caller as a justification;
-
the ability to provide a decision and its possible outcomes, with the current recommendation indicated;
2.1.2. Representation
-
multi-lingual translations for symbolic variables, in a similar way to the openEHR Archetype Definition Language (ADL2);
3. DLM Syntax
The openEHR Decision Language (DL) is primarily used to write Decision Logic Modules (DLMs). A DLM has the following structure.
dlm <form> <identifier> definitions -- Descriptive | | lang and translations meta-data, as for archetypes | language = { original_language: [ISO_639-1::en], translations: {...} } ; | | description meta-data, as for archetypes | description = {...} ; [use_model <reference model ids; defaults to openEHR Foundation & Base types>] [use <local identifier>: <dlm identifier> <local identifier>: <dlm identifier>] [preconditions <conditions that act as pre-conditions for this module>] [definitions -- Reference <constant definitions>] input -- Administrative State <administrative subject variables> input -- Historical State <historical subject variables> input -- Tracked State <real-time subject variable> rules -- Conditions <conditions expressed as EL functions> rules -- Main <computational rules expressed as EL functions> rules -- Output <output rules expressed as EL functions> definitions -- Terminology terminology = {...};
Many of the sections are optional and are only used in specific forms of DLM, indicated by the <form>
on the first line.
The definitions — Descriptive
and definitions — Terminology
sections (which are logically identical data structures to the same-named sections in openEHR archetypes, but in a JSON5 superset form) can be omitted for DLMs in development for which no descriptive meta-data or terminology is needed.
3.1. Identifiers
All identifiers in a DLM are strings with no whitespace. If the terminology
section is present, these identifiers are included with linguistic definitions and translations, in the same way as archetypes. This approach enables the symbolic variables such as is_type1_diabetic
to be used in rules, and to have a full, formal, multi-lingual definition, such as the following:
definitions -- Terminology
terminology = {
term_definitions: {
"en" : {
"resting_heart_rate" : {
text: "heart rate at rest",
description: "..."
}
...
"SpO2": {
text: "Oxygen saturation";
description: "..."
}
}
}
}
3.2. Identification Section
The identification section takes the form dlm <form> <identifier>
, where:
-
<form>
: flavour of DLM artefact, with valueruleset | guideline
; -
<identifier>
: identifier, in the format<concept>.vN.N.N
wherevN.N.N
represents a numeric version of the logical formmajor.minor.patch
, and whose values over time obey the Semver.org rules.
The following shows the identification line for a guideline:
dlm guideline chadvasc2.v1.0.5
A reference to a DLM may be effected by quoting the whole identifier, or a form with the minor and / or patch parts of the version missing. Either of these forms identify the most recent matching DLm available. For example, the reference NHS-chops14.v4
identifies whatever the most recent minor version of the v4
major version of the NHS-chops DLM is locally available.
3.3. Language and Description Sections
The language
and description
sections are the same as for openEHR archetypes, and are formally defined by the openEHR Resource specification. The following provides an example.
definitions -- Descriptive
language = {
original_language: [ISO_639-1::en]
}
;
description = {
lifecycle_state: "unmanaged",
original_author: {
name: "Thomas Beale",
email: "thomas.beale@openEHR.org",
organisation: "openEHR Foundation <http://www.openEHR.org>",
date: "2021-01-10"
},
details: {
"en" : {
language: [ISO_639-1::en],
purpose: "To record an individual's QRISK3 score."
}
},
copyright: "© 2021 openEHR Foundation",
licence: "Creative Commons CC-BY <https://creativecommons.org/licenses/by/3.0/>",
ip_acknowledgements: {
"ClinRisk" : "This content developed from original publication of
© 2017 ClinRisk Ltd., see https://qrisk.org",
"QRISK" : "QRISK® is a registered trademark of the University of Nottingham and EMIS"
}
}
;
3.4. Use_model Section
The optional use_model
section enables a DLM to specify a model that defines the type system for the DLM. The identifier of the model must be resolvable to a BMM model, i.e. a model for which an openEHR Basic Meta-Model file is available. This might be a well-known model such as the openEHR Reference Model (BMM form), or a custom model created for local use. The model identifier must include a version matching part, with at least the major version present. The following example specifies the use of the openEHR RM in the latest 1.1
version available.
use_model openEHR-RM.v1.1
The types defined in all 'used' models become available to the DLM for use in declarations. If no model is specified, the openEHR Base and Foundation types are assumed.
3.5. Use Section
A DLM can use other DLMs, by declaring each DLM with an identifier in the use
section. The identifier must include a version-matching part. The following example declares the identifier BSA
as a convenient local label to refer to the latest version of the DLM Body_surface_area.v1
.
use BSA: Body_surface_area.v1
3.6. Preconditions Section
The preconditions
section is used to state logical conditions that must evaluate to true for the DLM to be used for the subject. Any Boolean-typed identifier may be used from the input
, condition
or rules
sections, or any Boolean-returning logical expression referencing any identifiers declared in the DLM. A typical preconditions
section is shown below:
preconditions is_pregnant
3.7. Reference Section
The reference
section of a DLM contains what might be thought of constant definitions, i.e. identifiers declared with fixed values. The following illustrates.
definitions -- Reference
paracetamol_dose: Quantity = 1g;
chlorphenamine_dose: Quantity = 10mg;
prednisolone_dose_per_m2: Quantity = 40mg;
These may be data structures of significant complexity, such as the following risk tables.
definitions -- Reference
Snoking_interaction_scales = {
[female]: {
[age_1]: {
[non_smoker]: 0,
[ex_smoker]: -4.70571617858518910,
[light_smoker]: -2.74303834035733370,
[moderate_smoker]: -0.866080888293921820,
[heavy_smoker]: 0.902415623697106480
},
[age_2]: {
[non_smoker]: 0,
[etc]: -0.0755892446431930260000000
}
},
[male]: {
[age_1]: {
[non_smoker]: 0,
[etc]: -0.2101113393351634600000000
},
[age_2]: {
[non_smoker]: 0,
[etc]: -0.0004985487027532612100000
}
}
}
;
3.8. Input Section
3.8.1. Subject Variables
The input
section contains declarations of all subject variables used by a DLM. At a minimum, a subject variable declaration states the symbolic name and type of the variable in the manner typical of a typed programming language, as exemplified by the following:
input
heart_rate: Quantity
Although a subject variable declaration appears to declare a simple property of a type such as a Quantity
, in fact it creates an instance of a proxy object described below in Section 4, that provides access to snapshot values of the variable over time, as well as other smart facilities including null-value detection and range conversion, described in the sections below.
3.8.1.1. Variable Naming
The naming of a subject variable is important, and should reflect its intended domain meaning with respect to the guideline or plan which it formalises. Thus, a cardiology guideline might use a variable systolic_bp
to mean 'current instantaneous systolic blood pressure' and a variable target_systolic_bp
to mean a target pressure for the patient to aim for over the course of hypertension treatment. However a guideline that refers to different systolic blood pressures, e.g. historical, average and current might use variables such as actual_systolic_bp
, 24h_average_systolic_bp
etc.
The naming is important in another way. Generally a subject variable should reflect a fact or assertion about the subject in reality rather than a purely epistemic view relating to an information system. For example a variable is_type1_diabetic
is intended to reflect the patient’s real diabetic status, not just the knowledge of the local hospital EMR system of whether the patient is diabetic. Such variables may be termed 'ontic' i.e. reflecting the real world, rather than reflecting states of knowledge of some information source. The reason for using ontic variables is to allow DLM authors to define rules in terms of true clinical reality based on reliable previously established facts, rather than continually having to compensate for missing or unreliable knowledge within a guideline.
Epistemic variables may of course be defined, e.g. the variable has_diabetes_diagnosis
directly reflects the idea that the presence of a diagnosis of a condition is distinct from the true fact of having the condition. These are typically used when the purpose of the guideline is to establish the presence or otherwise of the condition named in such variables.
3.8.1.2. Unavailable Values
One of the facilities created by a declaration of the form identifier: Type
are subordinate predicate functions to detect if a value is available for the variable, i.e. if it is not logically null. Lack of a value is caused either by the true absence of the data in back-end systems (e.g. blood pressure has not recently been measured) or a technical failure to query or otherwise interrogate the relevant system.
It should be noted that within the overall conceptual model of process-based computing in openEHR, the common problem of a failure to locate a data item in back-end systems causing a live user to be asked to supply it is assumed to be addressed outside the DLM itself. This means that the simple lack of a value in back-end systems does not need to be compensated for by logic (such as null checks) in a DLM itself - it will already have been done in the Subject Proxy service. Consequently, if a variable value is unavailable within a DLM computation, this already takes into account attempts to obtain a value from a user.
The general case is that any subject variable might not have a value available for it, or at least a sufficiently current value (see next section for the concept of currency) at the moment of a particular rule invocation (remembering that the same rule might be invoked repeatedly over time). This means that the simple (primary variable) reference systolic_blood_pressure
may in fact return a null value. If rules containing primary variable references such as systolic_blood_pressure
are written under a non-null assumption, a null value will cause an exception of type no available value
, and the original rule invocation will fail.
In most cases this is likely to be the preferred style of rule expression, since it makes rules simpler and clearer. However, in some cases, it may be known a priori that certain variables are only sometimes likely to be available, and if so, they are used, but if not, no exception is generated. This may be achieved by calling the subordinate predicate is_available
as a guard on the direct access, as follows.
rules
is_hypertensive:
Result := systolic_blood_pressure.is_available and then systolic_blood_pressure.in_range([high]) or ...
In the above, the semi-strict Boolean operator and then
ensures the second reference to systolic_blood_pressure
will only be evaluated if systolic_blood_pressure.is_available
returns True.
3.8.2. Tracked Variables
An important category of subject variable is the tracked variable, which enables the current value of a variable, with some lag, to be obtained automatically from the back-end system. The acceptable lag is indicated by the subordinate currency attribute, as a temporal duration. This specifies how recent the value obtained from the external world (the 'sample') must be to be valid from the point of view of the DLM. Currency may be understood as the converse of 'staleness', that is, a variable sample that must be say 1 hour or less old is understood as stale after 1 hour.
The use of the currency modifier establishes that a subject variable is a time-related sample of some kind (instantaneous, average, minimum, etc) of a real-world time-varying continuant quality (e.g. blood pressure) of an independent continuant entity (usually a person).
Since the various physiological and disease process that occur in a human body have significantly differing temporal rhythms, currency will vary widely for different subject variables, as per the following examples.
input -- Administrative State
|
| untracked variable:
| DOB never changes, no currency needed
|
date_of_birth: Date
;
input -- Historical State
|
| tracked variable:
| weight changes over a period of days
|
weight: Quantity
currency = 3 days
;
|
| untracked variable:
| assuming an adult subject, height constant
|
height: Quantity
;
input -- Tracked State
|
| tracked variable:
| blood glucose changes within minutes in response to food
|
blood_glucose: Quantity
currency = 15 min
;
|
| tracked variable:
| Heart-rate may change quickly
|
heart_rate: Quantity
currency = 5 sec
;
Variables for which no currency is stated may be understood as having the currency equal to the age of the subject.
3.8.3. Quantitative Tracked Variables
Many tracked variables are quantitative, and a ubiquitous need within clinical guidelines and rules is to be able to refer to a continuous variable such as vital signs and most lab test values as being in a designated range. Such ranges may be the usual ones published e.g. the normal and high ranges for lipids in a cholesterol test for adults, or ranges defined by the DLM.
TBD: could ranges be declared elsewhere and re-used, e.g. standard BMI ranges, BP ranges etc?
The ranges for a subject variable are declared in the following way:
input -- Tracked State
|
| Systolic BP (mmHg)
|
systolic_blood_pressure: Real
currency = 1 min
ranges["mmHg"] =
------------------------------------
|≥ 180|: [critical_high],
|> 140|: [very_high],
|> 120|: [high],
|> 90 .. ≤ 120|: [normal],
|≤ 90|: [low],
|≤ 50|: [critical_low]
------------------------------------
;
The above declaration allows the use of the predefined range
function, which returns the most precise range in which the value falls, in rule expressions such as the following:
Result :=
case systolic_blood_pressure.range in
=====================================
[critical_high]: [emergency],
-------------------------------------
[high], [very_high]: [high_risk],
-------------------------------------
*: [monitor]
=====================================
;
Note that ranges may be defined in two ways:
-
to be overlapping, such that
[high]
refers to any value higher than 120, while[very_high]
refers to any value over 140; -
non-overlapping, such that each sub-range stops at the start of the next one.
In the latter case, determining that a patient has high blood pressure requires an expression of the form systolic_blood_pressure.in_range ({[high], [very_high], [critical_high]})
, using a set argument.
Sometimes there are multiple ranges, usually due to alternative units systems. This is handled by the use of a discriminator on a number of range groups. The following shows an example.
input -- Tracked State
PaO2_FiO2_ratio: Quantity
currency = 1 min,
ranges["mm[Hg]"] =
---------------------------------
|≥400 |: [normal],
|300 .. 399|: [low],
|200 .. 299|: [very_low],
|100 .. 199|: [extremely_low],
|<100|: [critical_low]
---------------------------------
;,
ranges["kPa"] =
---------------------------------
|≥53|: [normal],
|39.9 .. 53|: [low],
|26.6 .. 39.8|: [very_low],
|13.3 .. 26.5|: [extremely_low],
|<13.3|: [critical_low]
---------------------------------
;
To access a range within this structure, an expression of the form systolic_blood_pressure.in_range (["kPa"], [high])
is needed. This makes use of an overload of the in_range()
function taking two keys. We can now see that the simpler form systolic_blood_pressure.in_range ([critical_high])
first chooses the first range group, and then extracts the required entry.
The above case reveals the general structure of the ranges
property, with a formal type equivalent to Map <Terminology_code, Map <Interval <T>, Terminology_code>
, where T
is the declared type of the subject variable. In both the simple and discriminator cases, the entry |> 140|: [very_high]
defines a [key, value]
pair whose key is of type Interval <Real>
and whose value is of type Terminology_code
.
3.9. Rules Section
The DLM rules
section is the section of primary importance, since it contains the rules for which a DLM is created. DLM rules are formally expressed as functions in the openEHR Expression Language, based on the openEHR BMM.
This section may be typically divided into two or more groups for authoring convenience. The first group may be used for simple Boolean-returning 0-order functions that represent 'named conditions', for use in the primary rules. The Boolean
type may be omitted, since all conditions have this as their formal type. The following is an example.
rules -- Conditions
her2_positive:
Result := her2_expression = [positive]
;
non_class_I_heart_failure:
Result := has_heart_failure_class_II or
has_heart_failure_class_III or
has_heart_failure_class_IV
;
anthracyclines_contraindicated:
Result := has_transmural_MI or
ejection_fraction.in_range ([low]) or
non_class_I_heart_failure
;
The primary rules may be included in a separate rules
group, consisting of 0-order functions returning any type. EL structures of any complexity may be used. The following provides an example.
rules -- Main
hypertension_risk: Terminology_term
Result :=
choice in
=================================================
has_pre_eclampsia or
has_eclampsia: [emergency],
-------------------------------------------------
previous_obstetric_hypertension or
previous_pre_eclampsia or
previous_eclampsia or
has_pregnancy_hypertension: [high_risk],
-------------------------------------------------
*: [low_risk]
=================================================
;
gestational_diabetes_risk: Boolean
Result :=
bmi.in_range ([high]) or
previous_macrosomic_baby or
previous_gestational_diabetes or
family_history_of_diabetes or
race_related_diabetes_risk
;
3.11. Terminology Section
The definitions — Terminology
section of a DLM serves the same purpose as the terminology section in an openEHR archetype, which is to provide multi-lingual definitions of all codes used in the artefact. Unlike archetypes, the codes in a DLM may be freely named, since they act as names of all symbolic entities referenced elsewhere in the DLM, including rules (i.e. functions), subject variables and constants. A typical DLM terminology section is shown below.
definitions -- Terminology
terminology = {
term_definitions: {
"en" : {
"date_of_birth" : {
text: "Date of birth"
},
"age_in_years" : {
text: "Age (years)"
},
"qRisk_score" : {
text: "QRISK2 score"
},
"diabetes_status" : {
text: "Diabetic status of subject"
},
"no_diabetes" : {
text: "Non-diabetic"
},
"type1_diabetes" : {
text: "Has type 1 diabetes"
},
"type2_diabetes" : {
text: "Has type 2 diabetes"
}
}
}
value_sets: {
"diabetes_status" : {
id: "diabetes_status",
members: ["no_diabetes", "type1_diabetes", "type2_diabetes"]
}
}
}
;
4. DLM Model
4.1. Overview
The structure of the proc.decision_language
packages is shown below.
proc.decision_language
Package strucureThe packages are described below.
4.2. Decision Logic Module Package
The module structure of a Decision Logic Module is formally represented by a class model consisting of minimal extensions to the BMM class (i.e. BMM_CLASS
) concept. A DLM is thus understood as a special kind of module expressible as a constrained form of class definition, such that only certain types of features are allowed. It also has additions for documentary meta-data and terminology provided by the AUTHORED_RESOURCE
class from the openEHR BASE component.
The meta-model is shown below, with the meta-class DECISION_LOGIC_MODULE
being the root entity.
proc.decision_language.dlm
PackageWithin this model, the various DLM sections are modelled as specialisations of the BMM meta-class BMM_FEATURE_GROUP
, so as to restrict the kind of features they may define. These are described in the following sub-sections.
4.2.1. Pre-conditions Section
The DLM preconditions
section is formally represented as a feature group called 'preconditions'
whose members are limited to being a single BMM_FUNCTION
containing the Boolean expression that appears in that section. The expression may reference only rules and input variables.
4.2.2. Reference Section
The DLM reference
section is formally represented as a feature group called 'reference'
whose members are limited to BMM constants.
4.2.3. Input Section
The DLM input
section is formally represented as a feature group called 'input'
whose members are limited to BMM constants of a specific concrete type TRACKED_VARIABLE<T>
and descendants, supplied by the proc.decision_language.concrete
package.
4.2.4. Rules Section
The DLM rules
section is formally represented as a feature group called 'rules'
whose members are limited to BMM functions. A specific meta-type DLM_RULE
is used in case extensions to the standard BMM_FUNCTION
are required.
4.2.5. Class Descriptions
4.2.5.1. DECISION_LOGIC_MODULE Class
Class |
DECISION_LOGIC_MODULE |
|
---|---|---|
Description |
Specialised kind of class that represents a Decision Logic Module (DLM). |
|
Inherit |
||
Functions |
Signature |
Meaning |
0..1 |
create_bmm_class |
Generate a |
4.2.5.2. DLM_REFERENCE_SECTION Class
Class |
DLM_REFERENCE_SECTION |
|
---|---|---|
Description |
Specialised feature group used in DLM to represent the |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
name: |
Name of this feature group; defaults to 'reference'. |
0..1 |
features: |
Constant definitions needed by module. |
4.2.5.3. DLM_INPUT_SECTION Class
Class |
DLM_INPUT_SECTION |
|
---|---|---|
Description |
Specialised feature group used in DLM to represent the |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
name: |
Name of this feature group; defaults to 'input'. |
0..1 |
features: |
Input variable proxies. |
4.2.5.4. DLM_RULES_SECTION Class
Class |
DLM_RULES_SECTION |
|
---|---|---|
Description |
Specialised feature group used in DLM to represent the |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
name: |
Name of this feature group; defaults to 'rules'. |
0..1 |
Rules for this module. |
4.3. DLM Concrete Model
In order to supply a few of the key constructs of a DLM, a concrete model is provided with specific types that express the needed semantics. The main types required relate to input variables. The DLM concrete model UML is shown below.
proc.decision_language.concrete
Package4.3.1. Subject Variables
The variable definitions found in the input
section of a DLM are designed to facilitate both intuitive DLM authoring and tracking of values over time from real data sources, typically health records, devices and so on. The generic class STATE_VARIABLE<T>
and descendants provide a representation of a subject variable with a symbolic name. The generic type parameter is substituted with types used for representing atomic data values, including primitive types such as String
, Integer
etc, as well as types like Terminology_code
, Quantity
etc, as available in the models (type definitions) used by a DLM.
The class STATE_VARIABLE<T>
models the simplest case: a variable that may be queried once for an execution run. This is sufficient for subject variables that are not time-dependent, and will not change during the execution, such as date_of_birth
, sex
, and Boolean variables such as is_type1_diabetic
. The history
attribute contains the variable value (normally only one sample), while the features is_available()
and unavailable_reason()
provide a way for missing data to be checked for.
For time-varying variables, the values must usually be tracked. The class TRACKED_STATE_VARIABLE<T>
is is provided for this purpose, and adds the meta-attribute currency
, a duration indicating the maximum age of the sample value to be useful or valid. The history
attribute now contains variable samples over time. The function value()
extracts the most recent available value, while is_available()
is redefined to indicate whether a sufficiently recent value is available.
Many tracked variables are quantitative, and for these, extra facilities are provided via the class TRACKED_QUANTITATIVE_VARIABLE<T>
, which adds the ranges facility described earlier in Section 3.8.3.
Variable declarations in DL syntax, as described in the language section above are in fact instantiations of the STATE_VARIABLE<T>
or a descendant, potentially with constructor paramaters supplied. Consider the following declaration, shown earlier:
systolic_blood_pressure: Quantity
currency = 1 min,
ranges["mm[Hg]"] =
--------------------------------
|≥180|: [critical_high],
|>140|: [very_high],
|>120|: [high],
|>90..≤120|: [normal],
|≤90|: [low],
|≤50|: [critical_low]
--------------------------------
;
If we were to rewrite this in a more standard programming language, it might look like the following object instantiation, preceded by setup code (the syntax 'Type_name (args)' is used to represent an object creation using a constructor call in each case):
// build the ranges Map
ranges: Map <Terminology_code, Interval<Quantity> ();
ranges.put (Terminology_code("critical_high"), Interval<Quantity>(180 mm[Hg], Void);
...
ranges.put (Terminology_code("critical_low"), Interval<Quantity>(Void, 50 mm[Hg]);
// instantiate the tracked variable object
systolic_blood_pressure: TRACKED_QUANTITATIVE_VARIABLE<Quantity> (
"systolic_blood_pressure", // name
"PT1M", // currency
ranges // ranges
);
It will be appreciated that this is substantially more complex, and also arcane to a domain specialist. In the above, the part between the parentheses in the lower declaration corresponds to a call to a constructor of type TRACKED_QUANTITATIVE_VARIABLE
with the signature (name: String, currency: Iso8601_duration, ranges: Map<Terminology_code, Interval<T>)
. From a formal point of view, such an instantiation creates an instance that will remain for the life of the DLM’s execution, in other words, a computed constant value. It is thus a meta-instance of the BMM meta-type BMM_CONSTANT
, as shown in the DLM model above.
Each input
variable declaration creates an object similar to the above, which may then be used during the execution of the DLM by calls made from the functions in the rules
section. The simplest possible 'bare' reference of the variable name alone, i.e. systolic_blood_pressure
in the example above, makes use of the default delegate feature of the BMM (BMM_FUNCTION
) to invoke the value()
function, avoiding the need to write systolic_blood_pressure.value()
. However, all the features defined on TRACKED_VARIABLE
and its descendants are indeed available for use in DLM code if needed. Thus, systolic_blood_pressure.in_range([high])
is a normal call on the systolic_blood_pressure
instance of TRACKED_QUANTITATIVE_VARIABLE<Quantity>
.
TO BE CONTINUED
4.3.2. Class Descriptions
4.3.2.1. STATE_VARIABLE Class
Class |
STATE_VARIABLE<T> |
|
---|---|---|
Description |
Abstraction of a real-world variable that represents a quality of a subject, e.g. patient diabetic status, date of birth etc. The generic parameter is a model type from an accessible model. |
|
Attributes |
Signature |
Meaning |
0..1 |
history: |
Local history of values. |
1..1 |
name: |
Name of variable. |
Functions |
Signature |
Meaning |
1..1 |
is_available (): |
Return True if there is a value in |
0..1 |
unavailable_reason (): |
If |
0..1 |
value (): |
Retrieve latest value, or null if none. |
4.3.2.2. VALUE_SNAPSHOT Class
Class |
VALUE_SNAPSHOT<T> |
|
---|---|---|
Description |
One or more snapshot attempts of the state variable, either containing values or unavailable reason. |
|
Attributes |
Signature |
Meaning |
0..1 |
value: |
Value of variable in the real world, if available; Void if not. |
0..1 |
effective_time: |
Real-world time at which |
1..1 |
sample_time: |
Time at which this sample was obtained from its source (e.g. a patient record system, device, or user interaction). |
0..1 |
unavailable_reason: |
|
Functions |
Signature |
Meaning |
1..1 |
is_available (): |
Return True if |
Invariants |
Inv_available: |
4.3.2.3. TRACKED_STATE_VARIABLE Class
Class |
TRACKED_STATE_VARIABLE<T> |
|
---|---|---|
Description |
A 'tracked' subject variable representing a continuant quality of a subject over time, e.g. patient systolic blood pressure, heart rate etc, whose value is sampled over time. The generic parameter is a model type from an accessible model. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
0..1 |
currency: |
If set, maximum age of a real-world snapshot of this variable’s value to be usable or valid. |
0..1 |
max_history: |
|
Functions |
Signature |
Meaning |
1..1 |
value_at_time ( |
Return the value from |
1..1 |
is_available (): |
Return True if there is a member of |
4.3.2.4. TRACKED_QUANTITATIVE_VARIABLE Class
Class |
TRACKED_QUANTITATIVE_VARIABLE<T> |
|
---|---|---|
Description |
Specialised property that represents a 'tracked variable' within the DLM |
|
Inherit |
||
Attributes |
Signature |
Meaning |
0..1 |
unit_ranges: |
Range definitions, represented as tables, each one exhaustively covering the value space. |
Functions |
Signature |
Meaning |
1..1 |
in_range ( |
Determine if the last read value of the variable is in the named range within the default group. Use when there is only one range group. |
1..1 |
range (): |
Return the name of the range from the default range group within which the last read value of the variable resides. Use when there is only one range group. |
1..1 |
range_definition ( |
Return the interval of the named range within the default range group. Use when there is only one range group. |
1..1 |
in_group_range ( |
Form of |
1..1 |
group_range ( |
Form of |
1..1 |
group_range_definition ( |
Form of |