LazStats: Use TAChart in PlotXYUnit (old code still available after undefining USE_TACHART):

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7626 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-08-22 17:31:05 +00:00
parent 2379dbcfef
commit 8d74b6e07d
3 changed files with 395 additions and 516 deletions

View File

@@ -2,3 +2,5 @@
{$DEFINE USE_EXTERNAL_HELP_VIEWER} {$DEFINE USE_EXTERNAL_HELP_VIEWER}
{$ENDIF} {$ENDIF}
{$DEFINE USE_TACHART}

View File

@@ -3,13 +3,17 @@
unit PlotXYUnit; unit PlotXYUnit;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
{$I ../../../LazStats.inc}
interface interface
uses uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, Buttons, StdCtrls, ExtCtrls, Buttons,
MainUnit, Globals, OutputUnit, FunctionsLib, DataProcs, BlankFrmUnit; {$IFNDEF USE_TACHART}
BlankFrmUnit,
{$ENDIF}
MainUnit, Globals, OutputUnit, FunctionsLib, DataProcs;
type type
@@ -50,29 +54,15 @@ type
private private
{ private declarations } { private declarations }
FAutoSized: Boolean; FAutoSized: Boolean;
procedure PlotXY(VAR Xpoints : DblDyneVec; {$IFDEF USE_TACHART}
VAR Ypoints : DblDyneVec; function PlotXY(XPoints, YPoints, UpConf, LowConf: DblDyneVec;
VAR UpConf : DblDyneVec; XMean, YMean, R, Slope, Intercept: Double): Boolean;
VAR LowConf : DblDyneVec; {$ELSE}
ConfBand : double; function PlotXY(XPoints, YPoints, UpConf, LowConf: DblDyneVec;
Xmean, Ymean , R : double; XMean, YMean, R, Slope, Intercept, XMax, XMin, YMax, YMin: Double;
Slope, Intercept : double; N: Integer): Boolean;
Xmax, Xmin, Ymax, Ymin : double; {$ENDIF}
N : integer);
{
procedure pplotxy(VAR Xpoints : DblDyneVec;
VAR Ypoints : DblDyneVec;
VAR UpConf : DblDyneVec;
VAR LowConf : DblDyneVec;
ConfBand : double;
Xmean, Ymean , R : double;
Slope, Intercept : double;
Xmax, Xmin, Ymax, Ymin : double;
N : integer);
}
procedure UpdateBtnStates; procedure UpdateBtnStates;
function Validate(out AMsg: String; out AControl: TWinControl; function Validate(out AMsg: String; out AControl: TWinControl;
Xcol,Ycol: Integer): Boolean; Xcol,Ycol: Integer): Boolean;
public public
@@ -85,7 +75,12 @@ var
implementation implementation
uses uses
Math; {$IFDEF USE_TACHART}
TAChartUtils,
ChartUnit,
{$ENDIF}
Math, Utils;
{ TPlotXYFrm } { TPlotXYFrm }
@@ -100,7 +95,6 @@ begin
LineChk.Checked := false; LineChk.Checked := false;
MeansChk.Checked := false; MeansChk.Checked := false;
ConfChk.Checked := false; ConfChk.Checked := false;
//PrintChk.Checked := false;
VarList.Items.Clear; VarList.Items.Clear;
for i := 1 to NoVariables do for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
@@ -160,31 +154,31 @@ end;
procedure TPlotXYFrm.ComputeBtnClick(Sender: TObject); procedure TPlotXYFrm.ComputeBtnClick(Sender: TObject);
var var
Xmin, Xmax, Ymin, Ymax, SSx, t, DF : double; Xmin, Xmax, Ymin, Ymax, SSx, SSY, t, DF: double;
Xmean, Ymean, Xvariance, Yvariance, Xstddev, Ystddev, ConfBand : double; Xmean, Ymean, Xvariance, Yvariance, Xstddev, Ystddev, ConfBand: double;
X, Y, R, temp, SEPred, Slope, Intercept, predicted, sedata : double; X, Y, R, temp, SEPred, Slope, Intercept, predicted, sedata: double;
i, j : integer; i, j: integer;
Xcol, Ycol, N, NoSelected : integer; Xcol, Ycol, N, NoSelected: integer;
Xpoints : DblDyneVec; Xpoints: DblDyneVec = nil;
Ypoints : DblDyneVec; Ypoints: DblDyneVec = nil;
UpConf : DblDyneVec; UpConf: DblDyneVec = nil;
lowConf : DblDyneVec; lowConf: DblDyneVec = nil;
cellstring : string; cellstring: string;
ColNoSelected : IntDyneVec; ColNoSelected: IntDyneVec= nil;
C: TWinControl; C: TWinControl;
msg: String; msg: String;
lReport: TStrings; lReport: TStrings;
begin begin
SetLength(Xpoints,NoCases + 1); SetLength(Xpoints, NoCases);
SetLength(Ypoints,NoCases + 1); SetLength(Ypoints, NoCases);
SetLength(UpConf,NoCases + 1); SetLength(UpConf, NoCases);
SetLength(lowConf,NoCases + 1); SetLength(lowConf, NoCases);
SetLength(ColNoSelected,NoVariables); SetLength(ColNoSelected, NoVariables);
Xcol := 0; Xcol := 0;
Ycol := 0; Ycol := 0;
for i := 1 to Novariables do for i := 1 to NoVariables do
begin begin
cellstring := OS3MainFrm.DataGrid.Cells[i,0]; cellstring := OS3MainFrm.DataGrid.Cells[i,0];
if cellstring = XEdit.Text then Xcol := i; if cellstring = XEdit.Text then Xcol := i;
@@ -195,7 +189,7 @@ begin
if not Validate(msg, C, Xcol, Ycol) then if not Validate(msg, C, Xcol, Ycol) then
begin begin
C.SetFocus; C.SetFocus;
MessageDlg(msg, mtError, [mbOK], 0); ErrorMsg(msg);
ModalResult := mrNone; ModalResult := mrNone;
exit; exit;
end; end;
@@ -203,72 +197,63 @@ begin
NoSelected := 2; NoSelected := 2;
ColNoSelected[0] := Xcol; ColNoSelected[0] := Xcol;
ColNoSelected[1] := Ycol; ColNoSelected[1] := Ycol;
N := 0; Xmax := -Infinity;
Xmax := -1.0e20; Xmin := Infinity;
Xmin := 1.0e20; Ymax := -Infinity;
Ymax := -1.0e20; Ymin := Infinity;
Ymin := 1.0e20;
Xmean := 0.0; Xmean := 0.0;
Ymean := 0.0; Ymean := 0.0;
Xvariance := 0.0; XVariance := 0.0;
Yvariance := 0.0; YVariance := 0.0;
R := 0.0; R := 0.0;
N := 0;
for i := 1 to NoCases do for i := 1 to NoCases do
begin begin
if Not GoodRecord(i,NoSelected,ColNoSelected) then continue; if not GoodRecord(i, NoSelected, ColNoSelected) then continue;
N := N + 1; inc(N);
X := StrToFloat(OS3MainFrm.DataGrid.Cells[Xcol,i]); X := StrToFloat(OS3MainFrm.DataGrid.Cells[Xcol,i]);
Y := StrToFloat(OS3MainFrm.DataGrid.Cells[Ycol,i]); Y := StrToFloat(OS3MainFrm.DataGrid.Cells[Ycol,i]);
Xpoints[N] := X; XPoints[N-1] := X;
Ypoints[N] := Y; YPoints[N-1] := Y;
if X > Xmax then Xmax := X; XMax := Max(X, XMax);
if X < Xmin then Xmin := X; XMin := Min(X, XMin);
if Y > Ymax then Ymax := Y; YMax := Max(Y, YMax);
if Y < Ymin then Ymin := Y; YMin := Min(Y, YMin);
Xmean := Xmean + X; XMean := XMean + X;
Ymean := Ymean + Y; YMean := YMean + Y;
Xvariance := Xvariance + (X * X); SSX := SSX + sqr(X);
Yvariance := Yvariance + (Y * Y); SSY := SSY + sqr(Y);
R := R + (X * Y); R := R + X * Y;
end;
if N < 1 then
begin
ErrorMsg('No data values.');
exit;
end; end;
// sort on X // sort on X
for i := 1 to N - 1 do SortOnX(XPoints, YPoints);
begin
for j := i + 1 to N do
begin
if Xpoints[i] > Xpoints[j] then //swap
begin
temp := Xpoints[i];
Xpoints[i] := Xpoints[j];
Xpoints[j] := temp;
temp := Ypoints[i];
Ypoints[i] := Ypoints[j];
Ypoints[j] := temp;
end;
end;
end;
// calculate statistics // calculate statistics
Xvariance := Xvariance - (Xmean * Xmean / N); XVariance := SSX - sqr(XMean) / N;
SSx := Xvariance; XVariance := XVariance / (N - 1);
Xvariance := Xvariance / (N - 1); XStdDev := sqrt(XVariance);
Xstddev := sqrt(Xvariance);
Yvariance := Yvariance - (Ymean * Ymean / N); YVariance := SSY - sqr(YMean) / N;
Yvariance := Yvariance / (N - 1); YVariance := YVariance / (N - 1);
Ystddev := sqrt(Yvariance); YStdDev := sqrt(YVariance);
R := R - (Xmean * Ymean / N); R := R - Xmean * Ymean / N;
R := R / (N - 1); R := R / (N - 1);
R := R / (Xstddev * Ystddev); R := R / (XStdDev * YStdDev);
SEPred := sqrt(1.0 - (R * R)) * Ystddev; SEPred := sqrt(1.0 - sqr(R)) * YStdDev;
SEPred := SEPred * sqrt((N - 1) / (N - 2)); SEPred := SEPred * sqrt((N - 1) / (N - 2));
Xmean := Xmean / N; XMean := XMean / N;
Ymean := Ymean / N; YMean := YMean / N;
Slope := R * Ystddev / Xstddev; Slope := R * YStdDev / XStdDev;
Intercept := Ymean - Slope * Xmean; Intercept := YMean - Slope * XMean;
// Now, print the descriptive statistics to the output form if requested // Now, print the descriptive statistics to the output form if requested
if DescChk.Checked then if DescChk.Checked then
@@ -277,11 +262,11 @@ begin
try try
lReport.Add('X vs. Y PLOT'); lReport.Add('X vs. Y PLOT');
lReport.Add(''); lReport.Add('');
lReport.Add('X = %s, Y = %s from file: %s',[Xedit.Text, YEdit.Text,OS3MainFrm.FileNameEdit.Text]); lReport.Add('X = %s, Y = %s from file: %s', [XEdit.Text, YEdit.Text, OS3MainFrm.FileNameEdit.Text]);
lReport.Add(''); lReport.Add('');
lReport.Add('Variable Mean Variance Std.Dev.'); lReport.Add('Variable Mean Variance Std.Dev.');
lReport.Add('%-10s%8.2f %8.2f %8.2f', [XEdit.Text,Xmean,Xvariance,Xstddev]); lReport.Add('%-10s%8.2f %8.2f %8.2f', [XEdit.Text, XMean, XVariance, XStdDev]);
lReport.Add('%-10s%8.2f %8.2f %8.2f', [YEdit.Text,Ymean,Yvariance,Ystddev]); lReport.Add('%-10s%8.2f %8.2f %8.2f', [YEdit.Text, YMean, YVariance, YStdDev]);
lReport.Add(''); lReport.Add('');
lReport.Add('Correlation: %8.3f', [R]); lReport.Add('Correlation: %8.3f', [R]);
lReport.Add('Slope: %8.3f', [Slope]); lReport.Add('Slope: %8.3f', [Slope]);
@@ -295,36 +280,31 @@ begin
end; end;
end; end;
// get upper and lower confidence points for each X value // Get upper and lower confidence points for each X value
if ConfChk.Checked then if ConfChk.Checked then
begin begin
ConfBand := StrToFloat(ConfEdit.Text) / 100.0; ConfBand := StrToFloat(ConfEdit.Text) / 100.0;
DF := N - 2; DF := N - 2;
t := inverset(ConfBand,DF); t := InverseT(ConfBand, DF);
for i := 1 to N do for i := 0 to N-1 do
begin begin
X := Xpoints[i]; X := XPoints[i];
predicted := slope * X + intercept; predicted := slope * X + intercept;
sedata := SEPred * sqrt(1.0 + (1.0 / N) + (sqr(X - Xmean) / SSx)); sedata := SEPred * sqrt(1.0 + (1.0 / N) + (sqr(X - XMean) / SSx));
UpConf[i] := predicted + (t * sedata); UpConf[i] := predicted + (t * sedata);
lowConf[i] := predicted - (t * sedata); lowConf[i] := predicted - (t * sedata);
if UpConf[i] > Ymax then Ymax := UpConf[i]; YMax := Max(YMax, UpConf[i]);
if lowConf[i] < Ymin then Ymin := lowConf[i]; YMin := Min(YMin, LowConf[i]);
end; end;
end end
else ConfBand := 0.0; else
ConfBand := 0.0;
// plot the values (and optional line and confidence band if elected) // Plot the values (and optional line and confidence band if elected)
plotxy(Xpoints, Ypoints, UpConf, LowConf, ConfBand, Xmean, Ymean, R, PlotXY(
Slope, Intercept, Xmax, Xmin, Ymax, Ymin, N); Xpoints, Ypoints, UpConf, LowConf, XMean, YMean, R, Slope, Intercept
Application.ProcessMessages; {$IFNDEF USE_TACHART},Xmax, Xmin, Ymax, Ymin, N{$ENDIF}
);
{
// print the same if elected
if PrintChk.Checked then
pplotxy(Xpoints, Ypoints, UpConf, LowConf, ConfBand, Xmean, Ymean,
R, Slope, Intercept, Xmax, Xmin, Ymax, Ymin, N);
}
// cleanup // cleanup
ColNoSelected := nil; ColNoSelected := nil;
@@ -334,6 +314,7 @@ begin
Xpoints := nil; Xpoints := nil;
end; end;
procedure TPlotXYFrm.FormActivate(Sender: TObject); procedure TPlotXYFrm.FormActivate(Sender: TObject);
var var
w: Integer; w: Integer;
@@ -355,21 +336,74 @@ begin
FAutoSized := True; FAutoSized := True;
end; end;
procedure TPlotXYFrm.FormCreate(Sender: TObject); procedure TPlotXYFrm.FormCreate(Sender: TObject);
begin begin
Assert(OS3MainFrm <> nil); Assert(OS3MainFrm <> nil);
if BlankFrm = nil then Application.CreateForm(TBlankFrm, BlankFrm);
end; end;
procedure TPlotXYFrm.plotxy(VAR Xpoints : DblDyneVec;
VAR Ypoints : DblDyneVec; {$IFDEF USE_TACHART}
VAR UpConf : DblDyneVec; function TPlotXYFrm.PlotXY(XPoints, YPoints, UpConf, LowConf: DblDyneVec;
VAR LowConf : DblDyneVec; XMean, YMean, R, Slope, Intercept: Double): boolean;
ConfBand : double; var
Xmean, Ymean , R : double; tmpX, tmpY: DblDyneVec;
Slope, Intercept : double; ext: TDoubleRect;
Xmax, Xmin, Ymax, Ymin : double; xmin, xmax, ymin, ymax: Double;
N : integer); begin
if ChartForm = nil then
ChartForm := TChartForm.Create(Application);
ChartForm.Clear;
// Titles
ChartForm.SetTitle(Format('X vs. Y plot using file "%s"', [
OS3MainFrm.FileNameEdit.Text
]));
ChartForm.SetFooter(Format('R(X,Y) = %.3f, Slope = %.2f, Intercept = %.2f', [
R, Slope, Intercept
]));
ChartForm.SetXTitle(XEdit.Text);
chartForm.SetYTitle(YEdit.Text);
// Draw upper confidence band
if ConfChk.Checked then
ChartForm.PlotXY(ptLines, XPoints, UpConf, 'Upper confidence band', clRed);
// Plot data points
ChartForm.PlotXY(ptSymbols, XPoints, YPoints, 'Data values', clNavy);
// Draw lower confidence band
if ConfChk.Checked then
ChartForm.PlotXY(ptLines, XPoints, LowConf, 'Lower confidence band', clRed);
ChartForm.GetXRange(xmin, xmax, false);
ChartForm.GetYRange(ymin, ymax, false);
// Draw means
if MeansChk.Checked then
begin
ChartForm.HorLine(YMean, clGreen, psDash, 'Mean ' + YEdit.Text);
ChartForm.VertLine(XMean, clGreen, psDashDot, 'Mean ' + XEdit.Text);
end;
// Draw regression line
if LineChk.Checked then
begin
SetLength(tmpX, 2);
SetLengtH(tmpY, 2);
tmpX[0] := xmin; tmpY[0] := tmpX[0] * slope + intercept;
tmpX[1] := xmax; tmpY[1] := tmpX[1] * slope + intercept;
ChartForm.PlotXY(ptLines, tmpX, tmpY, 'Predicted', clBlack);
end;
// Show chart
Result := ChartForm.ShowModal <> mrClose;
end;
{$ELSE}
function TPlotXYFrm.PlotXY(XPoints, YPoints, UpConf, LowConf: DblDyneVec;
{ConfBand, }XMean, YMean, R, Slope, Intercept, XMax, XMin, YMax, YMin: Double;
N: Integer): Boolean;
var var
i, xpos, ypos, hleft, hright, vtop, vbottom, imagewide : integer; i, xpos, ypos, hleft, hright, vtop, vbottom, imagewide : integer;
vhi, hwide, offset, strhi, imagehi : integer; vhi, hwide, offset, strhi, imagehi : integer;
@@ -377,10 +411,14 @@ var
Title : string; Title : string;
begin begin
if BlankFrm = nil then Application.CreateForm(TBlankFrm, BlankFrm);
BlankFrm.Image1.Canvas.Clear; BlankFrm.Image1.Canvas.Clear;
BlankFrm.Show; BlankFrm.Show;
Title := 'X versus Y PLOT Using File: ' + OS3MainFrm.FileNameEdit.Text; Title := 'X versus Y PLOT Using File: ' + OS3MainFrm.FileNameEdit.Text;
BlankFrm.Caption := Title; BlankFrm.Caption := Title;
imagewide := BlankFrm.Image1.Width; imagewide := BlankFrm.Image1.Width;
imagehi := BlankFrm.Image1.Height; imagehi := BlankFrm.Image1.Height;
vtop := 20; vtop := 20;
@@ -405,8 +443,7 @@ begin
xpos := hright; xpos := hright;
BlankFrm.Image1.Canvas.Pen.Color := clGreen; BlankFrm.Image1.Canvas.Pen.Color := clGreen;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos); BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
Title := 'MEAN '; Title := 'MEAN ' + YEdit.Text;
Title := Title + YEdit.Text;
strhi := BlankFrm.Image1.Canvas.TextHeight(Title); strhi := BlankFrm.Image1.Canvas.TextHeight(Title);
ypos := ypos - strhi div 2; ypos := ypos - strhi div 2;
BlankFrm.Image1.Canvas.Brush.Color := clWhite; BlankFrm.Image1.Canvas.Brush.Color := clWhite;
@@ -419,8 +456,7 @@ begin
ypos := vbottom; ypos := vbottom;
BlankFrm.Image1.Canvas.Pen.Color := clGreen; BlankFrm.Image1.Canvas.Pen.Color := clGreen;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos); BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
Title := 'MEAN '; Title := 'MEAN ' + XEdit.Text;
Title := Title + XEdit.Text;
strhi := BlankFrm.Image1.Canvas.TextWidth(Title); strhi := BlankFrm.Image1.Canvas.TextWidth(Title);
xpos := xpos - strhi div 2; xpos := xpos - strhi div 2;
ypos := vtop - BlankFrm.Image1.Canvas.TextHeight(Title); ypos := vtop - BlankFrm.Image1.Canvas.TextHeight(Title);
@@ -432,16 +468,17 @@ begin
if LineChk.Checked then if LineChk.Checked then
begin begin
BlankFrm.Image1.Canvas.Pen.Color := clBlack; BlankFrm.Image1.Canvas.Pen.Color := clBlack;
Yvalue := (Xpoints[1] * slope) + intercept; // predicted score Yvalue := (Xpoints[0] * slope) + intercept; // predicted score
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin))); ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
ypos := ypos + vtop; ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[1]- Xmin) / (Xmax - Xmin))); xpos := round(hwide * ( (Xpoints[0]- Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft; xpos := xpos + hleft;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
Yvalue := (Xpoints[N] * slope) + intercept; // predicted score
Yvalue := (Xpoints[N-1] * slope) + intercept; // predicted score
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin))); ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
ypos := ypos + vtop; ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[N] - Xmin) / (Xmax - Xmin))); xpos := round(hwide * ( (Xpoints[N-1] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft; xpos := xpos + hleft;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos); BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
end; end;
@@ -469,8 +506,9 @@ begin
xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(XEdit.Text) div 2); xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(XEdit.Text) div 2);
ypos := vbottom + 20; ypos := vbottom + 20;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,XEdit.Text); BlankFrm.Image1.Canvas.TextOut(xpos,ypos,XEdit.Text);
Title := format('R(X,Y) = %5.3f, Slope = %6.2f, Intercept = %6.2f', Title := format('R(X,Y) = %5.3f, Slope = %6.2f, Intercept = %6.2f', [
[R,Slope,Intercept]); R, Slope, Intercept
]);
xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(Title) div 2); xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(Title) div 2);
ypos := ypos + 15; ypos := ypos + 15;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title); BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
@@ -503,7 +541,7 @@ begin
end; end;
// draw points for x and y pairs // draw points for x and y pairs
for i := 1 to N do for i := 0 to N-1 do
begin begin
ypos := round(vhi * ( (Ymax - Ypoints[i]) / (Ymax - Ymin))); ypos := round(vhi * ( (Ymax - Ypoints[i]) / (Ymax - Ymin)));
ypos := ypos + vtop; ypos := ypos + vtop;
@@ -516,15 +554,16 @@ begin
end; end;
// draw confidence bands if requested // draw confidence bands if requested
if ConfBand <> 0.0 then // if ConfBand <> 0.0 then
if ConfChk.Checked then
begin begin
BlankFrm.Image1.Canvas.Pen.Color := clRed; BlankFrm.Image1.Canvas.Pen.Color := clRed;
ypos := round(vhi * ((Ymax - UpConf[1]) / (Ymax - Ymin))); ypos := round(vhi * ((Ymax - UpConf[0]) / (Ymax - Ymin)));
ypos := ypos + vtop; ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[1] - Xmin) / (Xmax - Xmin))); xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft; xpos := xpos + hleft;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
for i := 2 to N do for i := 1 to N-1 do
begin begin
ypos := round(vhi * ((Ymax - UpConf[i]) / (Ymax - Ymin))); ypos := round(vhi * ((Ymax - UpConf[i]) / (Ymax - Ymin)));
ypos := ypos + vtop; ypos := ypos + vtop;
@@ -532,12 +571,12 @@ begin
xpos := xpos + hleft; xpos := xpos + hleft;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos); BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
end; end;
ypos := round(vhi * ((Ymax - lowConf[1]) / (Ymax - Ymin))); ypos := round(vhi * ((Ymax - lowConf[0]) / (Ymax - Ymin)));
ypos := ypos + vtop; ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[1] - Xmin) / (Xmax - Xmin))); xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft; xpos := xpos + hleft;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos); BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
for i := 2 to N do for i := 1 to N-1 do
begin begin
ypos := round(vhi * ((Ymax - lowConf[i]) / (Ymax - Ymin))); ypos := round(vhi * ((Ymax - lowConf[i]) / (Ymax - Ymin)));
ypos := ypos + vtop; ypos := ypos + vtop;
@@ -547,198 +586,18 @@ begin
end; end;
end; end;
end; end;
//------------------------------------------------------------------- {$ENDIF}
(*
procedure TPlotXYFrm.pplotxy(VAR Xpoints : DblDyneVec;
VAR Ypoints : DblDyneVec;
VAR UpConf : DblDyneVec;
VAR LowConf : DblDyneVec;
ConfBand : double;
Xmean, Ymean , R : double;
Slope, Intercept : double;
Xmax, Xmin, Ymax, Ymin : double;
N : integer);
var
i, xpos, ypos, hleft, hright, vtop, vbottom, imagewide : integer;
vhi, hwide, offset, strhi : integer;
imagehi, maxval, minval, valincr, Yvalue, Xvalue : double;
Title : string;
procedure TPlotXYFrm.UpdateBtnStates;
begin begin
if not PrintDialog.Execute then XinBtn.Enabled := (VarList.ItemIndex > -1) and (XEdit.Text = '');
exit; XoutBtn.Enabled := (XEdit.Text <> '');
YinBtn.Enabled := (VarList.ItemIndex > -1) and (YEdit.Text = '');
Printer.Orientation := poLandscape; YoutBtn.Enabled := (YEdit.Text <> '');
Printer.BeginDoc;
Title := 'X versus Y PLOT Using File: ' + OS3MainFrm.FileNameEdit.Text;
strhi := Printer.Canvas.TextWidth(Title) div 2;
Printer.Canvas.TextOut(strhi,5,Title);
imagewide := Printer.PageWidth - 100;
imagehi := Printer.PageHeight - 100;
vtop := 120;
vbottom := round(imagehi) - 100;
vhi := vbottom - vtop;
hleft := 300;
hright := imagewide - 200;
hwide := hright - hleft;
Printer.Canvas.Pen.Color := clBlack;
Printer.Canvas.Brush.Color := clWhite;
// draw Means
if MeansChk.Checked then
begin
ypos := round(vhi * ( (Ymax - Ymean) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := hleft;
Printer.Canvas.MoveTo(xpos,ypos);
xpos := hright;
Printer.Canvas.Pen.Color := clGreen;
Printer.Canvas.LineTo(xpos,ypos);
Title := 'MEAN ';
Title := Title + YEdit.Text;
strhi := Printer.Canvas.TextHeight(Title);
ypos := ypos - strhi div 2;
Printer.Canvas.Brush.Color := clWhite;
Printer.Canvas.TextOut(xpos,ypos,Title);
xpos := round(hwide * ( (Xmean - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
ypos := vtop;
Printer.Canvas.MoveTo(xpos,ypos);
ypos := vbottom;
Printer.Canvas.Pen.Color := clGreen;
Printer.Canvas.LineTo(xpos,ypos);
Title := 'MEAN ';
Title := Title + XEdit.Text;
strhi := Printer.Canvas.TextWidth(Title);
xpos := xpos - strhi div 2;
ypos := vtop - Printer.Canvas.TextHeight(Title);
Printer.Canvas.Brush.Color := clWhite;
Printer.Canvas.TextOut(xpos,ypos,Title);
end;
// draw slope line
if LineChk.Checked then
begin
Printer.Canvas.Pen.Color := clBlack;
Yvalue := (Xpoints[1] * slope) + intercept; // predicted score
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[1]- Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
Printer.Canvas.MoveTo(xpos,ypos);
Yvalue := (Xpoints[N] * slope) + intercept; // predicted score
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[N] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
Printer.Canvas.LineTo(xpos,ypos);
end;
// draw horizontal axis
Printer.Canvas.Pen.Color := clBlack;
Printer.Canvas.MoveTo(hleft,vbottom);
Printer.Canvas.LineTo(hright,vbottom);
valincr := (Xmax - Xmin) / 10.0;
for i := 1 to 11 do
begin
ypos := vbottom;
Xvalue := Xmin + valincr * (i - 1);
xpos := round(hwide * ((Xvalue - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
Printer.Canvas.MoveTo(xpos,ypos);
ypos := ypos + 10;
Printer.Canvas.LineTo(xpos,ypos);
Title := format('%6.2f',[Xvalue]);
offset := Printer.Canvas.TextWidth(Title) div 2;
xpos := xpos - offset;
Printer.Canvas.Pen.Color := clBlack;
Printer.Canvas.TextOut(xpos,ypos,Title);
end;
xpos := hleft + (hwide div 2) - (Printer.Canvas.TextWidth(XEdit.Text) div 2);
ypos := vbottom + 40;
Printer.Canvas.TextOut(xpos,ypos,XEdit.Text);
Title := format('R(X,Y) = %5.3f, Slope = %6.2f, Intercept = %6.2f',
[R,Slope,Intercept]);
xpos := hleft + (hwide div 2) - (Printer.Canvas.TextWidth(Title) div 2);
ypos := ypos + 40;
Printer.Canvas.TextOut(xpos,ypos,Title);
// Draw vertical axis
Title := YEdit.Text;
xpos := hleft - Printer.Canvas.TextWidth(Title) div 2;
ypos := vtop - Printer.Canvas.TextHeight(Title);
Printer.Canvas.TextOut(xpos,ypos,YEdit.Text);
xpos := hleft;
ypos := vtop;
Printer.Canvas.MoveTo(xpos,ypos);
ypos := vbottom;
Printer.Canvas.LineTo(xpos,ypos);
valincr := (Ymax - Ymin) / 10.0;
for i := 1 to 11 do
begin
Title := format('%8.2f',[Ymax - ((i-1)*valincr)]);
strhi := Printer.Canvas.TextHeight(Title);
xpos := 10;
Yvalue := Ymax - (valincr * (i-1));
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
ypos := ypos + vtop - strhi div 2;
Printer.Canvas.TextOut(xpos,ypos,Title);
xpos := hleft;
ypos := ypos + strhi div 2;
Printer.Canvas.MoveTo(xpos,ypos);
xpos := hleft - 10;
Printer.Canvas.LineTo(xpos,ypos);
end;
// draw points for x and y pairs
for i := 1 to N do
begin
ypos := round(vhi * ( (Ymax - Ypoints[i]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[i] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
Printer.Canvas.Pen.Color := clBlack;
Printer.Canvas.Ellipse(xpos,ypos,xpos+15,ypos+15);
end;
// draw confidence bands if requested
if ConfBand <> 0.0 then
begin
Printer.Canvas.Pen.Color := clRed;
ypos := round(vhi * ((Ymax - UpConf[1]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[1] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
Printer.Canvas.MoveTo(xpos,ypos);
for i := 2 to N do
begin
ypos := round(vhi * ((Ymax - UpConf[i]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[i] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
Printer.Canvas.LineTo(xpos,ypos);
end;
ypos := round(vhi * ((Ymax - lowConf[1]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[1] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
Printer.Canvas.MoveTo(xpos,ypos);
for i := 2 to N do
begin
ypos := round(vhi * ((Ymax - lowConf[i]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[i] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
Printer.Canvas.LineTo(xpos,ypos);
end;
end;
Printer.EndDoc;
Printer.Orientation := poPortrait;
end; end;
//-------------------------------------------------------------------
*)
function TPlotXYFrm.Validate(out AMsg: String; out AControl: TWinControl; function TPlotXYFrm.Validate(out AMsg: String; out AControl: TWinControl;
Xcol, Ycol: Integer): Boolean; Xcol, Ycol: Integer): Boolean;
begin begin
@@ -760,18 +619,12 @@ begin
Result := true; Result := true;
end; end;
procedure TPlotXYFrm.VarListSelectionChange(Sender: TObject; User: boolean); procedure TPlotXYFrm.VarListSelectionChange(Sender: TObject; User: boolean);
begin begin
UpdateBtnStates; UpdateBtnStates;
end; end;
procedure TPlotXYFrm.UpdateBtnStates;
begin
XinBtn.Enabled := (VarList.ItemIndex > -1) and (XEdit.Text = '');
XoutBtn.Enabled := (XEdit.Text <> '');
YinBtn.Enabled := (VarList.ItemIndex > -1) and (YEdit.Text = '');
YoutBtn.Enabled := (YEdit.Text <> '');
end;
initialization initialization
{$I plotxyunit.lrs} {$I plotxyunit.lrs}

View File

@@ -5,7 +5,8 @@ unit Utils;
interface interface
uses uses
Classes, SysUtils, StdCtrls, Dialogs; Classes, SysUtils, StdCtrls, Dialogs,
Globals;
function AnySelected(AListbox: TListBox): Boolean; function AnySelected(AListbox: TListBox): Boolean;
@@ -16,6 +17,8 @@ procedure Exchange(var a, b: Double); overload;
procedure Exchange(var a, b: Integer); overload; 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);
implementation implementation
function AnySelected(AListBox: TListBox): Boolean; function AnySelected(AListBox: TListBox): Boolean;
@@ -68,5 +71,26 @@ begin
b := tmp; b := tmp;
end; end;
procedure SortOnX(X, Y: DblDyneVec);
var
i, j, N: Integer;
begin
N := Length(X);
if N <> Length(Y) then
raise Exception.Create('[SortOnX] Both arrays must have the same length');
for i := 0 to N - 2 do
begin
for j := i + 1 to N - 1 do
begin
if X[i] > X[j] then //swap
begin
Exchange(X[i], X[j]);
Exchange(Y[i], Y[j]);
end;
end;
end;
end;
end. end.