"""Plot fractional-part representatives; write the PNG into the current directory. Build with ``make _media/reduction-modulo-one-sawtooth.png``. The curve is an exact mathematical example, not measured data. """ from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt def main(): lower, upper = -2.4, 2.4 blue, orange = "#176b91", "#a64b16" fig, ax = plt.subplots(figsize=(7.8, 3.1), layout="constrained") fig.patch.set_facecolor("white") ax.set_facecolor("white") for integer in range(-3, 3): left, right = max(integer, lower), min(integer + 1, upper) if left < right: ax.plot([left, right], [left - integer, right - integer], color=blue, lw=2) if lower < integer < upper: ax.axvline(integer, color="0.85", ls="--", lw=0.8, zorder=0) ax.plot(integer, 0, "o", color=blue, ms=6, zorder=3) if lower < integer + 1 < upper: ax.plot(integer + 1, 1, "o", color=blue, markerfacecolor="white", markeredgewidth=1.5, ms=6, zorder=3) ax.scatter([-1.2], [0.8], color=orange, s=42, zorder=4) ax.annotate(r"$-1.2-(-2)=0.8$", (-1.2, 0.8), (-2.25, 1.08), color=orange, fontsize=11, arrowprops={"arrowstyle": "->", "color": orange}) ax.set(xlim=(lower, upper), ylim=(-0.08, 1.22), xlabel=r"Real input $x$", ylabel=r"$x-\lfloor x\rfloor$", title="Reduction modulo one: filled points belong; open points do not") ax.set_xticks(range(-2, 3)) ax.set_yticks([0, 0.5, 1]) ax.tick_params(labelsize=10) ax.grid(axis="y", alpha=0.2) fig.savefig(Path(__file__).with_suffix(".png").name, dpi=100, facecolor="white", transparent=False) plt.close(fig) if __name__ == "__main__": main()