Layout Plotting¶
In [1]:
Copied!
import os
import numpy as np
from impact import Impact
from impact.parsers import parse_impact_input
from impact.plotting import layout_plot
from impact.fieldmaps import ele_field, lattice_field
from bokeh.plotting import output_notebook
from bokeh.plotting import show
import matplotlib.pyplot as plt
from ipywidgets import interact
output_notebook(hide_banner=True)
import os
import numpy as np
from impact import Impact
from impact.parsers import parse_impact_input
from impact.plotting import layout_plot
from impact.fieldmaps import ele_field, lattice_field
from bokeh.plotting import output_notebook
from bokeh.plotting import show
import matplotlib.pyplot as plt
from ipywidgets import interact
output_notebook(hide_banner=True)
In [2]:
Copied!
infile = "templates/lcls_injector/ImpactT.in"
infile = "templates/lcls_injector/ImpactT.in"
matplotlib plotting from the Impact object¶
In [3]:
Copied!
I = Impact(infile)
I.plot(figsize=(12, 4))
I = Impact(infile)
I.plot(figsize=(12, 4))
In [4]:
Copied!
# Track 1 particle
I.track1()
# These are the fields seen by the bunch centroid
I.plot("Ez", y2="Bz")
# Track 1 particle
I.track1()
# These are the fields seen by the bunch centroid
I.plot("Ez", y2="Bz")
In [5]:
Copied!
# Fieldmaps can be added to existing axes
from impact.plot import add_fieldmaps_to_axes
fig, ax = plt.subplots()
add_fieldmaps_to_axes(I, t=1, ax=ax, bounds=(0, 10))
# Fieldmaps can be added to existing axes
from impact.plot import add_fieldmaps_to_axes
fig, ax = plt.subplots()
add_fieldmaps_to_axes(I, t=1, ax=ax, bounds=(0, 10))
Low-level get field¶
In [6]:
Copied!
# Get fieldmaps
fmaps = I.fieldmaps
# This shows the field from a single element
ele_field(I.ele["GUN"], z=0.1, fmaps=fmaps)
# Get fieldmaps
fmaps = I.fieldmaps
# This shows the field from a single element
ele_field(I.ele["GUN"], z=0.1, fmaps=fmaps)
Out[6]:
np.float64(1738690.5187003822)
In [7]:
Copied!
# this gets the total field from all elements in the lattice
lattice_field(I.lattice, z=0.3, fmaps=fmaps)
# this gets the total field from all elements in the lattice
lattice_field(I.lattice, z=0.3, fmaps=fmaps)
Out[7]:
np.float64(0.0)
In [8]:
Copied!
I.input["fieldmaps"].keys()
I.input["fieldmaps"].keys()
Out[8]:
dict_keys(['rfdata201', 'rfdata102', 'rfdata4', 'rfdata5', 'rfdata6', 'rfdata7'])
In [9]:
Copied!
# Period in ps
T = 1 / 2856000000.0
T / 1e-12 # ps
# Period in ps
T = 1 / 2856000000.0
T / 1e-12 # ps
Out[9]:
350.140056022409
In [10]:
Copied!
I = Impact(infile)
I.plot(figsize=(12, 4), field_t=0)
I = Impact(infile)
I.plot(figsize=(12, 4), field_t=0)
In [11]:
Copied!
# Make a function to get a field array at a given phase/2pi
zz = np.linspace(0, I.stop, 1000)
def field_at(phi0):
Ez_at = np.array([I.field(z=z, t=phi0 / 2856000000.0, component="Ez") for z in zz])
plt.plot(zz, Ez_at / 1e6)
plt.ylim(-100, 100)
# plt.xlim(2, 2.2)
# def field_at(phi0):
# t=phi0/2856000000.0
# fig = I.plot(figsize=(12,4), field_t=t, return_figure=True)
# fig.axes[0].set_ylim(-100,100)
# fig.axes[1].set_ylim(-0, 0.3)
field_at(0)
# Make a function to get a field array at a given phase/2pi
zz = np.linspace(0, I.stop, 1000)
def field_at(phi0):
Ez_at = np.array([I.field(z=z, t=phi0 / 2856000000.0, component="Ez") for z in zz])
plt.plot(zz, Ez_at / 1e6)
plt.ylim(-100, 100)
# plt.xlim(2, 2.2)
# def field_at(phi0):
# t=phi0/2856000000.0
# fig = I.plot(figsize=(12,4), field_t=t, return_figure=True)
# fig.axes[0].set_ylim(-100,100)
# fig.axes[1].set_ylim(-0, 0.3)
field_at(0)
In [12]:
Copied!
# Visualize the oscillating fields
interact(field_at, phi0=(0, 2, 0.01))
# Visualize the oscillating fields
interact(field_at, phi0=(0, 2, 0.01))
Out[12]:
<function __main__.field_at(phi0)>
In [13]:
Copied!
# These are the fields seen by the bunch
I.track1()
zz = I.stat("mean_z")
tt = I.stat("t")
Ez_seen = np.array(
[
lattice_field(I.lattice, z=z, t=t, fmaps=fmaps, component="Ez")
for z, t in zip(zz, tt)
]
)
zz = zz[: len(tt)]
plt.plot(zz, Ez_seen)
# These are the fields seen by the bunch
I.track1()
zz = I.stat("mean_z")
tt = I.stat("t")
Ez_seen = np.array(
[
lattice_field(I.lattice, z=z, t=t, fmaps=fmaps, component="Ez")
for z, t in zip(zz, tt)
]
)
zz = zz[: len(tt)]
plt.plot(zz, Ez_seen)
Out[13]:
[<matplotlib.lines.Line2D at 0x7f2bd54ff230>]
In [14]:
Copied!
# MeV energy gain
-np.trapz(Ez_seen, zz) / 1e6
# MeV energy gain
-np.trapz(Ez_seen, zz) / 1e6
/tmp/ipykernel_2340/1062521924.py:2: DeprecationWarning: `trapz` is deprecated. Use `trapezoid` instead, or one of the numerical integration functions in `scipy.integrate`. -np.trapz(Ez_seen, zz) / 1e6
Out[14]:
np.float64(34.272824268974844)
In [15]:
Copied!
# This is pretty close to the tracked kinetic energy
I.stat("mean_kinetic_energy")[-1] / 1e6
# This is pretty close to the tracked kinetic energy
I.stat("mean_kinetic_energy")[-1] / 1e6
Out[15]:
np.float64(34.269711)
Bokeh plotting from the input file¶
In [16]:
Copied!
infile = "templates/lcls_injector/ImpactT.in"
os.path.exists(infile)
dat = parse_impact_input(infile)
header = dat["header"]
lattice = dat["lattice"]
infile = "templates/lcls_injector/ImpactT.in"
os.path.exists(infile)
dat = parse_impact_input(infile)
header = dat["header"]
lattice = dat["lattice"]
In [17]:
Copied!
layout = layout_plot(lattice)
show(layout)
layout = layout_plot(lattice)
show(layout)
Output Plotting¶
In [18]:
Copied!
from bokeh.plotting import figure
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Range1d
from impact.parsers import load_many_fort
from impact.parsers import UNITS
from bokeh.plotting import figure
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Range1d
from impact.parsers import load_many_fort
from impact.parsers import UNITS
In [19]:
Copied!
opath = "templates/lcls_injector/output/"
data = load_many_fort(opath, verbose=True)
ds = ColumnDataSource(data)
opath = "templates/lcls_injector/output/"
data = load_many_fort(opath, verbose=True)
ds = ColumnDataSource(data)
Loaded fort 18 : Time and energy Loaded fort 24 : RMS X information Loaded fort 25 : RMS Y information Loaded fort 26 : RMS Z information Loaded fort 27 : Max amplitude information Loaded fort 28 : Load balance and loss diagnostics Loaded fort 29 : Cube root of third moments of the beam distribution Loaded fort 30 : Fourth root of the fourth moments of the beam distribution
In [20]:
Copied!
def plot1(y_axis, x_axis="mean_z", source=ds):
yunit = UNITS[y_axis]
ylabel = y_axis + " (" + yunit + ")"
xunit = UNITS[x_axis]
xlabel = x_axis + " (" + xunit + ")"
p = figure(width=600, height=200, x_axis_label=xlabel, y_axis_label=ylabel)
p.line(x_axis, y_axis, source=source, color="red")
return p
show(plot1("norm_emit_x"))
def plot1(y_axis, x_axis="mean_z", source=ds):
yunit = UNITS[y_axis]
ylabel = y_axis + " (" + yunit + ")"
xunit = UNITS[x_axis]
xlabel = x_axis + " (" + xunit + ")"
p = figure(width=600, height=200, x_axis_label=xlabel, y_axis_label=ylabel)
p.line(x_axis, y_axis, source=source, color="red")
return p
show(plot1("norm_emit_x"))
Stacking plots¶
This also links the panning, zooming
In [21]:
Copied!
p1 = plot1("sigma_x")
p2 = plot1("norm_emit_x")
zmax = 2
layout.x_range = Range1d(0, zmax)
p1.x_range = Range1d(0, zmax)
layout.width = p1.width
# Link panning, zooming
layout.x_range = p1.x_range
p2.x_range = p1.x_range
show(column(p1, p2, layout))
p1 = plot1("sigma_x")
p2 = plot1("norm_emit_x")
zmax = 2
layout.x_range = Range1d(0, zmax)
p1.x_range = Range1d(0, zmax)
layout.width = p1.width
# Link panning, zooming
layout.x_range = p1.x_range
p2.x_range = p1.x_range
show(column(p1, p2, layout))