Executing product-development-product-improvement/multivariate-process-monitoring.rst end to end against process-improve 1.78.0 shows:
1. The contribution block does not run (line 499). model.score_contributions(t_at_alarm, weighted=True) raises TypeError: score_contributions() takes the preprocessed data X, not a score vector. There is no weighted parameter; the T2 decomposition is model.t2_contributions(X). The prose at lines 489-494 describes a re-weighting by 1/sqrt(lambda_a) that the library does not offer under that name.
2. The contribution numbers and the conclusion drawn from them are wrong (lines 516-528, 596-600). The five quoted values (Air flow -1.62, Upstream pH -1.45, Pulp level -1.32, Feed rate -1.25, CuSO4 -1.12) only reproduce in magnitude, with opposite sign, from the removed formula. The phase-2 subgroup 3 row in scaled units is Upstream pH 5.87, CuSO4 2.76, Pulp level 0.68, Feed rate 0.53, Air flow -0.40, and t2_contributions gives Upstream pH 6.44, CuSO4 2.22, Pulp level 0.68, Feed rate 0.48, Air flow -0.49 of a total T2 of about 9.3. The alarm is dominated by upstream pH, with CuSO4 second. The text's "all five variables contribute in the same direction with comparable magnitude" and "not as a single rogue variable" are artefacts of spreading one score over near-equal loadings.
3. "No phase-1 alarms" is false (lines 269, 311). With the chapter's own target 30.12 and limits 27.40 / 32.83, 54 of the 125 phase-1 subgroup means fall outside the limits. The cause is the autocorrelation the chapter documents two paragraphs earlier: the mean within-subgroup standard deviation (2.47) understates the between-subgroup spread (3.55), so the 3-sigma half-width is far too tight. This is a useful teaching point, not a defect in the data.
4. Loadings interpretation (figure caption, lines 400-404). p1 is said to be "dominated by the air-flow / pulp-level / pH triple", but Pulp level (0.337) is the smallest entry in p1 and Upstream pH (0.403) the second smallest; the three largest are Feed rate, CuSO4 and Air flow. p2's second-largest entry, Pulp level (-0.491), is not mentioned.
Smaller items. Lines 147-148 and 636 say "2-minute subgroups" while the code uses n_sub = 8 (four minutes, 125 subgroups, as the caption at 308 says). Line 145: 478 rows carry the 15 December timestamp, not 479. Line 223: rho_1 is 0.885, not "around 0.87". Line 358: the third component adds 14.7% (rounds to 15%). Line 267: the half-width is 2.716, not 2.71. Lines 416-418 could say once that spe is on the square-root scale.
The chapter's figures come from figures/monitoring/flotation_monitoring_case.py, which has the same score_contributions call (kgdunn/figures#87); the contribution PNG changes with the fix. Found by executing every code block of the book (#274).
Executing
product-development-product-improvement/multivariate-process-monitoring.rstend to end against process-improve 1.78.0 shows:1. The contribution block does not run (line 499).
model.score_contributions(t_at_alarm, weighted=True)raisesTypeError: score_contributions() takes the preprocessed data X, not a score vector. There is noweightedparameter; the T2 decomposition ismodel.t2_contributions(X). The prose at lines 489-494 describes a re-weighting by1/sqrt(lambda_a)that the library does not offer under that name.2. The contribution numbers and the conclusion drawn from them are wrong (lines 516-528, 596-600). The five quoted values (Air flow -1.62, Upstream pH -1.45, Pulp level -1.32, Feed rate -1.25, CuSO4 -1.12) only reproduce in magnitude, with opposite sign, from the removed formula. The phase-2 subgroup 3 row in scaled units is
Upstream pH 5.87, CuSO4 2.76, Pulp level 0.68, Feed rate 0.53, Air flow -0.40, andt2_contributionsgivesUpstream pH 6.44, CuSO4 2.22, Pulp level 0.68, Feed rate 0.48, Air flow -0.49of a total T2 of about 9.3. The alarm is dominated by upstream pH, with CuSO4 second. The text's "all five variables contribute in the same direction with comparable magnitude" and "not as a single rogue variable" are artefacts of spreading one score over near-equal loadings.3. "No phase-1 alarms" is false (lines 269, 311). With the chapter's own target 30.12 and limits 27.40 / 32.83, 54 of the 125 phase-1 subgroup means fall outside the limits. The cause is the autocorrelation the chapter documents two paragraphs earlier: the mean within-subgroup standard deviation (2.47) understates the between-subgroup spread (3.55), so the 3-sigma half-width is far too tight. This is a useful teaching point, not a defect in the data.
4. Loadings interpretation (figure caption, lines 400-404). p1 is said to be "dominated by the air-flow / pulp-level / pH triple", but Pulp level (0.337) is the smallest entry in p1 and Upstream pH (0.403) the second smallest; the three largest are Feed rate, CuSO4 and Air flow. p2's second-largest entry, Pulp level (-0.491), is not mentioned.
Smaller items. Lines 147-148 and 636 say "2-minute subgroups" while the code uses
n_sub = 8(four minutes, 125 subgroups, as the caption at 308 says). Line 145: 478 rows carry the 15 December timestamp, not 479. Line 223: rho_1 is 0.885, not "around 0.87". Line 358: the third component adds 14.7% (rounds to 15%). Line 267: the half-width is 2.716, not 2.71. Lines 416-418 could say once thatspeis on the square-root scale.The chapter's figures come from
figures/monitoring/flotation_monitoring_case.py, which has the samescore_contributionscall (kgdunn/figures#87); the contribution PNG changes with the fix. Found by executing every code block of the book (#274).