Initial Commit
This commit is contained in:
25
OpticsMachine.py
Normal file
25
OpticsMachine.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import re
|
||||
import sys
|
||||
from typing import is_typeddict
|
||||
|
||||
sys.path.append('/sf/bd/packages/sfbd')
|
||||
from sfbd.interface import getSnapPV,getSnapVal
|
||||
|
||||
from epics import PV
|
||||
|
||||
class Machine:
|
||||
def __init__(self):
|
||||
print('Initializing PVs for Snapshot...')
|
||||
mags = ['SINLH02-MBND100', 'SINBC02-MBND100', 'S10BC02-MBND100', 'SARCL02-MBND100', 'SATCL01-MBND100',
|
||||
'SATUN05-MBND100']
|
||||
self.snapPVs = getSnapPV() + [PV('%s:ENERGY-OP' % ele, auto_monitor=False) for ele in mags]
|
||||
self.omfilter = ['.*-RMSM:SM-SET','.*-RSYS:REQUIRED-OP','.*-RSYS:SET-ACC-VOLT','.*-RSYS:SET-BEAM-PHASE']
|
||||
|
||||
|
||||
|
||||
def getSnap(self,filters = ['.*']):
|
||||
if isinstance(filters, str):
|
||||
filters = [filters]
|
||||
recomp = re.compile('|'.join(filters))
|
||||
pvget = [pv for pv in self.snapPVs if recomp.match(pv.pvname)]
|
||||
self.snap = getSnapVal(pvget)
|
||||
36
OpticsModel.py
Normal file
36
OpticsModel.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import sys
|
||||
import numpy as np
|
||||
|
||||
sys.path.append('/sf/bd/packages/onlinemodel')
|
||||
from onlinemodel.core import Facility
|
||||
from onlinemodel.code import MadX
|
||||
|
||||
class Model:
|
||||
def __init__(self, phase, debug=False):
|
||||
print('Initializing online model ...')
|
||||
self.phase = phase # current planned future
|
||||
self.om = Facility(phase)
|
||||
self.madx = MadX()
|
||||
self.twiss = None
|
||||
|
||||
def update(self, snap) -> None:
|
||||
self.om.updateModel(snap,True)
|
||||
|
||||
def track(self, start,end,twiss):
|
||||
destination = 'ARAMIS'
|
||||
start0 = start[0:7]
|
||||
end0 = end[0:7]
|
||||
if 'SPO' in end:
|
||||
destination = 'PORTHOS'
|
||||
elif 'SAT' in end:
|
||||
destination = 'ATHOS'
|
||||
elif 'S10BD' in end:
|
||||
destination = 'INJECTOR'
|
||||
self.om.setBranch(destination,start0,end0)
|
||||
self.madx.setInitialCondition(twiss['betax'],twiss['betay'],twiss['alphax'],twiss['alphay'],150.)
|
||||
if len(start) <8:
|
||||
start = '#s'
|
||||
if len(end) < 8:
|
||||
end = '#e'
|
||||
self.madx.track(self.om,False,start,end)
|
||||
self.twiss = self.madx.getTwiss()
|
||||
158
OpticsPlotting.py
Normal file
158
OpticsPlotting.py
Normal file
@@ -0,0 +1,158 @@
|
||||
#!/opt/gfa/python-3.5/latest/bin/python
|
||||
|
||||
import sys
|
||||
import datetime
|
||||
import os.path
|
||||
import time
|
||||
from os import walk
|
||||
import numpy as np
|
||||
import sys
|
||||
import re
|
||||
|
||||
|
||||
from matplotlib.figure import Figure
|
||||
import matplotlib.patches as patches
|
||||
|
||||
from matplotlib.backends.backend_qt5agg import (
|
||||
FigureCanvasQTAgg as FigureCanvas,
|
||||
NavigationToolbar2QT as NavigationToolbar)
|
||||
|
||||
|
||||
|
||||
|
||||
class OpticsPlotting:
|
||||
|
||||
def initmpl(self,mplvl,mplwindow):
|
||||
self.fig=Figure()
|
||||
self.axes=self.fig.add_subplot(111)
|
||||
self.axes2 = self.axes.twinx()
|
||||
self.canvas = FigureCanvas(self.fig)
|
||||
mplvl.addWidget(self.canvas)
|
||||
self.canvas.draw()
|
||||
self.toolbar=NavigationToolbar(self.canvas,mplwindow, coordinates=True)
|
||||
mplvl.addWidget(self.toolbar)
|
||||
|
||||
|
||||
def plotSingle(self,x,y,color,legend,dashed=False):
|
||||
|
||||
if dashed:
|
||||
self.axes.plot(x,y,'--',color=color,label=legend)
|
||||
else:
|
||||
self.axes.plot(x,y,color=color,label=legend)
|
||||
|
||||
|
||||
|
||||
|
||||
def plot(self,data,filt,z0,z1):
|
||||
|
||||
self.axes.clear()
|
||||
self.axes2.clear()
|
||||
|
||||
s=np.array(data['S'])
|
||||
if z0>z1:
|
||||
tmp=z1
|
||||
z1=z0
|
||||
z0=tmp
|
||||
|
||||
i1=np.argmin(np.abs(s-z0))
|
||||
i2=np.argmin(np.abs(s-z1))
|
||||
|
||||
ylabel=r''
|
||||
if filt['BETX']:
|
||||
self.plotSingle(s[i1:i2],data['BETX'][i1:i2],(0,0,1,1),r'$\beta_{x}$')
|
||||
ylabel=ylabel+r'$\beta_x$ (m), '
|
||||
if filt['BETY']:
|
||||
self.plotSingle(s[i1:i2],data['BETY'][i1:i2],(1,0,0,1),r'$\beta_{y}$')
|
||||
ylabel=ylabel+r'$\beta_y$ (m), '
|
||||
if filt['ALFX']:
|
||||
self.plotSingle(s[i1:i2],data['ALFX'][i1:i2],(0,0,1,1),r'$\alpha_{x}$')
|
||||
ylabel=ylabel+r'$\alpha_x$ (rad), '
|
||||
if filt['ALFY']:
|
||||
self.plotSingle(s[i1:i2],data['ALFY'][i1:i2],(1,0,0,1),r'$\alpha_{y}$')
|
||||
ylabel=ylabel+r'$\alpha_y$ (rad), '
|
||||
if filt['DX']:
|
||||
self.plotSingle(s[i1:i2],data['DX'][i1:i2],(0,0,1,1),r'$\eta_{x}$')
|
||||
ylabel=ylabel+r'$\eta_x$ (m), '
|
||||
if filt['DY']:
|
||||
self.plotSingle(s[i1:i2],data['DY'][i1:i2],(1,0,0,1),r'$\eta_{y}$')
|
||||
ylabel=ylabel+r'$\eta_y$ (m), '
|
||||
if filt['RE56']:
|
||||
self.plotSingle(s[i1:i2],data['RE56'][i1:i2],(0,0,0,1),r'$R_{56}$')
|
||||
ylabel=ylabel+r'$R_{56}$ (m), '
|
||||
if filt['Energy']:
|
||||
self.plotSingle(s[i1:i2],data['Energy'][i1:i2],(0,1,0,1),r'$E$')
|
||||
ylabel=ylabel+r'$E$ (MeV), '
|
||||
|
||||
|
||||
if len(ylabel) < 3:
|
||||
self.canvas.draw()
|
||||
return
|
||||
|
||||
self.axes.legend(bbox_to_anchor=(0.15,0.85))
|
||||
self.axes.set_xlabel('s (m)')
|
||||
self.axes.set_ylabel(ylabel[0:-2])
|
||||
|
||||
self.plotLayout(s,data['NAME'])
|
||||
self.axes.set_xlim([s[i1],s[i2]])
|
||||
ylim=self.axes.get_ylim()
|
||||
dl=np.abs(ylim[1]-ylim[0])
|
||||
yl=[ylim[0],ylim[1]+0.2*dl]
|
||||
self.axes.set_ylim(yl)
|
||||
self.axes2.set_xlim([s[i1],s[i2]])
|
||||
self.canvas.draw()
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def plotLayout(self,s,elements):
|
||||
splitquads=False
|
||||
sstart=0
|
||||
|
||||
s1=[np.min(s),np.max(s)]
|
||||
s2=[0.9,0.9]
|
||||
self.axes2.plot(s1,s2,'k')
|
||||
for i,name in enumerate(elements):
|
||||
if 'MBND' in name:
|
||||
s1=s[i-1]
|
||||
s2=s[i]
|
||||
self.axes2.add_patch(patches.Rectangle((s1, 0.9), (s2-s1),0.03,facecolor='blue',edgecolor="none"))
|
||||
if 'MSEX' in name:
|
||||
s1=s[i-1]
|
||||
s2=s[i]
|
||||
self.axes2.add_patch(patches.Rectangle((s1, 0.87), (s2-s1),0.06,facecolor='green',edgecolor="none"))
|
||||
|
||||
if 'UIND' in name:
|
||||
s1=s[i-1]
|
||||
s2=s[i]
|
||||
self.axes2.add_patch(patches.Rectangle((s1, 0.88), (s2-s1),0.04,facecolor='purple',edgecolor="none"))
|
||||
|
||||
if 'ACC' in name or 'TDS' in name:
|
||||
s1=s[i-1]
|
||||
s2=s[i]
|
||||
self.axes2.add_patch(patches.Rectangle((s1, 0.89), (s2-s1),0.02,facecolor='cyan',edgecolor="none"))
|
||||
|
||||
if 'MQUA' in name:
|
||||
if splitquads == True:
|
||||
if 'END' in name:
|
||||
s1=sstart
|
||||
s2=s[i]
|
||||
self.axes2.add_patch(patches.Rectangle((s1, 0.85), (s2-s1),0.1,facecolor='red',edgecolor="none"))
|
||||
splitquads=False
|
||||
else:
|
||||
if 'START' in name:
|
||||
splitquads=True
|
||||
sstart=s[i]
|
||||
else:
|
||||
s1=s[i-1]
|
||||
s2=s[i]
|
||||
self.axes2.add_patch(patches.Rectangle((s1, 0.85), (s2-s1),0.1,facecolor='red',edgecolor="none"))
|
||||
|
||||
self.axes2.set_ylim([0,1])
|
||||
self.axes2.yaxis.set_visible(False)
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
131
OpticsTools.py
Normal file
131
OpticsTools.py
Normal file
@@ -0,0 +1,131 @@
|
||||
import sys
|
||||
#import re
|
||||
#import numpy as np
|
||||
#import copy
|
||||
#import os
|
||||
#import json
|
||||
from datetime import datetime
|
||||
import time
|
||||
#from shutil import copyfile
|
||||
#from os.path import isfile, join
|
||||
|
||||
from PyQt5 import QtWidgets,QtGui
|
||||
from PyQt5.uic import loadUiType
|
||||
#from PyQt5.QtGui import QPixmap, QTransform
|
||||
#from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
|
||||
|
||||
from ui.OpticsToolsGui import Ui_OpticsGUI
|
||||
|
||||
from OpticsModel import Model
|
||||
from OpticsMachine import Machine
|
||||
from OpticsPlotting import OpticsPlotting
|
||||
class OpticsTools(QtWidgets.QMainWindow, Ui_OpticsGUI):
|
||||
def __init__(self,phase=0):
|
||||
super(OpticsTools, self).__init__()
|
||||
self.setupUi(self)
|
||||
|
||||
self.version = '1.0.1'
|
||||
self.setWindowIcon(QtGui.QIcon("rsc/iconoptics.png"))
|
||||
self.setWindowTitle("SwissFEL Optics Tools")
|
||||
|
||||
self.plot = OpticsPlotting()
|
||||
self.plot.initmpl(self.mplvl, self.mplwindow)
|
||||
|
||||
# initialize online model
|
||||
self.model = Model(phase)
|
||||
if phase == 0:
|
||||
self.machine = Machine()
|
||||
else:
|
||||
self.machine = None
|
||||
|
||||
|
||||
# widget signals
|
||||
self.UITrack.clicked.connect(self.track)
|
||||
|
||||
# all action for optics plotting
|
||||
self.PBetax.toggled.connect(self.doplot)
|
||||
self.PAlphax.toggled.connect(self.doplot)
|
||||
self.PBetay.toggled.connect(self.doplot)
|
||||
self.PAlphay.toggled.connect(self.doplot)
|
||||
self.PEtax.toggled.connect(self.doplot)
|
||||
self.PEtay.toggled.connect(self.doplot)
|
||||
self.PR56.toggled.connect(self.doplot)
|
||||
# self.PEnergy.toggled.connect(self.doplot)
|
||||
self.PStart.editingFinished.connect(self.doplot)
|
||||
self.PEnd.editingFinished.connect(self.doplot)
|
||||
|
||||
def track(self):
|
||||
start = str(self.UITrackStart.text())
|
||||
end = str(self.UITrackEnd.text())
|
||||
twiss = {}
|
||||
twiss['betax'] = float(str(self.UIBetax.text()))
|
||||
twiss['betay'] = float(str(self.UIBetay.text()))
|
||||
twiss['alphax'] = float(str(self.UIAlphax.text()))
|
||||
twiss['alphay'] = float(str(self.UIAlphay.text()))
|
||||
self.model.track(start,end,twiss)
|
||||
self.updateOpticsTable()
|
||||
|
||||
def updateOpticsTable(self):
|
||||
self.UITwissValues.clear()
|
||||
if self.model.twiss is None:
|
||||
return
|
||||
|
||||
res = self.model.twiss
|
||||
if 'NAME' in res.keys():
|
||||
nrow = len(res['NAME'])
|
||||
if nrow == 0:
|
||||
return
|
||||
else:
|
||||
return
|
||||
ncol = len(res.keys())
|
||||
self.UITwissValues.setColumnCount(ncol + 1)
|
||||
self.UITwissValues.setRowCount(nrow)
|
||||
for j,key in enumerate(res.keys()):
|
||||
col = res[key]
|
||||
self.UITwissValues.setHorizontalHeaderItem(j, QtWidgets.QTableWidgetItem(key))
|
||||
for i,val in enumerate(col):
|
||||
if j == 0:
|
||||
self.UITwissValues.setItem(i, j, QtWidgets.QTableWidgetItem(val))
|
||||
else:
|
||||
self.UITwissValues.setItem(i, j, QtWidgets.QTableWidgetItem('%10.6f' % val))
|
||||
self.UITwissValues.resizeColumnsToContents()
|
||||
self.UITwissValues.verticalHeader().hide()
|
||||
self.UITwissValues.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
|
||||
|
||||
def doplot(self):
|
||||
if self.model.twiss is None:
|
||||
return
|
||||
|
||||
zstart=float(str(self.PStart.text()))
|
||||
zend=float(str(self.PEnd.text()))
|
||||
|
||||
filt={}
|
||||
filt['BETX']=self.PBetax.isChecked()
|
||||
filt['BETY']=self.PBetay.isChecked()
|
||||
filt['ALFX']=self.PAlphax.isChecked()
|
||||
filt['ALFY']=self.PAlphay.isChecked()
|
||||
filt['DX']=self.PEtax.isChecked()
|
||||
filt['DY']=self.PEtay.isChecked()
|
||||
filt['RE56']=self.PR56.isChecked()
|
||||
filt['Energy']=self.PEnergy.isChecked()
|
||||
self.plot.plot(self.model.twiss,filt,zstart,zend)
|
||||
|
||||
|
||||
|
||||
# --------------------------------
|
||||
# Main routine
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
QtWidgets.QApplication.setStyle(QtWidgets.QStyleFactory.create("plastique"))
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
if len(sys.argv) > 1:
|
||||
arg=int(sys.argv[1])
|
||||
else:
|
||||
arg=0
|
||||
main = OpticsTools()
|
||||
main.show()
|
||||
sys.exit(app.exec_())
|
||||
BIN
rsc/iconoptics.png
Normal file
BIN
rsc/iconoptics.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
1440
ui/OpticsToolsGui.py
Normal file
1440
ui/OpticsToolsGui.py
Normal file
File diff suppressed because it is too large
Load Diff
2591
ui/OpticsToolsGui.ui
Normal file
2591
ui/OpticsToolsGui.ui
Normal file
File diff suppressed because it is too large
Load Diff
2
updateGui.sh
Executable file
2
updateGui.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
pyuic5 ui/OpticsToolsGui.ui > ui/OpticsToolsGui.py
|
||||
Reference in New Issue
Block a user