LazStats: use TAChart in xvsmultyunit

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7628 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-08-22 22:23:20 +00:00
parent f8e970a929
commit 79a85d3e59
6 changed files with 138 additions and 73 deletions

Binary file not shown.

View File

@ -8,11 +8,8 @@ unit PlotXYUnit;
interface interface
uses uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, Buttons, StdCtrls, ExtCtrls, Buttons,
{$IFNDEF USE_TACHART}
BlankFrmUnit,
{$ENDIF}
MainUnit, Globals, OutputUnit, FunctionsLib, DataProcs; MainUnit, Globals, OutputUnit, FunctionsLib, DataProcs;
type type
@ -74,10 +71,14 @@ var
implementation implementation
{$R *.lfm}
uses uses
{$IFDEF USE_TACHART} {$IFDEF USE_TACHART}
TAChartUtils, TAChartUtils,
ChartUnit, ChartUnit,
{$ELSE}
BlankFrmUnit,
{$ENDIF} {$ENDIF}
Math, Utils; Math, Utils;
@ -624,8 +625,5 @@ begin
end; end;
initialization
{$I plotxyunit.lrs}
end. end.

View File

@ -2,14 +2,15 @@
unit XvsMultYUnit; unit XvsMultYUnit;
{$mode objfpc}{$H+} {$MODE objfpc}{$H+}
{$I ../../../LazStats.inc}
interface interface
uses uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
StdCtrls, Buttons, ExtCtrls, Printers, StdCtrls, Buttons, ExtCtrls, Printers,
MainUnit, Globals, OutputUnit, DataProcs, BlankFrmUnit, MatrixLib; MainUnit, Globals, OutputUnit, DataProcs, MatrixLib;
type type
@ -51,8 +52,12 @@ type
{ private declarations } { private declarations }
FAutoSized: Boolean; FAutoSized: Boolean;
selected: IntDyneVec; selected: IntDyneVec;
procedure PlotXY(XValues : DblDyneVec; YValues : DblDyneMat; MaxX, MinX, {$IFDEF USE_TACHART}
MaxY, MinY : double; N, NoY : integer); procedure PlotXY(XValues: DblDyneVec; YValues: DblDyneMat);
{$ELSE}
procedure PlotXY(XValues: DblDyneVec; YValues: DblDyneMat;
MaxX, MinX, MaxY, MinY: double; N, NoY: integer);
{$ENDIF}
procedure UpdateBtnStates; procedure UpdateBtnStates;
public public
{ public declarations } { public declarations }
@ -63,7 +68,15 @@ var
implementation implementation
{$R *.lfm}
uses uses
{$IFDEF USE_TACHART}
TAChartUtils,
ChartUnit,
{$ELSE}
BlankFrmUnit,
{$ENDIF}
Math, Utils; Math, Utils;
{ TXvsMultYForm } { TXvsMultYForm }
@ -91,37 +104,41 @@ end;
procedure TXvsMultYForm.ComputeBtnClick(Sender: TObject); procedure TXvsMultYForm.ComputeBtnClick(Sender: TObject);
var var
i, j, k, N, NoY, XCol, NoSelected: integer; i, j, k, N, NoY, XCol, NoSelected: integer;
YValues, RMatrix: DblDyneMat; MinX, MaxX, MinY, MaxY: double;
XValues, Means, Variances, StdDevs: DblDyneVec;
MinX, MaxX, MinY, MaxY, temp: double;
Title: string; Title: string;
RowLabels, ColLabels: StrDyneVec; RMatrix: DblDyneMat = nil;
lReport: TStrings; XValues: DblDyneVec = nil;
YValues: DblDyneMat = nil;
Means: DblDyneVec = nil;
Variances: DblDyneVec = nil;
StdDevs: DblDyneVec = nil;
RowLabels: StrDyneVec = nil;
ColLabels: StrDyneVec = nil;
errorcode: boolean = false; errorcode: boolean = false;
Ncases: integer = 0; Ncases: integer = 0;
lReport: TStrings;
begin begin
if XEdit.Text = '' then if XEdit.Text = '' then
begin begin
MessageDlg('No X variable selected.', mtError, [mbOK], 0); ErrorMsg('No X variable selected.');
exit; exit;
end; end;
if YBox.Items.Count = 0 then if YBox.Items.Count = 0 then
begin begin
MessageDlg('No Y variables selected.', mtError, [mbOK], 0); ErrorMsg('No Y variables selected.');
exit; exit;
end; end;
MaxX := -Infinity;
MinX := Infinity;
MaxY := -Infinity;
MinY := Infinity;
NoY := YBox.Items.Count; NoY := YBox.Items.Count;
MaxX := -10000;
MinX := 10000;
MaxY := -1000;
MinY := 1000;
N := 0;
SetLength(selected, NoY + 1); SetLength(selected, NoY + 1);
SetLength(RowLabels,NoVariables); SetLength(RowLabels, NoVariables);
SetLength(ColLabels,NoVariables); SetLength(ColLabels, NoVariables);
XCol := 0; XCol := 0;
for i := 1 to NoVariables do for i := 1 to NoVariables do
@ -135,7 +152,7 @@ begin
begin begin
selected[j] := 0; selected[j] := 0;
for i := 1 to NoVariables do for i := 1 to NoVariables do
if Trim(YBox.Items.Strings[j]) = Trim(OS3MainFrm.DataGrid.Cells[i,0]) then if Trim(YBox.Items[j]) = Trim(OS3MainFrm.DataGrid.Cells[i,0]) then
begin begin
selected[j] := i; selected[j] := i;
Break; Break;
@ -154,11 +171,8 @@ begin
lReport := TStringList.Create; lReport := TStringList.Create;
try try
lReport.Add('X VERSUS MULTIPLE Y VALUES PLOT'); SetLength(YValues, NoY, NoCases);
lReport.Add(''); SetLength(XValues, NoCases);
SetLength(YValues, NoCases+1, NoY+1);
SetLength(XValues, NoCases+1);
SetLength(Means, NoSelected+1); SetLength(Means, NoSelected+1);
SetLength(Variances, NoSelected+1); SetLength(Variances, NoSelected+1);
SetLength(StdDevs, NoSelected+1); SetLength(StdDevs, NoSelected+1);
@ -172,25 +186,30 @@ begin
for j := 0 to NoSelected-1 do RMatrix[i,j] := 0.0; for j := 0 to NoSelected-1 do RMatrix[i,j] := 0.0;
end; end;
N := 0;
for i := 1 to NoCases do for i := 1 to NoCases do
begin begin
if not GoodRecord(i,NoSelected,selected) then continue; if not GoodRecord(i, NoSelected, selected) then continue;
XValues[i] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[XCol,i])); inc(N);
if XValues[i] > MaxX then MaxX := XValues[i]; XValues[i-1] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[XCol,i]));
if XValues[i] < MinX then MinX := XValues[i]; MaxX := Max(MaxX, XValues[i-1]);
MinX := Min(MinX, XValues[i-1]);
for j := 0 to NoY - 1 do for j := 0 to NoY - 1 do
begin begin
YValues[i-1,j] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[selected[j],i])); YValues[j, i-1] := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[selected[j], i]));
if YValues[i-1,j] > MaxY then MaxY := YValues[i-1,j]; MaxY := Max(MaxY, YValues[j, i-1]);
if YValues[i-1,j] < MinY then MinY := YValues[i-1,j]; MinY := Min(MinY, YValues[j, i-1]);
end; end;
end; end;
// get descriptive data // get descriptive data
if DescChk.Checked then if DescChk.Checked then
begin begin
lReport.Add('X VERSUS MULTIPLE Y VALUES PLOT');
lReport.Add('');
Correlations(NoSelected,selected,RMatrix,Means,Variances,StdDevs,errorcode,Ncases); Correlations(NoSelected,selected,RMatrix,Means,Variances,StdDevs,errorcode,Ncases);
N := Ncases; //N := Ncases;
Title := 'CORRELATIONS'; Title := 'CORRELATIONS';
MatPrint(RMatrix, NoSelected, NoSelected, Title, RowLabels, ColLabels, N, lReport); MatPrint(RMatrix, NoSelected, NoSelected, Title, RowLabels, ColLabels, N, lReport);
Title := 'Means'; Title := 'Means';
@ -199,30 +218,15 @@ begin
DynVectorPrint(Variances, NoSelected, Title, RowLabels, N, lReport); DynVectorPrint(Variances, NoSelected, Title, RowLabels, N, lReport);
Title := 'Standard Deviations'; Title := 'Standard Deviations';
DynVectorPrint(StdDevs, NoSelected, Title, RowLabels, N, lReport); DynVectorPrint(StdDevs, NoSelected, Title, RowLabels, N, lReport);
end;
DisplayReport(lReport); DisplayReport(lReport);
end;
// sort on X // Sort on X
for i := 0 to N-2 do SortOnX(XValues, YValues);
begin
for j := i+1 to N-1 do // Plot x vs multiple y
begin PlotXY(XValues, YValues{$IFNDEF USE_TACHART}, MaxX, MinX, MaxY, MinY, N, NoY{$ENDIF});
if XValues[i] > XValues[j] then // swap
begin
temp := XValues[i];
XValues[i] := XValues[j];
XValues[j] := temp;
for k := 0 to NoY-1 do
begin
temp := YValues[i,k];
YValues[i,k] := YValues[j,k];
YValues[j,k] := temp;
end;
end;
end;
end;
PlotXY(XValues, YValues, MaxX, MinX, MaxY, MinY, N, NoY);
finally finally
lReport.Free; lReport.Free;
@ -238,6 +242,7 @@ begin
end; end;
end; end;
procedure TXvsMultYForm.FormActivate(Sender: TObject); procedure TXvsMultYForm.FormActivate(Sender: TObject);
var var
w: Integer; w: Integer;
@ -256,14 +261,13 @@ begin
FAutoSized := true; FAutoSized := true;
end; end;
procedure TXvsMultYForm.FormCreate(Sender: TObject); procedure TXvsMultYForm.FormCreate(Sender: TObject);
begin begin
Assert(OS3MainFrm <> nil); Assert(OS3MainFrm <> nil);
if BlankFrm = nil then
Application.CreateForm(TBlankFrm, BlankFrm);
end; end;
procedure TXvsMultYForm.XInBtnClick(Sender: TObject); procedure TXvsMultYForm.XInBtnClick(Sender: TObject);
var var
index: integer; index: integer;
@ -277,6 +281,7 @@ begin
UpdateBtnStates; UpdateBtnStates;
end; end;
procedure TXvsMultYForm.XOutBtnClick(Sender: TObject); procedure TXvsMultYForm.XOutBtnClick(Sender: TObject);
begin begin
if (XEdit.Text <> '') then if (XEdit.Text <> '') then
@ -287,6 +292,7 @@ begin
UpdateBtnStates; UpdateBtnStates;
end; end;
procedure TXvsMultYForm.YInBtnClick(Sender: TObject); procedure TXvsMultYForm.YInBtnClick(Sender: TObject);
var var
i: integer; i: integer;
@ -305,6 +311,7 @@ begin
UpdateBtnStates; UpdateBtnStates;
end; end;
procedure TXvsMultYForm.YOutBtnClick(Sender: TObject); procedure TXvsMultYForm.YOutBtnClick(Sender: TObject);
var var
i: integer; i: integer;
@ -323,7 +330,40 @@ begin
UpdateBtnStates; UpdateBtnStates;
end; end;
// routine to plot X versus multiple Y values
// Routine to plot X versus multiple Y values
{$IFDEF USE_TACHART}
procedure TXvsMultYForm.PlotXY(XValues: DblDyneVec; YValues: DblDyneMat);
var
N, Ny, Nc: Integer;
j: Integer;
pt: TPlotType;
begin
// Preparations
if LinesBox.Checked then pt := ptLinesAndSymbols else pt := ptSymbols;
N := Length(XValues);
Ny := Length(YValues);
Nc := Length(DATA_COLORS);
if ChartForm = nil then
ChartForm := TChartForm.Create(Application)
else
ChartForm.Clear;
// Titles
ChartForm.SetTitle(PlotTitleEdit.Text);
ChartForm.SetXTitle(XEdit.Text);
ChartForm.SetYTitle('Y Values');
// Plot a series for each y value
for j := 0 to Ny - 1 do
ChartForm.PlotXY(pt, XValues, YValues[j], Trim(YBox.Items[j]), DATA_COLORS[j mod Nc]);
// Show chart
ChartForm.ShowModal;
end;
{$ELSE}
procedure TXvsMultYForm.PlotXY(XValues: DblDyneVec; YValues: DblDyneMat; procedure TXvsMultYForm.PlotXY(XValues: DblDyneVec; YValues: DblDyneMat;
MaxX, MinX, MaxY, MinY: double; N, NoY: integer); MaxX, MinX, MaxY, MinY: double; N, NoY: integer);
var var
@ -332,8 +372,10 @@ var
valincr, Yvalue, Xvalue: double; valincr, Yvalue, Xvalue: double;
Title: string; Title: string;
begin begin
Title := PlotTitleEdit.Text; if BlankFrm = nil then
BlankFrm.Caption := Title; Application.CreateForm(TBlankFrm, BlankFrm);
BlankFrm.Caption := PlotTitleEdit.Text;
BlankFrm.Show; BlankFrm.Show;
imagewide := BlankFrm.Image1.Width; imagewide := BlankFrm.Image1.Width;
@ -417,12 +459,12 @@ begin
BlankFrm.Image1.Canvas.Pen.Color := DATA_COLORS[j mod Length(DATA_COLORS)]; BlankFrm.Image1.Canvas.Pen.Color := DATA_COLORS[j mod Length(DATA_COLORS)];
BlankFrm.Image1.Canvas.Font.Color := DATA_COLORS[j mod Length(DATA_COLORS)]; BlankFrm.Image1.Canvas.Font.Color := DATA_COLORS[j mod Length(DATA_COLORS)];
Title := Trim(OS3MainFrm.DataGrid.Cells[selected[j],0]); Title := Trim(OS3MainFrm.DataGrid.Cells[selected[j],0]);
for i := 1 to N do for i := 0 to N-1 do
begin begin
ypos := vtop + round(vhi * ( (maxY - YValues[i-1,j]) / (maxY - minY))); ypos := vtop + round(vhi * ( (maxY - YValues[j, i]) / (maxY - minY)));
xpos := hleft + round(hwide * ( (XValues[i-1]-minX) / (maxX - minX))); xpos := hleft + round(hwide * ( (XValues[i] - minX) / (maxX - minX)));
if xpos < hleft then xpos := hleft; if xpos < hleft then xpos := hleft;
if i = 1 then if i = 0 then
BlankFrm.Image1.Canvas.MoveTo(xpos, ypos); BlankFrm.Image1.Canvas.MoveTo(xpos, ypos);
if LinesBox.Checked then if LinesBox.Checked then
BlankFrm.Image1.Canvas.LineTo(xpos, ypos); BlankFrm.Image1.Canvas.LineTo(xpos, ypos);
@ -437,6 +479,8 @@ begin
BlankFrm.Image1.Canvas.Font.Color := clBlack; BlankFrm.Image1.Canvas.Font.Color := clBlack;
end; end;
{$ENDIF}
procedure TXvsMultYForm.UpdateBtnStates; procedure TXvsMultYForm.UpdateBtnStates;
var var
@ -449,8 +493,6 @@ begin
YOutBtn.Enabled := AnySelected(YBox); YOutBtn.Enabled := AnySelected(YBox);
end; end;
initialization
{$I xvsmultyunit.lrs}
end. end.

View File

@ -113,6 +113,8 @@ object ChartForm: TChartForm
Grid.Color = clSilver Grid.Color = clSilver
Grid.Style = psSolid Grid.Style = psSolid
Grid.Visible = False Grid.Visible = False
Intervals.MaxLength = 80
Intervals.MinLength = 30
Alignment = calBottom Alignment = calBottom
Marks.LabelBrush.Style = bsClear Marks.LabelBrush.Style = bsClear
Minors = <> Minors = <>

View File

@ -18,6 +18,7 @@ procedure Exchange(var a, b: Integer); overload;
procedure Exchange(var a, b: String); overload; procedure Exchange(var a, b: String); overload;
procedure SortOnX(X, Y: DblDyneVec); procedure SortOnX(X, Y: DblDyneVec);
procedure SortOnX(X: DblDyneVec; Y: DblDyneMat);
implementation implementation
@ -92,5 +93,27 @@ begin
end; end;
end; end;
// NOTE: The matrix Y is transposed relative to the typical usage in LazStats
procedure SortOnX(X: DblDyneVec; Y: DblDyneMat);
var
i, j, k, N, Ny: Integer;
begin
N := Length(X);
if N <> Length(Y[0]) then
raise Exception.Create('[SortOnX] Arrays X and Y (2nd index) must have the same length');
Ny := Length(Y);
for i := 0 to N-2 do
begin
for j := i+1 to N-1 do
if X[i] > X[j] then
begin
Exchange(X[i], X[j]);
for k := 0 to Ny-1 do
Exchange(Y[k, i], Y[k, j]);
end;
end;
end;
end. end.