But then you need a second language to define a function to calculate a simple 
score. Without it's possible to create tooling to help modelers write at least 
simple expressions. basic math and some simple 'if x is between 3 and 10, fill 
this field with this value' is entirely doable without manually writing 
expressions, even in the proposed syntax. And the more technically inclined 
modellers can do a lot more if the tooling helps them with choosing the right 
paths. Also functions will need to be reimplemented for every environment - 
doesn't sound like interoperability to me.

On the subject of the lists of values problem: Instead of binding outside the 
expression language, you could do something like assigning the value of a path 
to variables with a readable name as statements in the actual expression 
language. in combination with a for loop that can contain multiple statements, 
or at least variable assignments and one statement, it would solve these issues 
completely and still be readable to humans. and you can still write tooling to 
visualize the rules to non-technical people like we can now.

Also I consider the requirement to explicitly state the type of variables 
beforehand to be tricky. Tooling could solve it, but it's not something I can 
easily explain to less technical people.

An alternative could be to switch to something Turing complete, like JavaScript 
or typescript, to define a few included functions to lookup data and to 
interact with the data, and a defined data model to ensure interoperability. 
Much easier to specify and implement, although it will be harder/no longer 
possible to write tooling to visualize the code and harder to write tools that 
allow less-technical people to write code.

Regards,

Pieter Bos

Op 2 feb. 2019 14:16 schreef Ian McNicoll <i...@freshehr.com>:
Hi Pieter,

"But why would I need a function to calculate a score that is just a sum of a 
number of values, instead of a few +-operators?"

It is an open question but one advantage of using the function approach, with 
simple values is that it can encapsulate the algorithm without too much 
dependency on understanding openEHR paths or path -bindings. That should allow 
broader engagement with non-openEHR specialists.

My preference is to support use of openEHR datatypes within the expression 
(albeit perhaps in reduced format), as otherwise passing units etc as scalars 
starts to get cumbersome.

e.g


$apgar_heartrate, $apgar_breathing, $apgar_reflex, $apgar_muscle, $apgar_colour)

where each of these is actually an ordinal, rather than a scalar value.

Not such a good example but think of a BMI calc, where the units used for 
height and weight are critical

We can learn a lot from GDL experience in this regard.

Ian

Dr Ian McNicoll
mobile +44 (0)775 209 7859
office +44 (0)1536 414994
skype: ianmcnicoll
email: i...@freshehr.com<mailto:i...@freshehr.com>
twitter: @ianmcnicoll

[https://docs.google.com/uc?export=download&id=0BzLo3mNUvbAjUmNWaFZYZlZ5djg&revid=0BzLo3mNUvbAjRzZKc0JpUXl2SkRtMDJ0bkdUcUQxM2dqSVdrPQ]
Co-Chair, openEHR Foundation 
ian.mcnic...@openehr.org<mailto:ian.mcnic...@openehr.org>
Director, freshEHR Clinical Informatics Ltd.
Director, HANDIHealth CIC
Hon. Senior Research Associate, CHIME, UCL


On Fri, 1 Feb 2019 at 14:53, Pieter Bos 
<pieter....@nedap.com<mailto:pieter....@nedap.com>> wrote:
About the calculation:

Ah, I see, the assignment seems like a good solution. But why would I need a 
function to calculate a score that is just a sum of a number of values, instead 
of a few +-operators?


Multiplicities/data binding:

The there exists case is clear. However, what if I have four events, all having 
four elements, each with dv_quantity as value. Say I want the magnitude of the 
last of these quantities to be larger than the sum of the first three. Before I 
could write something like:

for_all $event in /data/events[id3]
     $event/data/items/element[id6]/value/magnitude >
        $event/data/items/element[id4]/value/magnitude +
        $event/data/items/element[id5]/value/magnitude +
        $event/data/items/element[id6]/value/magnitude

(I omitted a few node ids here that are not important for the example)
Not the most readable -  but it does the job. With data binding, how do I 
express this? There no longer seems to be a path lookup outside of data 
binding, so I can’t write:

for_all $event in $events
     $event/data/items/element[id6]/value/magnitude >
        $event/data/items/element[id4]/value/magnitude +
        $event/data/items/element[id5]/value/magnitude +
        $event/data/items/element[id6]/value/magnitude

And binding all the separate paths to variables doesn’t work either – they will 
be bound as lists, and there is no way to iterate over four lists of values at 
once.

Note that a path that points to a single typed dvquantity in an archetype can 
still point to many items in the RM if somewhere up the tree there is a list or 
a set, for example more than one observation. So if you really want them to be 
typed on validation time, you need to check every attribute in the path to see 
if it can point to more than one value, then either make it a 
List<List<Integer>> or define in which order to add it as a single list.
I implemented it by determining type at runtime, but it’s possible otherwise. 
This means that very often you need a for all statement, in which case data 
binding doesn’t really help. I defined some tricks with the basic operators 
also working on equally sized lists to make things a bit easier to understand 
for modelers. That’s why I asked about the execution rules. The tricks I did 
can be easily rewritten into for_all statements if we need to have them removed.

This leads to more interesting cases when you flatten rules to an OPT 2 
template, to obtain a single artifact that can be used for many things, 
including rule evaluation. That is very doable right now by prepending some 
paths and adding some for_all statements. I’m not sure how to do that with data 
binding.

Regards,


Pieter Bos

From: openEHR-technical 
<openehr-technical-boun...@lists.openehr.org<mailto:openehr-technical-boun...@lists.openehr.org>>
 on behalf of Thomas Beale 
<thomas.be...@openehr.org<mailto:thomas.be...@openehr.org>>
Reply-To: For openEHR technical discussions 
<openehr-technical@lists.openehr.org<mailto:openehr-technical@lists.openehr.org>>
Date: Friday, 1 February 2019 at 14:16
To: 
"openehr-technical@lists.openehr.org<mailto:openehr-technical@lists.openehr.org>"
 
<openehr-technical@lists.openehr.org<mailto:openehr-technical@lists.openehr.org>>
Subject: Re: Rules in archetypes - what are the requirements?


Thanks Pieter,

this is very useful.
On 01/02/2019 12:54, Pieter Bos wrote:
For us the main requirement of the rules is to calculate the value of other 
fields based on other fields. Only the checking of assertions has relatively 
little added value for the use cases our customers encounter. I would find it 
very hard to explain to any users or modelers that they can write checks that 
do the actual score calculation, but that they cannot actually use the 
calculated value anywhere. So we ignore this limitation altogether.

the obvious solution to that requirement seems to be to a) use functions and b) 
to allow assignment:

rules
    -- assert that manually set total is correct
    check $apgar_total_value == apgar_total ($apgar_heartrate_value, 
$apgar_breathing_value, $apgar_reflex_value, $apgar_muscle_value, 
$apgar_colour_value)



rules
    -- assign total value
    $apgar_total_value = apgar_total ($apgar_heartrate_value, 
$apgar_breathing_value, $apgar_reflex_value, $apgar_muscle_value, 
$apgar_colour_value)



Also the value binding seems to have an case that has not been covered:


it is possible that a single path lookup results in a list of values. This 
means a single path-bound variable will contain multiple values (so a list of 
values). In the old case, you could handle this with a for_all statement to 
express that the assertion should be valid within the scope of a single event, 
for all events. How could value binding solve this? The same question applies 
to output variable binding as well as input variable binding.

conceptually, rules statements are typed, so in this case, the type will be 
List<Real> or List<DvQuantity> or whatever. In that case, expressions need to 
treat it in the normal way, i.e. with List or Set operators that obtain single 
values. E.g.

$systolic_bp_samples: List<Real>

there_exists v in $systolic_bp_samples : v > Systolic_bp_threshold implies ....

These kinds of things (and for_all) are documented in the Expression Language 
draft<https://specifications.openehr.org/releases/LANG/latest/expression_language.html#_collection_operators>.

Related to this, both the current and proposed specification is missing 
execution rules, especially when paths lookup to a list of values instead of a 
single variable and how to handle that. For example what does the following 
mean when /data/events/data/items/element[id3]/value/magnitude resolves to more 
than one value?

I don't see how it can, since that path is defined to be of type Real (not 
List<Real> or Set<Real> etc) by the RM definition of DvQuantity. But I'm 
probably missing something in the sense of your question...

Anyway, the more I can find out about current requirements, working solutions, 
workaround etc, the better - the intention is to evolve the expression facility 
in archetypes to match those needs and to be as useful as possible.

- thomas


_______________________________________________
openEHR-technical mailing list
openEHR-technical@lists.openehr.org<mailto:openEHR-technical@lists.openehr.org>
http://lists.openehr.org/mailman/listinfo/openehr-technical_lists.openehr.org
_______________________________________________
openEHR-technical mailing list
openEHR-technical@lists.openehr.org
http://lists.openehr.org/mailman/listinfo/openehr-technical_lists.openehr.org

Reply via email to