LazStats: More refactoring of ResistanceLineUnit

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7757 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-10-10 11:28:34 +00:00
parent a91ba1bc04
commit 3cf0e45644

View File

@ -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);