"""Original schematic geometry, not historical measurements. Tested with Python 3.14, NumPy 2.3.5 and Matplotlib 3.10.7. Run from _media; writes the matching PNG into the current directory. """ from pathlib import Path import matplotlib.pyplot as plt from matplotlib.patches import FancyArrowPatch, FancyBboxPatch import numpy as np def main(): plt.rcParams.update({"font.size": 11, "axes.spines.top": False, "axes.spines.right": False}) fig = plt.figure(figsize=(11, 6.4), facecolor="white", layout="constrained") grid = fig.add_gridspec(2, 2, height_ratios=[3.5, 1]) ax = fig.add_subplot(grid[0, 0]) track = fig.add_subplot(grid[0, 1]) chain = fig.add_subplot(grid[1, :]) blue, orange, green = "#185c9c", "#c55a16", "#267355" origin, baseline = np.array([0., 0.]), np.array([4., 0.]) sight = np.array([0.5, np.sqrt(3)/2]) parallel = np.dot(baseline, sight) * sight perpendicular = baseline - parallel assert np.isclose(np.dot(perpendicular, sight), 0) assert np.allclose(parallel + perpendicular, baseline) def arrow(start, end, color, text=None, offset=(0, 0)): ax.add_patch(FancyArrowPatch(start, end, arrowstyle="-|>", mutation_scale=14, lw=2, color=color)) if text: middle = (np.asarray(start) + np.asarray(end))/2 + offset ax.text(*middle, text, color=color, ha="center", va="center", bbox={"facecolor": "white", "edgecolor": "none", "pad": 1.5}) arrow(origin, baseline, "#444444", r"$\mathbf{b}=\mathbf{r}_2-\mathbf{r}_1$", (0, -.24)) arrow(origin, 3.2*sight, blue) ax.text(.8, 2.9, r"toward phase centre $\mathbf{s}_0$", color=blue) arrow(origin, parallel, orange, r"$(\mathbf{b}\cdot\mathbf{s}_0)\mathbf{s}_0$", (-.5, .07)) arrow(parallel, baseline, green, r"$\mathbf{b}_\perp$", (.35, .22)) tangent = perpendicular/np.linalg.norm(perpendicular) ax.plot(*np.stack([parallel-.4*tangent, baseline+.45*tangent]).T, color=green, ls=":", lw=1) corner = parallel + .14*tangent ax.plot(*np.stack([corner-.14*sight, corner, parallel+.14*sight]).T, color="#777777", lw=1) ax.scatter([0, 4], [0, 0], s=65, c="#444444", zorder=5) ax.text(-.1, -.55, "Antenna 1", ha="center") ax.text(4, -.55, "Antenna 2", ha="center") ax.text(.15, -1.03, r"Reference delay magnitude: $|\tau_g|=|\mathbf{b}\cdot\mathbf{s}_0|/c$") ax.set(xlim=(-1.3, 5), ylim=(-1.25, 3.4), aspect="equal") ax.set_title("Path delay and sky-plane projection", loc="left", weight="bold") ax.axis("off") hour = np.linspace(-np.pi/2, np.pi/2, 401) declination = np.deg2rad(45) for radius, color in [(1, blue), (.6, green)]: u = radius*np.cos(hour) v = radius*np.sin(declination)*np.sin(hour) track.plot(u, v, c=color, lw=2, label=f"Baseline {radius:g}" ) track.plot(-u, -v, c=color, ls="--", lw=1.4) for degrees, label in [(-60, "−4 h"), (0, "0 h"), (60, "+4 h")]: h = np.deg2rad(degrees) xy = (np.cos(h), np.sin(declination)*np.sin(h)) track.scatter(*xy, c=blue, s=25, zorder=5) track.annotate(label, xy, xytext=(7, 2), textcoords="offset points", fontsize=10) track.axhline(0, c=".8", lw=.7) track.axvline(0, c=".8", lw=.7) track.set(xlim=(-1.32, 1.38), ylim=(-.95, 1.0), aspect="equal", xlabel=r"$u$ / (longest baseline / $\lambda$)", ylabel=r"$v$ / (longest baseline / $\lambda$)") track.set_title("Earth rotation: east–west baselines", loc="left", weight="bold") track.text(-1.2, .83, r"$\delta=45^\circ$; solid: 12-hour track", fontsize=10) track.text(-1.2, -.88, "Dashed: Hermitian partners (inferred)", fontsize=10) track.legend(loc="upper center", bbox_to_anchor=(.5, -.22), ncol=2, frameon=False, fontsize=10) chain.set(xlim=(0, 10), ylim=(0, 1)) chain.axis("off") blocks = [(.02, 1.9, "Two antenna\nvoltage signals"), (2.45, 2.1, "Reference delay +\nphase compensation"), (5.1, 2.25, "Complex correlation\n" + r"$\langle E_1 E_2^*\rangle$"), (7.9, 2, "Visibility at one\nprojected baseline")] for x, width, label in blocks: chain.add_patch(FancyBboxPatch((x, .2), width, .65, boxstyle="round,pad=0.02", ec="#aaaaaa", fc="#f4f7fa")) chain.text(x+width/2, .525, label, ha="center", va="center", fontsize=10) for start, end in [(1.95, 2.4), (4.6, 5.05), (7.4, 7.85)]: chain.annotate("", (end, .525), (start, .525), arrowprops={"arrowstyle": "->", "color": ".4"}) fig.suptitle("Separated antennas measure spatial coherence", fontsize=16, weight="bold") fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=110, facecolor="white") plt.close(fig) if __name__ == "__main__": main()