diff --git a/applications/lazstats/source/forms/simulations/distribunit.lfm b/applications/lazstats/source/forms/simulations/distribunit.lfm index 528ffece9..4c966c26c 100644 --- a/applications/lazstats/source/forms/simulations/distribunit.lfm +++ b/applications/lazstats/source/forms/simulations/distribunit.lfm @@ -1,229 +1,44 @@ object DistribFrm: TDistribFrm Left = 420 - Height = 223 + Height = 432 Top = 215 - Width = 384 + Width = 687 HelpType = htKeyword HelpKeyword = 'html/DistributionPlotsandCriticalValu.htm' - AutoSize = True BorderStyle = bsDialog Caption = 'Distributions' - ClientHeight = 223 - ClientWidth = 384 + ClientHeight = 432 + ClientWidth = 687 OnActivate = FormActivate - OnCreate = FormCreate OnShow = FormShow Position = poMainFormCenter LCLVersion = '2.1.0.0' - object GroupBox1: TGroupBox - AnchorSideLeft.Control = Owner - AnchorSideTop.Control = Owner - Left = 12 - Height = 109 - Top = 12 - Width = 180 - AutoSize = True - BorderSpacing.Left = 12 - BorderSpacing.Top = 12 - Caption = 'Plot Distribution:' - ChildSizing.LeftRightSpacing = 16 - ChildSizing.TopBottomSpacing = 8 - ChildSizing.VerticalSpacing = 8 - ChildSizing.EnlargeVertical = crsHomogenousSpaceResize - ChildSizing.Layout = cclLeftToRightThenTopToBottom - ChildSizing.ControlsPerLine = 1 - ClientHeight = 89 - ClientWidth = 176 - TabOrder = 0 - object NDChk: TRadioButton - Left = 16 - Height = 19 - Top = 8 - Width = 144 - Caption = 'Normal Distribution' - OnClick = NDChkClick - TabOrder = 0 - end - object ChiChk: TRadioButton - Left = 16 - Height = 19 - Top = 35 - Width = 144 - Caption = 'Chi-Square Distribution' - OnClick = ChiChkClick - TabOrder = 1 - end - object FChk: TRadioButton - Left = 16 - Height = 19 - Top = 62 - Width = 144 - Caption = 'Central F Distribution' - OnClick = FChkClick - TabOrder = 2 - end - end - object GroupBox2: TGroupBox - AnchorSideLeft.Control = GroupBox1 - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = GroupBox1 - AnchorSideRight.Control = GroupBox1 - AnchorSideRight.Side = asrBottom - Left = 204 - Height = 140 - Top = 12 - Width = 170 - AutoSize = True - BorderSpacing.Left = 12 - BorderSpacing.Right = 12 - BorderSpacing.Bottom = 12 - Caption = 'Parameters' - ClientHeight = 120 - ClientWidth = 166 - TabOrder = 1 - object AlphaLabel: TLabel - AnchorSideTop.Control = AlphaEdit - AnchorSideTop.Side = asrCenter - AnchorSideRight.Control = AlphaEdit - Left = 19 - Height = 15 - Top = 6 - Width = 84 - Anchors = [akTop, akRight] - BorderSpacing.Right = 8 - Caption = 'Type I Error Rate' - ParentColor = False - end - object DF1Label: TLabel - AnchorSideTop.Control = DF1Edit - AnchorSideTop.Side = asrCenter - AnchorSideRight.Control = DF1Edit - Left = 12 - Height = 15 - Top = 33 - Width = 91 - Anchors = [akTop, akRight] - BorderSpacing.Right = 8 - Caption = 'Deg. Freedom (1)' - ParentColor = False - end - object DF2Label: TLabel - AnchorSideLeft.Control = GroupBox2 - AnchorSideTop.Control = DF2Edit - AnchorSideTop.Side = asrCenter - AnchorSideRight.Control = DF2Edit - Left = 12 - Height = 15 - Top = 60 - Width = 91 - Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 12 - BorderSpacing.Right = 8 - Caption = 'Deg. Freedom (2)' - ParentColor = False - end - object MeanLabel: TLabel - AnchorSideTop.Control = MeanEdit - AnchorSideTop.Side = asrCenter - AnchorSideRight.Control = MeanEdit - Left = 73 - Height = 15 - Top = 93 - Width = 30 - Anchors = [akTop, akRight] - BorderSpacing.Right = 8 - Caption = 'Mean' - ParentColor = False - Visible = False - end - object AlphaEdit: TEdit - AnchorSideTop.Control = GroupBox2 - AnchorSideRight.Control = GroupBox2 - AnchorSideRight.Side = asrBottom - Left = 111 - Height = 23 - Top = 2 - Width = 43 - Alignment = taRightJustify - Anchors = [akTop, akRight] - BorderSpacing.Top = 2 - BorderSpacing.Right = 12 - TabOrder = 0 - Text = 'AlphaEdit' - end - object DF1Edit: TEdit - AnchorSideTop.Control = AlphaEdit - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = AlphaEdit - AnchorSideRight.Side = asrBottom - Left = 111 - Height = 23 - Top = 29 - Width = 43 - Alignment = taRightJustify - Anchors = [akTop, akRight] - BorderSpacing.Top = 4 - TabOrder = 1 - Text = 'DF1Edit' - end - object MeanEdit: TEdit - AnchorSideTop.Control = DF2Edit - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = AlphaEdit - AnchorSideRight.Side = asrBottom - Left = 111 - Height = 23 - Top = 89 - Width = 43 - Alignment = taRightJustify - Anchors = [akTop, akRight] - BorderSpacing.Top = 4 - BorderSpacing.Bottom = 8 - TabOrder = 3 - Text = 'MeanEdit' - Visible = False - end - object DF2Edit: TEdit - AnchorSideTop.Control = DF1Edit - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = AlphaEdit - AnchorSideRight.Side = asrBottom - Left = 111 - Height = 23 - Top = 56 - Width = 43 - Alignment = taRightJustify - Anchors = [akTop, akRight] - BorderSpacing.Top = 4 - BorderSpacing.Bottom = 10 - TabOrder = 2 - Text = 'DF2Edit' - end - end object CloseBtn: TButton AnchorSideTop.Control = Bevel1 AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Owner AnchorSideBottom.Side = asrBottom - Left = 321 + Left = 624 Height = 25 - Top = 180 + Top = 401 Width = 55 - Anchors = [akTop, akRight] + Anchors = [akRight, akBottom] AutoSize = True BorderSpacing.Top = 8 BorderSpacing.Right = 8 + BorderSpacing.Bottom = 6 Caption = 'Close' ModalResult = 11 - TabOrder = 4 + TabOrder = 2 end object ComputeBtn: TButton AnchorSideTop.Control = CloseBtn AnchorSideRight.Control = CloseBtn - Left = 237 + Left = 540 Height = 25 - Top = 180 + Top = 401 Width = 76 Anchors = [akTop, akRight] AutoSize = True @@ -231,14 +46,14 @@ object DistribFrm: TDistribFrm BorderSpacing.Right = 8 Caption = 'Compute' OnClick = ComputeBtnClick - TabOrder = 3 + TabOrder = 1 end object ResetBtn: TButton AnchorSideTop.Control = CloseBtn AnchorSideRight.Control = ComputeBtn - Left = 175 + Left = 478 Height = 25 - Top = 180 + Top = 401 Width = 54 Anchors = [akTop, akRight] AutoSize = True @@ -247,19 +62,352 @@ object DistribFrm: TDistribFrm BorderSpacing.Bottom = 8 Caption = 'Reset' OnClick = ResetBtnClick - TabOrder = 2 + TabOrder = 0 end object Bevel1: TBevel AnchorSideLeft.Control = Owner - AnchorSideTop.Control = GroupBox2 AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = CloseBtn Left = 0 Height = 8 - Top = 164 - Width = 384 - Anchors = [akTop, akLeft, akRight] + Top = 385 + Width = 687 + Anchors = [akLeft, akRight, akBottom] Shape = bsBottomLine end + object Panel1: TPanel + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = Owner + AnchorSideRight.Control = Panel2 + AnchorSideBottom.Control = Bevel1 + Left = 8 + Height = 377 + Top = 8 + Width = 479 + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Left = 8 + BorderSpacing.Top = 8 + BorderSpacing.Right = 12 + BevelOuter = bvNone + BorderStyle = bsSingle + ClientHeight = 373 + ClientWidth = 475 + Color = clWhite + ParentColor = False + TabOrder = 3 + object Chart: TChart + Left = 6 + Height = 361 + Top = 6 + Width = 463 + AxisList = < + item + Grid.Color = clSilver + Grid.Visible = False + Marks.LabelBrush.Style = bsClear + Minors = <> + Title.LabelFont.Orientation = 900 + Title.LabelFont.Style = [fsBold] + Title.Visible = True + Title.Caption = 'Probability Density' + Title.LabelBrush.Style = bsClear + end + item + Grid.Color = clSilver + Grid.Visible = False + Alignment = calBottom + AxisPen.Visible = True + Marks.LabelBrush.Style = bsClear + Minors = <> + Title.LabelFont.Style = [fsBold] + Title.Visible = True + Title.Caption = 'Scale' + Title.LabelBrush.Style = bsClear + Title.TextFormat = tfHTML + end> + BackColor = clWhite + Foot.Brush.Color = clBtnFace + Foot.Font.Color = clBlue + Margins.Bottom = 0 + Title.Brush.Style = bsClear + Title.Font.Color = clBlue + Title.Text.Strings = ( + 'TAChart' + ) + Title.TextFormat = tfHTML + Toolset = ChartToolset + Align = alClient + BorderSpacing.Around = 6 + Color = clWhite + object FuncSeries: TFuncSeries + ExtentAutoY = True + end + object VertLineSeries: TLineSeries + Active = False + end + end + end + object SaveBtn: TButton + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = CloseBtn + Left = 8 + Height = 25 + Top = 401 + Width = 50 + AutoSize = True + BorderSpacing.Left = 8 + Caption = 'Save' + OnClick = SaveBtnClick + TabOrder = 4 + end + object PrintBtn: TButton + AnchorSideLeft.Control = SaveBtn + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = CloseBtn + Left = 66 + Height = 25 + Top = 401 + Width = 51 + AutoSize = True + BorderSpacing.Left = 8 + Caption = 'Print' + OnClick = PrintBtnClick + TabOrder = 5 + end + object Panel2: TPanel + AnchorSideTop.Control = Owner + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Bevel1 + Left = 499 + Height = 377 + Top = 8 + Width = 180 + Anchors = [akTop, akRight, akBottom] + AutoSize = True + BorderSpacing.Top = 8 + BorderSpacing.Right = 8 + BevelOuter = bvNone + Caption = 'Panel2' + ClientHeight = 377 + ClientWidth = 180 + TabOrder = 6 + object GroupBox1: TGroupBox + AnchorSideLeft.Control = Panel2 + AnchorSideTop.Control = Panel2 + AnchorSideRight.Side = asrBottom + Left = 0 + Height = 136 + Top = 0 + Width = 180 + AutoSize = True + Caption = 'Plot Distribution:' + ChildSizing.LeftRightSpacing = 16 + ChildSizing.TopBottomSpacing = 8 + ChildSizing.VerticalSpacing = 8 + ChildSizing.EnlargeVertical = crsHomogenousSpaceResize + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 1 + ClientHeight = 116 + ClientWidth = 176 + TabOrder = 0 + object NDChk: TRadioButton + Left = 16 + Height = 19 + Top = 8 + Width = 144 + Caption = 'Normal Distribution' + OnClick = NDChkClick + TabOrder = 0 + end + object tChk: TRadioButton + Left = 16 + Height = 19 + Top = 35 + Width = 144 + Caption = 'Student t Distribution' + OnClick = tChkClick + TabOrder = 3 + Visible = False + end + object FChk: TRadioButton + Left = 16 + Height = 19 + Top = 62 + Width = 144 + Caption = 'Central F Distribution' + OnClick = FChkClick + TabOrder = 2 + end + object ChiChk: TRadioButton + Left = 16 + Height = 19 + Top = 89 + Width = 144 + Caption = 'Chi-Square Distribution' + OnClick = ChiChkClick + TabOrder = 1 + end + end + object GroupBox2: TGroupBox + AnchorSideLeft.Control = GroupBox1 + AnchorSideTop.Control = GroupBox1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = GroupBox1 + AnchorSideRight.Side = asrBottom + Left = 0 + Height = 140 + Top = 152 + Width = 180 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Top = 16 + BorderSpacing.Bottom = 12 + Caption = 'Parameters' + ClientHeight = 120 + ClientWidth = 176 + TabOrder = 1 + object AlphaLabel: TLabel + AnchorSideTop.Control = AlphaEdit + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = AlphaEdit + Left = 29 + Height = 15 + Top = 6 + Width = 84 + Anchors = [akTop, akRight] + BorderSpacing.Right = 8 + Caption = 'Type I Error Rate' + ParentColor = False + end + object DF1Label: TLabel + AnchorSideTop.Control = DF1Edit + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = DF1Edit + Left = 22 + Height = 15 + Top = 33 + Width = 91 + Anchors = [akTop, akRight] + BorderSpacing.Right = 8 + Caption = 'Deg. Freedom (1)' + ParentColor = False + end + object DF2Label: TLabel + AnchorSideLeft.Control = GroupBox2 + AnchorSideTop.Control = DF2Edit + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = DF2Edit + Left = 22 + Height = 15 + Top = 60 + Width = 91 + Anchors = [akTop, akRight] + BorderSpacing.Left = 12 + BorderSpacing.Right = 8 + Caption = 'Deg. Freedom (2)' + ParentColor = False + end + object MeanLabel: TLabel + AnchorSideTop.Control = MeanEdit + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = MeanEdit + Left = 83 + Height = 15 + Top = 93 + Width = 30 + Anchors = [akTop, akRight] + BorderSpacing.Right = 8 + Caption = 'Mean' + ParentColor = False + Visible = False + end + object AlphaEdit: TEdit + AnchorSideTop.Control = GroupBox2 + AnchorSideRight.Control = GroupBox2 + AnchorSideRight.Side = asrBottom + Left = 121 + Height = 23 + Top = 2 + Width = 43 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 2 + BorderSpacing.Right = 12 + TabOrder = 0 + Text = 'AlphaEdit' + end + object DF1Edit: TEdit + AnchorSideTop.Control = AlphaEdit + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = AlphaEdit + AnchorSideRight.Side = asrBottom + Left = 121 + Height = 23 + Top = 29 + Width = 43 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 4 + TabOrder = 1 + Text = 'DF1Edit' + end + object MeanEdit: TEdit + AnchorSideTop.Control = DF2Edit + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = AlphaEdit + AnchorSideRight.Side = asrBottom + Left = 121 + Height = 23 + Top = 89 + Width = 43 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 4 + BorderSpacing.Bottom = 8 + TabOrder = 3 + Text = 'MeanEdit' + Visible = False + end + object DF2Edit: TEdit + AnchorSideTop.Control = DF1Edit + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = AlphaEdit + AnchorSideRight.Side = asrBottom + Left = 121 + Height = 23 + Top = 56 + Width = 43 + Alignment = taRightJustify + Anchors = [akTop, akRight] + BorderSpacing.Top = 4 + BorderSpacing.Bottom = 10 + TabOrder = 2 + Text = 'DF2Edit' + end + end + end + object SavePictureDialog: TSavePictureDialog + Filter = 'Graphic (*.png;*.bmp;*.jpeg;*.jpg;*.jpe;*.jfif;*.svg)|*.png;*.bmp;*.jpeg;*.jpg;*.jpe;*.jfif;*.svg|Portable Network Graphic (*.png)|*.png|Bitmaps (*.bmp)|*.bmp|Joint Picture Expert Group (*.jpeg;*.jpg;*.jpe;*.jfif)|*.jpeg;*.jpg;*.jpe;*.jfif|Scaleable Vector Graphic (*.svg)|*.svg|All Files (*.*)|*.*' + Left = 160 + Top = 72 + end + object PrintDialog: TPrintDialog + Left = 160 + Top = 130 + end + object ChartToolset: TChartToolset + Left = 319 + Top = 209 + object ZoomDragTool: TZoomDragTool + Shift = [ssLeft] + LimitToExtent = [zdDown] + Brush.Style = bsClear + end + object PanDragTool: TPanDragTool + Shift = [ssRight] + LimitToExtent = [pdDown] + end + end end diff --git a/applications/lazstats/source/forms/simulations/distribunit.pas b/applications/lazstats/source/forms/simulations/distribunit.pas index 33ea1c5f6..a93027de3 100644 --- a/applications/lazstats/source/forms/simulations/distribunit.pas +++ b/applications/lazstats/source/forms/simulations/distribunit.pas @@ -3,6 +3,8 @@ // Test input parameters: // - F distribution: DF1 = 3, DF2 = 20 +// ToDo: Fix calculation of t distribution + unit DistribUnit; {$mode objfpc}{$H+} @@ -10,12 +12,9 @@ unit DistribUnit; interface uses - Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, - StdCtrls, Printers, ExtCtrls, Math, - BlankFrmUnit, FunctionsLib, Globals; - - type - TwoCol = array[1..2, 1..100] of double; + Classes, SysUtils, FileUtil, TAGraph, TAFuncSeries, TASeries, TATools, + PrintersDlgs, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls, + Printers, ExtCtrls, ExtDlgs, Math, FunctionsLib, Globals; type @@ -24,12 +23,25 @@ type TDistribFrm = class(TForm) AlphaEdit: TEdit; Bevel1: TBevel; + ChartToolset: TChartToolset; + PanDragTool: TPanDragTool; + tChk: TRadioButton; + ZoomDragTool: TZoomDragTool; + PrintDialog: TPrintDialog; + SavePictureDialog: TSavePictureDialog; + VertLineSeries: TLineSeries; + FuncSeries: TFuncSeries; + Panel2: TPanel; + SaveBtn: TButton; + PrintBtn: TButton; + Chart: TChart; ChiChk: TRadioButton; DF1Edit: TEdit; DF2Edit: TEdit; FChk: TRadioButton; MeanEdit: TEdit; NDChk: TRadioButton; + Panel1: TPanel; ResetBtn: TButton; ComputeBtn: TButton; CloseBtn: TButton; @@ -43,26 +55,24 @@ type procedure ComputeBtnClick(Sender: TObject); procedure FChkClick(Sender: TObject); procedure FormActivate(Sender: TObject); - procedure FormCreate(Sender: TObject); procedure FormShow(Sender: TObject); + procedure CalcChiSq(const AX: Double; out AY: Double); + procedure CalcF(const AX: Double; out AY: Double); + procedure CalcND(const AX: Double; out AY: Double); + procedure Calct(const AX: Double; out AY: Double); procedure NDChkClick(Sender: TObject); + procedure PrintBtnClick(Sender: TObject); procedure ResetBtnClick(Sender: TObject); + procedure SaveBtnClick(Sender: TObject); + procedure tChkClick(Sender: TObject); private { private declarations } + DF1: Integer; + DF2: Integer; procedure NDPlot; procedure ChiPlot; procedure FPlot; - procedure HScale(Xmin, Xmax: double; NSteps: integer; AColor: TColor; - FontSize: integer; X, Y, XLength: integer; CharLabel: string); - procedure VScale(Ymin, Ymax: double; NSteps: integer; AColor: TColor; - FontSize: integer; X, Y, YLength: integer; CharLabel: string); - procedure NormPts(zMin, zMax: double; NPts: integer; var RealPts: TwoCol); - procedure PltPts(RealPts: TwoCol; XMax, XMin, YMax, YMin: double; - Npts, XAxisStart, YAxisStart, XAxisRange, YAxisRange: integer; AColor: TColor); - procedure ChiPts(cMin, cMax: double; NPts, DF: integer; var RealPts: TwoCol); - procedure FPts(FMin, FMax: double; NPts, DF1, DF2: integer; var RealPts: TwoCol); - function Chi2Func(chisqr, df: double): double; - function FFunc(F: double; DF1, DF2: integer): double; + procedure tPlot; function Validate(out AMsg: String; out AControl: TWinControl): Boolean; public @@ -74,18 +84,45 @@ var implementation +uses + //spe, // a numlib unit (tDist) + OSPrinters, + TAChartUtils, TADrawerSVG, TAPrint; + + { TDistribFrm } procedure TDistribFrm.ResetBtnClick(Sender: TObject); begin NDChk.Checked := false; - ChiChk.Checked := false; + tChk.Checked := false; FChk.Checked := false; + ChiChk.Checked := false; AlphaEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL); DF1Edit.Text := ''; DF2Edit.Text := ''; MeanEdit.Text := ''; GroupBox2.Enabled := false; + FuncSeries.OnCalculate := nil; + VertLineSeries.Active := false; + Chart.Title.Visible := false; + Chart.BottomAxis.Title.Caption := 'Scale'; +end; + +procedure TDistribFrm.SaveBtnClick(Sender: TObject); +var + ext: String; +begin + if SavePictureDialog.Execute then + begin + ext := Lowercase(ExtractFileExt(SavePictureDialog.FileName)); + case ext of + '.bmp': Chart.SaveToFile(TBitmap, SavePictureDialog.Filename); + '.png': Chart.SaveToFile(TPortableNetworkGraphic, SavePictureDialog.FileName); + '.jpg', '.jpeg', '.jpe', '.jfif': Chart.SaveToFile(TJpegImage, SavePictureDialog.FileName); + '.svg': Chart.SaveToSVGFile(SavePictureDialog.FileName); + end; + end; end; procedure TDistribFrm.FormShow(Sender: TObject); @@ -93,6 +130,47 @@ begin ResetBtnClick(self); end; +procedure TDistribFrm.CalcF(const AX: Double; out AY: Double); +var + ratio1, ratio2, ratio3, ratio4: double; + part1, part2, part3, part4, part5, part6, part7, part8, part9: double; +begin + // Returns the height of the density curve for the F statistic + ratio1 := (DF1 + DF2) / 2.0; + ratio2 := (DF1 - 2.0) / 2.0; + ratio3 := DF1 / 2.0; + ratio4 := DF2 / 2.0; + part1 := exp(lngamma(ratio1)); + part2 := power(DF1, ratio3); + part3 := power(DF2, ratio4); + part4 := exp(lngamma(ratio3)); + part5 := exp(lngamma(ratio4)); + part6 := power(AX, ratio2); + part7 := power((AX*DF1 + DF2), ratio1); + part8 := (part1 * part2 * part3) / (part4 * part5); + if (part7 = 0.0) then + part9 := 0.0 + else + part9 := part6 / part7; + AY := part8 * part9; +end; + +procedure TDistribFrm.CalcND(const AX: Double; out AY: Double); +begin + AY := 1.0 / sqrt(TWO_PI) * exp(-sqr(AX)/ 2.0); +end; + +procedure TDistribFrm.CalcChiSq(const AX: Double; out AY: Double); +begin + AY := 1.0 / (power(2.0, DF1*0.5) * exp(lngamma(DF1*0.5))) * power(AX, (DF1-2.0)*0.5) * (1.0 / exp(AX*0.5)); +end; + +procedure TDistribFrm.Calct(const AX: Double; out AY: Double); +begin + AY := Student(AX, DF1, 1.0); + //AY := tDist(AX, DF1, 1); +end; + procedure TDistribFrm.NDChkClick(Sender: TObject); begin if NDChk.Checked then @@ -111,6 +189,34 @@ begin GroupBox2.Enabled := false; end; +procedure TDistribFrm.PrintBtnClick(Sender: TObject); +const + MARGIN = 10; +var + R: TRect; + d: Integer; +begin + if not PrintDialog.Execute then + exit; + + Printer.BeginDoc; + try + R := Rect(0, 0, Printer.PageWidth, Printer.PageHeight div 2); + + d := R.Right - R.Left; + R.Left += d div MARGIN; + R.Right -= d div MARGIN; + + d := R.Bottom - R.Top; + R.Top += d div MARGIN; + R.Bottom -= d div MARGIN; + + Chart.Draw(TPrinterDrawer.Create(Printer, true), R); + finally + Printer.EndDoc; + end; +end; + procedure TDistribFrm.ComputeBtnClick(Sender: TObject); var msg: String; @@ -131,6 +237,12 @@ begin ok := true; end; + if tChk.Checked then + begin + tPlot(); + ok := true; + end; + if ChiChk.Checked then begin ChiPlot(); @@ -182,428 +294,148 @@ begin GroupBox2.Enabled := false; end; +procedure TDistribFrm.tChkClick(Sender: TObject); +begin + if tChk.Checked then + begin + GroupBox2.Enabled := true; + DF1Label.Enabled := true; + DF1Edit.Enabled := true; + DF2Label.Enabled := false; + MeanLabel.Enabled := false; + AlphaLabel.Enabled := true; + AlphaEdit.Enabled := true; + DF2Edit.Enabled := false; + MeanEdit.Enabled := false; + end else + GroupBox2.Enabled := false; +end; + + procedure TDistribFrm.NDPlot; var - CharLabel: string; - Clwidth, Clheight,X, Y, XAxisStart, XAxisEnd, YAxisStart, YAxisEnd: integer; - i, Xrange, Yrange, t: integer; - alpha, h, z, hprop, zprop: double; - RealPts: TwoCol; + alpha: Double; + zCrit, pCrit: Double; begin - for i := 1 to 100 do realpts[1,i] := 0.0; - for i := 1 to 100 do realpts[2,i] := 0.0; - - BlankFrm.Image1.Canvas.Pen.Color := clBlack; - BlankFrm.Image1.Canvas.Brush.Color := clWhite; - BlankFrm.Image1.Canvas.Clear; - BlankFrm.Image1.Canvas.FloodFill(1,1,clWhite,fsborder); - BlankFrm.Image1.Canvas.Pen.Width := 2; - Clwidth := BlankFrm.Image1.Width; - Clheight := BlankFrm.Image1.Height; - - XAxisStart := Clwidth div 8; - XAxisEnd := Clwidth - Clwidth div 8; - YAxisStart := (Clheight * 7) div 10; - YAxisEnd := Clheight div 10; - XRange := XAxisEnd - XAxisStart; - YRange := YAxisStart - YAxisEnd; alpha := StrToFloat(AlphaEdit.Text); + zCrit := inversez(1.0 - alpha); + CalcND(zCrit, pCrit); - BlankFrm.Show; - - // Create values of normal curve - NormPts(-4.0, 4.0, 100, RealPts); - PltPts(RealPts, 4.0, -4.0, 0.5, 0.0, 100, XAxisStart, YAxisStart, XRange, YRange, clBlack); - - // Draw line for alpha z := 1.645 - CharLabel := 'Normal Distribution. Alpha: ' + AlphaEdit.Text; - BlankFrm.Caption := CharLabel; - z := inversez(1.0 - alpha); - zprop := (4.0 + z) / 8.0; - h := (1.0 / sqrt(2.0 * 3.1415)) * (1.0 / exp(z * z / 2.0)); - hprop := (0.5 - h) / 0.5; - X := round(zprop * XRange) + XAxisStart; - Y := YAxisEnd + round(hprop * YRange); - BlankFrm.Image1.Canvas.MoveTo(X, YAxisStart); - BlankFrm.Image1.Canvas.LineTo(X, Y-10); // alpha cutoff - - // floodfill rejection section with red - BlankFrm.Image1.Canvas.Brush.Color := clRed; - BlankFrm.Image1.Canvas.Brush.Color := clWhite; - - // create labeled axis - HScale(-4.0, 4.0, 11, clWhite, 10, XAxisStart, YAxisStart, XRange, 'z SCALE'); - VScale(0.0, 0.5, 11, clWhite, 10, XAxisStart, YAxisStart, YRange, 'DENSITY'); - - // Print Heading - t := BlankFrm.Image1.Canvas.TextWidth(CharLabel); - X := (BlankFrm.Width - t) div 2; - BlankFrm.Image1.Canvas.TextOut(X, 0, charLabel); - CharLabel := 'Critical Value: ' + Format('%.3f',[z]); - t := BlankFrm.Image1.Canvas.TextWidth(charLabel); - X := (BlankFrm.Image1.Width - t) div 2; - Y := BlankFrm.Image1.Canvas.TextHeight(CharLabel); - BlankFrm.Image1.Canvas.TextOut(X, Y, CharLabel); + Chart.Title.Text.Clear; + Chart.Title.Text.Add('Normal Distribution'); + Chart.Title.Text.Add(Format('α = %.3g', [alpha])); + Chart.Title.Text.Add(Format('Critical value = %.3f', [zCrit])); + Chart.Title.Visible := true; + Chart.BottomAxis.Title.Caption := 'z'; + FuncSeries.Extent.XMin := -4; + FuncSeries.Extent.XMax := +4; + FuncSeries.Extent.UseXMin := true; + FuncSeries.Extent.UseXMax := true; + FuncSeries.OnCalculate := @CalcND; + FuncSeries.DomainExclusions.Clear; + VertLineSeries.Clear; + VertLineSeries.AddXY(zCrit, 0); + VertLineSeries.AddXY(zCrit, pCrit); + VertLineSeries.Active := true; end; procedure TDistribFrm.ChiPlot; var - charLabel: string; - ClWidth, ClHeight, X, Y, XAxisStart, XAxisEnd, YAxisStart, YAxisEnd: integer; - i, Xrange, Yrange, df, t: integer; - alpha, h, z, hprop, zprop, MaxChi, MaxProb: double; - RealPts: TwoCol; + alpha: Double; + Chi2Crit, pCrit: Double; begin - for i := 1 to 100 do realpts[1,i] := 0.0; - for i := 1 to 100 do realpts[2,i] := 0.0; - - MaxProb := 0.0; - BlankFrm.Image1.Canvas.Pen.Color := clBlack; - BlankFrm.Image1.Canvas.Brush.Color := clWhite; - BlankFrm.Image1.Canvas.Clear; - BlankFrm.Image1.Canvas.FloodFill(1, 1, clWhite, fsBorder); - BlankFrm.Image1.Canvas.Pen.Width := 2; - ClWidth := BlankFrm.Image1.Width; - ClHeight := BlankFrm.Image1.Height; - - XAxisStart := ClWidth div 8; - XAxisEnd := ClWidth - ClWidth div 8; - YAxisStart := (ClHeight * 7) div 10; - YAxisEnd := ClHeight div 10; - XRange := XAxisEnd - XAxisStart; - YRange := YAxisStart - YAxisEnd; alpha := StrToFloat(AlphaEdit.Text); - charLabel := 'Chi Squared Distribution. Alpha: ' + AlphaEdit.Text; - df := StrToInt(DF1Edit.Text); - if (df < 1) or (df > 100) then - exit; + DF1 := StrToInt(DF1Edit.Text); + Chi2Crit := InverseChi(1.0 - alpha, DF1); + CalcChiSq(Chi2Crit, pCrit); - charLabel := charLabel + ' D.F.: ' + DF1Edit.Text; - BlankFrm.Caption := charLabel; - BlankFrm.Show; - - // Create values of chi-squared curve - MaxChi := 125.0; - ChiPts(0.0, MaxChi, 100, df, realpts); - for i := 1 to 100 do - if (RealPts[2,i] > MaxProb) then - MaxProb := RealPts[2,i]; - PltPts(RealPts, MaxChi, 0.0, MaxProb, 0.0, 100, XAxisStart, YAxisStart, XRange, YRange, clBlack); - - // Draw line for alpha - z := InverseChi(1.0-alpha, df); - zprop := z / MaxChi; - h := Chi2Func(z, df); - hprop := (MaxProb - h) / MaxProb; - X := round(zprop * Xrange) + XaxisStart; - Y := YaxisEnd + round(hprop * Yrange); - BlankFrm.Image1.Canvas.MoveTo(X, YaxisStart); - BlankFrm.Image1.Canvas.LineTo(X, Y); // alpha cutoff - - // floodfill main section with blue - BlankFrm.Image1.Canvas.Brush.Color := clBlue; - BlankFrm.Image1.Canvas.Brush.Color := clWhite; - - // create charLabeled axis - HScale(0.0, MaxChi, 11, clWhite, 10, XAxisStart, YAxisStart, XRange, 'CHI SQUARED SCALE'); - VScale(0.0, MaxProb, 11, clWhite, 10, XAxisStart, YAxisStart, YRange, 'DENSITY'); - - // Print Heading - t := BlankFrm.Image1.Canvas.TextWidth(CharLabel); - X := (BlankFrm.Width - t) div 2; - BlankFrm.Image1.Canvas.TextOut(X,0,CharLabel); - - CharLabel := 'Critical Value: ' + Format('%6.3f',[z]); - t := BlankFrm.Image1.Canvas.TextWidth(CharLabel); - X := (BlankFrm.Image1.Width - t) div 2; - Y := BlankFrm.Image1.Canvas.TextHeight(CharLabel); - BlankFrm.Image1.Canvas.TextOut(X, Y, CharLabel); + Chart.Title.Text.Clear; + Chart.Title.Text.Add('Chi-Squared Distribution.'); + Chart.Title.Text.Add(Format('α = %.3g / Degrees of freedom = %d', [alpha, DF1])); + Chart.Title.Text.Add(Format('Critical value = %.3f', [Chi2Crit])); + Chart.Title.Visible := true; + Chart.BottomAxis.Title.Caption := 'χ2'; + FuncSeries.Extent.XMin := 0; + FuncSeries.Extent.XMax := 125; + FuncSeries.Extent.UseXMin := true; + FuncSeries.Extent.UseXMax := true; + FuncSeries.OnCalculate := @CalcChiSq; + FuncSeries.DomainExclusions.AddRange(-Infinity, 0, [ioOpenEnd]); + VertLineSeries.Clear; + VertLineSeries.AddXY(Chi2Crit, 0); + VertLineSeries.AddXY(Chi2Crit, pCrit); + VertLineSeries.Active := true; end; procedure TDistribFrm.FPlot; var - CharLabel: string; - ClWidth, ClHeight, X, Y, XAxisStart, XAxisEnd, YAxisStart, YAxisEnd: integer; - i, Xrange, Yrange, t, df1, df2: integer; - RealPts: TwoCol; - alpha, h, F, hprop, Fprop, MaxProb, MaxF: double; - done: boolean; + alpha: Double; + FCrit, pCrit: Double; begin - for i := 1 to 100 do - begin - realpts[1,i] := 0.0; - realpts[2,i] := 0.0; - end; - - MaxProb := 0.0; - BlankFrm.Image1.Canvas.Pen.Color := clBlack; - BlankFrm.Image1.Canvas.Brush.Color := clWhite; - BlankFrm.Image1.Canvas.Clear; - BlankFrm.Image1.Canvas.FloodFill(1,1,clWhite,fsborder); - BlankFrm.Image1.Canvas.Pen.Width := 2; - ClWidth := BlankFrm.Image1.Width; - ClHeight := BlankFrm.Image1.Height; - XAxisStart := ClWidth div 8; - XAxisEnd := ClWidth - ClWidth div 8; - YAxisStart := (ClHeight * 7) div 10; - YAxisEnd := ClHeight div 10; - XRange := XAxisEnd - XAxisStart; - YRange := YAxisStart - YAxisEnd; - alpha := StrToFloat(AlphaEdit.Text); - charLabel := 'F Distribution. Alpha: ' + AlphaEdit.Text; - df1 := StrToInt(DF1Edit.Text); - CharLabel := CharLabel + ', D.F.1: '; - CharLabel := CharLabel + DF1Edit.Text; - df2 := StrToInt(DF2Edit.Text); - CharLabel := CharLabel + ', D.F.2: '; - CharLabel := CharLabel + DF2Edit.Text; - BlankFrm.Caption := CharLabel; - BlankFrm.Show; + DF1 := StrToInt(DF1Edit.Text); + DF2 := StrToInt(DF2Edit.Text); + FCrit := FPercentPoint(1.0 - alpha, DF1, DF2); + CalcF(FCrit, pCrit); - // Create values of F curve - MaxF := 20.0; - done := false; - while not done do - begin - h := Ffunc(MaxF, df1, df2); - if h < 0.001 then - MaxF := MaxF - 1.0 - else - done := true; - end; - - FPts(0.0, MaxF, 100, df1, df2, RealPts); - for i := 1 to 100 do - if (RealPts[2,i] > MaxProb) then - MaxProb := RealPts[2,i]; - PltPts(RealPts, MaxF, 0.0, MaxProb, 0.0, 100, XAxisStart, YAxisStart, XRange, YRange, clBlack); - - // Draw line for alpha - F := FPercentPoint(1.0-alpha, df1, df2); - Fprop := F / MaxF; - h := Ffunc(F, df1, df2); - hprop := (MaxProb - h) / MaxProb; - X := round(Fprop * XRange) + XAxisStart; - Y := YAxisEnd + round(hprop * YRange); - BlankFrm.Image1.Canvas.MoveTo(X, YAxisStart); - BlankFrm.Image1.Canvas.LineTo(X, Y); // alpha cutoff - - // floodfill main section with blue - BlankFrm.Canvas.Brush.Color := clBlue; - - // create charLabeled axis - HScale(0.0, MaxF, 11, clWhite, 10, XAxisStart, YAxisStart, XRange, 'F SCALE'); - VScale(0.0, MaxProb, 11, clWhite, 10, XAxisStart, YAxisStart, YRange, 'DENSITY'); - - // Print Heading - t := BlankFrm.Image1.Canvas.TextWidth(CharLabel); - X := (BlankFrm.Image1.Width - t) div 2; - BlankFrm.Image1.Canvas.TextOut(X, 0, CharLabel); - charLabel := 'Critical Value: ' + Format('%.3f', [F]); - t := BlankFrm.Image1.Canvas.TextWidth(charLabel); - X := (BlankFrm.Image1.Width - t) div 2; - Y := BlankFrm.Image1.Canvas.TextHeight(CharLabel); - BlankFrm.Image1.Canvas.TextOut(X, Y, CharLabel); + Chart.Title.Text.Clear; + Chart.Title.Text.Add('F Distribution.'); + Chart.Title.Text.Add(Format('α = %.3g / DF1 = %d, DF2 = %d', [alpha, DF1, DF2])); + Chart.Title.Text.Add(Format('Critical value = %.3f', [FCrit])); + Chart.Title.Visible := true; + Chart.BottomAxis.Title.Caption := 'F'; + FuncSeries.Extent.XMin := 0; + FuncSeries.Extent.XMax := 15; + FuncSeries.Extent.UseXMin := true; + FuncSeries.Extent.UseXMax := true; + FuncSeries.OnCalculate := @CalcF; + FuncSeries.DomainExclusions.AddRange(-Infinity, 0, [ioOpenEnd]); + VertLineSeries.Clear; + VertLineSeries.AddXY(FCrit, 0); + VertLineSeries.AddXY(FCrit, pCrit); + VertLineSeries.Active := true; end; -procedure TDistribFrm.HScale(XMin, XMax: double; Nsteps: integer; - AColor: TColor; FontSize: integer; X, Y, XLength: integer; CharLabel: string); +procedure TDistribFrm.tPlot; var - i, TickEnd, Xpos, Ypos, TextX: integer; - Xincr, Xval: double; + alpha: Double; + tCrit, pCrit: Double; begin - BlankFrm.Image1.Canvas.MoveTo(X,Y); - BlankFrm.Image1.Canvas.LineTo(X+Xlength,Y); - BlankFrm.Image1.Canvas.Font.Size := FontSize; - BlankFrm.Image1.Canvas.Brush.Color := AColor; - TickEnd := Y + 10; - Xincr := (Xmax - Xmin) / Nsteps; - for i := 0 to Nsteps do - begin - XPos := round(Xlength/Nsteps*i + X); - BlankFrm.Image1.Canvas.MoveTo(XPos, Y); - BlankFrm.Image1.Canvas.LineTo(XPos, TickEnd); - TextX := XPos - 8; - Xval := Xmin + i*Xincr; - BlankFrm.Image1.Canvas.TextOut(TextX, Y+15, Format('%.2f', [Xval])); - end; + alpha := StrToFloat(AlphaEdit.Text); + DF1 := StrToInt(DF1Edit.Text); + tCrit := Inverset(1.0 - alpha, DF1); + Calct(tCrit, pCrit); - // print charLabel below X axis - YPos := Y + 30; - XPos := round((BlankFrm.Width / 2) - (BlankFrm.Image1.Canvas.TextWidth(CharLabel) / 2)); - BlankFrm.Image1.Canvas.TextOut(Xpos, Ypos, CharLabel); -end; - -procedure TDistribFrm.VScale(YMin, YMax: double; NSteps: integer; - AColor: TColor; FontSize: integer; X, Y, YLength: integer; CharLabel: string); -var - TickEnd, Ypos, Xpos, TextY: integer; - Yincr, Yval: double; - chpixs, i: integer; -begin - BlankFrm.Image1.Canvas.MoveTo(X,Y); - BlankFrm.Image1.Canvas.LineTo(X,Y-Ylength); - BlankFrm.Image1.Canvas.Font.Size := FontSize; - BlankFrm.Image1.Canvas.Brush.Color := AColor; - - TickEnd := X - 10; - Yincr := (YMax - YMin) / Nsteps; - TextY := 0; - for i := 0 to NSteps do - begin - YPos := round(Y - Ylength / NSteps * i); - BlankFrm.Image1.Canvas.MoveTo(X, YPos); - BlankFrm.Image1.Canvas.LineTo(TickEnd, YPos); - TextY := TickEnd - 30; - Yval := Ymin + i * Yincr; - BlankFrm.Image1.Canvas.TextOut(TextY, Ypos-8, Format('%.2f', [Yval])); - end; - - // print charLabel vertically - chpixs := BlankFrm.Image1.Canvas.TextHeight(CharLabel); - XPos := TextY - 15; - for i := 1 to Length(CharLabel) do - begin - YPos := round(Y - YLength / 2 - Length(charLabel) * chpixs / 2 + chpixs*i); - BlankFrm.Image1.Canvas.TextOut(XPos, YPos, CharLabel[i]); - end; -end; - -procedure TDistribFrm.NormPts(zMin, zMax: double; NPts: integer; - var RealPts: TwoCol); -var - zIncr, z, h: double; - i: integer; -begin - zIncr := (zMax - zMin) / Npts; - for i := 1 to Npts do - begin - z := zMin + (zIncr * i); - h := (1.0 / sqrt(2.0 * PI)) * (1.0 / exp(z * z / 2.0)); - RealPts[1, i] := z; - RealPts[2, i] := h; - end; -end; - -procedure TDistribFrm.PltPts(RealPts: TwoCol; Xmax, Xmin, Ymax, Ymin: double; - NPts, XAxisStart, YAxisStart, XAxisRange, YAxisRange: integer; AColor: TColor); -var - hprop, zprop, z, h: double; - i, X, Y: integer; - intpts: array[1..100] of TPoint; -begin - for i := 1 to NPts do - begin - z := RealPts[1,i]; - h := RealPts[2,i]; - zprop := (z - XMin) / (XMax - XMin); - X := round(zprop * XAxisRange + XAxisStart); - hprop := (h - Ymin) / (Ymax - Ymin); - Y := round(YAxisStart - hprop * YAxisRange); - intpts[i] := Point(X, Y); - end; - BlankFrm.Image1.Canvas.Pen.Color := AColor; - BlankFrm.Image1.Canvas.Polyline(Slice(intpts, Npts - 1)); -end; - -procedure TDistribFrm.ChiPts(cMin, cMax: double; NPts, DF: integer; - var RealPts: TwoCol); -var - ratio1, ratio2, ratio3, cIncr, chi, h: double; - i: integer; -begin - ratio1 := DF / 2.0; - ratio2 := (DF - 2.0) / 2.0; - cIncr := (cMax - cMin) / NPts; - for i := 1 to NPts do - begin - chi := cMin + cIncr*i; -// h := inversechi(chi, df); - ratio3 := chi / 2.0; - h := (1.0 / (power(2.0, ratio1) * exp(lngamma(ratio1)))) * power(chi, ratio2) * (1.0 / exp(ratio3)); - RealPts[1,i] := chi; - RealPts[2,i] := h; - end; -end; - -procedure TDistribFrm.FPts(FMin, FMax: double; NPts, DF1, DF2: integer; - var RealPts: TwoCol); -var - FIncr, F, h: double; - i: integer; -begin - FIncr := (FMax - FMin) / NPts; - for i := 1 to NPts do - begin - F := FMin + FIncr * i; - h := Ffunc(F, DF1, DF2); - RealPts[1,i] := F; - RealPts[2,i] := h; - end; -end; - -function TDistribFrm.Chi2Func(ChiSqr, DF: double): double; -var - ratio1, ratio2, ratio3: double; -begin - // Returns the height of the density curve for the chi-squared statistic - ratio1 := df / 2.0; - ratio2 := (df - 2.0) / 2.0; - ratio3 := chisqr / 2.0; - Result := (1.0 / (power(2.0,ratio1) * exp(lngamma(ratio1)))) * power(chisqr,ratio2) * (1.0 / exp(ratio3)); -end; - -function TDistribFrm.FFunc(F: double; DF1, DF2: integer): double; -var - ratio1, ratio2, ratio3, ratio4: double; - part1, part2, part3, part4, part5, part6, part7, part8, part9: double; -begin - // Returns the height of the density curve for the F statistic - ratio1 := (df1 + df2) / 2.0; - ratio2 := (df1 - 2.0) / 2.0; - ratio3 := df1 / 2.0; - ratio4 := df2 / 2.0; - part1 := exp(lngamma(ratio1)); - part2 := power(df1, ratio3); - part3 := power(df2, ratio4); - part4 := exp(lngamma(ratio3)); - part5 := exp(lngamma(ratio4)); - part6 := power(F,ratio2); - part7 := power((F*df1 + df2), ratio1); - part8 := (part1 * part2 * part3) / (part4 * part5); - if (part7 = 0.0) then - part9 := 0.0 - else - part9 := part6 / part7; - Result := part8 * part9; -{ - ratio1 := (df1 + df2) / 2.0; - ratio2 := (df1 - 2.0) / 2.0; - ratio3 := df1 / 2.0; - ratio4 := df2 / 2.0; - ffunc := ((gamma(ratio1) * realraise(df1,ratio3) * - realraise(df2,ratio4)) / - (gamma(ratio3) * gamma(ratio4))) * - (realraise(f,ratio2) / realraise((f*df1+df2),ratio1)); -} + Chart.Title.Text.Clear; + Chart.Title.Text.Add('Student t Distribution.'); + Chart.Title.Text.Add(Format('α = %.3g / Degrees of freedom = %d', [alpha, DF1])); + Chart.Title.Text.Add(Format('Critical value = %.3f', [tCrit])); + Chart.Title.Visible := true; + Chart.BottomAxis.Title.Caption := 't'; + FuncSeries.Extent.XMin := -4; + FuncSeries.Extent.XMax := 4; + FuncSeries.Extent.UseXMin := true; + FuncSeries.Extent.UseXMax := true; + FuncSeries.OnCalculate := @Calct; + FuncSeries.DomainExclusions.Clear; + VertLineSeries.Clear; + VertLineSeries.AddXY(tCrit, 0); + VertLineSeries.AddXY(tCrit, pCrit); + VertLineSeries.Active := true; end; procedure TDistribFrm.FormActivate(Sender: TObject); var w: Integer; begin - w := MaxValue([ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); + w := MaxValue([SaveBtn.Width, PrintBtn.Width, ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); + SaveBtn.Width := w; + PrintBtn.Width := w; ResetBtn.Constraints.MinWidth := w; ComputeBtn.Constraints.MinWidth := w; CloseBtn.Constraints.MinWidth := w; end; -procedure TDistribFrm.FormCreate(Sender: TObject); -begin - if BlankFrm = nil then - Application.CreateForm(TBlankFrm, BlankFrm); -end; function TDistribFrm.Validate(out AMsg: String; out AControl: TWinControl): boolean; var