"""Response-scale interaction in an additive-rate dye-loss toy model. Tested with Python 3.14 and the root NumPy/Matplotlib dependencies. Run in the output directory; writes a white PNG to cwd. """ from pathlib import Path import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt alpha = beta = .1 rates = np.array([0., alpha, beta, alpha+beta]) losses = -np.expm1(-rates) t = np.linspace(0, 8, 401) contrast = -(-np.expm1(-alpha*t))*(-np.expm1(-beta*t)) fig, axes = plt.subplots(1, 2, figsize=(8, 3.5), dpi=120) fig.patch.set_facecolor('white') ax = axes[0] ax.bar(range(4), losses, color=['#8c8c8c','#4477aa','#55a68c','#b36532']) ax.set_xticks(range(4), ['Neither','Initiation','Light','Both'], fontsize=8) ax.set_ylabel('Fractional loss at time 1') ax.set_ylim(0,.225) ax.set_title('Additive rates, nonadditive losses', fontsize=11) for j, y in enumerate(losses): ax.text(j,y+.006,f'{y:.3f}',ha='center',fontsize=9) ax = axes[1] ax.plot(t,contrast, color='#b36532', label='Fractional-loss contrast') ax.axhline(0, color='#4477aa', ls='--', label='Rate contrast (zero)') ax.plot([1],[contrast[np.argmin(abs(t-1))]],'o',color='#b36532',ms=4) ax.set_xlabel('Time (arbitrary unit)') ax.set_ylabel('Interaction contrast') ax.set_title(r'$k_{ij}=0.1i+0.1j$; no rate interaction',fontsize=11) ax.legend(fontsize=8,loc='lower left') for ax in axes: ax.set_facecolor('white') ax.grid(axis='y',alpha=.15) ax.set_axisbelow(True) fig.suptitle('The measurement scale changes the interaction contrast',fontsize=12) fig.tight_layout(rect=(0,0,1,.93)) fig.savefig(Path.cwd()/'dye-loss-interaction-scale.png',facecolor='white') plt.close(fig)