mfgqc 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mfgqc-0.1.0/LICENSE +21 -0
- mfgqc-0.1.0/PKG-INFO +213 -0
- mfgqc-0.1.0/README.md +174 -0
- mfgqc-0.1.0/mfgqc/__init__.py +227 -0
- mfgqc-0.1.0/mfgqc/_result.py +318 -0
- mfgqc-0.1.0/mfgqc/assumptions.py +249 -0
- mfgqc-0.1.0/mfgqc/attribute_agreement.py +287 -0
- mfgqc-0.1.0/mfgqc/capability.py +409 -0
- mfgqc-0.1.0/mfgqc/constants.py +114 -0
- mfgqc-0.1.0/mfgqc/control_charts.py +512 -0
- mfgqc-0.1.0/mfgqc/data.py +752 -0
- mfgqc-0.1.0/mfgqc/diagnostics.py +427 -0
- mfgqc-0.1.0/mfgqc/doe/__init__.py +31 -0
- mfgqc-0.1.0/mfgqc/doe/alias.py +123 -0
- mfgqc-0.1.0/mfgqc/doe/analysis.py +696 -0
- mfgqc-0.1.0/mfgqc/doe/design.py +292 -0
- mfgqc-0.1.0/mfgqc/doe/generate.py +71 -0
- mfgqc-0.1.0/mfgqc/doe/significance.py +81 -0
- mfgqc-0.1.0/mfgqc/doe/views.py +286 -0
- mfgqc-0.1.0/mfgqc/errors.py +40 -0
- mfgqc-0.1.0/mfgqc/gage_rr.py +475 -0
- mfgqc-0.1.0/mfgqc/hypothesis.py +584 -0
- mfgqc-0.1.0/mfgqc/ingestion.py +746 -0
- mfgqc-0.1.0/mfgqc/msa.py +360 -0
- mfgqc-0.1.0/mfgqc/multivari.py +150 -0
- mfgqc-0.1.0/mfgqc/nonparametric.py +159 -0
- mfgqc-0.1.0/mfgqc/palette.py +133 -0
- mfgqc-0.1.0/mfgqc/pareto_analysis.py +363 -0
- mfgqc-0.1.0/mfgqc/plotting.py +163 -0
- mfgqc-0.1.0/mfgqc/posthoc.py +259 -0
- mfgqc-0.1.0/mfgqc/power/__init__.py +19 -0
- mfgqc-0.1.0/mfgqc/power/solve.py +365 -0
- mfgqc-0.1.0/mfgqc/precontrol.py +170 -0
- mfgqc-0.1.0/mfgqc/process_sigma.py +227 -0
- mfgqc-0.1.0/mfgqc/registry.py +185 -0
- mfgqc-0.1.0/mfgqc/regression.py +871 -0
- mfgqc-0.1.0/mfgqc/regression_ext.py +366 -0
- mfgqc-0.1.0/mfgqc/reliability/__init__.py +40 -0
- mfgqc-0.1.0/mfgqc/reliability/availability.py +87 -0
- mfgqc-0.1.0/mfgqc/reliability/demonstrate.py +200 -0
- mfgqc-0.1.0/mfgqc/reliability/life.py +364 -0
- mfgqc-0.1.0/mfgqc/reliability/nonparametric.py +123 -0
- mfgqc-0.1.0/mfgqc/reliability/system.py +219 -0
- mfgqc-0.1.0/mfgqc/reliability/views.py +87 -0
- mfgqc-0.1.0/mfgqc/sampling.py +984 -0
- mfgqc-0.1.0/mfgqc/timeseries.py +639 -0
- mfgqc-0.1.0/mfgqc/timeseries_charts.py +391 -0
- mfgqc-0.1.0/mfgqc.egg-info/PKG-INFO +213 -0
- mfgqc-0.1.0/mfgqc.egg-info/SOURCES.txt +95 -0
- mfgqc-0.1.0/mfgqc.egg-info/dependency_links.txt +1 -0
- mfgqc-0.1.0/mfgqc.egg-info/requires.txt +14 -0
- mfgqc-0.1.0/mfgqc.egg-info/top_level.txt +1 -0
- mfgqc-0.1.0/pyproject.toml +59 -0
- mfgqc-0.1.0/setup.cfg +4 -0
- mfgqc-0.1.0/tests/test_api.py +148 -0
- mfgqc-0.1.0/tests/test_assumption_flags.py +90 -0
- mfgqc-0.1.0/tests/test_attribute_agreement.py +116 -0
- mfgqc-0.1.0/tests/test_attribute_charts.py +61 -0
- mfgqc-0.1.0/tests/test_availability.py +27 -0
- mfgqc-0.1.0/tests/test_capability.py +59 -0
- mfgqc-0.1.0/tests/test_capability_ci.py +45 -0
- mfgqc-0.1.0/tests/test_capability_nonnormal.py +148 -0
- mfgqc-0.1.0/tests/test_clean_conservative.py +109 -0
- mfgqc-0.1.0/tests/test_control_charts.py +37 -0
- mfgqc-0.1.0/tests/test_cusum_ewma.py +171 -0
- mfgqc-0.1.0/tests/test_demonstration.py +46 -0
- mfgqc-0.1.0/tests/test_diagnostics.py +208 -0
- mfgqc-0.1.0/tests/test_frontend_readiness.py +240 -0
- mfgqc-0.1.0/tests/test_gage_ci.py +44 -0
- mfgqc-0.1.0/tests/test_gage_rr.py +80 -0
- mfgqc-0.1.0/tests/test_hypothesis.py +164 -0
- mfgqc-0.1.0/tests/test_idiom_consistency.py +70 -0
- mfgqc-0.1.0/tests/test_ingestion.py +111 -0
- mfgqc-0.1.0/tests/test_kaplan_meier.py +50 -0
- mfgqc-0.1.0/tests/test_life_fit.py +120 -0
- mfgqc-0.1.0/tests/test_more_charts.py +107 -0
- mfgqc-0.1.0/tests/test_msa.py +160 -0
- mfgqc-0.1.0/tests/test_mtbf_bounds.py +38 -0
- mfgqc-0.1.0/tests/test_palette.py +53 -0
- mfgqc-0.1.0/tests/test_pareto_contingency.py +142 -0
- mfgqc-0.1.0/tests/test_plotting.py +42 -0
- mfgqc-0.1.0/tests/test_posthoc.py +135 -0
- mfgqc-0.1.0/tests/test_power.py +107 -0
- mfgqc-0.1.0/tests/test_process_sigma.py +84 -0
- mfgqc-0.1.0/tests/test_provenance.py +145 -0
- mfgqc-0.1.0/tests/test_published_oracles_six.py +138 -0
- mfgqc-0.1.0/tests/test_qcdata.py +76 -0
- mfgqc-0.1.0/tests/test_regression_anova.py +324 -0
- mfgqc-0.1.0/tests/test_regression_ext.py +120 -0
- mfgqc-0.1.0/tests/test_reliability_oracle.py +134 -0
- mfgqc-0.1.0/tests/test_reporting.py +28 -0
- mfgqc-0.1.0/tests/test_sampling.py +273 -0
- mfgqc-0.1.0/tests/test_spc_additions.py +111 -0
- mfgqc-0.1.0/tests/test_system.py +39 -0
- mfgqc-0.1.0/tests/test_timeseries.py +194 -0
- mfgqc-0.1.0/tests/test_timeseries_multivari.py +109 -0
- mfgqc-0.1.0/tests/test_z19.py +98 -0
mfgqc-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Brantner Solutions
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mfgqc-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mfgqc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Auditable SPC, capability, and gage R&R for manufacturing: statistical guardrails, hash-chained provenance, canonical QC charts.
|
|
5
|
+
Author: Brantner Solutions
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://mfgqc.brantnersolutions.com
|
|
8
|
+
Project-URL: Documentation, https://mfgqc.brantnersolutions.com
|
|
9
|
+
Project-URL: Repository, https://github.com/cjbrant/mfgQC
|
|
10
|
+
Project-URL: Issues, https://github.com/cjbrant/mfgQC/issues
|
|
11
|
+
Keywords: spc,statistical-process-control,capability,cpk,gage-rr,msa,six-sigma,manufacturing,control-charts,doe,design-of-experiments,reliability,acceptance-sampling,quality-control
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Manufacturing
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: numpy>=1.23
|
|
27
|
+
Requires-Dist: pandas>=1.5
|
|
28
|
+
Requires-Dist: scipy>=1.9
|
|
29
|
+
Requires-Dist: matplotlib>=3.6
|
|
30
|
+
Requires-Dist: statsmodels>=0.13
|
|
31
|
+
Requires-Dist: scikit-learn>=1.1
|
|
32
|
+
Provides-Extra: test
|
|
33
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
34
|
+
Provides-Extra: docs
|
|
35
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
|
|
36
|
+
Requires-Dist: mkdocstrings[python]>=0.25; extra == "docs"
|
|
37
|
+
Requires-Dist: mkdocs-material[imaging]>=9.5; extra == "docs"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# mfgQC
|
|
41
|
+
|
|
42
|
+
[](https://pypi.org/project/mfgqc/)
|
|
43
|
+
[](https://pypi.org/project/mfgqc/)
|
|
44
|
+
[](LICENSE)
|
|
45
|
+
[](https://github.com/cjbrant/mfgQC/actions/workflows/tests.yml)
|
|
46
|
+
[](https://mfgqc.brantnersolutions.com)
|
|
47
|
+
|
|
48
|
+
**Auditable SPC, capability, and gage R&R for manufacturing** — by
|
|
49
|
+
[Brantner Solutions](https://brantnersolutions.com).
|
|
50
|
+
Full documentation: **[mfgqc.brantnersolutions.com](https://mfgqc.brantnersolutions.com)**.
|
|
51
|
+
|
|
52
|
+
Quality-control analysis for manufacturing practitioners, not statisticians or
|
|
53
|
+
programmers. Three pillars:
|
|
54
|
+
|
|
55
|
+
1. **Statistical guardrails.** Every analysis checks its own assumptions and
|
|
56
|
+
reports the outcome. It warns and recommends; it never silently switches
|
|
57
|
+
methods. Auto-correction is opt-in.
|
|
58
|
+
2. **Practitioner-oriented.** You bring domain knowledge; mfgQC brings the
|
|
59
|
+
statistics, data handling, and canonical charts. Errors say what's missing
|
|
60
|
+
and why.
|
|
61
|
+
3. **Auditable by construction.** `QCData` and result objects are immutable and
|
|
62
|
+
carry a structured, propagating provenance history, so the full lineage from
|
|
63
|
+
raw data to final number can be reconstructed.
|
|
64
|
+
|
|
65
|
+
## Install
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install mfgqc
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
For development (editable install with test extras):
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install -e ".[test]"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Requires Python 3.10+. Core dependencies are NumPy, pandas, SciPy, Matplotlib,
|
|
78
|
+
statsmodels, and scikit-learn.
|
|
79
|
+
|
|
80
|
+
## Use
|
|
81
|
+
|
|
82
|
+
The idiom is always the same: `load` a frame, attach metadata with `.spec()` /
|
|
83
|
+
`.roles()`, then call an analysis. Every result has `.report()` (text),
|
|
84
|
+
`.summary()` (a flat dict), `.to_dict()` (full structured payload), and `.view()`
|
|
85
|
+
(the canonical chart).
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import pandas as pd, mfgqc
|
|
89
|
+
|
|
90
|
+
qc = (mfgqc.load(df, measure="width", subgroup="lot", subgroup_size=5)
|
|
91
|
+
.spec(lower=1.0, upper=2.0, target=1.5))
|
|
92
|
+
|
|
93
|
+
print(qc.capability()) # Cp/Cpk (within-sigma) + Pp/Ppk (overall) + assumption report
|
|
94
|
+
print(qc.control_chart()) # inferred chart, run-rules violations
|
|
95
|
+
print(qc.gage_rr()) # ANOVA gage R&R (needs part/operator/replicate roles)
|
|
96
|
+
|
|
97
|
+
fig = qc.capability().view(save="capability.png") # canonical chart (matplotlib Figure)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
To load a CSV, read it with pandas first: `mfgqc.load(pd.read_csv(path), measure=...)`.
|
|
101
|
+
|
|
102
|
+
## Provenance & auditability
|
|
103
|
+
|
|
104
|
+
This is mfgQC's reason to exist over `qcc` or Minitab: the lineage from raw data to
|
|
105
|
+
final number is recorded, immutable, and verifiable — not asserted in a doc.
|
|
106
|
+
|
|
107
|
+
**What is recorded.** Every step that derives a number appends a structured
|
|
108
|
+
provenance entry: ingest, spec/role binding, each transform (e.g. Box-Cox),
|
|
109
|
+
subgroup aggregation, the sigma method chosen, and each assumption check. The
|
|
110
|
+
chain is reconstructable end to end:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
qc = mfgqc.load(df, measure="y").spec(lower=0.1, upper=8)
|
|
114
|
+
cap = qc.transform("boxcox").capability()
|
|
115
|
+
|
|
116
|
+
[s["operation"] for s in cap.lineage()]
|
|
117
|
+
# ['load', 'spec', 'transform', 'capability', 'assumption:normality']
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Immutability guarantee (append-only by construction).** `QCData` and every
|
|
121
|
+
result are frozen dataclasses; the history is an immutable tuple of frozen steps,
|
|
122
|
+
so it cannot be reordered, inserted into, or edited in place. The ingest boundary
|
|
123
|
+
defensive-copies the input frame, `.frame` hands back a copy, and `.values()` is
|
|
124
|
+
read-only — so nothing a caller does to what mfgQC returns can reach back and
|
|
125
|
+
change a recorded result.
|
|
126
|
+
|
|
127
|
+
**Tamper-evidence (hash-chained and verifiable).** Each step folds into a
|
|
128
|
+
running SHA-256, exposed as `provenance_digest()` and stamped into `to_dict()`.
|
|
129
|
+
Capture the digest when you record a number, and re-check it later:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
digest = cap.provenance_digest() # store alongside the reported Cpk
|
|
133
|
+
cap.verify_provenance(digest) # True; flips to False if any step was edited
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**The limit, stated honestly.** The digest is a content hash, not a cryptographic
|
|
137
|
+
signature: code running in the same process could edit a step *and* recompute the
|
|
138
|
+
digest. It defends against accidental corruption and post-hoc edits to a stored
|
|
139
|
+
result, not against an adversary who controls the interpreter. One boundary is
|
|
140
|
+
explicit: once you extract the matplotlib `Figure` from `.view()`, edits to that
|
|
141
|
+
Figure are outside the lineage.
|
|
142
|
+
|
|
143
|
+
## Modules
|
|
144
|
+
|
|
145
|
+
- **Capability** — Cp/Cpk (within-subgroup sigma) vs Pp/Ppk (overall sigma), Cpm,
|
|
146
|
+
each with confidence intervals (small-n point estimates are overconfident; the
|
|
147
|
+
interval is reported so you see it); normal plus Box-Cox / Clements / Johnson
|
|
148
|
+
non-normal methods.
|
|
149
|
+
- **Control charts** — I-MR, Xbar-R, Xbar-S, p/np/c/u, EWMA, CUSUM, short-run;
|
|
150
|
+
Nelson and Western Electric run rules.
|
|
151
|
+
- **Measurement systems analysis** — ANOVA gage R&R, bias, linearity, stability,
|
|
152
|
+
attribute agreement (Cohen/Fleiss/weighted kappa).
|
|
153
|
+
- **Hypothesis testing** — assumption-routing two-sample / one-sample / variance /
|
|
154
|
+
proportion tests, one-way ANOVA, post-hoc (Tukey/Games-Howell/Dunn/Dunnett),
|
|
155
|
+
non-parametrics (Mood's median, repeated measures).
|
|
156
|
+
- **Regression & DOE** — OLS, model selection, logistic, non-linear least squares,
|
|
157
|
+
Box-Cox; full and fractional factorial design generation and effect analysis
|
|
158
|
+
(Lenth for unreplicated designs) with alias structure.
|
|
159
|
+
- **Sample size & power** — t-test, ANOVA, proportion, and variance, via the
|
|
160
|
+
noncentral distributions.
|
|
161
|
+
- **Attributes & reliability** — DPMO/sigma level, life-distribution fitting with
|
|
162
|
+
censoring, Kaplan-Meier, system reliability, bearing life (ISO 281), MTBF,
|
|
163
|
+
availability, demonstration tests.
|
|
164
|
+
- **Acceptance sampling** — single attribute plans, OC curves, ANSI/ASQ Z1.4 and
|
|
165
|
+
Z1.9.
|
|
166
|
+
|
|
167
|
+
## Method choices
|
|
168
|
+
|
|
169
|
+
The choices a practitioner needs to trust the number are explicit, not hidden:
|
|
170
|
+
|
|
171
|
+
- **Control-chart inference.** `control_chart()` with no `kind=` picks the
|
|
172
|
+
variables chart from the subgroup size: size 1 → I-MR (individuals + moving
|
|
173
|
+
range), size 2–10 → X̄-R, size > 10 → X̄-S. Pass `kind=` to override; attribute
|
|
174
|
+
charts (`p`/`np`/`c`/`u`) are always explicit.
|
|
175
|
+
- **Within-subgroup sigma (Cp/Cpk).** Equal subgroups use R̄/d₂; individuals use
|
|
176
|
+
MR̄/d₂; unequal subgroup sizes use the pooled within-subgroup standard
|
|
177
|
+
deviation. Pp/Ppk always use the overall standard deviation. The estimator
|
|
178
|
+
actually used is reported in the capability result (`sigma_used`, e.g.
|
|
179
|
+
`"within (R-bar/d2)"`).
|
|
180
|
+
|
|
181
|
+
## Building on mfgQC
|
|
182
|
+
|
|
183
|
+
mfgQC is built to be driven programmatically (e.g. by a report builder or UI):
|
|
184
|
+
|
|
185
|
+
- `mfgqc.list_analyses()` / `mfgqc.ANALYSES` — machine-readable catalog of every
|
|
186
|
+
analysis and its required inputs.
|
|
187
|
+
- `result.to_dict()` — full JSON-serializable payload (fields, assumption checks,
|
|
188
|
+
provenance); `result.summary()` is the flat form.
|
|
189
|
+
- `result.view(save="chart.png")` — headless chart rendering to PNG/SVG.
|
|
190
|
+
- `mfgqc.MissingPrerequisiteError` — specific, catchable error naming what an
|
|
191
|
+
analysis still needs.
|
|
192
|
+
|
|
193
|
+
## Documentation
|
|
194
|
+
|
|
195
|
+
Full user guide and reference (with the formula, assumptions, and source standard
|
|
196
|
+
each method is pinned to) live at
|
|
197
|
+
**[mfgqc.brantnersolutions.com](https://mfgqc.brantnersolutions.com)**.
|
|
198
|
+
|
|
199
|
+
## Tests
|
|
200
|
+
|
|
201
|
+
The suite has two layers. Regression tests pin mfgQC to its build oracles
|
|
202
|
+
(Montgomery; AIAG MSA 4th ed.; Lawson, *Design and Analysis of Experiments with
|
|
203
|
+
R*). A separate `tests/correctness/` suite pins each analysis to an **independent**
|
|
204
|
+
source it was not built against (the NIST/SEMATECH e-Handbook and StRD certified
|
|
205
|
+
datasets, the R `qcc`/`SixSigma` packages, and scipy/statsmodels computed in-test).
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
pytest
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
© Brantner Solutions · [brantnersolutions.com](https://brantnersolutions.com) · MIT License
|
mfgqc-0.1.0/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# mfgQC
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/mfgqc/)
|
|
4
|
+
[](https://pypi.org/project/mfgqc/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/cjbrant/mfgQC/actions/workflows/tests.yml)
|
|
7
|
+
[](https://mfgqc.brantnersolutions.com)
|
|
8
|
+
|
|
9
|
+
**Auditable SPC, capability, and gage R&R for manufacturing** — by
|
|
10
|
+
[Brantner Solutions](https://brantnersolutions.com).
|
|
11
|
+
Full documentation: **[mfgqc.brantnersolutions.com](https://mfgqc.brantnersolutions.com)**.
|
|
12
|
+
|
|
13
|
+
Quality-control analysis for manufacturing practitioners, not statisticians or
|
|
14
|
+
programmers. Three pillars:
|
|
15
|
+
|
|
16
|
+
1. **Statistical guardrails.** Every analysis checks its own assumptions and
|
|
17
|
+
reports the outcome. It warns and recommends; it never silently switches
|
|
18
|
+
methods. Auto-correction is opt-in.
|
|
19
|
+
2. **Practitioner-oriented.** You bring domain knowledge; mfgQC brings the
|
|
20
|
+
statistics, data handling, and canonical charts. Errors say what's missing
|
|
21
|
+
and why.
|
|
22
|
+
3. **Auditable by construction.** `QCData` and result objects are immutable and
|
|
23
|
+
carry a structured, propagating provenance history, so the full lineage from
|
|
24
|
+
raw data to final number can be reconstructed.
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install mfgqc
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
For development (editable install with test extras):
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install -e ".[test]"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Requires Python 3.10+. Core dependencies are NumPy, pandas, SciPy, Matplotlib,
|
|
39
|
+
statsmodels, and scikit-learn.
|
|
40
|
+
|
|
41
|
+
## Use
|
|
42
|
+
|
|
43
|
+
The idiom is always the same: `load` a frame, attach metadata with `.spec()` /
|
|
44
|
+
`.roles()`, then call an analysis. Every result has `.report()` (text),
|
|
45
|
+
`.summary()` (a flat dict), `.to_dict()` (full structured payload), and `.view()`
|
|
46
|
+
(the canonical chart).
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
import pandas as pd, mfgqc
|
|
50
|
+
|
|
51
|
+
qc = (mfgqc.load(df, measure="width", subgroup="lot", subgroup_size=5)
|
|
52
|
+
.spec(lower=1.0, upper=2.0, target=1.5))
|
|
53
|
+
|
|
54
|
+
print(qc.capability()) # Cp/Cpk (within-sigma) + Pp/Ppk (overall) + assumption report
|
|
55
|
+
print(qc.control_chart()) # inferred chart, run-rules violations
|
|
56
|
+
print(qc.gage_rr()) # ANOVA gage R&R (needs part/operator/replicate roles)
|
|
57
|
+
|
|
58
|
+
fig = qc.capability().view(save="capability.png") # canonical chart (matplotlib Figure)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
To load a CSV, read it with pandas first: `mfgqc.load(pd.read_csv(path), measure=...)`.
|
|
62
|
+
|
|
63
|
+
## Provenance & auditability
|
|
64
|
+
|
|
65
|
+
This is mfgQC's reason to exist over `qcc` or Minitab: the lineage from raw data to
|
|
66
|
+
final number is recorded, immutable, and verifiable — not asserted in a doc.
|
|
67
|
+
|
|
68
|
+
**What is recorded.** Every step that derives a number appends a structured
|
|
69
|
+
provenance entry: ingest, spec/role binding, each transform (e.g. Box-Cox),
|
|
70
|
+
subgroup aggregation, the sigma method chosen, and each assumption check. The
|
|
71
|
+
chain is reconstructable end to end:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
qc = mfgqc.load(df, measure="y").spec(lower=0.1, upper=8)
|
|
75
|
+
cap = qc.transform("boxcox").capability()
|
|
76
|
+
|
|
77
|
+
[s["operation"] for s in cap.lineage()]
|
|
78
|
+
# ['load', 'spec', 'transform', 'capability', 'assumption:normality']
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Immutability guarantee (append-only by construction).** `QCData` and every
|
|
82
|
+
result are frozen dataclasses; the history is an immutable tuple of frozen steps,
|
|
83
|
+
so it cannot be reordered, inserted into, or edited in place. The ingest boundary
|
|
84
|
+
defensive-copies the input frame, `.frame` hands back a copy, and `.values()` is
|
|
85
|
+
read-only — so nothing a caller does to what mfgQC returns can reach back and
|
|
86
|
+
change a recorded result.
|
|
87
|
+
|
|
88
|
+
**Tamper-evidence (hash-chained and verifiable).** Each step folds into a
|
|
89
|
+
running SHA-256, exposed as `provenance_digest()` and stamped into `to_dict()`.
|
|
90
|
+
Capture the digest when you record a number, and re-check it later:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
digest = cap.provenance_digest() # store alongside the reported Cpk
|
|
94
|
+
cap.verify_provenance(digest) # True; flips to False if any step was edited
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**The limit, stated honestly.** The digest is a content hash, not a cryptographic
|
|
98
|
+
signature: code running in the same process could edit a step *and* recompute the
|
|
99
|
+
digest. It defends against accidental corruption and post-hoc edits to a stored
|
|
100
|
+
result, not against an adversary who controls the interpreter. One boundary is
|
|
101
|
+
explicit: once you extract the matplotlib `Figure` from `.view()`, edits to that
|
|
102
|
+
Figure are outside the lineage.
|
|
103
|
+
|
|
104
|
+
## Modules
|
|
105
|
+
|
|
106
|
+
- **Capability** — Cp/Cpk (within-subgroup sigma) vs Pp/Ppk (overall sigma), Cpm,
|
|
107
|
+
each with confidence intervals (small-n point estimates are overconfident; the
|
|
108
|
+
interval is reported so you see it); normal plus Box-Cox / Clements / Johnson
|
|
109
|
+
non-normal methods.
|
|
110
|
+
- **Control charts** — I-MR, Xbar-R, Xbar-S, p/np/c/u, EWMA, CUSUM, short-run;
|
|
111
|
+
Nelson and Western Electric run rules.
|
|
112
|
+
- **Measurement systems analysis** — ANOVA gage R&R, bias, linearity, stability,
|
|
113
|
+
attribute agreement (Cohen/Fleiss/weighted kappa).
|
|
114
|
+
- **Hypothesis testing** — assumption-routing two-sample / one-sample / variance /
|
|
115
|
+
proportion tests, one-way ANOVA, post-hoc (Tukey/Games-Howell/Dunn/Dunnett),
|
|
116
|
+
non-parametrics (Mood's median, repeated measures).
|
|
117
|
+
- **Regression & DOE** — OLS, model selection, logistic, non-linear least squares,
|
|
118
|
+
Box-Cox; full and fractional factorial design generation and effect analysis
|
|
119
|
+
(Lenth for unreplicated designs) with alias structure.
|
|
120
|
+
- **Sample size & power** — t-test, ANOVA, proportion, and variance, via the
|
|
121
|
+
noncentral distributions.
|
|
122
|
+
- **Attributes & reliability** — DPMO/sigma level, life-distribution fitting with
|
|
123
|
+
censoring, Kaplan-Meier, system reliability, bearing life (ISO 281), MTBF,
|
|
124
|
+
availability, demonstration tests.
|
|
125
|
+
- **Acceptance sampling** — single attribute plans, OC curves, ANSI/ASQ Z1.4 and
|
|
126
|
+
Z1.9.
|
|
127
|
+
|
|
128
|
+
## Method choices
|
|
129
|
+
|
|
130
|
+
The choices a practitioner needs to trust the number are explicit, not hidden:
|
|
131
|
+
|
|
132
|
+
- **Control-chart inference.** `control_chart()` with no `kind=` picks the
|
|
133
|
+
variables chart from the subgroup size: size 1 → I-MR (individuals + moving
|
|
134
|
+
range), size 2–10 → X̄-R, size > 10 → X̄-S. Pass `kind=` to override; attribute
|
|
135
|
+
charts (`p`/`np`/`c`/`u`) are always explicit.
|
|
136
|
+
- **Within-subgroup sigma (Cp/Cpk).** Equal subgroups use R̄/d₂; individuals use
|
|
137
|
+
MR̄/d₂; unequal subgroup sizes use the pooled within-subgroup standard
|
|
138
|
+
deviation. Pp/Ppk always use the overall standard deviation. The estimator
|
|
139
|
+
actually used is reported in the capability result (`sigma_used`, e.g.
|
|
140
|
+
`"within (R-bar/d2)"`).
|
|
141
|
+
|
|
142
|
+
## Building on mfgQC
|
|
143
|
+
|
|
144
|
+
mfgQC is built to be driven programmatically (e.g. by a report builder or UI):
|
|
145
|
+
|
|
146
|
+
- `mfgqc.list_analyses()` / `mfgqc.ANALYSES` — machine-readable catalog of every
|
|
147
|
+
analysis and its required inputs.
|
|
148
|
+
- `result.to_dict()` — full JSON-serializable payload (fields, assumption checks,
|
|
149
|
+
provenance); `result.summary()` is the flat form.
|
|
150
|
+
- `result.view(save="chart.png")` — headless chart rendering to PNG/SVG.
|
|
151
|
+
- `mfgqc.MissingPrerequisiteError` — specific, catchable error naming what an
|
|
152
|
+
analysis still needs.
|
|
153
|
+
|
|
154
|
+
## Documentation
|
|
155
|
+
|
|
156
|
+
Full user guide and reference (with the formula, assumptions, and source standard
|
|
157
|
+
each method is pinned to) live at
|
|
158
|
+
**[mfgqc.brantnersolutions.com](https://mfgqc.brantnersolutions.com)**.
|
|
159
|
+
|
|
160
|
+
## Tests
|
|
161
|
+
|
|
162
|
+
The suite has two layers. Regression tests pin mfgQC to its build oracles
|
|
163
|
+
(Montgomery; AIAG MSA 4th ed.; Lawson, *Design and Analysis of Experiments with
|
|
164
|
+
R*). A separate `tests/correctness/` suite pins each analysis to an **independent**
|
|
165
|
+
source it was not built against (the NIST/SEMATECH e-Handbook and StRD certified
|
|
166
|
+
datasets, the R `qcc`/`SixSigma` packages, and scipy/statsmodels computed in-test).
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
pytest
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
© Brantner Solutions · [brantnersolutions.com](https://brantnersolutions.com) · MIT License
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"""mfgQC - quality-control analysis for manufacturing practitioners.
|
|
2
|
+
|
|
3
|
+
Three design pillars: statistical guardrails (every analysis checks and reports
|
|
4
|
+
its own assumptions, never silently switching methods), practitioner-oriented
|
|
5
|
+
(legible errors, no statistics/programming background assumed), and auditable by
|
|
6
|
+
construction (immutable data and results carrying a structured, propagating
|
|
7
|
+
provenance history).
|
|
8
|
+
|
|
9
|
+
Quick start (fluent idiom: verb -> object -> methods)
|
|
10
|
+
-----------------------------------------------------
|
|
11
|
+
>>> import pandas as pd, mfgqc
|
|
12
|
+
>>> clean_df = mfgqc.clean(raw, [mfgqc.fix_names(), mfgqc.coerce_numeric(["width"])])
|
|
13
|
+
>>> data = mfgqc.load(clean_df, measure="width", subgroup="batch").spec(lower=1.0, upper=2.0)
|
|
14
|
+
>>> mfgqc.overview(data) # role/spec-aware diagnostic
|
|
15
|
+
>>> cap = data.capability() # uses the attached spec
|
|
16
|
+
>>> cc = data.control_chart()
|
|
17
|
+
>>> grr = data.gage_rr()
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from .assumptions import AssumptionCheck
|
|
23
|
+
from .capability import CapabilityResult
|
|
24
|
+
from .control_charts import ControlChartResult, Violation
|
|
25
|
+
from .data import (
|
|
26
|
+
Crossed,
|
|
27
|
+
QCData,
|
|
28
|
+
QCMeta,
|
|
29
|
+
Step,
|
|
30
|
+
Subgroups,
|
|
31
|
+
from_wide,
|
|
32
|
+
load,
|
|
33
|
+
)
|
|
34
|
+
from .gage_rr import GageRRResult
|
|
35
|
+
from .hypothesis import (
|
|
36
|
+
HypothesisResult,
|
|
37
|
+
test_anova,
|
|
38
|
+
test_mean,
|
|
39
|
+
test_means,
|
|
40
|
+
test_paired,
|
|
41
|
+
test_proportion,
|
|
42
|
+
test_proportions,
|
|
43
|
+
test_variance,
|
|
44
|
+
)
|
|
45
|
+
from .ingestion import (
|
|
46
|
+
Overview,
|
|
47
|
+
clean,
|
|
48
|
+
clean_report,
|
|
49
|
+
coerce_numeric,
|
|
50
|
+
drop,
|
|
51
|
+
drop_constant,
|
|
52
|
+
drop_duplicates,
|
|
53
|
+
fix_names,
|
|
54
|
+
normalize_case,
|
|
55
|
+
overview,
|
|
56
|
+
parse_dates,
|
|
57
|
+
recode_empty,
|
|
58
|
+
recode_missing,
|
|
59
|
+
rename,
|
|
60
|
+
select,
|
|
61
|
+
standard_tidy,
|
|
62
|
+
)
|
|
63
|
+
from .msa import BiasResult, LinearityResult, StabilityResult
|
|
64
|
+
from .palette import set_theme
|
|
65
|
+
from .pareto_analysis import ContingencyResult, ParetoResult, contingency, pareto, test_independence
|
|
66
|
+
from .regression import (
|
|
67
|
+
AnovaResult,
|
|
68
|
+
CorrelationResult,
|
|
69
|
+
RegressionResult,
|
|
70
|
+
correlation,
|
|
71
|
+
)
|
|
72
|
+
from .sampling import (
|
|
73
|
+
AOQResult,
|
|
74
|
+
LotDisposition,
|
|
75
|
+
OCCurveResult,
|
|
76
|
+
SamplingPlan,
|
|
77
|
+
Z19Disposition,
|
|
78
|
+
Z19Plan,
|
|
79
|
+
find_plan,
|
|
80
|
+
sampling_plan,
|
|
81
|
+
z14_plan,
|
|
82
|
+
z19_plan,
|
|
83
|
+
)
|
|
84
|
+
from .timeseries_charts import CUSUMResult, EWMAResult
|
|
85
|
+
from . import doe as design
|
|
86
|
+
from .doe import DOEResult, Design, LenthResult
|
|
87
|
+
from . import power
|
|
88
|
+
from .power import PowerResult
|
|
89
|
+
from .process_sigma import ProcessSigmaResult, compute as process_sigma
|
|
90
|
+
from .attribute_agreement import AttributeAgreementResult
|
|
91
|
+
from .posthoc import PosthocResult
|
|
92
|
+
from .nonparametric import test_medians, test_repeated
|
|
93
|
+
from .precontrol import PrecontrolResult
|
|
94
|
+
from .regression_ext import LogisticResult, NonlinearResult
|
|
95
|
+
from .timeseries import TimeSeriesResult
|
|
96
|
+
from .multivari import MultivariResult
|
|
97
|
+
from . import reliability
|
|
98
|
+
from .reliability.availability import availability
|
|
99
|
+
from .reliability import (
|
|
100
|
+
LifeFitResult,
|
|
101
|
+
KaplanMeierResult,
|
|
102
|
+
SystemReliabilityResult,
|
|
103
|
+
BearingLifeResult,
|
|
104
|
+
AvailabilityResult,
|
|
105
|
+
MTBFResult,
|
|
106
|
+
DemonstrationResult,
|
|
107
|
+
)
|
|
108
|
+
from .errors import MissingPrerequisiteError, PyQCError
|
|
109
|
+
from .registry import ANALYSES, ANALYSES_BY_NAME, Analysis, list_analyses
|
|
110
|
+
|
|
111
|
+
__version__ = "0.1.0"
|
|
112
|
+
|
|
113
|
+
__all__ = [
|
|
114
|
+
# fluent entry points
|
|
115
|
+
"load",
|
|
116
|
+
"from_wide",
|
|
117
|
+
"overview",
|
|
118
|
+
"clean",
|
|
119
|
+
"clean_report",
|
|
120
|
+
# data model
|
|
121
|
+
"QCData",
|
|
122
|
+
"QCMeta",
|
|
123
|
+
"Step",
|
|
124
|
+
"Subgroups",
|
|
125
|
+
"Crossed",
|
|
126
|
+
"Overview",
|
|
127
|
+
"AssumptionCheck",
|
|
128
|
+
# cleaning tasks
|
|
129
|
+
"fix_names",
|
|
130
|
+
"coerce_numeric",
|
|
131
|
+
"parse_dates",
|
|
132
|
+
"recode_missing",
|
|
133
|
+
"recode_empty",
|
|
134
|
+
"drop_constant",
|
|
135
|
+
"drop_duplicates",
|
|
136
|
+
"select",
|
|
137
|
+
"drop",
|
|
138
|
+
"rename",
|
|
139
|
+
"normalize_case",
|
|
140
|
+
"standard_tidy",
|
|
141
|
+
# results
|
|
142
|
+
"CapabilityResult",
|
|
143
|
+
"ControlChartResult",
|
|
144
|
+
"Violation",
|
|
145
|
+
"GageRRResult",
|
|
146
|
+
"HypothesisResult",
|
|
147
|
+
"BiasResult",
|
|
148
|
+
"LinearityResult",
|
|
149
|
+
"StabilityResult",
|
|
150
|
+
"RegressionResult",
|
|
151
|
+
"AnovaResult",
|
|
152
|
+
"CorrelationResult",
|
|
153
|
+
"ParetoResult",
|
|
154
|
+
"ContingencyResult",
|
|
155
|
+
"EWMAResult",
|
|
156
|
+
"CUSUMResult",
|
|
157
|
+
# hypothesis tests
|
|
158
|
+
"test_mean",
|
|
159
|
+
"test_means",
|
|
160
|
+
"test_paired",
|
|
161
|
+
"test_anova",
|
|
162
|
+
"test_variance",
|
|
163
|
+
"test_proportion",
|
|
164
|
+
"test_proportions",
|
|
165
|
+
# regression / ANOVA / correlation
|
|
166
|
+
"correlation",
|
|
167
|
+
# Pareto + contingency
|
|
168
|
+
"pareto",
|
|
169
|
+
"contingency",
|
|
170
|
+
"test_independence",
|
|
171
|
+
# acceptance sampling
|
|
172
|
+
"sampling_plan",
|
|
173
|
+
"find_plan",
|
|
174
|
+
"set_theme",
|
|
175
|
+
"z14_plan",
|
|
176
|
+
"z19_plan",
|
|
177
|
+
"SamplingPlan",
|
|
178
|
+
"OCCurveResult",
|
|
179
|
+
"AOQResult",
|
|
180
|
+
"LotDisposition",
|
|
181
|
+
"Z19Plan",
|
|
182
|
+
"Z19Disposition",
|
|
183
|
+
# design of experiments
|
|
184
|
+
"design",
|
|
185
|
+
"DOEResult",
|
|
186
|
+
"Design",
|
|
187
|
+
"LenthResult",
|
|
188
|
+
# sample size & power
|
|
189
|
+
"power",
|
|
190
|
+
"PowerResult",
|
|
191
|
+
# attributes capability
|
|
192
|
+
"process_sigma",
|
|
193
|
+
"ProcessSigmaResult",
|
|
194
|
+
# attribute agreement (kappa)
|
|
195
|
+
"AttributeAgreementResult",
|
|
196
|
+
# multiple comparisons & nonparametrics
|
|
197
|
+
"PosthocResult",
|
|
198
|
+
"test_medians",
|
|
199
|
+
"test_repeated",
|
|
200
|
+
# SPC additions
|
|
201
|
+
"PrecontrolResult",
|
|
202
|
+
# regression additions
|
|
203
|
+
"LogisticResult",
|
|
204
|
+
"NonlinearResult",
|
|
205
|
+
# time-series & multi-vari
|
|
206
|
+
"TimeSeriesResult",
|
|
207
|
+
"MultivariResult",
|
|
208
|
+
# reliability & maintainability
|
|
209
|
+
"reliability",
|
|
210
|
+
"availability",
|
|
211
|
+
"LifeFitResult",
|
|
212
|
+
"KaplanMeierResult",
|
|
213
|
+
"SystemReliabilityResult",
|
|
214
|
+
"BearingLifeResult",
|
|
215
|
+
"AvailabilityResult",
|
|
216
|
+
"MTBFResult",
|
|
217
|
+
"DemonstrationResult",
|
|
218
|
+
# errors
|
|
219
|
+
"PyQCError",
|
|
220
|
+
"MissingPrerequisiteError",
|
|
221
|
+
# analysis registry (for frontends)
|
|
222
|
+
"ANALYSES",
|
|
223
|
+
"ANALYSES_BY_NAME",
|
|
224
|
+
"Analysis",
|
|
225
|
+
"list_analyses",
|
|
226
|
+
"__version__",
|
|
227
|
+
]
|