Observables#

Observables provide a unified way to access a large quantity of figures resulting from various computations on lattices. They may be used in parameter scans, matching, response matrices…

Observables values may be scalars or numpy arrays of any shape.

AT provides a number of specific observables sharing a common interface, inherited from the Observable base class. They are:

An Observable has optional target, weight and bounds attributes for matching. After evaluation, it has the following main properties:

Custom Observables may be created by providing the adequate evaluation function.

For evaluation, observables must be grouped in an ObservableList which optimises the computation, avoiding redundant function calls. ObservableList provides the evaluate() method, and the values, deviations, residuals and sum_residuals properties, among others.

This example shows how to declare various Observables, how to evaluate them and how to extract and display their values.

Setup the environment#

import at
import sys
import numpy as np
from importlib.resources import files, as_file
from at import (
    Observable,
    ObservableList,
    RingObservable,
    OrbitObservable,
    GlobalOpticsObservable,
    LocalOpticsObservable,
    MatrixObservable,
    TrajectoryObservable,
    EmittanceObservable,
    LatticeObservable,
    GeometryObservable,
    Need,
)

Load a test lattice#

fname = "hmba.mat"
with as_file(files("machine_data") / fname) as path:
    hmba_lattice = at.load_lattice(path)

Create Observables#

Create an empty ObservableList:

obs1 = ObservableList()

Horizontal closed orbit on all Monitors:

obs1.append(OrbitObservable(at.Monitor, axis="x"))

Create a 2nd ObservableList:

obs2 = ObservableList()

Vertical \(\beta\) at all monitors, with a target and bounds.

The vertical \(\beta\) is constrained in the interval [target+low_bound target+up_bound], so here [-Infinity 7.0]

The residual will be zero within the interval.

obs2.append(
    LocalOpticsObservable(
        at.Monitor, "beta", plane=1, target=7.0, bounds=(-np.inf, 0.0)
    )
)

check the concatenation of ObservableLists:

allobs = obs1 + obs2

Full transfer matrix to BPM02:

allobs.append(MatrixObservable("BPM_02"))

Maximum of vertical beta on monitors:

allobs.append(LocalOpticsObservable(at.Monitor, "beta", plane="v", statfun=np.amax))

First 4 coordinates of the closed orbit at Quadrupoles:

allobs.append(
    LocalOpticsObservable(
        at.Quadrupole, "closed_orbit", plane=slice(4), target=0.0, weight=1.0e-6
    )
)

Position along the lattice of all quadrupoles:

allobs.append(LocalOpticsObservable(at.Quadrupole, "s_pos"))

Phase advance between elements 33 and 101 in all planes:

First, let’s define a custom evaluation function:

def phase_advance(elemdata):
    mu = elemdata.mu
    return mu[-1] - mu[0]

Then create the Observable. The evaluation function should return one value per refpoint (2 here). Alternatively, it may return a single value (the difference, here), but then one must set summary=True. all_points is set to True to force the evaluation of the phase advance at all points, to avoid phase jumps.

allobs.append(
    LocalOpticsObservable([33, 101], phase_advance, all_points=True, summary=True)
)

Horizontal tune with the integer part:

allobs.append(GlobalOpticsObservable("tune", plane=0, use_integer=True))

Total phase advance at the end of the lattice (all planes):

allobs.append(LocalOpticsObservable(at.End, "mu"))

Horizontal W-function:

allobs.append(LocalOpticsObservable(at.Sextupole, "W", plane='x'))

Chromaticity in all planes:

allobs.append(GlobalOpticsObservable("chromaticity"))

Average of sextupole strengths:

allobs.append(LatticeObservable(at.Sextupole, "H", statfun=np.mean))

Strengths of all sextupoles:

allobs.append(LatticeObservable(at.Sextupole, "PolynomB", index=2))

Horizontal emittance:

allobs.append(EmittanceObservable("emittances", plane="x"))

Ring circumference:

def circumference(ring):
    return ring.get_s_pos(len(ring))[0]

allobs.append(RingObservable(circumference))

px component of the trajectory on all monitors:

allobs.append(TrajectoryObservable(at.Monitor, axis="px"))
allobs.append(GeometryObservable(at.Monitor, "x"))

Evaluation#

An input trajectory is required for the trajectory Observable

r_in = np.zeros(6)
r_in[0] = 0.001
r_in[2] = 0.001
allobs.evaluate(hmba_lattice.enable_6d(copy=True), r_in=r_in, dp=0.0, initial=True)

Extract a single Observable value#

(phase advance between elements 3 and 101):

allobs[6].value
array([ 9.38969042e+00,  2.99742405e+00, -4.29831951e-15])

Get the list of all Observable values:#

allobs.values
[array([-3.02197154e-09,  4.50706100e-07,  4.08215752e-07,  2.37905632e-08,
        -1.31787026e-08,  2.47236653e-08, -2.95318224e-08, -4.05608197e-07,
        -4.47409217e-07, -2.24856457e-09]),
 array([5.30279703, 7.17604152, 6.55087808, 2.31448878, 3.40498444,
        3.405044  , 2.3146451 , 6.55106241, 7.17614175, 5.30283837]),
 array([[[-1.08194106e+00,  3.18809568e+00,  0.00000000e+00,
           0.00000000e+00,  8.22407787e-02, -1.72158067e-05],
         [-6.80522735e-01,  1.08099571e+00,  0.00000000e+00,
           0.00000000e+00,  4.90131193e-02, -1.02601216e-05],
         [ 0.00000000e+00,  0.00000000e+00,  7.55929650e-01,
           3.87059271e+00,  0.00000000e+00,  0.00000000e+00],
         [ 0.00000000e+00,  0.00000000e+00, -6.79279293e-01,
          -2.15524755e+00,  0.00000000e+00,  0.00000000e+00],
         [-1.13309291e-08, -1.08618451e-07,  0.00000000e+00,
           0.00000000e+00,  9.99995907e-01, -2.09333332e-04],
         [ 2.93742438e-03,  6.73567963e-02,  0.00000000e+00,
           0.00000000e+00,  2.83582586e-04,  9.99999941e-01]]]),
 np.float64(7.176141754884372),
 array([[-3.02817765e-09, -1.45848774e-10,  0.00000000e+00,
          0.00000000e+00],
        [-1.78482705e-09,  2.17272051e-09,  0.00000000e+00,
          0.00000000e+00],
        [ 2.06043298e-07,  1.68974845e-07,  0.00000000e+00,
          0.00000000e+00],
        [ 4.63473231e-07,  2.65118678e-07,  0.00000000e+00,
          0.00000000e+00],
        [ 4.92858975e-07, -2.48835341e-09,  0.00000000e+00,
          0.00000000e+00],
        [ 2.39074030e-07, -2.69330095e-07,  0.00000000e+00,
          0.00000000e+00],
        [ 2.24952950e-08, -2.55618843e-08,  0.00000000e+00,
          0.00000000e+00],
        [-2.95810598e-08, -2.51349419e-08,  0.00000000e+00,
          0.00000000e+00],
        [ 3.86447213e-08,  4.66083373e-08,  0.00000000e+00,
          0.00000000e+00],
        [-1.14696048e-08, -5.89639322e-08,  0.00000000e+00,
          0.00000000e+00],
        [-1.92477071e-07, -1.36146237e-07,  0.00000000e+00,
          0.00000000e+00],
        [-4.58538826e-07, -2.67114037e-07,  0.00000000e+00,
          0.00000000e+00],
        [-4.90197685e-07, -2.06362953e-09,  0.00000000e+00,
          0.00000000e+00],
        [-2.42431088e-07,  2.63622248e-07,  0.00000000e+00,
          0.00000000e+00],
        [-8.04974095e-10, -1.24376478e-09,  0.00000000e+00,
          0.00000000e+00],
        [-1.92739962e-09, -1.83202802e-09,  0.00000000e+00,
          0.00000000e+00]]),
 array([ 2.693952  ,  3.4295565 ,  5.52309303,  6.52741246,  7.08941246,
         8.14326589, 10.34278161, 11.93982486, 13.94182609, 15.63285034,
        18.00333506, 19.05718849, 19.61918849, 20.67257592, 22.71704445,
        23.36843995]),
 array([ 9.38969042e+00,  2.99742405e+00, -4.29831951e-15]),
 np.float64(2.3815630185939196),
 array([[1.49638018e+01, 5.36820522e+00, 6.85246959e-04]]),
 array([18.37111586, 25.91715269, 12.96214627,  9.66599267, 13.81023312,
        24.25197581]),
 array([1.79196882e-01, 1.22425551e-01, 1.70292084e-04]),
 np.float64(-25.369212247139345),
 array([-78.95535579,  77.03724443, -74.18952538, -74.18952538,
         77.03724443, -78.95535579]),
 np.float64(1.3203585666474837e-10),
 np.float64(26.374287952316944),
 array([ 0.00000000e+00, -6.94370475e-04,  6.07151650e-04,  2.38468289e-04,
        -6.81824075e-04, -4.78921799e-04,  4.41491590e-04,  7.01582185e-04,
        -6.05543948e-04, -9.78684826e-05]),
 array([ 2.6514    ,  6.4783308 ,  7.51380991, 10.28830988, 12.71979153,
        13.62739043, 16.04912109, 18.79203055, 19.81402164, 23.58054559])]

Get a pretty output of all Observables.#

As no variation was made, Actual values are always equal to Initial values.

The residual is zero for all Observables for which no target was specified

print(allobs)
    location              Initial            Actual         Low bound        High bound          residual 
orbit[x]
    BPM_01           -3.02197e-09      -3.02197e-09               -                 -                 0.0 
    BPM_02            4.50706e-07       4.50706e-07               -                 -                 0.0 
    BPM_03            4.08216e-07       4.08216e-07               -                 -                 0.0 
    BPM_04            2.37906e-08       2.37906e-08               -                 -                 0.0 
    BPM_05           -1.31787e-08      -1.31787e-08               -                 -                 0.0 
    BPM_06            2.47237e-08       2.47237e-08               -                 -                 0.0 
    BPM_07           -2.95318e-08      -2.95318e-08               -                 -                 0.0 
    BPM_08           -4.05608e-07      -4.05608e-07               -                 -                 0.0 
    BPM_09           -4.47409e-07      -4.47409e-07               -                 -                 0.0 
    BPM_10           -2.24856e-09      -2.24856e-09               -                 -                 0.0 
beta[y]
    BPM_01                 5.3028            5.3028              -inf               7.0               0.0 
    BPM_02                7.17604           7.17604              -inf               7.0         0.0309906 
    BPM_03                6.55088           6.55088              -inf               7.0               0.0 
    BPM_04                2.31449           2.31449              -inf               7.0               0.0 
    BPM_05                3.40498           3.40498              -inf               7.0               0.0 
    BPM_06                3.40504           3.40504              -inf               7.0               0.0 
    BPM_07                2.31465           2.31465              -inf               7.0               0.0 
    BPM_08                6.55106           6.55106              -inf               7.0               0.0 
    BPM_09                7.17614           7.17614              -inf               7.0         0.0310259 
    BPM_10                5.30284           5.30284              -inf               7.0               0.0 
matrix
    BPM_02       [-1.082     ...]  [-1.082     ...]               -                 -    [ 0.0       ...] 
amax(beta[y])
                          7.17614           7.17614               -                 -                 0.0 
closed_orbit[slice(None, 4, None)]
    QF1A         [-3.028e-09 ...]  [-3.028e-09 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 9.17e-06  ...] 
    QD2A         [-1.785e-09 ...]  [-1.785e-09 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 3.186e-06 ...] 
    QD3A         [ 2.06e-07  ...]  [ 2.06e-07  ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.04245   ...] 
    QF4A         [ 4.635e-07 ...]  [ 4.635e-07 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.2148    ...] 
    QF4B         [ 4.929e-07 ...]  [ 4.929e-07 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.2429    ...] 
    QD5B         [ 2.391e-07 ...]  [ 2.391e-07 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.05716   ...] 
    QF6B         [ 2.25e-08  ...]  [ 2.25e-08  ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.000506  ...] 
    QF8B         [-2.958e-08 ...]  [-2.958e-08 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.000875  ...] 
    QF8D         [ 3.864e-08 ...]  [ 3.864e-08 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.001493  ...] 
    QF6D         [-1.147e-08 ...]  [-1.147e-08 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.0001316 ...] 
    QD5D         [-1.925e-07 ...]  [-1.925e-07 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.03705   ...] 
    QF4D         [-4.585e-07 ...]  [-4.585e-07 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.2103    ...] 
    QF4E         [-4.902e-07 ...]  [-4.902e-07 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.2403    ...] 
    QD3E         [-2.424e-07 ...]  [-2.424e-07 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 0.05877   ...] 
    QD2E         [-8.05e-10  ...]  [-8.05e-10  ...]  [ 0.0       ...]  [ 0.0       ...]  [ 6.48e-07  ...] 
    QF1E         [-1.927e-09 ...]  [-1.927e-09 ...]  [ 0.0       ...]  [ 0.0       ...]  [ 3.715e-06 ...] 
s_pos
    QF1A                  2.69395           2.69395               -                 -                 0.0 
    QD2A                  3.42956           3.42956               -                 -                 0.0 
    QD3A                  5.52309           5.52309               -                 -                 0.0 
    QF4A                  6.52741           6.52741               -                 -                 0.0 
    QF4B                  7.08941           7.08941               -                 -                 0.0 
    QD5B                  8.14327           8.14327               -                 -                 0.0 
    QF6B                  10.3428           10.3428               -                 -                 0.0 
    QF8B                  11.9398           11.9398               -                 -                 0.0 
    QF8D                  13.9418           13.9418               -                 -                 0.0 
    QF6D                  15.6329           15.6329               -                 -                 0.0 
    QD5D                  18.0033           18.0033               -                 -                 0.0 
    QF4D                  19.0572           19.0572               -                 -                 0.0 
    QF4E                  19.6192           19.6192               -                 -                 0.0 
    QD3E                  20.6726           20.6726               -                 -                 0.0 
    QD2E                   22.717            22.717               -                 -                 0.0 
    QF1E                  23.3684           23.3684               -                 -                 0.0 
phase_advance
                 [ 9.39      ...]  [ 9.39      ...]               -                 -    [ 0.0       ...] 
tune[x]
                          2.38156           2.38156               -                 -                 0.0 
mu
    End          [ 14.96     ...]  [ 14.96     ...]               -                 -    [ 0.0       ...] 
W[x]
    SD1A                  18.3711           18.3711               -                 -                 0.0 
    SF2A                  25.9172           25.9172               -                 -                 0.0 
    SD1B                  12.9621           12.9621               -                 -                 0.0 
    SD1D                  9.66599           9.66599               -                 -                 0.0 
    SF2E                  13.8102           13.8102               -                 -                 0.0 
    SD1E                   24.252            24.252               -                 -                 0.0 
chromaticity
                 [ 0.1792    ...]  [ 0.1792    ...]               -                 -    [ 0.0       ...] 
mean(H)
                         -25.3692          -25.3692               -                 -                 0.0 
PolynomB[2]
    SD1A                 -78.9554          -78.9554               -                 -                 0.0 
    SF2A                  77.0372           77.0372               -                 -                 0.0 
    SD1B                 -74.1895          -74.1895               -                 -                 0.0 
    SD1D                 -74.1895          -74.1895               -                 -                 0.0 
    SF2E                  77.0372           77.0372               -                 -                 0.0 
    SD1E                 -78.9554          -78.9554               -                 -                 0.0 
emittances[x]
                      1.32036e-10       1.32036e-10               -                 -                 0.0 
circumference
                          26.3743           26.3743               -                 -                 0.0 
trajectory[px]
    BPM_01                    0.0               0.0               -                 -                 0.0 
    BPM_02            -0.00069437       -0.00069437               -                 -                 0.0 
    BPM_03            0.000607152       0.000607152               -                 -                 0.0 
    BPM_04            0.000238468       0.000238468               -                 -                 0.0 
    BPM_05           -0.000681824      -0.000681824               -                 -                 0.0 
    BPM_06           -0.000478922      -0.000478922               -                 -                 0.0 
    BPM_07            0.000441492       0.000441492               -                 -                 0.0 
    BPM_08            0.000701582       0.000701582               -                 -                 0.0 
    BPM_09           -0.000605544      -0.000605544               -                 -                 0.0 
    BPM_10           -9.78685e-05      -9.78685e-05               -                 -                 0.0 
geometry[x]
    BPM_01                 2.6514            2.6514               -                 -                 0.0 
    BPM_02                6.47833           6.47833               -                 -                 0.0 
    BPM_03                7.51381           7.51381               -                 -                 0.0 
    BPM_04                10.2883           10.2883               -                 -                 0.0 
    BPM_05                12.7198           12.7198               -                 -                 0.0 
    BPM_06                13.6274           13.6274               -                 -                 0.0 
    BPM_07                16.0491           16.0491               -                 -                 0.0 
    BPM_08                 18.792            18.792               -                 -                 0.0 
    BPM_09                 19.814            19.814               -                 -                 0.0 
    BPM_10                23.5805           23.5805               -                 -                 0.0