"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Latex(r\"$\\sigma_t = $ %.1f ps, while $\\gamma\\tau_0 = $ %.1f ps.\" % (sigma_t*1e12, gamma_0*tau_0*1e12))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can calculate the excitation probability for every ion in the bunch."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We define Doppler factor $f_D = \\gamma (1 + \\beta \\cos\\theta)$."
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [],
"source": [
"f_D = gamma_0*(1+dp)*(1+beta_0*np.cos(theta_l))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then $\\omega_l'$ "
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [],
"source": [
"omega_l = 2*np.pi/(lambda_l/c)*f_D"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [],
"source": [
"sigma_average = sigma_0*sigma_t/(tau_0*f_D) * \\\n",
" np.sqrt(2*np.pi)/4 * \\\n",
" np.exp(-np.power( (omega_0 - omega_l)/(sigma_w*f_D) , 2)/2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Position of the laser center at the time of collision $\\boldsymbol{r}_l = \\boldsymbol{a} + c(t_{\\mathrm{col}}-t_l)\\boldsymbol{n}$:"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"x_l = ax + c*(t_col-t_l)*nx\n",
"y_l = ay + c*(t_col-t_l)*ny\n",
"z_l = az + c*(t_col-t_l)*nz"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Distance to the laser center r2 = $(\\boldsymbol{r} - \\boldsymbol{r}_l)^2$"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [],
"source": [
"r2 = (x_col-x_l)*(x_col-x_l) + (y_col-y_l)*(y_col-y_l) + (z_col-z_l)*(z_col-z_l)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's find the laser pulse width\n",
"\n",
"$$\n",
"w = w_0 \\sqrt{1 + \\left(\\frac{\\boldsymbol{r}_l - \\boldsymbol{a}}{z_R}\\right)^2}.\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [],
"source": [
"w = w_0*np.sqrt( 1 + ((x_l-ax)*(x_l-ax) + (y_l-ay)*(y_l-ay) + (z_l-az)*(z_l-az))/(z_R*z_R) )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And finally number of excitation events for every ion can be found as\n",
"\n",
"$$\n",
"\\frac{dN_{\\hbar \\omega}}{dS} \\bar\\sigma = \\frac{2N_{\\hbar\\omega}}{\\pi w^2} \\exp \\left(-\\frac{2(\\boldsymbol{r} - \\boldsymbol{r}_l)^2}{w^2}\\right) \\bar\\sigma,\n",
"$$\n",
"\n",
"$$\n",
"N_{exc} = \\frac{1 - \\exp\\left[-(1+B)\\frac{dN_{\\hbar \\omega}}{dS} \\bar\\sigma \\right]}{1+B}.\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [],
"source": [
"N_exc = 2*N_hw/(np.pi*w*w)*np.exp(-2*r2/w/w)*sigma_average\n",
"N_exc = (1 - np.exp(-1*(1+g1/g2)*N_exc))/(1+g1/g2)"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Points [z,N_exc]"
]
},
"execution_count": 51,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"#%output backend='matplotlib' fig='png' size=250\n",
"#%opts Points [aspect=3]\n",
"\n",
"hv.Points((z*1e3, N_exc), [dim_z,\"N_exc\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since we treat $N_{exc}$ as the probability of ion excitation, let's randomply select excited atoms according to their $N_{exc}$ value:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For every ion select a random number from 0 to 1:"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [],
"source": [
"rnd = np.random.uniform(size=Np)"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Points [z,rnd]"
]
},
"execution_count": 53,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points((z*1e3, rnd), [dim_z,\"rnd\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And we count the ion as excited if its N_exc value is larger than the rnd value:"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [],
"source": [
"Excited = N_exc > rnd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Plot excited ions:"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [],
"source": [
"%opts Points.Excited (alpha=0.8, color='black')\n",
"%opts Points.Still (alpha=0.3)"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Overlay\n",
" .Still.I :Points [z,y]\n",
" .Excited.I :Points [z,y]"
]
},
"execution_count": 56,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points((z*1e3, y*1e3), [dim_z,dim_y], group='Still') * \\\n",
"hv.Points((z[Excited]*1e3, y[Excited]*1e3), [dim_z,dim_y], group='Excited')"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Overlay\n",
" .Still.I :Points [z,dp]\n",
" .Excited.I :Points [z,dp]"
]
},
"execution_count": 57,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points((z*1e3, dp*100), [dim_z,dim_dp], group='Still') * \\\n",
"hv.Points((z[Excited]*1e3, dp[Excited]*100), [dim_z,dim_dp], group='Excited')"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"13.5% of all ions are excited.\n"
]
}
],
"source": [
"print(\"%.1f%% of all ions are excited.\" % (100*len(z[Excited])/len(z)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Photon emissions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The effect of photon absorption on the ion momentum in the lab frame can be neglected. We should take into account only the emitted photon. On every turn we will select a random direction of photon emission in the ion's frame of reference. The random polar angle $\\theta_1'$ can be obtained as arccos of uniformly distributed random number from $-1$ to $+1$. Then using the above expressions we can find the frequency of the scattered photon as well as $\\theta_1$ angle between the initial ion momentum and the direction of photon emission in the lab frame. Finally a random azimuthal angle (from $0$ to $2\\pi$) is needed to get the direction of photon scattering in the plane which is perpendicular to the initial ion momentum."
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"# random polar angle in the ion's frame:\n",
"costheta = np.random.uniform(-1,+1, size=Np)\n",
"theta1p = np.arccos(costheta)\n",
"\n",
"# emitted photon energy in the lab frame:\n",
"hw1_emitted = gamma_0*(1+dp) * ( 1 + beta_0*np.cos(theta1p) )*hw0 # eV\n",
"# only excited atoms are emitting of course:\n",
"hw1_emitted = hw1_emitted*Excited\n",
"\n",
"dp = dp - hw1_emitted/(gamma_0*mc)"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Overlay\n",
" .Still.I :Points [z,dp]\n",
" .Excited.I :Points [z,dp]"
]
},
"execution_count": 60,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"hv.Points((z*1e3, dp*100), [dim_z,dim_dp], group='Still') * \\\n",
"hv.Points((z[Excited]*1e3, dp[Excited]*100), [dim_z,dim_dp], group='Excited')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's summarize the above theory into the python function to simulate the process of ion excitations and photon emissions in a turn-by-turn simulation."
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [],
"source": [
"X = np.matrix([\n",
" x ,\n",
" xp,\n",
" y ,\n",
" yp,\n",
" z ,\n",
" dp\n",
"])"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [],
"source": [
"def ExciteIons(X):\n",
" # Returns a vector of ion states after interaction with the laser: Excited / Not excited.\n",
"\n",
" x = X[0].A1; xp = X[1].A1; y = X[2].A1; yp = X[3].A1; z = X[4].A1; dp = X[5].A1\n",
" \n",
" vz = c*beta_0\n",
"\n",
" vx = vz*xp\n",
" vy = vz*yp\n",
" \n",
" t_col = ((x-ax)*nx + (y-ay)*ny + (z-az)*nz + c*t_l) / (c - (vx*nx+vy*ny+vz*nz)) # sec\n",
" \n",
" x_col = x + vx*t_col # m\n",
" y_col = y + vy*t_col # m\n",
" z_col = z + vz*t_col # m\n",
" \n",
" f_D = gamma_0*(1+dp)*(1+beta_0*np.cos(theta_l))\n",
" omega_l = 2*np.pi/(lambda_l/c)*f_D\n",
" sigma_average = sigma_0*sigma_t/(tau_0*f_D) * \\\n",
" np.sqrt(2*np.pi)/4 * \\\n",
" np.exp(-np.power( (omega_0 - omega_l)/(sigma_w*f_D) , 2)/2)\n",
" \n",
" x_l = ax + c*(t_col-t_l)*nx\n",
" y_l = ay + c*(t_col-t_l)*ny\n",
" z_l = az + c*(t_col-t_l)*nz\n",
" \n",
" r2 = (x_col-x_l)*(x_col-x_l) + (y_col-y_l)*(y_col-y_l) + (z_col-z_l)*(z_col-z_l)\n",
" \n",
" w = w_0*np.sqrt( 1 + ((x_l-ax)*(x_l-ax) + (y_l-ay)*(y_l-ay) + (z_l-az)*(z_l-az))/(z_R*z_R) )\n",
" \n",
" N_exc = 2*N_hw/(np.pi*w*w)*np.exp(-2*r2/w/w)*sigma_average\n",
" N_exc = (1 - np.exp(-1*(1+g1/g2)*N_exc))/(1+g1/g2)\n",
" \n",
" rnd = np.random.uniform(size=Np)\n",
" \n",
" Excited = N_exc > rnd\n",
" \n",
" return Excited"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Overlay\n",
" .Still.I :Points [z,dp]\n",
" .Excited.I :Points [z,dp]"
]
},
"execution_count": 63,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"Excited = ExciteIons(X)\n",
"\n",
"hv.Points((z*1e3, dp*100), [dim_z,dim_dp], group='Still') * \\\n",
"hv.Points((z[Excited]*1e3, dp[Excited]*100), [dim_z,dim_dp], group='Excited')"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [],
"source": [
"def EmitPhotons(X, Excited):\n",
" # Returns vector of emitted photons and vector X after photon emissions\n",
" \n",
" x = X[0].A1; xp = X[1].A1; y = X[2].A1; yp = X[3].A1; z = X[4].A1; dp = X[5].A1\n",
" \n",
" Np_Excited = len(x[Excited])\n",
" \n",
" # random polar angle in the ion's frame:\n",
" cos_theta1p = np.random.uniform(-1,+1, size=Np_Excited)\n",
" theta1p = np.arccos(cos_theta1p)\n",
" \n",
" # emission angle in the lab frame:\n",
" sin_theta1 = np.sin(theta1p)/(gamma_0 * (1+dp[Excited]) * ( 1 + beta_0*np.cos(theta1p) ))\n",
" theta1 = np.arcsin(sin_theta1)\n",
" \n",
" # azimuthal angle of emission:\n",
" phi1 = np.random.uniform(0,2*np.pi, size=Np_Excited)\n",
"\n",
" # emitted photon energy in the lab frame:\n",
" hw1_emitted = gamma_0*(1+dp[Excited]) * ( 1 + beta_0*np.cos(theta1p) )*hw0 # eV\n",
"\n",
"\n",
" # duration of time between the ion excitation and photon emission (in the lab frame):\n",
" dt_excited = gamma_0*np.random.exponential(scale=tau_0, size=Np_Excited) # seconds\n",
"\n",
" # distance travelled by the ion between its excitation and photon emission:\n",
" ds = dt_excited*c # meters\n",
"\n",
" # emitted photon location:\n",
" s_photon = z[Excited] + ds\n",
" x_photon = x[Excited] + ds*xp[Excited]\n",
" y_photon = y[Excited] + ds*yp[Excited]\n",
"\n",
" p_photon = hw1_emitted # eV/c\n",
" pz_photon = p_photon*np.cos(theta1)\n",
" pt_photon = p_photon*np.sin(theta1) # photon transverse momentum\n",
" px_photon = pt_photon*np.cos(phi1)\n",
" py_photon = pt_photon*np.sin(phi1)\n",
" \n",
" xp_photon = px_photon/pz_photon # rad\n",
" yp_photon = py_photon/pz_photon # rad\n",
" \n",
" # The effect of photon emission on ion is noticeble only in the dp value (see earlier explanation):\n",
" dp[Excited] = dp[Excited] - hw1_emitted/(gamma_0*mc)\n",
" \n",
" Photons = np.matrix([\n",
" x_photon,\n",
" xp_photon,\n",
" y_photon,\n",
" yp_photon,\n",
" s_photon,\n",
" p_photon\n",
" ])\n",
" \n",
" X1 = np.matrix([\n",
" x ,\n",
" xp,\n",
" y ,\n",
" yp,\n",
" z ,\n",
" dp\n",
" ])\n",
" \n",
" return X1, Photons"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [],
"source": [
"X1, Photons = EmitPhotons(X, Excited)"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Layout\n",
" .Points.I :Points [s,x]\n",
" .Points.II :Points [xp_photon,x]"
]
},
"execution_count": 66,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"#%output backend='matplotlib' fig='png' size=150\n",
"#%opts Points [aspect=2]\n",
"\n",
"x_photon = Photons[0].A1\n",
"xp_photon = Photons[1].A1\n",
"s_photon = Photons[4].A1\n",
"p_photon = Photons[5].A1\n",
"\n",
"dim_s = hv.Dimension('s', unit='m')# , range=(-600.0,+600.0))\n",
"dim_xp_photon = hv.Dimension('xp_photon', unit='mrad', label=\"x'\", range=(-100,+100))\n",
"\n",
"hv.Points((s_photon,x_photon*1e3), [dim_s,dim_x]) + \\\n",
"hv.Points((xp_photon*1e3,x_photon*1e3), [dim_xp_photon,dim_x])"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Layout\n",
" .Points.I :Points [s,p_photon]\n",
" .Points.II :Points [xp_photon,p_photon]"
]
},
"execution_count": 67,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"dim_p_photon = hv.Dimension('p_photon', unit='keV', label=\"Photon energy\") #, range=(0,None))\n",
"\n",
"hv.Points((s_photon,p_photon/1e3), [dim_s,dim_p_photon]) + \\\n",
"hv.Points((xp_photon*1e3,p_photon/1e3), [dim_xp_photon,dim_p_photon])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And now we can do the full 1-turn tracking of the ion beam."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Transverse 1-turn matrix\n",
"\n",
"The expressions will be written for the general coupled case (in x-y) but with matrix elements simplified for the uncoupled case. 1-turn matrix in the uncoupled case can be expressed in the Twiss parametrization."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Full 1-turn matrix (excluding RF-effects) can be written as\n",
"\n",
"$$\n",
"\\begin{pmatrix}\n",
"x \\\\\n",
"x' \\\\\n",
"y \\\\\n",
"y' \\\\\n",
"\\Delta l \\\\\n",
"\\Delta p/p\n",
"\\end{pmatrix}_{n+1} =\n",
"\\begin{pmatrix}\n",
"R_{11} & R_{12} & R_{13} & R_{14} & 0 & R_{16} \\\\\n",
"R_{21} & R_{22} & R_{23} & R_{24} & 0 & R_{26} \\\\\n",
"R_{31} & R_{32} & R_{33} & R_{34} & 0 & R_{36} \\\\\n",
"R_{41} & R_{42} & R_{43} & R_{44} & 0 & R_{46} \\\\\n",
"R_{51} & R_{52} & R_{53} & R_{54} & 1 & R_{56} \\\\\n",
"0 & 0 & 0 & 0 & 0 & 1\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"x \\\\\n",
"x' \\\\\n",
"y \\\\\n",
"y' \\\\\n",
"0 \\\\\n",
"\\Delta p/p\n",
"\\end{pmatrix}_n,\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"where $n$ is the turn number."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the notation used here $\\Delta l$ is the path length difference between the trajectory of the particle with these particular coordinates and the central particle. $\\Delta l$ can be used to find the longitudinal particle coordinate along the bunch $z$ (used earlier). Since particles with different momentum move with different velocity\n",
"\n",
"$$\n",
"z_{n+1} = z_n - \\Delta l_{n+1} + T_s \\Delta \\upsilon,\n",
"$$\n",
"\n",
"where $T_s$ is the revolution period and\n",
"\n",
"$$\n",
"\\Delta \\upsilon = \\upsilon_s \\frac{1}{\\gamma^2}\\frac{\\Delta p}{p},\n",
"$$\n",
"\n",
"where $\\upsilon_s$ is the reference ion velocity. Therefore \n",
"\n",
"$$\n",
"z_{n+1} = z_n - \\Delta l_{n+1} + T_s \\upsilon_s \\frac{1}{\\gamma^2}\\frac{\\Delta p}{p} = z_n - \\Delta l_{n+1} + \\frac{L}{\\gamma^2}\\frac{\\Delta p}{p},\n",
"$$\n",
"\n",
"where $T_s \\upsilon_s = L$ is the ring circumference."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So we can replace $\\Delta l$ with $z$ in the above matrix 1-turn expression:\n",
"\n",
"$$\n",
"\\begin{pmatrix}\n",
"x \\\\\n",
"x' \\\\\n",
"y \\\\\n",
"y' \\\\\n",
"z \\\\\n",
"\\Delta p/p\n",
"\\end{pmatrix}_{n+1} =\n",
"\\begin{pmatrix}\n",
"R_{11} & R_{12} & R_{13} & R_{14} & 0 & R_{16} \\\\\n",
"R_{21} & R_{22} & R_{23} & R_{24} & 0 & R_{26} \\\\\n",
"R_{31} & R_{32} & R_{33} & R_{34} & 0 & R_{36} \\\\\n",
"R_{41} & R_{42} & R_{43} & R_{44} & 0 & R_{46} \\\\\n",
"-R_{51} & -R_{52} & -R_{53} & -R_{54} & 1 & -R_{56} + L\\gamma^{-2} \\\\\n",
"0 & 0 & 0 & 0 & 0 & 1\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"x \\\\\n",
"x' \\\\\n",
"y \\\\\n",
"y' \\\\\n",
"z \\\\\n",
"\\Delta p/p\n",
"\\end{pmatrix}_n.\n",
"$$ "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Effects of RF-resonators should be included separately because in our case the longitudinal nonlinearity of RF is often important."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The expression looks more simple in the uncoupled case:\n",
"\n",
"$$\n",
"\\begin{pmatrix}\n",
"x \\\\\n",
"x' \\\\\n",
"y \\\\\n",
"y' \\\\\n",
"z \\\\\n",
"\\Delta p/p\n",
"\\end{pmatrix}_{n+1} =\n",
"\\begin{pmatrix}\n",
"R_{11} & R_{12} & 0 & 0 & 0 & R_{16} \\\\\n",
"R_{21} & R_{22} & 0 & 0 & 0 & R_{26} \\\\\n",
"0 & 0 & R_{33} & R_{34} & 0 & 0 \\\\\n",
"0 & 0 & R_{43} & R_{44} & 0 & 0 \\\\\n",
"-R_{51} & -R_{52} & 0 & 0 & 1 & -R_{56} + L\\gamma^{-2} \\\\\n",
"0 & 0 & 0 & 0 & 0 & 1\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"x \\\\\n",
"x' \\\\\n",
"y \\\\\n",
"y' \\\\\n",
"z \\\\\n",
"\\Delta p/p\n",
"\\end{pmatrix}_n.\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since the closed orbit with some momentum offset is given by\n",
"\n",
"$$\n",
"\\begin{pmatrix}\n",
"x \\\\\n",
"x'\n",
"\\end{pmatrix} =\n",
"\\begin{pmatrix}\n",
"D_x \\\\\n",
"D'_x\n",
"\\end{pmatrix}\n",
"\\frac{\\Delta p}{p},\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"we can find the $R_{16}$ and $R_{26}$ matrix elements from the vales of dispersion functions defined earlier\n",
"\n",
"$$\n",
"\\begin{pmatrix}\n",
"D_x \\\\\n",
"D'_x\n",
"\\end{pmatrix}\n",
"\\frac{\\Delta p}{p} =\n",
"\\begin{pmatrix}\n",
"R_{11} & R_{12} \\\\\n",
"R_{21} & R_{22}\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"D_x \\\\\n",
"D'_x\n",
"\\end{pmatrix}\n",
"\\frac{\\Delta p}{p} +\n",
"\\begin{pmatrix}\n",
"R_{16} \\\\\n",
"R_{26} \\\\\n",
"\\end{pmatrix}\n",
"\\frac{\\Delta p}{p}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"therefore\n",
"\n",
"$$\n",
"\\begin{pmatrix}\n",
"R_{16} \\\\\n",
"R_{26}\n",
"\\end{pmatrix} = \n",
"\\begin{pmatrix}\n",
"D_x \\\\\n",
"D'_x\n",
"\\end{pmatrix} -\n",
"\\begin{pmatrix}\n",
"R_{11} & R_{12} \\\\\n",
"R_{21} & R_{22}\n",
"\\end{pmatrix}\n",
"\\begin{pmatrix}\n",
"D_x \\\\\n",
"D'_x\n",
"\\end{pmatrix}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the uncoupled case the 1-turn matrix can be written in Twiss as\n",
"\n",
"$$\n",
"\\begin{pmatrix}\n",
"R_{11} & R_{12} \\\\\n",
"R_{21} & R_{22} \\\\\n",
"\\end{pmatrix} = \n",
"\\begin{pmatrix}\n",
"\\cos\\mu_x + \\alpha_x\\sin\\mu_x & \\beta_x \\sin\\mu_x \\\\\n",
"-\\gamma_x \\sin\\mu_x & \\cos\\mu_x - \\alpha_x \\sin\\mu_x \\\\\n",
"\\end{pmatrix},\n",
"$$\n",
"\n",
"where $\\mu_x = 2\\pi\\nu_x$ ($\\nu_x$ -- betatron tune), $\\alpha_x = -\\beta'_x / 2$, $\\gamma_x = (1 + \\alpha_x^2)/\\beta_x$.\n",
"\n",
"And the same for the y-plane."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The matrix elements $R_{51}$ and $R_{52}$ can be found from the symplecticity of the full-turn matrix $M$ as described in Analytical Tools in Accelerator Physics by V. Litvinenko (page 43, equation L3-53):\n",
"\n",
"$$\n",
"-R_{51} = R_{16}R_{21} - R_{26}R_{11}, \\\\\n",
"-R_{52} = R_{16}R_{22} - R_{26}R_{12}.\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [],
"source": [
"# For the SPS Q26 optics the betatron tunes are:\n",
"\n",
"nux = 26.12999969\n",
"nuy = 26.17999991\n",
"\n",
"mux = 2*np.pi*nux\n",
"muy = 2*np.pi*nuy\n",
"\n",
"R11 = np.cos(mux) + alpha_x*np.sin(mux); R12 = beta_x*np.sin(mux)\n",
"R21 = -(1+alpha_x*alpha_x)*np.sin(mux)/beta_x; R22 = np.cos(mux) - alpha_x*np.sin(mux)\n",
"\n",
"R33 = np.cos(muy) + alpha_y*np.sin(muy); R34 = beta_y*np.sin(muy)\n",
"R43 = -(1+alpha_y*alpha_y)*np.sin(muy)/beta_y; R44 = np.cos(muy) - alpha_y*np.sin(muy)\n",
"\n",
"R16 = Dx - (Dx*R11 + Dpx*R12)\n",
"R26 = Dpx - (Dx*R21 + Dpx*R22)\n",
"\n",
"R51 = R26*R11 - R16*R21\n",
"R52 = R26*R12 - R16*R22\n",
"\n",
"gamma_t = 22.77422909 # gamma transition in the ring\n",
"\n",
"R56 = L/(gamma_t*gamma_t)"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [],
"source": [
"M = np.matrix([\n",
" [ R11, R12, 0 , 0 , 0 , R16],\n",
" [ R21, R22, 0 , 0 , 0 , R26],\n",
" [ 0 , 0 , R33, R34, 0 , 0 ],\n",
" [ 0 , 0 , R43, R44, 0 , 0 ],\n",
" [-R51, -R52, 0 , 0 , 1 , -R56+L/(gamma_0*gamma_0)],\n",
" [ 0 , 0 , 0 , 0 , 0 , 1 ]\n",
"])"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-4.346e-01 +3.981e+01 +0.000e+00 +0.000e+00 +0.000e+00 -3.754e-01 \n",
"\n",
"-4.481e-02 +1.804e+00 +0.000e+00 +0.000e+00 +0.000e+00 +3.116e-02 \n",
"\n",
"+0.000e+00 +0.000e+00 +1.615e+00 +4.011e+01 +0.000e+00 +0.000e+00 \n",
"\n",
"+0.000e+00 +0.000e+00 -5.566e-02 -7.633e-01 +0.000e+00 +0.000e+00 \n",
"\n",
"+3.036e-02 -1.918e+00 +0.000e+00 +0.000e+00 +1.000e+00 -1.258e+01 \n",
"\n",
"+0.000e+00 +0.000e+00 +0.000e+00 +0.000e+00 +0.000e+00 +1.000e+00 \n",
"\n"
]
}
],
"source": [
"for row in M:\n",
" for itm in row.A1:\n",
" print(\"%+.3e \" % itm, end=\"\")\n",
" print(\"\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" From SPS_optics:\n",
"\n",
"\n",
"\n",
"-4.346e-01 +3.981e+01 +0.000e+00 +0.000e+00 +0.000e+00 -3.754e-01 \n",
"\n",
"-4.481e-02 +1.804e+00 +0.000e+00 +0.000e+00 +0.000e+00 +3.116e-02 \n",
"\n",
"+0.000e+00 +0.000e+00 +1.615e+00 +4.011e+01 +0.000e+00 +0.000e+00 \n",
"\n",
"+0.000e+00 +0.000e+00 -5.566e-02 -7.633e-01 +0.000e+00 +0.000e+00 \n",
"\n",
"+3.036e-02 -1.918e+00 +0.000e+00 +0.000e+00 +1.000e+00 -1.318e+01 \n",
"\n",
"+0.000e+00 +0.000e+00 +0.000e+00 +0.000e+00 +0.000e+00 +1.000e+00 \n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can quickly test that the 1-turn transformation is not changing the beam distribution:\n",
"\n",
"Initial distribution:"
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {},
"outputs": [],
"source": [
"def plot_xxp_yyp(X):\n",
" x = X[0].A1 # .A1 converts matrix into 1D-array\n",
" xp = X[1].A1\n",
" y = X[2].A1\n",
" yp = X[3].A1\n",
" \n",
" return hv.Points((x*1e3,xp*1e3), kdims=[dim_x,dim_xp]) + hv.Points((y*1e3,yp*1e3), kdims=[dim_y,dim_yp])"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Layout\n",
" .Points.I :Points [x,xp]\n",
" .Points.II :Points [y,yp]"
]
},
"execution_count": 72,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"plot_xxp_yyp(X)"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Layout\n",
" .Points.I :Points [x,xp]\n",
" .Points.II :Points [y,yp]"
]
},
"execution_count": 73,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"# test one turn:\n",
"X1 = M*X\n",
"# test many turns\n",
"#X1 = M*M*M*M*M*M*M*M*M*M*M*M*M*M*M*M*M*M*M*X\n",
"\n",
"plot_xxp_yyp(X1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Effects of RF-resonator"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The transverse cooling happens because RF-resonator restores only the longitudinal component $p_z$ of the ion momentum, while the photon emission reduces the full momentum $p$. So, in order to simulate the transverse radiative cooling we need to take into account the resonator effect not only on $\\Delta p/p$ but also on the angles $x'$ and $y'$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Longitudinal momentum gain of the ion after it has passed through the RF-resonator depends on the ion phase with respect to the RF:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$$\n",
"\\frac{dp_z}{dt} = e(Z-N_e)E_{\\rm{RF}}\\cos\\phi,\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"where $E_{\\rm{RF}}$ is the accelerating electric field and $\\phi$ is the ion phase in the RF resonator. The resulting longitudinal momentum change:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$$\n",
"\\delta p_z = e(Z-N_e)\\frac{ V_{\\rm{RF}} }{ L_{\\rm{RF}}} (\\cos\\phi) \\Delta t = e(Z-N_e)\\frac{ V_{\\rm{RF}} }{\\upsilon_z} \\cos\\phi,\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"where $V_{\\rm{RF}}$ is the RF-voltage, $\\upsilon_z$ is the ion velocity."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since $x' = p_x/p_z$ and $p_x$ is not changed in the resonator the angle $x'$ after the resonator"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$$\n",
"x' + \\delta x' = \\frac{p_x}{p_z + \\delta p_z} = x' \\left ( 1+\\frac{\\delta p_z} {p_z} \\right )^{-1}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"RF-resonator frequency $f_{\\rm{RF}}$ is some high harmonic $h$ of ion revolution frequency:\n",
"\n",
"$$\n",
"f_{\\rm{RF}} = \\frac{h}{T_s},\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Longitudinal coordinate $z$ gives the longitudinal distance from the ion to the reference particle at the moment when the reference particle arrives at the RF-phase $\\phi_0$ (which is always the same). So the ion then arrives to the RF-resonator after the time\n",
"\n",
"$$\n",
"\\Delta T = -\\frac{z}{\\upsilon_z} \\approx -\\frac{z}{\\upsilon_s}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then the ion phase in the RF-resonator is\n",
"\n",
"$$\n",
"\\phi = \\phi_0 + 2\\pi f_{\\rm{RF}}\\Delta T = \\phi_0 - 2\\pi \\frac{hz}{T_s\\upsilon_z} \\approx \\phi_0 - 2\\pi \\frac{hz}{L}.\n",
"$$"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {},
"outputs": [],
"source": [
"# Pass beam through the RF-resonator:\n",
"\n",
"def RFcavity(X, h, eVrf, phi0):\n",
" # returns vector X after RF-cavity\n",
"\n",
" x = X[0].A1; xp = X[1].A1; y = X[2].A1; yp = X[3].A1; z = X[4].A1; dp = X[5].A1\n",
" \n",
" p = p0 + p0*dp # eV/c\n",
" # since p*p = px*px + py*py + pz*pz, and px = pz*x', py=pz*y':\n",
" pz = p/np.sqrt(1+xp*xp+yp*yp)\n",
" px = pz*xp\n",
" py = pz*yp\n",
"\n",
" v0 = c/np.sqrt(1 + mc*mc/(p0*p0))\n",
" v = c/np.sqrt(1 + mc*mc/(p*p))\n",
" vz = v*pz/p\n",
" \n",
" # phase in the resonator: \n",
" phi = phi0 - 2*np.pi*h*(z/L)*v0/vz\n",
"\n",
" pz = pz + eVrf*(Z-Ne)*np.cos(phi)/beta_0 # pz after RF-cavity \n",
" \n",
" xp = px/pz\n",
" yp = py/pz\n",
" \n",
" p = np.sqrt(px*px+py*py+pz*pz)\n",
" dp = (p-p0)/p0 # new relative momentum deviation\n",
" \n",
" return np.matrix([\n",
" x ,\n",
" xp,\n",
" y ,\n",
" yp,\n",
" z ,\n",
" dp\n",
" ])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Multi-turn tracking"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we can check if our implementation of RF-cavity is changing the transverse beam emittance (because we've included higher-order effects)."
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"turn = 100000 (100 %)"
]
}
],
"source": [
"N_turns = 100000\n",
"N_plots = 11\n",
"\n",
"h = 4620 # SPS 200 MHz\n",
"eVrf = 7e6 # eV\n",
"phi0 = np.pi/2\n",
"\n",
"t_plots = np.arange(0,N_turns+1,int(N_turns/(N_plots-1)))\n",
"\n",
"X_plots = {}\n",
"\n",
"X1 = X;\n",
"for turn in range(0,N_turns+1):\n",
" if turn in t_plots:\n",
" print( \"\\rturn = %g (%g %%)\" % (turn, (100*turn/N_turns)), end=\"\")\n",
" X_plots[turn] = X1\n",
" X1 = RFcavity(X1, h, eVrf, phi0)\n",
" X1 = M*X1"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Area [z] (I)"
]
},
"execution_count": 76,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"# function to calculate beam current profile:\n",
"def get_I(z, z_bin = 5e-3, z_min=-0.4, z_max=+0.4):\n",
" # z, z_bin, z_min, z_max in meters\n",
" \n",
" hist, bins = np.histogram( z, range=(z_min, z_max), bins=int((z_max-z_min)/z_bin) )\n",
" Qm = Qe*(Z-Ne)*N_ions/Np # macroparticle charge in C\n",
" I = hist*Qm/(z_bin/c) # A\n",
"\n",
" z_centers = (bins[:-1] + bins[1:]) / 2\n",
" \n",
" return z_centers, I\n",
"\n",
"%opts Area [show_grid=True aspect=2] (linewidth=1, alpha=0.7)\n",
"\n",
"z_centers, I = get_I(z)\n",
"\n",
"dim_I = hv.Dimension('I', unit='A', range=(0.0,+4.0))\n",
"\n",
"z_I = hv.Area((z_centers*1e3, I), kdims=[dim_z], vdims=[dim_I])\n",
"\n",
"z_I"
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {},
"outputs": [],
"source": [
"# plot z-dp + beam current profile:\n",
"def plot_z_dp(X):\n",
" z = X[4].A1\n",
" dp = X[5].A1\n",
" z_centers, I = get_I(z)\n",
" img = (hv.Points((z*1e3, dp*100), [dim_z,dim_dp]) + \\\n",
" hv.Area((z_centers*1e3, I), kdims=[dim_z], vdims=[dim_I]) ).cols(1)\n",
" return img"
]
},
{
"cell_type": "code",
"execution_count": 78,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
],
"text/plain": [
":Layout\n",
" .Points.I :Points [z,dp]\n",
" .Area.I :Area [z] (I)"
]
},
"execution_count": 78,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {}
},
"output_type": "execute_result"
}
],
"source": [
"plot_z_dp(X_plots[t_plots[-1]])"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"
\n",
"
\n",
" \n",
" \n",
" \n",
"
\n",
"
\n",
"
\n",
"
\n",
""
],
"text/plain": [
":Layout\n",
" .Points.I :HoloMap [t (sec)]\n",
" :Points [z,dp]\n",
" .Area.I :HoloMap [t (sec)]\n",
" :Area [z] (I)"
]
},
"execution_count": 79,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": 140260486533712
}
},
"output_type": "execute_result"
}
],
"source": [
"items = [(turn*L/c, (plot_z_dp(X_plots[turn]))) for turn in t_plots]\n",
"\n",
"m = hv.HoloMap(items, kdims = ['t (sec)'])\n",
"m.collate()"
]
},
{
"cell_type": "code",
"execution_count": 80,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"
\n",
"
\n",
" \n",
" \n",
" \n",
"
\n",
"
\n",
"
\n",
"
\n",
""
],
"text/plain": [
":Layout\n",
" .Points.I :HoloMap [t (sec)]\n",
" :Points [x,xp]\n",
" .Points.II :HoloMap [t (sec)]\n",
" :Points [y,yp]"
]
},
"execution_count": 80,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": 140260447643920
}
},
"output_type": "execute_result"
}
],
"source": [
"items = [(turn*L/c, plot_xxp_yyp(X_plots[turn])) for turn in t_plots]\n",
"\n",
"m = hv.HoloMap(items, kdims = ['t (sec)'])\n",
"m.collate()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### And finally the full turn-by-turn Monte Carlo simulation including photon emissions"
]
},
{
"cell_type": "code",
"execution_count": 81,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"turn = 1e+06 (100 %, 0 h. 0 min. left))"
]
}
],
"source": [
"import time\n",
"\n",
"N_turns = 1000000\n",
"#N_turns = 2000000\n",
"\n",
"N_plots = 21\n",
"\n",
"t_plots = np.arange(0,N_turns+1,int(N_turns/(N_plots-1)))\n",
"\n",
"X_plots = {}\n",
"Excited_plots = {}\n",
"\n",
"X1 = X;\n",
"T_start = time.time()\n",
"for turn in range(0,N_turns+1):\n",
" Excited = ExciteIons(X1)\n",
"\n",
" if turn in t_plots:\n",
" if turn != t_plots[0]:\n",
" sec_left = ((time.time() - T_start)/turn)*(N_turns - turn)\n",
" hours_left = np.floor(sec_left/3600)\n",
" min_left = (sec_left - hours_left*3600)/60\n",
" print( \"\\rturn = %g (%g %%, %g h. %.0f min. left)\" %\n",
" (turn, (100*turn/N_turns), hours_left, min_left), end=\"\")\n",
" X_plots[turn] = X1\n",
" Excited_plots[turn] = Excited\n",
"\n",
" X1, Photons = EmitPhotons(X1, Excited)\n",
" X1 = RFcavity(X1, h, eVrf, phi0)\n",
" X1 = M*X1"
]
},
{
"cell_type": "code",
"execution_count": 82,
"metadata": {},
"outputs": [],
"source": [
"#X_plots"
]
},
{
"cell_type": "code",
"execution_count": 83,
"metadata": {},
"outputs": [],
"source": [
"np.save(\"X_plots.npy\", X_plots)"
]
},
{
"cell_type": "code",
"execution_count": 84,
"metadata": {},
"outputs": [],
"source": [
"def plot_z_dp_Excited(X,Excited):\n",
" z = X[4].A1\n",
" dp = X[5].A1\n",
"\n",
" txt = \"%.1f%% of ions excited\" % (100*len(z[Excited])/len(z))\n",
"\n",
" z_centers, I = get_I(z, z_bin = 1e-3)\n",
" img = (hv.Points((z*1e3, dp*100), [dim_z,dim_dp], group='Still') * \\\n",
" hv.Points((z[Excited]*1e3, dp[Excited]*100), [dim_z,dim_dp], group='Excited', label=txt) + \\\n",
" hv.Area((z_centers*1e3, I), kdims=[dim_z], vdims=[dim_I]) ).cols(1)\n",
" \n",
" return img"
]
},
{
"cell_type": "code",
"execution_count": 85,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"
\n",
"
\n",
" \n",
" \n",
" \n",
"
\n",
"
\n",
"
\n",
"
\n",
""
],
"text/plain": [
":Layout\n",
" .Overlay.I :HoloMap [t (sec)]\n",
" :Overlay\n",
" .Still.I :Points [z,dp]\n",
" .Excited.A_18_full_stop_8_percent_of_ions_excited :Points [z,dp]\n",
" .Area.I :HoloMap [t (sec)]\n",
" :Area [z] (I)"
]
},
"execution_count": 85,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": 140260477082128
}
},
"output_type": "execute_result"
}
],
"source": [
"#dim_I = hv.Dimension('I', unit='A', range=(0.0,+100.0))\n",
"dim_I = hv.Dimension('I', unit='A', range=(0.0,+8.0))\n",
"\n",
"items = [(turn*L/c, plot_z_dp_Excited(X_plots[turn],Excited_plots[turn])) for turn in t_plots]\n",
"\n",
"m = hv.HoloMap(items, kdims = ['t (sec)'])\n",
"m.collate()"
]
},
{
"cell_type": "code",
"execution_count": 86,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"
\n",
"
\n",
" \n",
" \n",
" \n",
"
\n",
"
\n",
"
\n",
"
\n",
""
],
"text/plain": [
":Layout\n",
" .Points.I :HoloMap [t (sec)]\n",
" :Points [x,xp]\n",
" .Points.II :HoloMap [t (sec)]\n",
" :Points [y,yp]"
]
},
"execution_count": 86,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": 140260434768976
}
},
"output_type": "execute_result"
}
],
"source": [
"items = [(turn*L/c, plot_xxp_yyp(X_plots[turn])) for turn in t_plots]\n",
"\n",
"m = hv.HoloMap(items, kdims = ['t (sec)'])\n",
"m.collate()"
]
},
{
"cell_type": "code",
"execution_count": 87,
"metadata": {},
"outputs": [],
"source": [
"def plot_z_y_Excited(X,Excited):\n",
" z = X[4].A1\n",
" y = X[2].A1\n",
"\n",
" txt = \"%.1f%% of ions excited\" % (100*len(z[Excited])/len(z))\n",
" \n",
" z_centers, I = get_I(z, z_bin = 1e-3)\n",
" img = (hv.Points((z*1e3, y*1e3), [dim_z,dim_y], group='Still') * \\\n",
" hv.Points((z[Excited]*1e3, y[Excited]*1e3), [dim_z,dim_y], group='Excited', label=txt) + \\\n",
" hv.Area((z_centers*1e3, I), kdims=[dim_z], vdims=[dim_I]) ).cols(1)\n",
" \n",
" return img"
]
},
{
"cell_type": "code",
"execution_count": 88,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"\n",
"
\n",
"
\n",
" \n",
" \n",
" \n",
"
\n",
"
\n",
"
\n",
"
\n",
""
],
"text/plain": [
":Layout\n",
" .Overlay.I :HoloMap [t (sec)]\n",
" :Overlay\n",
" .Still.I :Points [z,y]\n",
" .Excited.A_18_full_stop_8_percent_of_ions_excited :Points [z,y]\n",
" .Area.I :HoloMap [t (sec)]\n",
" :Area [z] (I)"
]
},
"execution_count": 88,
"metadata": {
"application/vnd.holoviews_exec.v0+json": {
"id": 140260285494864
}
},
"output_type": "execute_result"
}
],
"source": [
"items = [(turn*L/c, plot_z_y_Excited(X_plots[turn],Excited_plots[turn])) for turn in t_plots]\n",
"\n",
"m = hv.HoloMap(items, kdims = ['t (sec)'])\n",
"m.collate()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"\n",
"## Technical info:\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {},
"outputs": [],
"source": [
"%load_ext watermark"
]
},
{
"cell_type": "code",
"execution_count": 90,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"holoviews 1.12.6\n",
"numpy 1.17.2\n",
"2019-10-24 \n",
"\n",
"CPython 3.7.4\n",
"IPython 7.8.0\n",
"\n",
"compiler : GCC 7.3.0\n",
"system : Linux\n",
"release : 4.4.0-165-generic\n",
"machine : x86_64\n",
"processor : x86_64\n",
"CPU cores : 40\n",
"interpreter: 64bit\n"
]
}
],
"source": [
"%watermark --python --date --iversions --machine"
]
},
{
"cell_type": "code",
"execution_count": 91,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[NbConvertApp] Converting notebook psi_beam_vs_laser.ipynb to HTML\n",
"[NbConvertApp] Writing 4313792 bytes to psi_beam_vs_laser.html\n"
]
}
],
"source": [
"!jupyter nbconvert --to HTML psi_beam_vs_laser.ipynb"
]
},
{
"cell_type": "code",
"execution_count": 92,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'/home/petrenko/work/GF'"
]
},
"execution_count": 92,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pwd"
]
}
],
"metadata": {
"anaconda-cloud": {},
"hide_input": false,
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
}
},
"nbformat": 4,
"nbformat_minor": 4
}