Files
OpticsTools/matchmaker.py
2026-01-26 12:51:50 +01:00

155 lines
6.2 KiB
Python

import os
import re
from onlinemodel.madx import CMadX
import io
import contextlib
from io import StringIO
import sys
class MatchMaker:
def __init__(self,signal = None):
self.matchlist={'Reference-SwissFEL':'Scripts/Reference-SwissFEL','SwissFEL+':'Scripts/SFPlus'}
self.referencePoints={}
self.variables={}
self.scriptdir = None
self.signal=signal
def initScripts(self,target):
self.scriptdir = self.matchlist[target]
if os.path.exists(self.scriptdir+'/initTwiss.madx'):
self.parseReferencePoints()
self.scriptInjector = os.path.exists(self.scriptdir+'/matchInjector.madx')
self.scriptAramis = os.path.exists(self.scriptdir+'/matchAramis.madx')
self.scriptAthos = os.path.exists(self.scriptdir + '/matchAthos.madx')
self.scriptPorthos = os.path.exists(self.scriptdir + '/matchPorthos.madx')
self.settings = os.path.exists(self.scriptdir + '/ReferenceSettings')
def parseReferencePoints(self):
file = self.scriptdir+'/initTwiss.madx'
self.referencePoints.clear()
self.variables.clear()
with open(file,'r') as f:
lines = f.readlines()
for line in lines:
if 'location:' in line:
tags = line.split('location:')
location = tags[1].strip()
if 'label:' in tags[0]:
label = tags[0].split('label:')[1].strip()
else:
label=None
fields_all = tags[0].split(',')
fields = [fld.split(';')[0].strip() for fld in fields_all if "=" in fld]
self.referencePoints[location] = {'Twiss':{twiss.split('=')[0].strip().lower():float(twiss.split('=')[1].strip()) for twiss in fields},'Label':label}
if 'Description:' in line:
tags = line.split('Description:')
description = tags[1].strip()
flds=tags[0].split('=')
name = flds[0].split(':')[0].strip()
val = float(flds[1].split(';')[0].strip())
self.variables[name] = {'Value':val,'Description':description}
print('Found Variable',name,'with value',val)
print('##### Reference Twiss values parsed')
def match(self, om, variables = None, Injector=True, Athos = True, Aramis = False, Porthos = False):
if Athos:
target = 'SATBD01'
else:
target = 'SARUN20'
f = io.StringIO()
madx = CMadX(f)
madx.E0 = 2000
om.setBranch(target, 'SINLH01')
madx.updateLattice(om, target) # write lattice
madx.commonHeader('SwissFEL', '#s/#e', None) # sets header
madx.madx.call(self.scriptdir + '/initTwiss.madx')
if not variables is None:
madx.definePresets(variables)
if Injector:
if self.signal:
self.signal.emit('Matching Injector ...')
madx.madx.call(self.scriptdir+'/matchInjector.madx', chdir=True)
self.updateOnlineModel(om,madx.madx, 's[i1].*k1|s20sy01.*k1')
self.parseMatchOutput(f.getvalue().split('\n'),'Injector')
if Athos:
f.flush()
if self.signal:
self.signal.emit('Matching Athos ...')
madx.madx.call(self.scriptdir+'/matchAthos.madx', chdir=True)
self.updateOnlineModel(om, madx.madx, 'sat.*k1|s20sy02.*m[kq]')
self.parseMatchOutput(f.getvalue().split('\n'), 'Athos')
if Aramis:
f.flush()
if self.signal:
self.signal.emit('Matching Aramis ...')
if target=='SATBD01':
target = 'SARUN20'
om.setBranch(target, 'SINLH01')
madx.updateLattice(om, target) # write lattice
madx.commonHeader('SwissFEL', '#s/#e', None) # sets header
madx.madx.call(self.scriptdir + '/initTwiss.madx')
madx.madx.call(self.scriptdir + '/matchAramis.madx', chdir=True)
self.updateOnlineModel(om, madx.madx, 's[3a][0r].*k1|s20sy03.*k1')
self.parseMatchOutput(f.getvalue().split('\n'), 'Aramis')
if self.signal:
self.signal.emit('Matching done')
return madx.madx.table.twiss
def parseMatchOutput(self, result,prefix,full=False):
isMatch = False
penalty = 1
report=[]
for line in result:
if full:
print(line)
continue
if 'MATCH SUMMARY' in line:
isMatch = True
continue
if 'VARIABLE "TAR"' in line:
isMatch = False
print("--------------------------------------")
print('MATCHING RESULTS: %s (error: %e)' % (prefix,penalty))
if penalty > 1e-5:
for rep in report:
print(rep)
penalty = 1
report.clear()
continue
if isMatch and len(line) > 4:
if 'Final Penal' in line:
penalty = float(line.split('=')[1].strip())
else:
report.append(line)
def updateOnlineModel(self,om,madx,filter):
reg = re.compile(filter)
for var in list(madx.globals):
if reg.match(var):
if '.k1' in var:
element = var.split('.k1')[0]
ele = om.getElement(element)
if not ele is None:
ele.k1 = madx.globals.get(var,0)
print('... Updating', ele.Name, 'to k1=',ele.k1)
else:
print('### Unidentified element', element)
elif '.cory' in var:
element = var.split('.cory')[0]
ele = om.getElement(element)
if not ele is None:
ele.design_kick = madx.globals.get(var, 0)
print('... Updating', ele.Name, 'to design_kick=', ele.design_kick)
else:
print('### Unidentified element', element)