diff --git a/applications/lazstats/source/forms/analysis/descriptive/boxplotunit.pas b/applications/lazstats/source/forms/analysis/descriptive/boxplotunit.pas index e01beb3c7..44e158e32 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/boxplotunit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/boxplotunit.pas @@ -387,8 +387,7 @@ procedure TBoxPlotFrm.FormCreate(Sender: TObject); begin Assert(OS3MainFrm <> nil); - Width := Scale96ToFont(DEFAULT_WIDTH); - Height := Scale96ToFont(DEFAULT_HEIGHT); + InitForm(self); FReportFrame := TReportFrame.Create(self); FReportFrame.Parent := ReportPage; diff --git a/applications/lazstats/source/forms/analysis/descriptive/bubbleplotunit.pas b/applications/lazstats/source/forms/analysis/descriptive/bubbleplotunit.pas index d109a1817..6e9816e8f 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/bubbleplotunit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/bubbleplotunit.pas @@ -400,8 +400,7 @@ begin Assert(OS3MainFrm <> nil); if DictionaryFrm = nil then Application.CreateForm(TDictionaryFrm, DictionaryFrm); - Width := Scale96ToFont(DEFAULT_WIDTH); - Height := Scale96ToFont(DEFAULT_HEIGHT); + InitForm(self); FReportFrame := TReportFrame.Create(self); FReportFrame.Parent := ReportPage; diff --git a/applications/lazstats/source/forms/analysis/descriptive/frequnit.lfm b/applications/lazstats/source/forms/analysis/descriptive/frequnit.lfm index 1169b3cbb..6b6da14b4 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/frequnit.lfm +++ b/applications/lazstats/source/forms/analysis/descriptive/frequnit.lfm @@ -1,285 +1,367 @@ object FreqFrm: TFreqFrm Left = 490 - Height = 388 + Height = 543 Top = 228 - Width = 502 + Width = 889 HelpType = htKeyword HelpKeyword = 'html/FrequencyAnalysis.htm' Caption = 'Frequency Distribution' - ClientHeight = 388 - ClientWidth = 502 + ClientHeight = 543 + ClientWidth = 889 OnActivate = FormActivate OnCreate = FormCreate - OnShow = FormShow Position = poMainFormCenter LCLVersion = '2.1.0.0' - object PlotOptionsGroup: TRadioGroup - AnchorSideTop.Control = Owner - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - Left = 346 - Height = 222 - Top = 8 - Width = 148 - Anchors = [akTop, akRight] - AutoFill = True - AutoSize = True - BorderSpacing.Top = 8 - BorderSpacing.Right = 8 - Caption = 'Plot Options' - ChildSizing.LeftRightSpacing = 12 - ChildSizing.TopBottomSpacing = 6 - ChildSizing.EnlargeHorizontal = crsHomogenousChildResize - ChildSizing.EnlargeVertical = crsHomogenousChildResize - ChildSizing.ShrinkHorizontal = crsScaleChilds - ChildSizing.ShrinkVertical = crsScaleChilds - ChildSizing.Layout = cclLeftToRightThenTopToBottom - ChildSizing.ControlsPerLine = 1 - ClientHeight = 202 - ClientWidth = 144 - ItemIndex = 0 - Items.Strings = ( - '2D Vertical Bars' - '3D Vertical Bars' - '2D Pie Chart' - 'Exploded Pie Chart' - '2D Line Chart' - '3D Line Chart' - 'Plot 2D Points' - 'Plot 3D Points' - '2D Horizontal Bars' - '3D Horizontal Bars' - ) - OnSelectionChanged = PlotOptionsGroupSelectionChanged - TabOrder = 1 - end - object BarTypeGroup: TRadioGroup - AnchorSideLeft.Control = PlotOptionsGroup - AnchorSideTop.Control = PlotOptionsGroup - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = PlotOptionsGroup - AnchorSideRight.Side = asrBottom - Left = 346 - Height = 70 - Top = 242 - Width = 148 - Anchors = [akTop, akLeft, akRight] - AutoFill = True - AutoSize = True - BorderSpacing.Top = 12 - Caption = 'Bar Type' - ChildSizing.LeftRightSpacing = 12 - ChildSizing.TopBottomSpacing = 6 - ChildSizing.EnlargeHorizontal = crsHomogenousChildResize - ChildSizing.EnlargeVertical = crsHomogenousChildResize - ChildSizing.ShrinkHorizontal = crsScaleChilds - ChildSizing.ShrinkVertical = crsScaleChilds - ChildSizing.Layout = cclLeftToRightThenTopToBottom - ChildSizing.ControlsPerLine = 1 - ClientHeight = 50 - ClientWidth = 144 - Enabled = False - ItemIndex = 0 - Items.Strings = ( - 'Separated' - 'Contiguous' - ) - TabOrder = 2 - end - object NormPltChk: TCheckBox - AnchorSideLeft.Control = Owner - AnchorSideTop.Side = asrBottom - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Bevel1 + object ParamsPanel: TPanel Left = 8 - Height = 19 - Top = 320 - Width = 149 - Anchors = [akLeft, akBottom] + Height = 527 + Top = 8 + Width = 288 + Align = alLeft BorderSpacing.Left = 8 BorderSpacing.Top = 8 - Caption = 'Plot Normal Distribution' - TabOrder = 3 - end - object Panel1: TPanel - AnchorSideLeft.Control = Owner - AnchorSideTop.Control = Owner - AnchorSideRight.Control = PlotOptionsGroup - AnchorSideBottom.Control = NormPltChk - Left = 8 - Height = 304 - Top = 8 - Width = 330 - Anchors = [akTop, akLeft, akRight, akBottom] - BorderSpacing.Around = 8 + BorderSpacing.Right = 4 + BorderSpacing.Bottom = 8 BevelOuter = bvNone - ClientHeight = 304 - ClientWidth = 330 + ClientHeight = 527 + ClientWidth = 288 TabOrder = 0 - object Label1: TLabel - AnchorSideLeft.Control = Panel1 - AnchorSideTop.Control = Panel1 - Left = 0 - Height = 15 - Top = 0 - Width = 97 - Caption = 'Available Variables' - ParentColor = False - end - object Label2: TLabel - AnchorSideLeft.Control = SelList - AnchorSideTop.Control = Panel1 - Left = 196 - Height = 15 - Top = 0 - Width = 104 - Caption = 'Variables to Analyze' - ParentColor = False - end - object VarList: TListBox - AnchorSideLeft.Control = Panel1 - AnchorSideTop.Control = Label1 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = AllBtn - AnchorSideBottom.Control = Panel1 - AnchorSideBottom.Side = asrBottom - Left = 0 - Height = 287 - Top = 17 - Width = 134 - Anchors = [akTop, akLeft, akRight, akBottom] - BorderSpacing.Top = 2 - BorderSpacing.Right = 8 - ItemHeight = 0 - MultiSelect = True - OnSelectionChange = VarListSelectionChange - TabOrder = 0 - end - object SelList: TListBox - AnchorSideLeft.Control = AllBtn - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = Label2 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Panel1 + object Panel1: TPanel + AnchorSideLeft.Control = ParamsPanel + AnchorSideTop.Control = ParamsPanel + AnchorSideRight.Control = ParamsPanel AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Panel1 - AnchorSideBottom.Side = asrBottom - Left = 196 - Height = 287 - Top = 17 - Width = 134 - Anchors = [akTop, akLeft, akRight, akBottom] - BorderSpacing.Left = 8 - BorderSpacing.Top = 2 - ItemHeight = 0 - OnSelectionChange = SelListSelectionChange - TabOrder = 4 + AnchorSideBottom.Control = PlotOptionsGroup + Left = 0 + Height = 217 + Top = 0 + Width = 288 + Anchors = [akTop, akLeft, akRight] + BevelOuter = bvNone + ClientHeight = 217 + ClientWidth = 288 + TabOrder = 0 + object Label1: TLabel + AnchorSideLeft.Control = Panel1 + AnchorSideTop.Control = Panel1 + Left = 0 + Height = 15 + Top = 0 + Width = 97 + Caption = 'Available Variables' + ParentColor = False + end + object Label2: TLabel + AnchorSideLeft.Control = SelList + AnchorSideTop.Control = Panel1 + Left = 175 + Height = 15 + Top = 0 + Width = 104 + Caption = 'Variables to Analyze' + ParentColor = False + end + object VarList: TListBox + AnchorSideLeft.Control = Panel1 + AnchorSideTop.Control = Label1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = AllBtn + AnchorSideBottom.Control = Panel1 + AnchorSideBottom.Side = asrBottom + Left = 0 + Height = 200 + Top = 17 + Width = 113 + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Top = 2 + BorderSpacing.Right = 8 + ItemHeight = 0 + MultiSelect = True + OnDblClick = VarListDblClick + OnSelectionChange = VarListSelectionChange + TabOrder = 0 + end + object SelList: TListBox + AnchorSideLeft.Control = AllBtn + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Label2 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = Panel1 + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Panel1 + AnchorSideBottom.Side = asrBottom + Left = 175 + Height = 200 + Top = 17 + Width = 113 + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Left = 8 + BorderSpacing.Top = 2 + ItemHeight = 0 + OnSelectionChange = SelListSelectionChange + TabOrder = 4 + end + object InBtn: TBitBtn + AnchorSideLeft.Control = Panel1 + AnchorSideLeft.Side = asrCenter + Left = 131 + Height = 26 + Top = 23 + Width = 26 + Images = MainDataModule.ImageList + ImageIndex = 1 + OnClick = InBtnClick + Spacing = 0 + TabOrder = 1 + end + object OutBtn: TBitBtn + AnchorSideLeft.Control = Panel1 + AnchorSideLeft.Side = asrCenter + Left = 131 + Height = 26 + Top = 56 + Width = 26 + Images = MainDataModule.ImageList + ImageIndex = 0 + OnClick = OutBtnClick + Spacing = 0 + TabOrder = 2 + end + object AllBtn: TBitBtn + AnchorSideLeft.Control = Panel1 + AnchorSideLeft.Side = asrCenter + AnchorSideTop.Control = OutBtn + AnchorSideTop.Side = asrBottom + Left = 121 + Height = 25 + Top = 106 + Width = 46 + AutoSize = True + BorderSpacing.Top = 24 + Caption = 'ALL' + OnClick = AllBtnClick + TabOrder = 3 + end end - object InBtn: TBitBtn - AnchorSideLeft.Control = Panel1 - AnchorSideLeft.Side = asrCenter - Left = 151 - Height = 28 - Top = 23 - Width = 28 - Images = MainDataModule.ImageList - ImageIndex = 1 - OnClick = InBtnClick - Spacing = 0 + object PlotOptionsGroup: TRadioGroup + AnchorSideLeft.Control = ParamsPanel + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = BarTypeGroup + Left = 0 + Height = 127 + Top = 273 + Width = 277 + Anchors = [akLeft, akBottom] + AutoFill = True + AutoSize = True + BorderSpacing.Top = 8 + BorderSpacing.Right = 8 + Caption = 'Plot Options' + ChildSizing.LeftRightSpacing = 12 + ChildSizing.TopBottomSpacing = 6 + ChildSizing.HorizontalSpacing = 12 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 2 + ClientHeight = 107 + ClientWidth = 273 + Columns = 2 + ItemIndex = 0 + Items.Strings = ( + '2D Vertical Bars' + '3D Vertical Bars' + '2D Pie Chart' + 'Exploded Pie Chart' + '2D Line Chart' + '3D Line Chart' + 'Plot 2D Points' + 'Plot 3D Points' + '2D Horizontal Bars' + '3D Horizontal Bars' + ) + OnSelectionChanged = PlotOptionsGroupSelectionChanged TabOrder = 1 end - object OutBtn: TBitBtn - AnchorSideLeft.Control = Panel1 - AnchorSideLeft.Side = asrCenter - Left = 151 - Height = 28 - Top = 56 - Width = 28 - Images = MainDataModule.ImageList - ImageIndex = 0 - OnClick = OutBtnClick - Spacing = 0 + object NormPltChk: TCheckBox + AnchorSideLeft.Control = ParamsPanel + AnchorSideTop.Side = asrBottom + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Bevel1 + Left = 0 + Height = 19 + Top = 467 + Width = 149 + Anchors = [akLeft, akBottom] + BorderSpacing.Top = 8 + Caption = 'Plot Normal Distribution' TabOrder = 2 end - object AllBtn: TBitBtn - AnchorSideLeft.Control = Panel1 - AnchorSideLeft.Side = asrCenter - Left = 142 + object Bevel1: TBevel + AnchorSideLeft.Control = ParamsPanel + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = CloseBtn + Left = 0 + Height = 8 + Top = 486 + Width = 288 + Anchors = [akLeft, akRight, akBottom] + Shape = bsBottomLine + end + object ResetBtn: TButton + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = ComputeBtn + AnchorSideBottom.Control = ParamsPanel + AnchorSideBottom.Side = asrBottom + Left = 87 Height = 25 - Top = 136 - Width = 46 + Top = 502 + Width = 54 + Anchors = [akRight, akBottom] AutoSize = True - Caption = 'ALL' - OnClick = AllBtnClick + Caption = 'Reset' + OnClick = ResetBtnClick TabOrder = 3 end + object CloseBtn: TButton + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = ParamsPanel + AnchorSideBottom.Side = asrBottom + Left = 233 + Height = 25 + Top = 502 + Width = 55 + Anchors = [akRight, akBottom] + AutoSize = True + BorderSpacing.Left = 8 + BorderSpacing.Top = 8 + Caption = 'Close' + ModalResult = 1 + OnClick = CloseBtnClick + TabOrder = 4 + end + object ComputeBtn: TButton + AnchorSideRight.Control = CloseBtn + AnchorSideBottom.Control = ParamsPanel + AnchorSideBottom.Side = asrBottom + Left = 149 + Height = 25 + Top = 502 + Width = 76 + Anchors = [akRight, akBottom] + AutoSize = True + BorderSpacing.Left = 8 + BorderSpacing.Top = 8 + BorderSpacing.Right = 8 + Caption = 'Compute' + OnClick = ComputeBtnClick + TabOrder = 5 + end + object BarTypeGroup: TRadioGroup + AnchorSideLeft.Control = ParamsPanel + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = NormPltChk + Left = 0 + Height = 51 + Top = 408 + Width = 182 + Anchors = [akLeft, akBottom] + AutoFill = True + AutoSize = True + BorderSpacing.Top = 8 + Caption = 'Bar Type' + ChildSizing.LeftRightSpacing = 12 + ChildSizing.TopBottomSpacing = 6 + ChildSizing.EnlargeHorizontal = crsHomogenousChildResize + ChildSizing.EnlargeVertical = crsHomogenousChildResize + ChildSizing.ShrinkHorizontal = crsScaleChilds + ChildSizing.ShrinkVertical = crsScaleChilds + ChildSizing.Layout = cclLeftToRightThenTopToBottom + ChildSizing.ControlsPerLine = 2 + ClientHeight = 31 + ClientWidth = 178 + Columns = 2 + Enabled = False + ItemIndex = 0 + Items.Strings = ( + 'Separated' + 'Contiguous' + ) + TabOrder = 6 + end + object Panel2: TPanel + AnchorSideLeft.Control = ParamsPanel + AnchorSideRight.Control = ParamsPanel + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = PlotOptionsGroup + Left = 0 + Height = 23 + Top = 236 + Width = 288 + Anchors = [akTop, akLeft, akRight] + AutoSize = True + BevelOuter = bvNone + ClientHeight = 23 + ClientWidth = 288 + TabOrder = 7 + object NoIntervalsEdit: TSpinEdit + AnchorSideLeft.Control = NoIntervalsLabel + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Panel2 + Left = 121 + Height = 23 + Top = 0 + Width = 74 + Alignment = taRightJustify + BorderSpacing.Left = 16 + MinValue = 1 + TabOrder = 0 + Value = 10 + end + object NoIntervalsLabel: TLabel + AnchorSideLeft.Control = Panel2 + AnchorSideTop.Control = NoIntervalsEdit + AnchorSideTop.Side = asrCenter + Left = 0 + Height = 15 + Top = 4 + Width = 105 + Caption = 'Number of intervals' + ParentColor = False + end + end end - object Bevel1: TBevel - AnchorSideLeft.Control = Owner - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = CloseBtn - Left = 0 - Height = 8 - Top = 339 - Width = 502 - Anchors = [akLeft, akRight, akBottom] - Shape = bsBottomLine + object ParamsSplitter: TSplitter + Left = 300 + Height = 543 + Top = 0 + Width = 5 + ResizeStyle = rsPattern end - object ResetBtn: TButton - AnchorSideTop.Side = asrCenter - AnchorSideRight.Control = ComputeBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 289 - Height = 25 - Top = 355 - Width = 54 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 12 - BorderSpacing.Bottom = 8 - Caption = 'Reset' - OnClick = ResetBtnClick - TabOrder = 4 - end - object CloseBtn: TButton - AnchorSideLeft.Side = asrBottom - AnchorSideTop.Side = asrCenter - AnchorSideRight.Control = Owner - AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 435 - Height = 25 - Top = 355 - Width = 55 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 - BorderSpacing.Top = 8 - BorderSpacing.Right = 12 - BorderSpacing.Bottom = 8 - Caption = 'Close' - ModalResult = 1 - TabOrder = 5 - end - object ComputeBtn: TButton - AnchorSideRight.Control = CloseBtn - AnchorSideBottom.Control = Owner - AnchorSideBottom.Side = asrBottom - Left = 351 - Height = 25 - Top = 355 - Width = 76 - Anchors = [akRight, akBottom] - AutoSize = True - BorderSpacing.Left = 8 + object PageControl: TPageControl + Left = 309 + Height = 527 + Top = 8 + Width = 572 + ActivePage = ReportPage + Align = alClient + BorderSpacing.Left = 4 BorderSpacing.Top = 8 BorderSpacing.Right = 8 BorderSpacing.Bottom = 8 - Caption = 'Compute' - OnClick = ComputeBtnClick - TabOrder = 6 + TabIndex = 0 + TabOrder = 2 + object ReportPage: TTabSheet + Caption = 'Report' + end end end diff --git a/applications/lazstats/source/forms/analysis/descriptive/frequnit.pas b/applications/lazstats/source/forms/analysis/descriptive/frequnit.pas index 2fc717112..190a0ae5b 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/frequnit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/frequnit.pas @@ -7,9 +7,9 @@ unit FreqUnit; interface uses - Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, - StdCtrls, Buttons, ExtCtrls, - Globals, MainUnit, OutputUnit, FunctionsLib, GraphLib, DataProcs; + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, + StdCtrls, Buttons, ExtCtrls, ComCtrls, Spin, + Globals, MainUnit, FunctionsLib, GraphLib, DataProcs, ReportFrameUnit, ChartFrameUnit; type @@ -18,7 +18,11 @@ type TFreqFrm = class(TForm) Bevel1: TBevel; ComputeBtn: TButton; + NoIntervalsLabel: TLabel; + PageControl: TPageControl; Panel1: TPanel; + Panel2: TPanel; + ParamsPanel: TPanel; ResetBtn: TButton; CloseBtn: TButton; NormPltChk: TCheckBox; @@ -30,86 +34,51 @@ type SelList: TListBox; PlotOptionsGroup: TRadioGroup; BarTypeGroup: TRadioGroup; + ParamsSplitter: TSplitter; + ReportPage: TTabSheet; + NoIntervalsEdit: TSpinEdit; VarList: TListBox; procedure AllBtnClick(Sender: TObject); + procedure CloseBtnClick(Sender: TObject); + procedure ComputeBtnClick(Sender: TObject); procedure FormActivate(Sender: TObject); procedure FormCreate(Sender: TObject); - procedure FormShow(Sender: TObject); procedure InBtnClick(Sender: TObject); - procedure ComputeBtnClick(Sender: TObject); - procedure PlotOptionsGroupSelectionChanged(Sender: TObject); - procedure SelListSelectionChange(Sender: TObject; User: boolean); procedure OutBtnClick(Sender: TObject); + procedure PlotOptionsGroupSelectionChanged(Sender: TObject); procedure ResetBtnClick(Sender: TObject); + procedure SelListSelectionChange(Sender: TObject; User: boolean); + procedure VarListDblClick(Sender: TObject); procedure VarListSelectionChange(Sender: TObject; User: boolean); private { private declarations } + FReportFrame: TReportFrame; FAutoSized: Boolean; + procedure ClearTabs; + function CreateChartFrame(AColIndex: Integer; AVarName: String): TChartFrame; + function GetPageCaption(AVarName: String): String; + procedure PlotFreq(AColIndex: Integer; AVarName: String; const xLabels: StrDyneVec; + const Freq: DblDyneVec); procedure UpdateBtnStates; public { public declarations } + procedure Reset; end; var FreqFrm: TFreqFrm; + implementation +{$R *.lfm} + uses - Math, - FreqSpecsUnit; + Math, TAChartUtils, TALegend, TASeries, + Utils, FreqSpecsUnit; { TFreqFrm } -procedure TFreqFrm.ResetBtnClick(Sender: TObject); -var - i: integer; - -begin - VarList.Clear; - SelList.Clear; - for i := 1 to NoVariables do - VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); - BarTypeGroup.ItemIndex := 0; - PlotOptionsGroup.ItemIndex := 0; - NormPltChk.Checked := false; - UpdateBtnStates; -end; - -procedure TFreqFrm.FormActivate(Sender: TObject); -var - w: Integer; -begin - if FAutoSized then - exit; - - w := MaxValue([ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); - ResetBtn.Constraints.MinWidth := w; - ComputeBtn.Constraints.MinWidth := w; - CloseBtn.Constraints.MinWidth := w; - Panel1.Constraints.MinHeight := BarTypeGroup.Top + BarTypeGroup.Height - Panel1.Top; - Panel1.Constraints.MinWidth := Label2.Width * 2 + AllBtn.Width + 2 * VarList.BorderSpacing.Right; - Constraints.MinWidth := Width; - Constraints.MinHeight := Height; - FAutoSized := true; -end; - -procedure TFreqFrm.FormCreate(Sender: TObject); -begin - Assert(OS3MainFrm <> nil); - - if FreqSpecsFrm = nil then - Application.CreateForm(TFreqSpecsFrm, FreqSpecsFrm); - - if GraphFrm = nil then - Application.CreateForm(TGraphFrm, GraphFrm); -end; - -procedure TFreqFrm.FormShow(Sender: TObject); -begin - ResetBtnClick(self); -end; - procedure TFreqFrm.AllBtnClick(Sender: TObject); var count, index : integer; @@ -118,69 +87,75 @@ begin for index := 0 to count-1 do SelList.Items.Add(VarList.Items[index]); VarList.Clear; + ClearTabs; UpdateBtnStates; end; -procedure TFreqFrm.InBtnClick(Sender: TObject); + +procedure TFreqFrm.ClearTabs; var - i: integer; + i: Integer; begin - i := 0; - while i < VarList.Items.Count do - begin - if (VarList.Selected[i]) then - begin - SelList.Items.Add(VarList.Items[i]); - VarList.Items.Delete(i); - i := 0; - end else - i := i + 1; - end; - UpdateBtnStates; + FReportFrame.Clear; + for i := PageControl.PageCount-1 downto 1 do + PageControl.Pages[i].Free; end; -procedure TFreqFrm.SelListSelectionChange(Sender: TObject; User: boolean); + +procedure TFreqFrm.CloseBtnClick(Sender: TObject); begin - UpdateBtnStates; + Close; end; + procedure TFreqFrm.ComputeBtnClick(Sender: TObject); var - i, j, k : integer; - freq : DblDyneVec; - pcnt : DblDyneVec; - cumpcnt : DblDyneVec; - pcntilerank : DblDyneVec; - cumfreq : DblDyneVec; - XValue : DblDyneVec; - value : double; - NoVars : integer; - plottype : integer; - cellval : string; - col : integer; - min, max : double; - range : double; - incrsize : double; - nointervals : double; - nints : integer; -// ColNoSelected : IntDyneVec; - NormDist : boolean; - Histogram : boolean; - Sumx, Sumx2, Mean, Variance, StdDev, zlow, zhi : double; - X, zproplow, zprophi, zfreq : double; - Ncases : integer; - lReport: TStrings; - + i, j, k: integer; + freq: DblDyneVec = nil; + pcnt: DblDyneVec = nil; + cumpcnt: DblDyneVec = nil; + pcntilerank: DblDyneVec = nil; + cumfreq: DblDyneVec = nil; + XLabels: StrDyneVec = nil; + XValue: DblDyneVec = nil; + value: double; + NoVars: integer; + plottype: integer; + cellval: string; + col: integer; + min, max, range: double; + incrsize: double; + nointervals: double; + nInts: integer; + NormDist: boolean; + Sumx, Sumx2, Mean, Variance, StdDev, zlow, zhi: double; + X, zproplow, zprophi, zfreq: double; + nCases: integer; + oldPageIndex: Integer; + found: Boolean; + lReport: TStrings; begin - if BarTypeGroup.ItemIndex = 1 then Histogram := true else Histogram := false; - if NormPltChk.Checked = true then NormDist := true else NormDist := false; + if SelList.Count = 0 then + begin + ErrorMsg('No variable(s) selected.'); + exit; + end; - SetLength(freq,NoCases); - SetLength(pcnt,NoCases); - SetLength(cumpcnt,NoCases); - SetLength(pcntilerank,NoCases); - SetLength(cumfreq,NoCases); - SetLength(XValue,NoCases); + NormDist := NormPltChk.Checked; + + SetLength(freq, NoCases); + SetLength(pcnt, NoCases); + SetLength(cumpcnt, NoCases); + SetLength(pcntilerank, NoCases); + SetLength(cumfreq, NoCases); + SetLength(XValue, NoCases); + + (* ---------------> causes flicker + // Remove already existing chart pages + oldPageIndex := PageControl.PageIndex; + for i := PageControl.PageCount-1 downto 1 do + PageControl.Pages[i].Free; + *) lReport := TStringList.Create; try @@ -193,27 +168,29 @@ begin begin { get column no. of variable } col := 1; - cellval := SelList.Items.Strings[i-1]; + cellval := SelList.Items[i-1]; for j := 1 to NoVariables do begin if OS3MainFrm.DataGrid.Cells[j,0] = cellval then begin col := j; - lReport.Add('Frequency Analysis for Variable "%s"', [cellval]); + if i > 1 then lReport.Add(''); + lReport.Add('Frequency analysis for variable "%s"', [cellval]); break; end; end; { get min and max values for variable in col } - min := 1.0e32; - max := -1.0e32; + min := Infinity; + max := -Infinity; for j := 1 to NoCases do begin - if not ValidValue(j,col) then continue; + if not ValidValue(j, col) then continue; value := StrToFloat(OS3MainFrm.DataGrid.Cells[col,j]); if value > max then max := value; if value < min then min := value; end; + (* range := max - min + 1.0; incrsize := 1.0; { if too many increments, set increment size for 15 increments } @@ -236,52 +213,59 @@ begin nints := StrToInt(FreqSpecsFrm.NoInts.Text); if nints > 200 then nints := 200; + *) - {Now, get frequency of cases in each interval } - for j := 1 to nints+1 do - freq[j-1] := 0; - Ncases := 0; + nInts := NoIntervalsEdit.Value; + incrSize := (max - min) / nInts; + + SetLength(freq, nInts); + SetLength(XValue, nInts); + SetLength(XLabels, nInts); + + { Get frequency of cases in each interval } + nCases := 0; for j := 1 to NoCases do begin - if not ValidValue(j,col) then continue; - inc(Ncases); - value := StrToFloat(OS3MainFrm.DataGrid.Cells[col,j]); - for k := 1 to nints do - begin - if (value >= min + ((k-1) * incrsize)) and - (value < min + (k * incrsize)) then freq[k-1] := freq[k-1] + 1; - end; + if not ValidValue(j, col) then continue; + inc(nCases); + value := StrToFloat(OS3MainFrm.DataGrid.Cells[col, j]); + for k := 0 to nints-1 do + if (value >= min + k * incrSize) and (value < min + ((k+1) * incrSize)) then + freq[k] := freq[k] + 1.0; end; - for j := 1 to nints+1 do - XValue[j-1] := min + (j-1) * incrsize; - - { get cumulative frequencies and percents to midpoints } - cumfreq[0] := freq[0]; - pcnt[0] := freq[0] / Ncases; - cumpcnt[0] := cumfreq[0] / Ncases; - pcntilerank[0] := (freq[0] / 2.0) / Ncases; - for k := 2 to nints do + for j := 0 to nInts-1 do begin - cumfreq[k-1] := cumfreq[k-2] + freq[k-1]; - pcnt[k-1] := freq[k-1] / Ncases; - cumpcnt[k-1] := cumfreq[k-1] / Ncases; - pcntilerank[k-1] := (cumfreq[k-2] + freq[k-1] / 2.0) / Ncases; + XValue[j] := min + j * incrSize; + XLabels[j] := Format('%.2f'+LineEnding+'to'+LineEnding+'%.2f', [XValue[j], XValue[j] + incrSize]); end; - { Now, print results to report } + { Get cumulative frequencies and percents to midpoints } + cumFreq[0] := freq[0]; + pcnt[0] := freq[0] / nCases; + cumPcnt[0] := cumFreq[0] / nCases; + pcntileRank[0] := (freq[0] * 0.5) / nCases; + for k := 1 to nInts - 1do + begin + cumfreq[k] := cumfreq[k-1] + freq[k]; + pcnt[k] := freq[k] / nCases; + cumPcnt[k] := cumFreq[k] / nCases; + pcntileRank[k] := (cumFreq[k-1] + freq[k] * 0.5) / nCases; + end; + + { Print results to report } lReport.Add(' FROM TO FREQ. PCNT CUM.FREQ. CUM.PCNT. %ILE RANK'); lReport.Add(''); - for k := 1 to nints do + for k := 0 to nInts - 1 do lReport.Add('%8.2f%8.2f%8.0f%8.2f %8.2f %8.2f %8.2f', [ - min+(k-1)*incrsize, // from - min+k*incrsize, // to - freq[k-1], // freq - pcnt[k-1], // pcnt - cumfreq[k-1], // cum.freq. - cumpcnt[k-1], // cum.pcnt. - pcntilerank[k-1] // %ile rank + min + k*incrSize, // from + min + (k+1)*incrSize, // to + freq[k], // freq + pcnt[k], // pcnt + cumFreq[k], // cum.freq. + cumPcnt[k], // cum.pcnt. + pcntileRank[k] // %ile rank ]); - + (* { Now, prepare plot values as indicated in options list } if NormDist = false then SetLength(GraphFrm.Ypoints,1,nints+1) @@ -292,7 +276,7 @@ begin begin GraphFrm.Ypoints[0,k-1] := freq[k-1]; GraphFrm.Xpoints[0,k-1] := XValue[k-1]; - end; + end; *) // Create ND plot if checked. // BUT: Only 3D-vertical plots when normal curve is desired @@ -332,15 +316,20 @@ begin zproplow := probz(zlow); zprophi := probz(zhi); zfreq := NoCases * abs(zprophi - zproplow); + (* !!!!!!!!!!!!!!!!!!! GraphFrm.Ypoints[1,k-1] := zfreq; lReport.Add(' %2d %6.2f', [k, GraphFrm.Ypoints[1,k-1]]); + *) end; end; // Show report in form - DisplayReport(lReport); + FReportFrame.DisplayReport(lReport); // Plot data + PlotFreq(col, cellVal, xLabels, freq); + end; + (* plottype := PlotOptionsGroup.ItemIndex + 1; if Histogram then GraphFrm.barwideprop := 1.0 @@ -370,18 +359,143 @@ begin GraphFrm.Xpoints := nil; GraphFrm.Ypoints := nil; end; // for novars list - + *) + { + for j := PageControl.PageCount-1 downto 1 do + begin + found := false; + for i := 0 to SelList.Count-1 do + if GetPageCaption(SelList.Items[i]) = PageControl.Pages[j].Caption then + begin + found := true; + break; + end; + if not found then + PageControl.Pages[j].Free; + end; + } finally lReport.Free; + (* XValue := nil; cumfreq := nil; pcntilerank := nil; cumpcnt := nil; pcnt := nil; freq := nil; + *) end; end; + +function TFreqFrm.CreateChartFrame(AColIndex: Integer; AVarName: String): TChartFrame; +var + sheetTitle: String; + tabSheet: TTabSheet; + i: Integer; +begin + sheetTitle := GetPageCaption(AVarName); + + // Find existing sheet first. + for i := 1 to PageControl.PageCount-1 do + if PageControl.Pages[i].Caption = sheetTitle then begin + tabSheet := PageControl.Pages[i]; + Result := tabSheet.Controls[0] as TChartFrame; + exit; + end; + + // Not found: create new sheet ... + tabSheet := PageControl.AddTabSheet; + tabSheet.Caption := sheetTitle; + tabSheet.Tag := AColIndex; + + // ... and add ChartFrame + Result := TChartFrame.Create(tabSheet); + Result.Parent := tabSheet; + Result.Align := alClient; + Result.Chart.Legend.Alignment := laBottomCenter; + Result.Chart.Legend.ColumnCount := 3; + Result.Chart.Legend.TextFormat := tfHTML; + Result.Chart.BottomAxis.Intervals.MaxLength := 80; + Result.Chart.BottomAxis.Intervals.MinLength := 30; +end; + + +procedure TFreqFrm.FormActivate(Sender: TObject); +var + w: Integer; +begin + if FAutoSized then + exit; + + w := MaxValue([ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]); + ResetBtn.Constraints.MinWidth := w; + ComputeBtn.Constraints.MinWidth := w; + CloseBtn.Constraints.MinWidth := w; + + (* + Panel1.Constraints.MinHeight := BarTypeGroup.Top + BarTypeGroup.Height - Panel1.Top; + Panel1.Constraints.MinWidth := Label2.Width * 2 + AllBtn.Width + 2 * VarList.BorderSpacing.Right; + Constraints.MinWidth := Width; + Constraints.MinHeight := Height; + *) + + Position := poMainFormCenter; + FAutoSized := true; +end; + + +procedure TFreqFrm.FormCreate(Sender: TObject); +begin + Assert(OS3MainFrm <> nil); + + if FreqSpecsFrm = nil then + Application.CreateForm(TFreqSpecsFrm, FreqSpecsFrm); + + if GraphFrm = nil then + Application.CreateForm(TGraphFrm, GraphFrm); + + InitForm(Self); + + FReportFrame := TReportFrame.Create(self); + FReportFrame.Parent := ReportPage; + FReportFrame.Align := alClient; + + Reset; +end; + + +function TFreqFrm.GetPageCaption(AVarName: String): String; +begin + Result := 'Plot of ' + AVarName; +end; + + +procedure TFreqFrm.InBtnClick(Sender: TObject); +var + i: integer; +begin + i := 0; + while i < VarList.Items.Count do + begin + if (VarList.Selected[i]) then + begin + SelList.Items.Add(VarList.Items[i]); + VarList.Items.Delete(i); + i := 0; + end else + i := i + 1; + end; + ClearTabs; + UpdateBtnStates; +end; + + +procedure TFreqFrm.SelListSelectionChange(Sender: TObject; User: boolean); +begin + UpdateBtnStates; +end; + procedure TFreqFrm.OutBtnClick(Sender: TObject); var i: integer; @@ -395,20 +509,75 @@ begin SelList.Items.Delete(i); i := 0; end else - i := i + 1; + inc(i); end; + ClearTabs; UpdateBtnStates; end; + +procedure TFreqFrm.PlotFreq(AColIndex: Integer; AVarName: String; + const xLabels: StrDyneVec; const Freq: DblDyneVec); +var + ser: TBarSeries; + chartFrame: TChartFrame; +begin + chartFrame := CreateChartFrame(AColIndex, AVarName); + chartFrame.Clear; + + ser := chartFrame.PlotXY(ptVertBars, nil, Freq, xLabels, nil, '', clDefault) as TBarSeries; + ser.BarBrush.Color := DATA_COLORS[(AColIndex-1) mod Length(DATA_COLORS)]; + if BarTypeGroup.ItemIndex = 1 then + begin + ser.BarWidthPercent := 100; + ser.BarPen.Color := ser.BarBrush.Color; + end; + + chartFrame.Chart.Margins.Bottom := 0; + chartFrame.Chart.BottomAxis.Marks.Source := ser.Source; + chartFrame.Chart.BottomAxis.Marks.Style := smsLabel; + chartFrame.Chart.BottomAxis.Marks.Alignment := taCenter; + chartFrame.SetTitle('Frequency distribution'); + chartFrame.SetXTitle(AVarName + ' categories'); + chartFrame.SetYTitle('Frequency'); + chartFrame.Chart.Legend.Visible := false; +end; + + procedure TFreqFrm.PlotOptionsGroupSelectionChanged(Sender: TObject); begin - BarTypeGroup.Enabled := PlotOptionsGroup.ItemIndex in [0, 1, 8, 9]; // Bar series only + BarTypeGroup.Enabled := PlotOptionsGroup.ItemIndex in [0, 1, 8, 9]; // Bar series only end; + +procedure TFreqFrm.Reset; +var + i: integer; +begin + VarList.Clear; + SelList.Clear; + for i := 1 to NoVariables do + VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]); + BarTypeGroup.ItemIndex := 0; + PlotOptionsGroup.ItemIndex := 0; + NormPltChk.Checked := false; + + ClearTabs; + UpdateBtnStates; +end; + + +procedure TFreqFrm.ResetBtnClick(Sender: TObject); +begin + Reset; +end; + + procedure TFreqFrm.UpdateBtnStates; var lSelected: Boolean; i: Integer; + chartFrame: TChartFrame; begin lSelected := false; for i := 0 to VarList.Items.Count-1 do @@ -429,15 +598,39 @@ begin OutBtn.Enabled := lSelected; AllBtn.Enabled := VarList.Items.Count > 0; + + BarTypeGroup.Enabled := PlotOptionsGroup.ItemIndex in [0, 1, 8, 9]; // Bar series only + + FReportFrame.UpdateBtnStates; + for i := 1 to PageControl.PageCount-1 do + begin + chartFrame := PageControl.Pages[i].Controls[0] as TChartFrame; + chartFrame.UpdateBtnStates; + end; end; + +procedure TFreqFrm.VarListDblClick(Sender: TObject); +var + index: integer; +begin + index := VarList.ItemIndex; + if index > -1 then + begin + SelList.Items.Add(VarList.Items[index]); + VarList.Items.Delete(index); + ClearTabs; + UpdateBtnStates; + end; +end; + + + procedure TFreqFrm.VarListSelectionChange(Sender: TObject; User: boolean); begin UpdateBtnStates; end; -initialization - {$I frequnit.lrs} end. diff --git a/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas b/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas index 1fa564a6e..206c97284 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/plotxyunit.pas @@ -377,8 +377,7 @@ procedure TPlotXYFrm.FormCreate(Sender: TObject); begin Assert(OS3MainFrm <> nil); - Width := Scale96ToFont(DEFAULT_WIDTH); - Height := Scale96ToFont(DEFAULT_HEIGHT); + InitForm(self); FReportFrame := TReportFrame.Create(self); FReportFrame.Parent := ReportPage; diff --git a/applications/lazstats/source/forms/analysis/descriptive/xvsmultyunit.pas b/applications/lazstats/source/forms/analysis/descriptive/xvsmultyunit.pas index 90e36aa8c..e4d086665 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/xvsmultyunit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/xvsmultyunit.pas @@ -263,8 +263,7 @@ procedure TXvsMultYForm.FormCreate(Sender: TObject); begin Assert(OS3MainFrm <> nil); - Width := Scale96ToFont(DEFAULT_WIDTH); - Height := Scale96ToFont(DEFAULT_HEIGHT); + InitForm(self); FReportFrame := TReportFrame.Create(self); FReportFrame.Parent := ReportPage; diff --git a/applications/lazstats/source/forms/analysis/statistical_process_control/basicspcunit.pas b/applications/lazstats/source/forms/analysis/statistical_process_control/basicspcunit.pas index 6a1311991..63cb8ccc0 100644 --- a/applications/lazstats/source/forms/analysis/statistical_process_control/basicspcunit.pas +++ b/applications/lazstats/source/forms/analysis/statistical_process_control/basicspcunit.pas @@ -171,8 +171,7 @@ procedure TBasicSPCForm.FormCreate(Sender: TObject); begin Assert(OS3MainFrm <> nil); - Width := Scale96ToFont(DEFAULT_WIDTH); - Height := Scale96ToFont(DEFAULT_HEIGHT); + InitForm(Self); FReportFrame := TReportFrame.Create(self); FReportFrame.Parent := ReportPage; diff --git a/applications/lazstats/source/forms/simulations/distribunit.pas b/applications/lazstats/source/forms/simulations/distribunit.pas index 56d08b1a4..58219f459 100644 --- a/applications/lazstats/source/forms/simulations/distribunit.pas +++ b/applications/lazstats/source/forms/simulations/distribunit.pas @@ -452,6 +452,8 @@ end; procedure TDistribFrm.FormCreate(Sender: TObject); begin + InitForm(self); + FChartFrame := TChartFrame.Create(self); FChartFrame.Parent := ChartPanel; FChartFrame.Align := alClient; @@ -460,9 +462,8 @@ begin FChartFrame.Chart.Legend.TextFormat := tfHTML; FChartFrame.Chart.BottomAxis.Intervals.MaxLength := 80; FChartFrame.Chart.BottomAxis.Intervals.MinLength := 30; - FChartFrame.ChartToolbar.Transparent := false; - FChartFrame.ChartToolbar.Color := clForm; + InitToolbar(FChartFrame.ChartToolbar, tpTop); tbErase := TToolButton.Create(self); tbErase.ImageIndex := 6; tbErase.Caption := 'Erase'; diff --git a/applications/lazstats/source/units/utils.pas b/applications/lazstats/source/units/utils.pas index f48d60e14..05fc756cb 100644 --- a/applications/lazstats/source/units/utils.pas +++ b/applications/lazstats/source/units/utils.pas @@ -5,12 +5,14 @@ unit Utils; interface uses - Classes, SysUtils, Graphics, Controls, StdCtrls, ComCtrls, Dialogs, + Classes, SysUtils, Graphics, Controls, StdCtrls, ComCtrls, Dialogs, Forms, Globals; type TToolbarPosition = (tpTop, tpLeft, tpRight); +procedure InitForm(AForm: TForm); + procedure AddButtonToToolbar(AToolButton: TToolButton; AToolBar: TToolBar); procedure InitToolbar(AToolbar: TToolbar; APosition: TToolbarPosition); @@ -48,6 +50,13 @@ begin end; +procedure InitForm(AForm: TForm); +begin + AForm.Width := AForm.Scale96ToFont(DEFAULT_WIDTH); + AForm.Height := AForm.Scale96ToFont(DEFAULT_HEIGHT); +end; + + procedure InitToolbar(AToolbar: TToolbar; APosition: TToolbarPosition); begin // AToolbar.Transparent := false;