Skip to content

Commit 46b7f50

Browse files
committed
MPL: KnownElementsList.plot()
Example: ```py import matplotlib.pyplot as plt sim.lattice.plot() plt.show() ```
1 parent 2736f4f commit 46b7f50

File tree

2 files changed

+130
-8
lines changed

2 files changed

+130
-8
lines changed

src/python/impactx/__init__.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,27 @@
1818

1919
# import core bindings to C++
2020
from . import impactx_pybind as cxx
21-
from .distribution_input_helpers import twiss # noqa
22-
from .extensions.ImpactXParticleContainer import (
23-
register_ImpactXParticleContainer_extension,
24-
)
2521
from .impactx_pybind import * # noqa
26-
from .madx_to_impactx import read_beam, read_lattice # noqa
22+
from .madx_to_impactx import read_beam # noqa
2723

2824
__version__ = cxx.__version__
2925
__doc__ = cxx.__doc__
3026
__license__ = cxx.__license__
3127
__author__ = cxx.__author__
3228

29+
from .distribution_input_helpers import twiss # noqa
30+
from .extensions.KnownElementsList import (
31+
register_KnownElementsList_extension,
32+
)
33+
from .extensions.ImpactXParticleContainer import (
34+
register_ImpactXParticleContainer_extension,
35+
)
36+
3337
# at this place we can enhance Python classes with additional methods written
3438
# in pure Python or add some other Python logic
3539

3640
# MAD-X file reader for beamline lattice elements
37-
elements.KnownElementsList.load_file = lambda self, madx_file, nslice=1: self.extend(
38-
read_lattice(madx_file, nslice)
39-
) # noqa
41+
register_KnownElementsList_extension(cxx.elements.KnownElementsList)
4042

4143
# MAD-X file reader for reference particle
4244
RefPart.load_file = read_beam # noqa
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"""
2+
This file is part of ImpactX
3+
4+
Copyright 2025 ImpactX contributors
5+
Authors: Axel Huebl
6+
License: BSD-3-Clause-LBNL
7+
"""
8+
9+
from ..madx_to_impactx import read_lattice # noqa
10+
11+
12+
def kel_plot(self, ax=None, legend=True, legend_ncols=5):
13+
"""Plot over s of all elements in the KnownElementsList."""
14+
from math import copysign
15+
16+
import matplotlib.pyplot as plt
17+
import numpy as np
18+
from matplotlib.patches import Rectangle
19+
20+
ax = ax or plt.subplot(111)
21+
22+
element_lengths = [element.ds for element in self]
23+
element_s = np.cumulative_sum(element_lengths, include_initial=True)
24+
25+
ax.hlines(0, 0, element_s[-1], color="black", linestyle="--")
26+
27+
# plot config
28+
colors = {
29+
"Quad": "tab:blue",
30+
"ChrQuad": "tab:blue",
31+
"ExactQuad": "tab:blue",
32+
"SoftQuadrupole": "tab:blue",
33+
"Multipole": "tab:orange",
34+
"ExactMultipole": "tab:orange",
35+
"Sbend": "tab:green",
36+
"ExactSbend": "tab:green",
37+
"CFbend": "tab:olive",
38+
"ConstF": "tab:red",
39+
"ChrPlasmaLens": "tab:red",
40+
"SoftSolenoid": "tab:red",
41+
"TaperedPL": "tab:red",
42+
"RFCavity": "tab:brown",
43+
"ShortRF": "tab:brown",
44+
"Buncher": "tab:purple",
45+
"Aperture": "black",
46+
"Kicker": "tab:pink",
47+
}
48+
# 'tab:cyan'
49+
50+
skip_names = [
51+
"BeamMonitor",
52+
"Drift",
53+
"ChrDrift",
54+
"ExactDrift",
55+
"Empty",
56+
"Marker",
57+
"Source",
58+
]
59+
60+
handles = {}
61+
62+
for i, element in enumerate(self):
63+
el_dict = element.to_dict()
64+
el_type = el_dict["type"]
65+
if el_type in skip_names:
66+
continue
67+
68+
if el_type in colors:
69+
color = colors[el_dict["type"]]
70+
else:
71+
color = "tab:gray"
72+
73+
height = 0.5
74+
if "k" in el_dict:
75+
height = copysign(0.8, el_dict["k"])
76+
if "phi" in el_dict:
77+
height = copysign(0.8, el_dict["phi"])
78+
79+
patch = Rectangle(
80+
(element_s[i], 0),
81+
element_lengths[i],
82+
height,
83+
color=color,
84+
alpha=1.0,
85+
zorder=2,
86+
)
87+
ax.add_patch(patch)
88+
89+
handles[el_type] = patch
90+
91+
if legend:
92+
labels = list(handles.keys())
93+
values = list(handles.values())
94+
ax.legend(
95+
handles=values,
96+
labels=labels,
97+
bbox_to_anchor=(0.0, 1.02, 1.0, 0.102),
98+
loc="lower left",
99+
ncols=legend_ncols,
100+
mode="expand",
101+
borderaxespad=0.0,
102+
)
103+
104+
ax.set_xlabel(r"$s$ [m]")
105+
106+
ax.set_ylim(-1, 1)
107+
ax.set_yticks([])
108+
109+
ax.set_aspect(1 / 1.618) # golden ratio
110+
111+
return ax
112+
113+
114+
def register_KnownElementsList_extension(kel):
115+
"""KnownElementsList helper methods"""
116+
# register member functions for KnownElementsList
117+
kel.load_file = lambda self, madx_file, nslice=1: self.extend(
118+
read_lattice(madx_file, nslice)
119+
)
120+
kel.plot = kel_plot

0 commit comments

Comments
 (0)