LazStats: Refactor ErrorCurvesUnit. Add pdf help to chm.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7407 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-04-26 21:11:48 +00:00
parent 8d5974168a
commit 516ebcad09
4 changed files with 326 additions and 285 deletions

View File

@ -8,6 +8,7 @@ object ErrorCurvesFrm: TErrorCurvesFrm
Caption = 'Alpha and Beta Curves for z tests' Caption = 'Alpha and Beta Curves for z tests'
ClientHeight = 306 ClientHeight = 306
ClientWidth = 350 ClientWidth = 350
OnActivate = FormActivate
OnCreate = FormCreate OnCreate = FormCreate
OnShow = FormShow OnShow = FormShow
Position = poMainFormCenter Position = poMainFormCenter
@ -47,7 +48,6 @@ object ErrorCurvesFrm: TErrorCurvesFrm
Height = 15 Height = 15
Top = 154 Top = 154
Width = 199 Width = 199
Anchors = [akTop]
BorderSpacing.Left = 24 BorderSpacing.Left = 24
Caption = 'Standard Deviation of the Distribution' Caption = 'Standard Deviation of the Distribution'
ParentColor = False ParentColor = False
@ -105,7 +105,7 @@ object ErrorCurvesFrm: TErrorCurvesFrm
Alignment = taRightJustify Alignment = taRightJustify
BorderSpacing.Top = 8 BorderSpacing.Top = 8
TabOrder = 2 TabOrder = 2
Text = 'Edit1' Text = 'AltMeanEdit'
end end
object SDEdit: TEdit object SDEdit: TEdit
AnchorSideLeft.Control = Label3 AnchorSideLeft.Control = Label3
@ -121,7 +121,7 @@ object ErrorCurvesFrm: TErrorCurvesFrm
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Right = 24 BorderSpacing.Right = 24
TabOrder = 3 TabOrder = 3
Text = 'Edit1' Text = 'SDEdit'
end end
object TypeIEdit: TEdit object TypeIEdit: TEdit
AnchorSideLeft.Control = SDEdit AnchorSideLeft.Control = SDEdit
@ -134,7 +134,7 @@ object ErrorCurvesFrm: TErrorCurvesFrm
Alignment = taRightJustify Alignment = taRightJustify
BorderSpacing.Top = 8 BorderSpacing.Top = 8
TabOrder = 4 TabOrder = 4
Text = 'Edit1' Text = 'TypeIEdit'
end end
object TypeIIEdit: TEdit object TypeIIEdit: TEdit
AnchorSideLeft.Control = SDEdit AnchorSideLeft.Control = SDEdit
@ -146,9 +146,9 @@ object ErrorCurvesFrm: TErrorCurvesFrm
Width = 60 Width = 60
Alignment = taRightJustify Alignment = taRightJustify
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Bottom = 8 BorderSpacing.Bottom = 12
TabOrder = 5 TabOrder = 5
Text = 'Edit1' Text = 'TypeIIEdit'
end end
object NullType: TRadioGroup object NullType: TRadioGroup
AnchorSideLeft.Control = Owner AnchorSideLeft.Control = Owner
@ -156,15 +156,15 @@ object ErrorCurvesFrm: TErrorCurvesFrm
AnchorSideTop.Control = Owner AnchorSideTop.Control = Owner
AnchorSideRight.Control = SDEdit AnchorSideRight.Control = SDEdit
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 60 Left = 48
Height = 72 Height = 72
Top = 8 Top = 8
Width = 231 Width = 255
Anchors = [akTop, akLeft, akRight]
AutoFill = True AutoFill = True
AutoSize = True AutoSize = True
BorderSpacing.Left = 12 BorderSpacing.Left = 12
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Right = 12
Caption = 'Null Hypothesis Characteristic:' Caption = 'Null Hypothesis Characteristic:'
ChildSizing.LeftRightSpacing = 12 ChildSizing.LeftRightSpacing = 12
ChildSizing.TopBottomSpacing = 6 ChildSizing.TopBottomSpacing = 6
@ -176,11 +176,11 @@ object ErrorCurvesFrm: TErrorCurvesFrm
ChildSizing.Layout = cclLeftToRightThenTopToBottom ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1 ChildSizing.ControlsPerLine = 1
ClientHeight = 52 ClientHeight = 52
ClientWidth = 227 ClientWidth = 251
ItemIndex = 1 ItemIndex = 1
Items.Strings = ( Items.Strings = (
'One-tailed (Directional alterntive)' 'One-tailed (directional alternative)'
'Two-tailed (non-directional alterntive)' 'Two-tailed (non-directional alternative)'
) )
TabOrder = 0 TabOrder = 0
end end
@ -192,80 +192,64 @@ object ErrorCurvesFrm: TErrorCurvesFrm
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 0 Left = 0
Height = 8 Height = 8
Top = 243 Top = 247
Width = 350 Width = 350
Anchors = [akTop, akLeft, akRight] Anchors = [akTop, akLeft, akRight]
Shape = bsBottomLine Shape = bsBottomLine
end end
object ReturnBtn: TButton object CloseBtn: TButton
AnchorSideTop.Control = Bevel1 AnchorSideTop.Control = Bevel1
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
AnchorSideBottom.Side = asrBottom AnchorSideBottom.Side = asrBottom
Left = 277 Left = 287
Height = 25 Height = 25
Top = 259 Top = 263
Width = 61 Width = 55
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
AutoSize = True AutoSize = True
BorderSpacing.Left = 8
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Right = 12 BorderSpacing.Right = 8
BorderSpacing.Bottom = 8 BorderSpacing.Bottom = 8
Caption = 'Return' Caption = 'Close'
ModalResult = 1 ModalResult = 11
TabOrder = 6 TabOrder = 8
end
object CancelBtn: TButton
AnchorSideTop.Control = Bevel1
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = ComputeBtn
AnchorSideBottom.Control = ResetBtn
Left = 115
Height = 25
Top = 259
Width = 62
Anchors = [akTop, akRight]
AutoSize = True
BorderSpacing.Top = 8
BorderSpacing.Right = 12
Caption = 'Cancel'
ModalResult = 2
TabOrder = 7
end end
object ResetBtn: TButton object ResetBtn: TButton
AnchorSideTop.Control = Bevel1 AnchorSideTop.Control = Bevel1
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = CancelBtn AnchorSideRight.Control = ComputeBtn
AnchorSideBottom.Control = ComputeBtn AnchorSideBottom.Control = ComputeBtn
Left = 49 Left = 141
Height = 25 Height = 25
Top = 259 Top = 263
Width = 54 Width = 54
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
AutoSize = True AutoSize = True
BorderSpacing.Left = 12 BorderSpacing.Left = 8
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Right = 12 BorderSpacing.Right = 8
Caption = 'Reset' Caption = 'Reset'
OnClick = ResetBtnClick OnClick = ResetBtnClick
TabOrder = 8 TabOrder = 6
end end
object ComputeBtn: TButton object ComputeBtn: TButton
AnchorSideTop.Control = Bevel1 AnchorSideTop.Control = Bevel1
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = ReturnBtn AnchorSideRight.Control = CloseBtn
AnchorSideBottom.Control = ReturnBtn AnchorSideBottom.Control = CloseBtn
Left = 189 Left = 203
Height = 25 Height = 25
Top = 259 Top = 263
Width = 76 Width = 76
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
AutoSize = True AutoSize = True
BorderSpacing.Top = 8 BorderSpacing.Top = 8
BorderSpacing.Right = 12 BorderSpacing.Right = 8
Caption = 'Compute' Caption = 'Compute'
OnClick = ComputeBtnClick OnClick = ComputeBtnClick
TabOrder = 9 TabOrder = 7
end end
end end

View File

@ -1,3 +1,10 @@
// No data file needed for testing
//
// Test input:
// - Mean for NULL Hypothesis: 100
// - Mean for alternative Nullhyothesis: 115
// - Standard deviation of the distribution: 15
unit ErrorCurvesUnit; unit ErrorCurvesUnit;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
@ -10,7 +17,7 @@ uses
BlankFrmUnit, FunctionsLib, Globals; BlankFrmUnit, FunctionsLib, Globals;
type type
TwoCol = array[1..2,1..100] of double; TwoCol = array[1..2, 1..100] of double;
type type
@ -20,9 +27,8 @@ type
Bevel1: TBevel; Bevel1: TBevel;
NullType: TRadioGroup; NullType: TRadioGroup;
ResetBtn: TButton; ResetBtn: TButton;
CancelBtn: TButton;
ComputeBtn: TButton; ComputeBtn: TButton;
ReturnBtn: TButton; CloseBtn: TButton;
NullMeanEdit: TEdit; NullMeanEdit: TEdit;
AltMeanEdit: TEdit; AltMeanEdit: TEdit;
SDEdit: TEdit; SDEdit: TEdit;
@ -34,27 +40,20 @@ type
Label4: TLabel; Label4: TLabel;
Label5: TLabel; Label5: TLabel;
procedure ComputeBtnClick(Sender: TObject); procedure ComputeBtnClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject); procedure FormShow(Sender: TObject);
procedure ResetBtnClick(Sender: TObject); procedure ResetBtnClick(Sender: TObject);
private private
{ private declarations } { private declarations }
procedure PltPts(realpts : TwoCol; procedure PltPts(RealPts: TwoCol; Xmax, Xmin, Ymax, Ymin: double;
Xmax, Xmin, Ymax, Ymin : double; Npts, XAxisStart, YAxisStart, XAxisRange, YAxisRange: integer;
Npts, XaxisStart, YaxisStart, XaxisRange : integer; AColor: TColor);
YaxisRange : integer; procedure Hscale(Xmin, Xmax: double; NSteps: integer; AColor: TColor;
acolor : TColor; Sender : TObject); FontSize: integer; X, Y, XLength: integer; CharLabel: string);
procedure Hscale(Xmin, Xmax : double; Nsteps : integer; procedure Vscale(Ymin, Ymax: double; NSteps: integer; AColor: TColor;
acolor : TColor; FontSize : integer; FontSize: integer; X, Y, YLength: integer; CharLabel: string);
X, Y, Xlength : integer; procedure NormPts(zMin, zMax: double; NPts: integer; var RealPts: TwoCol);
charLabel : string; Sender : TObject);
procedure Vscale(Ymin, Ymax : double; Nsteps : integer;
acolor : TColor; FontSize : integer;
X, Y, Ylength : integer;
charLabel : string; Sender : TObject);
procedure NormPts(zMin, zMax : double; Npts : integer;
VAR realpts : TwoCol;
Sender : TObject);
public public
{ public declarations } { public declarations }
@ -65,157 +64,222 @@ var
implementation implementation
uses
Math;
{ TErrorCurvesFrm } { TErrorCurvesFrm }
procedure TErrorCurvesFrm.ResetBtnClick(Sender: TObject); procedure TErrorCurvesFrm.ResetBtnClick(Sender: TObject);
begin begin
NullMeanEdit.Text := ''; NullMeanEdit.Text := '';
AltMeanEdit.Text := ''; AltMeanEdit.Text := '';
SDEdit.Text := ''; SDEdit.Text := '';
TypeIEdit.Text := '0.05'; TypeIEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL);
TypeIIEdit.Text := '0.05'; TypeIIEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL);
NullMeanEdit.SetFocus;
end; end;
procedure TErrorCurvesFrm.FormShow(Sender: TObject); procedure TErrorCurvesFrm.FormShow(Sender: TObject);
begin begin
ResetBtnClick(self); ResetBtnClick(self);
end; end;
{ Generate a null and alternate hypothesis for a specified effect size,
Type I error rate and Type II error rate using the normal distribution z-test.
Estimate the N needed.
Uses the Plot.h header file and form FrmPlot. }
procedure TErrorCurvesFrm.ComputeBtnClick(Sender: TObject); procedure TErrorCurvesFrm.ComputeBtnClick(Sender: TObject);
var var
// generate a null and alternate hypothesis for a specified effect Clwidth, Clheight, X, Y, XaxisStart, XaxisEnd, YaxisStart, YaxisEnd: integer;
// size, Type I error rate and Type II error rate using the normal Xrange, Yrange, t, range, Nsize: integer;
// distribution z-test. Estimate the N needed. alpha, beta, nullmean, altmean, Diff, StdDev, CriticalX, zalpha: double;
// Uses the Plot.h header file and form FrmPlot. zbeta, Xprop, stderrmean, xlow, xhigh: double;
Clwidth,Clheight,X,Y,XaxisStart,XaxisEnd,YaxisStart,YaxisEnd : integer; charLabel: string;
Xrange, Yrange, t, range, Nsize: integer; RealPts: TwoCol;
alpha, beta, nullmean, altmean, Diff, StdDev, CriticalX, zalpha : double;
zbeta, Xprop, stderrmean, xlow, xhigh : double;
valuestr, charLabel : string;
realpts : TwoCol;
begin begin
BlankFrm.Show; if NullMeanEdit.Text = '' then
BlankFrm.Image1.Canvas.Clear; begin
BlankFrm.Image1.Canvas.Pen.Color := clBlack; NullMeanEdit.SetFocus;
BlankFrm.Image1.Canvas.Brush.Color := clWhite; MessageDlg('Input requred.', mtError, [mbOk], 0);
BlankFrm.Image1.Canvas.Clear; exit;
BlankFrm.Image1.Canvas.FloodFill(1,1,clWhite,fsborder); end;
alpha := StrToFloat(TypeIEdit.Text); if not TryStrToFloat(NullMeanEdit.Text, nullMean) then
if NullType.ItemIndex = 1 then alpha := alpha / 2.0; begin
beta := StrToFloat(TypeIIEdit.Text); NullMeanEdit.SetFocus;
nullmean := StrToFloat(NullMeanEdit.Text); MessageDlg('Valid number required.', mtError, [mbOk], 0);
altmean := StrToFloat(AltMeanEdit.Text); exit;
StdDev := StrToFloat(SDEdit.Text); end;
zalpha := inversez(1.0 - alpha);
zbeta := inversez(1.0 - beta);
Diff := abs(nullmean - altmean);
Nsize := round((StdDev / Diff) * abs(zbeta + zalpha));
Nsize := Nsize * Nsize;
CriticalX := zalpha * (StdDev / sqrt(Nsize)) + nullmean;
stderrmean := StdDev / sqrt(Nsize);
Clwidth := BlankFrm.Image1.Width;
Clheight := BlankFrm.Image1.Height;
// Determine X scale and print it if AltMeanEdit.Text = '' then
YaxisStart := (Clheight * 6) div 10; begin
YaxisEnd := Clheight div 10; AltMeanEdit.SetFocus;
Yrange := YaxisStart - YaxisEnd; MessageDlg('Input requred.', mtError, [mbOk], 0);
xlow := nullmean - 4 * stderrmean; exit;
xhigh := altmean + 4 * stderrmean; end;
XaxisStart := Clwidth div 8; if not TryStrToFloat(AltMeanEdit.Text, altMean) then
XaxisEnd := Clwidth - (Clwidth div 8); begin
Xrange := XaxisEnd - XaxisStart; AltMeanEdit.SetFocus;
Hscale(xlow, xhigh, 9, clWhite, 8, XaxisStart, YaxisStart, Xrange,'X SCALE',BlankFrm); MessageDlg('Valid number required.', mtError, [mbOk], 0);
exit;
end;
// Create values of the alternative distribution if SDEdit.Text = '' then
Xprop := ( (nullmean + 4*stderrmean) - xlow) / (xhigh - xlow); begin
range := round(Xprop * Xrange); SDEdit.SetFocus;
NormPts(-4.0, 4.0, 100, realpts, self); MessageDlg('Input requred.', mtError, [mbOk], 0);
Xprop := ((altmean - 4 * stderrmean) - xlow) / (xhigh - xlow); exit;
X := round((Xprop * Xrange) + XaxisStart); // where to start curve end;
PltPts(realpts, 4.0, -4.0, 0.5, 0.0, 100, X, YaxisStart, range, if not TryStrToFloat(SDEdit.Text, StdDev) or (StdDev <= 0) then
Yrange, clBlack, self); begin
SDEdit.SetFocus;
MessageDlg('Valid positive number required.', mtError, [mbOk], 0);
exit;
end;
//Draw vertical axis at the critical X value if TypeIEdit.Text = '' then
Xprop := (CriticalX - xlow) / (xhigh - xlow); begin
X := round((Xprop * Xrange) + XaxisStart); TypeIEdit.SetFocus;
Y := YaxisStart; MessageDlg('Input required.', mtError, [mbOK], 0);
BlankFrm.Image1.Canvas.MoveTo(X,Y); exit;
BlankFrm.Image1.Canvas.LineTo(X,YaxisEnd); end;
charLabel := 'Critical X = '; if not TryStrToFloat(TypeIEdit.Text, alpha) or (alpha < 0) or (alpha > 1) then
valuestr := format('%6.2f',[CriticalX]); begin
charLabel := charLabel + valuestr; TypeIEdit.Setfocus;
t := BlankFrm.Image1.Canvas.TextWidth(charLabel) div 2; MessageDlg('Valid number required between 0 and 1.', mtError, [mbOK], 0);
BlankFrm.Image1.Canvas.TextOut(X-t,YaxisEnd-15,charLabel); exit;
end;
// floodfill Alternate distribution area with blue if TypeIIEdit.Text = '' then
Xprop := (CriticalX - xlow) / (xhigh - xlow); begin
X := round((Xprop * Xrange) + XaxisStart); TypeIIEdit.SetFocus;
Y := YaxisStart - 3; MessageDlg('Input required.', mtError, [mbOK], 0);
BlankFrm.Image1.Canvas.Brush.Color := clBlue; exit;
BlankFrm.Image1.Canvas.FloodFill(X-2,Y,clBlack,fsBorder ); end;
BlankFrm.Image1.Canvas.Brush.Color := clWhite; if not TryStrToFloat(TypeIEdit.Text, beta) or (beta < 0) or (beta > 1) then
begin
TypeIIEdit.Setfocus;
MessageDlg('Valid number required between 0 and 1.', mtError, [mbOK], 0);
exit;
end;
// Create values of normal curve for null distribution BlankFrm.Show;
NormPts(-4.0, 4.0, 100, realpts, self);
Xprop := ( (nullmean + 4*stderrmean) - xlow) / (xhigh - xlow);
range := round(Xprop * Xrange);
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
PltPts(realpts, 4.0, -4.0, 0.5, 0.0, 100, XaxisStart, YaxisStart, range,
Yrange, clBlack, self);
//Draw vertical axis at null mean BlankFrm.Image1.Canvas.Pen.Color := clBlack;
Xprop := (nullmean - xlow) / (xhigh - xlow); BlankFrm.Image1.Canvas.Brush.Color := clWhite;
X := round((Xprop * Xrange) + XaxisStart); BlankFrm.Image1.Canvas.Clear;
Y := YaxisStart; BlankFrm.Image1.Canvas.FloodFill(1,1,clWhite,fsborder);
BlankFrm.Image1.Canvas.MoveTo(X,Y);
BlankFrm.Image1.Canvas.LineTo(X,YaxisEnd);
charLabel := 'Null Mean';
t := BlankFrm.Image1.Canvas.TextWidth(charLabel) div 2;
BlankFrm.Image1.Canvas.TextOut(X-t,YaxisEnd,charLabel);
// floodfill alpha area with red if NullType.ItemIndex = 1 then alpha := alpha / 2.0;
Xprop := (CriticalX - xlow) / (xhigh - xlow);
X := round((Xprop * Xrange) + XaxisStart);
Y := YaxisStart - 3;
BlankFrm.Image1.Canvas.Brush.Color := clRed;
BlankFrm.Image1.Canvas.FloodFill(X+2,Y,clBlack,fsBorder );
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
//Draw vertical axis at alternative mean zalpha := InverseZ(1.0 - alpha);
BlankFrm.Image1.Canvas.Pen.Color := clBlack; zbeta := InverseZ(1.0 - beta);
Xprop := (altmean - xlow) / (xhigh - xlow); Diff := abs(nullmean - altmean);
X := round((Xprop * Xrange) + XaxisStart); Nsize := round((StdDev / Diff) * abs(zbeta + zalpha));
Y := YaxisStart; Nsize := Nsize * Nsize;
BlankFrm.Image1.Canvas.MoveTo(X,Y); CriticalX := zalpha * (StdDev / sqrt(Nsize)) + nullmean;
BlankFrm.Image1.Canvas.LineTo(X,YaxisEnd); stderrmean := StdDev / sqrt(Nsize);
charLabel := 'Alternative Mean';
t := BlankFrm.Image1.Canvas.TextWidth(charLabel) div 2;
BlankFrm.Image1.Canvas.TextOut(X-t,YaxisEnd,charLabel);
// draw the vertical density axis scale values Clwidth := BlankFrm.Image1.Width;
Vscale(0.0, 0.5, 11, clWhite, 10, XaxisStart, YaxisStart, Yrange, 'DENSITY', self); Clheight := BlankFrm.Image1.Height;
// Print Heading // Determine X scale and print it
charLabel := 'Type I and II Error Areas'; YaxisStart := (Clheight * 6) div 10;
BlankFrm.Caption := charLabel; YaxisEnd := Clheight div 10;
charLabel := 'Alpha := '; Yrange := YaxisStart - YaxisEnd;
charLabel := charLabel + TypeIEdit.Text; xlow := nullmean - 4 * stderrmean;
charLabel := charLabel + ', Beta := '; xhigh := altmean + 4 * stderrmean;
charLabel := charLabel + TypeIIEdit.Text; XaxisStart := Clwidth div 8;
charLabel := charLabel + ', N := '; XaxisEnd := Clwidth - (Clwidth div 8);
charLabel := charLabel + IntToStr(Nsize); Xrange := XaxisEnd - XaxisStart;
t := BlankFrm.Image1.Canvas.TextWidth(charLabel); HScale(xlow, xhigh, 9, clWhite, 8, XaxisStart, YaxisStart, Xrange, 'X SCALE');
X := round((BlankFrm.Image1.Width / 2) - (t / 2));
BlankFrm.Image1.Canvas.TextOut(X,0,charLabel);
// print z scale for the null distribution // Create values of the alternative distribution
Xprop := ( (nullmean + 4*stderrmean) - xlow) / (xhigh - xlow); Xprop := ((nullmean + 4*stderrmean) - xlow) / (xhigh - xlow);
range := round(Xprop * Xrange); range := round(Xprop * Xrange);
Hscale(-4.0, 4.0, 11, clWhite, 8, XaxisStart, YaxisStart+50, range,'NULL Z SCALE', self); NormPts(-4.0, 4.0, 100, realpts{%H-});
Xprop := ((altmean - 4 * stderrmean) - xlow) / (xhigh - xlow);
X := round((Xprop * Xrange) + XaxisStart); // where to start curve
PltPts(realpts, 4.0, -4.0, 0.5, 0.0, 100, X, YaxisStart, range, Yrange, clBlack);
end; //Draw vertical axis at the critical X value
Xprop := (CriticalX - xlow) / (xhigh - xlow);
X := round((Xprop * Xrange) + XaxisStart);
Y := YaxisStart;
BlankFrm.Image1.Canvas.MoveTo(X,Y);
BlankFrm.Image1.Canvas.LineTo(X,YaxisEnd);
CharLabel := 'Critical X: ' + Format('%6.2f', [CriticalX]);
t := BlankFrm.Image1.Canvas.TextWidth(CharLabel) div 2;
BlankFrm.Image1.Canvas.TextOut(X-t, YaxisEnd-15, CharLabel);
// floodfill Alternate distribution area with blue
Xprop := (CriticalX - xlow) / (xhigh - xlow);
X := round((Xprop * Xrange) + XaxisStart);
Y := YaxisStart - 3;
BlankFrm.Image1.Canvas.Brush.Color := clBlue;
BlankFrm.Image1.Canvas.FloodFill(X-2, Y, clBlack, fsBorder);
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
// Create values of normal curve for null distribution
NormPts(-4.0, 4.0, 100, realpts);
Xprop := ( (nullmean + 4*stderrmean) - xlow) / (xhigh - xlow);
range := round(Xprop * Xrange);
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
PltPts(realpts, 4.0, -4.0, 0.5, 0.0, 100, XaxisStart, YaxisStart, range, Yrange, clBlack);
//Draw vertical axis at null mean
Xprop := (nullmean - xlow) / (xhigh - xlow);
X := round((Xprop * Xrange) + XaxisStart);
Y := YaxisStart;
BlankFrm.Image1.Canvas.MoveTo(X,Y);
BlankFrm.Image1.Canvas.LineTo(X,YaxisEnd);
CharLabel := 'Null Mean';
t := BlankFrm.Image1.Canvas.TextWidth(charLabel) div 2;
BlankFrm.Image1.Canvas.TextOut(X-t, YaxisEnd, CharLabel);
// floodfill alpha area with red
Xprop := (CriticalX - xlow) / (xhigh - xlow);
X := round((Xprop * Xrange) + XaxisStart);
Y := YaxisStart - 3;
BlankFrm.Image1.Canvas.Brush.Color := clRed;
BlankFrm.Image1.Canvas.FloodFill(X+2, Y, clBlack, fsBorder);
BlankFrm.Image1.Canvas.Brush.Color := clWhite;
//Draw vertical axis at alternative mean
BlankFrm.Image1.Canvas.Pen.Color := clBlack;
Xprop := (altmean - xlow) / (xhigh - xlow);
X := round((Xprop * Xrange) + XaxisStart);
Y := YaxisStart;
BlankFrm.Image1.Canvas.MoveTo(X,Y);
BlankFrm.Image1.Canvas.LineTo(X,YaxisEnd);
charLabel := 'Alternative Mean';
t := BlankFrm.Image1.Canvas.TextWidth(charLabel) div 2;
BlankFrm.Image1.Canvas.TextOut(X-t,YaxisEnd,charLabel);
// draw the vertical density axis scale values
Vscale(0.0, 0.5, 11, clWhite, 10, XaxisStart, YaxisStart, Yrange, 'DENSITY');
// Print Heading
CharLabel := 'Type I and II Error Areas';
BlankFrm.Caption := CharLabel;
CharLabel := 'Alpha: ' + TypeIEdit.Text + ', Beta: ' + TypeIIEdit.Text + ', N: ' + IntToStr(Nsize);
t := BlankFrm.Image1.Canvas.TextWidth(CharLabel);
X := round((BlankFrm.Image1.Width - t) / 2);
BlankFrm.Image1.Canvas.TextOut(X, 0, CharLabel);
// print z scale for the null distribution
Xprop := ((nullmean + 4*stderrmean) - xlow) / (xhigh - xlow);
range := round(Xprop * Xrange);
Hscale(-4.0, 4.0, 11, clWhite, 8, XaxisStart, YaxisStart+50, range,'NULL Z SCALE');
end;
procedure TErrorCurvesFrm.FormActivate(Sender: TObject);
var
w: Integer;
begin
w := MaxValue([ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]);
ResetBtn.Constraints.MinWidth := w;
ComputeBtn.Constraints.MinWidth := w;
CloseBtn.Constraints.MinWidth := w;
end;
procedure TErrorCurvesFrm.FormCreate(Sender: TObject); procedure TErrorCurvesFrm.FormCreate(Sender: TObject);
begin begin
@ -224,112 +288,105 @@ begin
end; end;
procedure TErrorCurvesFrm.PltPts(realpts: TwoCol; Xmax, Xmin, Ymax, procedure TErrorCurvesFrm.PltPts(realpts: TwoCol; Xmax, Xmin, Ymax,
Ymin: double; Npts, XaxisStart, YaxisStart, XaxisRange: integer; Ymin: double; Npts, XAxisStart, YAxisStart, XAxisRange, YAxisRange: integer;
YaxisRange: integer; acolor: TColor; Sender: TObject); AColor: TColor);
var var
hprop, zprop, z, h : double; hprop, zprop, z, h: double;
i, X, Y : integer; i, X, Y: integer;
intpts : array[1..100] of TPoint; intpts: array[1..100] of TPoint;
begin begin
for i := 1 to Npts do for i := 1 to Npts do
begin begin
z := realpts[1,i]; z := RealPts[1, i];
h := realpts[2,i]; h := RealPts[2, i];
zprop := (z - Xmin) / (Xmax - Xmin); zprop := (z - Xmin) / (Xmax - Xmin);
X := round((zprop * XaxisRange) + XaxisStart); X := round((zprop * XAxisRange) + XAxisStart);
hprop := (h - Ymin) / (Ymax - Ymin); hprop := (h - Ymin) / (Ymax - Ymin);
Y := round(YaxisStart - (hprop * YaxisRange)); Y := round(YAxisStart - (hprop * YAxisRange));
intpts[i] := Point(X,Y); intpts[i] := Point(X,Y);
end; end;
BlankFrm.Image1.Canvas.Pen.Color := acolor;
BlankFrm.Image1.Canvas.Polyline(Slice(intpts,Npts - 1)); BlankFrm.Image1.Canvas.Pen.Color := AColor;
BlankFrm.Image1.Canvas.Polyline(Slice(intpts, Npts - 1));
end; end;
procedure TErrorCurvesFrm.Hscale(Xmin, Xmax: double; Nsteps: integer; procedure TErrorCurvesFrm.Hscale(Xmin, Xmax: double; Nsteps: integer;
acolor: TColor; FontSize: integer; X, Y, Xlength: integer; charLabel: string; AColor: TColor; FontSize: integer; X, Y, XLength: integer; CharLabel: string);
Sender: TObject);
var var
i, TickEnd, Xpos, Ypos, TextX : integer; i, TickEnd, Xpos, Ypos, TextX: integer;
Xincr, Xval : double; Xincr, Xval: double;
Svalue, Ast : string;
begin begin
BlankFrm.Image1.Canvas.MoveTo(X,Y); BlankFrm.Image1.Canvas.MoveTo(X,Y);
BlankFrm.Image1.Canvas.LineTo(X+Xlength,Y); BlankFrm.Image1.Canvas.LineTo(X+Xlength,Y);
BlankFrm.Image1.Canvas.Font.Size := FontSize; BlankFrm.Image1.Canvas.Font.Size := FontSize;
BlankFrm.Image1.Canvas.Brush.Color := acolor; BlankFrm.Image1.Canvas.Brush.Color := AColor;
TickEnd := Y + 10; TickEnd := Y + 10;
Xincr := (Xmax - Xmin) / Nsteps; Xincr := (Xmax - Xmin) / Nsteps;
for i := 0 to Nsteps + 1 do for i := 0 to Nsteps + 1 do
begin begin
Xpos := round(((Xlength / Nsteps) * i) + X); Xpos := round(Xlength/Nsteps * i + X);
BlankFrm.Image1.Canvas.MoveTo(Xpos,Y); BlankFrm.Image1.Canvas.MoveTo(Xpos, Y);
BlankFrm.Image1.Canvas.LineTo(Xpos,TickEnd); BlankFrm.Image1.Canvas.LineTo(Xpos, TickEnd);
TextX := Xpos - 8; TextX := Xpos - 8;
Xval := Xmin + ( i * Xincr); Xval := Xmin + i*Xincr;
Svalue := format('%4.2f',[Xval]); BlankFrm.Image1.Canvas.TextOut(TextX, Y+15, Format('%.2f', [Xval]));
Ast := Svalue; end;
BlankFrm.Image1.Canvas.TextOut(TextX, Y+15, Ast);
end; // print label below X axis
// print label below X axis Ypos := Y + 30;
Ypos := Y + 30; Xpos := round((BlankFrm.Image1.Width / 2) - (BlankFrm.Image1.Canvas.TextWidth(CharLabel) / 2));
Xpos := round((BlankFrm.Image1.Width / 2) - (BlankFrm.Image1.Canvas.TextWidth(charLabel) / 2)); BlankFrm.Image1.Canvas.TextOut(Xpos, Ypos, CharLabel);
BlankFrm.Image1.Canvas.TextOut(Xpos,Ypos,charLabel);
end; end;
procedure TErrorCurvesFrm.Vscale(Ymin, Ymax: double; Nsteps: integer; procedure TErrorCurvesFrm.Vscale(Ymin, Ymax: double; NSteps: integer;
acolor: TColor; FontSize: integer; X, Y, Ylength: integer; charLabel: string; AColor: TColor; FontSize: integer; X, Y, YLength: integer; CharLabel: string);
Sender: TObject);
var var
TickEnd, Ypos, Xpos, TextY : integer; TickEnd, Ypos, Xpos, TextY: integer;
Yincr, Yval : double; Yincr, Yval: double;
Svalue, symbol, Ast : string; chpixs, i: integer;
chpixs, i : integer;
begin begin
BlankFrm.Image1.Canvas.MoveTo(X,Y); BlankFrm.Image1.Canvas.MoveTo(X,Y);
BlankFrm.Image1.Canvas.LineTo(X,Y-Ylength); BlankFrm.Image1.Canvas.LineTo(X,Y-Ylength);
BlankFrm.Image1.Canvas.Font.Size := FontSize; BlankFrm.Image1.Canvas.Font.Size := FontSize;
BlankFrm.Image1.Canvas.Brush.Color := acolor; BlankFrm.Image1.Canvas.Brush.Color := acolor;
TickEnd := X - 10; TickEnd := X - 10;
Yincr := (Ymax - Ymin) / Nsteps; Yincr := (Ymax - Ymin) / Nsteps;
TextY := 0; TextY := 0;
for i := 0 to Nsteps + 1 do
begin for i := 0 to Nsteps + 1 do
Ypos := round(Y - ((Ylength / Nsteps) * i)); begin
BlankFrm.Image1.Canvas.MoveTo(X,Ypos); Ypos := round(Y - Ylength/Nsteps*i);
BlankFrm.Image1.Canvas.LineTo(TickEnd,Ypos); BlankFrm.Image1.Canvas.MoveTo(X, Ypos);
TextY := TickEnd - 30; BlankFrm.Image1.Canvas.LineTo(TickEnd, Ypos);
Yval := Ymin + ( i * Yincr); TextY := TickEnd - 30;
Svalue := format('%4.2f',[Yval]); Yval := Ymin + i*Yincr;
Ast := Svalue; BlankFrm.Image1.Canvas.TextOut(TextY, Ypos-8, Format('%.2f', [Yval]));
BlankFrm.Image1.Canvas.TextOut(TextY, Ypos-8, Ast); end;
end;
// print label vertically // print label vertically
Xpos := TextY - 15; Xpos := TextY - 15;
for i := 1 to Length(charLabel) do chpixs := BlankFrm.Image1.Canvas.TextHeight(CharLabel);
begin for i := 1 to Length(CharLabel) do
chpixs := BlankFrm.Image1.Canvas.TextHeight(charLabel); begin
Ypos := round(Y - (Ylength / 2) - ( (Length(charLabel) * chpixs) / 2 ) + (chpixs * i)); Ypos := round(Y - Ylength/2 - Length(CharLabel)*chpixs/2 + chpixs*i);
symbol := charLabel[i]; BlankFrm.Image1.Canvas.TextOut(Xpos,Ypos, CharLabel[i]);
// symbol[2] := 0; end;
BlankFrm.Image1.Canvas.TextOut(Xpos,Ypos,symbol);
end;
end; end;
procedure TErrorCurvesFrm.NormPts(zMin, zMax: double; Npts: integer; procedure TErrorCurvesFrm.NormPts(zMin, zMax: double; Npts: integer;
var realpts: TwoCol; Sender: TObject); var realpts: TwoCol);
var var
zIncr, z, h : double; zIncr, z, h: double;
i : integer; i: integer;
begin begin
zIncr := (zMax - zMin) / Npts; zIncr := (zMax - zMin) / Npts;
for i := 1 to Npts do for i := 1 to Npts do
begin begin
z := zMin + (zIncr * i); z := zMin + (zIncr * i);
h := (1.0 / sqrt(2.0 * 3.14159265358979)) * h := (1.0 / sqrt(2.0 * PI)) * (1.0 / exp(z * z / 2.0));
( 1.0 / exp(z * z / 2.0)); realpts[1, i] := z;
realpts[1,i] := z; realpts[2, i] := h;
realpts[2,i] := h; end;
end;
end; end;
initialization initialization