codex/bioassay-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()