codexsynthetic-insulin-glucagon-step-response.py
synthetic-insulin-glucagon-step-response.py
"""Original synthetic response model; Python 3.14 / numpy 2.3.5 / matplotlib 3.10.7.
All parameters and curves are invented teaching examples, never measurements.
Glucose stimulus is imposed externally, not generated by a closed glucose balance.
Run from _media with MPLBACKEND=Agg and MPLCONFIGDIR=/tmp/codex-wiki-matplotlib.
The output is a same-basename opaque PNG in the current working directory.
"""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
SEGMENTS = ((0.0, 10.0, 1.0), (10.0, 40.0, 1.6),
(40.0, 70.0, 0.65), (70.0, 100.0, 1.0))
TAU_INSULIN = 4.0
TAU_GLUCAGON = 6.0
def targets(g):
return g**4 / (1.0 + g**4), 1.0 / (1.0 + g**4)
def response():
"""Exact solutions per constant-input interval; duplicate boundary samples.
Duplicate times show stimulus jumps while hormone responses stay continuous.
"""
initial_i = initial_h = 0.5
series = []
for begin, end, g in SEGMENTS:
t = np.linspace(begin, end, round((end - begin) / 0.05) + 1)
target_i, target_h = targets(g)
i = target_i + (initial_i - target_i) * np.exp(-(t - begin) / TAU_INSULIN)
h = target_h + (initial_h - target_h) * np.exp(-(t - begin) / TAU_GLUCAGON)
series.append(np.column_stack((t, np.full_like(t, g), i, h)))
initial_i, initial_h = i[-1], h[-1]
return np.concatenate(series)
def tendencies(g, i, h):
return 0.3 + 0.6 * h / (1.0 + i), (0.25 + 0.5 * i) * g
def draw():
t, g, i, h = response().T
release, uptake = tendencies(g, i, h)
fig, axes = plt.subplots(3, 1, figsize=(11, 9), dpi=110, sharex=True,
gridspec_kw={"height_ratios": [0.85, 1.25, 1.25]})
fig.patch.set_facecolor("white")
fig.suptitle("Synthetic insulin–glucagon response to imposed glucose steps",
fontsize=16, weight="bold", y=0.98)
fig.text(0.5, 0.935, "Invented parameters • arbitrary units • no biological measurements or fitted data",
ha="center", fontsize=11)
axes[0].plot(t, g, color="#444e58", lw=2.2)
axes[0].set_ylabel("Imposed stimulus g\n(dimensionless)")
axes[0].set(ylim=(0.4, 1.8), yticks=[0.65, 1.0, 1.6])
axes[0].text(5, 1.18, "Reference", ha="center", fontsize=10)
axes[0].text(17, 1.28, "Higher stimulus", fontsize=10)
axes[0].text(46, 1.28, "Lower stimulus", fontsize=10)
axes[0].text(78, 1.57, "Reference restored", fontsize=10)
axes[1].plot(t, i, color="#176398", lw=2.2, label="Insulin response I (τ = 4)")
axes[1].plot(t, h, color="#ac5319", lw=2.2, label="Glucagon response H (τ = 6)")
axes[1].set_ylabel("Normalized response\n(arbitrary units)")
axes[1].set_ylim(0, 1.05)
axes[1].legend(loc="upper right", fontsize=10, framealpha=1)
axes[2].plot(t, release, color="#80613f", lw=2.2, label="Release tendency R")
axes[2].plot(t, uptake, color="#288568", lw=2.2, label="Uptake tendency U")
axes[2].set_ylabel("Illustrative tendencies\n(arbitrary flux units)")
axes[2].set_ylim(0, 1.32)
axes[2].legend(loc="upper right", fontsize=10, framealpha=1)
axes[2].set_xlabel("Time (arbitrary units)")
for ax in axes:
ax.set_facecolor("white")
ax.set_xlim(0, 100)
ax.spines[["top", "right"]].set_visible(False)
ax.grid(axis="y", color="#e3e7eb", lw=0.6)
for boundary in [10, 40, 70]:
ax.axvline(boundary, color="#adb5bd", ls="--", lw=0.8, zorder=0)
fig.text(0.5, 0.022, "Glucose is prescribed: these curves do not demonstrate self-correction of blood glucose.",
ha="center", fontsize=11)
fig.subplots_adjust(left=0.13, right=0.98, top=0.89, bottom=0.09, hspace=0.25)
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
draw()