Inspiration
An aerospace contractor 3D-prints Ti-6Al-4V brackets by laser powder bed fusion, and the brackets keep failing the client's strength tests. The shop already logs chamber oxygen, powder-room humidity and powder reuse, but nobody relates them to part strength, so trouble shows up only when parts fail. We built the screen a quality engineer opens the day a build's witness tensile coupons come back from the lab.
What it does
Upload one row per tested witness coupon: a build ID and the ultimate tensile strength (MPa); the per-build logs are optional. The tool answers with one action (RELEASE, HOLD, INVESTIGATE, COLLECT MORE DATA, IMPROVE or CHECK DATA) plus the evidence:
- Stability: X-bar and S control charts with limits from a 20-build baseline (sigma_short pooled within builds), read with the course's 8 tests for special causes (defaults: tests 1-4 on X-bar, test 1 on S).
- Capability: one-sided Cpk and Ppk against the client minimum (default 895 MPa, the ASTM F2924 minimum for Ti-6Al-4V), with 95% intervals and one-sided lower bounds. The process counts as capable only when Cpk's lower bound clears the required 1.33 over a 20-build baseline.
- Failures: expected coupons below spec (normal model) next to the observed count, with a Shapiro-Wilk check and a Q-Q plot.
- Drivers: a regression of build means on the logged factors (HC3 robust errors) that names what to fix first, and says plainly that it shows association, not proof.
Every tab has a "how to read this" note, and the Method tab shows every formula.
How we built it
qc.pyis a plain, tested Python statistics library with no web code;app.pyis a thin Shiny for Python dashboard that only callsqc.assess(), so every number on screen traces to one function.- Deployed to the course Posit Connect by GitHub Actions (committed manifest, health check, logged-out check), plus a static Shinylive mirror on GitHub Pages that runs Python in the browser.
- Three seeded, simulated datasets with a codebook: a stable printer (RELEASE), a dehumidifier failure after build 20 (HOLD; first alarm at build 22; humidity -1.82 MPa per %RH), and a new printer with messy lab data (IMPROVE).
Challenges we ran into
- False alarms. With all 8 tests on both charts, about 46% of perfectly stable 25-build histories trip at least one test (we simulated it). We kept tests 1-4 on X-bar and test 1 on S as defaults, and HOLD looks only at patterns still active at the newest build.
- Stability can't be proven from four builds. A confidence bound on Cpk assumes stability, so RELEASE also needs a 20-build baseline of builds with replicate coupons.
- Messy lab data. Missing results, short builds and single-coupon builds are handled and reported, never imputed.
Accomplishments that we're proud of
- 53 automated tests: a hand-worked known answer (Cpk 2.0742, 95% lower bound 1.4587), the course's own examples, Anscombe's quartet for the regression, a planted signal for each of the 8 tests, and degenerate cases (constant data never yields an infinite Cpk).
- Our 8 tests match the course's
spc_tests_from()on 500 random charts with zero mismatches, and a separate stats-reviewer agent re-derived every number; all of its findings were fixed. - On the humidity dataset the tool tells the drift story the way the course teaches it: Cpk 1.43 but Ppk 0.88.
What we learned
- sigma_short versus sigma_total is the whole difference between capability and performance.
- Every extra run rule costs false alarms, so measure the cost before choosing defaults.
- Statistics first, styling last: verify against known answers before building any UI.
What's next
- A Phase I workflow that excludes builds with explained special causes and freezes the limits.
- Multi-printer comparison (ANOVA), and a designed-experiment template to confirm the humidity driver before changing the process.
Log in or sign up for Devpost to join the conversation.