diff --git a/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.pas b/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.pas index 4f6add797..bbb59ca8b 100644 --- a/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.pas +++ b/applications/lazstats/source/forms/analysis/descriptive/resistancelineunit.pas @@ -11,7 +11,7 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, - StdCtrls, ExtCtrls, Buttons, Printers, ComCtrls, + StdCtrls, ExtCtrls, Buttons, Printers, ComCtrls, Grids, MainUnit, Globals, DataProcs, DictionaryUnit, MathUnit, BasicStatsReportAndChartFormUnit; @@ -57,10 +57,14 @@ type procedure PlotXY(const XPoints, YPoints: DblDyneVec; ARegressionResults: TBivariateRegressionResults); + function PrepareData(ADataGrid: TStringGrid; + out xCol, ycol: Integer; out XData, YData: DblDyneVec; + out ColNoSelected: IntDyneVec): Boolean; + procedure ResidualsToGrid(xCol, yCol: Integer; const AColNoSelected: IntDyneVec; Slope, Intercept: Double); - procedure ResistantLineAnalysis(const xyPoints: DblDyneMat; + procedure ResistantLineAnalysis(const XData, YData: DblDyneVec; out XMedians, yMedians: DblDyneVec; out GrpSize: IntDyneVec); procedure WriteMedianReport(AReport: TStrings; @@ -87,7 +91,7 @@ implementation {$R *.lfm} uses - Math, Grids, + Math, TATypes, TAChartUtils, TAChartAxisUtils, TALegend, TASources, TACustomSeries, ChartFrameUnit, Utils, GridProcs; @@ -136,14 +140,14 @@ end; procedure TResistanceLineForm.Compute; var - xyPoints: DblDyneMat = nil; // 1st index: x or y, 2nd index: data index + xValues: DblDyneVec = nil; + yValues: DblDyneVec = nil; xMedians: DblDyneVec = nil; yMedians: DblDyneVec = nil; colNoSelected : IntDyneVec = nil; grpSize: IntDyneVec = nil; xCol, yCol: Integer; regressionRes: TBivariateRegressionResults; - N: Integer; confBand: Double; slope1, slope2, slopeRL: Double; c1, c2, c3, c: Double; @@ -152,48 +156,19 @@ var begin dataGrid := OS3MainFrm.DataGrid; - xCol := GetVariableIndex(dataGrid, XEdit.Text); - yCol := GetVariableIndex(dataGrid, YEdit.Text); - if xCol = -1 then - begin - ErrorMsg('X variable not specified or not found.'); - exit; - end; - if yCol = -1 then - begin - ErrorMsg('Y variable not specified or not found.'); - exit; - end; - - SetLength(colNoSelected, 2); - colNoSelected[0] := xCol; - colNoSelected[1] := yCol; - // Get values from the grid - SetLength(xyPoints, 2); - xyPoints[0] := CollectValues(dataGrid, xCol, colNoSelected); - xyPoints[1] := CollectValues(dataGrid, ycol, colNoSelected); - N := Length(xyPoints[0]); - if N < 3 then - begin - ErrorMsg('At least three data points required.'); + if not PrepareData(dataGrid, xCol, yCol, xValues, yvalues, colNoSelected) then exit; - end; - if N <> Length(xyPoints[1]) then - begin - ErrorMsg('Equal count of cases required for x and y variables.'); - exit; - end; // Sort on the x values - SortOnX(xyPoints[0], xyPoints[1]); + SortOnX(xValues, yValues); // Calculate bivariate regression confBand := StrToFloat(ConfEdit.Text) / 100; - Calc_BivariateRegression(xyPoints[0], xyPoints[1], confBand, regressionRes); + Calc_BivariateRegression(xValues, yValues, confBand, regressionRes); // Do the resistant line analysis - ResistantLineAnalysis(xyPoints, xMedians, yMedians, grpSize); + ResistantLineAnalysis(xValues, yValues, xMedians, yMedians, grpSize); slope1 := (yMedians[1] - yMedians[0]) / (xMedians[1] - xMedians[0]); slope2 := (yMedians[2] - yMedians[1]) / (xMedians[2] - xMedians[1]); @@ -230,10 +205,10 @@ begin // Plot results in ChartFrame if PlotPointsChk.Checked then - PlotXY(xyPoints[0], xyPoints[1], regressionRes); + PlotXY(xValues, yValues, regressionRes); if PlotMediansChk.Checked then - PlotMedians(XMedians, YMedians, slopeRL, c); + PlotMedians(xMedians, yMedians, slopeRL, c); end; @@ -356,6 +331,54 @@ begin end; +function TResistanceLineForm.PrepareData(ADataGrid: TStringGrid; + out xCol, ycol: Integer; out XData, YData: DblDyneVec; + out ColNoSelected: IntDyneVec): Boolean; +var + N: Integer; +begin + Result := false; + + ColNoSelected := nil; + XData := nil; + YData := nil; + + xCol := GetVariableIndex(ADataGrid, XEdit.Text); + yCol := GetVariableIndex(ADataGrid, YEdit.Text); + if xCol = -1 then + begin + ErrorMsg('X variable not specified or not found.'); + exit; + end; + + if yCol = -1 then + begin + ErrorMsg('Y variable not specified or not found.'); + exit; + end; + + SetLength(ColNoSelected, 2); + ColNoSelected[0] := xCol; + ColNoSelected[1] := yCol; + + XData := CollectValues(ADataGrid, xCol, colNoSelected); + YData := CollectValues(ADataGrid, ycol, colNoSelected); + N := Length(XData); + if N < 3 then + begin + ErrorMsg('At least three data points required.'); + exit; + end; + if N <> Length(YData) then + begin + ErrorMsg('Equal count of cases required for x and y variables.'); + exit; + end; + + Result := true; +end; + + procedure TResistanceLineForm.Reset; var i: integer; @@ -421,14 +444,14 @@ begin end; { Do the resistant line analysis } -procedure TResistanceLineForm.ResistantLineAnalysis(const xyPoints: DblDyneMat; +procedure TResistanceLineForm.ResistantLineAnalysis(const XData, YData: DblDyneVec; out XMedians, yMedians: DblDyneVec; out GrpSize: IntDyneVec); var i, N, offs: Integer; xVector: DblDyneVec = nil; yVector: DblDyneVec = nil; begin - N := Length(xyPoints[0]); + N := Length(XData); GrpSize := nil; XMedians := nil; @@ -453,8 +476,8 @@ begin offs := 0; for i := 0 to GrpSize[1] - 1 do begin - xVector[i] := xyPoints[0, i + offs]; - yVector[i] := xyPoints[1, i + offs]; + xVector[i] := XData[i + offs]; + yVector[i] := YData[i + offs]; end; xMedians[0] := Calc_Median(xVector); yMedians[0] := Calc_Median(yVector); @@ -465,8 +488,8 @@ begin offs := GrpSize[0]; for i := 0 to GrpSize[1] - 1 do begin - xVector[i] := xyPoints[0, i + offs]; - yVector[i] := xyPoints[1, i + offs]; + xVector[i] := XData[i + offs]; + yVector[i] := YData[i + offs]; end; xMedians[1] := Calc_Median(xVector); yMedians[1] := Calc_Median(yVector); @@ -477,8 +500,8 @@ begin offs := GrpSize[0] + GrpSize[1]; for i := 0 to GrpSize[2] - 1 do begin - xVector[i] := xyPoints[0, i + offs]; - yVector[i] := xyPoints[1, i + offs]; + xVector[i] := XData[i + offs]; + yVector[i] := YData[i + offs]; end; xMedians[2] := Calc_Median(xVector); yMedians[2] := Calc_Median(yVector);