codexpast-exam-of-the-mathematics-course-of-the-year-2-of-the-natural-sciences-course-of-the-university-of-cambridge2022paper-1-paraboloidal-cap.py
past-exam-of-the-mathematics-course-of-the-year-2-of-the-natural-sciences-course-of-the-university-of-cambridge/2022/paper-1-paraboloidal-cap.py
"""Q1 paraboloidal cap; Python 3.14.4, root pyproject.toml dependencies.
Write the opaque PNG to cwd. Run in the matching _media course directory.
"""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
def main():
radius, angle = np.meshgrid(np.linspace(0, 1, 55), np.linspace(0, 2 * np.pi, 100))
x = radius * np.cos(angle)
y = radius * np.sin(angle)
z = (radius**2 - 1) / 2
fig = plt.figure(figsize=(8.6, 4.2), facecolor="white")
ax = fig.add_subplot(1, 2, 1, projection="3d")
ax.plot_surface(x, y, z, color="#347da9", alpha=0.57, linewidth=0, antialiased=True)
ax.plot_surface(x, y, np.zeros_like(z), color="#c3d8e4", alpha=0.24, linewidth=0)
theta = np.linspace(0, 2 * np.pi, 300)
ax.plot(np.cos(theta), np.sin(theta), np.zeros_like(theta), color="#174d70", lw=1.8)
ax.scatter([0], [0], [-0.5], color="#a34b27", s=28, depthshade=False)
ax.set(xlabel=r"$x$", ylabel=r"$y$", zlabel=r"$z$", title="Curved base and top disk", zlim=(-0.58, 0.1))
ax.set_box_aspect((1, 1, 0.65))
ax.view_init(elev=23, azim=-58)
ax.set_xticks([-1, 0, 1])
ax.set_yticks([-1, 0, 1])
ax.set_zticks([-0.5, 0])
ax.tick_params(labelsize=8, pad=0)
section = fig.add_subplot(1, 2, 2)
horizontal = np.linspace(-1, 1, 400)
bottom = (horizontal**2 - 1) / 2
section.fill_between(horizontal, bottom, 0, color="#d2e3ed")
section.plot(horizontal, bottom, color="#175e90", lw=2)
section.plot([-1, 1], [0, 0], color="#175e90", lw=2)
section.axvline(0, color="#999999", lw=0.7, ls="--")
section.scatter([0], [-0.5], color="#a34b27", s=28, zorder=4)
section.annotate(r"Vertex $(0,-1/2)$", (0, -0.5), xytext=(0.14, -0.65), fontsize=9, arrowprops={"arrowstyle": "->", "color": "#777777"})
section.text(0, -0.22, "Solid interior", ha="center", fontsize=10)
section.text(0, 0.09, "Top disk: z = 0", ha="center", fontsize=10)
section.set(xlabel=r"$x$ (section $y=0$)", ylabel=r"$z$", title="Meridian cross-section", xlim=(-1.15, 1.15), ylim=(-0.74, 0.19), aspect="equal")
section.spines[["top", "right"]].set_visible(False)
section.set_xticks([-1, 0, 1])
section.set_yticks([-0.5, 0])
section.grid(alpha=0.12)
fig.suptitle(r"$(x^2+y^2-1)/2\leq z\leq0$", fontsize=14, y=0.98)
fig.subplots_adjust(left=0.01, right=0.985, bottom=0.15, top=0.82, wspace=0.30)
fig.savefig(Path(__file__).with_suffix(".png").name, dpi=115, facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()