From 8e59f55c29a07769b6287048b7abb5961464b276 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Tue, 27 Oct 2020 18:06:08 +0000 Subject: [PATCH] LazStats: Inherit CochranQUnit from TBasicStatsReportForm git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7818 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- applications/lazstats/source/LazStats.lpi | 2 +- .../analysis/nonparametric/binomialunit.pas | 1 + .../analysis/nonparametric/cochranqunit.lfm | 337 +++++++----------- .../analysis/nonparametric/cochranqunit.pas | 235 ++++++------ .../lazstats/source/forms/mainunit.pas | 6 +- 5 files changed, 261 insertions(+), 320 deletions(-) diff --git a/applications/lazstats/source/LazStats.lpi b/applications/lazstats/source/LazStats.lpi index 53ec6e5d6..474989804 100644 --- a/applications/lazstats/source/LazStats.lpi +++ b/applications/lazstats/source/LazStats.lpi @@ -761,7 +761,7 @@ - + diff --git a/applications/lazstats/source/forms/analysis/nonparametric/binomialunit.pas b/applications/lazstats/source/forms/analysis/nonparametric/binomialunit.pas index 734e50669..5cc05af82 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/binomialunit.pas +++ b/applications/lazstats/source/forms/analysis/nonparametric/binomialunit.pas @@ -34,6 +34,7 @@ type var BinomialForm: TBinomialForm; + implementation {$R *.lfm} diff --git a/applications/lazstats/source/forms/analysis/nonparametric/cochranqunit.lfm b/applications/lazstats/source/forms/analysis/nonparametric/cochranqunit.lfm index 21a158050..979acaca4 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/cochranqunit.lfm +++ b/applications/lazstats/source/forms/analysis/nonparametric/cochranqunit.lfm @@ -1,211 +1,142 @@ -object CochranQFrm: TCochranQFrm +inherited CochranQForm: TCochranQForm Left = 562 - Height = 344 + Height = 393 Top = 203 - Width = 414 + Width = 810 HelpType = htKeyword HelpKeyword = 'html/CochranQTest.htm' - AutoSize = True Caption = 'Cochran Q Test' - ClientHeight = 344 - ClientWidth = 414 - OnActivate = FormActivate - OnCreate = FormCreate - OnShow = FormShow - Position = poMainFormCenter - LCLVersion = '2.1.0.0' - object Label1: TLabel - AnchorSideLeft.Control = VarList - AnchorSideTop.Control = Owner - Left = 8 - Height = 15 - Top = 8 - Width = 97 - BorderSpacing.Top = 8 - Caption = 'Available Variables' - ParentColor = False + ClientHeight = 393 + ClientWidth = 810 + inherited ParamsPanel: TPanel + Height = 377 + ClientHeight = 377 + inherited CloseBtn: TButton + Top = 352 + TabOrder = 8 + end + inherited ComputeBtn: TButton + Top = 352 + TabOrder = 7 + end + inherited ResetBtn: TButton + Top = 352 + TabOrder = 6 + end + inherited HelpBtn: TButton + Top = 352 + TabOrder = 5 + end + inherited ButtonBevel: TBevel + Top = 336 + end + object Label1: TLabel[5] + AnchorSideLeft.Control = VarList + AnchorSideTop.Control = ParamsPanel + Left = 0 + Height = 15 + Top = 0 + Width = 97 + Caption = 'Available Variables' + ParentColor = False + end + object Label2: TLabel[6] + AnchorSideLeft.Control = SelList + AnchorSideTop.Control = ParamsPanel + Left = 171 + Height = 15 + Top = 0 + Width = 93 + Caption = 'Selected Variables' + ParentColor = False + end + object VarList: TListBox[7] + AnchorSideLeft.Control = ParamsPanel + AnchorSideTop.Control = Label1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = AllBtn + AnchorSideBottom.Control = ButtonBevel + Left = 0 + Height = 319 + Top = 17 + Width = 119 + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Top = 2 + BorderSpacing.Right = 6 + ItemHeight = 0 + MultiSelect = True + OnDblClick = VarListDblClick + OnSelectionChange = VarListSelectionChange + TabOrder = 0 + end + object InBtn: TBitBtn[8] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = VarList + Left = 132 + Height = 26 + Top = 17 + Width = 26 + Images = MainDataModule.ImageList + ImageIndex = 1 + OnClick = InBtnClick + Spacing = 0 + TabOrder = 1 + end + object OutBtn: TBitBtn[9] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = InBtn + AnchorSideTop.Side = asrBottom + Left = 132 + Height = 26 + Top = 47 + Width = 26 + BorderSpacing.Top = 4 + Images = MainDataModule.ImageList + ImageIndex = 0 + OnClick = OutBtnClick + Spacing = 0 + TabOrder = 2 + end + object AllBtn: TBitBtn[10] + AnchorSideLeft.Control = ParamsPanel + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = OutBtn + AnchorSideTop.Side = asrBottom + Left = 125 + Height = 25 + Top = 77 + Width = 40 + AutoSize = True + BorderSpacing.Top = 4 + Caption = 'All' + OnClick = AllBtnClick + TabOrder = 3 + end + object SelList: TListBox[11] + AnchorSideLeft.Control = AllBtn + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Label2 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = ButtonBevel + Left = 171 + Height = 319 + Top = 17 + Width = 120 + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Left = 6 + BorderSpacing.Top = 2 + ItemHeight = 0 + MultiSelect = True + OnDblClick = SelListDblClick + OnSelectionChange = VarListSelectionChange + TabOrder = 4 + end end - object Label2: TLabel - AnchorSideLeft.Control = SelList - AnchorSideTop.Control = Owner - Left = 238 - Height = 15 - Top = 8 - Width = 93 - BorderSpacing.Top = 8 - Caption = 'Selected Variables' - ParentColor = False - end - object VarList: TListBox - AnchorSideLeft.Control = Owner - AnchorSideTop.Control = Label1 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = AllBtn - AnchorSideBottom.Control = Bevel1 - Left = 8 - Height = 270 - Top = 25 - Width = 168 - Anchors = [akTop, akLeft, akRight, akBottom] - BorderSpacing.Left = 8 - BorderSpacing.Top = 2 - BorderSpacing.Right = 8 - Constraints.MinHeight = 200 - ItemHeight = 0 - MultiSelect = True - OnSelectionChange = VarListSelectionChange - TabOrder = 0 - end - object InBtn: TBitBtn - AnchorSideLeft.Control = Owner - AnchorSideLeft.Side = asrCenter - AnchorSideTop.Control = VarList - Left = 193 - Height = 28 - Top = 25 - Width = 28 - Images = MainDataModule.ImageList - ImageIndex = 1 - OnClick = InBtnClick - Spacing = 0 - TabOrder = 1 - end - object OutBtn: TBitBtn - AnchorSideLeft.Control = Owner - AnchorSideLeft.Side = asrCenter - AnchorSideTop.Control = InBtn - AnchorSideTop.Side = asrBottom - Left = 193 - Height = 28 - Top = 57 - Width = 28 - BorderSpacing.Top = 4 - Images = MainDataModule.ImageList - ImageIndex = 0 - OnClick = OutBtnClick - Spacing = 0 - TabOrder = 2 - end - object AllBtn: TBitBtn - AnchorSideLeft.Control = Owner - AnchorSideLeft.Side = asrCenter - AnchorSideTop.Control = OutBtn - AnchorSideTop.Side = asrBottom - Left = 184 - Height = 25 - Top = 89 - Width = 46 - AutoSize = True - BorderSpacing.Top = 4 - Caption = 'ALL' - OnClick = AllBtnClick - TabOrder = 3 - end - object SelList: TListBox - AnchorSideLeft.Control = AllBtn - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = Label2 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Bevel1 - Left = 238 - Height = 270 - Top = 25 - Width = 168 - Anchors = [akTop, akLeft, akRight, akBottom] - BorderSpacing.Left = 8 - BorderSpacing.Top = 2 - BorderSpacing.Right = 8 - ItemHeight = 0 - MultiSelect = True - OnSelectionChange = VarListSelectionChange - TabOrder = 4 - end - object ResetBtn: TButton - AnchorSideRight.Control = ComputeBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 205 - Height = 25 - Top = 311 - Width = 54 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Reset' - OnClick = ResetBtnClick - TabOrder = 6 - end - object ComputeBtn: TButton - AnchorSideRight.Control = CloseBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 267 - Height = 25 - Top = 311 - Width = 76 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Compute' - OnClick = ComputeBtnClick - TabOrder = 7 - end - object CloseBtn: TButton - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 351 - Height = 25 - Top = 311 - Width = 55 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Close' - ModalResult = 11 - TabOrder = 8 - end - object HelpBtn: TButton - Tag = 113 - AnchorSideRight.Control = ResetBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 146 - Height = 25 - Top = 311 - Width = 51 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - BorderSpacing.Bottom = 8 - Caption = 'Help' - OnClick = HelpBtnClick - TabOrder = 5 - end - object Bevel1: TBevel - AnchorSideLeft.Control = Owner - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = CloseBtn - Left = 0 - Height = 8 - Top = 295 - Width = 414 - Anchors = [akLeft, akRight, akBottom] - Shape = bsBottomLine + inherited ParamsSplitter: TSplitter + Height = 393 end end diff --git a/applications/lazstats/source/forms/analysis/nonparametric/cochranqunit.pas b/applications/lazstats/source/forms/analysis/nonparametric/cochranqunit.pas index 700127783..8a8284284 100644 --- a/applications/lazstats/source/forms/analysis/nonparametric/cochranqunit.pas +++ b/applications/lazstats/source/forms/analysis/nonparametric/cochranqunit.pas @@ -5,20 +5,15 @@ unit CochranQUnit; interface uses - Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Buttons, ExtCtrls, - MainUnit, Globals, OutputUnit, DataProcs, FunctionsLib, contexthelpunit; + MainUnit, Globals, FunctionsLib, BasicStatsReportFormUnit; type - { TCochranQFrm } + { TCochranQForm } - TCochranQFrm = class(TForm) - Bevel1: TBevel; - HelpBtn: TButton; - ResetBtn: TButton; - ComputeBtn: TButton; - CloseBtn: TButton; + TCochranQForm = class(TBasicStatsReportForm) InBtn: TBitBtn; Label2: TLabel; SelList: TListBox; @@ -27,81 +22,47 @@ type Label1: TLabel; VarList: TListBox; procedure AllBtnClick(Sender: TObject); - procedure ComputeBtnClick(Sender: TObject); - procedure FormActivate(Sender: TObject); - procedure FormCreate(Sender: TObject); - procedure FormShow(Sender: TObject); - procedure HelpBtnClick(Sender: TObject); procedure InBtnClick(Sender: TObject); procedure OutBtnClick(Sender: TObject); - procedure ResetBtnClick(Sender: TObject); + procedure SelListDblClick(Sender: TObject); + procedure VarListDblClick(Sender: TObject); procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean); private - { private declarations } - FAutoSized: Boolean; - procedure UpdateBtnStates; + + protected + procedure AdjustConstraints; override; + procedure Compute; override; + procedure UpdateBtnStates; override; + function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override; + public - { public declarations } + procedure Reset; override; end; var - CochranQFrm: TCochranQFrm; + CochranQForm: TCochranQForm; + implementation +{$R *.lfm} + uses - Math, Utils; + Utils, GridProcs; -{ TCochranQFrm } -procedure TCochranQFrm.ResetBtnClick(Sender: TObject); -var - i: integer; +{ TCochranQForm } + +procedure TCochranQForm.AdjustConstraints; begin - VarList.Clear; - SelList.Clear; - for i := 1 to NoVariables do - VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); - UpdateBtnStates; + inherited; + ParamsPanel.Constraints.MinWidth := 4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left; + ParamsPanel.Constraints.MinHeight := AllBtn.Top + AllBtn.Height + + ButtonBevel.Height + CloseBtn.BorderSpacing.Top + CloseBtn.Height; end; -procedure TCochranQFrm.FormActivate(Sender: TObject); -var - w: Integer; -begin - if FAutoSized then - exit; - w := MaxValue([HelpBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); - HelpBtn.Constraints.MinWidth := w; - ResetBtn.Constraints.MinWidth := w; - ComputeBtn.Constraints.MinWidth := w; - CloseBtn.Constraints.MinWidth := w; - - Constraints.MinWidth := Width; - Constraints.MinHeight := Height; - - FAutoSized := true; -end; - -procedure TCochranQFrm.FormCreate(Sender: TObject); -begin - Assert(OS3MainFrm <> nil); -end; - -procedure TCochranQFrm.FormShow(Sender: TObject); -begin - ResetBtnClick(self); -end; - -procedure TCochranQFrm.HelpBtnClick(Sender: TObject); -begin - if ContextHelpForm = nil then - Application.CreateForm(TContextHelpForm, ContextHelpForm); - ContextHelpForm.HelpMessage((Sender as TButton).tag); -end; - -procedure TCochranQFrm.AllBtnClick(Sender: TObject); +procedure TCochranQForm.AllBtnClick(Sender: TObject); var index: integer; begin @@ -110,34 +71,24 @@ begin UpdateBtnStates; end; -procedure TCochranQFrm.ComputeBtnClick(Sender: TObject); + +procedure TCochranQForm.Compute; var - i, j, k, col: integer; - ColNoSelected: IntDyneVec = nil; - R1, L1, L2, C1, g1, Q, g2, chiprob: double; - cellstring: string; - lReport: TStrings; + i, j, col: integer; + selCount: Integer; + ColNoSelected: IntDyneVec = nil; + R1, L1, L2, C1, g1, Q, g2, chiprob: double; + lReport: TStrings; begin - if SelList.Items.Count = 0 then - begin - MessageDlg('No variable(s) selected.', mtError, [mbOK], 0); - exit; - end; + selCount := SelList.Items.Count; + SetLength(ColNoSelected, selCount); - SetLength(ColNoSelected,NoVariables); - C1 := 0.0; - k := SelList.Items.Count; - - // Get column numbers and labels of variables selected - for i := 1 to k do - begin - cellstring := SelList.Items.Strings[i-1]; - for j := 1 to NoVariables do - if (cellstring = OS3MainFrm.DataGrid.Cells[j,0]) then - ColNoSelected[i-1] := j; - end; + // Get column numbers of variables selected + for i := 0 to selCount-1 do + ColNoSelected[i] := GetVariableIndex(OS3MainFrm.DataGrid, SelList.Items[i]); // Calculate results + C1 := 0.0; R1 := 0.0; L1 := 0.0; L2 := 0.0; @@ -145,39 +96,39 @@ begin g2 := 0.0; for i := 1 to NoCases do begin - if (not GoodRecord(i,k,ColNoSelected)) then continue; - for j := 1 to k do + if (not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected)) then continue; + for j := 0 to selCount-1 do begin - col := ColNoSelected[j-1]; - R1 := R1 + StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,i])); + col := ColNoSelected[j]; + R1 := R1 + StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col, i])); end; L1 := L1 + R1; L2 := L2 + (R1 * R1); R1 := 0.0; end; - for j := 1 to k do + for j := 0 to selCount-1 do begin for i := 1 to NoCases do begin - if (not GoodRecord(i,k,ColNoSelected)) then continue; - col := ColNoSelected[j-1]; - C1 := C1 + StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,i])); + if (not GoodRecord(OS3MainFrm.DataGrid, i, ColNoSelected)) then continue; + col := ColNoSelected[j]; + C1 := C1 + StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col, i])); end; g1 := g1 + C1; g2 := g2 + (C1 * C1); C1 := 0.0; end; - if (k * L1 - L2) > 0.0 then + if (selCount * L1 - L2) > 0.0 then begin - Q := ((k - 1) * ((k * g2) - (g1 * g1))) / ((k * L1) - L2); - chiprob := 1.0 - chisquaredprob(Q, k - 1); + Q := ((selCount - 1) * ((selCount * g2) - (g1 * g1))) / ((selCount * L1) - L2); + chiProb := 1.0 - ChiSquaredProb(Q, selCount - 1); end else begin Q := 0.0; - chiprob := 1.0; - Messagedlg('Error in obtaining Q and the probability.', mtError, [mbOK], 0); + chiProb := 1.0; + ErrorMsg('Error in obtaining Q and the probability.'); end; //present results @@ -187,16 +138,17 @@ begin lReport.Add('See pages 161-166 in S. Siegel: Nonparametric Statistics for the Behavioral Sciences'); lReport.Add('McGraw-Hill Book Company, New York, 1956'); lReport.Add(''); - lReport.Add('Cochran Q Statistic: %6.3f', [Q]); - lReport.Add('which is distributed as chi-square with %d D.F. and probability %.4f', [k-1, chiprob]); - DisplayReport(lReport); + lReport.Add('Cochran Q Statistic: %.3f', [Q]); + lReport.Add('which is distributed as chi-square'); + lReport.Add('with %d degrees of freedum and probability %.4f', [selCount-1, chiProb]); + FReportFrame.DisplayReport(lReport); finally lReport.Free; - ColNoSelected := nil; end; end; -procedure TCochranQFrm.InBtnClick(Sender: TObject); + +procedure TCochranQForm.InBtnClick(Sender: TObject); var i: integer; begin @@ -214,7 +166,8 @@ begin UpdateBtnStates; end; -procedure TCochranQFrm.OutBtnClick(Sender: TObject); + +procedure TCochranQForm.OutBtnClick(Sender: TObject); var i: integer; begin @@ -232,21 +185,77 @@ begin UpdateBtnStates; end; -procedure TCochranQFrm.UpdateBtnStates; + +procedure TCochranQForm.Reset; +var + i: integer; begin + inherited; + VarList.Clear; + SelList.Clear; + for i := 1 to NoVariables do + VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); + UpdateBtnStates; +end; + + +procedure TCochranQForm.SelListDblClick(Sender: TObject); +var + index: Integer; +begin + index := SelList.ItemIndex; + if index > -1 then + begin + VarList.Items.Add(SelList.Items[index]); + SelList.Items.Delete(index); + UpdateBtnStates; + end; +end; + + +procedure TCochranQForm.UpdateBtnStates; +begin + inherited; InBtn.Enabled := AnySelected(VarList); OutBtn.Enabled := AnySelected(SelList); AllBtn.Enabled := VarList.Items.Count > 0; end; -procedure TCochranQFrm.VarListSelectionChange(Sender: TObject; User: boolean); + +function TCochranQForm.Validate(out AMsg: String; out AControl: TWinControl): Boolean; +begin + Result := false; + + if SelList.Items.Count = 0 then + begin + AMsg := 'No variable(s) selected.'; + AControl := VarList; + exit; + end; + + Result := true; +end; + + +procedure TCochranQForm.VarListDblClick(Sender: TObject); +var + index: Integer; +begin + index := VarList.ItemIndex; + if index > -1 then + begin + SelList.Items.Add(VarList.Items[index]); + Varlist.Items.Delete(index); + UpdateBtnStates; + end; +end; + + +procedure TCochranQForm.VarListSelectionChange(Sender: TObject; User: boolean); begin UpdateBtnStates; end; -initialization - {$I cochranqunit.lrs} - end. diff --git a/applications/lazstats/source/forms/mainunit.pas b/applications/lazstats/source/forms/mainunit.pas index da57e4938..e8a956a6f 100644 --- a/applications/lazstats/source/forms/mainunit.pas +++ b/applications/lazstats/source/forms/mainunit.pas @@ -1872,9 +1872,9 @@ end; // Menu "Analysis" > "Nonparametric" > "Cochran Q Test" procedure TOS3MainFrm.mnuAnalysisNonPar_CochranClick(Sender: TObject); begin - if CochranQFrm = nil then - Application.CreateForm(TCochranQFrm, CochranQFrm); - CochranQFrm.ShowModal; + if CochranQForm = nil then + Application.CreateForm(TCochranQForm, CochranQForm); + CochranQForm.Show; end; // Menu "Analysis" > "Nonparametric" > "Sign Test"