codexmean-value-theorem-secant-and-tangent.py
mean-value-theorem-secant-and-tangent.py
"""Plot the distinct parallel secant and tangent promised by the MVT.
Run from _media to save the opaque PNG there. Python 3.14; NumPy/Matplotlib.
"""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
def main():
plt.rcParams.update({"font.size": 12, "axes.spines.top": False,
"axes.spines.right": False})
fig, ax = plt.subplots(figsize=(7.2, 4.8), dpi=120, constrained_layout=True)
x = np.linspace(0.85, 3.15, 450)
ax.plot(x, x**2, color="#235789", linewidth=2.8, label=r"$f(x)=x^2$")
ax.plot(x, 4*x-3, color="#287a51", linewidth=2.2,
linestyle="--", label=r"secant: $y=4x-3$")
ax.plot(x, 4*x-4, color="#b63c45", linewidth=2.2,
label=r"tangent: $y=4x-4$")
ax.scatter([1, 3], [1, 9], color="#287a51", s=55, zorder=5)
ax.scatter([2], [4], color="#b63c45", s=55, zorder=5)
ax.annotate(r"$(1,1)$", (1, 1), xytext=(1.10, 0.35))
ax.annotate(r"$(3,9)$", (3, 9), xytext=(2.60, 9.35))
ax.annotate(r"$c=2$: $f'(2)=4$", (2, 4), xytext=(2.20, 2.05),
arrowprops={"arrowstyle": "->", "color": "#555555"})
ax.text(0.045, 0.63, "Both lines have slope 4\nTheir heights differ by 1",
transform=ax.transAxes, fontsize=11,
bbox={"facecolor": "white", "edgecolor": "#cccccc", "pad": 6})
ax.set(xlim=(0.85, 3.15), ylim=(-0.9, 10), xlabel=r"$x$", ylabel=r"$y$",
title="Mean value theorem: matching slopes")
ax.set_xticks([1, 2, 3])
ax.grid(alpha=0.16)
ax.legend(loc="upper left", fontsize=11)
ax.set_facecolor("white")
fig.savefig(Path.cwd() / "mean-value-theorem-secant-and-tangent.png",
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()