{"spec_id":"feynman-basic","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nfeynman-basic: Feynman Diagram for Particle Interactions\nLibrary: plotnine 0.15.5 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-06-03\n\"\"\"\n\nimport os\nimport sys\n\n\n# This file is named plotnine.py; remove its directory from sys.path so the\n# installed plotnine package is found instead of this script.\n_here = os.path.abspath(os.path.dirname(__file__))\nsys.path = [p for p in sys.path if os.path.abspath(p or \".\") != _here]\ndel _here\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    annotate,\n    arrow,\n    coord_fixed,\n    element_rect,\n    element_text,\n    geom_path,\n    geom_point,\n    geom_segment,\n    geom_text,\n    ggplot,\n    labs,\n    scale_color_manual,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_void,\n)\n\n\n# Theme-adaptive chrome tokens (Imprint palette, canonical)\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Particle type colors — Imprint palette positions 1–4, canonical order\nCOL_FERMION = \"#009E73\"  # position 1 — brand green (electrons, muons)\nCOL_PHOTON = \"#C475FD\"  # position 2 — lavender (virtual photon)\nCOL_GLUON = \"#4467A3\"  # position 3 — blue (gluon leg in legend)\nCOL_BOSON = \"#BD8233\"  # position 4 — ochre (scalar boson leg in legend)\n\n# Main diagram: e- e+ -> gamma -> mu- mu+\n# Vertex positions\nv1x, v1y = 3.0, 3.5\nv2x, v2y = 7.0, 3.5\n\n# Fermion segments with correct Feynman arrow conventions:\n# Particles (e-, mu-): arrows forward in time (left to right)\n# Antiparticles (e+, mu+): arrows backward in time (right to left)\nfermion_particles = pd.DataFrame({\"x\": [0.5, v2x], \"y\": [5.8, v2y], \"xend\": [v1x, 9.5], \"yend\": [v1y, 5.8]})\nfermion_antiparticles = pd.DataFrame({\"x\": [v1x, 9.5], \"y\": [v1y, 1.2], \"xend\": [0.5, v2x], \"yend\": [1.2, v2y]})\n\n# Fermion labels positioned near line endpoints\nfermion_labels = pd.DataFrame(\n    {\"x\": [0.3, 0.3, 9.7, 9.7], \"y\": [6.25, 0.75, 6.25, 0.75], \"label\": [\"e⁻\", \"e⁺\", \"μ⁻\", \"μ⁺\"]}\n)\n\n# Wavy photon propagator between vertices\nn_waves, amp = 7, 0.35\nn_pts = n_waves * 40\nt_ph = np.linspace(0, 1, n_pts)\nphoton_df = pd.DataFrame({\"x\": v1x + (v2x - v1x) * t_ph, \"y\": v1y + amp * np.sin(2 * np.pi * n_waves * t_ph)})\n\n# Photon label\nphoton_label = pd.DataFrame({\"x\": [(v1x + v2x) / 2], \"y\": [v1y + 0.75], \"label\": [\"γ\"]})\n\n# Vertex interaction dots\nvertex_df = pd.DataFrame({\"x\": [v1x, v2x], \"y\": [v1y, v2y], \"ptype\": [\"vertex\", \"vertex\"]})\n\n# Legend: four particle line styles at the bottom\nleg_y = -0.5\nleg_len = 1.5\n\nleg_fermion = pd.DataFrame({\"x\": [0.3], \"y\": [leg_y], \"xend\": [0.3 + leg_len], \"yend\": [leg_y]})\n\nt_lp = np.linspace(0, 1, 120)\nleg_photon_df = pd.DataFrame({\"x\": 2.8 + leg_len * t_lp, \"y\": leg_y + 0.2 * np.sin(2 * np.pi * 4 * t_lp)})\n\nt_gl = np.linspace(0, 1, 400)\nn_loops = 7\ngluon_base_x = 5.5 + leg_len * t_gl\ngluon_loop_x = 0.12 * np.sin(2 * np.pi * n_loops * t_gl)\ngluon_loop_y = 0.35 * np.abs(np.sin(np.pi * n_loops * t_gl))\nleg_gluon_df = pd.DataFrame({\"x\": gluon_base_x + gluon_loop_x, \"y\": leg_y - 0.05 + gluon_loop_y})\n\nleg_boson = pd.DataFrame({\"x\": [8.0], \"y\": [leg_y], \"xend\": [8.0 + leg_len], \"yend\": [leg_y]})\n\nlegend_labels = pd.DataFrame(\n    {\n        \"x\": [0.3 + leg_len / 2, 2.8 + leg_len / 2, 5.5 + leg_len / 2, 8.0 + leg_len / 2],\n        \"y\": [leg_y - 0.65] * 4,\n        \"label\": [\"Fermion\", \"Photon\", \"Gluon\", \"Scalar Boson\"],\n    }\n)\n\n# Time axis indicator\ntime_arrow_df = pd.DataFrame({\"x\": [1.5], \"y\": [0.3], \"xend\": [8.5], \"yend\": [0.3]})\ntime_label_df = pd.DataFrame({\"x\": [5.0], \"y\": [0.7], \"label\": [\"time\"]})\n\n# Build plot using plotnine grammar of graphics\nplot = (\n    ggplot()\n    # Particle fermion lines (arrows forward in time)\n    + geom_segment(\n        data=fermion_particles,\n        mapping=aes(x=\"x\", y=\"y\", xend=\"xend\", yend=\"yend\"),\n        size=2.0,\n        color=COL_FERMION,\n        arrow=arrow(length=0.18, type=\"closed\"),\n    )\n    # Antiparticle fermion lines (arrows backward in time)\n    + geom_segment(\n        data=fermion_antiparticles,\n        mapping=aes(x=\"x\", y=\"y\", xend=\"xend\", yend=\"yend\"),\n        size=2.0,\n        color=COL_FERMION,\n        arrow=arrow(length=0.18, type=\"closed\"),\n    )\n    # Photon wavy propagator\n    + geom_path(data=photon_df, mapping=aes(x=\"x\", y=\"y\"), size=2.0, color=COL_PHOTON)\n    # Vertex interaction points\n    + geom_point(data=vertex_df, mapping=aes(x=\"x\", y=\"y\", color=\"ptype\"), size=8, show_legend=False)\n    + scale_color_manual(values={\"vertex\": INK})\n    # Particle labels\n    + geom_text(\n        data=fermion_labels, mapping=aes(x=\"x\", y=\"y\", label=\"label\"), size=4, color=COL_FERMION, fontweight=\"bold\"\n    )\n    + geom_text(\n        data=photon_label, mapping=aes(x=\"x\", y=\"y\", label=\"label\"), size=4, color=COL_PHOTON, fontweight=\"bold\"\n    )\n    # Time axis arrow\n    + geom_segment(\n        data=time_arrow_df,\n        mapping=aes(x=\"x\", y=\"y\", xend=\"xend\", yend=\"yend\"),\n        size=0.8,\n        color=INK_SOFT,\n        arrow=arrow(length=0.1, type=\"open\"),\n    )\n    + geom_text(\n        data=time_label_df, mapping=aes(x=\"x\", y=\"y\", label=\"label\"), size=3, color=INK_MUTED, fontstyle=\"italic\"\n    )\n    # Legend: fermion (solid + arrow)\n    + geom_segment(\n        data=leg_fermion,\n        mapping=aes(x=\"x\", y=\"y\", xend=\"xend\", yend=\"yend\"),\n        size=1.5,\n        color=COL_FERMION,\n        arrow=arrow(length=0.1, type=\"closed\"),\n    )\n    # Legend: photon (wavy)\n    + geom_path(data=leg_photon_df, mapping=aes(x=\"x\", y=\"y\"), size=1.5, color=COL_PHOTON)\n    # Legend: gluon (curly loops)\n    + geom_path(data=leg_gluon_df, mapping=aes(x=\"x\", y=\"y\"), size=1.5, color=COL_GLUON)\n    # Legend: scalar boson (dashed)\n    + geom_segment(\n        data=leg_boson,\n        mapping=aes(x=\"x\", y=\"y\", xend=\"xend\", yend=\"yend\"),\n        size=1.5,\n        color=COL_BOSON,\n        linetype=\"dashed\",\n    )\n    # Legend text labels (size=3.5 — slightly larger than previous for legibility)\n    + geom_text(data=legend_labels, mapping=aes(x=\"x\", y=\"y\", label=\"label\"), size=3.5, color=INK_SOFT)\n    # Process subtitle annotation\n    + annotate(\"text\", x=5.0, y=6.8, label=\"e⁻e⁺ → γ → μ⁻μ⁺\", size=3.5, color=INK_SOFT, fontstyle=\"italic\")\n    + scale_x_continuous(limits=(-0.5, 10.5), expand=(0, 0.2))\n    + scale_y_continuous(limits=(-1.5, 7.5), expand=(0, 0.1))\n    + coord_fixed(ratio=1)\n    + labs(title=\"feynman-basic · python · plotnine · anyplot.ai\")\n    + theme_void()\n    + theme(\n        figure_size=(8, 4.5),\n        plot_title=element_text(size=12, ha=\"center\", fontweight=\"bold\", margin={\"b\": 8}, color=INK),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        plot_margin=0.02,\n    )\n)\n\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\", verbose=False)\n"}