LHC IR Errors Assignments

This example shows how to use the misalign_lhc_ir_quadrupoles function to assign magnet errors in the Insertion Region magnets of the LHC.

Warning

The implementation of this function makes it valid only for LHC IP IRs, which are 1, 2, 5 and 8. Other IRs have different layouts that are incompatible.

Important

This example requires the acc-models-lhc repository to be cloned locally. One can get it by running the following command:

git clone -b 2022 https://gitlab.cern.ch/acc-models/acc-models-lhc.git --depth 1

Here I set the 2022 branch for stability and reproducibility of the documentation builds, but you can use any branch you want.

import matplotlib.pyplot as plt
import numpy as np

from cpymad.madx import Madx

from pyhdtoolkit.cpymadtools import lhc, matching
from pyhdtoolkit.plotting.styles import _SPHINX_GALLERY_PARAMS
from pyhdtoolkit.utils import logging

logging.config_logger(level="error")
plt.rcParams.update(_SPHINX_GALLERY_PARAMS)  # for readability of this tutorial

Let’s start by setting up the LHC in MAD-X, in this case at injection optics and energy. To understand the function below have a look at the lhc setup example.

madx: Madx = lhc.prepare_lhc_run3(
    opticsfile="acc-models-lhc/operation/optics/R2022a_A11mC11mA10mL10m.madx",
    energy=450,  # given in GeV
    stdout=False,
)

Importantly in MAD-X, when dealing with RNG one should set a generator and seed, which we do below:

madx.option(rand="best", randid=np.random.randint(1, 11))  # random number generator
madx.eoption(seed=np.random.randint(1, 999999999))  # not using default seed

We can now install errors in the IR quadrupoles. Note that this function accepts keyword arguments for the error definition, and any kwarg will be passed to the EALIGN command of MAD-X.

Here let’s apply systematic horizontal misalignment errors and tilt errors to the quadrupoles Q1 to Q6 (first to sixth) on both sides of IP1:

lhc.misalign_lhc_ir_quadrupoles(
    madx,
    ips=[1],
    beam=1,
    quadrupoles=[1, 2, 3, 4, 5, 6],
    sides="RL",
    dx="0.001*TGAUSS(2.5)",
    dpsi="0.003*GAUSS(2.5)",
)

Let’s match to our working point, and retrieve the errors directly through the internal MAD-X tables through cpymad:

madx.command.use(sequence="lhcb1")
matching.match_tunes_and_chromaticities(madx, "lhc", "lhcb1", 62.31, 60.32, 2.0, 2.0)
error_table = madx.table.ir_quads_errors.dframe()

Let’s quickly re-arrange the resulting DataFrame to align with the order in which they are in the machine:

error_table.name = error_table.name.apply(lambda x: x[:-2])
error_table = error_table.set_index("name", drop=True)
error_table = error_table[["dx", "dy", "dpsi", "dtheta"]]  # only keep those
error_table = error_table.reindex(  # their order in the machine
    [
        "mqml.6l1.b1",
        "mqml.5l1.b1",
        "mqy.4l1.b1",
        "mqxa.3l1",
        "mqxb.b2l1",
        "mqxb.a2l1",
        "mqxa.1l1",
        "mqxa.1r1",
        "mqxb.a2r1",
        "mqxb.b2r1",
        "mqxa.3r1",
        "mqy.4r1.b1",
        "mqml.5r1.b1",
        "mqml.6r1.b1",
    ]
)
error_table
dx dy dpsi dtheta
name
mqml.6l1.b1 -0.000709 0.0 -0.003019 0.0
mqml.5l1.b1 0.000744 0.0 -0.001892 0.0
mqy.4l1.b1 0.001629 0.0 0.003766 0.0
mqxa.3l1 0.000830 0.0 0.004931 0.0
mqxb.b2l1 -0.001001 0.0 -0.002123 0.0
mqxb.a2l1 -0.000967 0.0 0.003650 0.0
mqxa.1l1 0.000112 0.0 0.001656 0.0
mqxa.1r1 -0.000972 0.0 0.005006 0.0
mqxb.a2r1 -0.000344 0.0 0.002245 0.0
mqxb.b2r1 -0.000341 0.0 0.001890 0.0
mqxa.3r1 -0.000224 0.0 0.000512 0.0
mqy.4r1.b1 0.000582 0.0 0.000137 0.0
mqml.5r1.b1 -0.000691 0.0 -0.001984 0.0
mqml.6r1.b1 0.001868 0.0 -0.000194 0.0


We can also check that all these elements have been correctly affected:

assert all(error_table["dx"] != 0)
assert all(error_table["dpsi"] != 0)

We can visualise the distribution of errors across these magnets with a bar chart, making use of the DataFrame plotting capabilities:

axes = error_table.plot(
    y=["dx", "dpsi"],
    kind="bar",
    title="Applied Errors",
    xlabel="Magnet Name",
    figsize=(20, 11),
    subplots=True,
    rot=45,
)

axes[0].set_title("")
axes[0].set_ylabel("dx [m]")
axes[1].set_title("")
axes[1].set_ylabel("dpsi [rad]")
plt.show()
Applied Errors

Let’s not forget to close the rpc connection to MAD-X:

References

The use of the following functions, methods, classes and modules is shown in this example:

  • lhc: prepare_lhc_run3, misalign_lhc_ir_quadrupoles

  • matching: match_tunes_and_chromaticities

Total running time of the script: (0 minutes 15.791 seconds)

Gallery generated by Sphinx-Gallery