LazStats: Refactor GenKappaUnit. Add pdf help to chm. Add files GenKappa.laz and KappaTest3.laz from OpenStat sample files.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7410 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-04-27 10:33:16 +00:00
parent 793f9a5144
commit b873677972
6 changed files with 507 additions and 335 deletions

View File

@@ -0,0 +1,107 @@
20
3
Rater
VARIABLE 1
1
I
0
99999
L
Object
VARIABLE 2
1
I
0
99999
L
Category
VARIABLE 3
1
I
0
99999
L
Case 0
Rater
Object
Category
Case 1
1
1
1
Case 2
1
1
1
Case 3
1
1
1
Case 4
1
1
1
Case 5
1
1
1
Case 6
1
1
2
Case 7
1
1
2
Case 8
1
1
2
Case 9
1
1
3
Case 10
1
1
3
Case 11
2
1
1
Case 12
2
1
1
Case 13
2
1
1
Case 14
2
1
1
Case 15
2
1
1
Case 16
2
1
1
Case 17
2
1
2
Case 18
2
1
2
Case 19
2
1
2
Case 20
2
1
3

View File

@@ -0,0 +1,87 @@
15
3
rater
VARIABLE 1
1
I
0
99999
L
object
VARIABLE 2
1
I
0
99999
L
category
VARIABLE 3
1
I
0
99999
L
Case 0
rater
object
category
Case 1
1
1
1
Case 2
1
2
2
Case 3
1
3
3
Case 4
1
4
2
Case 5
1
5
3
Case 6
2
1
1
Case 7
2
2
2
Case 8
2
3
2
Case 9
2
4
3
Case 10
2
5
3
Case 11
3
1
1
Case 12
3
2
2
Case 13
3
3
3
Case 14
3
4
2
Case 15
3
5
3

View File

@@ -13,92 +13,74 @@ object GenKappaFrm: TGenKappaFrm
Position = poMainFormCenter Position = poMainFormCenter
LCLVersion = '2.1.0.0' LCLVersion = '2.1.0.0'
object ResetBtn: TButton object ResetBtn: TButton
AnchorSideRight.Control = CancelBtn AnchorSideRight.Control = ComputeBtn
AnchorSideBottom.Control = Owner AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom AnchorSideBottom.Side = asrBottom
Left = 167 Left = 259
Height = 25 Height = 25
Top = 323 Top = 323
Width = 54 Width = 54
Anchors = [akRight, akBottom] Anchors = [akRight, akBottom]
AutoSize = True AutoSize = True
BorderSpacing.Left = 12 BorderSpacing.Left = 8
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Right = 12 BorderSpacing.Right = 8
BorderSpacing.Bottom = 8 BorderSpacing.Bottom = 8
Caption = 'Reset' Caption = 'Reset'
OnClick = ResetBtnClick OnClick = ResetBtnClick
TabOrder = 2 TabOrder = 2
end end
object CancelBtn: TButton
AnchorSideRight.Control = ComputeBtn
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 233
Height = 25
Top = 323
Width = 62
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Left = 12
BorderSpacing.Top = 8
BorderSpacing.Right = 12
BorderSpacing.Bottom = 8
Caption = 'Cancel'
ModalResult = 2
TabOrder = 3
end
object ComputeBtn: TButton object ComputeBtn: TButton
AnchorSideRight.Control = ReturnBtn AnchorSideRight.Control = CloseBtn
AnchorSideBottom.Control = Owner AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom AnchorSideBottom.Side = asrBottom
Left = 307 Left = 321
Height = 25 Height = 25
Top = 323 Top = 323
Width = 76 Width = 76
Anchors = [akRight, akBottom] Anchors = [akRight, akBottom]
AutoSize = True AutoSize = True
BorderSpacing.Left = 12 BorderSpacing.Left = 8
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Right = 12 BorderSpacing.Right = 8
BorderSpacing.Bottom = 8 BorderSpacing.Bottom = 8
Caption = 'Compute' Caption = 'Compute'
OnClick = ComputeBtnClick OnClick = ComputeBtnClick
TabOrder = 4 TabOrder = 3
end end
object ReturnBtn: TButton object CloseBtn: TButton
AnchorSideRight.Control = Owner AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = Owner AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom AnchorSideBottom.Side = asrBottom
Left = 395 Left = 405
Height = 25 Height = 25
Top = 323 Top = 323
Width = 61 Width = 55
Anchors = [akRight, akBottom] Anchors = [akRight, akBottom]
AutoSize = True AutoSize = True
BorderSpacing.Left = 12 BorderSpacing.Left = 8
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Right = 12 BorderSpacing.Right = 8
BorderSpacing.Bottom = 8 BorderSpacing.Bottom = 8
Caption = 'Return' Caption = 'Close'
ModalResult = 1 ModalResult = 11
TabOrder = 5 TabOrder = 4
end end
object HelpBtn: TButton object HelpBtn: TButton
Tag = 125 Tag = 125
AnchorSideRight.Control = ResetBtn AnchorSideRight.Control = ResetBtn
AnchorSideBottom.Control = Owner AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom AnchorSideBottom.Side = asrBottom
Left = 104 Left = 200
Height = 25 Height = 25
Top = 323 Top = 323
Width = 51 Width = 51
Anchors = [akRight, akBottom] Anchors = [akRight, akBottom]
AutoSize = True AutoSize = True
BorderSpacing.Left = 12 BorderSpacing.Left = 8
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Right = 12 BorderSpacing.Right = 8
BorderSpacing.Bottom = 8 BorderSpacing.Bottom = 8
Caption = 'Help' Caption = 'Help'
OnClick = HelpBtnClick OnClick = HelpBtnClick
@@ -195,6 +177,7 @@ object GenKappaFrm: TGenKappaFrm
BorderSpacing.Top = 2 BorderSpacing.Top = 2
BorderSpacing.Right = 8 BorderSpacing.Right = 8
ItemHeight = 0 ItemHeight = 0
OnSelectionChange = VarListSelectionChange
TabOrder = 0 TabOrder = 0
end end
object CatIn: TBitBtn object CatIn: TBitBtn
@@ -306,6 +289,7 @@ object GenKappaFrm: TGenKappaFrm
Anchors = [akLeft, akRight, akBottom] Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8 BorderSpacing.Left = 8
BorderSpacing.Bottom = 12 BorderSpacing.Bottom = 12
ReadOnly = True
TabOrder = 3 TabOrder = 3
Text = 'CatEdit' Text = 'CatEdit'
end end
@@ -323,8 +307,9 @@ object GenKappaFrm: TGenKappaFrm
Anchors = [akLeft, akRight, akBottom] Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8 BorderSpacing.Left = 8
BorderSpacing.Bottom = 12 BorderSpacing.Bottom = 12
ReadOnly = True
TabOrder = 6 TabOrder = 6
Text = 'Edit1' Text = 'ObjectEdit'
end end
object RaterEdit: TEdit object RaterEdit: TEdit
AnchorSideLeft.Control = RaterOut AnchorSideLeft.Control = RaterOut
@@ -341,8 +326,9 @@ object GenKappaFrm: TGenKappaFrm
Anchors = [akLeft, akRight, akBottom] Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 8 BorderSpacing.Left = 8
BorderSpacing.Bottom = 12 BorderSpacing.Bottom = 12
ReadOnly = True
TabOrder = 9 TabOrder = 9
Text = 'Edit1' Text = 'RaterEdit'
end end
end end
end end

View File

@@ -1,3 +1,7 @@
// File for testing according to pdf help: KappaTest3.laz
// BUT: Yields different results than pdf
// --> using file genkappa.laz for the chm
unit GenKappaUnit; unit GenKappaUnit;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
@@ -18,9 +22,8 @@ type
Label4: TLabel; Label4: TLabel;
Panel1: TPanel; Panel1: TPanel;
ResetBtn: TButton; ResetBtn: TButton;
CancelBtn: TButton;
ComputeBtn: TButton; ComputeBtn: TButton;
ReturnBtn: TButton; CloseBtn: TButton;
CatIn: TBitBtn; CatIn: TBitBtn;
CatOut: TBitBtn; CatOut: TBitBtn;
CatEdit: TEdit; CatEdit: TEdit;
@@ -46,6 +49,7 @@ type
procedure RaterInClick(Sender: TObject); procedure RaterInClick(Sender: TObject);
procedure RaterOutClick(Sender: TObject); procedure RaterOutClick(Sender: TObject);
procedure ResetBtnClick(Sender: TObject); procedure ResetBtnClick(Sender: TObject);
procedure VarListSelectionChange(Sender: TObject; User: boolean);
private private
{ private declarations } { private declarations }
FAutoSized: Boolean; FAutoSized: Boolean;
@@ -55,11 +59,12 @@ type
function compute_term1(R: IntDyneCube; i, j, k: integer): double; function compute_term1(R: IntDyneCube; i, j, k: integer): double;
function compute_term2(R: IntDyneCube; i, j, l: integer): double; function compute_term2(R: IntDyneCube; i, j, l: integer): double;
function compute_denom(R: IntDyneCube): double; function compute_denom(R: IntDyneCube): double;
function compute_partial_pchance(R : IntDyneCube; i, j : integer; function compute_partial_pchance(R: IntDyneCube; i, j: integer; denom: double): double;
denom : double) : double;
function compute_partial_pobs(R: IntDyneCube; k, l: integer): double; function compute_partial_pobs(R: IntDyneCube; k, l: integer): double;
function KappaVariance(R: IntDyneCube; n, m, K1: integer): double; function KappaVariance(R: IntDyneCube; n, m, K1: integer): double;
procedure UpdateBtnStates;
public public
{ public declarations } { public declarations }
end; end;
@@ -70,7 +75,7 @@ var
implementation implementation
uses uses
Math; Math, Utils;
{ TGenKappaFrm } { TGenKappaFrm }
@@ -92,110 +97,98 @@ begin
end; end;
procedure TGenKappaFrm.CatInClick(Sender: TObject); procedure TGenKappaFrm.CatInClick(Sender: TObject);
VAR index : integer; var
index: integer;
begin begin
index := VarList.ItemIndex; index := VarList.ItemIndex;
CatEdit.Text := VarList.Items.Strings[index]; if (index > -1) and (CatEdit.Text = '') then
begin
CatEdit.Text := VarList.Items[index];
VarList.Items.Delete(index); VarList.Items.Delete(index);
CatIn.Enabled := false; UpdateBtnStates;
CatOut.Enabled := true; end;
end; end;
procedure TGenKappaFrm.CatOutClick(Sender: TObject); procedure TGenKappaFrm.CatOutClick(Sender: TObject);
begin
if CatEdit.Text <> '' then
begin begin
VarList.Items.Add(CatEdit.Text); VarList.Items.Add(CatEdit.Text);
CatEdit.Text := ''; CatEdit.Text := '';
CatIn.Enabled := true; UpdateBtnStates;
CatOut.Enabled := false; end;
end; end;
procedure TGenKappaFrm.ComputeBtnClick(Sender: TObject); procedure TGenKappaFrm.ComputeBtnClick(Sender: TObject);
VAR var
CatCol, ObjCol, RaterCol, frequency, i, j, k, l: integer; CatCol, ObjCol, RaterCol, frequency, i, j, k, l: integer;
value, rater, category, anobject: integer; value, rater, category, anobject: integer;
// int CatCol:=0, ObjCol:=0, RaterCol:=0;
// int value, rater, category, object;
R: IntDyneCube; R: IntDyneCube;
// int ***R;
pobs, pchance, kappa, num, denom, partial_pchance, a_priori: double; pobs, pchance, kappa, num, denom, partial_pchance, a_priori: double;
average_frequency: DblDyneVec; average_frequency: DblDyneVec;
outline : array[0..131] of char;
// char outline[131], astring[21];
z: double; z: double;
lReport: TStrings;
begin begin
lReport := TStringList.Create;
try
lReport.Add('GENERALIZED KAPPA COEFFICIENT PROCEDURE');
lReport.Add('Adapted from the program written by Giovanni Flammia');
lReport.Add('Copy-write 1995, M.I.T. Lab. for Computer Science');
lReport.Add('');
// get columns for the variables
CatCol := 0; CatCol := 0;
ObjCol := 0; ObjCol := 0;
RaterCol := 0; RaterCol := 0;
OutputFrm.RichEdit.Clear; for i := 1 to NoVariables do
OutputFrm.RichEdit.Lines.Add('Generalized Kappa Coefficient Procedure');
OutputFrm.RichEdit.Lines.Add('adapted from the program written by Giovanni Flammia');
OutputFrm.RichEdit.Lines.Add('copywritten 1995, M.I.T. Lab. for Computer Science');
OutputFrm.RichEdit.Lines.Add('');
// get columns for the variables
for i := 0 to NoVariables - 1 do
begin begin
if (OS3MainFrm.DataGrid.Cells[i+1,0] = CatEdit.Text) then CatCol := i+1; if (OS3MainFrm.DataGrid.Cells[i, 0] = CatEdit.Text) then CatCol := i;
if (OS3MainFrm.DataGrid.Cells[i+1,0] = RaterEdit.Text) then RaterCol := i+1; if (OS3MainFrm.DataGrid.Cells[i, 0] = RaterEdit.Text) then RaterCol := i;
if (OS3MainFrm.DataGrid.Cells[i+1,0] = ObjectEdit.Text) then ObjCol := i+1; if (OS3MainFrm.DataGrid.Cells[i, 0] = ObjectEdit.Text) then ObjCol := i;
end; end;
if ((CatCol = 0) or (RaterCol = 0) or (ObjCol = 0)) then if ((CatCol = 0) or (RaterCol = 0) or (ObjCol = 0)) then
begin begin
ShowMessage('ERROR! One or more variables not defined.'); MessageDlg('One or more variables not defined.', mtError, [mbOK], 0);
exit; exit;
end; end;
// get max no of codes for objects, raters, categories // get max no of codes for objects, raters, categories
NoCats := 0; NoCats := 0;
NoObjects := 0; NoObjects := 0;
NoRaters := 0; NoRaters := 0;
for i := 0 to NoCases - 1 do for i := 1 to NoCases do
begin begin
value := StrToInt(Trim(OS3MainFrm.DataGrid.Cells[CatCol,i+1])); value := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[CatCol, i])));
// result := GetValue(i+1,CatCol,intvalue,dblvalue,strvalue);
// if (result :=:= 1) value := 0;
// else value := intvalue;
if (value > NoCats) then NoCats := value; if (value > NoCats) then NoCats := value;
value := StrToInt(Trim(OS3MainFrm.DataGrid.Cells[ObjCol,i+1]));
// result := GetValue(i+1,ObjCol,intvalue,dblvalue,strvalue); value := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ObjCol, i])));
// if (result :=:= 1) value := 0;
// else value := intvalue;
if (value > NoObjects) then NoObjects := value; if (value > NoObjects) then NoObjects := value;
value := StrToInt(Trim(OS3MainFrm.DataGrid.Cells[RaterCol,i+1]));
// result := GetValue(i+1,RaterCol,intvalue,dblvalue,strvalue); value := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RaterCol, i])));
// if (result :=:= 1) value := 0;
// else value := intvalue;
if (value > NoRaters) then NoRaters := value; if (value > NoRaters) then NoRaters := value;
end; end;
outline := format('%d Raters using %d Categories to rate %d Objects', lReport.Add('%d Raters using %d Categories to rate %d Objects', [NoRaters, NoCats, NoObjects]);
[NoRaters, NoCats, NoObjects]); lReport.Add('');
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.RichEdit.Lines.Add('');
// get memory for R and set to zero // get memory for R and set to zero
SetLength(R, NoRaters+1, NoCats+1, NoObjects+1); SetLength(R, NoRaters+1, NoCats+1, NoObjects+1);
for i := 0 to NoRaters - 1 do for i := 0 to NoRaters - 1 do
begin
for k := 0 to NoCats - 1 do for k := 0 to NoCats - 1 do
begin
for l := 0 to NoObjects - 1 do for l := 0 to NoObjects - 1 do
begin
R[i,k,l] := 0; R[i,k,l] := 0;
end;
end;
end;
// get memory for average_frequency // get memory for average_frequency
SetLength(average_frequency, NoCats+1); SetLength(average_frequency, NoCats+1);
for k := 0 to NoCats - 1 do average_frequency[k] := 0.0; for k := 0 to NoCats - 1 do
average_frequency[k] := 0.0;
// read data and store in R // read data and store in R
for i := 0 to NoCases - 1 do for i := 1 to NoCases do
begin begin
rater := StrToInt(Trim(OS3MainFrm.DataGrid.Cells[RaterCol,i+1])); rater := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[RaterCol, i])));
anobject := StrToInt(Trim(OS3MainFrm.DataGrid.Cells[ObjCol,i+1])); anobject := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[ObjCol, i])));
category := StrToInt(Trim(OS3MainFrm.DataGrid.Cells[CatCol,i+1])); category := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[CatCol, i])));
R[rater-1, category-1, anobject-1] := 1; R[rater-1, category-1, anobject-1] := 1;
end; end;
@@ -205,73 +198,60 @@ begin
for i := 0 to NoRaters - 1 do for i := 0 to NoRaters - 1 do
begin begin
for j := 0 to NoRaters - 1 do for j := 0 to NoRaters - 1 do
begin
if (i <> j) then if (i <> j) then
begin begin
partial_pchance := compute_partial_pchance(R,i,j,denom); partial_pchance := compute_partial_pchance(R,i,j,denom);
pchance := pchance + partial_pchance; pchance := pchance + partial_pchance;
end; end;
end;
for k := 0 to NoCats - 1 do for k := 0 to NoCats - 1 do
begin begin
frequency := 0; frequency := 0;
for l := 0 to NoObjects - 1 do for l := 0 to NoObjects - 1 do
begin
frequency := frequency + R[i,k,l]; frequency := frequency + R[i,k,l];
end;
a_priori := frequency / NoObjects; a_priori := frequency / NoObjects;
outline := format('Frequency[%d,%d] := %f',[i+1,k+1,a_priori]); lReport.Add('Frequency[%d,%d]: %f', [i+1, k+1, a_priori]);
OutputFrm.RichEdit.Lines.Add(outline);
end; end;
end; end;
for k := 0 to NoCats - 1 do for k := 0 to NoCats - 1 do
begin
for l := 0 to NoObjects - 1 do for l := 0 to NoObjects - 1 do
begin
for i := 0 to NoRaters - 1 do for i := 0 to NoRaters - 1 do
begin
average_frequency[k] := average_frequency[k] + R[i,k,l]; average_frequency[k] := average_frequency[k] + R[i,k,l];
end;
end;
end;
for k := 0 to NoCats - 1 do for k := 0 to NoCats - 1 do
begin begin
average_frequency[k] := average_frequency[k] / (NoObjects * NoRaters); average_frequency[k] := average_frequency[k] / (NoObjects * NoRaters);
outline := format('Average_Frequency[%d] := %f',[k+1,average_frequency[k]]); lReport.Add('Average_Frequency[%d]: %f', [k+1, average_frequency[k]]);
OutputFrm.RichEdit.Lines.Add(outline);
end; end;
outline := format('PChance := %f',[pchance]);
OutputFrm.RichEdit.Lines.Add(outline); lReport.Add('PChance: %f', [pchance]);
// compute observed probability of agreement among all raters // compute observed probability of agreement among all raters
num := 0.0; num := 0.0;
for k := 0 to NoCats - 1 do for k := 0 to NoCats - 1 do
begin
for l := 0 to NoObjects - 1 do for l := 0 to NoObjects - 1 do
begin
num := num + compute_partial_pobs(R,k,l); num := num + compute_partial_pobs(R,k,l);
end; if (denom > 0.0) then
end; pobs := num / denom
if (denom > 0.0) then pobs := num / denom else
else pobs := 0.0; pobs := 0.0;
outline := format('PObs := %f',[pobs]); lReport.Add('PObs: %f', [pobs]);
OutputFrm.RichEdit.Lines.Add(outline);
kappa := (pobs - pchance) / (1.0 - pchance); kappa := (pobs - pchance) / (1.0 - pchance);
outline := format('Kappa := %f',[kappa]); lReport.Add('Kappa: %f', [kappa]);
OutputFrm.RichEdit.Lines.Add(outline);
z := KappaVariance(R,NoObjects,NoRaters,NoCats); z := KappaVariance(R,NoObjects,NoRaters,NoCats);
if (z > 0.0) then z := kappa / sqrt(z); if (z > 0.0) then z := kappa / sqrt(z);
outline := format('z for Kappa := %8.3f with probability > %8.3f',[z,1.0-probz(z)]); lReport.Add('z for Kappa: %.3f with probability > %.3f', [z, 1.0-probz(z)]);
OutputFrm.RichEdit.Lines.Add(outline);
OutputFrm.ShowModal;
// clean up space allocated DisplayReport(lReport);
finally
lReport.Free;
average_frequency := nil; average_frequency := nil;
R := nil; R := nil;
end; end;
end;
procedure TGenKappaFrm.FormActivate(Sender: TObject); procedure TGenKappaFrm.FormActivate(Sender: TObject);
var var
@@ -279,12 +259,11 @@ var
begin begin
if FAutoSized then if FAutoSized then
exit; exit;
w := MaxValue([HelpBtn.Width, ResetBtn.Width, CancelBtn.Width, ComputeBtn.Width, ReturnBtn.Width]); w := MaxValue([HelpBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]);
HelpBtn.Constraints.MinWidth := w; HelpBtn.Constraints.MinWidth := w;
ResetBtn.Constraints.MinWidth := w; ResetBtn.Constraints.MinWidth := w;
CancelBtn.Constraints.MinWidth := w;
ComputeBtn.Constraints.MinWidth := w; ComputeBtn.Constraints.MinWidth := w;
ReturnBtn.Constraints.MinWidth := w; CloseBtn.Constraints.MinWidth := w;
Constraints.MinWidth := Width; Constraints.MinWidth := Width;
Constraints.MinHeight := Height; Constraints.MinHeight := Height;
@@ -295,8 +274,6 @@ end;
procedure TGenKappaFrm.FormCreate(Sender: TObject); procedure TGenKappaFrm.FormCreate(Sender: TObject);
begin begin
Assert(OS3MainFrm <> nil); Assert(OS3MainFrm <> nil);
if OutputFrm = nil then
Application.CreateForm(TOutputFrm, OutputFrm);
end; end;
procedure TGenKappaFrm.FormShow(Sender: TObject); procedure TGenKappaFrm.FormShow(Sender: TObject);
@@ -308,31 +285,29 @@ procedure TGenKappaFrm.HelpBtnClick(Sender: TObject);
begin begin
if ContextHelpForm = nil then if ContextHelpForm = nil then
Application.CreateForm(TContextHelpForm, ContextHelpForm); Application.CreateForm(TContextHelpForm, ContextHelpForm);
ContextHelpForm.HelpMessage((Sender as TButton).tag); ContextHelpForm.HelpMessage((Sender as TButton).Tag);
end; end;
function TGenKappaFrm.compute_term1(R: IntDyneCube; i, j, k: integer): double; function TGenKappaFrm.compute_term1(R: IntDyneCube; i, j, k: integer): double;
VAR var
kk : integer; // range over 0 .. num_categories-1 */ kk : integer; // range over 0 .. num_categories-1 */
l,ll : integer; // range over 0 .. num_points-1 */ l,ll : integer; // range over 0 .. num_points-1 */
denom_i : integer; //:=0; denom_i : integer; //:=0;
denom_j : integer; //:=0; denom_j : integer; //:=0;
num_i : integer; //:=0; num_i : integer; //:=0;
num_j : integer; //:=0; num_j : integer; //:=0;
begin begin
denom_i := 0; denom_i := 0;
denom_j := 0; denom_j := 0;
num_i := 0; num_i := 0;
num_j := 0; num_j := 0;
for kk := 0 to NoCats - 1 do for kk := 0 to NoCats - 1 do
begin
for ll := 0 to NoObjects - 1 do for ll := 0 to NoObjects - 1 do
begin begin
denom_i := denom_i + R[i, kk, ll]; denom_i := denom_i + R[i, kk, ll];
denom_j := denom_j + R[j, kk, ll]; denom_j := denom_j + R[j, kk, ll];
end; end;
end;
for l := 0 to NoObjects - 1 do for l := 0 to NoObjects - 1 do
begin begin
@@ -340,11 +315,11 @@ begin
num_j := num_j + R[j, k, l]; num_j := num_j + R[j, k, l];
end; end;
result := ((num_i / denom_i) * (num_j / denom_j)); result := (num_i * num_j) / (denom_i * denom_j); //((num_i / denom_i) * (num_j / denom_j));
end; end;
function TGenKappaFrm.compute_term2(R: IntDyneCube; i, j, l: integer): double; function TGenKappaFrm.compute_term2(R: IntDyneCube; i, j, l: integer): double;
VAR var
sum_i, sum_j, k: integer; sum_i, sum_j, k: integer;
begin begin
sum_i := 0; sum_i := 0;
@@ -356,42 +331,34 @@ begin
sum_j := sum_j + R[j, k, l]; sum_j := sum_j + R[j, k, l];
end; end;
result := (sum_i * sum_j ); Result := sum_i * sum_j;
end; end;
//---------------------------------------------------------------------------
function TGenKappaFrm.compute_denom(R: IntDyneCube): double; function TGenKappaFrm.compute_denom(R: IntDyneCube): double;
VAR var
sum: IntDyneVec; sum: IntDyneVec;
aresult : double;
i, k, l: integer; i, k, l: integer;
begin begin
aresult := 0; Result := 0;
SetLength(sum, NoObjects); // sum := (int *)calloc(num_points,sizeof(int)); SetLength(sum, NoObjects); // sum := (int *)calloc(num_points,sizeof(int));
for l := 0 to NoObjects - 1 do for l := 0 to NoObjects - 1 do
begin begin
sum[l] := 0; sum[l] := 0;
for i := 0 to NoRaters - 1 do for i := 0 to NoRaters - 1 do
begin
for k := 0 to NoCats - 1 do for k := 0 to NoCats - 1 do
begin
sum[l] := sum[l] + R[i,k,l]; sum[l] := sum[l] + R[i,k,l];
end; end;
end;
end;
for l := 0 to NoObjects - 1 do for l := 0 to NoObjects - 1 do
begin Result := Result + sum[l] * (sum[l] - 1);
aresult := aresult + sum[l] * ( sum[l] - 1);
end;
sum := nil; sum := nil;
result := aresult;
end; end;
function TGenKappaFrm.compute_partial_pchance(R: IntDyneCube; i, j: integer; function TGenKappaFrm.compute_partial_pchance(R: IntDyneCube; i, j: integer;
denom: double): double; denom: double): double;
VAR var
term1, term2: double; term1, term2: double;
k, l: integer; k, l: integer;
begin begin
@@ -399,48 +366,42 @@ begin
term2 := 0; term2 := 0;
for k := 0 to NoCats - 1 do for k := 0 to NoCats - 1 do
begin
term1 := term1 + compute_term1(R,i,j,k); term1 := term1 + compute_term1(R,i,j,k);
end;
for l := 0 to NoObjects - 1 do for l := 0 to NoObjects - 1 do
begin
term2 := term2 + compute_term2(R,i,j,l); term2 := term2 + compute_term2(R,i,j,l);
if (denom > 0.0) then
Result := term1 * term2 / denom
else
Result := 0.0;
end; end;
if (denom > 0.0) then result := ( term1 * ( term2 / denom ) )
else result := 0.0;
end;
//---------------------------------------------------------------------------
function TGenKappaFrm.compute_partial_pobs(R: IntDyneCube; k, l: integer): double; function TGenKappaFrm.compute_partial_pobs(R: IntDyneCube; k, l: integer): double;
VAR var
sum, i: integer; sum, i: integer;
begin begin
sum := 0; sum := 0;
for i := 0 to NoRaters - 1 do for i := 0 to NoRaters - 1 do
begin
sum := sum + R[i, k, l]; sum := sum + R[i, k, l];
Result := sum * (sum - 1);
end; end;
result := (sum * (sum - 1)); { Calculates the variance of Kappa
end; R contains 1's or 0's for raters, categories and objects (row, col, slice)
m is number of raters
n is number of subjects
K1 is the number of categories }
function TGenKappaFrm.KappaVariance(R : IntDyneCube; n, m, K1: integer): double; function TGenKappaFrm.KappaVariance(R : IntDyneCube; n, m, K1: integer): double;
VAR var
xij, variance, term1, term2 : double; xij, term1, term2: double;
i, j, k: integer; i, j, k: integer;
pj: DblDyneVec; pj: DblDyneVec;
begin begin
// calculates the variance of Kappa
// R contains 1's or 0's for raters, categories and objects (row, col, slice)
// m is number of raters
// n is number of subjects
// K1 is the number of categories
term1 := 0.0; term1 := 0.0;
term2 := 0.0; term2 := 0.0;
SetLength(pj,K1); SetLength(pj,K1);
for j := 0 to K1 - 1 do pj[j] := 0.0; for j := 0 to K1 - 1 do pj[j] := 0.0;
@@ -449,65 +410,96 @@ begin
begin begin
xij := 0.0; xij := 0.0;
for i := 0 to m - 1 do // accross raters for i := 0 to m - 1 do // accross raters
begin
for k := 0 to n - 1 do // accross objects for k := 0 to n - 1 do // accross objects
begin
xij := xij + R[i,j,k]; xij := xij + R[i,j,k];
end;
end;
pj[j] := pj[j] + xij; pj[j] := pj[j] + xij;
end; end;
for j := 0 to K1 - 1 do pj[j] := pj[j] / (n * m);
for j := 0 to K1 - 1 do
pj[j] := pj[j] / (n * m);
for j := 0 to K1 - 1 do for j := 0 to K1 - 1 do
begin begin
term1 := term1 + (pj[j] * (1.0 - pj[j])); term1 := term1 + (pj[j] * (1.0 - pj[j]));
term2 := term2 + (pj[j] * (1.0 - pj[j]) * (1.0 - 2.0 * pj[j])); term2 := term2 + (pj[j] * (1.0 - pj[j]) * (1.0 - 2.0 * pj[j]));
end; end;
term1 := term1 * term1; term1 := term1 * term1;
if ((term1 > 0) and (term2 > 0)) then if (term1 > 0) and (term2 > 0) then
variance := (2.0 / (n * m * (m-1) * term1)) * (term1 - term2) Result := (2.0 / (n * m * (m-1) * term1)) * (term1 - term2)
else variance := 0.0; else
Result := 0.0;
pj := nil; pj := nil;
result := variance;
end; end;
procedure TGenKappaFrm.ObjInClick(Sender: TObject); procedure TGenKappaFrm.ObjInClick(Sender: TObject);
VAR index : integer; var
index: integer;
begin begin
index := VarList.ItemIndex; index := VarList.ItemIndex;
if (index > -1) and (ObjectEdit.Text = '') then
ObjectEdit.Text := VarList.Items.Strings[index]; begin
ObjectEdit.Text := VarList.Items[index];
VarList.Items.Delete(index); VarList.Items.Delete(index);
ObjIn.Enabled := false; UpdateBtnStates;
ObjOut.Enabled := true; end;
end; end;
procedure TGenKappaFrm.ObjOutClick(Sender: TObject); procedure TGenKappaFrm.ObjOutClick(Sender: TObject);
begin
if ObjectEdit.Text <> '' then
begin begin
VarList.Items.Add(ObjectEdit.Text); VarList.Items.Add(ObjectEdit.Text);
ObjectEdit.Text := ''; ObjectEdit.Text := '';
ObjIn.Enabled := true; UpdateBtnStates;
ObjOut.Enabled := false; end;
end; end;
procedure TGenKappaFrm.RaterInClick(Sender: TObject); procedure TGenKappaFrm.RaterInClick(Sender: TObject);
VAR index : integer; var
index: integer;
begin begin
index := VarList.ItemIndex; index := VarList.ItemIndex;
if (index > -1) and (RaterEdit.Text = '') then
begin
RaterEdit.Text := VarList.Items.Strings[index]; RaterEdit.Text := VarList.Items.Strings[index];
VarList.Items.Delete(index); VarList.Items.Delete(index);
RaterIn.Enabled := false; UpdateBtnStates;
RaterOut.Enabled := true; end;
end; end;
procedure TGenKappaFrm.RaterOutClick(Sender: TObject); procedure TGenKappaFrm.RaterOutClick(Sender: TObject);
begin
if RaterEdit.Text <> '' then
begin begin
VarList.Items.Add(RaterEdit.Text); VarList.Items.Add(RaterEdit.Text);
RaterEdit.Text := ''; RaterEdit.Text := '';
RaterIn.Enabled := true; UpdateBtnStates;
RaterOut.Enabled := false;
end; end;
end;
procedure TGenKappaFrm.UpdateBtnStates;
var
lSelected: Boolean;
begin
lSelected := AnySelected(VarList);
CatIn.Enabled := lSelected and (CatEdit.Text = '');
CatOut.Enabled := (CatEdit.Text <> '');
ObjIn.Enabled := lSelected and (ObjectEdit.Text = '');
ObjOut.Enabled := (ObjectEdit.Text <> '');
RaterIn.Enabled := lSelected and (RaterEdit.Text = '');
RaterOut.Enabled := (RaterEdit.Text <> '');
end;
procedure TGenKappaFrm.VarListSelectionChange(Sender: TObject; User: boolean);
begin
UpdateBtnStates;
end;
initialization initialization
{$I genkappaunit.lrs} {$I genkappaunit.lrs}