You've already forked lazarus-ccr
LazStats: Fix individuals x-bar chart to agree with JMP software. Nicer labeling of horizontal lines in the SPC charts. Calculate and display Cp, Cpk and Cpm values.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7665 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -128,6 +128,8 @@ const
|
||||
TOP_MARGIN = 150;
|
||||
BOTTOM_MARGIN = 200;
|
||||
|
||||
FORMAT_MASK = '0.000';
|
||||
|
||||
|
||||
{ TBasicSPCForm }
|
||||
|
||||
@ -323,7 +325,7 @@ const
|
||||
TARGET_COLOR = clBlue;
|
||||
CL_COLOR = clRed;
|
||||
SPEC_COLOR = clGreen;
|
||||
CL_STYLE = psDot;
|
||||
CL_STYLE = psDash;
|
||||
SPEC_STYLE = psSolid;
|
||||
var
|
||||
ser: TChartSeries;
|
||||
@ -349,19 +351,19 @@ begin
|
||||
if not IsNaN(GrandMean) then
|
||||
begin
|
||||
FChartFrame.HorLine(GrandMean, clRed, psSolid, AGrandMeanTitle);
|
||||
rightLabels.Add(GrandMean, GrandMean, AGrandMeanTitle);
|
||||
rightLabels.Add(GrandMean, GrandMean, AGrandMeanTitle + '=' + FormatFloat(FORMAT_MASK, GrandMean));
|
||||
end;
|
||||
|
||||
if not IsNaN(UCL) then
|
||||
begin
|
||||
FChartFrame.HorLine(UCL, CL_COLOR, CL_STYLE, 'UCL/LCL');
|
||||
rightLabels.Add(UCL, UCL, 'UCL');
|
||||
rightLabels.Add(UCL, UCL, 'UCL=' + FormatFloat(FORMAT_MASK, UCL));
|
||||
end;
|
||||
|
||||
if not IsNaN(LCL) then
|
||||
begin
|
||||
FChartFrame.HorLine(LCL, CL_COLOR, CL_STYLE, '');
|
||||
rightLabels.Add(UCL, LCL, 'LCL');
|
||||
rightLabels.Add(UCL, LCL, 'LCL=' + FormatFloat(FORMAT_MASK, LCL));
|
||||
end;
|
||||
|
||||
if not IsNan(UpperSpec) then
|
||||
@ -371,12 +373,12 @@ begin
|
||||
else
|
||||
s := 'Upper/Lower Spec';
|
||||
FChartFrame.HorLine(UpperSpec, SPEC_COLOR, SPEC_STYLE, s);
|
||||
rightLabels.Add(UpperSpec, UpperSpec, 'Upper Spec');
|
||||
rightLabels.Add(UpperSpec, UpperSpec, 'USL=' + FormatFloat(FORMAT_MASK, UpperSpec));
|
||||
end;
|
||||
|
||||
if not IsNaN(TargetSpec) then begin
|
||||
FChartFrame.HorLine(TargetSpec, TARGET_COLOR, psSolid, 'Target');
|
||||
rightLabels.Add(TargetSpec, TargetSpec, 'Target');
|
||||
rightLabels.Add(TargetSpec, TargetSpec, 'Target=' + FormatFloat(FORMAT_MASK, TargetSpec));
|
||||
end;
|
||||
|
||||
if not IsNaN(LowerSpec) then
|
||||
@ -387,8 +389,10 @@ begin
|
||||
s := 'Upper/Lower Spec';
|
||||
constLine := FChartFrame.HorLine(LowerSpec, SPEC_COLOR, SPEC_STYLE, s);
|
||||
constLine.Legend.Visible := IsNaN(UpperSpec);
|
||||
rightLabels.Add(LowerSpec, LowerSpec, 'Lower Spec');
|
||||
rightLabels.Add(LowerSpec, LowerSpec, 'LSL=' + FormatFloat(FORMAT_MASK, LowerSpec));
|
||||
end;
|
||||
|
||||
FChartFrame.Chart.Legend.Visible := false;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
inherited XBarChartForm: TXBarChartForm
|
||||
Left = 572
|
||||
Height = 431
|
||||
Height = 476
|
||||
Top = 215
|
||||
HelpType = htKeyword
|
||||
HelpKeyword = 'html/XBarChart.htm'
|
||||
Caption = 'X-Bar Control Chart'
|
||||
ClientHeight = 431
|
||||
ClientHeight = 476
|
||||
OnActivate = FormActivate
|
||||
inherited SpecsPanel: TPanel
|
||||
Height = 431
|
||||
Height = 476
|
||||
Width = 379
|
||||
ClientHeight = 431
|
||||
ClientHeight = 476
|
||||
ClientWidth = 379
|
||||
inherited ButtonPanel: TPanel
|
||||
Top = 389
|
||||
Top = 434
|
||||
Width = 379
|
||||
ClientWidth = 379
|
||||
TabOrder = 5
|
||||
@ -34,7 +34,7 @@ inherited XBarChartForm: TXBarChartForm
|
||||
end
|
||||
end
|
||||
inherited VarList: TListBox
|
||||
Height = 356
|
||||
Height = 401
|
||||
Width = 169
|
||||
end
|
||||
inherited GroupLabel: TLabel
|
||||
@ -121,7 +121,7 @@ inherited XBarChartForm: TXBarChartForm
|
||||
AnchorSideRight.Control = MeasEdit
|
||||
AnchorSideRight.Side = asrBottom
|
||||
Left = 177
|
||||
Height = 103
|
||||
Height = 128
|
||||
Top = 293
|
||||
Width = 202
|
||||
Anchors = [akTop, akLeft, akRight]
|
||||
@ -129,7 +129,7 @@ inherited XBarChartForm: TXBarChartForm
|
||||
BorderSpacing.Top = 12
|
||||
BorderSpacing.Bottom = 8
|
||||
Caption = 'Show...'
|
||||
ClientHeight = 83
|
||||
ClientHeight = 108
|
||||
ClientWidth = 198
|
||||
TabOrder = 4
|
||||
object UpperSpecChk: TCheckBox
|
||||
@ -218,26 +218,38 @@ inherited XBarChartForm: TXBarChartForm
|
||||
TabOrder = 5
|
||||
Text = 'TargetSpecEdit'
|
||||
end
|
||||
object ZonesChk: TCheckBox
|
||||
AnchorSideLeft.Control = TargetChk
|
||||
AnchorSideTop.Control = TargetSpecEdit
|
||||
AnchorSideTop.Side = asrBottom
|
||||
Left = 12
|
||||
Height = 19
|
||||
Top = 81
|
||||
Width = 52
|
||||
BorderSpacing.Bottom = 8
|
||||
Caption = 'Zones'
|
||||
TabOrder = 6
|
||||
end
|
||||
end
|
||||
end
|
||||
inherited SpecsSplitter: TSplitter
|
||||
Left = 390
|
||||
Height = 431
|
||||
Height = 476
|
||||
end
|
||||
inherited PageControl: TPageControl
|
||||
Left = 398
|
||||
Height = 419
|
||||
Height = 464
|
||||
Width = 523
|
||||
inherited ReportPage: TTabSheet
|
||||
ClientHeight = 391
|
||||
ClientHeight = 436
|
||||
ClientWidth = 515
|
||||
inherited Panel1: TPanel
|
||||
Height = 351
|
||||
Height = 396
|
||||
Width = 503
|
||||
ClientHeight = 347
|
||||
ClientHeight = 392
|
||||
ClientWidth = 499
|
||||
inherited ReportMemo: TMemo
|
||||
Height = 339
|
||||
Height = 384
|
||||
Width = 491
|
||||
end
|
||||
end
|
||||
|
@ -1,3 +1,20 @@
|
||||
{ This unit was checked against the commercial statistical package JMP and
|
||||
creates correct results.
|
||||
|
||||
Data file for testing: "boltsize.laz"
|
||||
Group variable: LotNo
|
||||
Selected variable: BoltLngth
|
||||
|
||||
The original LazStats help files suggest
|
||||
Upper Spec Level 20.05
|
||||
Lower Spec Level 19.95
|
||||
Target Spec 20.00
|
||||
but this would indicate a very poor process. Better values:
|
||||
Upper Spec Level 21.00
|
||||
Lower Spec Level 19.00
|
||||
Target Spec 20.00
|
||||
}
|
||||
|
||||
unit XBarChartUnit;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
@ -6,13 +23,15 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls,
|
||||
ExtCtrls, StdCtrls, BasicSPCUnit;
|
||||
ExtCtrls, StdCtrls, Buttons, PrintersDlgs,
|
||||
Globals, BasicSPCUnit;
|
||||
|
||||
type
|
||||
|
||||
{ TXBarChartForm }
|
||||
|
||||
TXBarChartForm = class(TBasicSPCForm)
|
||||
ZonesChk: TCheckBox;
|
||||
LevelOptns: TGroupBox;
|
||||
LowerSpecChk: TCheckBox;
|
||||
LowerSpecEdit: TEdit;
|
||||
@ -23,8 +42,13 @@ type
|
||||
UpperSpecEdit: TEdit;
|
||||
XSigmaEdit: TEdit;
|
||||
procedure FormActivate(Sender: TObject);
|
||||
private
|
||||
FAveStdDev: Double;
|
||||
protected
|
||||
procedure Compute; override;
|
||||
procedure PlotMeans(ATitle, AXTitle, AYTitle, ADataTitle, AGrandMeanTitle: String;
|
||||
const Groups: StrDyneVec; const Means: DblDyneVec;
|
||||
UCL, LCL, GrandMean, TargetSpec, LowerSpec, UpperSpec: double); override;
|
||||
procedure Reset; override;
|
||||
function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override;
|
||||
end;
|
||||
@ -37,7 +61,7 @@ implementation
|
||||
|
||||
uses
|
||||
Math,
|
||||
Globals, Utils, MainUnit, DataProcs;
|
||||
Utils, MainUnit, DataProcs;
|
||||
|
||||
{$R *.lfm}
|
||||
|
||||
@ -80,15 +104,19 @@ var
|
||||
upperSpec: Double = NaN;
|
||||
lowerSpec: Double = NaN;
|
||||
targetSpec: Double = NaN;
|
||||
Cp: Double = NaN;
|
||||
Cpk: Double = NaN;
|
||||
Cpm: Double = NaN;
|
||||
ColNoSelected: IntDyneVec = nil;
|
||||
groups: StrDyneVec = nil;
|
||||
means: DblDyneVec = nil;
|
||||
stdDev: DblDyneVec = nil;
|
||||
count: IntDyneVec = nil;
|
||||
numGrps, grpIndex, totalNumCases, grpSize: Integer;
|
||||
numValues, numGrps, grpIndex, grpSize: Integer;
|
||||
grp: String;
|
||||
X, Xsq: Double;
|
||||
sigma, aveStdDev, UCL, LCL, grandMean, grandSD, SEMean, C4Value: Double;
|
||||
X, Xsq, prevX: Double;
|
||||
sigma, UCL, LCL, grandMean, grandSD, SEMean: Double;
|
||||
individualsChart: Boolean;
|
||||
lReport: TStrings;
|
||||
begin
|
||||
if GroupEdit.Text <> '' then
|
||||
@ -96,10 +124,12 @@ begin
|
||||
SetLength(ColNoSelected, 2);
|
||||
ColNoSelected[0] := GrpVar;
|
||||
ColNoSelected[1] := MeasVar;
|
||||
individualsChart := false;
|
||||
end else
|
||||
begin
|
||||
SetLength(ColNoSelected, 1);
|
||||
ColNoSelected[0] := MeasVar;
|
||||
individualsChart := true;
|
||||
end;
|
||||
|
||||
if UpperSpecChk.Checked and (UpperSpecEdit.Text <> '') then
|
||||
@ -117,71 +147,83 @@ begin
|
||||
else raise Exception.Create('Sigma case not handled.');
|
||||
end;
|
||||
|
||||
if GroupEdit.Text = '' then
|
||||
if individualsChart then
|
||||
SetLength(groups, NoCases)
|
||||
else
|
||||
groups := GetGroups;
|
||||
numGrps := Length(groups);
|
||||
|
||||
SetLength(means, numGrps);
|
||||
SetLength(count, numGrps);
|
||||
SetLength(stddev, numGrps);
|
||||
SEMean := 0.0;
|
||||
grandMean := 0.0;
|
||||
totalNumCases := 0;
|
||||
grandSD := 0.0;
|
||||
numValues := 0;
|
||||
|
||||
// calculate group means, grand mean, group sd's, seMean
|
||||
for i := 1 to NoCases do
|
||||
// calculate group means, grand mean, group std devs, seMean
|
||||
if IndividualsChart then
|
||||
begin
|
||||
if not GoodRecord(i, Length(ColNoSelected), ColNoSelected) then continue;
|
||||
if GroupEdit.Text = '' then
|
||||
// x-bar chart of individual measurements, no groups
|
||||
SetLength(count, 0); // not needed, count is always 1
|
||||
prevX := NaN;
|
||||
for i := 1 to NoCases do
|
||||
begin
|
||||
// individuals x-bar chart
|
||||
grpIndex := totalNumCases;
|
||||
if not GoodRecord(i, Length(ColNoSelected), ColNoSelected) then continue;
|
||||
grpIndex := numValues; // is counted up in this loop
|
||||
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[MeasVar, i]));
|
||||
Xsq := X*X;
|
||||
groups[grpIndex] := IntToStr(i);
|
||||
end else
|
||||
means[grpIndex] := means[grpIndex] + X;
|
||||
if not IsNaN(prevX) then
|
||||
stddev[grpIndex-1] := abs(X - prevX); // assume std dev to be moving range;
|
||||
// -1 --> skip empty 1st value
|
||||
grandMean := grandMean + X;
|
||||
grandSD := grandSD + Xsq;
|
||||
inc(numValues);
|
||||
prevX := X;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
// grouped x-bar chart
|
||||
SetLength(count, numGrps);
|
||||
for i := 1 to NoCases do
|
||||
begin
|
||||
// grouped x-bar chart
|
||||
if not GoodRecord(i, Length(ColNoSelected), ColNoSelected) then continue;
|
||||
grp := Trim(OS3MainFrm.DataGrid.Cells[GrpVar, i]);
|
||||
grpIndex := IndexOfString(groups, grp);
|
||||
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[MeasVar, i]));
|
||||
Xsq := X*X;
|
||||
inc(count[grpIndex]);
|
||||
means[grpIndex] := means[grpIndex] + X;
|
||||
stddev[grpIndex] := stddev[grpIndex] + Xsq;
|
||||
grandMean := grandMean + X;
|
||||
grandSD := grandSD + Xsq;
|
||||
inc(numValues);
|
||||
end;
|
||||
X := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[MeasVar, i]));
|
||||
Xsq := X*X;
|
||||
inc(count[grpIndex]);
|
||||
means[grpIndex] := means[grpIndex] + X;
|
||||
stddev[grpIndex] := stddev[grpIndex] + Xsq;
|
||||
grandMean := grandMean + X;
|
||||
SEMean := SEMean + Xsq;
|
||||
inc(totalNumCases);
|
||||
end;
|
||||
|
||||
SEMean := SEMean - sqr(grandMean) / totalNumCases;
|
||||
SEMean := sqrt(SEMean / (totalNumCases - 1));
|
||||
grandSD := SEMean;
|
||||
SEMean := SEMean / sqrt(totalNumCases);
|
||||
grandMean := grandMean / totalNumCases;
|
||||
grandSD := grandSD - sqr(grandMean) / numValues;
|
||||
grandSD := sqrt(grandSD / (numValues - 1));
|
||||
SEMean := grandSD / sqrt(numValues);
|
||||
grandMean := grandMean / numValues;
|
||||
|
||||
if (GroupEdit.Text = '') then
|
||||
if individualsChart then
|
||||
begin
|
||||
// Individuals chart
|
||||
grpSize := 1;
|
||||
SetLength(means, totalNumCases);
|
||||
SetLength(stddev, totalNumCases);
|
||||
Setlength(count, totalNumCases);
|
||||
for i := 0 to totalNumCases-1 do
|
||||
stddev[i] := SEMean;
|
||||
aveStdDev := NaN;
|
||||
if totalNumCases <= 25 then
|
||||
C4Value := C4[totalNumCases]
|
||||
else
|
||||
C4Value := 1.0;
|
||||
UCL := grandMean + sigma * grandSD / C4Value;
|
||||
LCL := grandMean - sigma * grandSD / C4Value;
|
||||
SetLength(means, numValues);
|
||||
Setlength(count, numValues);
|
||||
SetLength(stddev, numValues-1); // -1 for the missing 1st value
|
||||
FAveStdDev := 0;
|
||||
for i := 0 to High(stddev) do
|
||||
FAveStdDev := FAveStdDev + stdDev[i];
|
||||
FAveStdDev := FAveStdDev / Length(stddev) / 1.128; // 1.128 is the value of d2 fo n = 2.
|
||||
UCL := grandMean + sigma * FAveStdDev;
|
||||
LCL := grandMean - sigma * FAveStdDev;
|
||||
end else
|
||||
begin
|
||||
// Grouped chart
|
||||
|
||||
// Check group size - it is assumed that all groups are equally sized
|
||||
// Check group size first; it is assumed that all groups are equally sized
|
||||
grpSize := count[0];
|
||||
for i := 1 to numGrps-1 do
|
||||
if count[i] <> grpSize then
|
||||
@ -190,9 +232,10 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
aveStdDev := aveStdDev + stdDev[i];
|
||||
|
||||
aveStdDev := 0;
|
||||
SetLength(means, numGrps);
|
||||
Setlength(count, numGrps);
|
||||
SetLength(stddev, numGrps);
|
||||
FAveStdDev := 0;
|
||||
for i := 0 to numGrps-1 do
|
||||
begin
|
||||
if count[i] = 0 then
|
||||
@ -206,40 +249,71 @@ begin
|
||||
else
|
||||
begin
|
||||
stddev[i] := stddev[i] - sqr(means[i]) / count[i];
|
||||
stddev[i] := stddev[i] / (count[i] - 1); // Variance of group i
|
||||
aveStdDev := aveStdDev + stdDev[i]; // Sum of variances
|
||||
stddev[i] := sqrt(stddev[i]); // StdDev of group i
|
||||
stddev[i] := stddev[i] / (count[i] - 1); // Variance of group i
|
||||
FAveStdDev := FAveStdDev + stdDev[i]; // Sum of variances
|
||||
stddev[i] := sqrt(stddev[i]); // StdDev of group i
|
||||
end;
|
||||
means[i] := means[i] / count[i];
|
||||
end;
|
||||
end;
|
||||
aveStdDev := sqrt(aveStdDev / (numGrps * grpSize));
|
||||
UCL := grandMean + sigma * aveStdDev;
|
||||
LCL := grandMean - sigma * aveStdDev;
|
||||
FAveStdDev := sqrt(FAveStdDev / (numGrps * grpSize));
|
||||
UCL := grandMean + sigma * FAveStdDev;
|
||||
LCL := grandMean - sigma * FAveStdDev;
|
||||
|
||||
//UCL := grandMean + sigma * grandSD / sqrt(grpSize); // this works, too, a bit more off of JMP than the above...
|
||||
//LCL := grandMean - sigma * grandSD / sqrt(grpSize);
|
||||
|
||||
// UCL := grandMean + sigma * SEMean; // old LazStats calculation -- does not agree with JMP software.
|
||||
// LCL := grandMean - sigma * SEMean;
|
||||
end;
|
||||
|
||||
// Print results
|
||||
if not IsNaN(upperSpec) and not IsNaN(lowerSpec) then
|
||||
begin
|
||||
Cp := (upperSpec - lowerSpec) / (6* FAveStdDev);
|
||||
Cpk := Min(UpperSpec - grandMean, grandMean - LowerSpec) / (3 * FAveStdDev);
|
||||
if not IsNaN(targetSpec) then
|
||||
Cpm := (upperSpec - lowerSpec) / (6 * sqrt(sqr(FAveStdDev) + sqr(grandMean - targetSpec)));
|
||||
end;
|
||||
|
||||
// Print results
|
||||
lReport := TStringList.Create;
|
||||
try
|
||||
lReport.Add('X BAR CHART RESULTS');
|
||||
lReport.Add('');
|
||||
lReport.Add('Number of values: %8d', [totalNumCases]);
|
||||
lReport.Add('Number of values: %8d', [numValues]);
|
||||
lReport.Add('Number of groups: %8d', [numGrps]);
|
||||
lReport.Add('Group size: %8d', [grpSize]);
|
||||
lReport.Add('');
|
||||
lReport.Add('Grand Mean: %8.3f', [grandMean]);
|
||||
lReport.Add('Standard Deviation: %8.3f', [grandSD]);
|
||||
lReport.Add('Standard Error of Mean: %8.3f', [SEMean]);
|
||||
lReport.Add('Average Std Deviation: %8.3f', [aveStdDev]);
|
||||
lReport.Add('Lower Control Limit: %8.3f', [LCL]);
|
||||
lReport.Add('Average Std Deviation: %8.3f', [FAveStdDev]);
|
||||
lReport.Add('Upper Control Limit: %8.3f', [UCL]);
|
||||
lReport.Add('Lower Control Limit: %8.3f', [LCL]);
|
||||
lReport.Add('');
|
||||
lReport.Add(' Group Size Mean Std.Dev.');
|
||||
lReport.Add('------- ---- -------- --------');
|
||||
for i := 0 to numGrps-1 do
|
||||
lReport.Add('%7s %4d %8.2f %8.2f', [groups[i], count[i], means[i], stddev[i]]);
|
||||
if not IsNaN(targetSpec) then
|
||||
lReport.Add('Target: %8.3f', [targetSpec]);
|
||||
if not IsNaN(upperSpec) then
|
||||
lReport.Add('Upper Spec Limit: %8.3f', [upperSpec]);
|
||||
if not IsNaN(lowerSpec) then
|
||||
lReport.Add('Lower Spec Limit: %8.3f', [lowerSpec]);
|
||||
if not IsNaN(Cp) then
|
||||
lReport.Add('Cp: %8.3f', [cp]);
|
||||
if not IsNaN(Cpk) then
|
||||
lReport.Add('Cpk: %8.3f', [Cpk]);
|
||||
if not IsNaN(Cpm) then
|
||||
lReport.Add('Cpm: %8.3f', [Cpm]);
|
||||
lReport.Add('');
|
||||
lReport.Add(' Group Size Mean Std.Dev.');
|
||||
lReport.Add('------- ---- -------- --------');
|
||||
if individualsChart then
|
||||
begin
|
||||
lReport.Add ('%7s %4d %8.2f', [groups[i], count[i], means[i]]);
|
||||
for i := 1 to numGrps-1 do
|
||||
lReport.Add('%7s %4d %8.2f %8.2f', [groups[i], count[i], means[i], stddev[i-1]]);
|
||||
end else
|
||||
for i := 0 to numGrps-1 do
|
||||
lReport.Add('%7s %4d %8.2f %8.2f', [groups[i], count[i], means[i], stddev[i]]);
|
||||
|
||||
ReportMemo.Lines.Assign(lReport);
|
||||
finally
|
||||
@ -249,13 +323,42 @@ begin
|
||||
// Show graph
|
||||
PlotMeans(
|
||||
Format('x̄ chart for "%s"', [GetFileName]),
|
||||
GroupEdit.Text, MeasEdit.Text, 'Group means', 'Grand mean',
|
||||
GroupEdit.Text, MeasEdit.Text, '', 'Avg',
|
||||
groups, means,
|
||||
UCL, LCL, grandmean,
|
||||
targetSpec, lowerSpec, upperSpec
|
||||
);
|
||||
end;
|
||||
|
||||
procedure TXBarChartForm.PlotMeans(
|
||||
ATitle, AXTitle, AYTitle, ADataTitle, AGrandMeanTitle: String;
|
||||
const Groups: StrDyneVec; const Means: DblDyneVec;
|
||||
UCL, LCL, GrandMean, TargetSpec, LowerSpec, UpperSpec: double);
|
||||
const
|
||||
EPS = 1E-6;
|
||||
var
|
||||
y: Double;
|
||||
begin
|
||||
inherited;
|
||||
if not ZonesChk.Checked then
|
||||
exit;
|
||||
|
||||
y := GrandMean + FAveStdDev;
|
||||
while y < UCL - EPS do
|
||||
begin
|
||||
FChartFrame.HorLine(y, clRed, psDot, '');
|
||||
y := y + FAveStdDev;
|
||||
end;
|
||||
|
||||
y := GrandMean - FAveStdDev;
|
||||
while y > LCL + EPS do
|
||||
begin
|
||||
FChartFrame.HorLine(y, clRed, psDot, '');
|
||||
y := y - FAveStdDev;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TXBarChartForm.Reset;
|
||||
begin
|
||||
inherited;
|
||||
@ -266,6 +369,7 @@ begin
|
||||
UpperSpecChk.Checked := false;
|
||||
LowerSpecChk.Checked := false;
|
||||
TargetChk.Checked := false;
|
||||
ZonesChk.Checked := false;
|
||||
end;
|
||||
|
||||
function TXBarChartForm.Validate(out AMsg: String; out AControl: TWinControl): Boolean;
|
||||
|
Reference in New Issue
Block a user