"""Weighted centering versus Euclidean orthogonal projection; Python 3.14. Run through Make from the mirrored _media working directory. The points are computed from the defining matrices rather than positioned for appearance. """ from pathlib import Path import matplotlib.pyplot as plt import numpy as np def main(): a = np.array([0.25, 0.75]) x = np.array([4.0, 2.0]) centered = x - np.ones(2) * (a @ x) orthogonal = x - a * ((a @ x) / (a @ a)) assert np.allclose(centered, [1.5, -0.5]) assert np.allclose(orthogonal, [3, -1]) fig, ax = plt.subplots(figsize=(7, 5), dpi=100, facecolor='white') ax.set_facecolor('white') u = np.linspace(-0.4, 4.9, 200) ax.plot(u, -u / 3, color='#25734a', lw=2) ax.axhline(0, color='#bbc1c8', lw=0.8) ax.axvline(0, color='#bbc1c8', lw=0.8) ax.annotate('', xy=centered, xytext=x, arrowprops={'arrowstyle': '-|>', 'color': '#c45e25', 'lw': 2.4}) ax.annotate('', xy=orthogonal, xytext=x, arrowprops={'arrowstyle': '-|>', 'color': '#7b8491', 'lw': 1.5, 'linestyle': '--'}) ax.scatter(*x, s=50, color='#265fa2', zorder=4) ax.scatter(*centered, s=55, color='#25734a', zorder=4) ax.scatter(*orthogonal, s=45, facecolor='white', edgecolor='#7b8491', zorder=4) ax.annotate(r'$x=(4,2)$', x, xytext=(10, 8), textcoords='offset points', fontsize=12) ax.annotate(r'$P_a x=(1.5,-0.5)$', centered, xytext=(-105, -24), textcoords='offset points', color='#25734a', fontsize=11) ax.annotate('Euclidean orthogonal\nprojection (3, -1)', orthogonal, xytext=(14, -42), textcoords='offset points', color='#606975', fontsize=10) ax.text(1.05, 1.65, 'Centering subtracts\nthe same value\nfrom both coordinates', fontsize=10, color='#a64e1e') ax.text(3.75, -0.82, r'$a^T y=0$', color='#25734a', fontsize=12) ax.set_title('Weighted centering follows the constant-vector direction\n' r'$a=(1/4,3/4),\quad a^T x=2.5$', fontsize=13, pad=14) ax.set_xlabel('First coordinate') ax.set_ylabel('Second coordinate') ax.set_xlim(-0.6, 5.1) ax.set_ylim(-2.0, 3.0) ax.set_aspect('equal') ax.set_xticks(range(0, 6)) ax.set_yticks(range(-2, 4)) ax.spines[['top', 'right']].set_visible(False) fig.tight_layout() fig.savefig(Path(__file__).with_suffix('.png').name, dpi=100, facecolor='white') plt.close(fig) if __name__ == '__main__': main()