codex/microtomy-oblique-cylinder-section.py

microtomy-oblique-cylinder-section.py
"""Original ideal cylinder section geometry; write PNG into the cwd.

Tested with Python 3.14.4, NumPy 2.3.5 and Matplotlib 3.10.7.
This is a mathematical drawing, not a recorded specimen image.
"""
from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Arc
import numpy as np

radius = 20.0
theta = np.pi / 4
spacing = 20.0
a = radius / np.cos(theta)
shift = spacing * np.tan(theta)
phi = np.linspace(0, 2 * np.pi, 721)
x, y = a * np.cos(phi), radius * np.sin(phi)
assert np.allclose((x * np.cos(theta))**2 + y**2, radius**2)
assert np.isclose(a / radius, np.sqrt(2))
assert np.isclose(shift, 20)
assert np.allclose(((x + shift) * np.cos(theta) - spacing * np.sin(theta))**2
                   + y**2, radius**2)

plt.rcParams.update({"font.size": 10, "figure.facecolor": "white"})
fig, (side, profile) = plt.subplots(1, 2, figsize=(9, 5.2), dpi=100)
fig.subplots_adjust(left=0.075, right=0.98, top=0.82, bottom=0.30, wspace=0.26)
fig.suptitle("An oblique cut makes a circular fibre look elliptical", fontsize=15, y=0.96)
z = np.linspace(-25, 45, 100)
axis = z * np.tan(theta)
side.fill_betweenx(z, axis - a, axis + a, color="#d5e7f2")
side.plot(axis - a, z, color="#2976a3", linewidth=1.3)
side.plot(axis + a, z, color="#2976a3", linewidth=1.3)
side.plot(axis, z, color="#2976a3", linestyle="--", linewidth=1.2)
side.plot([0, 0], [0, 26], color="#777777", linestyle=":")
for level, center in [(0, 0), (spacing, shift)]:
    side.plot([center - a, center + a], [level, level], color="#bd541c", linewidth=2)
    side.scatter([center], [level], color="#bd541c", s=25, zorder=4)
side.add_patch(Arc((0, 0), 20, 20, theta1=45, theta2=90, color="#333333"))
side.text(6.5, 11, "θ", fontsize=12)
side.annotate("", xy=(-42, spacing), xytext=(-42, 0),
              arrowprops={"arrowstyle": "<->", "color": "#333333"})
side.text(-47, spacing/2, "h", ha="center", va="center", fontsize=11)
side.plot([0, 0], [-12, 0], color="#999999", linewidth=0.8)
side.plot([shift, shift], [-12, spacing], color="#999999", linewidth=0.8)
side.annotate("", xy=(shift, -12), xytext=(0, -12),
              arrowprops={"arrowstyle": "<->", "color": "#333333"})
side.text(shift/2, -21, "Δx = h tan θ", ha="center", fontsize=10)
side.set(xlim=(-53, 64), ylim=(-25, 45), xlabel="x (μm)", ylabel="z (μm)",
         title="Side view: two sampled section planes")
side.set_aspect("equal")
profile.plot(radius * np.cos(phi), radius * np.sin(phi), linestyle="--",
             color="#2976a3", linewidth=1.6, label="Normal cut: circle")
profile.plot(x, y, color="#bd541c", linewidth=2, label="Oblique cut: ellipse")
profile.plot([-a, a], [0, 0], color="#aaaaaa", linewidth=0.8)
profile.plot([0, 0], [-radius, radius], color="#aaaaaa", linewidth=0.8)
profile.set(xlim=(-35, 35), ylim=(-27, 27), xlabel="x relative to profile centre (μm)",
            ylabel="y (μm)", title="Profiles in their section planes")
profile.set_aspect("equal")
profile.legend(loc="upper center", bbox_to_anchor=(0.5, -0.20), ncol=2, fontsize=9,
               frameon=False)
for ax in [side, profile]:
    ax.spines[["top", "right"]].set_visible(False)
fig.text(0.5, 0.085, "Chosen geometry: R = 20 μm, θ = 45°, sampled-plane spacing h = 20 μm.",
         ha="center", fontsize=10)
fig.text(0.5, 0.035, "Ideal thin-plane intersections; deformation and finite-thickness blur are excluded.",
         ha="center", fontsize=10)
fig.savefig(Path("microtomy-oblique-cylinder-section.png"), facecolor="white")
plt.close(fig)