A small bash tool for computing GUM-style measurement uncertainty budgets for
dimensional gauges, driven by plain-text .conf files. All arithmetic goes
through bc(1), so there are no floating-point surprises at the precisions
typical of gauge calibration (single-digit micro-inches).
Given a config file listing a measurand and a set of independent uncertainty contributors (each with a stated value, a probability distribution, and a divisor), UncertCalc:
- Converts each contributor's stated value to a standard uncertainty
u_i = value / divisor. - Combines them by root-sum-square:
u_c = sqrt(Σ u_i²). - Looks up (or accepts) a coverage factor
kand reports the expanded uncertaintyU = k · u_c. - Prints a fixed-column budget table with per-contributor
u_iand percent contribution, flagging the dominant component.
Methodology follows the GUM (JCGM 100:2008): RSS combination of independent
standard uncertainties, with the large-DoF normal approximation for the
coverage factor (90 % → 1.645, 95 % → 2.000, 99 % → 2.576). Welch–Satterthwaite
and Type-A/B effective DoF tracking are not implemented; supply a literal k
to override the preset if your situation calls for it.
- bash 4 or newer (uses
[[ ... ]], regex matching, indexed arrays) bcwith the-lmath library (providessqrt,l(), etc.)
Both are present in every mainstream Linux/macOS install.
git clone <repo>
cd UncertCalc
chmod +x uncertcalc.shThat's the whole install. Run it as ./uncertcalc.sh <config> or symlink it
into your $PATH.
./uncertcalc.sh <config.conf> [options]
| Flag | Argument | Effect |
|---|---|---|
-k |
90 | 95 | 99 | <decimal> |
Coverage selector. 90/95/99 map to GUM presets; a decimal passes through as a literal k. Overrides coverage = in the config. |
-r |
<result> |
Measured result for the guard-banded decision rule. Must be paired with -t. Requires nominal in the config. See Decision rule. |
-t |
<tolerance> |
Symmetric tolerance half-width (so the spec is nominal ± tolerance) for the decision rule. Must be paired with -r and strictly positive. |
--no-color |
— | Suppress ANSI color codes on stdout, including the verdict color in the decision block. Implied when writing to a file with -o. |
--sigfigs |
<N> |
Significant figures used to round u_c, U, and every value in the decision block for display (default 4). |
-o |
<path> |
Write the budget (and decision block, if any) to <path> instead of stdout. Always plain text (no ANSI). |
--force |
— | With -o, overwrite an existing file without prompting. Without --force, an existing target triggers a [y/N] prompt and a N exits 0 without writing. |
-h, --help |
— | Print usage and exit 0. |
Comments start with #. The top of the file holds the header fields:
measurand = Thread Plug Gauge Pitch Diameter
unit = in # in | mm
nominal = 0.4675 # optional; required when using the -r/-t decision rule
coverage = 95% # 90% | 95% | 99% | <decimal k>; optional, overridden by -kUnknown header keys produce a stderr warning but do not abort parsing, so a config authored against a newer schema still loads against an older parser. Unknown contributor keys remain a hard error.
Each contributor is an [section] with five fields:
[reference_standard]
name = Reference Standard
type = B # A | B (informational; A/B otherwise warns)
value = 0.000100 # stated half-width / std dev / cert U
distribution = normal # normal | rectangular | triangular | u-shaped
divisor = 2 # GUM divisor for the chosen distribution| Code | Meaning |
|---|---|
| 0 | Success (including user declining an -o overwrite prompt; also includes the guard-band-collapse case, which prints a stderr warning and forces FAIL) |
| 1 | Usage error: missing config arg, file not found, bad unit, bad -k, bad --sigfigs, unknown flag, write error, -r/-t mismatch, non-numeric or non-positive -r/-t, missing nominal when the decision rule is invoked |
| 2 | Config parse / validation error: grammar, missing key, non-numeric value, empty file |
| 3 | Arithmetic error: divisor of zero |
When you also need a PASS/FAIL/INCONCLUSIVE statement of conformity, pass the
measured result with -r and a symmetric tolerance half-width with -t. The
config must include a nominal header. UncertCalc applies the ILAC P14:01/2022
simple guard band with w = U (clause 4.1):
- Simple acceptance zone:
[nominal − T, nominal + T] - Guard-banded acceptance zone:
[nominal − T + U, nominal + T − U] - PASS — result inside the guard-banded zone (true value is within tolerance at the chosen coverage)
- FAIL — result outside the simple acceptance zone
- INCONCLUSIVE — result inside the guard band itself (between the guard-banded boundary and the simple boundary; risk of misclassification exceeds the chosen coverage)
A TUR = T / U line is reported for context. When U ≥ T the guard band
collapses and a PASS verdict is unreachable for any result; UncertCalc emits a
stderr warning, forces the verdict to FAIL, and still exits 0 so the budget
and decision block can be archived as evidence.
The verdict is rendered in color (green/red/yellow) on stdout and suppressed by
--no-color or -o. The decision and zone math run against the full-precision
U; per-display rounding (via --sigfigs) cannot move a verdict across a
boundary.
Clause 7.8.6 requires that any statement of conformity to a specification
documents the decision rule used and accounts for the level of risk it carries.
The output above (rule name, ILAC reference, guard-band width w, both zones,
TUR, and the verdict) is intended to satisfy that documentation requirement
on its own when archived alongside the calibration record. UncertCalc takes
no position on what tolerance, coverage, or guard-band width is appropriate
for your accreditation scope — those remain your lab's decisions.
jobs/ring_go_3-8-16_2B_20260516.conf is a calibration of a GO thread ring
gauge against a calibrated setting plug on a horizontal comparator. With a
measured pitch diameter of 0.3330 in and a ±0.0005 in tolerance:
$ ./uncertcalc.sh jobs/ring_go_3-8-16_2B_20260516.conf -r 0.3330 -t 0.0005 --no-color
Uncertainty Budget: GO Thread Ring Gauge 3/8-16 UNC 2B
Component Type Value Distribution Divisor u_i %
---------------------------------------------------------------------------------------
Setting Plug Cal Cert B 0.000100 normal 2.000000 0.000050 24.44
Thermal Expansion B 0.000058 rectangular 1.732051 0.000033 10.96
* Comparator R&R A 0.000080 normal 1.000000 0.000080 62.56
Comparator Resolution B 0.000025 rectangular 1.732051 0.000014 2.04
---------------------------------------------------------------------------------------
* dominant component
Combined standard uncertainty u_c = 0.0001011 in
Coverage 95% (k = 2.000)
Expanded uncertainty U = 0.0002023 in
Decision Rule (ILAC P14:01/2022, simple guard band, w = U)
Nominal N = 0.3331 in
Tolerance T = 0.0005000 in
Result y = 0.3330 in
Expanded uncertainty U = 0.0002023 in
Deviation from nominal y-N = -0.0001000 in
Simple acceptance zone [0.3326, 0.3336] in
Guard-banded acceptance zone [0.3328, 0.3334] in
Test Uncertainty Ratio TUR = 2.472
Verdict PASSThe TUR of 2.47 means the tolerance is about 2.5× the expanded uncertainty — adequate but not generous. The measured 0.3330 falls inside the guard-banded zone with about 0.0002 in of headroom against the lower boundary, so a true value within tolerance is the most defensible conclusion at 95 % coverage.
Omit -r and -t to get just the v1 budget table — the decision block is
skipped entirely and the rest of the output is byte-for-byte unchanged.
uncertcalc.sh # Entry point: argv parsing and orchestration
lib/parse.sh # .conf parser + validator
lib/math.sh # rss, percent_contribution, sig_round (bc-backed)
lib/coverage.sh # 90/95/99% → k preset lookup
lib/decision.sh # Guard-banded decision rule, zones, TUR
lib/output.sh # Table + decision-block formatter and file writer
examples/
thread_plug.conf # Thread plug gauge (three-wire method)
ring_gauge.conf # Setting ring gauge ID (comparator vs gauge blocks)
jobs/
ring_go_3-8-16_2B_20260516.conf # Worked example used in this README
tests/
test_uncertcalc.sh # Bash test suite (no external framework)
bash tests/test_uncertcalc.sh- JCGM 100:2008 — Evaluation of measurement data — Guide to the expression of uncertainty in measurement (GUM).
- ILAC P14:01/2022 — Policy for Uncertainty in Calibration; clause 4.1 describes the simple guard-band decision rule used here.
- ISO/IEC 17025:2017 — General requirements for the competence of testing and calibration laboratories; clause 7.8.6 covers reporting statements of conformity to specifications, including the decision rule.