Title: advanced MEL programming
1advanced MEL programming
- David A. Nelsen, Jr., MD, MS
- Asst Medical Director for Clinical Informatics
- University of Arkansas for Medical Sciences
- Associate Professor
- Dept of Family Preventive Medicine
2Levels of Facility
- Beginner-minor modifications of text
translations, data symbols in a data display - Intermediate-custom text translations,
calculations in a set value, custom data
displays, straightforward fn - Advanced-complex functions, externalized content,
watchers, pushes eg mel_add_order()
3Why advanced MEL?
- Complex custom text translations
- Complex numeric operations
- Complex string manipulations
- Externalized content
- External processes
4How do I get to know MEL better
- Take a class
- Learn by example
- Learn by mistake
- MEL trace
- Just do it
5Objectives of this talk
- Pearls
- Shortcuts
- Arrays complex list management
- Data_symbols(delimited)
- !Watchers
6Whats in a form?
- Files
- .efm, .ef2, .ef3
- .xlt
- .xlw
PEARL 1 http//www.baxbex.com/openexpert.html
7.EFM
8.XLT
9.XLT
10.XLT
11.XLW
12Other Files
13MEL trace
- Ctrl-alt-m turns on off
- PEARL-drag shortcut to desktop
- Tells you exactly what your MEL is doing, step by
step - Only way to troubleshoot problem MEL code
- Great way to learn
14Problem 1
No Comment
- I do not like the
- Prob_List_Changes(full)
- Data symbol
No reason for removal
Added new problem of RUQ PAIN (ICD-789.01) Removed
problem of BRONCHITIS, ACUTE (ICD- 466.0) Removed
problem of DIABETES MELLITUS, CONTROLLED
(ICD-250.00) Assessed NICOTINE ADDICTION as
comment only - quit date set
Dont like the wording
15Solution
fn dn_filter_prob_list_output() If
PROB_LIST_CHANGES('delimited')"" then return ""
else "" endif local prob_arrgetfield(PROB_LIST_C
HANGES('delimited'),"", "") local n,
status_modifier, stop_reason, result_string"",
msize(prob_arr) for n1, nltm, nn1 do
prob_arrngetfield(prob_arrn,"","") endfor
ADDDx ofRUQ PAINICD-789.01Note previous open
chole10/05/2006UNSIGNEDREMOVEDx
ofBRONCHITIS, ACUTEICD-466.010/05/200610/05/2
006SUNSIGNEDREMOVEDx ofDIABETES
MELLITUS, BORDERLINE, CONTROLLEDICD-250.0010/05
/200610/05/2006TUNSIGNEDASSESSDx
ofNICOTINE ADDICTIONICD-305.104/25/2003C
UNSIGNEDquit date set
16GETFIELD
- description
- Turns a string into an array of substrings.
- syntax
- getfield(string, delims ,white)
17What is an array?
- An array is an ordered list
- global my_arrayarray("cat,dog,fish,spider")
- my_array1 returns "cat"
- my_array2 returns "dog"
- and so on
18Solution
prob_arr1"ADDDx ofRUQ PAINICD-789.01Note
previous open chole10/05/2006UNSIGNED"
prob_arr2"REMOVEDx ofBRONCHITIS,
ACUTEICD-466.010/05/200610/05/2006SUNSI
GNED" And so on.....
fn dn_filter_prob_list_output() If
PROB_LIST_CHANGES('delimited')"" then return ""
else "" endif local prob_arrgetfield(PROB_LIST_C
HANGES('delim'),"", "") local n,
status_modifier, stop_reason, result_string"",
msize(prob_arr) for n1, nltm, nn1 do
prob_arrngetfield(prob_arrn,"","") endfor
19Solution
fn dn_filter_prob_list_output() If
PROB_LIST_CHANGES('delimited')"" then return ""
else "" endif local prob_arrgetfield(PROB_LIST_CH
ANGES('delim'),"", "") local n,
status_modifier, stop_reason, result_string"",
msize(prob_arr) for n1, nltm, nn1 do
prob_arrngetfield(prob_arrn,"","") endfor
20Solution
fn dn_filter_prob_list_output() If
PROB_LIST_CHANGES('delimited')"" then return ""
else "" endif local prob_arrgetfield(PROB_LIST_CH
ANGES('delim'),"", "") local n,
status_modifier, stop_reason, result_string"",
msize(prob_arr) for n1, nltm, nn1 do
prob_arrngetfield(prob_arrn,"","") endfor
21Solution
prob_arr11"ADD" prob_arr12"Dx
of" prob_arr13"RUQ PAIN" prob_arr14"ICD-
789.01" prob_arr15"Note previous open chole
" prob_arr16"10/05/2006" ...and so on...
prob_arr21"REMOVE" prob_arr22"Dx
of" prob_arr23" BRONCHITIS,
ACUTE" prob_arr24" ICD-466.0
" prob_arr25"" prob_arr26"10/05/2006" ..
.and so on...
...... for n1, nltm, nn1 do
prob_arrngetfield(prob_arrn,"","") endfor
The "do" loop starts with n1 SO first thing I do
is turn prob_arr1 in to "sub" array
22So now we have the "2-D" array
1
2
3
4
5
6
7
14
15
.......
my_array1
my_array2
my_array3
my_array4
so my_array34"ICD-250.00" OR
my_array415" quit date set"
23Next we 'rebuild' our result
for n1, nltm, nn1 do
for n1, nltm, nn1 do cond case
prob_arrn9"N" status_modifier"New"
case prob_arrn9"W" status_modifier"Worsenin
g" case prob_arrn9"S"
status_modifier"Unchanged" case
prob_arrn9"B" status_modifier"Improving"
else status_modifier"" endcond
cond case prob_arrn8"S" stop_reason"
Resolved" case prob_arrn8"W"
stop_reason" Inactive" case
prob_arrn8"O" stop_reason" Ruled Out"
case prob_arrn8"T" stop_reason"a
duplicate or correction" else
stop_reason"" endcond cond case
prob_arrn1"ADD" result_stringresult_string
hret str(n) ") Added Diagnosis of "
prob_arrn3 "gt" prob_arrn4 if
status_modifier"" then "" else " with status of
" status_modifier ". " endif if
prob_arrn5 "" then "" else " COMMENT "
prob_arrn5 endif case prob_arrn1"AS
SESS" result_stringresult_string hret str(n)
") Assessed Diagnosis of " prob_arrn3
"gt" prob_arrn4 if status_modifier""
then "" else " with status of " status_modifier
". " endif if prob_arrn15 "" then ""
else " COMMENT " prob_arrn15 endif
case prob_arrn1"REMOVE" result_stringresult
_string hret str(n) ") Removed Problem of "
prob_arrn3 "gt" prob_arrn4 if
stop_reason"" then "" else ". Problem removed
as " stop_reason "." endif if
prob_arrn5 "" then "" else " COMMENT "
prob_arrn5 endif case
prob_arrn1"CHANGE" result_stringresult_stri
ng hret str(n) ") Diagnosis of "
prob_arrn11 "gt" prob_arrn12 " was
changed to " prob_arrn3 "gt"
prob_arrn4 if prob_arrn5 "" then ""
else " COMMENT " prob_arrn5 endif else
"" endcond endfor
case prob_arrn1"ASSESS" result_stringresult
_string hret str(n) ") Assessed Diagnosis
of " prob_arrn3 "gt" prob_arrn4
if status_modifier"" then "" else " with status
of " status_modifier ". " endif if
prob_arrn15 "" then "" else " COMMENT "
prob_arrn15 endif
case prob_arrn1"ADD" result_stringresult_st
ring hret str(n) ") Added Diagnosis of "
prob_arrn3 "gt" prob_arrn4 if
status_modifier"" then "" else " with status of
" status_modifier ". " endif if
prob_arrn5 "" then "" else " COMMENT "
prob_arrn5 endif
cond case prob_arrn9"N"
status_modifier"New" case
prob_arrn9"W" status_modifier"Worsening"
case prob_arrn9"S" status_modifier"Uncha
nged" case prob_arrn9"B"
status_modifier"Improving" else
status_modifier"" endcond
cond case prob_arrn8"S" stop_reason"
Resolved" case prob_arrn8"W"
stop_reason" Inactive" case
prob_arrn8"O" stop_reason" Ruled Out"
case prob_arrn8"T" stop_reason"a
duplicate or correction" else
stop_reason"" endcond
24Now we return the result of our manipulation
- fn dn_filter...
- return result_string
- AND dn_filter_prob_list_output()
- becomes
- 1) Added Diagnosis of RUQ PAINgtICD-789.01
COMMENT Note previous open chole - 2) Removed Problem of BRONCHITIS,
ACUTEgtICD-466.0. Problem removed as Resolved. - 3) Removed Problem of DIABETES MELLITUS,
BORDERLINE, CONTROLLEDgtICD-250.00. Problem
removed as a duplicate or correction. - 4) Assessed Diagnosis of NICOTINE
ADDICTIONgtICD-305.1 COMMENT quit date set
25Where can I use this?
- Put it in a problem/assessment form
- Put it in your usrlib.txt
- Make it a text component that you can call with
quicktext - Put it in a letter
26Another cool array example
- global gbl_meds_for_drpdwndn_medsforlist(
MEDS_AFTER('delimited') ) "" - fn dn_medsforlist(meds)
- if meds"" then return "No meds are listed for
this patient" else "" endif - local medarrgetfield(meds,"",",")
- local j,k,resultstring""
- for k1,kltsize(medarr),kk1
- do
- medarrkgetfield(medarrk,"","")
- endfor
- for j1,jltsize(medarr),jj1
- do
- resultstringresultstring ","
medarrj1 " " medarrj7 - endfor
- if size(resultstring)gt1998 then
resultstringremove(resultstring,1960) ",LIST
TRUNCATED-TOO LONG TO DISPLAY" else "" endif - return resultstring
By placing an argument in the function it will
refresh if the argument changes value
27Watchers
- A watcher is NOT a British gentleman who educates
beautiful young female vampire slayers. - A watcher is a 'trigger' that will cause certain
doc temps and/or obs to refresh. - A ! ... will force a MEL statement to be
registered as a watcher
global gbl_meds_for_drpdwn dn_medsforlist(MEDS
_AFTER('delimited')) "" ! global
gbl_meds_for_drpdwn dn_medsforlist(MEDS_AFTER('
delimited')) ""
28Watchers
- DOCUMENT variables are registered
- OBS() variables are registered
- if something changes the value of one of these,
any expression containing the variable is
refreshed - EXCEPT if it's hidden in a function
- well, sometimes
29Watchers
- Example
- document.mine1
- my_fn(document.mine2,document.mine3)
- if either document.mine2 or 3 changes then
document.mine1 is re-evaluated
30Watcher/not watcher example
- global my_varmy_fn(document.tmp1)
- fn my_fn(my_local_var)
- ......
- global my_varmy_fn()
- fn my_fn()
- local my_local_vardocument.tmp1
- ......
31Watcher Example--BMI autocalculation
Let's check this one out in EFE
32Spirometry II
- Medical Algorithms Project
- www.medal.org
- Kathy Trahan-Panther Creek
- Knowledge Bank
33Spirometry II
34"Custom" doctemps in EFE
- VFE does this for you
- "Initialize" the custom doctemp
- ?should I use a global var instead?
35"Custom" doctemps in EFE
- "XLT Holder"
- 2 pixels high light gray text
- DON'T REMAKE TRANSLATIONS
- my favorite syntax
- if document.dn_md_dropdown"" then
document.dn_md_dropdown"none" "" else "" endif
36- http//www.uams.edu/dfcm/Informatics/CHUG_2006.htm
- Â