Expert form
Synopsis
Form for expert training.
Route URL
#/expert
Old form in legacy FMX application
expert2.pas in the old application.
GUI
On form start, execute action Initialize
General layout
- Top of form
- Radio group (name: grpSelectData) with items:
- name: rbGeneralData text: "General data"
- name: rbAnamnese text: "Anamnese"
- name: rbImagery text: "Beeldvorming"
- name: rbPhysResearch text: "Fysisch onderzoek"
- name: rbLab text: "Laboratorium"
- name: rbAll Text: "Alles" On change: Execute SelectData action.
- label lblTitle: 'Kabisa EXPERT'
- Radio group (name: grpSelectData) with items:
- Vertical Centered : 3 columns, see below
- Bottom of form, row 1: Button array:
- name: btnClusters, label: 'Clusters', execute action ShowClusters.
- name: btnLecture, label: 'Les' execute action ShowLecture.
- name: btnGraphic, label: 'Graphic', execute action ShowGraphic.
- name: btnRemoveLast, label: 'Remove last arg', execute action RemoveLastArg.
- Name: btnPowertable, label: 'Powertable' execute action TogglePowerTable.
- Bottom of form, row 2: buttons:
Column 1
- Grid (name: grdSymptoms) 1 column: symptom name.
- On dubbelclick: execute SelectSymptom action.
- On keydown: execute FilterSymptom action.
- label "lblSearchValue", text initially empty.
- label "lblSearchHint", text "Type some letters for quick searching"
Column 2
- Arrow green. On click, execute SelectSymptom action with parameter Present equal to True.
- Arrow red. On click, execute SelectSymptom action with parameter Present equal to False.
- Grid (name: grdSelectedSymptoms) 1 column.
- label "lblAdding", text "quick adding", initially hidden.
Column 3
- Grid (name: grdDiagnoses), 2 columns.
- Column 1: probability.
- Column 2: Diagnosis name.
Actions
-
All data types and data structures in this form are used in the exact same way in Consultation. For this reason, all variables and data types must be defined in a separate unit: Units.Simulation, in a class TSimulation.
-
Define the following types:
Type TDatatype = (dtGeneral,dtAnamnese,dtImagery,dtPhysReseach,dtLab,dtAll,dtDiagnose); TSelectedSymptom = Class(TObject) diagnose: TDiagnose; // only used for nurse in consultation with *diagnose selected symptom: TSymptom; // Used in all other cases? isPresent: boolean; end; TSelectedSymptomArray = array of TSelectedSymptom; TProbability = Record diagnose : TDiagnosis; Association : TAssociation; pro : array[1..64] of double; lp : array[1..64] of double; temp_lp : double; temp_new : double; sens : Double; end; TProbabilityArray : Array of TProbability; TPowerTableItem = record diagnose : TDiagnosis; // ZIEKE, NRZ procent : double; // espr1 cutoff : double; Symptom: TSymptom; // SYMPE, NRS PC : Integer; PE : Integer; pwText : string; Prev : Integer; maxPCPE : Double; BitmapID : Integer; end; TPowerTable = array of TPowerTableItem;
Initialize
- Translate form
- Set a string searchterm to empty string.
-
Initialize 2 boolean form variables :
nonpresscanty:=False; nonpressplusplus:=False; -
Initialize empty selectedSymptoms : TSelectedSymptomArray, object has the following fields
- text Synonym text in selected language.
- symptom of type object Symptom
- isPresent of type boolean.
- Execute Restart action
- Execute SelectData action
SelectData
- initialize datatype value from grpSelectData radiogroup.
- Initialize an array displayedsynonyms containing all synonyms for Symptoms for which
- the property expand equals False
- the ttype property matches:
- dtGeneral :
ttype<2 or ttype>5 - dtAnamnese :
ttype=2 - dtImagery :
ttype=5 - dtPhysReseach :
ttype=3 - dtLab :
ttype=4 - dtAll :
ttype>=4The synonyms are are ordered on synonym.sortnr (a reference to the symtom ID must be kept)
- dtGeneral :
- Reset the searchterm string to empty.
- In grid grdSymptoms, show the array of displayedsynonyms.text, ordered by
sortNr.lang. - Make btnRemoveLast visible.
SelectSymptom
- Has a parameter Present of type boolean.
- if there are 58 symptoms in selectedSymptoms array, show a message
exit action.
Too many arguments - Determine symptom from selected row in grid grdSymptoms.
- If the selected symptom is already in the selectedSymptoms array, show a message (string 438)
exit action.
Argument already in list - if the selected symptom is in the excludes of one of the symptoms of in the selectedSymptoms array, show a message:
exit the action.
[mesexcl] {excl.name} [mesexc2] symptom.name [mesexc3] - if the selected symptom is in the implies of one of the symptoms of in the selectedSymptoms array, show a message:
exit the action.
[mesimpl] {excl.symptom.name} [mesimpl2] symptom.name - add selected symptom in to selectedSymptoms array:
- symptom equal to selected symptom.
- isPresent equal to action parameter present
- Display symptoms from selectedSymptoms in grdSelectedSymptoms
- Calculate diagnosis probabilities as in CalculateProbabilities, passing the symptom and Not IsPresent as parameters .
- Let symCount equal number of elements in the selectedSymptoms array
- In grid grdDiagnoses, show the probability records with Pro[symCount] > -2
- In column 1 : 100*Procent(Pro[symCount])
- In Column 2 : Diagnose.Name.Lang order by descending Pro[symCount]
FilterSymptom
- Add pressed key to searchterm (or remove last char, depending on key)
- if the search term is empty, show all records
- Filter the array displayedsynonyms so that
- Only records that contain the search term (case insensitive) are shown.
- Sort on position of the match in the search term.
- In grid cell, display matched substring in red.
- Show the filtered list in grid grdSymptoms,
ShowLecture
- Make sure form state is preserved.
- go to route /lecture/return/export
ShowCluster
- Make sure form state is preserved.
- go to route /cluster/return/export
ShowGraphic
- Show Graphic modal dialog using the selected symptoms and probabilities:
- probabilities
- selectedsymptoms.
RemoveLastArg
- set symCount equal to count of elements in selectedsymptoms
- in Probabilities array, set pl[symCount] and prob[symcount] to zero for all records.
- Remove last added element from selectedsymptoms
- set symCount equal to count of elements in selectedsymptoms (should be previous value -1)
- If the symCount is zero, then
- Disable btnRemoveLast
- Disable btnRestart
- Disable btnPowertable
- Make lblAdding invisible
- Make lblSearchHint visible.
- Redisplay grid grdDiagnoses, show the probability records with Prob[symCount] > -2
- In column 1 : 100*Procent(Prob[symCount])
- In Column 2 : Diagnose.Name.Lang order by descending Prob[symCount]
TogglePowerTable
-
When the powertable is visible:
- make it invisible
- set caption of btnPowertable to 'Show powertable'
-
If the powertable is not visible,
- Execute CalculatePowertable
- Show powertable with items:
- Column 1 : Diagnosis.Name.CONTINENT
- Column 2 : Symptom.Name.CONTINENT
- Column 3 : PC
- Column 4 : PE
- Column 5 : Bitmap according to bitmap ID.
Restart
- Clear list of selected symptoms.
- Set datatype = dtGeneral
- Radio button rbGeneralData is checked.
- Initialize Probabilities array of type TProbabilityArray:
For each Diagnosis with
Diagnosis.PC.cont<>0, add a record with- Pro[1]:=Log(Diagnosis.PC.continent/Sum[Diagnosis.PC.continent])
- All other PRO[] elements zero
- All PL[] elements zero
- Disable btnRemoveLast
- Clear searchterm.
- focus on *grdSymptoms
Exit
Navigate to menu
CalculateProbabilities
- Parameter aSymptom : TSymptom.
- Parameter IsExclude : Boolean
- Parameter DoShowMessage : Boolean
- Parameter MultipleSyms : Boolean
- let symcount be the number of elements in selectedSymptoms.
- For symptom 26 and continent 'Travel', set alarm equal to true, in all other cases alarm equals symptom.alarm.
- let factor be equal to symptom.comune.CONTINENT
- for every record in Probabilities:
- Set Association to the TAssociation record associated with the selected aSymptom and the record's Diagnose. If there is no such record, set to Nil.
- if Association is assigned, set sens to Association.Sens, else set sens to 0
- For all elements in Probabilities:
- If Association is empty, let
prob[symcount+1] =-13 - if Association is non-empty let prob[symcount+1] equal prob[symcount];
- If Association is empty, let
- Let p1 equal the sum of all
Pro[symcount]amounts from Probabilities, where Association is assigned. - Let sompr equal the sum of all
Pro[symcount]*sensamounts from Probabilities, where Association is assigned. - For each element in Probabilities, where association is assigned:
- Let
prev_old:=percent(prob[symcount]); - calculate temp variable Falsi:
FALSI:=(sompr- sens*prev_old+(1-p1)*fatcom)/(1-prev_old), if Falsi<=0 then FALSI=0.00001; - calculate 2 values, stored in the TProbability record
If not isExclude then begin afract:=sens/falsi; temp_lp := LG10(fract); temp_new := prob[symcount]+LG10(fract); end else begin acalcsens:=sens; if (aSymptom.id=27) and nonpresscanty then aCalcsens:=0.95 else if (aSymptom.id=117) and nonpressplusplus then aCalcsens:=0.81; afract:=(1-falsi)/(1-acalcsens); temp_lp := LG10(fract); temp_new := prob[symcount]-LG10(fract); end
- Let
- is MultipleSyms is true then call HandleMayCause with parameters MySymptom and DoShowMessage
- calculate p2:
p2:=0; for P in Probabilities do if Assigned(P.Association) then p2:=p2+procent(temp_new); - calculate factor:
factor:=(1-p2)/(1-p1); - For each element in workview where assocation is assigned do:
- calculate CondDao and temp_new:
CondDao:=( (procent(temp_new)*factor) / (1-procent(temp_new)*faktor_s) ) if CondDao<0 then CondDao:=0.0000000000001 temp_new := lg10(CONDDAO)
- calculate CondDao and temp_new:
-
For all records do:
- Set Prob[Symcount+1] = temp_new
- Set lp[Symcount+1] = temp_lp
-
if IsExclude is True then update form variables:
if (aSymptom.id=27) then nonpresscanty:=True else if (aSymptom.id=117) then nonpressplusplus:=True;
HandleMayCause
- Parameter: MySymptom (TSymtom)
- Parameter: DoShowMessage
- Initialize list of causedsymptoms (array):
- For every symptom S in the MayCause list of MySymptom do:
- If the Symptom S is in the SelectedSymtoms array, with Present=true then
- Add the symtom S to causedsymptoms
- If the Symptom S is in the SelectedSymtoms array, with Present=true then
- For every symptom S in causedsymptoms do
- Call droplight with the parameters S, MySymptom and DoShowMessage
DropLight
- Parameter: CausedSymptom (TSymptom)
- Parameter: MySymptom (TSymptom)
- Parameter: DoShowMessage
- Let symcount equal the number of elements in selectedsymptoms
- let Idx be the index of MySymptom in in selectedsymptoms
- For each element P in Probabilities where Association is assigned
- Calculate Factor as P.LP[Idx]
- If Factor>0 and P.LP[SymCount]>0 then
- if P.LP[SymCount]>FActor then
- set P.Prob[SymCount]=P.Prob[SymCount-1]-Factor
- if P.LP[SymCount]<=FActor then
- set P.Prob[SymCount]=P.Prob[SymCount-1]
- if P.LP[SymCount]>FActor then
- if DoShowMessage is true then show message: (strings 540,443,444)
Please notice the following: if {{CausedSymtom.Name.Language}} may be present because of the presence of {{MySymtom.Name.Language}} , or vice-versa: these characteristics are linked. We drop the lowest confirming power of both.
CalculatePowerTable
- Initialize powertable array of type TPowerTable.
- let symcount equal the number of elements in the selectedSymptoms array
-
For every record P in probabilities where (P.Pro[Symcount+1]>=-2),
- Let PCT equal * Procent(P.Pro[Symcount+1])*
-
Fetch All associated records A from Diagnose.Associations where:
- A.DiagID=P.Diagnose.Id
- PCT>=P.Diagnose.cutOff or (Pct>=0.01)
- A.SymID.ttype>1
- A.SymId is not in the selectedSymptoms array
- A.SymId is not in the excludes of an element of the selectedSymptoms array
- A.SymId is not in the implies of an element of the selectedSymptoms array
- A.SymId is not in the maycause records of an element of the selectedSymptoms array
-
For each record A, initialize a TPowerTableItem record and add it to powertable. Set the fields of the record to:
- Diagnose: equal to P.Diagnose
- Procent: equal to Procent(P.Pro[Symcount])
- PC, PE, prev calculate from CalculatePCPE using the A record.
- Bitmap calculate from CalculateBitmap using PC and PE.
CalculatePCPE
- Argument: A of type TAssociation
- Return values: prev, pc, pe
- let fatcom equal Symptom.comune with Symptom.id equal A.symId.
- let symcount equal the number of elements in the selectedSymptoms array
- Initiate P1, p2 to zero.
-
Loop over probabilities array associated with the current symptom (A.Symptom), let P be the probability record of the current item.
-
Calculate the following sums:
P1:=P1+Procent(P.pro[symcount]) P2:=P2+Procent(P.pro[symcount])*GetAssociation(P.Diagnose.Id,A.SymId).sens -
Note that the Association field of the Probability record P must not be used for this.
- If P.Diagnose.id equals the A.DiagId then additionally set
prev:=procent(P.pro[symcount]); P3:=GetAssociation(P.Diagnose.Id,A.SymId).sens; - if prev=1 then set
fp:=0.000000001; - if prev<>1 then Calculate fp:
fp:= (p2-Prev*p3+(1-P1)*fatcom) / (1-Prev); if fp=0 then fp:=0.000000001;
-
-
Calculate return value PC:
pc:=p3/fp; - if p3<>1 then calculate return value PE
PE:=(1-fp)/(1-p3); - if p3 equals 1 then return value PE:=0
CalculateBitmap
- 2 entry parameters PC,PE (double)
- The bitmap reference is sum of 2 numbers, forming a 2-digit number when added together.
- Each number is calculated as follows
The result of CalculateBitmap is then calculated as
Function CalcDigit(N : integer) : integer; Begin if n<1 then result:=0 else if n<6 then result:=1 else if n<17 then result:=2 else if n<58 then result:=3 else result:=4Result:=CalcDigit(trunc(PC))*10 + CalcDigit(Trunc(PE))