|
| 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