138 lines
4.3 KiB
Python
138 lines
4.3 KiB
Python
import time
|
|
import numpy as np
|
|
|
|
from bstrd import BSCache
|
|
from bstrd.bscache import is_available
|
|
from epics import PV
|
|
|
|
class AdaptiveOrbitNew:
|
|
"""
|
|
Wrapper class to bundle all daq/io needed for adaptive orbit feedback.
|
|
"""
|
|
def __init__(self):
|
|
self.BS=None
|
|
self.PVKick=[]
|
|
self.PVFB = []
|
|
self.BSChannels=[]
|
|
self.BS=None
|
|
self.PVKick=None
|
|
self.PVFB=None
|
|
|
|
|
|
def getChannels(self,beamline,bunch):
|
|
if beamline == 'Aramis':
|
|
ch0 = ['SARFE10-PBIG050-EVR0:CALCI']
|
|
chx = ['SARUN%2.2d-DBPM070:X%d' % (bpm,bunch) for bpm in range(1,17)]
|
|
chy = ['SARUN%2.2d-DBPM070:Y%d' % (bpm,bunch) for bpm in range(1,17)]
|
|
pvFB = [ch.split(':')[0]+':X-REF-FB' for ch in chx]+[ch.split(':')[0]+':Y-REF-FB' for ch in chx]
|
|
pvKick=['SARMA02-MCRX050:I-SET','SARMA02-MCRY050:I-SET','SARUN02-MCRX080:I-SET','SARUN02-MCRY080:I-SET','SFB_ORBIT_SAR:ONOFF1']
|
|
elif beamline == 'Athos':
|
|
ch0 = ['SATFE10-PEPG046-EVR0:CALCI']
|
|
chx=[]
|
|
chy=[]
|
|
for bpm in range(5,23):
|
|
idx = '070'
|
|
if bpm == 5 or bpm ==14:
|
|
idx='410'
|
|
chx.append('SATUN%2.2d-DBPM%s:X%d' % (bpm,idx,bunch))
|
|
chy.append('SATUN%2.2d-DBPM%s:Y%d' % (bpm,idx,bunch))
|
|
pvFB = [ch.split(':')[0]+':X-REF-FB' for ch in chx]+[ch.split(':')[0]+':Y-REF-FB' for ch in chx]
|
|
pvKick=['SATMA01-MCRX610:I-SET','SATMA01-MCRY610:I-SET','SATUN05-MCRX420:I-SET','SATUN05-MCRY420:I-SET','SFB_ORBIT_SAT:ONOFF1']
|
|
else:
|
|
return False
|
|
print("Initializing BSStream for beamline %s and Bunch %d" % (beamline,bunch))
|
|
ch = ch0+chx+chy
|
|
self.BS = self.initBSStream(ch)
|
|
if self.BS is None:
|
|
print('Failed to establish BS-stream')
|
|
return False
|
|
print("Initializing EPICS Channels")
|
|
self.PVFB=self.initPV(pvFB)
|
|
self.PVKick=self.initPV(pvKick)
|
|
if self.PVFB is None or self.PVKick is None:
|
|
print('Failed to establish PV-channels')
|
|
return False
|
|
return True
|
|
|
|
def initBSStream(self,channels):
|
|
ok = True
|
|
for chn in channels:
|
|
ok &= is_available(chn)
|
|
if ok:
|
|
bs = BSCache(1000,receive_timeout=1000) # 1000 second time out, capazity for 1000 second.
|
|
bs.get_vars(channels)
|
|
else:
|
|
for chn in channels:
|
|
if not is_available(chn):
|
|
print('ERROR: BS-Channel %s not found in BS-Dispatcher' % ch)
|
|
bs = None
|
|
self.BSChannels.clear()
|
|
self.BSChannels=channels
|
|
return bs
|
|
|
|
def initPV(self,chx):
|
|
pvs = []
|
|
for x in chx:
|
|
pvs.append(PV(x))
|
|
con = [pv.wait_for_connection(timeout=0.2) for pv in pvs]
|
|
ok = True
|
|
for i, val in enumerate(con):
|
|
ok &=val
|
|
if val is False:
|
|
name = pv[i].pvname
|
|
print("ERROR: PV-Channel %s is not available" % name)
|
|
if ok:
|
|
return pvs
|
|
return None
|
|
|
|
|
|
def flush(self):
|
|
self.BS.flush()
|
|
|
|
def terminate(self):
|
|
print('Stopping BSStream Thread...')
|
|
self.BS.stop()
|
|
self.BS.pt.running.clear() # for some reason I have to
|
|
|
|
def read(self):
|
|
if self.BS is None:
|
|
return None
|
|
data=self.BS.__next__()
|
|
return np.array([data['pid']]+[data[cnl] for cnl in self.BSChannels])
|
|
|
|
def readPV(self):
|
|
if self.PVFB is None:
|
|
return []
|
|
return [pv.value for pv in self.PVFB]
|
|
|
|
def setPV(self,fbval):
|
|
if self.PVFB is None:
|
|
return
|
|
for i in range(len(fbval)):
|
|
self.PVFB[i].value = fbval[i]
|
|
|
|
def getPVNames(self):
|
|
if self.PVFB is None:
|
|
return []
|
|
return [pv.pvname for pv in self.PVFB]
|
|
|
|
|
|
|
|
def getDetectorName(self):
|
|
return self.BSChannels[0]
|
|
|
|
def getKicker(self):
|
|
if self.PVKick is None:
|
|
return None
|
|
return [pv.value for pv in self.PVKick]
|
|
|
|
def setKicker(self,vals):
|
|
if self.PVKick is None:
|
|
return
|
|
for i,val in enumerate(vals):
|
|
self.PVKick[i].value = val
|
|
|
|
|
|
|
|
|