codexgravimetric-dilution-uncertainty.py
gravimetric-dilution-uncertainty.py
"""Original first-order uncertainty model for mass-based dilution; PNG to cwd."""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
def main():
factors = np.geomspace(1, 1000, 400)
f = 1 / factors
total_mass, mass_uncertainty, stock_relative = 20.0, 0.001, 0.005
# The total is nominal across examples; component-mass errors are independent.
weighing = mass_uncertainty / (total_mass * f) * np.sqrt((1-f)**2 + f**2)
combined = np.hypot(weighing, stock_relative)
at_ten = 0.001 / 2 * np.sqrt(0.9**2 + 0.1**2)
assert np.isclose(at_ten, 0.0004527692569068709)
fig, ax = plt.subplots(figsize=(8, 5), dpi=100, facecolor="white")
fig.subplots_adjust(left=0.12, right=0.97, top=0.76, bottom=0.24)
fig.suptitle("Strong dilution magnifies an independent weighing contribution",
y=0.96, fontsize=13, weight="bold", color="#172330")
fig.text(0.5, 0.88, "Chosen model: nominal final mass 20 g; each net mass has 1 mg standard uncertainty",
ha="center", fontsize=10, color="#45535d")
ax.loglog(factors, 100*weighing, color="#216c9b", linewidth=2.3,
label="Component-mass contribution")
ax.loglog(factors, 100*combined, color="#b45335", linewidth=2.3,
label="Combined with stock-value uncertainty")
ax.axhline(100*stock_relative, color="#71818b", linestyle=":", linewidth=1.7,
label="Assumed stock-value contribution: 0.5%")
ax.plot(10, 100*at_ten, "o", color="#216c9b", markersize=5)
ax.annotate("F = 10: 0.0453%", (10, 100*at_ten), (16, 0.018),
fontsize=10, color="#216c9b",
arrowprops={"arrowstyle": "-", "color": "#216c9b"})
ax.set_xlim(1, 1000)
ax.set_ylim(0.003, 10)
ax.set_xlabel(r"Nominal gravimetric dilution factor $F=1/f$", fontsize=11)
ax.set_ylabel("Relative standard uncertainty (%)", fontsize=11)
ax.grid(which="major", color="#dce4e9", linewidth=0.7)
ax.legend(loc="upper left", fontsize=9, framealpha=0.96)
fig.text(0.5, 0.075, "Illustrative first-order model, not measured balance performance.\n"
"A shared multiplicative mass-scale error cancels from the ratio; it is not this independent contribution.",
ha="center", fontsize=9.5, color="#45535d")
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=100,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()