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.