Example Library Resources
The following Library resources and contained rules constitute examples that show various aspects of rules and intended use. They do not constitute properly tested or production-ready rules, even if they might come close.
In the example descriptions, Coding values have been reduced to the Coding.code
element solely for brevity and where there is little if any ambiguity when the reader checks the ValueSet binding of the corresponding element in the profile. As apparent in the actual rule code listings here (which are not normative), Coding values must be specified properly and in accordance with the eHealth Implementation Guide’s General Guidance.
Automated Processing Type Library Resource Examples
Common to automated processing type Library resources is that they have a Library.type
set to automated-processing
and specify no output type parameters in Library.parameter
. In reality, evaluation of the Library causes return of a GuidanceResponse containing a AutomatedProcessingDTO
structure with instructions, but this need not be declared.
Except for the Fallback Library, evaluation of an automated processing type Library requires that a measurement has been submitted and that the ServiceRequest refers to an ActivityDefinition which refers to the Library, that is, the Library must be used in a CarePlan complex associated with the Patient for which a measurement is submitted.
Library Triaging Against Reference Ranges
This Library is intended for use with an ActivityDefinition which specifies submitting of an Observation where the submitted Observation.value
is to be compared against the reference range(s) defined in the ServiceRequest associated with the ActivityDefinition.
The Library has:
.type
set toautomated-processing
.parameter
.use
set toin
for input.type
set toObservation
The Library rule sets up instructions that causes production of a:
a Task with:
.category
set toMeasurementForAssessment
(a Coding signifying a measurement should be assessed/evaluated).priority
set to:routine
when theObservation.value
is within reference rangeurgent
when theObservation.value
is outside a “Yellow Alarm” type reference range (if defined) but within a “Red Alarm” type reference range (if defined)asap
when theObservation.value
is outside the “Red Alarm” type reference range (if defined)
.description
set to “Måling til vurdering” which is Danish for measurement to be assessedfurther elements set as described in Output from automated processing
a ClinicalImpression with:
.code
set toTriagingResult
.finding.itemCodeableConcept.Coding
set to:a Coding signifying a finding that a measurement is within reference range when that is the case
a Coding signifying a finding that a measurement is above reference range when that is the case - this whether above Red Alarm or above Yellow Alarm (but within Red Alarm)
a Coding signifying a finding that a measurement is below reference range when that is the case - this whether below Red Alarm or below Yellow Alarm (but within Red Alarm)
.description
set to “Automatisk processering grundet måling modtaget” which is Danish for automated processing due to submitted measurementfurther elements set as described in Output from automated processing
a Communication (of ehealth-message profile) provided that the
Task.priority
is notroutine
(that is, when the measurement is outside any reference range) with:.ehealth-restriction-category
that restricts access for Practitioners to those monitoring measurements.reasonCode
set toMeasurementForAssessment
.payload.content
set to “Måling til vurdering” which is Danish for measurement to be assessed (in the Default message)further elements set as described in Output from automated processing
The Library rule (in Library.content.data
) is :
package rules
import org.hl7.fhir.dstu3.model.Observation
// additional imports omitted for brevity
global com.systematic.ehealth.automatedprocessing.AutomatedProcessingDTO ruleResult
function CodingDTO withinReferenceRangeCoding() {
// Measurement finding within reference range
return new CodingDTO("http://snomed.info/sct", "442082004", "fund ved måling inden for referenceinterval");
}
function CodingDTO belowReferenceRangeCoding() {
// Measurement finding below reference range
return new CodingDTO("http://snomed.info/sct", "442686002", "fund ved måling under referenceinterval");
}
function CodingDTO aboveReferenceRangeCoding() {
// Measurement finding above reference range
return new CodingDTO("http://snomed.info/sct", "442756004", "fund ved måling over referenceinterval");
}
function CodingDTO redAlarmCoding() {
return new CodingDTO("urn:oid:1.2.208.184.100.1", "RAL", "Terapeutiske grænseværdier for RØD alarm");
}
function CodingDTO yellowAlarmCoding() {
return new CodingDTO("urn:oid:1.2.208.184.100.1", "GAL", "Terapeutiske grænseværdier for GUL alarm");
}
function ClinicalImpressionDTO createClinicalImpression(CodingDTO finding) {
String clinicalImpressionDescription = "Automatisk processering grundet måling modtaget";
CodingDTO clinicalImpressionCode = new CodingDTO("http://ehealth.sundhed.dk/cs/clinicalimpression-codes", "TriagingResult", "Result of triaging");
return new ClinicalImpressionDTO(clinicalImpressionCode, clinicalImpressionDescription, List.of(finding), List.of());
}
function TaskDTO createTask(String taskPriority) {
List<CommunicationDTO> communications = new ArrayList<>();
String description = "Måling til vurdering"; // Need assessment of measurement
CodingDTO taskCategory = new CodingDTO("http://ehealth.sundhed.dk/cs/task-category", "MeasurementForAssessment", "Need assessment of measurement");
if (!taskPriority.equals("routine")) {
CodingDTO communicationRestrictionCategory = new CodingDTO("http://ehealth.sundhed.dk/cs/restriction-category", "measurement-monitoring", "Monitoring of measurement(s)");
communications.add(new CommunicationDTO(taskCategory, description, communicationRestrictionCategory));
}
CodingDTO taskRestrictionCategory = new CodingDTO("http://ehealth.sundhed.dk/cs/restriction-category", "measurement-monitoring", "Monitoring of measurement(s)");
return new TaskDTO(taskCategory, description, taskPriority, List.of(taskRestrictionCategory), communications);
}
function Observation.ObservationReferenceRangeComponent getReferenceRange(Observation obs, CodingDTO code) {
for (Observation.ObservationReferenceRangeComponent r : obs.getReferenceRange()) {
String matchingCode = r.getType().getCoding().stream()
.filter(coding -> coding.getSystem().equals(code.getSystem()))
.filter(coding -> coding.getCode().equals(code.getCode()))
.map(Coding::getCode)
.findFirst()
.orElse(null);
if (matchingCode != null) {
return r;
}
}
return null;
}
rule "ObservationTriageMedcomReferenceRangesRule"
dialect "java"
when
col : Collection()
listObs : ArrayList() from collect (EHealthObservation() from col)
o : EHealthObservation() from listObs.get(0)
then
String priority = "routine";
// Get value from observation
BigDecimal value = ((Quantity)o.getValue()).getValue();
Observation.ObservationReferenceRangeComponent redRefRange = getReferenceRange(o, redAlarmCoding());
if (redRefRange != null) {
if (redRefRange.getLow() != null && redRefRange.getLow().hasValue() && redRefRange.getLow().getValue().compareTo(value) > 0) {
priority = "asap";
ruleResult.setClinicalImpressions(List.of(createClinicalImpression(belowReferenceRangeCoding())));
} else if (redRefRange.getHigh() != null && redRefRange.getHigh().hasValue() && redRefRange.getHigh().getValue().compareTo(value) < 0) {
priority = "asap";
ruleResult.setClinicalImpressions(List.of(createClinicalImpression(aboveReferenceRangeCoding())));
}
}
// Not necessary to check yellow alarm range if already outside red alarm range
if (!priority.equals("asap")) {
Observation.ObservationReferenceRangeComponent yellowRefRange = getReferenceRange(o, yellowAlarmCoding());
if (yellowRefRange != null) {
if (yellowRefRange.getLow() != null && yellowRefRange.getLow().hasValue() && yellowRefRange.getLow().getValue().compareTo(value) > 0) {
priority = "urgent";
ruleResult.setClinicalImpressions(List.of(createClinicalImpression(belowReferenceRangeCoding())));
} else if (yellowRefRange.getHigh() != null && yellowRefRange.getHigh().hasValue() && yellowRefRange.getHigh().getValue().compareTo(value) < 0) {
priority = "urgent";
ruleResult.setClinicalImpressions(List.of(createClinicalImpression(aboveReferenceRangeCoding())));
}
}
}
if (priority.equals("routine")) {
ruleResult.setClinicalImpressions(List.of(createClinicalImpression(withinReferenceRangeCoding())));
}
ruleResult.setTasks(List.of(createTask(priority)));;
end;
Library Producing a ClinicalImpression with Contained Observation
An example use for this Library is to obtain an Observation for a chronic chronic obstructive pulmonary disease (COPD) assessment test (CAT) score based on a QuestionnaireResponse submitted as response to a CAT Questionnaire. The CAT Questionnaire (not shown) contains 8 questions where the Patient can assess his/her condition using integer answers from 1 through 5. The total sum, the CAT score, is captured in an Observation wrapped in a ClinicalImpression created by automated processing. The CAT score is at most 40 which reflects very poor overall condition. There is a fixed triage such that a total sum below 15 is fine while 15 and above requires attention from a clinician, which is reflected in the Task created by automated processing.
The Library has:
.type
set toautomated-processing
.parameter
.use
set toin
for input.type
set toQuestionnaireResponse
The Library rule sets up instructions that causes production of a:
a Task with:
.category
set toMeasurementForAssessment
(a Coding signifying a measurement should be assessed/evaluated).priority
set toroutine
when the computed CAT score is below 15,urgent
otherwise.description
set to “Måling til vurdering” which is Danish for measurement to be assessedfurther elements set as described in Output from automated processing
a ClinicalImpression with:
.code
set toTriagingResult
.description
set to “Automatisk processering grundet måling modtaget“.finding.itemReference
referencing a contained Observation with:.code
set to an Coding for CAT Score in the MCS system.valueQuantity
set to the computed CAT score (sum)
Although the example here uses Questionnaire answers of integer type, the principle in the Library can easily be adjusted to processing of coded answers as long as they each have an integer value correspondence.
Library Activating a Self-Treatment ServiceRequest
An example use for this Library is to trigger activation of one or more ServiceRequest of self-treatment type based on answers (a QuestionnaireResponse) to a Questionnaire or, alternatively, computed from a submitted Observation. In the following, it is assumed that triggering is based on a QuestionnaireResponse.
In the initial state, the CarePlan would contain:
a number of ServiceRequest, say, specifying measuring and questionnaire answering activities (this is typical content but irrelevant for activation of the self-treatment activity).
an active ServiceRequest, here denoted the trigger ServiceRequest, specifying answering of the Questionnaire that triggers the self-treatment activity
an inactive (through a
ServiceRequest.status
set tosuspended
) self-treatment type ServiceRequest. This could specify an activity to perform a weight measurement or answering of a self-treatment related Questionnaire.
The trigger ServiceRequest references an ActivityDefinition which references the Library described below.
The Library has:
.type
set toautomated-processing
.parameter
.use
set toin
for input.type
set toQuestionnaireResponse
The Library rule sets examines the answers of the QuestionnaireResponse and, in case triggering is needed, sets up the instruction through the line ruleResult.setActivateSelfTreatment;
The automated processing reaction to a true parameter passed to setActivateSelfTreatment is described in Activation of suspended Self-treatment type ServiceRequest.
Calculation Type Library Resource Examples
A calculation type Library resource has a Library.type
set to logic-library
and its evaluation requires invocation of its evaluate
operation with input parameters as specified in the Library.
Library for Calculating Situation Quality
This Library and its rule is intended to qualify a measurement, typically submitted as an Observation or Media. Typically the associated Questionnaire poses questions relevant to the quality of that particular measurement, for instance whether a finger is warm (could be relevant for Pulse Oximeter measurement of oxygen saturation at index finger) or whether the patient is sitting or lying down. Prerequisite to submitting the Observation, the QuestionnaireResponse for the said Questionnaire would be passed as parameter to the evaluate
operation on the Library, returning one or more Coding in the SituationQuality. The returned Coding(s) would then be entered in Observation.ehealth-quality
.
The Library has:
.type
set tologic-library
.parameter[0]
.use
set toin
for input.type
set toQuestionnaireResponse
.parameter[1]
.use
set toout
for output.type
set toCodeableConcept
The Library rule sets examines the answers of the QuestionnaireResponse and determines the corresponding SituationQuality Coding(s).
Library for Calculating Usage Quality
The Library and rule for calculating Usage Quality is very similar to the Library for Calculating Situation Quality and is also intended to qualify a measurement, typically submitted as an Observation or Media. The difference is that the Questionnaire, which is the typical way to establish usage quality, poses questions relevant to the quality of how the involved Device (if any) was operated, for instance has the instructions for device use been followed.
Prerequisite to submitting the Observation, the QuestionnaireResponse for the said Questionnaire would be passed as parameter to the evaluate
operation on the Library, returning one or more Coding for UsageQuality. The returned Coding(s) would then be carried to Observation.ehealth-quality
.
The Library type, input and output are identical to that of Library for Calculating Situation Quality, and the rule differs in that the resulting Coding specifies UsageQuality.