{"id":177,"date":"2025-05-24T09:25:26","date_gmt":"2025-05-24T09:25:26","guid":{"rendered":"https:\/\/synchrotron-light.net\/wp\/?page_id=177"},"modified":"2025-07-20T05:13:03","modified_gmt":"2025-07-20T05:13:03","slug":"chapter-5-insertion-devices","status":"publish","type":"page","link":"https:\/\/synchrotron-light.net\/wp\/?page_id=177","title":{"rendered":"Chapter 5: Insertion devices"},"content":{"rendered":"<p>Below is a set of python codes associated with Chapter 5 of Daniele Pelliccia and David M. Paganin, &#8220;Synchrotron Light: A Physics Journey from Laboratory to Cosmos&#8221; (Oxford University Press, 2025).<\/p>\n<p>In order to run any of these python codes, you will need to include the following header file.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">import numpy as np\r\nimport matplotlib.pyplot as plt\r\nfrom mpl_toolkits.mplot3d import Axes3D\r\nfrom matplotlib import cm\r\nfrom matplotlib.colors import LightSource\r\nimport matplotlib.gridspec as gridspec\r\nfrom scipy import special\r\nfrom sys import stdout\r\n\r\nsynchrotron_style = {\r\n    'font.family': 'FreeSerif',\r\n    'font.size': 30,\r\n    'axes.linewidth': 2.0,\r\n    'axes.edgecolor': 'black',\r\n    'grid.color': '#5b5b5b',\r\n    'grid.linewidth': 1.2,\r\n}<\/pre>\n<h2 id=\"The-basics:-plotting-a-radial-field\">Electron trajectory<\/h2>\n<p>See Fig. 5.4.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true \"># Constants\r\nB0 = 2 # T (tesla)\r\nl_u = 0.15 # m\r\nme = 9.11e-31 # kg\r\nel_energy = 3  # GeV\r\nc = 2.99792458e8 # m\/s, speed of light \r\ngamma = 1000*el_energy\/0.511\r\ngamma = 10000\r\nbeta = 1.0 - 0.5\/gamma**2\r\ne_charge = 1.602e-19\r\n\r\n# Define longitudinal coordinate\r\nx = np.linspace(0, 5*l_u, 1000)\r\n# Magnetic field amplitude\r\nB = -B0*np.cos(2*np.pi*x\/l_u)\r\n# Deflection parameter\r\nK = e_charge*B0*l_u \/ (2 * np.pi * me * beta * c)\r\ndeflection = -K*np.sin(2*np.pi*x\/l_u)\/gamma\r\ntrajectory = K*l_u\/(2*np.pi*gamma)* np.cos(2*np.pi*x\/l_u)\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    \r\n    fig, axs = plt.subplots(3, 1,figsize=(7.7,9), sharex=True)\r\n    fig.subplots_adjust(hspace=0.1)\r\n    axs[0].plot(x\/l_u, B, 'grey', lw = 4)\r\n    axs[0].tick_params(axis='y', labelsize=28)\r\n    axs[0].set_ylabel('B (T)', fontsize=26, labelpad = 15)\r\n\r\n    axs[1].plot(x\/l_u, 1000*deflection, 'red', lw = 4)\r\n    axs[1].tick_params(axis='y', labelsize=28)\r\n    axs[1].set_ylabel('$\\\\vartheta$ (mrad)', fontsize=26, labelpad = -6)\r\n    \r\n    axs[2].plot(x\/l_u, 1000000*trajectory, lw = 4)\r\n    axs[2].tick_params(axis='y', labelsize=28)\r\n    axs[2].set_xlabel('$x\/\\\\lambda_u$', fontsize=28)\r\n    axs[2].tick_params(axis='x', labelsize=28)\r\n    axs[2].set_ylabel('$y$ ($\\\\mu$m)', fontsize=26, labelpad = 1)\r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-179\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.4.png\" alt=\"\" width=\"600\" height=\"668\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.4.png 600w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.4-480x534.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 600px, 100vw\" \/><\/p>\n<h2 style=\"text-align: left;\">Plots of the deflection angle<\/h2>\n<p>These plots are obtained using the magnetic field as a parameter, as in Fig. 5.5(a).<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">gamma=10000\r\nbeta = 1.0 - 0.5\/gamma**2\r\nme = 9.11e-31 # kg\r\ne_charge = 1.602e-19 # C\r\nc = 2.99792458e8 # m\/s, speed of light \r\nl_u = 0.15 # m\r\n# Define longitudinal coordinate\r\nx = np.linspace(0, l_u, 1000)\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, ax = plt.subplots(1, 1,figsize=(6,6))\r\n    for magnetic_field in [0.5,1,2]:\r\n        K = e_charge*magnetic_field*l_u \/ (2 * np.pi * me * beta * c)\r\n        deflection = -K*np.sin(2*np.pi*x\/l_u)\/gamma\r\n        \r\n        ax.plot(x\/l_u, 1000*deflection, lw = 4, label=\"B = \"+str(magnetic_field)+\" (T  )\")\r\n        ax.tick_params(axis='y', labelsize=28)\r\n        ax.set_ylabel('$\\\\vartheta$ (mrad)', fontsize=26, labelpad = 20)\r\n        ax.set_xlabel('$x\/\\\\lambda_u$', fontsize=28)\r\n        ax.tick_params(axis='x', labelsize=28)\r\n    plt.legend(fontsize=23, frameon=True, framealpha=1, handlelength=1) \r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-180\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5a.png\" alt=\"\" width=\"599\" height=\"566\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5a.png 599w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5a-480x454.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 599px, 100vw\" \/><\/p>\n<p>These plots are obtained using the Lorentz factor as a parameter, as in Fig. 5.5(b).<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">me = 9.11e-31 # kg\r\ne_charge = 1.602e-19 # C\r\nc = 2.99792458e8 # m\/s, speed of light \r\nl_u = 0.15 # m\r\nB = 2 # T (tesla)\r\n# Define longitudinal coordinate\r\nx = np.linspace(0, l_u, 1000)\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, ax = plt.subplots(1, 1,figsize=(6,6))\r\n    for gamma in [1000,5000,10000]:\r\n        beta = 1.0 - 0.5\/gamma**2\r\n        K = e_charge*B*l_u \/ (2 * np.pi * me * beta * c)\r\n        deflection = -K*np.sin(2*np.pi*x\/l_u)\/gamma\r\n        \r\n        ax.plot(x\/l_u, 1000*deflection, lw = 4, label=\"$\\\\gamma$ =   \"+str(gamma))\r\n        ax.tick_params(axis='y', labelsize=28)\r\n        ax.set_ylabel('$\\\\vartheta$ (mrad)', fontsize=26, labelpad = 20)\r\n        ax.set_xlabel('$x\/\\\\lambda_u$', fontsize=28)\r\n        ax.tick_params(axis='x', labelsize=28)\r\n    plt.legend(fontsize=23, frameon=True, framealpha=1, handlelength=1) \r\nplt.show()<\/pre>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-181\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5b.png\" alt=\"\" width=\"618\" height=\"566\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5b.png 618w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5b-480x440.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 618px, 100vw\" \/><\/h1>\n<h2 style=\"text-align: left;\">Plots of the electron trajectory<\/h2>\n<p>These plots are obtained using the wiggler period as a parameter, as in Fig. 5.5(c).<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">B0 = 2 # T (tesla)\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, ax = plt.subplots(1, 1,figsize=(6,6))\r\n    for period in [0.1,0.2,0.4]:\r\n        x = np.linspace(0, period, 1000)\r\n        K = e_charge*B0*period \/ (2 * np.pi * me * beta * c)\r\n        deflection = -K*np.sin(2*np.pi*x\/period)\/gamma\r\n        trajectory = K*period*np.cos(2*np.pi*x\/period) \/ (2*np.pi*gamma)\r\n        ax.plot(x\/period, 1000*trajectory, lw = 4, label=\"$\\\\lambda_u$ =  \"+str(period)+\"   m\")\r\n        ax.tick_params(axis='y', labelsize=28)\r\n        ax.set_xlim(-0.05,1.05)\r\n        ax.set_ylabel('$y$ (mm)', fontsize=28)\r\n        ax.set_xlabel('$x\/\\\\lambda_u$', fontsize=28)\r\n        ax.tick_params(axis='x', labelsize=28)\r\n    plt.legend(fontsize=23, frameon=True, framealpha=1, handlelength=1)  \r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-182\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5c.png\" alt=\"\" width=\"627\" height=\"570\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5c.png 627w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5c-480x436.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 627px, 100vw\" \/><\/p>\n<p>These plots are obtained using the Lorentz factor as a parameter, as in Fig. 5.5(d).<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">B0 = 2 # T (tesla)\r\nl_u = 0.15\r\nx = np.linspace(0, l_u, 1000)\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, ax = plt.subplots(1, 1,figsize=(6,6))\r\n    for gamma in [1000,5000,10000]:\r\n        \r\n        beta = 1.0 - 0.5\/gamma**2\r\n        K = e_charge*B0*l_u \/ (2 * np.pi * me * beta * c)\r\n        \r\n        deflection = -K*np.sin(2*np.pi*x\/l_u)\/gamma\r\n        trajectory = K*period*np.cos(2*np.pi*x\/l_u) \/ (2*np.pi*gamma)\r\n        \r\n        ax.plot(x\/l_u, 1000*trajectory, lw = 4, label=\"$\\\\gamma$  =    \"+str(gamma))\r\n        ax.tick_params(axis='y', labelsize=28)\r\n        #ax.set_ylabel('$\\\\vartheta$ (mrad)', fontsize=24, labelpad = 20)\r\n        ax.set_ylabel('$y$ (mm)', fontsize=28,labelpad=10)\r\n        ax.set_xlabel('$x\/\\\\lambda_u$', fontsize=28)\r\n        ax.tick_params(axis='x', labelsize=28)\r\n    plt.legend(fontsize=23, frameon=True, framealpha=1, handlelength=1)  \r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-183\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5d.png\" alt=\"\" width=\"587\" height=\"566\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5d.png 587w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.5d-480x463.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 587px, 100vw\" \/><\/p>\n<h2 id=\"An-infinity-of-stacked-carts\">Electron trajectory and critical energy<\/h2>\n<p>See Fig. 5.7.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true \">B0 = 2 # T (tesla)\r\nl_u = 0.15 # m\r\nme = 9.11e-31 # kg\r\nel_energy = 3  # GeV\r\nc = 2.99792458e8 # m\/s, speed of light \r\ngamma = 10000 # 1000*el_energy\/0.511\r\nbeta = 1.0 - 0.5\/gamma**2\r\ne_charge = 1.602e-19\r\n\r\nhbar = 6.582119569e-16  # eV s so that the critical energy units is eV\r\n# Define longitudinal coordinate\r\nx = np.linspace(0, 5*l_u, 1000)\r\n# Magnetic field amplitude\r\nB = B0*np.cos(2*np.pi*x\/l_u)\r\n# Deflection parameter\r\nK = e_charge*B0*l_u \/ (2 * np.pi * me * beta * c)\r\ndeflection = -K*np.sin(2*np.pi*x\/l_u)\/gamma\r\ntrajectory = K*l_u\/(2*np.pi*gamma)* np.cos(2*np.pi*x\/l_u)\r\n\r\ne_crit = (3*hbar*e_charge*np.abs(B)*gamma**2)\/(2*me)\r\n\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, ax = plt.subplots(2, 1,figsize=(10,20))\r\n    # fig.subplots_adjust(vspace=0.01)\r\n        \r\n    ax[0].plot(x\/l_u, 1000000*trajectory, lw = 4)#, label=\"$\\\\gamma$ =\"+str(gamma))\r\n    ax[0].tick_params(axis='y', labelsize=36)\r\n    ax[0].set_ylabel('$y$ ($\\\\mu$m)', fontsize=36,labelpad=0)\r\n    ax[0].set_xlabel('$x\/\\\\lambda_u$', fontsize=36)\r\n    ax[0].tick_params(axis='x', labelsize=36)\r\n    \r\n    ax[1].plot(x\/l_u, e_crit\/1000, 'black', lw = 4)\r\n    ax[1].tick_params(axis='y', labelsize=36)\r\n    ax[1].set_ylabel('$\\\\mathcal{E}_c$ (keV)', fontsize=36,labelpad=10)\r\n    \r\n    ax[1].set_xlabel('$x\/\\\\lambda_u$', fontsize=36)\r\n    ax[1].tick_params(axis='x', labelsize=36)\r\n\r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-185 size-large\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.7-569x1024.png\" alt=\"\" width=\"569\" height=\"1024\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.7-569x1024.png 569w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.7-480x864.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 569px, 100vw\" \/><\/p>\n<h2 id=\"Electron-trajectory:-figure-eigth\">Electron trajectory: figure-eight<\/h2>\n<p>See Fig. 5.8.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true \">l_u = 0.15 # m\r\ngamma = 10000\r\nbeta = 1 - 1\/gamma**2\r\nc = 2.99792458e8 # m\/s, speed of light \r\n\r\nxt = np.linspace(-0.1,0.1,100)\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    \r\n    plt.rcParams.update(synchrotron_style)\r\n    #fig = plt.figure(figsize=(7,7))\r\n    fig, ax = plt.subplots(1, 2, figsize=(16,10))\r\n    fig.subplots_adjust(wspace=0.3)\r\n    \r\n    xx = np.linspace(-0.9, 0.9, 100)\r\n    alpha_max = 1.0\/(2*np.sqrt(2)*beta)\r\n    ax[1].plot(alpha_max*xx,xx, 'k', ls = ':', lw = 4) \r\n    ax[1].plot([0, 0], [-1.1, 1.1], 'k', ls = ':', lw = 4)\r\n\r\n    for K in [1,2,5,10]:\r\n        \r\n        beta_bar = beta*(1-K**2\/(4*gamma**2))\r\n        gamma_bar = 1.0\/np.sqrt(1-beta_bar**2)\r\n        om_u = beta*c\r\n        t = np.linspace(0, 2*np.pi\/om_u, 1000)\r\n\r\n        y = K*l_u\/(2*np.pi*beta*gamma)*np.sin(om_u*t)\r\n        x = -K**2*l_u*gamma_bar\/(16*np.pi*beta**2 *gamma**2)*np.sin(2*om_u*t)\r\n        \r\n         \r\n        xred = 1e9*x\/(K*gamma)\r\n        yred = 1e9*y\/(K*gamma)\r\n        \r\n        a = K*l_u\/(2*np.pi*beta*gamma)\r\n\r\n        ax[0].plot(1e6*x,1e6*y, lw = 4, label = \"K = \"+str(K))\r\n        ax[1].plot(x\/a,y\/a, lw = 4, label = \"K = \"+str(K))    \r\n        \r\n    ax[0].tick_params(axis='x', labelsize=24)\r\n    ax[0].tick_params(axis='y', labelsize=24)\r\n    \r\n    ax[0].set_xlabel(\"$x'(t)$ ($\\\\mu$m)\", fontsize=24)\r\n    ax[0].set_ylabel(\"$y'(t)$ ($\\\\mu$m)\", fontsize=24)\r\n    \r\n    ax[1].tick_params(axis='x', labelsize=24)\r\n    ax[1].tick_params(axis='y', labelsize=24)\r\n    \r\n    ax[1].set_xlabel(\"$x'(t)\/a$\", fontsize=24)\r\n    ax[1].set_ylabel(\"$y'(t)\/a$\", fontsize=24)\r\n    \r\n    ax[0].set_xlim([1000000*y.min()\/2, 1000000*y.max()\/2])\r\n    ax[1].set_xlim([-0.3, 0.3])\r\n\r\n    ax[0].legend(fontsize = 24, frameon=True, framealpha=1, handlelength=1)\r\n    ax[1].legend(fontsize = 24, frameon=True, framealpha=1, handlelength=1)\r\n\r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-186\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.8-1024x653.png\" alt=\"\" width=\"800\" height=\"510\" \/><\/p>\n<p>The opening angle of the figure-eight, shown in Fig. 5.9, can be plotted with the following code.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true \">K=np.linspace(0,20,1000)\r\n\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, ax = plt.subplots(1, 1,figsize=(8,8))\r\n\r\n    for gamma in [1000]:\r\n        beta = 1.0 - 0.5\/gamma**2\r\n        alpha = 0.25*K\/np.sqrt(1+0.5*K**2)\r\n        alpha_max = 1.0\/(2*beta*np.sqrt(2))\r\n        \r\n        ax.plot([-1,20], [alpha_max,alpha_max], 'k', lw=4, ls=':')\r\n        ax.plot(K, alpha, lw = 4, label = \"$\\\\gamma$ =\"+str(gamma))\r\n        \r\n        ax.set_xticks([0, 5,10,15,20])\r\n        \r\n        #ax.plot(x\/period, 1000*trajectory, lw = 4, label=\"$\\\\lambda_u$ =\"+str(period)+\" m\")\r\n        ax.tick_params(axis='y', labelsize=30)\r\n        ax.set_ylim(-0.02,0.4)\r\n        ax.set_xlim(-1,21)\r\n        ax.set_ylabel('$\\\\alpha$', fontsize=28)\r\n        ax.set_xlabel('$K$', fontsize=28)\r\n        ax.tick_params(axis='x', labelsize=30)\r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-187\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.9.png\" alt=\"\" width=\"600\" height=\"596\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.9.png 600w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.9-480x477.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 600px, 100vw\" \/><\/p>\n<h2 id=\"2D-power-distribution\">Interference factor <span class=\"wp-katex-eq\" data-display=\"false\">\\mathcal{I}<\/span><\/h2>\n<p>See Fig. 5.15.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">e = 1.602e-19  # C\r\nc = 3.0e8  # m\/s\r\nm_e = 9.109383702e-31  #kg, electron mass\r\nB0=10.0 # T (tesla)\r\nepsilon_0 = 8.854e-12  #F\/m\r\nl_u = 0.15 #m\r\nN=10\r\ngamma = 1000\r\nbeta = 1 - 1\/gamma**2\r\nrho_min = gamma*m_e*c\/(e*B0) #m\r\nrho=10\r\nomega_0 = c\/rho\r\ntheta=0.0\r\n\r\np = 2*np.pi*(2*rho)\/l_u\r\nn = np.linspace(1,int(4*p),int(4*p))\r\nf_n = l_u*n\/(2*rho * gamma**2)\r\ninterf_factor = (1-np.cos(2*np.pi*2*n*N\/p))\/(1+np.cos(2*np.pi*n\/p))\r\ninterf_factor1 = 4*N**2*np.sin(N*2*np.pi*(n-1*p\/2)\/p)**2\/(N*2*np.pi*(n-p\/2)\/p)**2\r\n\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, ax = plt.subplots(1,1, figsize=(16,5.7))\r\n    ax.plot(n\/p, interf_factor, lw = 4, color='blue')\r\n    ax.plot(n\/p, interf_factor1, lw = 2, color='red')\r\n    #ax.plot(n[:5000]\/p, interf_factor2[:5000], lw = 2, color='red')\r\n    plt.xlabel('$n\/p$', fontsize=24, labelpad=10)\r\n    plt.ylabel('Interference factor', fontsize=30, labelpad=10)\r\n    plt.xticks(fontsize=26)\r\n    plt.yticks(fontsize=26)\r\n    \r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-188\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.15-1024x408.png\" alt=\"\" width=\"1024\" height=\"408\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.15-980x391.png 980w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.15-480x191.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/p>\n<h2 id=\"Longitudinal-Doppler-effect\">Transition between undulator and wiggler<\/h2>\n<p>See Fig. 5.16.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">e = 1.602e-19  # C\r\nc = 3.0e8  # m\/s\r\nm_e = 9.109383702e-31  # kg, electron mass\r\nB0=0.03#T\r\nepsilon_0 = 8.854e-12  # F\/m\r\nN=100\r\ngamma = 1000\r\nbeta = 1 - 1\/gamma**2\r\nl_u = 0.01 #m\r\nomega_u = 2*np.pi*c\/l_u\r\n\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    \r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, axs = plt.subplots(2,2, figsize=(16.5,14))\r\n    fig.subplots_adjust(hspace=0.3)\r\n    \r\n    for ax, K in zip(axs.flat, [0.2, 1, 2, 10]):   \r\n        \r\n        rho_min = l_u*gamma\/(2*np.pi*K)\r\n        omega_c = 3 * gamma**2 * K * omega_u\r\n        gammabar = gamma\/np.sqrt(1+K**2\/2)\r\n        Mtot = 2000\r\n        omega = np.linspace(1,int(5*omega_c),100000)\r\n        arg_k = omega\/(2*omega_c)\r\n        P_tot = e**2 * gamma**4 \/ (6*np.pi**2 * epsilon_0 *rho_min)*(3*omega\/(4*np.pi*gamma*omega_c))**2 *\\\r\n                            special.kv(2\/3,arg_k)**2\r\n        if K ==0.1:\r\n            pmax = 4*N**2*np.max(P_tot)\r\n        interference = np.zeros((P_tot.shape[0], Mtot))\r\n        for m in range(Mtot):\r\n            interference[:,m] = np.sin(np.pi*N*(omega\/(2*gammabar**2 * omega_u)-2*m-1))**2\/(np.pi*N*(omega\/(2*gammabar**2 * omega_u)-2*m-1))**2\r\n\r\n        int_factor = np.sum(interference, axis=1)\r\n        P_id = 4*N**2* P_tot*int_factor #\r\n        ax.plot(omega\/omega_c, P_id\/pmax, 'b', lw = 4)\r\n        ax.plot(omega\/omega_c, 4*N**2*P_tot\/pmax, 'r', lw = 4)\r\n        ax.set_xlabel('$\\\\omega\/\\omega_{c}^{\\mathrm{max}}$', fontsize=28, labelpad=1)\r\n        ax.tick_params(axis='x', labelsize=26)\r\n        ax.tick_params(axis='y', labelsize=26)\r\n        ax.set_title('$K = $'+str(K), fontsize=28, loc='right')\r\n        ax.yaxis.get_offset_text().set_fontsize(20)  \r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-190\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.16-1024x924.png\" alt=\"\" width=\"800\" height=\"722\" \/><\/p>\n<h2>Relativistic effects in the undulator spectrum<\/h2>\n<p>Plot of the first two harmonics in different reference frames, as in Fig. 5.20.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">theta = np.linspace(-np.pi, np.pi, 5000)\r\n\r\nK = 0.5\r\nc = 3.0e8  #m\/s\r\nl_u = 0.15 #m\r\nbeta = [0.001, 0.8]\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(18.5, 7))\r\n    for i,j in enumerate(beta):\r\n        \r\n        gamma = 1\/np.sqrt(1-j**2)\r\n        print(gamma)\r\n        beta_bar = j*(1-K**2\/(4*gamma**2))\r\n        gamma_bar = 1.0\/np.sqrt(1-beta_bar**2)\r\n        om_u = j*c\r\n\r\n        R1 = (1 - j*np.cos(theta))**(-4)*(1-np.sin(theta)**2\/(gamma**2 * (1 - j*np.cos(theta))**2))\r\n        R2 = np.sin(theta)**2\/(1 - j*np.cos(theta))**6\r\n\r\n        # Define parametric equations\r\n        X1 = R1*np.cos(theta)  #K*l_u\/(2*np.pi*gamma)*\r\n        Y1 = R1*np.sin(theta)\r\n\r\n        X2 = R2*np.cos(theta) #K**2*j*l_u*gamma_bar\/(16*np.pi*gamma**2)*\r\n        Y2 = R2*np.sin(theta)\r\n        \r\n        axs[i].plot(X1, Y1, 'brown', lw = 3)\r\n        axs[i].plot(X2, Y2, 'blue', lw = 3)\r\n\r\n        if i==0:\r\n            axs[i].set_ylim(-axs[i].get_xlim()[1], axs[i].get_xlim()[1])\r\n            axs[i].set_xlabel(\"$x'$ (a. u.)\", fontsize=24)\r\n            axs[i].set_ylabel(\"$y'$ (a. u.)\", fontsize=24)\r\n            axs[i].set_title(r\"(a)\", fontsize=30, loc='left')\r\n            \r\n        else:\r\n            axs[i].set_ylim(-axs[i].get_xlim()[1]\/2, axs[i].get_xlim()[1]\/2)\r\n            axs[i].set_xlabel(\"$x$ (a. u.)\", fontsize=24)\r\n            axs[i].set_ylabel(\"$y$ (a. u.)\", fontsize=24)\r\n            axs[i].set_title(r\"(b)\", fontsize=30, loc='left')\r\n        \r\n        \r\n        axs[i].tick_params(axis='x', labelsize=26)\r\n        axs[i].tick_params(axis='y', labelsize=26)\r\n        axs[i].set_aspect('equal')\r\n   \r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-191\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.20-1024x472.png\" alt=\"\" width=\"800\" height=\"369\" \/><\/p>\n<p>Numerical solution for the electron trajectory, as in Fig. 5.21.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">def bisection(function, a, b, tolerance): \r\n    c = (a+b)\/2.0\r\n    Iters = 1\r\n    while np.abs(f(c)) &gt;= tolerance:\r\n        if f(a)*f(c) &lt; 0:\r\n            b = c\r\n        else:\r\n            a = c\r\n        c = (a+b)\/2\r\n        Iters += 1\r\n    return c\r\n\r\nc = 3.0e8  #m\/s\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig = plt.figure(figsize=(15, 12), tight_layout=False)\r\n    gs = gridspec.GridSpec(2, 2)\r\n    ax1 = fig.add_subplot(gs[0, :])\r\n    ax12 = fig.add_subplot(gs[1, 0])\r\n    ax22 = fig.add_subplot(gs[1, 1]) \r\n    \r\n    for K in [0.1,1,10]:\r\n        \r\n        K_bar = K\/np.sqrt(1+K**2\/2)\r\n        l_u = 0.15 #m\r\n        omega_u = 2*np.pi*c\/l_u\r\n        k_u = 2*np.pi\/l_u\r\n        gamma = 1000\r\n        gamma_bar = gamma\/np.sqrt(1+K**2\/2)\r\n\r\n        lp_u = l_u\/gamma_bar\r\n        kp_u = gamma_bar*k_u \r\n        omegap_u = gamma_bar*omega_u\r\n\r\n        tp = np.linspace(0, 10*lp_u\/(2*c), 20000)\r\n        xp = np.zeros_like(tp)\r\n\r\n        for i, t in enumerate(tp):\r\n            f = lambda x: x - K_bar**2\/(8*kp_u)*np.sin(2*omegap_u*t+2*kp_u*x)\r\n            a,b = -K_bar**2\/(4*kp_u), K_bar**2\/(4*kp_u)\r\n            tol = 1e-11\r\n            xp[i] = bisection(f, a, b, tol)\r\n        \r\n        fx = np.abs(np.fft.fft(xp))**2\r\n        ax1.plot(tp[:2001]\/lp_u\/(2*c), xp[:2001] \/(K_bar**2\/(8*kp_u)), lw=3, label = \"K = 00 \"+str(K))\r\n        \r\n        for i in range(2):\r\n            if i ==0:    \r\n                ax12.plot(tp\/(lp_u\/(2*c)), xp \/(K_bar**2\/(8*kp_u)), lw=3)\r\n            else:\r\n                ax22.semilogy(np.arange(100)\/10, fx[1:101] , label = \"K = 00 \"+str(K) , lw=3)\r\n\r\n    ax1.set_xticks([0, tp[500]\/lp_u\/(2*c), tp[1000]\/lp_u\/(2*c), tp[1500]\/lp_u\/(2*c),tp[2000]\/lp_u\/(2*c)])\r\n    ax1.set_xticklabels(['0', '0.25','0.5','0.75', '1'], fontsize=24)\r\n    ax1.set_yticks([-1, -0.5, 0, 0.5, 1])\r\n    ax1.set_yticklabels([-1, -0.5, 0, 0.5, 1], fontsize=24)\r\n    ax1.set_xlabel(\"$2ct'\/\\\\lambda'_u$\", fontsize=28, labelpad=1)\r\n    ax1.set_ylabel(\"$\\\\frac{8x'k'_{u}}{\\\\bar{K}^{2}}$\", fontsize=38, rotation=0, labelpad=20)\r\n    ax1.legend(fontsize=26, frameon=True, framealpha=1, handlelength=1)\r\n    ax1.set_title(r\"(a)\", fontsize=26, loc='right')                \r\n\r\n    ax12.set_xticks([0, 2, 4, 6,8,10])\r\n    ax12.set_xticklabels(['0', '2', '4','6', '8', '10'], fontsize=24)\r\n    ax12.set_xlabel(\"$2ct'\/\\\\lambda'_u$\", fontsize=28, labelpad=1)\r\n    ax12.set_yticks([-1, -0.5, 0, 0.5, 1])\r\n    ax12.set_yticklabels([-1, -0.5, 0, 0.5, 1], fontsize=24)\r\n    ax12.set_ylabel(\"$\\\\frac{8x'k'_{u}}{\\\\bar{K}^{2}}$\", fontsize=38, rotation=0, labelpad=20)\r\n    ax12.set_title(r\"(b)\", fontsize=26, loc='left')    \r\n\r\n    ax22.set_xticks([0, 1,2,3,4,5,6,7,8,9,10])\r\n    ax22.set_xticklabels([0, 2,4,6,8,10,12,14,16,18,20], fontsize=24)\r\n    ax22.set_xlabel(\"$\\\\omega'\/\\\\omega'_{u}$\", fontsize=28, labelpad=1)\r\n    ax22.set(yticklabels=[])\r\n    ax22.set_ylabel(\"Log power spectrum\", fontsize=30, labelpad=1)\r\n    ax22.set_title(r\"(c)\", fontsize=32, loc='right')    \r\n   \r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-192\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.21-1024x816.png\" alt=\"\" width=\"800\" height=\"638\" \/><\/p>\n<h2>Polarisation ellipses<\/h2>\n<p>Portion of the polarisation ellipses for circularly polarised plane waves, as in Fig. 5.22.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">omega = 1\r\nt = np.linspace(0,np.pi\/4,101)\r\nphi_x1 = np.pi\/2\r\nphi_y1 = 0\r\n\r\nphi_x2 = np.pi\/2\r\nphi_y2 = np.pi\r\n\r\nEx_mod = 1\r\nEy_mod = 1\r\n\r\nEx1 = Ex_mod*np.cos(phi_x1 - omega*t)\r\nEy1 = Ey_mod*np.cos(phi_y1 - omega*t)\r\n\r\nEx2 = Ex_mod*np.cos(phi_x2 - omega*t)\r\nEy2 = Ey_mod*np.cos(phi_y2 - omega*t)\r\n\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig = plt.figure(figsize=(7,7))\r\n    plt.plot(Ex1,Ey1, 'k', lw = 4)\r\n    plt.plot(Ex2,Ey2, 'r', lw = 4)\r\n    \r\n    plt.plot(0.5*(Ex1+Ex2),0.5*(Ey1+Ey2), 'g', lw = 4)\r\n    \r\n    plt.xticks(ticks = [-1,-0.5,0,0.5,1],fontsize = 30)\r\n    plt.yticks(ticks = [-1,-0.5,0,0.5,1], fontsize = 30)\r\n    plt.xlabel('x', fontsize=30)\r\n    plt.ylabel(\"y\", fontsize=30)\r\n\r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-193\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.22.png\" alt=\"\" width=\"600\" height=\"543\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.22.png 600w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.22-480x435.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 600px, 100vw\" \/><\/p>\n<p>Polarisation ellipses corresponding to eqn (5.145), as in Fig. 5.23.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">omega = 1\r\nt = np.linspace(0,4*np.pi\/2,101)\r\nphi_x1 = np.pi\/2\r\nphi_y1 = 0\r\n\r\nphi_x2 = np.pi\/2\r\nphi_y2 = np.pi\r\n\r\nEx_mod = 1\r\nEy_mod = 1\r\n\r\nlabel_phase = ['$\\\\pi\/8$', '$\\\\pi\/4$', '$\\\\pi\/2$']\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig = plt.figure(figsize=(7,7))\r\n    \r\n    for i, phi_c in enumerate([np.pi\/8, np.pi\/4, np.pi\/2]):\r\n        \r\n        Ex1 = Ex_mod*np.cos(phi_x1 - omega*t)\r\n        Ey1 = Ey_mod*np.cos(phi_y1 - omega*t)\r\n\r\n        Ex2 = Ex_mod*np.cos(phi_x2 - omega*t + phi_c)\r\n        Ey2 = Ey_mod*np.cos(phi_y2 - omega*t + phi_c)\r\n    \r\n        plt.plot(0.5*(Ex1+Ex2),0.5*(Ey1+Ey2), lw = 4, label = '$\\\\varphi_{c}$   = '+label_phase[i]+' ')\r\n    \r\n    plt.xticks(ticks = [-1,-0.5,0,0.5,1],fontsize = 30)\r\n    plt.yticks(ticks = [-1,-0.5,0,0.5,1], fontsize = 30)\r\n    plt.xlabel('x', fontsize=30)\r\n    plt.ylabel(\"y\", fontsize=30)\r\n    plt.legend(fontsize=26, frameon = True, framealpha=1, handlelength=1)\r\n\r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-194\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.23.png\" alt=\"\" width=\"600\" height=\"571\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.23.png 600w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.23-480x456.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 600px, 100vw\" \/><\/p>\n<h2>Lissajous figures<\/h2>\n<p>See Fig. 5.27.<\/p>\n<pre class=\"theme:obsidian lang:python decode:true\">x = np.linspace(0,2*np.pi, 360)\r\nwith plt.style.context(('seaborn-whitegrid')):\r\n    plt.rcParams.update(synchrotron_style)\r\n    fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(10, 4.8), tight_layout=False)\r\n \r\n    axs[0].plot(np.sin(3*x), np.sin(2*x), 'g',lw=3)\r\n    axs[0].set_xticks([-1,0, 1])\r\n    axs[0].set_yticks([-1,0, 1])\r\n    axs[0].set_xticklabels([-1,0, 1], fontsize=24)\r\n    axs[0].set_yticklabels([-1,0, 1], fontsize=24)\r\n    axs[0].set_title(\"$ m=3, n=2 $\", fontsize=20)\r\n    \r\n    axs[1].plot(np.sin(1*x), np.sin(4*x), 'k',lw=3)\r\n    axs[1].set_xticks([-1,0, 1])\r\n    axs[1].set_yticks([-1,0, 1])\r\n    axs[1].set_xticklabels([-1,0, 1], fontsize=24)\r\n    axs[1].set_yticklabels([-1,0, 1], fontsize=24)\r\n    axs[1].set_title(\"$ m=1, n=4 $\", fontsize=20)\r\n\r\nplt.show()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-195\" src=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.27.png\" alt=\"\" width=\"827\" height=\"454\" srcset=\"https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.27.png 827w, https:\/\/synchrotron-light.net\/wp\/wp-content\/uploads\/2025\/05\/shynchrotron-light-5.27-480x264.png 480w\" sizes=\"(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 827px, 100vw\" \/><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Below is a set of python codes associated with Chapter 5 of Daniele Pelliccia and David M. Paganin, &#8220;Synchrotron Light: A Physics Journey from Laboratory to Cosmos&#8221; (Oxford University Press, 2025). In order to run any of these python codes, you will need to include the following header file. import numpy as np import matplotlib.pyplot [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":79,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"class_list":["post-177","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/synchrotron-light.net\/wp\/index.php?rest_route=\/wp\/v2\/pages\/177","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/synchrotron-light.net\/wp\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/synchrotron-light.net\/wp\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/synchrotron-light.net\/wp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/synchrotron-light.net\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=177"}],"version-history":[{"count":12,"href":"https:\/\/synchrotron-light.net\/wp\/index.php?rest_route=\/wp\/v2\/pages\/177\/revisions"}],"predecessor-version":[{"id":798,"href":"https:\/\/synchrotron-light.net\/wp\/index.php?rest_route=\/wp\/v2\/pages\/177\/revisions\/798"}],"up":[{"embeddable":true,"href":"https:\/\/synchrotron-light.net\/wp\/index.php?rest_route=\/wp\/v2\/pages\/79"}],"wp:attachment":[{"href":"https:\/\/synchrotron-light.net\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}