codexeukaryotic-cell-compartments.py
eukaryotic-cell-compartments.py
"""Original compartment schematic; writes same-basename PNG in the CWD.
Tested with Python 3.14.4, NumPy 2.3.5, Matplotlib 3.10.7.
All sizes, positions and component counts are illustrative, not measurements.
"""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Ellipse
import numpy as np
def label(ax, text, target, position, color="#243447", align="center"):
ax.annotate(text, xy=target, xytext=position, ha=align, va="center",
color=color, fontsize=11,
arrowprops={"arrowstyle": "-", "color": color, "lw": 1.2})
def main():
fig, ax = plt.subplots(figsize=(8.2, 5.6))
fig.patch.set_facecolor("white")
ax.add_patch(Ellipse((0, 0), 6.5, 4.2, facecolor="#eaf5fb",
edgecolor="#267e9e", lw=2.8))
center = (-0.75, 0.15)
ax.add_patch(Circle(center, 1.20, facecolor="#faf1ff",
edgecolor="#79519b", lw=2))
ax.add_patch(Circle(center, 1.10, facecolor="#faf1ff",
edgecolor="#79519b", lw=1.7))
x = np.linspace(-1.38, -0.18, 140)
for offset in (0.73, 0.36, -0.37):
ax.plot(x, offset + 0.085 * np.sin(12 * x), color="#9a64b2", lw=2)
ax.add_patch(Circle((-0.83, -0.04), 0.22, facecolor="#c994db",
edgecolor="#79519b", lw=1))
# An illustrative pore crosses both membranes at the right edge.
ax.plot([0.32, 0.46], [0.22, 0.22], color="white", lw=9)
ax.plot([0.30, 0.49], [0.30, 0.30], color="#4c5260", lw=3)
ax.plot([0.30, 0.49], [0.13, 0.13], color="#4c5260", lw=3)
ax.add_patch(Ellipse((1.75, -0.50), 1.25, 0.70, angle=18,
facecolor="#fff0cf", edgecolor="#b17816", lw=2))
t = np.linspace(-0.44, 0.44, 120)
ax.plot(1.75 + t, -0.50 + 0.18 * t + 0.13 * np.sin(22 * t),
color="#b17816", lw=1.8)
points = [(-2.45, 0.2), (-2.1, -0.95), (-0.25, -1.5), (0.9, 0.8),
(1.75, 0.60), (2.45, 0.05), (0.70, -0.75)]
ax.scatter(*zip(*points), s=45, color="#d16c31", zorder=5)
label(ax, "Cell membrane", (1.8, 1.75), (2.35, 2.48), "#267e9e")
label(ax, "Cell nucleus\n(excluded from cytoplasm)", (-1.10, 0.60),
(-2.40, 2.50), "#79519b")
label(ax, "DNA", (-0.70, 0.73), (-0.10, 1.84), "#79519b")
label(ax, "Nuclear envelope\n(two membranes)", (-1.86, -0.20),
(-3.90, -0.50), "#79519b")
label(ax, "Nucleolus", (-0.83, -0.04), (-2.6, -2.38), "#79519b")
label(ax, "Nuclear pore complex", (0.43, 0.22), (2.02, 1.34))
label(ax, "Cytosol\n(pale blue)", (0.65, -1.25), (0.05, -2.40), "#267e9e")
label(ax, "Mitochondrion", (1.9, -0.55), (2.83, -1.85), "#9d6b16")
label(ax, "Free ribosomes\n(no enclosing membranes)", (1.75, 0.60),
(3.62, 0.83), "#b65620")
ax.set(xlim=(-4.8, 5.05), ylim=(-2.75, 2.9), aspect="equal")
ax.axis("off")
fig.suptitle("Cytoplasm includes cytosol and organelles", fontsize=15, y=0.97)
fig.text(0.5, 0.08, "The nucleus is separate; organelle interiors are not cytosol.",
ha="center", fontsize=11)
fig.text(0.5, 0.025, "Original schematic of a nucleated eukaryotic cell • not to scale • many structures omitted",
ha="center", fontsize=9)
fig.subplots_adjust(left=0.025, right=0.975, bottom=0.14, top=0.90)
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=140,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()