codex/ruby-pressure-calibration-uncertainty.py

ruby-pressure-calibration-uncertainty.py
"""Plot an original synthetic shift calibration and its uncertainty budget.

Tested with Python 3.14, matplotlib 3.10.7 and numpy 2.3.5.
Run from _media; the output is written into the current directory.
"""
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np


def main():
    plt.rcParams.update({'font.size': 11, 'axes.spines.top': False, 'axes.spines.right': False})
    shifts = np.array([1., 2., 3.])
    reference = np.array([2.69, 5.42, 8.09])
    slope = shifts @ reference / (shifts @ shifts)
    delta = 2.0
    ua, ul, u0, k_t, ut = 0.020, 0.010, 0.010, 0.010, 0.50
    components = np.array([delta*ua, slope*ul, slope*u0, slope*k_t*ut])
    total = np.linalg.norm(components)
    fig, (cal, err) = plt.subplots(1, 2, figsize=(11.5, 6.0), facecolor='white',
                                  gridspec_kw={'width_ratios': [1.05, 1]})
    fig.subplots_adjust(left=0.075, right=0.965, bottom=0.26, top=0.77, wspace=0.56)
    fig.suptitle('A synthetic ruby-pressure calibration and uncertainty budget', fontsize=17, y=0.97)
    fig.text(0.5, 0.89, 'All points, sensitivities and uncertainties are stipulated; no historical measurements are plotted.',
             ha='center', fontsize=10)
    xx = np.linspace(0, 3.3, 200)
    cal.plot(xx, slope*xx, color='#246c9a', lw=2, label='Fit through reference zero')
    cal.scatter(shifts, reference, color='#152c3e', s=48, zorder=4, label='Synthetic reference points')
    cal.plot([delta, delta], [0, slope*delta], color='#b72e55', ls=':')
    cal.plot([0, delta], [slope*delta, slope*delta], color='#b72e55', ls=':')
    cal.scatter([delta], [slope*delta], facecolors='white', edgecolors='#b72e55', s=120, linewidths=2, zorder=5)
    cal.annotate('Chosen reading\n2.00 nm → 5.40 GPa', xy=(delta, slope*delta),
                 xytext=(0.25, 7.65), fontsize=11,
                 arrowprops={'arrowstyle': '->', 'color': '#b72e55'}, color='#b72e55')
    cal.text(0.18, 0.62, 'a = 2.70 GPa/nm', fontsize=12, color='#246c9a')
    cal.set(xlim=(0, 3.35), ylim=(0, 9.3), xlabel='Corrected line shift D (nm)', ylabel='Pressure relative to reference (GPa)')
    cal.legend(loc='upper left', bbox_to_anchor=(-0.015, -0.16), frameon=False, fontsize=9)
    cal.set_title('Response fit', loc='left', fontsize=13, pad=12)
    labels = ['Slope calibration', 'Loaded line position', 'Reference line position', 'Temperature correction', 'Combined standard uncertainty']
    values = np.r_[components, total]
    colors = ['#246c9a', '#4d8b40', '#88ad6c', '#d09b34', '#b72e55']
    bars = err.barh(np.arange(5), values, color=colors, height=0.58)
    err.invert_yaxis()
    err.set(yticks=np.arange(5), yticklabels=labels, xlim=(0, .071), xlabel='Standard contribution (GPa)')
    err.set_xticks([0, .02, .04, .06])
    err.tick_params(axis='y', labelsize=9)
    for b, v in zip(bars, values):
        err.text(v+.0014, b.get_y()+b.get_height()/2, f'{v:.4f}', va='center', fontsize=10)
    err.set_title('Independent contributions', loc='left', fontsize=13, pad=12)
    fig.text(0.75, 0.12, r'$u_p=\sqrt{0.0400^2+0.0270^2+0.0270^2+0.0135^2}$', ha='center', fontsize=11)
    fig.text(0.75, 0.065, 'Standard uncertainty ≠ a specified confidence interval', ha='center', fontsize=10)
    fig.savefig(Path.cwd() / (Path(__file__).stem+'.png'), dpi=100, facecolor='white')
    plt.close(fig)


if __name__ == '__main__':
    main()