Example-03: Workflow (ELEGANT)
[1]:
from pathlib import Path
from model.command.external import load_lattice
from model.command.external import rift_lattice
from model.command.external import text_lattice
from model.command.external import load_sdds
from model.command.external import convert
from model.command.external import add_rc
[2]:
# Given some initial ELEGANT lattice file (FODO)
file = Path('initial.lte')
with file.open('r') as stream:
print(stream.read())
# Several regular elements are defined
# HEAD and TAIL should appear as the first and the last elements
# All elements should be defined on a single line with numerical parameters
# Lattice should be defined using lines
# Comma after element type is mandatory
# Comments appearing after definitions should also represent an element definition
DR: DRIF,l=2
BM: CSBEND,angle=0.17453292519943295,fint=0,l=1.0
QD: QUAD,k1=-0.2,l=0.5
QF: QUAD,k1=0.2,l=1.0
M: MONI,
HEAD: MARK, ! TEST: DRIF,
TAIL: MARK, ! TEST: DRIF,
FODO: LINE=(HEAD, M, QD, DR, BM, DR, QF, DR, BM, DR, QD, TAIL)
[3]:
# If element and beamline definitions comply with the above requirements
# The lattice file can be loaded as a python dictionary
lattice = load_lattice(file)
for key, value in lattice.items():
print(key, value)
# For each element and beamline, a key-value pair in created
# Value is itself a dictionary containing all information about the original elements
# Each element parameter is casted from string to int, float or string
# Comment after element definition is saved into RC (it has a special use case, see below)
DR {'KIND': 'DRIF', 'RC': '', 'L': 2}
BM {'KIND': 'CSBEND', 'RC': '', 'ANGLE': 0.17453292519943295, 'FINT': 0, 'L': 1.0}
QD {'KIND': 'QUAD', 'RC': '', 'K1': -0.2, 'L': 0.5}
QF {'KIND': 'QUAD', 'RC': '', 'K1': 0.2, 'L': 1.0}
M {'KIND': 'MONI', 'RC': ''}
HEAD {'KIND': 'MARK', 'RC': 'TEST: DRIF,'}
TAIL {'KIND': 'MARK', 'RC': 'TEST: DRIF,'}
FODO {'KIND': 'LINE', 'SEQUENCE': ['HEAD', 'M', 'QD', 'DR', 'BM', 'DR', 'QF', 'DR', 'BM', 'DR', 'QD', 'TAIL']}
[4]:
# Error lattice is defined by a set of linear transformations between selected locations
# Each locations can be a MONITOR (beam observation) or a VIRTUAL (error)
# Two special locatons (HEAD and TAIL) should present in the lattice
# Using the above dictionary representation, new observation locations can be inserted
# Locations are inserted at the middle of selected elements (selected by type or name)
# Selected elements are splitted in half and renamed, old names are binded to beamlines
# Original element definitions are added to created location RC
# Typicaly, monitor locations correspond to MONITOR elements, but new monitor elements can be also inserted
# Virtual locations can be inserted into quadrupole or other elements to represent errors
lattice = rift_lattice(lattice,
'MONI',
'MARK',
['DRIF'],
['CSBEND', 'QUAD'],
exclude_virtual=['QD'])
for key, value in lattice.items():
print(key, value)
M_DR {'KIND': 'MONI', 'RC': ['DR', {'KIND': 'DRIF', 'L': 2}]}
H_DR {'KIND': 'DRIF', 'L': 1.0}
DR {'KIND': 'LINE', 'SEQUENCE': ['H_DR', 'M_DR', 'H_DR']}
V_BM {'KIND': 'MARK', 'RC': ['BM', {'KIND': 'CSBEND', 'ANGLE': 0.17453292519943295, 'FINT': 0, 'L': 1.0}]}
H_BM {'KIND': 'CSBEND', 'ANGLE': 0.08726646259971647, 'FINT': 0, 'L': 0.5}
BM {'KIND': 'LINE', 'SEQUENCE': ['H_BM', 'V_BM', 'H_BM']}
QD {'KIND': 'QUAD', 'RC': '', 'K1': -0.2, 'L': 0.5}
V_QF {'KIND': 'MARK', 'RC': ['QF', {'KIND': 'QUAD', 'K1': 0.2, 'L': 1.0}]}
H_QF {'KIND': 'QUAD', 'K1': 0.2, 'L': 0.5}
QF {'KIND': 'LINE', 'SEQUENCE': ['H_QF', 'V_QF', 'H_QF']}
M {'KIND': 'MONI', 'RC': ''}
HEAD {'KIND': 'MARK', 'RC': 'TEST: DRIF,'}
TAIL {'KIND': 'MARK', 'RC': 'TEST: DRIF,'}
FODO {'KIND': 'LINE', 'SEQUENCE': ['HEAD', 'M', 'QD', 'DR', 'BM', 'DR', 'QF', 'DR', 'BM', 'DR', 'QD', 'TAIL']}
[5]:
# Modified lattice can be converted to text
# Comments are added to locations while original comments are preserved
text = text_lattice('LTE', lattice, rc=True)
print(text)
M_DR: MONI, ! DR: DRIF, L=2,
H_DR: DRIF, L=1.0,
DR: LINE=(H_DR, M_DR, H_DR)
V_BM: MARK, ! BM: CSBEND, ANGLE=0.17453292519943295, FINT=0, L=1.0,
H_BM: CSBEND, ANGLE=0.08726646259971647, FINT=0, L=0.5,
BM: LINE=(H_BM, V_BM, H_BM)
QD: QUAD, K1=-0.2, L=0.5,
V_QF: MARK, ! QF: QUAD, K1=0.2, L=1.0,
H_QF: QUAD, K1=0.2, L=0.5,
QF: LINE=(H_QF, V_QF, H_QF)
M: MONI,
HEAD: MARK, ! TEST: DRIF,
TAIL: MARK, ! TEST: DRIF,
FODO: LINE=(HEAD, M, QD, DR, BM, DR, QF, DR, BM, DR, QD, TAIL)
[6]:
# Compute TWISS parameters using ELEGANT
# Separate command file is created
with Path('final.lte').open('w') as stream:
stream.write(text)
task = """
&run_setup
use_beamline="FODO",
lattice = "final.lte",
p_central_mev = 1000
&end
&run_control
&end
&twiss_output
filename = "binary.twiss",
output_at_each_step = 1
&end
&bunched_beam
&end
&track
&end
""" ;
with Path('final.ele').open('w') as stream:
stream.write(task)
!elegant final.ele > /dev/null
!sddsconvert -ascii binary.twiss final.twiss
[7]:
# Load lattice can be also loaded from file
# Original comments will be parsed as elements (look at HEAD and TAIL)
# Empty RC will be nested in this case
file = Path('final.lte')
with file.open('w') as stream:
stream.write(text)
lattice = load_lattice(file, rc=True)
for key, value in lattice.items():
print(key, value)
M_DR {'KIND': 'MONI', 'RC': ['DR', {'KIND': 'DRIF', 'RC': '', 'L': 2}]}
H_DR {'KIND': 'DRIF', 'RC': ['', {'KIND': '', 'RC': ''}], 'L': 1.0}
DR {'KIND': 'LINE', 'SEQUENCE': ['H_DR', 'M_DR', 'H_DR']}
V_BM {'KIND': 'MARK', 'RC': ['BM', {'KIND': 'CSBEND', 'RC': '', 'ANGLE': 0.17453292519943295, 'FINT': 0, 'L': 1.0}]}
H_BM {'KIND': 'CSBEND', 'RC': ['', {'KIND': '', 'RC': ''}], 'ANGLE': 0.08726646259971647, 'FINT': 0, 'L': 0.5}
BM {'KIND': 'LINE', 'SEQUENCE': ['H_BM', 'V_BM', 'H_BM']}
QD {'KIND': 'QUAD', 'RC': ['', {'KIND': '', 'RC': ''}], 'K1': -0.2, 'L': 0.5}
V_QF {'KIND': 'MARK', 'RC': ['QF', {'KIND': 'QUAD', 'RC': '', 'K1': 0.2, 'L': 1.0}]}
H_QF {'KIND': 'QUAD', 'RC': ['', {'KIND': '', 'RC': ''}], 'K1': 0.2, 'L': 0.5}
QF {'KIND': 'LINE', 'SEQUENCE': ['H_QF', 'V_QF', 'H_QF']}
M {'KIND': 'MONI', 'RC': ['', {'KIND': '', 'RC': ''}]}
HEAD {'KIND': 'MARK', 'RC': ['TEST', {'KIND': 'DRIF', 'RC': ''}]}
TAIL {'KIND': 'MARK', 'RC': ['TEST', {'KIND': 'DRIF', 'RC': ''}]}
FODO {'KIND': 'LINE', 'SEQUENCE': ['HEAD', 'M', 'QD', 'DR', 'BM', 'DR', 'QF', 'DR', 'BM', 'DR', 'QD', 'TAIL']}
[8]:
# TWISS results can be loaded into python dictionaries
data = Path('final.twiss')
parameters, columns = load_sdds(data)
[9]:
# Optics data can be converted into model table
# Note, all locations have different name
# If an element appear several times in a line, locations are renamed
table = convert(columns, 'SDDS', ['MONI'], ['MARK'], rc=True)
table
[9]:
{'HEAD': {'S': 0.0,
'BX': 4.287017734831204,
'AX': -1.321304551729011e-16,
'FX': 0.0,
'DQX': 1.549040841795901,
'DPX': 2.775557561562891e-17,
'BY': 19.81848926815186,
'AY': 6.545730027929358e-16,
'FY': 0.0,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': None},
'M': {'S': 0.0,
'BX': 4.287017734831204,
'AX': -1.321304551729011e-16,
'FX': 0.0,
'DQX': 1.549040841795901,
'DPX': 2.775557561562891e-17,
'BY': 19.81848926815186,
'AY': 6.545730027929358e-16,
'FY': 0.0,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': None},
'M_DR': {'S': 1.5,
'BX': 5.980356479284525,
'AX': -0.8524040348212205,
'FX': 0.3068185834444499,
'DQX': 1.744126672993481,
'DPX': 0.1561981825607101,
'BY': 15.31515988971357,
'AY': 1.649167846239909,
'FY': 0.08453149253790615,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': None},
'V_BM': {'S': 3.0,
'BX': 9.120629409314306,
'AX': -1.146568740048648,
'FX': 0.5107301355818847,
'DQX': 1.99289632225274,
'DPX': 0.2138526637243729,
'BY': 10.91413760701325,
'AY': 1.284847009200138,
'FY': 0.2008141505892614,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': None},
'M_DR_1': {'S': 4.5,
'BX': 12.70896979491113,
'AX': -1.336396672789745,
'FX': 0.6500917126795847,
'DQX': 2.383785789407781,
'DPX': 0.2698795969893243,
'BY': 7.606077834992553,
'AY': 0.9205261718281931,
'FY': 0.3661997933967667,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': None},
'V_QF': {'S': 6.0,
'BX': 16.39200719526896,
'AX': 3.608224830031759e-16,
'FX': 0.7521811119743597,
'DQX': 2.721417822995524,
'DPX': -5.551115123125783e-17,
'BY': 5.674619589422572,
'AY': 8.326672684688672e-16,
'FY': 0.6011311668647427,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': None},
'M_DR_2': {'S': 7.5,
'BX': 12.70896979491113,
'AX': 1.336396672789746,
'FX': 0.8542705112691347,
'DQX': 2.383785789407781,
'DPX': -0.2698795969893243,
'BY': 7.606077834992548,
'AY': -0.920526171828191,
'FY': 0.8360625403327188,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': None},
'V_BM_1': {'S': 9.0,
'BX': 9.120629409314306,
'AX': 1.146568740048649,
'FX': 0.9936320883668346,
'DQX': 1.992896322252739,
'DPX': -0.2138526637243729,
'BY': 10.91413760701323,
'AY': -1.284847009200136,
'FY': 1.001448183140224,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': None},
'M_DR_3': {'S': 10.5,
'BX': 5.980356479284523,
'AX': 0.852404034821221,
'FX': 1.197543640504269,
'DQX': 1.744126672993481,
'DPX': -0.1561981825607101,
'BY': 15.31515988971355,
'AY': -1.649167846239906,
'FY': 1.11773084119158,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': None},
'TAIL': {'S': 12.0,
'BX': 4.287017734831201,
'AX': 5.273559366969493e-16,
'FX': 1.50436222394872,
'DQX': 1.549040841795901,
'DPX': -1.110223024625157e-16,
'BY': 19.81848926815184,
'AY': 1.387778780781446e-16,
'FY': 1.202262333729486,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': None}}
[10]:
# RC parameter from lattice data can be added to model table
# Configuration table can be saved using util.save
table = add_rc(table, lattice)
table
[10]:
{'HEAD': {'S': 0.0,
'BX': 4.287017734831204,
'AX': -1.321304551729011e-16,
'FX': 0.0,
'DQX': 1.549040841795901,
'DPX': 2.775557561562891e-17,
'BY': 19.81848926815186,
'AY': 6.545730027929358e-16,
'FY': 0.0,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': None},
'M': {'S': 0.0,
'BX': 4.287017734831204,
'AX': -1.321304551729011e-16,
'FX': 0.0,
'DQX': 1.549040841795901,
'DPX': 2.775557561562891e-17,
'BY': 19.81848926815186,
'AY': 6.545730027929358e-16,
'FY': 0.0,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': None},
'M_DR': {'S': 1.5,
'BX': 5.980356479284525,
'AX': -0.8524040348212205,
'FX': 0.3068185834444499,
'DQX': 1.744126672993481,
'DPX': 0.1561981825607101,
'BY': 15.31515988971357,
'AY': 1.649167846239909,
'FY': 0.08453149253790615,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': ['DR', {'KIND': 'DRIF', 'L': 2}]},
'V_BM': {'S': 3.0,
'BX': 9.120629409314306,
'AX': -1.146568740048648,
'FX': 0.5107301355818847,
'DQX': 1.99289632225274,
'DPX': 0.2138526637243729,
'BY': 10.91413760701325,
'AY': 1.284847009200138,
'FY': 0.2008141505892614,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': ['BM',
{'KIND': 'CSBEND', 'ANGLE': 0.17453292519943295, 'FINT': 0, 'L': 1.0}]},
'M_DR_1': {'S': 4.5,
'BX': 12.70896979491113,
'AX': -1.336396672789745,
'FX': 0.6500917126795847,
'DQX': 2.383785789407781,
'DPX': 0.2698795969893243,
'BY': 7.606077834992553,
'AY': 0.9205261718281931,
'FY': 0.3661997933967667,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': ['DR', {'KIND': 'DRIF', 'L': 2}]},
'V_QF': {'S': 6.0,
'BX': 16.39200719526896,
'AX': 3.608224830031759e-16,
'FX': 0.7521811119743597,
'DQX': 2.721417822995524,
'DPX': -5.551115123125783e-17,
'BY': 5.674619589422572,
'AY': 8.326672684688672e-16,
'FY': 0.6011311668647427,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': ['QF', {'KIND': 'QUAD', 'K1': 0.2, 'L': 1.0}]},
'M_DR_2': {'S': 7.5,
'BX': 12.70896979491113,
'AX': 1.336396672789746,
'FX': 0.8542705112691347,
'DQX': 2.383785789407781,
'DPX': -0.2698795969893243,
'BY': 7.606077834992548,
'AY': -0.920526171828191,
'FY': 0.8360625403327188,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': ['DR', {'KIND': 'DRIF', 'L': 2}]},
'V_BM_1': {'S': 9.0,
'BX': 9.120629409314306,
'AX': 1.146568740048649,
'FX': 0.9936320883668346,
'DQX': 1.992896322252739,
'DPX': -0.2138526637243729,
'BY': 10.91413760701323,
'AY': -1.284847009200136,
'FY': 1.001448183140224,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': ['BM',
{'KIND': 'CSBEND', 'ANGLE': 0.17453292519943295, 'FINT': 0, 'L': 1.0}]},
'M_DR_3': {'S': 10.5,
'BX': 5.980356479284523,
'AX': 0.852404034821221,
'FX': 1.197543640504269,
'DQX': 1.744126672993481,
'DPX': -0.1561981825607101,
'BY': 15.31515988971355,
'AY': -1.649167846239906,
'FY': 1.11773084119158,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'MONITOR',
'RC': ['DR', {'KIND': 'DRIF', 'L': 2}]},
'TAIL': {'S': 12.0,
'BX': 4.287017734831201,
'AX': 5.273559366969493e-16,
'FX': 1.50436222394872,
'DQX': 1.549040841795901,
'DPX': -1.110223024625157e-16,
'BY': 19.81848926815184,
'AY': 1.387778780781446e-16,
'FY': 1.202262333729486,
'DQY': 0.0,
'DPY': 0.0,
'TYPE': 'VIRTUAL',
'RC': None}}