Files
lazarus-ccr/applications/lazstats/source_orig/resistancelineunit.pas

707 lines
24 KiB
ObjectPascal
Raw Normal View History

unit ResistanceLineUnit;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, Buttons, MainUnit, Globals, Math, functionsLib, OutPutUnit, DataProcs,
DictionaryUnit, contexthelpunit, BlankFrmUnit, Printers;
type
{ TResistanceLineForm }
TResistanceLineForm = class(TForm)
GridChk: TCheckBox;
PlotMediansChk: TCheckBox;
StdCorChk: TCheckBox;
PointsChk: TCheckBox;
ConfChk: TCheckBox;
ConfEdit: TEdit;
DescChk: TCheckBox;
GroupBox1: TGroupBox;
Label5: TLabel;
LineChk: TCheckBox;
VarList: TListBox;
MeansChk: TCheckBox;
Memo1: TMemo;
ResetBtn: TButton;
CancelBtn: TButton;
ComputeBtn: TButton;
ReturnBtn: TButton;
XInBtn: TBitBtn;
YInBtn: TBitBtn;
XOutBtn: TBitBtn;
YOutBtn: TBitBtn;
XEdit: TEdit;
YEdit: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
procedure ComputeBtnClick(Sender: TObject);
procedure ResetBtnClick(Sender: TObject);
procedure StdCorChkChange(Sender: TObject);
procedure XInBtnClick(Sender: TObject);
procedure XOutBtnClick(Sender: TObject);
procedure YInBtnClick(Sender: TObject);
procedure YOutBtnClick(Sender: TObject);
private
{ private declarations }
function Median(VAR X : DblDyneVec; size : integer) : double;
procedure plotxy(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; PlotNo : integer);
public
{ public declarations }
end;
var
ResistanceLineForm: TResistanceLineForm;
implementation
{ TResistanceLineForm }
procedure TResistanceLineForm.ResetBtnClick(Sender: TObject);
VAR i : integer;
begin
StdCorChk.Checked := false;
GridChk.Checked := false;
PlotMediansChk.Checked := false;
XEdit.Text := '';
YEdit.Text := '';
XOutBtn.Visible := false;
YOutBtn.Visible := false;
XInBtn.Visible := true;
YinBtn.Visible := true;
VarList.Clear;
for i := 1 to NoVariables do
VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
end;
procedure TResistanceLineForm.StdCorChkChange(Sender: TObject);
begin
if StdCorChk.Checked then GroupBox1.Visible := true else GroupBox1.Visible := false;
end;
procedure TResistanceLineForm.ComputeBtnClick(Sender: TObject);
var
XYPoints : DblDyneMat;
XYMedians : DblDyneMat;
XMedians : DblDyneVec;
YMedians : DblDyneVec;
XVector, YVector : DblDyneVec;
cellstring, outline : string;
ColNoSelected : IntDyneVec;
UpConf : DblDyneVec;
lowConf : DblDyneVec;
GrpSize : IntDyneVec;
Xcol, Ycol, N, NoSelected, i, j, size, size1, size2, size3 : integer;
X, Y, tempX, tempY : double;
Xmin, Xmax, Ymin, Ymax, SSx, t, DF : double;
Xmean, Ymean, Xvariance, Yvariance, Xstddev, Ystddev, ConfBand : double;
R, temp, SEPred, Slope, Intercept, predicted, sedata : double;
intercept1, intercept2, slope1, slope2 : double;
c, c1, c2, c3 : double; // constants obtained from control points
begin
SetLength(XYPoints,NoCases,NoCases);
SetLength(XYMedians,3,3);
SetLength(XMedians,3);
SetLength(YMedians,3);
SetLength(XVector,NoCases);
SetLength(YVector,NoCases);
SetLength(ColNoSelected,NoVariables);
SetLength(UpConf,NoCases + 1);
SetLength(lowConf,NoCases + 1);
SetLength(GrpSize,3);
Xcol := 0;
Ycol := 0;
Xmax := -1.0e20;
Xmin := 1.0e20;
Ymax := -1.0e20;
Ymin := 1.0e20;
Xmean := 0.0;
Ymean := 0.0;
Xvariance := 0.0;
Yvariance := 0.0;
R := 0.0;
OutPutFrm.RichEdit.Clear;
for i := 1 to Novariables do
begin
cellstring := OS3MainFrm.DataGrid.Cells[i,0];
if cellstring = XEdit.Text then Xcol := i;
if cellstring = YEdit.Text then Ycol := i;
end;
NoSelected := 2;
ColNoSelected[0] := Xcol;
ColNoSelected[1] := Ycol;
N := 0;
for i := 1 to NoCases do
begin
if Not GoodRecord(i,NoSelected,ColNoSelected) then continue;
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Xcol,i]));
Y := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Ycol,i]));
if X > Xmax then Xmax := X;
if X < Xmin then Xmin := X;
if Y > Ymax then Ymax := Y;
if Y < Ymin then Ymin := Y;
Xmean := Xmean + X;
Ymean := Ymean + Y;
Xvariance := Xvariance + (X * X);
Yvariance := Yvariance + (Y * Y);
R := R + (X * Y);
XYPoints[N,0] := X;
XYPoints[N,1] := Y;
N := N+1;
end;
// sort on X values
for i := 0 to N-2 do
begin
for j := i + 1 to N-1 do
begin
if XYPoints[i,0] > XYPoints[j,0] then // swap
begin
tempX := XYPoints[i,0];
tempY := XYPoints[i,1];
XYPoints[i,0] := XYPoints[j,0];
XYPoints[i,1] := XYPoints[j,1];
XYPoints[j,0] := tempX;
XYPoints[j,1] := tempY;
end;
end;
end;
// calculate statistics
Xvariance := Xvariance - (Xmean * Xmean / N);
SSx := Xvariance;
Xvariance := Xvariance / (N - 1);
Xstddev := sqrt(Xvariance);
Yvariance := Yvariance - (Ymean * Ymean / N);
Yvariance := Yvariance / (N - 1);
Ystddev := sqrt(Yvariance);
R := R - (Xmean * Ymean / N);
R := R / (N - 1);
R := R / (Xstddev * Ystddev);
SEPred := sqrt(1.0 - (R * R)) * Ystddev;
SEPred := SEPred * sqrt((N - 1) / (N - 2));
Xmean := Xmean / N;
Ymean := Ymean / N;
Slope := R * Ystddev / Xstddev;
Intercept := Ymean - Slope * Xmean;
// Now, print the descriptive statistics if requested
if DescChk.Checked then
begin
OutPutFrm.RichEdit.Lines.Add('Original X versus Y Plot Data');
OutPutFrm.RichEdit.Lines.Add('');
outline := format('X = %s, Y = %s from file: %s',[Xedit.Text,
YEdit.Text,OS3MainFrm.FileNameEdit.Text]);
OutPutFrm.RichEdit.Lines.Add(outline);
OutPutFrm.RichEdit.Lines.Add('');
OutPutFrm.RichEdit.Lines.Add('Variable Mean Variance Std.Dev.');
outline := format('%-10s%8.2f %8.2f %8.2f',
[XEdit.Text,Xmean,Xvariance,Xstddev]);
OutPutFrm.RichEdit.Lines.Add(outline);
outline := format('%-10s%8.2f %8.2f %8.2f',
[YEdit.Text,Ymean,Yvariance,Ystddev]);
OutPutFrm.RichEdit.Lines.Add(outline);
outline := format('Correlation = %6.4f, Slope = %8.2f, Intercept = %8.2f',
[R, Slope, Intercept]);
OutPutFrm.RichEdit.Lines.Add(outline);
outline := format('Standard Error of Estimate = %8.2f',[SEPred]);
OutPutFrm.RichEdit.Lines.Add(outline);
outline := format('Number of good cases = %d',[N]);
OutPutFrm.RichEdit.Lines.Add(outline);
// OutPutFrm.ShowModal;
end;
// get upper and lower confidence points for each X value
if ConfChk.Checked then
begin
ConfBand := StrToFloat(ConfEdit.Text) / 100.0;
DF := N - 2;
t := inverset(ConfBand,DF);
for i := 1 to N do
begin
X := XYpoints[i-1,0];
predicted := slope * X + intercept;
sedata := SEPred * sqrt(1.0 + (1.0 / N) + (sqr(X - Xmean) / SSx));
UpConf[i] := predicted + (t * sedata);
lowConf[i] := predicted - (t * sedata);
if UpConf[i] > Ymax then Ymax := UpConf[i];
if lowConf[i] < Ymin then Ymin := lowConf[i];
end;
end
else ConfBand := 0.0;
// plot the values (and optional line and confidence band if elected)
if PointsChk.Checked then
begin
for i := 0 to N-1 do
begin
XVector[i] := XYPoints[i,0];
YVector[i] := XYPoints[i,1];
end;
plotxy(XVector, YVector, UpConf, LowConf, ConfBand, Xmean, Ymean, R,
Slope, Intercept, Xmax, Xmin, Ymax, Ymin, N, 1);
end;
LineChk.Checked := false;
ConfChk.Checked := false;
ConfBand := 0.0;
OutPutFrm.RichEdit.Lines.Add('');
// Now do the resistant line analysis
// obtain 1/3 size
size := n div 3;
size1 := size;
size3 := size;
size2 := n - size1 - size3;
GrpSize[0] := size1;
GrpSize[1] := size2;
GrpSize[2] := size3;
OutPutFrm.RichEdit.Lines.Add('');
// get median for each group of x and y values
// first group:
for i := 0 to size1-1 do
begin
XVector[i] := XYPoints[i,0];
YVector[i] := XYPoints[i,1];
end;
XMedians[0] := Median(XVector,size1);
YMedians[0] := Median(YVector,size1);
OutPutFrm.RichEdit.Lines.Add('');
// second group
j := 0;
for i := size1 to size1 + size2 - 1 do
begin
XVector[j] := XYPoints[i,0];
YVector[j] := XYPoints[i,1];
j := j + 1;
end;
XMedians[1] := Median(XVector,size2);
YMedians[1] := Median(YVector,size2);
OutPutFrm.RichEdit.Lines.Add('');
// third group
j := 0;
for i := (size1 + size2) to N-1 do
begin
XVector[j] := XYPoints[i,0];
YVector[j] := XYPoints[i,1];
j := j + 1;
end;
XMedians[2] := Median(XVector,size3);
YMedians[2] := Median(YVector,size3);
// OutPutFrm.RichEdit.Lines.Add('');
OutPutFrm.RichEdit.Lines.Add('Group X Median Y Median Size');
for i := 0 to 2 do
begin
outline := format('%3d %5.3f %5.3f %d',
[i+1,XMedians[i],YMedians[i], GrpSize[i]]);
OutPutFrm.RichEdit.Lines.Add(outline);
end;
OutPutFrm.RichEdit.Lines.Add('');
slope1 := (YMedians[1] - YMedians[0]) / (XMedians[1] - XMedians[0]);
slope2 := (YMedians[2] - YMedians[1]) / (XMedians[2] - XMedians[1]);
outline := format('Half Slopes = %9.3f and %9.3f',[slope1,slope2]);
OutPutFrm.RichEdit.Lines.Add(outline);
Slope := (YMedians[2] - YMedians[0]) / (XMedians[2] - XMedians[0]);
outline := format('Slope = %9.3f',[Slope]);
OutPutFrm.RichEdit.Lines.Add(outline);
tempx := slope2 / slope1;
outline := format('Ratio of half slopes = %9.3f',[tempx]);
OutPutFrm.RichEdit.Lines.Add(outline);
// obtain estimate of the constant for the prediction equation
c1 := slope * XMedians[0] - YMedians[0];
c2 := slope * XMedians[1] - YMedians[1];
c3 := slope * XMedians[2] - YMedians[2];
c := (c1 + c2 + c3) / 3.0;
outline := format('Equation: y := %9.3f * X + (%9.3f)',[slope,c]);
OutPutFrm.RichEdit.Lines.Add(outline);
if GridChk.Checked then
begin
// Get the residuals (Y - predicted Y) for each X value and place in the grid
outline := 'Pred.';
outline := outline + OS3MainFrm.DataGrid.Cells[Ycol,0];
DictionaryFrm.NewVar(NoVariables+1);
DictionaryFrm.DictGrid.Cells[1,NoVariables] := outline;
OS3MainFrm.DataGrid.Cells[NoVariables,0] := outline;
outline := 'Residual';
DictionaryFrm.NewVar(NoVariables+1);
DictionaryFrm.DictGrid.Cells[1,NoVariables] := outline;
OS3MainFrm.DataGrid.Cells[NoVariables,0] := outline;
for i := 1 to NoCases do
begin
if Not GoodRecord(i,NoSelected,ColNoSelected) then continue;
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Xcol,i]));
Y := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Ycol,i]));
if c >= 0 then predicted := slope * X + c
else predicted := slope * X - c;
Y := Y - predicted; // residual
outline := format('%9.3f',[predicted]);
OS3MainFrm.DataGrid.Cells[NoVariables-1,i] := outline;
outline := format('%9.3f',[Y]);
OS3MainFrm.DataGrid.Cells[NoVariables,i] := outline;
end;
end;
OutPutFrm.ShowModal;
// plot the values (and optional line and confidence band if elected)
if PlotMediansChk.Checked then
plotxy(XMedians, YMedians, UpConf, LowConf, ConfBand, Xmean, Ymean, R,
Slope, Intercept, Xmax, Xmin, Ymax, Ymin, 3, 2);
// OutPutFrm.ShowModal;
// cleanup
GrpSize := nil;
LowConf := nil;
UpConf := nil;
ColNoSelected := nil;
YVector := nil;
XVector := nil;
YMedians := nil;
XMedians := nil;
XYMedians := nil;
XYPoints := nil;
end;
procedure TResistanceLineForm.XInBtnClick(Sender: TObject);
var
index : integer;
begin
index := VarList.ItemIndex;
XEdit.Text := VarList.items.Strings[index];
VarList.Items.Delete(index);
XOutBtn.Visible := true;
XInBtn.Visible := false;
end;
procedure TResistanceLineForm.XOutBtnClick(Sender: TObject);
begin
VarList.Items.Add(XEdit.Text);
XEdit.Text := '';
XInBtn.Visible := true;
XOutBtn.Visible := false;
end;
procedure TResistanceLineForm.YInBtnClick(Sender: TObject);
var index : integer;
begin
index := VarList.ItemIndex;
YEdit.Text := VarList.items.Strings[index];
VarList.Items.Delete(index);
YOutBtn.Visible := true;
YInBtn.Visible := false;
end;
procedure TResistanceLineForm.YOutBtnClick(Sender: TObject);
begin
VarList.Items.Add(YEdit.Text);
YEdit.Text := '';
YInBtn.Visible := true;
YOutBtn.Visible := false;
end;
function TResistanceLineForm.Median(VAR X : DblDyneVec; size : integer) : double;
var
midpt : integer;
value : double;
i, j : integer;
cellstring : string;
begin
// sort values
for i := 0 to size-2 do
begin
for j := i + 1 to size-1 do
begin
if X[i] > X[j] then // swap
begin
value := X[i];
X[i] := X[j];
X[j] := value;
end;
end;
end;
(*
// check for correct median calculation
OutPutFrm.RichEdit.Lines.Add('Sorted values to get median');
cellstring := format('size of array = %d',[size]);
OutPutFrm.RichEdit.Lines.Add(cellstring);
for i := 0 to size-1 do
begin
cellstring := format('no. %d = %9.3f',[i+1,X[i]]);
OutPutFrm.RichEdit.Lines.Add(cellstring);
end;
*)
if size > 2 then
begin
midpt := size div 2;
// cellstring := format('midpt = %d',[midpt]);
// OutPutFrm.RichEdit.Lines.Add(cellstring);
if 2 * midpt = size then // even no. of values
begin
value := (X[midpt-1] + X[midpt]) / 2;
end
else value := X[midpt]; // odd no. of values
Median := value;
end
else if size = 2 then Median := (X[0] + X[1]) / 2;
// cellstring := format('Median = %9.3f',[value]);
// OutPutFrm.ShowModal;
end;
procedure TResistanceLineForm.plotxy(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; PlotNo : integer);
var
i, xpos, ypos, hleft, hright, vtop, vbottom, imagewide : integer;
vhi, hwide, offset, strhi, imagehi : integer;
maxval, minval, valincr, Yvalue, Xvalue : double;
Title : string;
YU,YL, XU, XL : double;
begin
BlankFrm.Image1.Canvas.Clear;
if PlotNo = 1 then
begin
Title := 'X versus Y PLOT Using File: ' + OS3MainFrm.FileNameEdit.Text;
BlankFrm.Caption := Title;
end
else
begin
Title := 'Median Plot for three groups';
BlankFrm.Caption := Title;
end;
imagewide := BlankFrm.Image1.Width;
imagehi := BlankFrm.Image1.Height;
vtop := 20;
vbottom := round(imagehi) - 80;
vhi := vbottom - vtop;
hleft := 100;
hright := imagewide - 80;
hwide := hright - hleft;
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
// Draw chart border
BlankFrm.Image1.Canvas.Rectangle(0,0,imagewide,imagehi);
// end;
// draw Means
if MeansChk.Checked then
begin
ypos := round(vhi * ( (Ymax - Ymean) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := hleft;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
xpos := hright;
BlankFrm.Image1.Canvas.Pen.Color := clGreen;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
Title := 'MEAN ';
Title := Title + YEdit.Text;
strhi := BlankFrm.Image1.Canvas.TextHeight(Title);
ypos := ypos - strhi div 2;
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
xpos := round(hwide * ( (Xmean - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
ypos := vtop;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
ypos := vbottom;
BlankFrm.Image1.Canvas.Pen.Color := clGreen;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
Title := 'MEAN ';
Title := Title + XEdit.Text;
strhi := BlankFrm.Image1.Canvas.TextWidth(Title);
xpos := xpos - strhi div 2;
ypos := vtop - BlankFrm.Image1.Canvas.TextHeight(Title);
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
end;
// draw slope line
if LineChk.Checked then
begin
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
Yvalue := (Xpoints[0] * slope) + intercept; // predicted score
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[0]- Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
Yvalue := (Xpoints[N-1] * slope) + intercept; // predicted score
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[N-1] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
end;
// draw horizontal axis
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
BlankFrm.Image1.Canvas.MoveTo(hleft,vbottom);
BlankFrm.Image1.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;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
ypos := ypos + 10;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
Title := format('%6.2f',[Xvalue]);
offset := BlankFrm.Image1.Canvas.TextWidth(Title) div 2;
xpos := xpos - offset;
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
end;
if PlotNo = 1 then
begin
xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(XEdit.Text) div 2);
ypos := vbottom + 20;
BlankFrm.Image1.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) - (BlankFrm.Image1.Canvas.TextWidth(Title) div 2);
ypos := ypos + 15;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
end;
// Draw vertical axis
Title := YEdit.Text;
xpos := hleft - BlankFrm.Image1.Canvas.TextWidth(Title) div 2;
ypos := vtop - BlankFrm.Image1.Canvas.TextHeight(Title);
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,YEdit.Text);
xpos := hleft;
ypos := vtop;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
ypos := vbottom;
BlankFrm.Image1.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 := BlankFrm.Image1.Canvas.TextHeight(Title);
xpos := 10;
Yvalue := Ymax - (valincr * (i-1));
ypos := round(vhi * ( (Ymax - Yvalue) / (Ymax - Ymin)));
ypos := ypos + vtop - strhi div 2;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
xpos := hleft;
ypos := ypos + strhi div 2;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
xpos := hleft - 10;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
end;
// draw points for x and y pairs
for i := 0 to N-1 do
begin
ypos := round(vhi * ( (Ymax - Ypoints[i]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[i] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
BlankFrm.Image1.Canvas.Brush.Color := clYellow;
BlankFrm.Image1.Canvas.Brush.Style := bsSolid;
BlankFrm.Image1.Canvas.Pen.Color := clNavy;
BlankFrm.Image1.Canvas.Ellipse(xpos,ypos,xpos+5,ypos+5);
if ((PlotNo = 2) and (i = 0)) then
begin
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,'M1');
end;
if ((PlotNo = 2) and (i > 0)) then
begin
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
Title := format('M%d',[i+1]);
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
end;
end;
if ((PlotNo = 2) and (i > 0)) then
begin // draw slope line
BlankFrm.Image1.Canvas.Pen.Color := clRed;
ypos := round(vhi * ( (Ymax - Ypoints[0]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
BlankFrm.Image1.Canvas.MoveTo(xpos,ypos);
YL := Ypoints[0];
XL := xpoints[0];
ypos := round(vhi * ( (Ymax - Ypoints[2]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[2] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
YU := Ypoints[2];
XU := xpoints[2];
slope := (YU - YL) / (XU - XL);
ypos := vbottom + 20;
BlankFrm.Image1.Canvas.Brush.Color := clYellow;
Title := format('Slope = %6.2f',[Slope]);
xpos := hleft + (hwide div 2) - (BlankFrm.Image1.Canvas.TextWidth(Title) div 2);
ypos := ypos + 15;
BlankFrm.Image1.Canvas.TextOut(xpos,ypos,Title);
end;
// draw confidence bands if requested
if ConfBand <> 0.0 then
begin
BlankFrm.Image1.Canvas.Pen.Color := clRed;
ypos := round(vhi * ((Ymax - UpConf[1]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
BlankFrm.Image1.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-1] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
end;
ypos := round(vhi * ((Ymax - lowConf[1]) / (Ymax - Ymin)));
ypos := ypos + vtop;
xpos := round(hwide * ( (Xpoints[0] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
BlankFrm.Image1.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-1] - Xmin) / (Xmax - Xmin)));
xpos := xpos + hleft;
BlankFrm.Image1.Canvas.LineTo(xpos,ypos);
end;
end;
BlankFrm.ShowModal;
end;
//-------------------------------------------------------------------
initialization
{$I resistancelineunit.lrs}
end.