From ea551b66f3c7e568e395f98d261d74eaf1c8f999 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Sat, 24 Oct 2020 20:38:29 +0000 Subject: [PATCH] LazStats: Use TAChart in ABRAnovaUnit. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7796 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../analysis/comparisons/abranovaunit.lfm | 2 - .../analysis/comparisons/abranovaunit.pas | 278 ++++++++++-------- .../misc/basicstatsreportandchartformunit.lfm | 4 +- .../lazstats/source/frames/chartframeunit.lfm | 3 + 4 files changed, 166 insertions(+), 121 deletions(-) diff --git a/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.lfm b/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.lfm index a4c11b907..bc796c5d8 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.lfm +++ b/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.lfm @@ -311,8 +311,6 @@ inherited ABRAnovaForm: TABRAnovaForm Left = 350 Height = 336 Width = 465 - ActivePage = ChartPage - TabIndex = 1 end object ListChartSource_AB: TListChartSource[3] Left = 465 diff --git a/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.pas b/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.pas index 118f1177a..7d9b7c0df 100644 --- a/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.pas +++ b/applications/lazstats/source/forms/analysis/comparisons/abranovaunit.pas @@ -7,10 +7,9 @@ unit ABRANOVAUnit; interface uses - contexthelpunit, Classes, SysUtils, FileUtil, TASources, TAStyles, Forms, + Classes, SysUtils, FileUtil, TASources, TAStyles, Forms, Controls, Graphics, Dialogs, StdCtrls, Buttons, ExtCtrls, ComCtrls, MainUnit, - FunctionsLib, GraphLib, Globals, DataProcs, MatrixLib, - BasicStatsReportAndChartFormUnit; + FunctionsLib, Globals, DataProcs, MatrixLib, BasicStatsReportAndChartFormUnit; type @@ -49,7 +48,9 @@ type procedure COutBtnClick(Sender: TObject); procedure VarListDblClick(Sender: TObject); private - { private declarations } + type TInteraction = (AB, AC, BC); + + private ColNoSelected: IntDyneVec; ACol, BCol, NoSelected, MinA, MaxA, MinB, MaxB, NoAGrps, NoBGrps : integer; group, MaxRows, MaxCols, TotalN, NinGrp : integer; @@ -69,13 +70,16 @@ type RowLabels, ColLabels : StrDyneVec; selected : integer; + FBtnAB, FBtnAC, FBtnBC: TToolButton; + procedure InteractionChanged(Sender: TObject); + function InitData: Boolean; procedure GetData; procedure Calculate; procedure Summarize(AReport: TStrings); procedure MeansReport(AReport: TStrings); procedure BoxTests(AReport: TStrings); - procedure GraphMeans; + procedure PlotMeans(AInteraction: TInteraction); procedure CleanUp; protected @@ -99,15 +103,53 @@ implementation uses Math, - MathUnit, GridProcs; + TAChartUtils, TALegend, TACustomSource, TACustomSeries, TASeries, + Utils, MathUnit, GridProcs, ChartFrameUnit; { TABRAnovaForm } constructor TABRAnovaForm.Create(AOwner: TComponent); +var + btn: TToolButton; begin inherited; - if GraphFrm = nil then - Application.CreateForm(TGraphFrm, GraphFrm); + + FChartFrame.Chart.Margins.Bottom := 0; + FChartFrame.Chart.BottomAxis.AxisPen.Visible := true; + FChartFrame.Chart.BottomAxis.ZPosition := 1; + FChartFrame.Chart.BottomAxis.Grid.Visible := false; + + FChartFrame.ChartToolbar.ShowCaptions := true; + FChartFrame.ChartToolbar.ButtonHeight := 40;; + + + btn := TToolButton.Create(FChartFrame.ChartToolbar); + btn.Style := tbsDivider; + AddButtonToToolbar(btn, FChartFrame.ChartToolbar); + + FBtnAB := TToolButton.Create(FChartFrame.ChartToolbar); + FBtnAB.Caption := 'AB interaction'; + FBtnAB.Down := true; + FBtnAB.Style := tbsCheck; + FBtnAB.Grouped := true; + FBtnAB.OnClick := @InteractionChanged; + AddButtonToToolbar(FBtnAB, FChartFrame.ChartToolbar); + + FBtnAC := TToolButton.Create(FChartFrame.ChartToolbar); + FBtnAC.Caption := 'AC interaction'; + FBtnAC.Grouped := true; + FBtnAC.Style := tbsCheck; + FBtnAC.OnClick := @InteractionChanged; + AddButtonToToolbar(FBtnAC, FChartFrame.ChartToolbar); + + FBtnBC := TToolButton.Create(FChartFrame.ChartToolbar); + FbtnBC.Caption := 'BC interaction'; + FBtnBC.Grouped := true; + FBtnBC.Style := tbsCheck; + FBtnBC.OnClick := @InteractionChanged; + AddButtonToToolbar(FBtnBC, FChartFrame.ChartToolbar); + + PageControl.ActivePageIndex := 0; end; @@ -210,9 +252,11 @@ begin Acnt := nil; SumPSqr := nil; AMatrix := nil; - BCSums := nil; + { + BCSums := nil; // needed for plotting ACSums := nil; ABSums := nil; + } CSums := nil; BSums := nil; ASums := nil; @@ -243,6 +287,7 @@ end; procedure TABRAnovaForm.Compute; var lReport: TStrings; + interaction: TInteraction; begin lReport := TStringList.Create; try @@ -252,9 +297,18 @@ begin Calculate; Summarize(lReport); MeansReport(lReport); - if TestChk.Checked then BoxTests(lReport); + if TestChk.Checked then + BoxTests(lReport); + FReportFrame.DisplayReport(lReport); - if PlotChk.Checked then GraphMeans; + + if PlotChk.Checked then + begin + if FBtnAB.Down then interaction := AB else + if FBtnAC.Down then interaction := AC else + if FBtnBC.Down then interaction := BC; + PlotMeans(interaction); + end; end; finally lReport.Free; @@ -389,6 +443,23 @@ begin Result := true; end; +procedure TABRAnovaForm.InteractionChanged(Sender: TObject); +var + interaction: TInteraction; +begin + if TObject(Sender) is TToolButton then + TToolButton(Sender).Down := true; + + if FBtnAB.Down then + interaction := AB + else if FBtnAC.Down then + interaction := AC + else if FBtnBC.Down then + interaction := BC; + + PlotMeans(interaction); +end; + procedure TABRAnovaForm.GetData; var i, j, SubjA, SubjB: integer; @@ -868,120 +939,93 @@ begin XVector := nil; end; -procedure TABRAnovaForm.GraphMeans; + +procedure TABRAnovaForm.PlotMeans(AInteraction: TInteraction); +const + X_TITLE: array[TInteraction] of string = ( + 'B TREATMENT GROUP', + 'C TREATMENT (WITHIN SUBJECTS) GROUP', + 'C TREATMENT (WITHIN SUBJECTS) GROUP' + ); + SERIES_TITLE: array[TInteraction] of string = ( + 'A%d', + 'A%d', + 'B%d' + ); + var - MaxMean : double; - i, j : integer; + idx: Integer; + item: PChartDataItem; + ser: TChartSeries; + serSource: TListChartSource; + i, j: Integer; begin - // Do AB interaction - // Get maximum cell mean - MaxMean := ABSums[0,0] / (NinGrp*NoSelected); - SetLength(GraphFrm.Ypoints,NoAGrps,NoBGrps); - SetLength(GraphFrm.Xpoints,1,NoBGrps); - for i := 1 to NoAGrps do - begin - GraphFrm.SetLabels[i] := 'A ' + IntToStr(i); - for j := 1 to NoBGrps do - begin - GraphFrm.Ypoints[i-1,j-1] := ABSums[i-1,j-1] / (NinGrp * NoSelected); - if GraphFrm.Ypoints[i-1,j-1] > MaxMean then MaxMean := GraphFrm.Ypoints[i-1,j-1]; - end; - end; - for j := 1 to NoBGrps do - begin - GraphFrm.Xpoints[0,j-1] := j; - end; + FChartFrame.Clear; + ListChartSource_AB.Clear; + ListChartSource_AC.Clear; + ListChartSource_BC.Clear; + ChartStyles.Styles.Clear; - GraphFrm.nosets := NoAGrps; - GraphFrm.nbars := NoBGrps; - GraphFrm.Heading := 'AxBxR ANOVA'; - GraphFrm.XTitle := 'B TREATMENT GROUP'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.5; - GraphFrm.AutoScaled := false; - GraphFrm.GraphType := 2; // 3d Vertical Bar Chart - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; + ListChartSource_AB.YCount := NoAGrps; + for j := 0 to NoBGrps-1 do + begin + idx := ListChartSource_AB.Add(j+1, 0); + item := ListChartSource_AB.Item[idx]; + for i := 0 to NoAGrps-1 do + item^.SetY(i, ABSums[i, j] / (NInGrp * NoSelected)); + end; - // Do AC interaction - MaxMean := ACSums[0,0] / (NinGrp*NoBGrps); - SetLength(GraphFrm.Ypoints,NoAGrps,NoSelected); - SetLength(GraphFrm.Xpoints,1,NoSelected); - for i := 1 to NoAGrps do - begin - GraphFrm.SetLabels[i] := 'A ' + IntToStr(i); - for j := 1 to NoSelected do - begin - GraphFrm.Ypoints[i-1,j-1] := ACSums[i-1,j-1] / (NinGrp * NoBGrps); - if GraphFrm.Ypoints[i-1,j-1] > MaxMean then MaxMean := GraphFrm.Ypoints[i-1,j-1]; - end; - end; - for j := 1 to NoSelected do - begin - GraphFrm.Xpoints[0,j-1] := j; - end; - GraphFrm.nosets := NoAGrps; - GraphFrm.nbars := NoSelected; - GraphFrm.Heading := 'AxBxR ANOVA'; - GraphFrm.XTitle := 'C TREATMENT (WITHIN SUBJECTS) GROUP'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.5; - GraphFrm.AutoScaled := false; - GraphFrm.GraphType := 2; // 3d Vertical Bar Chart - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; + ListChartSource_AC.YCount := NoAGrps; + for j := 0 to NoSelected-1 do + begin + idx := ListChartSource_AC.Add(j+1, 0); + item := ListChartSource_AC.Item[idx]; + for i := 0 to NoAGrps-1 do + item^.SetY(i, ACSums[i, j] / (NInGrp * NoBGrps)); + end; - // Do BC interaction - SetLength(GraphFrm.Ypoints,NoBGrps,NoSelected); - SetLength(GraphFrm.Xpoints,NoSelected); - MaxMean := BCSums[0,0] / (NinGrp*NoAGrps); - for i := 1 to NoBGrps do - for j := 1 to NoSelected do - if ((BCSums[i-1,j-1] / (NinGrp*NoAGrps)) > MaxMean) then - MaxMean := BCSums[i-1,j-1] / (NinGrp*NoAGrps); - for i := 1 to NoBGrps do + ListChartSource_BC.YCount := NoBGrps; + for j := 0 to NoSelected-1 do + begin + idx := ListChartSource_BC.Add(j+1, 0); + item := ListChartSource_BC.Item[idx]; + for i := 0 to NoBGrps-1 do + item^.SetY(i, BCSums[i, j] / (NInGrp * NoAGrps)); + end; + + case AInteraction of + AB: serSource := ListChartSource_AB; + AC: serSource := ListChartSource_AC; + BC: serSource := ListChartSource_BC; + end; + + ser := FChartFrame.PlotXY(ptBars, nil, nil, nil, nil, '', clDefault); + with TBarSeries(ser) do + begin + Source := serSource; + Legend.Multiplicity := lmStyle; + Stacked := false; + Styles := ChartStyles; + end; + + for i := 0 to ser.Source.YCount-1 do + begin + with TChartStyle(ChartStyles.Styles.Add) do begin - GraphFrm.SetLabels[i] := 'B ' + IntToStr(i); - for j := 1 to NoSelected do - begin - GraphFrm.Ypoints[i-1,j-1] := BCSums[i-1,j-1] / (NinGrp * NoAGrps); - if GraphFrm.Ypoints[i-1,j-1] > MaxMean then MaxMean := GraphFrm.Ypoints[i-1,j-1]; - end; + Text := Format(SERIES_TITLE[AInteraction], [i+1]); + Brush.Color := DATA_COLORS[i mod Length(DATA_COLORS)]; + UseBrush := true; end; - for j := 1 to NoSelected do - begin - GraphFrm.Xpoints[0,j-1] := j; - end; - GraphFrm.nosets := NoBGrps; - GraphFrm.nbars := NoSelected; - GraphFrm.Heading := 'AxBxR ANOVA'; - GraphFrm.XTitle := 'C TREATMENT (WITHIN SUBJECTS) GROUP'; - GraphFrm.YTitle := 'Mean'; - GraphFrm.barwideprop := 0.5; - GraphFrm.AutoScaled := false; - GraphFrm.GraphType := 2; // 3d Vertical Bar Chart - GraphFrm.miny := 0.0; - GraphFrm.maxy := maxmean; - GraphFrm.BackColor := clCream; - GraphFrm.WallColor := clDkGray; - GraphFrm.FloorColor := clLtGray; - GraphFrm.ShowBackWall := true; - GraphFrm.ShowModal; - // cleanup the heap - GraphFrm.Xpoints := nil; - GraphFrm.Ypoints := nil; + end; + + FChartFrame.Chart.BottomAxis.Marks.Source := ser.Source; + FChartFrame.Chart.BottomAxis.Marks.Style := smsXValue; + FChartFrame.SetTitle('AxBxR ANOVA'); + FChartFrame.SetXTitle(X_TITLE[AInteraction]); + FChartFrame.SetYTitle('Means'); end; + procedure TABRAnovaForm.Reset; var i: integer; @@ -1053,7 +1097,7 @@ begin if CList.Items.Count = 0 then begin - AMsg := 'No Repeated Measures variables specified.'; + AMsg := 'No Repeated Measures variable(s) specified.'; AControl := CList; exit; end; diff --git a/applications/lazstats/source/forms/misc/basicstatsreportandchartformunit.lfm b/applications/lazstats/source/forms/misc/basicstatsreportandchartformunit.lfm index 674209486..d9f261a2f 100644 --- a/applications/lazstats/source/forms/misc/basicstatsreportandchartformunit.lfm +++ b/applications/lazstats/source/forms/misc/basicstatsreportandchartformunit.lfm @@ -31,13 +31,13 @@ inherited BasicStatsReportAndChartForm: TBasicStatsReportAndChartForm Height = 434 Top = 8 Width = 396 - ActivePage = ReportPage + ActivePage = ChartPage Align = alClient BorderSpacing.Left = 4 BorderSpacing.Top = 8 BorderSpacing.Right = 8 BorderSpacing.Bottom = 8 - TabIndex = 0 + TabIndex = 1 TabOrder = 2 object ReportPage: TTabSheet Caption = 'Report' diff --git a/applications/lazstats/source/frames/chartframeunit.lfm b/applications/lazstats/source/frames/chartframeunit.lfm index 24b9a6e80..f4f10304d 100644 --- a/applications/lazstats/source/frames/chartframeunit.lfm +++ b/applications/lazstats/source/frames/chartframeunit.lfm @@ -69,6 +69,7 @@ object ChartFrame: TChartFrame Caption = 'Save' ImageIndex = 4 OnClick = tbSaveChartClick + ShowCaption = False end object tbPrintChart: TToolButton Left = 26 @@ -77,6 +78,7 @@ object ChartFrame: TChartFrame Caption = 'Print' ImageIndex = 5 OnClick = tbPrintChartClick + ShowCaption = False end object tbCopyChart: TToolButton Left = 51 @@ -85,6 +87,7 @@ object ChartFrame: TChartFrame Caption = 'Copy' ImageIndex = 7 OnClick = tbCopyChartClick + ShowCaption = False end end object PrintDialog: TPrintDialog