codex/past-exam-of-the-mathematics-course-of-the-university-of-cambridge/2007/iii/paper-46-uniform-frailty.py

past-exam-of-the-mathematics-course-of-the-university-of-cambridge/2007/iii/paper-46-uniform-frailty.py
"""Uniform-frailty survival selection; Python 3.14, NumPy 2.3, Matplotlib 3.10.

Write the PNG basename to the caller's working directory. Respect any supplied
MPLCONFIGDIR; no cache location is created or overridden by this generator.
"""
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np

t = np.linspace(0, 10, 801)
survival = np.ones_like(t)
hazard = np.ones_like(t)
positive = t > 0
z = t[positive]
survival[positive] = np.exp(-z / 2) * (-np.expm1(-z)) / z
hazard[positive] = 0.5 + 1 / z - 1 / np.expm1(z)

fig, axes = plt.subplots(1, 2, figsize=(10, 4.2), dpi=100, facecolor="white")
for u, color in [(0.5, "#6699aa"), (1.0, "#999999"), (1.5, "#bb9977")]:
    axes[0].plot(t, np.exp(-u * t), ls="--", lw=1.3, color=color,
                 label=fr"Fixed frailty $U={u:g}$")
axes[0].plot(t, survival, color="#173f70", lw=2.5, label="Population mixture")
axes[0].set(xlabel=r"Time $t$ ($\theta=1$)", ylabel="Probability of survival",
            xlim=(0, 10), ylim=(0, 1.03), title="Population survival averages individual survival")
axes[0].legend(frameon=False, fontsize=8)
axes[1].plot(t, hazard, color="#173f70", lw=2.5, label="Population hazard")
axes[1].axhline(1, color="#777777", lw=1.2, ls=":", label=r"Initial mean hazard $1$")
axes[1].axhline(0.5, color="#6699aa", lw=1.5, ls="--", label=r"Limiting hazard $1/2$")
axes[1].set(xlabel=r"Time $t$ ($\theta=1$)", ylabel="Hazard",
            xlim=(0, 10), ylim=(0.45, 1.07), title="Survivors increasingly have smaller frailty")
axes[1].legend(frameon=False, fontsize=8)
for ax in axes:
    ax.set_facecolor("white")
    ax.grid(alpha=0.18)
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
fig.suptitle(r"Uniform frailty $U\sim\mathrm{Unif}[1/2,3/2]$: each individual hazard is constant",
             fontsize=12)
fig.tight_layout(rect=(0, 0, 1, 0.91))
fig.savefig("paper-46-uniform-frailty.png", facecolor="white", transparent=False)
plt.close(fig)