You've already forked lazarus-ccr
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7898 8e941d3f-bd1b-0410-a28a-d453659cc2b4
722 lines
18 KiB
ObjectPascal
722 lines
18 KiB
ObjectPascal
{ Test file: ABNested.laz (imported from OpenStat sample data zip file)
|
|
Dependent: Dep
|
|
Factor A : A
|
|
Factor B : B
|
|
}
|
|
|
|
unit BNestAUnit;
|
|
|
|
{$MODE objfpc}{$H+}
|
|
{$WARN 6058 off : Call to subroutine "$1" marked as inline is not inlined}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Forms, Controls, Graphics, LCLVersion,
|
|
StdCtrls, Buttons, ExtCtrls, ComCtrls,
|
|
TACustomSeries,
|
|
MainUnit, Globals, ReportFrameUnit, BasicStatsReportAndChartFormUnit;
|
|
|
|
type
|
|
|
|
{ TBNestedAForm }
|
|
|
|
TBNestedAForm = class(TBasicStatsReportAndChartForm)
|
|
ACodesEdit: TEdit;
|
|
AInBtn: TBitBtn;
|
|
AOutBtn: TBitBtn;
|
|
BCodesEdit: TEdit;
|
|
BInBtn: TBitBtn;
|
|
BOutBtn: TBitBtn;
|
|
Plot3DChk: TCheckBox;
|
|
PlotOptionsGroup: TGroupBox;
|
|
RandomBChk: TCheckBox;
|
|
DepInBtn: TBitBtn;
|
|
DepOutBtn: TBitBtn;
|
|
DepEdit: TEdit;
|
|
Label1: TLabel;
|
|
Label2: TLabel;
|
|
Label3: TLabel;
|
|
Label4: TLabel;
|
|
MeansPage: TTabSheet;
|
|
ShowPlotsChk: TCheckBox;
|
|
VarList: TListBox;
|
|
procedure AInBtnClick(Sender: TObject);
|
|
procedure AOutBtnClick(Sender: TObject);
|
|
procedure BInBtnClick(Sender: TObject);
|
|
procedure BOutBtnClick(Sender: TObject);
|
|
procedure DepInBtnClick(Sender: TObject);
|
|
procedure DepOutBtnClick(Sender: TObject);
|
|
procedure Plot3DChkChange(Sender: TObject);
|
|
procedure ShowPlotsChkChange(Sender: TObject);
|
|
procedure VarListDblClick(Sender: TObject);
|
|
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
|
|
|
|
private
|
|
SS, SumSqr, CellMeans, CellSDs : DblDyneMat;
|
|
CellCount : IntDyneMat;
|
|
ASS, BSS, ASumSqr, BSumSqr, AMeans, BMeans, ASDs : DblDyneVec;
|
|
ACount, BCount : IntDyneVec;
|
|
MinA, MinB, MaxA, MaxB, NoALevels, NoBLevels: integer;
|
|
SSTot, SumSqrTot, TotMean, MSTot, SSA, MSA, SSB, MSB, SSW, MSW : double;
|
|
TotN, dfA, dfBwA, dfwcell, dftotal : integer;
|
|
|
|
function GetVariables(out AValues, BValues, DepValues: DblDyneVec): Boolean;
|
|
procedure GetMemory;
|
|
procedure GetSums(const AValues, BValues, DepValues: DblDyneVec);
|
|
procedure ShowMeans;
|
|
procedure GetResults;
|
|
procedure ShowResults;
|
|
procedure ReleaseMemory;
|
|
procedure TwoWayPlot;
|
|
|
|
private
|
|
FMeansReportFrame: TReportFrame;
|
|
FChartCombobox: TCombobox;
|
|
FSeries: TChartSeries;
|
|
procedure PopulateChartCombobox;
|
|
procedure SelectPlot(Sender: TObject);
|
|
|
|
protected
|
|
procedure AdjustConstraints; override;
|
|
procedure Compute; override;
|
|
procedure UpdateBtnStates; override;
|
|
function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override;
|
|
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure Reset; override;
|
|
end;
|
|
|
|
var
|
|
BNestedAForm: TBNestedAForm;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
uses
|
|
Math,
|
|
TAChartUtils, TACustomSource, TALegend, TASeries,
|
|
Utils, MathUnit, MatrixUnit, GridProcs, ChartFrameUnit;
|
|
|
|
{ TBNestedAForm }
|
|
|
|
constructor TBNestedAForm.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
|
|
FMeansReportFrame := TReportFrame.Create(MeansPage);
|
|
FMeansReportFrame.Parent := MeansPage;
|
|
FMeansReportFrame.Align := alClient;
|
|
InitToolbar(FMeansReportFrame.ReportToolbar, tpTop);
|
|
MeansPage.PageIndex := 1;
|
|
|
|
FChartFrame.Chart.Margins.Bottom := 0;
|
|
FChartFrame.Chart.BottomAxis.AxisPen.Visible := true;
|
|
FChartFrame.Chart.BottomAxis.ZPosition := 1;
|
|
FChartFrame.Chart.BottomAxis.Grid.Visible := false;
|
|
AddComboboxToToolbar(FChartFrame.ChartToolbar, 'Plots:', FChartCombobox);
|
|
FChartCombobox.OnSelect := @SelectPlot;
|
|
|
|
PageControl.ActivePageIndex := 0;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.AdjustConstraints;
|
|
begin
|
|
inherited;
|
|
|
|
ParamsPanel.Constraints.MinWidth := Max(
|
|
4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left,
|
|
Max(Label3.Width, RandomBChk.Width) * 2 + AInBtn.Width + 2*VarList.BorderSpacing.Right
|
|
);
|
|
ParamsPanel.Constraints.MinHeight := RandomBChk.Top + RandomBChk.Height +
|
|
VarList.BorderSpacing.Bottom + PlotOptionsGroup.Height +
|
|
ButtonBevel.Height + CloseBtn.Height + CloseBtn.BorderSpacing.Top;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.AInBtnClick(Sender: TObject);
|
|
var
|
|
index: integer;
|
|
begin
|
|
index := VarList.ItemIndex;
|
|
if (index > -1) and (ACodesEdit.Text = '') then
|
|
begin
|
|
ACodesEdit.Text := VarList.Items[index];
|
|
VarList.Items.Delete(index);
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.AOutBtnClick(Sender: TObject);
|
|
begin
|
|
if ACodesEdit.Text <> '' then
|
|
begin
|
|
VarList.Items.Add(ACodesEdit.Text);
|
|
ACodesEdit.Text := '';
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.BInBtnClick(Sender: TObject);
|
|
var
|
|
index: integer;
|
|
begin
|
|
index := VarList.ItemIndex;
|
|
if (index > -1) and (BCodesEdit.Text = '') then
|
|
begin
|
|
BCodesEdit.Text := VarList.Items[index];
|
|
VarList.Items.Delete(index);
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.BOutBtnClick(Sender: TObject);
|
|
begin
|
|
if BCodesEdit.Text <> '' then
|
|
begin
|
|
VarList.Items.Add(BCodesEdit.Text);
|
|
BCodesEdit.Text := '';
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.Compute;
|
|
var
|
|
dataA: DblDyneVec = nil;
|
|
dataB: DblDyneVec = nil;
|
|
dataDep: DblDyneVec = nil;
|
|
begin
|
|
if GetVariables(dataA, dataB, dataDep) then
|
|
begin
|
|
GetMemory;
|
|
GetSums(dataA, dataB, dataDep);
|
|
ShowMeans;
|
|
GetResults;
|
|
ShowResults;
|
|
TwoWayPlot;
|
|
ReleaseMemory;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.DepInBtnClick(Sender: TObject);
|
|
var
|
|
index: integer;
|
|
begin
|
|
index := VarList.ItemIndex;
|
|
if (index > -1) and (DepEdit.Text = '') then
|
|
begin
|
|
DepEdit.Text := VarList.Items[index];
|
|
VarList.Items.Delete(index);
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.DepOutBtnClick(Sender: TObject);
|
|
begin
|
|
if DepEdit.Text <> '' then
|
|
begin
|
|
VarList.Items.Add(DepEdit.Text);
|
|
DepEdit.Text := '';
|
|
end;
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.Plot3DChkChange(Sender: TObject);
|
|
begin
|
|
if FSeries is TBarSeries then
|
|
begin
|
|
if Plot3dChk.Checked then
|
|
TBarSeries(FSeries).Depth := 20
|
|
else
|
|
TBarSeries(FSeries).Depth := 0;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.ShowPlotsChkChange(Sender: TObject);
|
|
begin
|
|
ChartPage.TabVisible := ShowPlotsChk.Checked;
|
|
Plot3DChk.Enabled := ShowPlotsChk.Checked;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.GetMemory;
|
|
begin
|
|
SS := MatCreate(NoBLevels,NoALevels);
|
|
SumSqr := MatCreate(NoBLevels,NoALevels);
|
|
CellCount := IntMatCreate(NoBLevels,NoALevels);
|
|
CellMeans := MatCreate(NoBLevels,NoALevels);
|
|
CellSDs := MatCreate(NoBLevels,NoALevels);
|
|
|
|
ASS := VecCreate(NoALevels);
|
|
BSS := VecCreate(NoBLevels);
|
|
ASumSqr := VecCreate(NoALevels);
|
|
BSumSqr := VecCreate(NoBLevels);
|
|
AMeans := VecCreate(NoALevels);
|
|
BMeans := VecCreate(NoBLevels);
|
|
ACount := IntVecCreate(NoALevels);
|
|
BCount := IntVecCreate(NoBLevels);
|
|
ASDs := VecCreate(NoALevels);
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.GetResults;
|
|
VAR
|
|
temp, constant : double;
|
|
NoBLevelsInA, BLevCount, i, j, celln : integer;
|
|
begin
|
|
celln := 0;
|
|
for i := 0 to NoALevels-1 do
|
|
for j := 0 to NoBLevels-1 do
|
|
if CellCount[j,i] > celln then celln := CellCount[j,i];
|
|
|
|
// Assume all cells have same n size
|
|
// Get number of levels in A
|
|
BLevCount := 0;
|
|
for i := 0 to NoALevels-1 do
|
|
begin
|
|
NoBLevelsInA := 0;
|
|
for j := 0 to NoBLevels-1 do
|
|
if CellCount[j,i] > 0 then NoBLevelsInA := NoBLevelsInA + 1;
|
|
if NoBLevelsInA > BLevCount then BLevCount := NoBLevelsInA;
|
|
end;
|
|
|
|
dfA := NoALevels - 1;
|
|
dfBwA := NoALevels * (BLevCount - 1);
|
|
dfwcell := NoALevels * BLevCount * (celln - 1);
|
|
dftotal := TotN - 1;
|
|
|
|
constant := SumSqrTot / TotN;
|
|
SSTot := SSTot - constant;
|
|
MSTot := SSTot / dftotal;
|
|
|
|
SSA := 0.0;
|
|
for i := 0 to NoALevels-1 do SSA := SSA + (ASumSqr[i] / ACount[i]);
|
|
temp := SSA;
|
|
SSA := SSA - constant;
|
|
MSA := SSA / dfA;
|
|
|
|
SSB := 0.0;
|
|
for i := 0 to NoALevels - 1 do
|
|
for j := 0 to NoBLevels-1 do
|
|
if CellCount[j,i] > 0 then SSB := SSB + (SumSqr[j,i] / CellCount[j,i]);
|
|
SSB := SSB - temp;
|
|
|
|
MSB := SSB / dfBwA;
|
|
SSW := SSTot - SSA - SSB;
|
|
MSW := SSW / dfwcell;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.GetSums(const AValues, BValues, DepValues: DblDyneVec);
|
|
var
|
|
AIndex, BIndex, i, j: integer;
|
|
YValue, YValueSqr: double;
|
|
begin
|
|
// Accumulate sums and sums of squared values
|
|
SSTot := 0;
|
|
SumSqrTot := 0;
|
|
TotN := 0;
|
|
for i := 0 to High(DepValues) do
|
|
begin
|
|
AIndex := round(AValues[i]) - MinA;
|
|
BIndex := round(BValues[i]) - MinB;
|
|
YValue := DepValues[i];
|
|
YValueSqr := YValue * YValue;
|
|
{
|
|
strvalue := Trim(OS3MainFrm.DataGrid.Cells[ACol,i]);
|
|
Aindex := round(StrToFloat(strvalue));
|
|
strvalue := Trim(OS3MainFrm.DataGrid.Cells[BCol,i]);
|
|
Bindex := round(StrToFloat(strvalue));
|
|
strvalue := Trim(OS3MainFrm.DataGrid.Cells[YCol,i]);
|
|
YValue := StrToFloat(strvalue);
|
|
Aindex := Aindex - MinA;
|
|
Bindex := Bindex - MinB;
|
|
}
|
|
SS[BIndex, AIndex] := SS[BIndex, AIndex] + YValueSqr;
|
|
SumSqr[BIndex, AIndex] := SumSqr[BIndex, AIndex] + YValue;
|
|
CellCount[BIndex, AIndex] := CellCount[BIndex, AIndex] + 1;
|
|
ACount[AIndex] := ACount[AIndex] + 1;
|
|
BCount[BIndex] := BCount[BIndex] + 1;
|
|
ASS[AIndex] := ASS[AIndex] + YValueSqr;
|
|
BSS[BIndex] := BSS[BIndex] + YValueSqr;
|
|
ASumSqr[AIndex] := ASumSqr[AIndex] + YValue;
|
|
BSumSqr[BIndex] := BSumSqr[BIndex] + YValue;
|
|
SSTot := SSTot + YValueSqr;
|
|
SumSqrTot := SumSqrTot + YValue;
|
|
TotN := TotN + 1;
|
|
end;
|
|
|
|
// Get cell means and marginal means, SDs plus square of sums
|
|
for i := 0 to NoBlevels-1 do
|
|
begin
|
|
for j := 0 to NoALevels-1 do
|
|
begin
|
|
if CellCount[i,j] > 0 then
|
|
begin
|
|
CellMeans[i,j] := SumSqr[i,j] / CellCount[i,j];
|
|
SumSqr[i,j] := SumSqr[i,j] * SumSqr[i,j];
|
|
CellSDs[i,j] := SS[i,j] - (SumSqr[i,j] / CellCount[i,j]);
|
|
CellSDs[i,j] := CellSDs[i,j] / (CellCount[i,j] - 1);
|
|
CellSDs[i,j] := Sqrt(CellSDs[i,j]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
for i := 0 to NoBLevels-1 do
|
|
begin
|
|
BMeans[i] := BSumSqr[i] / BCount[i];
|
|
BSumSqr[i] := BSumSqr[i] * BSumSqr[i];
|
|
end;
|
|
|
|
for i := 0 to NoALevels-1 do
|
|
begin
|
|
AMeans[i] := ASumSqr[i] / ACount[i];
|
|
ASumSqr[i] := ASumSqr[i] * ASumSqr[i];
|
|
ASDs[i] := ASS[i] - (ASumSqr[i] / ACount[i]);
|
|
ASDs[i] := ASDs[i] / (ACount[i] - 1);
|
|
ASDs[i] := Sqrt(ASDs[i]);
|
|
end;
|
|
|
|
TotMean := SumSqrTot / TotN;
|
|
SumSqrTot := SumSqrTot * SumSqrTot;
|
|
end;
|
|
|
|
|
|
function TBNestedAForm.GetVariables(
|
|
out AValues, BValues, DepValues: DblDyneVec): Boolean;
|
|
var
|
|
ColNoSelected: IntDyneVec = nil;
|
|
mn, mx: Double;
|
|
msg: String;
|
|
begin
|
|
Result := false;
|
|
|
|
SetLength(ColNoSelected, 3);
|
|
ColNoSelected[0] := GetVariableIndex(OS3MainFrm.DataGrid, ACodesEdit.Text); // A
|
|
ColNoSelected[1] := GetVariableIndex(OS3MainFrm.DataGrid, BCodesEdit.Text); // B
|
|
ColNoSelected[2] := GetVariableindex(OS3MainFrm.DataGrid, DepEdit.Text); // Dependent
|
|
|
|
AValues := CollectVecValues(OS3MainFrm.DataGrid, ColNoSelected[0], ColNoSelected);
|
|
if not CheckFactorCodes(ACodesEdit.Text, AValues, msg) then
|
|
begin
|
|
ErrorMsg(msg);
|
|
exit;
|
|
end;
|
|
|
|
BValues := CollectVecValues(OS3MainFrm.DataGrid, ColNoSelected[1], ColNoSelected);
|
|
if not CheckFactorCodes(BCodesEdit.Text, BValues, msg) then
|
|
begin
|
|
ErrorMsg(msg);
|
|
exit;
|
|
end;
|
|
|
|
DepValues := CollectVecValues(OS3MainFrm.DataGrid, ColNoSelected[2], ColNoSelected);
|
|
|
|
if (Length(DepValues) <> Length(AValues)) or
|
|
(Length(DepValues) <> Length(BValues)) then
|
|
begin
|
|
ErrorMsg('All variables must contain equal amounts of cases.');
|
|
exit;
|
|
end;
|
|
|
|
VecMaxMin(AValues, mx, mn);
|
|
MaxA := round(mx);
|
|
MinA := round(mn);
|
|
|
|
VecMaxMin(BValues, mx, mn);
|
|
MaxB := round(mx);
|
|
MinB := round(mn);
|
|
|
|
NoALevels := MaxA - MinA + 1;
|
|
NoBLevels := MaxB - MinB + 1;
|
|
|
|
Result := true;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.ShowMeans;
|
|
var
|
|
lReport: TStrings;
|
|
i, j: integer;
|
|
begin
|
|
lReport := TStringList.Create;
|
|
try
|
|
lReport.Add('NESTED ANOVA by Bill Miller');
|
|
lReport.Add('');
|
|
lReport.Add('File analyzed: %s', [OS3MainFrm.FileNameEdit.Text]);
|
|
lReport.Add('Factor A: %s', [ACodesEdit.Text]);
|
|
lReport.Add('Factor B: %s', [BCodesEdit.Text]);
|
|
lReport.Add('');
|
|
lReport.Add('CELL MEANS');
|
|
lReport.Add('-------------------------------------------');
|
|
lReport.Add('A LEVEL B LEVEL MEAN STD.DEV. ');
|
|
lReport.Add('------- ------- ---------- ----------');
|
|
for i := 0 to NoALevels-1 do
|
|
for j := 0 to NoBLevels-1 do
|
|
if CellCount[j,i] > 0 then
|
|
lReport.Add('%5d %5d %10.3f %10.3f', [i+MinA, j+MinB, CellMeans[j,i], CellSDs[j,i]]);
|
|
lReport.Add('-------------------------------------------');
|
|
lReport.Add('');
|
|
lReport.Add('A MARGIN MEANS');
|
|
lReport.Add('---------------------------------');
|
|
lReport.Add('A LEVEL MEAN STD.DEV. ');
|
|
lReport.Add('------- ---------- ----------');
|
|
for i := 0 to NoALevels-1 do
|
|
lReport.Add('%5d %10.3f %10.3f', [i+MinA, AMeans[i], ASDs[i]]);
|
|
lReport.Add('---------------------------------');
|
|
lReport.Add('');
|
|
lReport.Add('GRAND MEAN: %0.3f', [TotMean]);
|
|
lReport.Add('');
|
|
lReport.Add('');
|
|
|
|
FMeansReportFrame.DisplayReport(lReport);
|
|
finally
|
|
lReport.Free;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.ShowResults;
|
|
var
|
|
F, PF: double;
|
|
lReport: TStrings;
|
|
begin
|
|
lReport := TStringList.Create;
|
|
try
|
|
lReport.Add('NESTED ANOVA by Bill Miller');
|
|
lReport.Add('');
|
|
lReport.Add('File analyzed: %s', [OS3MainFrm.FileNameEdit.Text]);
|
|
lReport.Add('Factor A: %s', [ACodesEdit.Text]);
|
|
lReport.Add('Factor B: %s', [BCodesEdit.Text]);
|
|
lReport.Add('');
|
|
lReport.Add('ANOVA TABLE');
|
|
lReport.Add('-------------------------------------------------------------');
|
|
lReport.Add('SOURCE D.F. SS MS F PROB. ');
|
|
lReport.Add('--------- ---- ---------- ---------- --------- ---------');
|
|
|
|
if RandomBChk.Checked then
|
|
begin
|
|
F := MSA / MSB;
|
|
PF := ProbF(F, dfA, dfBwA);
|
|
end else
|
|
begin
|
|
F := MSA / MSW;
|
|
PF := ProbF(F, dfA, dfwcell);
|
|
end;
|
|
lReport.Add('A %4d %10.3f %10.3f %9.3f %9.3f', [dfA, SSA, MSA, F, PF]);
|
|
|
|
F := MSB / MSW;
|
|
PF := ProbF(F,dfBwA,dfwcell);
|
|
lReport.Add('B(W) %4d %10.3f %10.3f %9.3f %9.3f', [dfBwA, SSB, MSB, F, PF]);
|
|
|
|
lReport.Add('w.cells %4d %10.3f %10.3f', [dfwcell, SSW, MSW]);
|
|
lReport.Add('Total %4d %10.3f', [dftotal, SSTot]);
|
|
lReport.Add('-------------------------------------------------------------');
|
|
|
|
FReportFrame.DisplayReport(lReport);
|
|
finally
|
|
lReport.Free;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.PopulateChartCombobox;
|
|
var
|
|
idx: Integer;
|
|
begin
|
|
idx := FChartCombobox.ItemIndex;
|
|
|
|
FChartCombobox.Items.Clear;
|
|
FChartCombobox.Items.Add(ACodesEdit.Text);
|
|
FChartCombobox.Items.Add(BCodesEdit.Text);
|
|
|
|
FChartCombobox.ItemIndex := EnsureRange(idx, 0, FChartCombobox.Items.Count-1);
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.ReleaseMemory;
|
|
begin
|
|
ASDs := nil;
|
|
BCount := nil;
|
|
ACount := nil;
|
|
// BMeans := nil; // needed for plotting
|
|
// AMeans := nil;
|
|
BSumSqr := nil;
|
|
ASumSqr := nil;
|
|
BSS := nil;
|
|
ASS := nil;
|
|
CellSDs := nil;
|
|
CellMeans := nil;
|
|
CellCount := nil;
|
|
SumSqr := nil;
|
|
SS := nil;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.Reset;
|
|
begin
|
|
inherited;
|
|
|
|
if FMeansReportFrame <> nil then
|
|
FMeansReportFrame.Clear;
|
|
if FChartCombobox <> nil then
|
|
FChartCombobox.Items.Clear;
|
|
|
|
ACodesEdit.Clear;
|
|
BCodesEdit.Clear;
|
|
DepEdit.Clear;
|
|
|
|
CollectVariableNames(OS3MainFrm.DataGrid, VarList.Items);
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.SelectPlot(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
FSeries.Clear;
|
|
|
|
case FChartComboBox.ItemIndex of
|
|
0: begin // Plot means vs factor A
|
|
for i := 0 to NoALevels-1 do
|
|
FSeries.AddXY(MinA + i, AMeans[i], IntToStr(MinA + i));
|
|
FChartFrame.SetXTitle(ACodesEdit.Text + ' codes');
|
|
FChartFrame.SetTitle('Factor ' + ACodesEdit.Text);
|
|
end;
|
|
1: begin // Plot means vs factor B
|
|
for i := 0 to NoBLevels-1 do
|
|
FSeries.AddXY(MinB + i, BMeans[i], IntToStr(MinB + i));
|
|
FChartFrame.SetXTitle(BCodesEdit.Text + ' codes');
|
|
FChartFrame.SetTitle('Factor ' + BCodesEdit.Text);
|
|
end;
|
|
end;
|
|
|
|
FChartFrame.Chart.BottomAxis.Marks.Source := FSeries.Source;
|
|
FChartFrame.Chart.BottomAxis.Marks.Style := smsLabel;
|
|
FChartFrame.Chart.Legend.Visible := FSeries.Source.YCount > 1;
|
|
|
|
FChartFrame.UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.TwoWayPlot;
|
|
begin
|
|
if not ShowPlotsChk.Checked then
|
|
begin
|
|
ChartPage.TabVisible := false;
|
|
exit;
|
|
end;
|
|
|
|
FChartFrame.Clear; // this destroys the series
|
|
FChartFrame.SetYTitle('Mean');
|
|
|
|
FSeries := FChartFrame.PlotXY(ptBars, nil, nil, nil, nil, '', DATA_Colors[0]);
|
|
with TBarSeries(FSeries) do
|
|
begin
|
|
Stacked := false;
|
|
{$IF LCL_FullVersion >= 2010000}
|
|
DepthBrightnessDelta := -30;
|
|
{$IFEND}
|
|
end;
|
|
|
|
if Plot3DChk.Checked then
|
|
FSeries.Depth := 20;
|
|
|
|
FChartCombobox.Parent.Left := 0;
|
|
PopulateChartCombobox;
|
|
SelectPlot(nil);
|
|
|
|
ChartPage.TabVisible := true;
|
|
end;
|
|
|
|
|
|
function TBNestedAForm.Validate(out AMsg: String; out AControl: TWinControl): Boolean;
|
|
begin
|
|
Result := false;
|
|
|
|
if DepEdit.Text = '' then
|
|
begin
|
|
AMsg := 'Dependent variable not specified.';
|
|
AControl := VarList;
|
|
exit;
|
|
end;
|
|
|
|
if ACodesEdit.Text = '' then
|
|
begin
|
|
AMsg := 'Factor A variable not specified.';
|
|
AControl := VarList;
|
|
exit;
|
|
end;
|
|
|
|
if BCodesEdit.Text = '' then
|
|
begin
|
|
AMsg := 'Factor B variable not specified.';
|
|
AControl := VarList;
|
|
exit;
|
|
end;
|
|
|
|
Result := true;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.VarListDblClick(Sender: TObject);
|
|
var
|
|
index: Integer;
|
|
s: String;
|
|
begin
|
|
index := VarList.ItemIndex;
|
|
if index > -1 then
|
|
begin
|
|
s := VarList.Items[index];
|
|
if DepEdit.Text = '' then
|
|
DepEdit.Text := s
|
|
else
|
|
if ACodesEdit.Text = '' then
|
|
ACodesEdit.Text := s
|
|
else
|
|
if BCodesEdit.Text = '' then
|
|
BCodesEdit.Text := s;
|
|
VarList.Items.Delete(index);
|
|
UpdateBtnStates;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.VarListSelectionChange(Sender: TObject; User: boolean);
|
|
begin
|
|
UpdateBtnStates;
|
|
end;
|
|
|
|
|
|
procedure TBNestedAForm.UpdateBtnStates;
|
|
var
|
|
lSelected: Boolean;
|
|
begin
|
|
inherited;
|
|
|
|
if FMeansReportFrame <> nil then
|
|
FMeansReportFrame.UpdateBtnStates;
|
|
|
|
lSelected := AnySelected(VarList);
|
|
AInBtn.Enabled := lSelected and (ACodesEdit.Text = '');
|
|
BInBtn.Enabled := lSelected and (BCodesEdit.Text = '');
|
|
DepInBtn.Enabled := lSelected and (DepEdit.Text = '');
|
|
AOutBtn.Enabled := (ACodesEdit.Text <> '');
|
|
BOutBtn.Enabled := (BCodesEdit.Text <> '');
|
|
DepOutBtn.Enabled := (DepEdit.Text <> '');
|
|
end;
|
|
|
|
end.
|
|
|