Poster presented at the 13th International Congress on Medical Informatics - MEDINFO - in 2010.
See: http://www.mlhim.org http://gplus.to/MLHIM and http://gplus.to/MLHIMComm for more information about semantic interoperability in healthcare.
#mlhim #semantic_interoperability #health_informatics
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
Poster MEDINFO 2010
1. Forward Chaining Inference vs. Binary Decision Support in an Electronic
Health Record Application Based on Archetyped Data
Luciana Tricai Cavalini , Sergio Miranda Freire , Timothy Wayne Cook
a b c
Departament of Epidemiology and Biostatistics, Fluminense Federal University, Brazil
a
b
Medical Sciences College, Rio de Janeiro State University, Brazil
c
National Institute of Science and Technology – Medicine Assisted by Scientific Computing, Brazil
The purpose of this poster is to investigate the effects of two common approaches to decision support in electronic health
record applications. The uniqueness is that this electronic health record uses archetyped data based on the multi-level
modeling principles initially described in the openEHR specifications which were foundational to the formation of the ISO and
CEN 13606 Eletronic Health Record standards.
The objectives were to determine the best approach to decision support development and maintenance in a small purpose
specific application and to also provide an open source platform for the rapid construction of interoperable, purpose
specific healthcare applications and tools using robust, modern technologies including web services connectivity,
programming language and persistence layer agnostic specifications and internationalization and localization for global
application reuse-ability especially applicable to the world of non-governmental agencies working in developing nations
where the areas of meaningful use and measurement and evaluation can be a great challenge.
Introduction
The typical SQL data model approach to health care application design and development is well documented to cause
interoperability and ongoing software maintenance issues. The information model approach; using a generic reference
model built in software with single concept knowledge components represented as runtime, semantically contextual data
containers, provide a mechanism of ex-changing information between systems based on the same reference model but
that may not have necessarily had the purpose when created. The demonstration application will be available as part of
the Open Source Health Information Platform (OSHIP) Project.
Methods
We created a demonstration application using OSHIP since it is a full application server based on the openEHR specifications
and includes the C Language Inference Processing System (CLIPS) forward chaining RETE algorithm based engine. The
application was designed as a blood pressure registry system. The use case scenario was to monitor the self reported blood
pressure readings from a small town population of patients considered at risk for hypertension.
The initial testing methods used hand entered data and application timing routines to measure the performance differences
in detecting the “at risk” characteristics at each patient entry, across each patient's history and across the population.
Results
The preliminary results show that the CLIPS rules syntax had a higher learning curve initially. But that was short lived and it
was quickly found that creating the CLIPS rules in the Python language was less error prone and more rapidly performed
than using the normal if/then constructs. The code size for the same number of decision points is approximately 40% less
using CLIPS rules and execution time with 100 patient entries is 10 times faster in the CLIPS portion of the code.
A robust functional testing suite that will produce automated testing data to bring the numbers of patients and entries per
patient into the tens of thousands will be used for the demonstration.
# Hep B # Build the rules
if self.hepatitisB == 0: # any age ageRule = clips.BuildRule("age-rule", "(immunizations (age ?x&:(< 180 ?x)))", "(assert (too_old))", "The age Limit Rule.")
self.resultstxt += "<li>Needs Hepatitis B #1</li> " hepatitisB1Rule = clips.BuildRule("hepatitisB1-rule", "(immunizations (HepB ?x&:(= 0 ?x)))", "(assert (hepatitisB1))", "The HepatitisB Dose #1 Rule")
elif self.hepatitisB == 1 and self.age >= 30: hepatitisB2Rule = clips.BuildRule("hepatitisB2-rule", "(immunizations (HepB ?x&:(= 1 ?x)) (age ?y&:(<= 30 ?y)))", "(assert (hepatitisB2))","The HepatitisB
self.resultstxt += "<li>Needs Hepatitis B #2</li> " Dose #2 Rule")
elif self.hepatitisB == 2 and self.age >= 120: hepatitisB3Rule = clips.BuildRule("hepatitisB3-rule", "(immunizations (HepB ?x&:(= 2 ?x)) (age ?y&:(<= 120 ?y)))", "(assert (hepatitisB3))","The HepatitisB
self.resultstxt += "<li>Needs Hepatitis B #3</li> " Dose #3 Rule")
tetra1Rule = clips.BuildRule("tetra1-rule", "(immunizations (tetra ?x&:(= 0 ?x)) (age ?y&:(<= 60 ?y)))", "(assert (tetra1))","The tetra Dose #1 Rule")
Code in
# tetravalent (DTP+Hib) tetra2Rule = clips.BuildRule("tetra2-rule", "(immunizations (tetra ?x&:(= 1 ?x)) (age ?y&:(<= 120 ?y)))", "(assert (tetra2))","The tetra Dose #2 Rule")
if self.age >= 60: tetra3Rule = clips.BuildRule("tetra3-rule", "(immunizations (tetra ?x&:(= 2 ?x)) (age ?y&:(= 180 ?y)))", "(assert (tetra3))","The tetra Dose #3 Rule")
if self.tetravalent == 0: polio1Rule = clips.BuildRule("polio1-rule", "(immunizations (polio ?x&:(= 0 ?x)) (age ?y&:(<= 60 ?y)))", "(assert (polio1))","The polio Dose #1 Rule")
self.resultstxt += "<li>Needs Tetravalent (DTP+Hib) Dose #1</li> " polio2Rule = clips.BuildRule("polio2-rule", "(immunizations (polio ?x&:(= 1 ?x)) (age ?y&:(<= 120 ?y)))", "(assert (polio2))","The polio Dose #2 Rule")
elif self.tetravalent == 1 and self.age >= 120: polio3Rule = clips.BuildRule("polio3-rule", "(immunizations (polio ?x&:(= 2 ?x)) (age ?y&:(= 180 ?y)))", "(assert (polio3))","The polio Dose #3 Rule")
Boolean
self.resultstxt += "<li>Needs Tetravalent (DTP+Hib) Dose #2</li> " rota1Rule = clips.BuildRule("rota1-rule", "(immunizations (rota ?x&:(= 0 ?x)) (age ?y&:(<= 60 ?y)))", "(assert (rota1))","The rotavirus Dose #1 Rule")
elif self.tetravalent == 2 and self.age == 180: rota2Rule = clips.BuildRule("rota2-rule", "(immunizations (rota ?x&:(= 1 ?x)) (age ?y&:(<= 90 ?y)))", "(assert (rota2))","The rotavirus Dose #2 Rule")
self.resultstxt += "<li>Needs Tetravalent (DTP+Hib) Dose #3</li> "
# polio
expressions
if self.age >= 60:
if self.polio == 0:
Code in PyCLIPS
self.resultstxt += "<li>Needs Polio Dose #1</li> "
elif self.polio == 1 and self.age >= 120:
self.resultstxt += "<li>Needs Polio Dose #2</li> "
elif self.polio == 2 and self.age == 180:
self.resultstxt += "<li>Needs Polio Dose #3</li> "
# rotavirus
if self.age >= 60:
if self.rotavirus == 0:
self.resultstxt += "<li>Needs Rotavirus Dose #1</li> "
elif self.rotavirus == 1 and self.age >= 90:
self.resultstxt += "<li>Needs Rotavirus Dose #2</li> "
Visit us at http://www.mlhim.org