Inspiration

An aerospace contractor 3D-prints titanium brackets, and the client keeps failing them on strength tests. The people who release those builds need an early, trustworthy answer to three questions: is the print process stable, is it capable of meeting the client's limits, and if not, what changed?

We built AeroPrint for the supplier quality engineer who releases builds, and for the additive manufacturing process engineer who tunes the printer. It follows Prompt 1 (3D Printing for Aerospace) of the Cornell Six Sigma Hackathon, Distance Learning track.

What it does

You give it test results for each build (5 coupons per build, 5 required columns). It tells you:

  • Is the process capable? A clear Yes or No for tensile strength, porosity and dimensional deviation, with each capability index shown against the minimum of 1.33.
  • Which builds to hold? A build is QUARANTINE if a control chart rule broke on it. Builds with no rule broken are RELEASE if the process is capable and NOT RELEASED if it is not. No build is released from a process that is not capable.
  • What to look at first? It ranks the print settings (chamber oxygen, laser power and others) that look different on the builds that broke a rule.
  • Is a machine or material lot linked to the problem? A two-way ANOVA with an interaction plot, plus a plain "association, not cause" warning.

How we built it

The statistics are in one Python file (numpy, pandas, scipy). Each build is a subgroup of 5 coupons. On the X-bar and R charts the limits come from the baseline builds (the first 20 by default):

$$\bar{\bar{X}} \pm A_2\,\bar{R}, \qquad \text{R chart UCL} = D_4\,\bar{R}, \qquad A_2 = 0.577,\; D_4 = 2.114$$

Capability uses the within-build spread, not the overall spread:

$$\hat{\sigma} = \frac{\bar{R}}{d_2}, \quad d_2 = 2.326$$

$$C_{pl} = \frac{\mu - \mathrm{LSL}}{3\hat{\sigma}}, \qquad C_{pu} = \frac{\mathrm{USL} - \mu}{3\hat{\sigma}}, \qquad C_{pk} = \min(C_{pl}, C_{pu})$$

A process counts as capable only if every chart is in control and every Cpk is at least 1.33. The print settings get individual and moving range charts, and all 8 Nelson rules look for patterns. The possible-causes panel fits

$$y = \mu + \text{machine} + \text{lot} + \text{machine}\times\text{lot} + \varepsilon$$

to the build averages, with Type II sums of squares, an F-test per effect and a 0.05 significance level (α = 0.05).

The tool. FastAPI serves the analysis, with interactive docs. A React dashboard with hand-drawn SVG charts only draws what the API returns, so the browser does no statistics. Everything is deployed on Posit Connect and redeployed automatically through GitHub Actions.

Testing. 138 Python tests and 172 dashboard tests, including known answers we worked out by hand. Three builds, with limits 944.23 and 955.77, give Cpl = 3.877, and a 2×2 ANOVA was computed by hand. A separate reviewer recomputed every statistic independently. We built it with Claude Code and steered it toward statistically correct work, not just a pretty dashboard.

The three test datasets (all simulated)

Dataset What it shows Result
Capable Baseline A healthy process Capable, Cpk = 1.79, 30 builds released
Oxygen Drift Chamber oxygen creeps up from build 21 First alarm at B-1023, 8 quarantined, the rest not released, chamber oxygen ranked first
Marginal Spread In control, but the dimensional spread is too wide Not capable, Cpk = 1.04, all 30 not released. The ANOVA finds a machine effect (p-value 0.0015)

The machine effect in Marginal Spread is planted on purpose and disclosed: we chose its size after a scan so it is detectable without triggering control chart alarms.

Challenges

  • Getting capability right. Using the within-build spread and trusting an index only when the chart is in control.
  • Honest statistics on small data. With 30 builds, there are only 5 builds per machine and lot combination, and machine and lot change in blocks over time, so they are mixed up with time. The panel says so on the page.
  • One story everywhere. Making the API and the dashboard say the same thing about every build.
  • Limits from builds you trust. We had to decide how many builds should set the limits.

What we learned

Control limits must come from builds you trust. In the Oxygen Drift file, limits worked out from all 30 builds are bent by the drift itself, so 28 of 30 builds get flagged and the first alarm lands at B-1002. With the first 20 builds the alarm lands at B-1023, where the drift really starts. We also learned that a few builds give rough limits, so the tool warns below 10 baseline builds.

What's next

Recording machine and lot for each build in real production, a designed (randomised) experiment to confirm any suspected cause, and keyboard access to individual chart point values.

Try it

Built With

Share this project:

Updates