diff --git a/applications/lazstats/source/forms/simulations/corsimunit.lfm b/applications/lazstats/source/forms/simulations/corsimunit.lfm index da6f2fb3d..e0da63fb7 100644 --- a/applications/lazstats/source/forms/simulations/corsimunit.lfm +++ b/applications/lazstats/source/forms/simulations/corsimunit.lfm @@ -204,26 +204,28 @@ inherited CorSimForm: TCorSimForm AnchorSideTop.Control = NumObsEdit AnchorSideTop.Side = asrBottom Left = 0 - Height = 90 + Height = 140 Top = 148 - Width = 178 + Width = 220 AutoSize = True BorderSpacing.Top = 16 Caption = 'Plot options' - ClientHeight = 70 - ClientWidth = 174 + ClientHeight = 120 + ClientWidth = 216 TabOrder = 6 object NumBinsEdit: TSpinEdit AnchorSideLeft.Control = Label7 AnchorSideLeft.Side = asrBottom - AnchorSideTop.Control = PlotOptionsGroup + AnchorSideTop.Control = BinCountChk + AnchorSideTop.Side = asrBottom Left = 107 Height = 23 - Top = 8 + Top = 85 Width = 55 BorderSpacing.Left = 8 - BorderSpacing.Top = 8 + BorderSpacing.Top = 4 BorderSpacing.Right = 12 + BorderSpacing.Bottom = 12 MinValue = 2 OnChange = NumBinsEditChange TabOrder = 0 @@ -235,7 +237,7 @@ inherited CorSimForm: TCorSimForm AnchorSideTop.Side = asrCenter Left = 16 Height = 15 - Top = 12 + Top = 89 Width = 83 BorderSpacing.Left = 16 Caption = 'Number of bins' @@ -243,18 +245,65 @@ inherited CorSimForm: TCorSimForm end object BinCountChk: TCheckBox AnchorSideLeft.Control = Label7 - AnchorSideTop.Control = NumBinsEdit + AnchorSideTop.Control = OptionsBevel AnchorSideTop.Side = asrBottom Left = 16 Height = 19 - Top = 39 - Width = 113 + Top = 62 + Width = 188 BorderSpacing.Top = 8 - BorderSpacing.Bottom = 12 - Caption = 'Show frequencies' + BorderSpacing.Right = 12 + BorderSpacing.Bottom = 4 + Caption = 'Show frequencies in histograms' OnChange = BinCountChkChange TabOrder = 1 end + object RegressionLineChk: TCheckBox + AnchorSideLeft.Control = PlotOptionsGroup + AnchorSideTop.Control = RegressionResultsChk + AnchorSideTop.Side = asrBottom + Left = 16 + Height = 19 + Top = 27 + Width = 128 + BorderSpacing.Left = 16 + BorderSpacing.Top = 4 + Caption = 'Show regression line' + Checked = True + OnChange = RegressionLineChkChange + State = cbChecked + TabOrder = 2 + end + object OptionsBevel: TBevel + AnchorSideLeft.Control = PlotOptionsGroup + AnchorSideTop.Control = RegressionLineChk + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = PlotOptionsGroup + AnchorSideRight.Side = asrBottom + Left = 12 + Height = 8 + Top = 46 + Width = 192 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 12 + BorderSpacing.Right = 12 + Shape = bsBottomLine + end + object RegressionResultsChk: TCheckBox + AnchorSideLeft.Control = PlotOptionsGroup + AnchorSideTop.Control = PlotOptionsGroup + Left = 16 + Height = 19 + Top = 4 + Width = 143 + BorderSpacing.Left = 16 + BorderSpacing.Top = 4 + Caption = 'Show regression results' + Checked = True + OnChange = RegressionResultsChkChange + State = cbChecked + TabOrder = 3 + end end end inherited ParamsSplitter: TSplitter diff --git a/applications/lazstats/source/forms/simulations/corsimunit.pas b/applications/lazstats/source/forms/simulations/corsimunit.pas index 7c451b730..e74799b4c 100644 --- a/applications/lazstats/source/forms/simulations/corsimunit.pas +++ b/applications/lazstats/source/forms/simulations/corsimunit.pas @@ -23,6 +23,9 @@ type TCorSimForm = class(TBasicStatsReportAndChartForm) BinCountChk: TCheckBox; + RegressionResultsChk: TCheckBox; + OptionsBevel: TBevel; + RegressionLineChk: TCheckBox; Label7: TLabel; PlotOptionsGroup: TGroupBox; NumObsEdit: TEdit; @@ -40,13 +43,15 @@ type Label1: TLabel; procedure BinCountChkChange(Sender: TObject); procedure NumBinsEditChange(Sender: TObject); + procedure RegressionLineChkChange(Sender: TObject); + procedure RegressionResultsChkChange(Sender: TObject); private XHistogramChart: TChart; YHistogramChart: TChart; XHistogramSeries: TChartSeries; YHistogramSeries: TChartSeries; xValues, yValues: DblDyneVec; - simResult: TCorSimResult; + SimResult: TCorSimResult; procedure ChartAfterPaint(Sender: TChart); procedure ChartFrameResize(Sender: TObject); @@ -286,12 +291,23 @@ begin end; +procedure TCorSimForm.RegressionLineChkChange(Sender: TObject); +begin + if FChartFrame.Chart.SeriesCount > 1 then + FChartFrame.Chart.Series[1].Active := RegressionLineChk.Checked; +end; + +procedure TCorSimForm.RegressionResultsChkChange(Sender: TObject); +begin + FChartFrame.Chart.Foot.Visible := RegressionResultsChk.Checked; +end; + + procedure TCorSimForm.Plot; var freqData: DblDyneVec; x, mn, mx: Double; i, n: Integer; - xpts, ypts: DblDyneVec; begin FChartFrame.Clear; XHistogramSeries.Clear; @@ -306,6 +322,8 @@ begin 'Y Mean: %.3f, StdDev: %.3f', [ SimResult.CorrXY, SimResult.XMean, SimResult.XStdDev, SimResult.YMean, SimResult.YStdDev ])); + FChartFrame.Chart.Foot.Visible := RegressionResultsChk.Checked; + FChartFrame.Chart.Legend.Alignment := laBottomCenter; FChartFrame.Chart.Legend.ColumnCount := 2; @@ -323,12 +341,8 @@ begin end; // Draw regression line - // Regression line - SetLength(xpts, 2); - SetLength(yPts, 2); - xpts[0] := mn; ypts[0] := SimResult.a + SimResult.b * xpts[0]; - xpts[1] := mx; ypts[1] := SimResult.a + SimResult.b * xpts[1]; - FChartFrame.PlotXY(ptLines, xpts, ypts, nil, nil, 'Regression line', clBlack); + if RegressionLineChk.Checked then + FChartFrame.Line(SimResult.a, SimResult.b, mn, mx, 'Regression line', clBlack); // Draw right histogram VecMaxMin(yValues, mx, mn); @@ -345,6 +359,26 @@ end; procedure TCorSimForm.Reset; begin inherited; + + if Assigned(XHistogramSeries) then + XHistogramSeries.Clear; + if Assigned(YHistogramSeries) then + YHistogramSeries.Clear; + + xValues := nil; + yValues := nil; + + with SimResult do + begin + a := NaN; + b := NaN; + xMean := NaN; + yMean := NaN; + xStdDev := NaN; + yStdDev := NaN; + CorrXY := NaN; + end; + MeanXEdit.Text := '100'; MeanYEdit.Text := '100'; StdDevXEdit.Text := '15'; diff --git a/applications/lazstats/source/frames/chartframeunit.pas b/applications/lazstats/source/frames/chartframeunit.pas index 42b4fb0bd..bbf06d2bb 100644 --- a/applications/lazstats/source/frames/chartframeunit.pas +++ b/applications/lazstats/source/frames/chartframeunit.pas @@ -54,6 +54,8 @@ type procedure GetYRange(out YMin, YMax: Double; Logical: Boolean = true); function HorLine(y: Double; AColor: TColor; ALineStyle: TPenStyle; ALegendTitle: String): TConstantLine; + function Line(a, b, xmin, xmax: Double; LegendTitle: String; + AColor: TColor): TLineSeries; function PlotXY(AType: TPlotType; x, y: DblDyneVec; xLabels: StrDyneVec; yErrorBars: DblDyneVec; LegendTitle: string; AColor: TColor; ASymbol: TSeriesPointerStyle = psCircle): TChartSeries; @@ -157,6 +159,20 @@ begin end; +function TChartFrame.line(a, b, xmin, xmax: Double; LegendTitle: String; + AColor: TColor): TLineSeries; +var + xpts: DblDyneVec = nil; + ypts: DblDyneVec = nil; +begin + SetLength(xPts, 2); + SetLength(yPts, 2); + xpts[0] := xmin; ypts[0] := a + b * xpts[0]; + xpts[1] := xmax; ypts[1] := a + b * xpts[1]; + Result := TLineSeries(PlotXY(ptLines, xpts, ypts, nil, nil, LegendTitle, AColor)) +end; + + function TChartFrame.PlotXY(AType: TPlotType; x, y: DblDyneVec; xLabels: StrDyneVec; yErrorBars: DblDyneVec; LegendTitle: string; AColor: TColor; ASymbol: TSeriesPointerStyle = psCircle): TChartSeries;