codexatp-energy-coupling.py
atp-energy-coupling.py
"""Draw cumulative reaction free-energy changes, not activation barriers.
Tested with Python 3.14.4 and the repository's Matplotlib/NumPy environment.
Write an opaque white same-basename PNG to cwd, as required by Makefile.
All contributions use the same stipulated biochemical standard conditions.
"""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
def main():
uphill, hydrolysis = 20.0, -30.5
net = uphill + hydrolysis
ink, orange, blue = "#24333d", "#ad5516", "#19678d"
fig, ax = plt.subplots(figsize=(7.6, 5.4))
fig.set_facecolor("white")
ax.set_facecolor("white")
fig.subplots_adjust(left=0.14, right=0.96, top=0.78, bottom=0.30)
levels = [0.0, uphill, net]
for x, value, color in zip(range(3), levels, [ink, orange, blue]):
ax.plot([x - 0.26, x + 0.26], [value, value], color=color,
linewidth=3.5, solid_capstyle="round")
ax.text(x, value + 2.0, f"{value:+g}" if value else "0",
ha="center", va="bottom", fontsize=13, color=color,
weight="bold")
for x, start, end, color in [
(0.55, 0.0, uphill, orange),
(1.55, uphill, net, blue),
]:
ax.annotate("", xy=(x, end), xytext=(x, start),
arrowprops={"arrowstyle": "-|>", "color": color,
"lw": 2, "mutation_scale": 15})
ax.plot([0.26, 0.74], [0, 0], ":", color="#8d989f", lw=1.1)
ax.plot([1.26, 1.74], [uphill, uphill], ":", color="#8d989f", lw=1.1)
ax.text(0.61, 10, "+20", color=orange, ha="left", va="center", fontsize=12)
ax.text(1.61, 5, "−30.5", color=blue, ha="left", va="center", fontsize=12)
ax.axhline(0, color="#b3bdc3", linewidth=0.7, zorder=0)
ax.set(xlim=(-0.4, 2.4), ylim=(-16, 27),
ylabel="Cumulative ΔG°′ (kJ/mol)", yticks=[-10.5, 0, 10, 20],
xticks=[0, 1, 2],
xticklabels=["Reference", "Add A → B", "Add ATP hydrolysis"])
ax.tick_params(axis="both", labelsize=10)
ax.spines[["top", "right"]].set_visible(False)
fig.text(0.55, 0.94, "Free-energy changes add", ha="center", fontsize=16,
color=ink, weight="bold")
fig.text(0.55, 0.875, "Same stipulated conditions: +20 − 30.5 = −10.5 kJ/mol",
ha="center", fontsize=11.5, color=ink)
fig.text(0.55, 0.17, "A shared reaction mechanism must couple the transformations",
ha="center", fontsize=11, color=ink,
bbox={"facecolor": "#edf5f8", "edgecolor": blue, "pad": 7})
fig.text(0.55, 0.07, "Bookkeeping steps only: no pathway, intermediates, or barriers shown",
ha="center", fontsize=9.5, color="#53616a")
fig.savefig(Path(__file__).with_suffix(".png").name, dpi=140,
facecolor="white", transparent=False)
plt.close(fig)
print(f"Stipulated ΔG°′ contributions: {uphill:+g}, {hydrolysis:+g}; net: {net:+g} kJ/mol")
if __name__ == "__main__":
main()