codexpast-exam-of-the-advanced-quantum-field-theory-for-particle-physics-course-of-the-university-of-oxford2018-scalar-qed-four-point-diagrams.py
past-exam-of-the-advanced-quantum-field-theory-for-particle-physics-course-of-the-university-of-oxford/2018-scalar-qed-four-point-diagrams.py
"""Original diagrams; Python 3.14, NumPy and Matplotlib. Save only in the caller CWD."""
from pathlib import Path
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch
plt.rcParams.update({"font.size":11,"axes.titlesize":11,"figure.facecolor":"white","savefig.facecolor":"white"})
BLUE="#126782";RED="#ba4c30"
def line(ax,a,b,arrow=False,color=BLUE):
ax.add_patch(FancyArrowPatch(a,b,arrowstyle="-|>" if arrow else "-",mutation_scale=10,color=color,lw=1.6,shrinkA=0,shrinkB=0))
def wave(ax,a,b,height=0,color=RED,turns=9):
a=np.array(a);b=np.array(b);t=np.linspace(0,1,400)
x=a[0]+(b[0]-a[0])*t;y=a[1]+(b[1]-a[1])*t+height*np.sin(np.pi*t)
dx=np.gradient(x);dy=np.gradient(y);norm=np.sqrt(dx*dx+dy*dy);wiggle=.012*np.sin(2*np.pi*turns*t)
ax.plot(x-wiggle*dy/norm,y+wiggle*dx/norm,color=color,lw=1.3)
def dot(ax,p,seagull=False):ax.scatter(*p,s=30,marker="s" if seagull else "o",color="#222222",zorder=5)
def clean(ax):ax.set(xlim=(-.03,1.03),ylim=(-.07,1.03));ax.set_aspect("equal");ax.axis("off")
fig,axes=plt.subplots(3,3,figsize=(10.5,9.6),layout="constrained")
# Along the scalar chain, the endpoints consume one photon slot each for the internal line.
items=[('Box 1','CCCC',(1,2)),('Box 2','CCCC',(2,1)),('Triangle 1','CSC',(1,1)),('Triangle 2','SCC',(0,1)),('Triangle 3','SCC',(1,0)),('Triangle 4','CCS',(1,2)),('Triangle 5','CCS',(2,1)),('Bubble 1','SS',(0,1)),('Bubble 2','SS',(1,0))]
for ax,(name,types,assignment) in zip(axes.flat,items):
clean(ax);xs=np.linspace(.2,.8,len(types));nodes=[(x,.42) for x in xs]
line(ax,(.025,.42),nodes[0],True);line(ax,nodes[-1],(.975,.42),True)
for a,b in zip(nodes,nodes[1:]):line(ax,a,b,True)
wave(ax,nodes[0],nodes[-1],height=.43,turns=12)
for j,typ in enumerate(types):dot(ax,nodes[j],typ=='S');ax.text(xs[j],.49,typ,ha='center',fontsize=9)
for photon,nodeid in enumerate(assignment):
a=nodes[nodeid];offset=(-.10 if photon==0 else .10) if assignment[0]==assignment[1] else 0
b=(a[0]+offset,.06);wave(ax,a,b,turns=5);ax.text(b[0],-.025,r'$\gamma_'+str(photon+1)+'$',ha='center')
ax.text(.02,.31,r'$\phi$',ha='center');ax.text(.98,.31,r'$\phi^*$',ha='center')
ax.set_title(name+': '+types)
fig.savefig(Path.cwd()/Path(__file__).with_suffix(".png").name,dpi=120,transparent=False)
plt.close(fig)