diff --git a/OpticsMachine.py b/OpticsMachine.py index b92caf0..df3f2a6 100644 --- a/OpticsMachine.py +++ b/OpticsMachine.py @@ -1,25 +1,95 @@ import re -import sys -from typing import is_typeddict - - -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 __init__(self, parent=None, office=False): + self.parent=parent + self.offline = office + self.PVs={} + self.PVNames = [] + def initPVs(self,elements=None): + filters = ['-RMSM:SM-SET', '-RSYS:REQUIRED-OP', '-RSYS:SET-ACC-VOLT', '-RSYS:SET-BEAM-PHASE'] + self.PVNames.clear() + for ele0 in elements: + ele = ele0.Name.replace('.','-').upper() + if 'MQUA' in ele: + self.PVNames += [ele+':K1L-SET'] + if 'MSEX' in ele: + self.PVNames += [ele+':K2L-SET'] + if 'MBND' in ele: + if 'MBND100' in ele: + self.PVNames += [ele + ':K0L-SET'] + elif 'SATMA01-MBND300' in ele: + self.PVNames += [ele + ':K0L-SET'] + if 'RACC100' in ele: + name=ele[0:7] + self.PVNames += [name + filter for filter in filters] + if 'UMOD' in ele: + self.PVNames += [ele[0:7] + '-UMOD:K-SET'] + if 'UIND' in ele: + if 'SARUN' in ele: + self.PVNames += [ele + ':K_UND_SET'] + elif 'SATUN' in ele: + self.PVNames += [ele + ':K_READ', ele + ':POL-SET'] + elif 'SINLH' in ele: + self.PVNames += [ele + ':K-SP', ele + ':X-SP'] + self.PVNames += ['SINLH02-MBND100:ENERGY-OP'] - 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) \ No newline at end of file + if self.offline: + self.PVs = {ele: None for ele in self.PVNames} + else: + self.PVs={ele:PV(ele, auto_monitor=False) for ele in self.PVNames} + + def getMachineStatus(self): + if self.offline: + values = {ele: self.PVs[ele] for ele in self.PVs.keys()} + else: + values = {ele:self.PVs[ele].get() for ele in self.PVs.keys()} + + magnets={} + rf = {} + und={} + energy={} + for key in self.PVs.keys(): + if 'MQUA' in key or 'MSEX' in key: + magnets[key[0:15]]=values[key] + if 'MBND' in key: + if 'SINBC' in key or 'SINLH' in key or 'S10BC' in key or 'SATMA' in key or 'SATUN' in key: + magnets[key[0:15]] = values[key] + if 'UMOD' in key: + und[key[0:12]]=[values[key],0.] + if 'UIND' in key: + if 'SARUN' in key: + und[key[0:15]]=[values[key],0] + elif 'SATUN' in key and 'K_READ' in key: + und[key[0:15]]=[values[key],values[key.replace('K_READ','POL-SET')]] + elif 'SINLH' in key and 'K-SP' in key: + x = values[key.replace('K-SP','X-SP')] + if x is None: + und[key[0:15]] = [None,0] + elif x < -100: + und[key[0:15]]=[0,0] + else: + und[key[0:15]] = [values[key], 0] + if 'RMSM' in key: + if values[key]is None: + rf[key[0:7]+'-RSYS']=[None,0] + elif values[key]<9: + rf[key[0:7]+'-RSYS']=[0,0] + else: +# ['-RMSM:SM-SET', '-RSYS:REQUIRED-OP', '-RSYS:SET-ACC-VOLT', '-RSYS:SET-BEAM-PHASE'] + key = key.replace('RMSM:SM-SET','RSYS:REQUIRED-OP') + if values[key] == 0: + rf[key[0:7] + '-RSYS'] = [0, 0] + else: + key1 = key.replace('SM-SET','SET-ACC-VOLT') + key2 = key.replace('SM-SET', 'SET-BEAM-PHASE') + rf[key[0:7] + '-RSYS'] = [values[key1], values[key2]] + if 'ENERGY-OP' in key: + energy[key[0:15]]=values[key] + + status={'Magnet':magnets,'RF':rf,'Undulator':und,'Energy':energy} + return status diff --git a/OpticsModel.py b/OpticsModel.py index f0617e3..e80fd13 100644 --- a/OpticsModel.py +++ b/OpticsModel.py @@ -16,17 +16,19 @@ class Model: # hook up events self.eventHandling() + def getElements(self): + return self.om.listElement('*', 1) def getSettings(self): - elements = self.om.listElement('*',1) + elements = self.getElements() quadrupoles={} sextupoles={} dipoles={} rf={} undulators={} kicker={} - loc = 'SINLH01.DBAM010' - energy={'location': loc, 'energy':self.om.EnergyAt(loc)} + loc = 'SINLH02.MBND100' + energy={'location': loc, 'energy':self.om.EnergyAt(loc)[0]} for ele in elements: if 'MQUA' in ele.Name: quadrupoles[ele.Name]={'k1':ele.k1,'k1L':ele.k1*ele.Length} @@ -35,10 +37,10 @@ class Model: elif 'MBND' in ele.Name: if 'SINLH' in ele.Name or 'SINBC' in ele.Name or 'S10BC' in ele.Name or 'SATMA' in ele.Name or 'SATUN' in ele.Name: dipoles[ele.Name]={'angle':ele.angle} - elif 'UIND' in ele.Name: + elif 'UIND' in ele.Name or 'UMOD' in ele.Name: undulators[ele.Name]={'K':ele.K,'kx':ele.kx,'ky':ele.ky} elif 'RACC' in ele.Name: - rf[ele.Name]={'Gradient':ele.Gradient,'Phase':ele.Phase} + rf[ele.Name]={'Gradient':ele.Gradient*ele.Length,'Phase':ele.Phase} elif 'MKAC' in ele.Name or 'MKDC' in ele.Name: kicker[ele.Name] = {'cory': ele.cory} return {'Quadrupole':quadrupoles,'Sextupole':sextupoles,'Dipole':dipoles,'RF':rf,'Undulator':undulators,'Kicker':kicker,'Energy':energy} diff --git a/OpticsTools.py b/OpticsTools.py index 42be773..e54b0d1 100644 --- a/OpticsTools.py +++ b/OpticsTools.py @@ -27,16 +27,20 @@ class OpticsTools(QtWidgets.QMainWindow, Ui_OpticsGUI): # initialize online model self.model = Model(phase=phase,parent=self) - if phase == 0 and office == False: - self.machine = Machine() - else: - self.machine = None + if phase > 0: + office = True + self.machine = Machine(parent = True, office = office) + self.machine.initPVs(self.model.getElements()) + + self.reference = ReferenceManager(parent = self) self.sandbox = Sandbox(parent = self, machine = self.machine) - + # initialization self.loadSettingsdirect("/sf/data/applications/BD-OpticsTools/reference/settings/ReferenceSetting.json") + self.sandbox.updateSandbox() + # events handling self.actionOpen_2.triggered.connect(self.loadSettings) self.actionSave.triggered.connect(self.saveSettings) diff --git a/sandbox.py b/sandbox.py index cd20b27..ab55d92 100644 --- a/sandbox.py +++ b/sandbox.py @@ -1,10 +1,196 @@ +from PyQt5 import QtCore, QtGui, QtWidgets +import numpy as np +import re + +CGrey = QtGui.QColor(230,230,230) +CBeige = QtGui.QColor(250, 240, 200) +CGreen = QtGui.QColor(100, 255, 100) +CYellow = QtGui.QColor(255, 255, 0) +CRed = QtGui.QColor(255, 100, 100) +CWhite = QtGui.QColor(255, 255, 255) class Sandbox: def __init__(self, parent=None,machine=False): self.parent=parent self.machine=machine + self.parent.MagReStart.editingFinished.connect(self.updateSandbox) + self.parent.MagReFilter.editingFinished.connect(self.updateSandbox) + + + def updateSandbox(self): - a = 1 + machine = self.parent.machine.getMachineStatus() + model = self.parent.model.getSettings() + self.updateMagSandbox(self.parent.MagSB,model,machine['Magnet']) + self.updateUndSandbox(self.parent.UndSB,model,machine['Undulator']) + self.updateRFSandbox(self.parent.RFSB, model, machine['RF']) + self.updateEnergySandbox(model['Energy'],machine['Energy']) + + def updateEnergySandbox(self,model,machine): + E0=1.e-6*model['energy'] + self.parent.SBE0Model.setText('%7.3f' % E0) + E0 = None + for key in machine.keys(): + E0 = machine[key] + if E0 is None: + self.parent.SBE0Machine.setText("---") + else: + self.parent.SBE0Machine.setText('%7.3f' % E0) + + def updateSandboxCommon(self,sb,values,colors,labels): + sb.clear() + ncol = len(labels) + nrow = len(values) + sb.setColumnCount(ncol) + sb.setRowCount(nrow) + for i in range(ncol): + sb.setHorizontalHeaderItem(i, QtWidgets.QTableWidgetItem(labels[i])) + for irow,value in enumerate(values): + color=colors[irow] + for icol in range(ncol): + sb.setItem(irow, icol, QtWidgets.QTableWidgetItem(value[icol])) + sb.item(irow, icol).setBackground(color[icol]) + sb.resizeColumnsToContents() + sb.verticalHeader().hide() + + + def updateRFSandbox(self,sb,model,machine): + labels = ['Station', 'Model', 'Model', 'Machine', 'Machine'] + values = [] + colors = [] + for key in machine.keys(): + sbvalue = [key[0:7]] + sbcolor = [CWhite] + mokey = key[0:7]+'.RACC100' + print(mokey) + scl=1. + if 'CB' in mokey: + scl = 4 + elif 'SINSB03' in mokey or 'SINSB04' in mokey or 'SINXB' in mokey: + scl = 2 + + if mokey in model['RF'].keys(): + Grad=1e-6*model['RF'][mokey]['Gradient']*scl + Phase= model['RF'][mokey]['Phase'] + sbvalue+=['%7.3f' % Grad,'%7.3f' % Phase] + sbcolor += [CBeige, CBeige] + else: + sbvalue += ['---', '---'] + sbcolor += [CGrey, CGrey] + value = machine[key] + if value[0] is None: + sbvalue += ['---', '---'] + sbcolor += [CGrey, CGrey] + else: + sbvalue += ['%f' % machine[key]['Gradient'], '%f' % machine[key]['Phase']] + sbcolor += [CBeige, CBeige] + values.append(sbvalue) + colors.append(sbcolor) + self.updateSandboxCommon(sb, values, colors, labels) + + def updateUndSandbox(self,sb,model,machine,): + labels = ['Undulator', 'Model', 'Model', 'Machine', 'Machine'] + values=[] + colors=[] + pol = ['LH', 'LV+', 'LV-', 'C+', 'C-', 'ZL'] + for key in machine.keys(): + sbvalue=[key] + sbcolor=[CWhite] + mokey = key.replace('-', '.') + if 'UMOD' in mokey: + if 'SATDI' in mokey: + mokey = mokey + '050' + else: + mokey = mokey + '030' + if mokey in model['Undulator'].keys(): + value = model['Undulator'][mokey] + K = '%7.3f' % value['K'] + kx = value['kx'] + ky = value['ky'] + if np.abs(kx - 1) < 0.1: + Pol = 'LV' + elif np.abs(ky - 1) < 0.1: + Pol = 'LH' + elif np.abs(kx - ky) < 0.1: + Pol = 'C' + else: + Pol = 'undef' + sbvalue+=[K,Pol] + sbcolor+=[CBeige,CBeige] + else: + sbvalue+=['---','---'] + sbcolor+=[CGrey,CGrey] + value = machine[key] + # machine + if value[0] is None: + sbvalue +=['---','---'] + sbcolor += [CGrey, CGrey] + else: + sbvalue += ['%7.3f' % value[0], pol[int(value[1])]] + sbcolor += [CBeige,CBeige] + values.append(sbvalue) + colors.append(sbcolor) + self.updateSandboxCommon(sb,values,colors,labels) + + def updateMagSandbox(self,sb,magnets,machine): + labels = ['Magnet', 'Model', 'Machine'] + filt = str(self.parent.MagReStart.text()) + found = False + if filt == '' or filt == '*': + found = True + regpat = re.compile(filt) + filt2 = str(self.parent.MagReFilter.text()) + filt2 = '.*' + filt2 + regpat2 = re.compile(filt2) + + values = [] + colors=[] + + for key in machine.keys(): + if regpat.match(key): + found = True + if not (found and regpat2.match(key)): + continue + sbval=[key] + sbcol=[CWhite] + + maval = machine[key] + moval=None + mokey = key.replace('-','.') + if 'MQUA' in key and mokey in magnets['Quadrupole'].keys(): + moval = magnets['Quadrupole'][mokey]['k1L'] + if 'MSEX' in key and mokey in magnets['Sextupole'].keys(): + moval = magnets['Sextupole'][mokey]['k2L'] + if 'MBND' in key and mokey in magnets['Dipole'].keys(): + moval = magnets['Dipole'][mokey]['angle'] + + + if moval is None: # model + sbval.append('---') + sbcol.append(CGrey) + else: + sbval.append('%7.3f' % moval) + sbcol.append(CBeige) + + if maval is None: # machine + sbval.append('---') + sbcol.append(CGrey) + else: + sbval.append('%7.3' % maval) + if moval is None: + sbcol.append(CGrey) + else: + df = np.abs(moval-maval) + if df < 0.001: + sbcol.append(CGreen) + elif df < 0.01: + sbcol.append(CYellow) + else: + sbcol.append(CRed) + values.append(sbval) + colors.append(sbcol) + + self.updateSandboxCommon(sb, values, colors, labels) diff --git a/ui/OpticsToolsGui.py b/ui/OpticsToolsGui.py index f6c7dab..9cec6b1 100644 --- a/ui/OpticsToolsGui.py +++ b/ui/OpticsToolsGui.py @@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_OpticsGUI(object): def setupUi(self, OpticsGUI): OpticsGUI.setObjectName("OpticsGUI") - OpticsGUI.resize(1052, 780) + OpticsGUI.resize(813, 775) self.centralwidget = QtWidgets.QWidget(OpticsGUI) self.centralwidget.setObjectName("centralwidget") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.centralwidget) @@ -298,6 +298,23 @@ class Ui_OpticsGUI(object): self.groupBox_9.setObjectName("groupBox_9") self.verticalLayout_17 = QtWidgets.QVBoxLayout(self.groupBox_9) self.verticalLayout_17.setObjectName("verticalLayout_17") + self.gridLayout_2 = QtWidgets.QGridLayout() + self.gridLayout_2.setObjectName("gridLayout_2") + self.SBE0Model = QtWidgets.QLineEdit(self.groupBox_9) + self.SBE0Model.setObjectName("SBE0Model") + self.gridLayout_2.addWidget(self.SBE0Model, 1, 1, 1, 1) + self.SBE0Machine = QtWidgets.QLineEdit(self.groupBox_9) + self.SBE0Machine.setObjectName("SBE0Machine") + self.gridLayout_2.addWidget(self.SBE0Machine, 1, 2, 1, 1) + self.label_26 = QtWidgets.QLabel(self.groupBox_9) + self.label_26.setObjectName("label_26") + self.gridLayout_2.addWidget(self.label_26, 1, 0, 1, 1) + self.verticalLayout_17.addLayout(self.gridLayout_2) + self.RFSB = QtWidgets.QTableWidget(self.groupBox_9) + self.RFSB.setObjectName("RFSB") + self.RFSB.setColumnCount(0) + self.RFSB.setRowCount(0) + self.verticalLayout_17.addWidget(self.RFSB) self.UndSB = QtWidgets.QTableWidget(self.groupBox_9) self.UndSB.setObjectName("UndSB") self.UndSB.setColumnCount(0) @@ -310,51 +327,11 @@ class Ui_OpticsGUI(object): self.SB2ModUnd.setObjectName("SB2ModUnd") self.verticalLayout_17.addWidget(self.SB2ModUnd) self.horizontalLayout_5.addWidget(self.groupBox_9) - self.RFgroup = QtWidgets.QGroupBox(self.tab_8) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.RFgroup.sizePolicy().hasHeightForWidth()) - self.RFgroup.setSizePolicy(sizePolicy) - self.RFgroup.setMinimumSize(QtCore.QSize(400, 0)) - self.RFgroup.setObjectName("RFgroup") - self.verticalLayout_18 = QtWidgets.QVBoxLayout(self.RFgroup) - self.verticalLayout_18.setObjectName("verticalLayout_18") - self.label_25 = QtWidgets.QLabel(self.RFgroup) - self.label_25.setObjectName("label_25") - self.verticalLayout_18.addWidget(self.label_25) - self.gridLayout_2 = QtWidgets.QGridLayout() - self.gridLayout_2.setObjectName("gridLayout_2") - self.label_26 = QtWidgets.QLabel(self.RFgroup) - self.label_26.setObjectName("label_26") - self.gridLayout_2.addWidget(self.label_26, 1, 0, 1, 1) - self.label_27 = QtWidgets.QLabel(self.RFgroup) - self.label_27.setObjectName("label_27") - self.gridLayout_2.addWidget(self.label_27, 2, 0, 1, 1) - self.SBE0Machine = QtWidgets.QLineEdit(self.RFgroup) - self.SBE0Machine.setObjectName("SBE0Machine") - self.gridLayout_2.addWidget(self.SBE0Machine, 2, 1, 1, 1) - self.SBE0Model = QtWidgets.QLineEdit(self.RFgroup) - self.SBE0Model.setObjectName("SBE0Model") - self.gridLayout_2.addWidget(self.SBE0Model, 1, 1, 1, 1) - self.verticalLayout_18.addLayout(self.gridLayout_2) - self.RFSB = QtWidgets.QTableWidget(self.RFgroup) - self.RFSB.setObjectName("RFSB") - self.RFSB.setColumnCount(0) - self.RFSB.setRowCount(0) - self.verticalLayout_18.addWidget(self.RFSB) - self.Mach2ModRF = QtWidgets.QPushButton(self.RFgroup) - self.Mach2ModRF.setObjectName("Mach2ModRF") - self.verticalLayout_18.addWidget(self.Mach2ModRF) - self.SB2ModRF = QtWidgets.QPushButton(self.RFgroup) - self.SB2ModRF.setObjectName("SB2ModRF") - self.verticalLayout_18.addWidget(self.SB2ModRF) - self.horizontalLayout_5.addWidget(self.RFgroup) self.TabMaster.addTab(self.tab_8, "") self.verticalLayout_4.addWidget(self.TabMaster) OpticsGUI.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(OpticsGUI) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1052, 22)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 813, 22)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") @@ -480,7 +457,7 @@ class Ui_OpticsGUI(object): self.menubar.addAction(self.menuHelp.menuAction()) self.retranslateUi(OpticsGUI) - self.TabMaster.setCurrentIndex(0) + self.TabMaster.setCurrentIndex(1) self.actionQuit.triggered.connect(OpticsGUI.close) # type: ignore QtCore.QMetaObject.connectSlotsByName(OpticsGUI) @@ -521,16 +498,11 @@ class Ui_OpticsGUI(object): self.SB2MachineMag.setText(_translate("OpticsGUI", "Model -> Machine")) self.Mach2ModMag.setText(_translate("OpticsGUI", "Model <- Sandbox <- Machine")) self.SB2ModMag.setText(_translate("OpticsGUI", "Model <- Sandbox")) - self.groupBox_9.setTitle(_translate("OpticsGUI", "Undulator/ID (K/Gap and Pol./Offset")) + self.groupBox_9.setTitle(_translate("OpticsGUI", "RF (Gradient & Phase) + Undulator (K, Pol)")) + self.label_26.setText(_translate("OpticsGUI", "Energy")) self.Mach2ModUnd.setText(_translate("OpticsGUI", "Model <- Sandbox <- Machine")) self.SB2ModUnd.setText(_translate("OpticsGUI", "Model <- Sandbox")) - self.RFgroup.setTitle(_translate("OpticsGUI", "RF (Gradient and Phase)")) - self.label_25.setText(_translate("OpticsGUI", "Initial Energy (MeV)")) - self.label_26.setText(_translate("OpticsGUI", "Model")) - self.label_27.setText(_translate("OpticsGUI", "Machine")) - self.Mach2ModRF.setText(_translate("OpticsGUI", "Model <- Sandbox <- Machine")) - self.SB2ModRF.setText(_translate("OpticsGUI", "Model <- Sandbox")) - self.TabMaster.setTabText(self.TabMaster.indexOf(self.tab_8), _translate("OpticsGUI", "Settings Sandbox")) + self.TabMaster.setTabText(self.TabMaster.indexOf(self.tab_8), _translate("OpticsGUI", "Sandbox")) self.menuFile.setTitle(_translate("OpticsGUI", "File")) self.menuHelp.setTitle(_translate("OpticsGUI", "Help")) self.actionOpen_2.setText(_translate("OpticsGUI", "Open Settings...")) diff --git a/ui/OpticsToolsGui.ui b/ui/OpticsToolsGui.ui index cd1fe6b..587dfd6 100644 --- a/ui/OpticsToolsGui.ui +++ b/ui/OpticsToolsGui.ui @@ -6,8 +6,8 @@ 0 0 - 1052 - 780 + 813 + 775 @@ -494,9 +494,29 @@ - Undulator/ID (K/Gap and Pol./Offset + RF (Gradient & Phase) + Undulator (K, Pol) + + + + + + + + + + + + Energy + + + + + + + + @@ -517,75 +537,6 @@ - - - - - 0 - 0 - - - - - 400 - 0 - - - - RF (Gradient and Phase) - - - - - - Initial Energy (MeV) - - - - - - - - - Model - - - - - - - Machine - - - - - - - - - - - - - - - - - - Model <- Sandbox <- Machine - - - - - - - Model <- Sandbox - - - - - - @@ -597,7 +548,7 @@ 0 0 - 1052 + 813 22