codexbioassay-parallelism.py
bioassay-parallelism.py
"""Original response-shape comparison; Python 3.14, NumPy 2.3.5, Matplotlib 3.10.7.
Run from the output directory; writes bioassay-parallelism.png to cwd.
All concentrations and responses are stipulated mathematical examples.
"""
from pathlib import Path
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
def main():
x = np.geomspace(0.1, 1000, 600)
reference = x / (10 + x)
parallel_test = x / (5 + x)
different_slope = x**2 / (100 + x**2)
fig, axes = plt.subplots(1, 2, figsize=(9, 3.8), dpi=120, facecolor='white')
for ax in axes:
ax.set_xscale('log')
ax.set_xlim(0.1, 1000)
ax.set_ylim(0, 1.03)
ax.set_xlabel('Concentration (arbitrary units)')
ax.set_ylabel('Normalized response')
ax.plot(x, reference, color='#225ea8', label='Reference')
ax.grid(alpha=0.2)
axes[0].plot(x, parallel_test, color='#b44d2b', label='Test: shared shape')
axes[0].axhline(0.5, color='grey', lw=0.8, ls='--')
axes[0].scatter([5, 10], [0.5, 0.5], color=['#b44d2b', '#225ea8'], zorder=4)
axes[0].annotate('Equal-effect concentration ratio = 2', xy=(7, 0.5),
xytext=(0.05, 0.21), textcoords='axes fraction', fontsize=8.5,
arrowprops={'arrowstyle': '->', 'color': '0.3'})
axes[0].set_title('Parallel on log concentration')
axes[1].plot(x, different_slope, color='#b44d2b', label='Test: different slope')
for response, ratio in [(0.2, 0.5), (0.8, 2)]:
xr = 10 * response / (1 - response)
xt = 10 * np.sqrt(response / (1 - response))
axes[1].hlines(response, min(xr, xt), max(xr, xt), color='0.35', lw=1.5)
axes[1].scatter([xr, xt], [response, response],
color=['#225ea8', '#b44d2b'], zorder=4)
axes[1].text(0.13, response + 0.03, f'Equal-effect ratio = {ratio:g}', fontsize=8.5)
axes[1].set_title('Different slopes: ratio depends on response')
for ax in axes:
ax.legend(loc='lower right', fontsize=8)
fig.suptitle('Equal-effect ratios need a shared response shape', fontsize=12)
fig.tight_layout(rect=(0, 0, 1, 0.95))
fig.savefig(Path('bioassay-parallelism.png'), facecolor='white', dpi=120)
plt.close(fig)
if __name__ == '__main__':
main()