system.kanoa.quality.spc.spcCheckT2(rows, variableNames, alpha)
Hotelling's T2 multivariate control chart. Charts a matrix of correlated variables per observation, not a single value series. Mean vector and covariance matrix are computed from chkItemEvent data (Phase I - the baseline is the same data being charted). UCL uses the chi-square approximation (valid once the baseline sample is reasonably large), not the exact F-distribution - simpler, no incomplete-beta-function implementation needed, and standard practice in most commercial SPC software for this case.
variableNames and alpha are required parameters with no default value in the signature - pass None explicitly to get the default behavior described below. This is deliberate: the module is a candidate for a future Java port, and Java has no native optional-parameter support.
Parameters
rows list[list[float]]: one row per observation (e.g. one inspected unit/event), each row holding the same p variables in the same order - e.g. [[length, width, height], [length, width, height], ...]. All rows must be the same length; missing/None values aren't supported (filter incomplete rows out before calling).
variableNames List of Strings: p names for labeling. Pass None to auto-label Var1..Varp.
alpha Float: false-alarm rate for the UCL. Pass None for the default, 0.0027, which matches the ~3-sigma-equivalent Type I error rate used for the univariate Shewhart charts elsewhere in this module, so a T2 chart's out-of-control rate is comparable to what users already expect from individuals/xbar/etc.
Returns
results Dictionary
chartType String i.e. 't2'
error String
p Integer variable count
n Integer observation count
variableNames List of Strings
mean List of Float values the p-dim mean vector
covariance list[list[float]] the p x p sample covariance matrix
points List of Float values T2 value per observation
ucl Float chi-square-approximation control limit
aboveUCL List of Integers indices of observations exceeding ucl
outOfControl Boolean
Examples
In-control baseline
rows = [
[100.4, 50.2], [98.6, 50.3], [100.2, 50.1], [96.0, 50.4], [109.8, 49.9],
[102.1, 50.0], [103.2, 49.8], [97.5, 50.5], [101.0, 50.0], [99.8, 50.2],
[100.5, 49.9], [98.9, 50.3], [102.4, 49.8], [99.1, 50.4],
]
variableNames = ["Length", "Width"]
result = system.kanoa.quality.spc.spcCheckT2(rows, variableNames, None)
# result["p"] = 2
# result["n"] = 14
# result["mean"] = [100.679, 50.129]
# result["covariance"] = [[10.594, -0.559], [-0.559, 0.055]]
# result["ucl"] = 11.983
# result["points"] = [0.136, 0.56, 0.138, 2.09, 10.417, 0.305, 2.13, 2.614, 0.508, 0.098, 2.271, 0.539, 2.542, 1.652]
# result["aboveUCL"] = []
# result["outOfControl"] = False
Note mean/covariance are computed from these same 14 rows (Phase I) - Length and Width happen to be fairly strongly negatively correlated here (-0.559 covariance), which is exactly what lets T2 catch a point that breaks that relationship, below.
Adding a correlation-breaking observation
rows.append([115.0, 51.5]) # both Length AND Width move up together - breaks the negative correlation
result = system.kanoa.quality.spc.spcCheckT2(rows, variableNames, None)
# result["n"] = 15
# result["points"][-1] = 12.218 (exceeds ucl = 11.983)
# result["aboveUCL"] = [14]
# result["outOfControl"] = True
Notice the new point isn't extreme on either variable by itself (Length=115 and Width=51.5 are each only a couple of points away from their own means) - it's flagged because the combination moves against the established relationship between the two, which is precisely what a pair of independent univariate charts on Length and Width individually would miss.