LazStats: Improved calculation of V-Mask in CUSUMUnit; slide V-Mask over data set.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7660 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-09-09 18:04:01 +00:00
parent 31f3d9ba6b
commit 9c7509c4de
3 changed files with 137 additions and 61 deletions

View File

@ -3,6 +3,7 @@ inherited CUSUMChartForm: TCUSUMChartForm
HelpKeyword = 'html/CUMSUMChart.htm' HelpKeyword = 'html/CUMSUMChart.htm'
Caption = 'Cumulative Sum Control Chart' Caption = 'Cumulative Sum Control Chart'
OnActivate = FormActivate OnActivate = FormActivate
ShowHint = True
inherited SpecsPanel: TPanel inherited SpecsPanel: TPanel
Width = 432 Width = 432
ClientWidth = 432 ClientWidth = 432
@ -55,20 +56,21 @@ inherited CUSUMChartForm: TCUSUMChartForm
end end
object GroupBox1: TGroupBox[8] object GroupBox1: TGroupBox[8]
AnchorSideLeft.Control = MeasEdit AnchorSideLeft.Control = MeasEdit
AnchorSideTop.Control = MeasEdit AnchorSideTop.Control = GroupBox2
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = MeasEdit AnchorSideRight.Control = MeasEdit
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 228 Left = 228
Height = 107 Height = 153
Top = 120 Top = 202
Width = 204 Width = 204
Anchors = [akTop, akLeft, akRight] Anchors = [akTop, akLeft, akRight]
BorderSpacing.Top = 24 AutoSize = True
Caption = 'CUMSUM V-Mask Specifications' BorderSpacing.Top = 16
ClientHeight = 87 Caption = 'V-Mask Specifications'
ClientHeight = 133
ClientWidth = 200 ClientWidth = 200
TabOrder = 3 TabOrder = 4
object Label4: TLabel object Label4: TLabel
AnchorSideLeft.Control = GroupBox1 AnchorSideLeft.Control = GroupBox1
AnchorSideTop.Control = DeltaEdit AnchorSideTop.Control = DeltaEdit
@ -112,6 +114,7 @@ inherited CUSUMChartForm: TCUSUMChartForm
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 114 Left = 114
Height = 23 Height = 23
Hint = 'Detection level for a shift in the process mean, '#13#10'expressed in data units (default), or'#13#10'as a multiple of the standard deviation of the '#13#10'data points (when "Normalized CUSUM" is checked).'
Top = 2 Top = 2
Width = 78 Width = 78
Alignment = taRightJustify Alignment = taRightJustify
@ -131,6 +134,7 @@ inherited CUSUMChartForm: TCUSUMChartForm
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 114 Left = 114
Height = 23 Height = 23
Hint = 'Probability of concluding that a shift in the process has occurred, when in fact it did not. '
Top = 29 Top = 29
Width = 78 Width = 78
Alignment = taRightJustify Alignment = taRightJustify
@ -150,6 +154,7 @@ inherited CUSUMChartForm: TCUSUMChartForm
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 114 Left = 114
Height = 23 Height = 23
Hint = 'Probability of not detecting that a shift in the process mean has, in fact, occurred'
Top = 56 Top = 56
Width = 78 Width = 78
Alignment = taRightJustify Alignment = taRightJustify
@ -161,25 +166,52 @@ inherited CUSUMChartForm: TCUSUMChartForm
TabOrder = 2 TabOrder = 2
Text = 'BetaEdit' Text = 'BetaEdit'
end end
object VMaskScrollbar: TScrollBar
AnchorSideLeft.Control = Label1
AnchorSideTop.Control = Label1
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = BetaEdit
AnchorSideRight.Side = asrBottom
Left = 12
Height = 17
Top = 104
Width = 180
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Top = 2
BorderSpacing.Bottom = 12
PageSize = 0
TabOrder = 3
end
object Label1: TLabel
AnchorSideLeft.Control = Label4
AnchorSideTop.Control = BetaEdit
AnchorSideTop.Side = asrBottom
Left = 12
Height = 15
Top = 87
Width = 100
Caption = 'Position of V-Mask'
ParentColor = False
end
end end
object GroupBox2: TGroupBox[9] object GroupBox2: TGroupBox[9]
AnchorSideLeft.Control = GroupBox1 AnchorSideLeft.Control = GroupBox1
AnchorSideTop.Control = GroupBox1 AnchorSideTop.Control = MeasEdit
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = MeasEdit AnchorSideRight.Control = MeasEdit
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 228 Left = 228
Height = 51 Height = 74
Top = 243 Top = 112
Width = 204 Width = 204
Anchors = [akTop, akLeft, akRight] Anchors = [akTop, akLeft, akRight]
AutoSize = True AutoSize = True
BorderSpacing.Top = 16 BorderSpacing.Top = 16
BorderSpacing.Bottom = 8 BorderSpacing.Bottom = 8
Caption = 'Option:' Caption = 'Option:'
ClientHeight = 31 ClientHeight = 54
ClientWidth = 200 ClientWidth = 200
TabOrder = 4 TabOrder = 3
object TargetChk: TCheckBox object TargetChk: TCheckBox
AnchorSideLeft.Control = GroupBox2 AnchorSideLeft.Control = GroupBox2
AnchorSideTop.Control = TargetEdit AnchorSideTop.Control = TargetEdit
@ -207,11 +239,24 @@ inherited CUSUMChartForm: TCUSUMChartForm
Anchors = [akTop, akLeft, akRight] Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 8 BorderSpacing.Left = 8
BorderSpacing.Right = 8 BorderSpacing.Right = 8
BorderSpacing.Bottom = 8 BorderSpacing.Bottom = 4
Constraints.MinWidth = 64 Constraints.MinWidth = 64
TabOrder = 1 TabOrder = 1
Text = 'TargetEdit' Text = 'TargetEdit'
end end
object ShowMeanDevChk: TCheckBox
AnchorSideLeft.Control = TargetChk
AnchorSideTop.Control = TargetEdit
AnchorSideTop.Side = asrBottom
Left = 12
Height = 19
Top = 27
Width = 169
BorderSpacing.Top = 4
BorderSpacing.Bottom = 8
Caption = 'Show mean group deviation'
TabOrder = 2
end
end end
end end
inherited SpecsSplitter: TSplitter inherited SpecsSplitter: TSplitter

View File

@ -15,6 +15,9 @@ type
TCUSUMChartForm = class(TBasicSPCForm) TCUSUMChartForm = class(TBasicSPCForm)
AlphaEdit: TEdit; AlphaEdit: TEdit;
BetaEdit: TEdit; BetaEdit: TEdit;
Label1: TLabel;
VMaskScrollbar: TScrollBar;
ShowMeanDevChk: TCheckBox;
DeltaEdit: TEdit; DeltaEdit: TEdit;
GroupBox1: TGroupBox; GroupBox1: TGroupBox;
GroupBox2: TGroupBox; GroupBox2: TGroupBox;
@ -26,6 +29,7 @@ type
procedure FormActivate(Sender: TObject); procedure FormActivate(Sender: TObject);
private private
SEMean: Double; SEMean: Double;
k, h: Double;
protected protected
procedure Compute; override; procedure Compute; override;
procedure PlotMeans(ATitle, AXTitle, AYTitle, ADataTitle, AGrandMeanTitle: String; procedure PlotMeans(ATitle, AXTitle, AYTitle, ADataTitle, AGrandMeanTitle: String;
@ -52,7 +56,8 @@ uses
procedure TCUSUMChartForm.Compute; procedure TCUSUMChartForm.Compute;
var var
i, j, grpIndex, numGrps, grpSize, oldGrpSize, numValues: Integer; i, j, grpIndex, numGrps, grpSize, oldGrpSize, numValues: Integer;
X, Xsq, Xmin, Xmax, target, grandMean, grandSum, grandSD, UCL, LCL: Double; X, Xsq, Xmin, Xmax, target, diff, grandMean, grandSum, grandSD: Double;
deltaSD, alpha, beta: double;
sizeError: Boolean; sizeError: Boolean;
grp: String; grp: String;
groups: StrDyneVec = nil; groups: StrDyneVec = nil;
@ -140,8 +145,9 @@ begin
grandSum := grandSum + (means[0] - target); grandSum := grandSum + (means[0] - target);
for j := 1 to numGrps-1 do for j := 1 to numGrps-1 do
begin begin
cusums[j] := cusums[j-1] + (means[j] - target); diff := means[j] - target;
grandSum := grandSum + (means[j] - target); cusums[j] := cusums[j-1] + diff;
grandSum := grandSum + diff;
end; end;
SEMean := SEMean - sqr(grandMean)/numValues; SEMean := SEMean - sqr(grandMean)/numValues;
@ -150,9 +156,18 @@ begin
SEMean := SEMean/sqrt(numValues); SEMean := SEMean/sqrt(numValues);
grandMean := grandMean/numValues; // mean of all observations grandMean := grandMean/numValues; // mean of all observations
grandSum := grandSum/numGrps; // mean of the group means grandSum := grandSum/numGrps; // mean of the group means
UCL := grandMean + 3.0*SEMean;
LCL := grandMean - 3.0*SEMean; if DeltaEdit.Text <> '' then
if (LCL < 0.0) then LCL := 0.0; begin
deltaSD := StrToFloat(DeltaEdit.Text) / SEMean;
// This is in multiples of std deviations
// see : https://www.itl.nist.gov/div898/handbook/pmc/section3/pmc323.htm
alpha := StrToFloat(AlphaEdit.Text);
beta := StrToFloat(BetaEdit.Text);
k := deltaSD * SEMean / 2.0;
h := SEMean / deltaSD * ln((1 - beta) / alpha);
end;
// Print results // Print results
lReport := TStringList.Create; lReport := TStringList.Create;
@ -160,19 +175,35 @@ begin
lReport.Clear; lReport.Clear;
lReport.Add('CUSUM Chart Results'); lReport.Add('CUSUM Chart Results');
lReport.Add(''); lReport.Add('');
lReport.Add(' Group Size Mean Std.Dev. Cum.Dev. of' );
lReport.Add(' Mean from Target');
lReport.Add('------- ---- -------- -------- ----------------');
for i := 0 to numGrps - 1 do
lReport.Add('%7d %4d %8.2f %8.2f %10.2f', [i+1, count[i], means[i], stddev[i], cusums[i]]);
lReport.Add('');
lReport.Add('Mean of group deviations: %8.3f', [grandSum]); lReport.Add('Mean of group deviations: %8.3f', [grandSum]);
lReport.Add('Mean of all observations: %8.3f', [grandMean]); lReport.Add('Mean of all observations: %8.3f', [grandMean]);
lReport.Add('Std. Dev. of Observations: %8.3f', [grandSD]); lReport.Add('Std. Dev. of Observations: %8.3f', [grandSD]);
lReport.Add('Standard Error of Mean: %8.3f', [SEMean]); lReport.Add('Standard Error of Mean: %8.3f', [SEMean]);
lReport.Add('Target Specification: %8.3f', [target]); lReport.Add('Target Specification: %8.3f', [target]);
lReport.Add('Lower Control Limit: %8.3f', [LCL]);
lReport.Add('Upper Control Limit: %8.3f', [UCL]); lReport.Add('');
lReport.Add('Differences in data units');
lReport.Add('');
lReport.Add('Group Size Mean Std.Dev. Mean-Dev Cum.Dev. of' );
lReport.Add(' Mean from Target');
lReport.Add('----- ---- -------- -------- -------- ----------------');
for i := 0 to numGrps - 1 do
begin
lReport.Add('%5s %4d %8.3f %8.3f %8.3f %10.3f', [
groups[i], count[i], means[i], stddev[i], means[i]-target, cusums[i]
]);
end;
if DeltaEdit.Text <> '' then
begin
lReport.Add('');
lReport.Add('V-Mask parameters:');
lReport.Add(' Alpha (Type I error) %8.3f', [alpha]);
lReport.Add(' Beta (Type II error) %8.3f', [beta]);
lReport.Add(' k: %8.3f (%.2f sigma)', [k, k/SEMean]);
lReport.Add(' h: %8.3f (%.2f sigma)', [h, h/SEMean]);
end;
ReportMemo.Lines.Assign(lReport); ReportMemo.Lines.Assign(lReport);
finally finally
@ -180,6 +211,9 @@ begin
end; end;
// Show graph // Show graph
VMaskScrollbar.Max := numGrps;
if not ShowMeanDevChk.Checked then
grandSum := NaN;
PlotMeans( PlotMeans(
Format('Cumulative Sum Chart for "%s"', [GetFileName]), // chart title Format('Cumulative Sum Chart for "%s"', [GetFileName]), // chart title
GroupEdit.Text, // x title GroupEdit.Text, // x title
@ -218,61 +252,58 @@ begin
end; end;
end; end;
{ Overridden to draw the V-Mark } { Overridden to draw the V-Mark }
procedure TCUSUMChartForm.PlotMeans(ATitle, AXTitle, AYTitle, ADataTitle, AGrandMeanTitle: String; procedure TCUSUMChartForm.PlotMeans(ATitle, AXTitle, AYTitle, ADataTitle, AGrandMeanTitle: String;
const Groups: StrDyneVec; const Means: DblDyneVec; const Groups: StrDyneVec; const Means: DblDyneVec;
UCL, LCL, GrandMean, TargetSpec, LowerSpec, UpperSpec: double); UCL, LCL, GrandMean, TargetSpec, LowerSpec, UpperSpec: double);
var var
alpha, beta, delta, deltaSD, gamma, d, h, k: Double;
ser: TLineSeries; ser: TLineSeries;
ext: TDoubleRect; xVM, yVM, x1, y1, x2, y2, x3, y3, x4, y4: Double;
x0, y0, x1, y1, x2, y2, x3, y3: Double;
begin begin
inherited; inherited;
if DeltaEdit.Text = '' then if DeltaEdit.Text = '' then
exit; exit;
alpha := StrToFloat(AlphaEdit.Text);
beta := StrToFloat(BetaEdit.Text);
delta := StrToFloat(DeltaEdit.Text); // This is in data units
deltaSD := delta / SEMean; // This is in multiples of std deviations
// see : https://www.itl.nist.gov/div898/handbook/pmc/section3/pmc323.htm
d := 2.0 / sqr(deltaSD) * ln((1.0 - beta)/alpha);
k := deltaSD * SEMean / 2.0;
h := d * k;
ser := TLineSeries.Create(FChartFrame.Chart); ser := TLineSeries.Create(FChartFrame.Chart);
FChartFrame.Chart.AddSeries(ser); FChartFrame.Chart.AddSeries(ser);
ser.SeriesColor := clBlue; ser.SeriesColor := clBlue;
ser.Title := 'V-Mask'; ser.Title := 'V-Mask';
ext := FChartFrame.Chart.GetFullExtent; // Position of V mask point
x1 := Length(Means); // 1-based! xVM := VMaskScrollbar.Position;
y1 := Means[High(Means)] + h; yVM := Means[VMaskScrollbar.Position-1];
x0 := 1;
y0 := y1 - k*(x0 - x1);
x2 := x1; // Upper part of V mask
y2 := Means[High(Means)] - h; x2 := xVM;
x3 := x0; y2 := yVM + h;
y3 := y2 + k*(x3 - x2); x1 := 1; // x values begin with 1
y1 := y2 - k*(x1 - x2);
// Lower part of V mask
x3 := xVM;
y3 := yVM - h;
x4 := 1;
y4 := y3 + k*(x4 - x3);
ser.AddXY(x0, y0);
ser.AddXY(x1, y1); ser.AddXY(x1, y1);
ser.AddXY(x2, y2); ser.AddXY(x2, y2);
ser.AddXY(x2, NaN); // Do not draw the vertical line
ser.AddXY(x3, y3); ser.AddXY(x3, y3);
ser.AddXY(x4, y4);
end; end;
procedure TCUSUMChartForm.Reset; procedure TCUSUMChartForm.Reset;
begin begin
inherited; inherited;
DeltaEdit.Clear; ShowMeanDevChk.Checked := false;
AlphaEdit.Text := FormatFloat('0.00', DEFAULT_ALPHA_LEVEL);
BetaEdit.Text := FormatFloat('0.00', DEFAULT_BETA_LEVEL);
TargetEdit.Clear; TargetEdit.Clear;
DeltaEdit.Clear;
AlphaEdit.Text := FormatFloat('0.00000', 0.0027); //DEFAULT_ALPHA_LEVEL);
BetaEdit.Text := FormatFloat('0.00000', 0.01); //DEFAULT_BETA_LEVEL);
VMaskScrollbar.Min := 2;
VMaskScrollbar.Max := 1000;
VMaskScrollbar.Position := VMaskScrollbar.Max;
end; end;

View File

@ -2123,7 +2123,7 @@ procedure TOS3MainFrm.mnuAnalysisSPC_CChartClick(Sender: TObject);
begin begin
if CChartForm = nil then if CChartForm = nil then
Application.CreateForm(TCChartForm, CChartForm); Application.CreateForm(TCChartForm, CChartForm);
CChartForm.ShowModal; CChartForm.Show;
end; end;
@ -2132,7 +2132,7 @@ procedure TOS3MainFrm.mnuAnalysisSPC_CUSUMClick(Sender: TObject);
begin begin
if CUSUMChartForm = nil then if CUSUMChartForm = nil then
Application.CreateForm(TCUSUMChartForm, CUSUMChartForm); Application.CreateForm(TCUSUMChartForm, CUSUMChartForm);
CUSUMChartForm.ShowModal; CUSUMChartForm.Show;
end; end;
@ -2141,7 +2141,7 @@ procedure TOS3MainFrm.mnuAnalysisSPC_PChartClick(Sender: TObject);
begin begin
if PChartForm = nil then if PChartForm = nil then
Application.CreateForm(TPChartForm, PChartForm); Application.CreateForm(TPChartForm, PChartForm);
PChartForm.ShowModal; PChartForm.Show;
end; end;
@ -2150,7 +2150,7 @@ procedure TOS3MainFrm.mnuAnalysisSPC_RangeClick(Sender: TObject);
begin begin
if RChartForm = nil then if RChartForm = nil then
Application.CreateForm(TRChartForm, RChartForm); Application.CreateForm(TRChartForm, RChartForm);
RChartForm.ShowModal; RChartForm.Show;
end; end;
@ -2159,7 +2159,7 @@ procedure TOS3MainFrm.mnuAnalysisSPC_SChartClick(Sender: TObject);
begin begin
if SChartForm = nil then if SChartForm = nil then
Application.CreateForm(TSChartForm, SChartForm); Application.CreateForm(TSChartForm, SChartForm);
SChartForm.ShowModal; SChartForm.Show;
end; end;
@ -2168,7 +2168,7 @@ procedure TOS3MainFrm.mnuAnalysisSPC_UChartClick(Sender: TObject);
begin begin
if UChartForm = nil then if UChartForm = nil then
Application.CreateForm(TUChartForm, UChartForm); Application.CreateForm(TUChartForm, UChartForm);
UChartForm.ShowModal; UChartForm.Show;
end; end;
@ -2177,7 +2177,7 @@ procedure TOS3MainFrm.mnuAnalysisSPC_XBarClick(Sender: TObject);
begin begin
if XBarChartForm = nil then if XBarChartForm = nil then
Application.CreateForm(TXBarChartForm, XBarChartForm); Application.CreateForm(TXBarChartForm, XBarChartForm);
XBarChartForm.ShowModal; XBarChartForm.Show;
end; end;