Versions Compared

Key

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

...

Except for the Fallback Library, evaluation of an automated processing type Library requires that a measurement has been submitted and that the ProcedureRequest 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 implicit use in case no other automated processing type library has been set up for a given ProcedureRequest through its ActivityDefinition.

The Library has:

...

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 to automated-processing

  • .parameter

    • .use set to in for input

    • .type set to Observation

...

  • a Task with:

    • .category set to MeasurementForAssessment (a Coding signifying a measurement should be assessed/evaluated)

    • .priority set to:

    a Task with:

    • .category set to MeasurementForAssessment (a Coding signifying a measurement should be assessed/evaluated)

    • .priority set to:

      • routine when the Observation.value is within reference range

      • urgent when the Observation.value is outside a “Yellow Alarm” type reference range (if defined) but within a “Red Alarm” type reference range (if defined)

      • asap when the Observation.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 assessed
      • routine when the Observation.value is within reference range

    • .description set to “Måling til vurdering” which is Danish for measurement to be assessed

    • further elements set as described in Output from automated processing

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 ProcedureRequest associated with the ActivityDefinition.

The Library has:

  • .type set to automated-processing

  • .parameter

    • .use set to in for input

    • .type set to Observation

The Library rule sets up instructions that causes production of a:

      • urgent when the Observation.value is outside a “Yellow Alarm” type reference range (if defined) but within a “Red Alarm” type reference range (if defined)

      • asap when the Observation.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 assessed

    • further elements set as described in Output from automated processing

  • a ClinicalImpression with:

    • .code set to TriagingResult

    • .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 measurement

    • further elements set as described in Output from automated processing

  • a ClinicalImpression with:

  • .code set to TriagingResult

  • .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 measurement

    Communication (of ehealth-message profile) provided that the Task.priority is not routine (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 to MeasurementForAssessment

    • .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

  • a Communication (of ehealth-message profile) provided that the Task.priority is not routine (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 to MeasurementForAssessment

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

...

The Library rule (in Library.content.data) is :

Code Block
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;

...

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 ProcedureRequest 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 ProcedureRequestServiceRequest, say, specifying measuring and questionnaire answering activities (this is typical content but irrelevant for activation of the self-treatment activity).

  • an active ProcedureRequestServiceRequest, here denoted the trigger ProcedureRequestServiceRequest, specifying answering of the Questionnaire that triggers the self-treatment activity

  • an inactive (through a ProcedureRequestServiceRequest.status set to suspended) self-treatment type ProcedureRequestServiceRequest. This could specify an activity to perform a weight measurement or answering of a self-treatment related Questionnaire.

The trigger ProcedureRequest ServiceRequest references an ActivityDefinition which references the Library described below.

...

Expand
titleSelf-Treatment ProcedureRequest ServiceRequest Activation Rule Content
Code Block
package rules
import org.hl7.fhir.dstu3.model.QuestionnaireResponse
// Further imports omitted for brevity

global com.systematic.ehealth.automatedprocessing.AutomatedProcessingDTO ruleResult

rule "SelfTreatmentProcedureRequestActivationRuleSelfTreatmentServiceRequestActivationRule"

dialect "java"

when
   $questionnaireResponses : Collection()
   $listQrs : ArrayList() from collect (QuestionnaireResponse() from $questionnaireResponses)
then
   QuestionnaireResponse qr = (QuestionnaireResponse)$listQrs.get(0);
   boolean activate = false;
   
   // QuestionnaireResponse examined (omitted), activate set to true when needed
   
   ruleResult.setActivateSelfTreatment(activate);
end

The automated processing reaction to a true parameter passed to setActivateSelfTreatment is described in Activation of suspended Self-treatment type ProcedureRequestServiceRequest.

Calculation Type Library Resource Examples

...

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.

Library for Calculating Body Mass Index

The Library for calculating the body mass index (BMI) is intended for providing an Observation with the BMI which can defined as an ActivityDefinition with associated reference ranges. Given an Observation of height and an Observation of weight as parameters, the evaluate operation returns a Quantity which can be set as the BMI Observation’s Observation.valueQuantity.

The Library has:

  • .type set to logic-library

  • .parameter[0]

    • .use set to in for input

    • .type set to Observation

  • .parameter[1]

    • .use set to in for input

    • .type set to Observation

  • .parameter[2]

    • .use set to out for output

    • .type set to Quantity

Expand

titleBMI Calculation Rule
Code Blockpackage rules import org.hl7.fhir.dstu3.model.Observation // additional imports omitted for brevity global org.hl7.fhir.dstu3.model.Quantity ruleResult function CodingDTO getWeightObservationCode() { return new CodingDTO("urn:oid:1.2.208.176.2.1", "NPU03804", "Pt—Legeme; masse = ? kg"); } function CodingDTO getHeightObservationCode() { return new CodingDTO("urn:oid:1.2.208.176.2.1", "NPU03794", "Pt—Legeme; højde = ? m"); } function Quantity getWeight(Collection observations) { for (Object o: observations) { Observation observation = (Observation)o; if (getWeightObservationCode().getCode.equals(observation.getCode()) && getWeightObservationCode().getSystem().equals(observation.getSystem())) { return (Quantity)observation.getValue(); } } return null; } function Quantity getHeight(Collection observations) { for (Object o: observations) { Observation observation = (Observation)o; if (getHeightObservationCode().getCode.equals(observation.getCode()) && getHeightObservationCode().getSystem().equals(observation.getSystem())) { return (Quantity)observation.getValue(); } } return null; } rule "BodyMassIndexCalculationRule" dialect "java" when $observations: Collection() then Quantity weightQuantity = getWeight($observations); Quantity heightQuantity = getHeight($observations); // Compute BMI BigDecimal squareHeight = heightQuantity.getValue().multiply(heightQuantity.getValue()); BigDecimal bmi = weightQuantity.divide(squareHeight, 2, RoundingMode.HALF_UP); ruleResult.setValue(bmi); ruleResult.setCode("kg/m2"); ruleResult.setSystem("http://unitsofmeasure.org"); ruleResult.setUnit("kg/m2"); end;