codex/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

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()