codexproduct-topology-open-rectangle-projections.py
product-topology-open-rectangle-projections.py
"""Draw coordinate strips and their open-rectangle intersection (Python 3.14)."""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
def main():
plt.rcParams.update({"font.size": 11, "axes.titlesize": 12})
fig, axes = plt.subplots(1, 3, figsize=(10.8, 4.6), facecolor="white")
blue, orange, purple = "#2878a3", "#c36d24", "#7556a6"
for ax in axes:
ax.set(xlim=(-0.35, 3.3), ylim=(-0.35, 4.7), aspect="equal")
ax.spines[["top", "right"]].set_visible(False)
ax.spines["bottom"].set_position("zero")
ax.spines["left"].set_position("zero")
ax.set_xticks([1, 2, 3])
ax.set_yticks([1, 2, 3, 4])
ax.set_xlabel(r"$x_1$", loc="right")
ax.set_ylabel(r"$x_2$", loc="top", rotation=0)
a, b, c = axes
a.add_patch(Rectangle((1, -0.35), 1, 5.05, color=blue, alpha=0.16))
for x in (1, 2):
a.axvline(x, color=blue, ls="--", lw=1.5)
for start, end in ((4.1, 4.65), (0.2, -0.32)):
a.annotate("", (1.5, end), (1.5, start),
arrowprops={"arrowstyle": "->", "color": blue, "lw": 2})
a.set_title(r"$\pi_1^{-1}((1,2))=(1,2)\times\mathbb{R}$", pad=17)
b.add_patch(Rectangle((-0.35, 2), 3.65, 2, color=orange, alpha=0.16))
for y in (2, 4):
b.axhline(y, color=orange, ls="--", lw=1.5)
for start, end in ((2.6, 3.25), (0.35, -0.3)):
b.annotate("", (end, 3), (start, 3),
arrowprops={"arrowstyle": "->", "color": orange, "lw": 2})
b.set_title(r"$\pi_2^{-1}((2,4))=\mathbb{R}\times(2,4)$", pad=17)
c.add_patch(Rectangle((1, 2), 1, 2, facecolor=purple,
alpha=0.17, edgecolor=purple, ls="--", lw=2))
# A separate border keeps the excluded boundary readable.
c.add_patch(Rectangle((1, 2), 1, 2, fill=False,
edgecolor=purple, ls="--", lw=1.5))
c.scatter([1.4], [3], color=purple, s=42, zorder=5)
c.text(1.5, 3.12, "(1.4, 3)", color=purple, fontsize=10)
c.annotate("", (1.4, 0), (1.4, 2.93),
arrowprops={"arrowstyle": "->", "color": blue, "ls": ":"})
c.annotate("", (0, 3), (1.34, 3),
arrowprops={"arrowstyle": "->", "color": orange, "ls": ":"})
c.plot([1, 2], [0, 0], color=blue, lw=4)
c.plot([0, 0], [2, 4], color=orange, lw=4)
c.scatter([1, 2], [0, 0], facecolor="white", edgecolor=blue, zorder=6)
c.scatter([0, 0], [2, 4], facecolor="white", edgecolor=orange, zorder=6)
c.set_title(r"Both tests: $(1,2)\times(2,4)$", pad=17)
fig.suptitle("Two coordinate observations select an open rectangle", y=0.97)
fig.text(0.5, 0.04, "Dashed boundaries are excluded; strip arrows indicate unbounded continuation.",
ha="center", fontsize=10)
fig.subplots_adjust(left=0.06, right=0.98, top=0.80, bottom=0.18, wspace=0.30)
fig.savefig(Path(__file__).with_suffix(".png").name, dpi=100,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()