codexdye-loss-interaction-scale.py
dye-loss-interaction-scale.py
"""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)