"""Illustrate phase centroids, including two different zero-order states. Build: make _media/kuramoto-order-parameter.png Tested with Python 3.14.4, NumPy 2.3.5 and Matplotlib 3.10.7. Writes an opaque PNG with this script's basename to the working directory. """ from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np def main(): cases = [ ("Aligned", np.full(8, np.pi / 6), "8 at one phase"), ("Two opposing clusters", np.array([0.0] * 4 + [np.pi] * 4), "4 at each phase"), ("Evenly spaced", np.arange(8) * np.pi / 4, "1 at each phase"), ] circle = np.linspace(0, 2 * np.pi, 401) fig, axes = plt.subplots(1, 3, figsize=(10.2, 4.0), dpi=110, facecolor="white") for ax, (title, phases, label) in zip(axes, cases): z = np.exp(1j * phases).mean() ax.plot(np.cos(circle), np.sin(circle), color="#64748b", lw=1.3) ax.axhline(0, color="#cbd5e1", lw=0.8) ax.axvline(0, color="#cbd5e1", lw=0.8) points, counts = np.unique(np.round(phases, 12), return_counts=True) for phase, count in zip(points, counts): x, y = np.cos(phase), np.sin(phase) ax.plot(x, y, "o", color="#2563a0", ms=6 + 1.2 * count) if abs(z) > 1e-12: ax.annotate("", xy=(z.real, z.imag), xytext=(0, 0), arrowprops=dict(arrowstyle="->", color="#c13c35", lw=2.5)) else: ax.plot(0, 0, "o", color="#c13c35", ms=7) ax.set_title(title, fontsize=12) ax.text(0, -1.32, label, ha="center", fontsize=10, color="#2563a0") ax.text(0, -1.56, rf"$r={abs(z):.0f}$", ha="center", fontsize=13, color="#c13c35") ax.set(xlim=(-1.25, 1.25), ylim=(-1.65, 1.3), aspect="equal") ax.axis("off") fig.suptitle("Eight phases on the unit circle; red marks their centroid", fontsize=13) fig.tight_layout(rect=(0, 0, 1, 0.93)) fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), facecolor="white") plt.close(fig) if __name__ == "__main__": main()