Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
14d37c3e67 | |||
14d0db7fad | |||
2267992699 | |||
26998e15dd | |||
100be302e9 | |||
1d933a66ce | |||
a5189537bb | |||
b221a7f964 | |||
127f3ef9db | |||
8de87ed1a9 | |||
423e724022 | |||
fa67b2fab9 | |||
716d1cbf2a | |||
2a0c5cf049 | |||
f5b6f29efc | |||
68cd4d5633 | |||
52e126c1af | |||
bca4098438 | |||
964da0a16f | |||
f2c07f0c98 | |||
36b7a2980a | |||
5e06e49c45 | |||
01be4a5203 | |||
e603069ffd | |||
26eebc650b | |||
24cbccb6a6 | |||
d1fb0b3462 | |||
a07f1bcf42 | |||
2906c9cc44 | |||
6fa15dd9d6 |
@ -27,8 +27,8 @@ class AdaptiveOrbit:
|
|||||||
idx = '070'
|
idx = '070'
|
||||||
if bpm == 5 or bpm ==14:
|
if bpm == 5 or bpm ==14:
|
||||||
idx='410'
|
idx='410'
|
||||||
self.ATchx.append('SATUN%2.2d-DBPM%s:X2' % (bpm,idx))
|
self.ATchx.append('SATUN%2.2d-DBPM%s:X1' % (bpm,idx))
|
||||||
self.ATchy.append('SATUN%2.2d-DBPM%s:Y2' % (bpm,idx))
|
self.ATchy.append('SATUN%2.2d-DBPM%s:Y1' % (bpm,idx))
|
||||||
self.bsAT = self.initBSStream([self.ATch0]+self.ATchx+self.ATchy)
|
self.bsAT = self.initBSStream([self.ATch0]+self.ATchx+self.ATchy)
|
||||||
self.pvAT = self.initPV(self.ATchx)
|
self.pvAT = self.initPV(self.ATchx)
|
||||||
self.kickerAT = self.initPV(['SATMA01-MCRX610:I-SET','SATMA01-MCRY610:I-SET','SATUN05-MCRX420:I-SET','SATUN05-MCRY420:I-SET','SFB_ORBIT_SAT:ONOFF1'])
|
self.kickerAT = self.initPV(['SATMA01-MCRX610:I-SET','SATMA01-MCRY610:I-SET','SATUN05-MCRX420:I-SET','SATUN05-MCRY420:I-SET','SFB_ORBIT_SAT:ONOFF1'])
|
||||||
@ -39,7 +39,7 @@ class AdaptiveOrbit:
|
|||||||
|
|
||||||
def initBSStream(self,channels):
|
def initBSStream(self,channels):
|
||||||
print("Initializing BSstream")
|
print("Initializing BSstream")
|
||||||
bs = BSCache(100000,100000) # 1000 second time out, capazity for 1000 second.
|
bs = BSCache(100000,receive_timeout=100000) # 1000 second time out, capazity for 1000 second.
|
||||||
bs.get_vars(channels)
|
bs.get_vars(channels)
|
||||||
return bs
|
return bs
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class Dispersion:
|
|||||||
self.scale = scl
|
self.scale = scl
|
||||||
# define stream
|
# define stream
|
||||||
print('Getting BSCache')
|
print('Getting BSCache')
|
||||||
self.bsc = BSCache(100000,10000) # 100 second timeout, size for 100 second data taken
|
self.bsc = BSCache(100000, receive_timeout=10000) # 1000 second timeout, size for 100 second data taken
|
||||||
self.bsc.get_vars(self.sensor) # this starts the stream into the cache
|
self.bsc.get_vars(self.sensor) # this starts the stream into the cache
|
||||||
print('Getting BSCache done')
|
print('Getting BSCache done')
|
||||||
|
|
||||||
|
@ -1,23 +1,34 @@
|
|||||||
import time
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
from bstrd import BSCache
|
from bstrd import BSCache
|
||||||
from epics import PV
|
from epics import PV
|
||||||
|
|
||||||
|
athos_uncalibrated = 'SATFE10-PEPG046-EVR0:CALCI'
|
||||||
|
athos_calibrated = 'SATFE10-PEPG046:FCUP-INTENSITY-CAL'
|
||||||
|
aramis_uncalibrated = 'SARFE10-PBIG050-EVR0:CALCI'
|
||||||
|
aramis_calibrated = 'SARFE10-PBPG050:HAMP-INTENSITY-CAL'
|
||||||
|
eehg_spectrometer = 'SSL2-CPCW-SPEC01:SPECTRUM'
|
||||||
|
channel_dict = {
|
||||||
|
'PSSS': ['SARFE10-PSSS059:SPECTRUM_Y'],
|
||||||
|
'PMOS Maloja': ['SATOP21-PMOS127-2D:SPECTRUM_Y', athos_uncalibrated, athos_calibrated],
|
||||||
|
'PMOS Furka': ['SATOP31-PMOS132-2D:SPECTRUM_Y', 'SATOP31-PMOS132-2D:SPECTRUM_X', athos_uncalibrated, athos_calibrated],
|
||||||
|
'PSSS LB': ['SARFE10-PSSS059-LB:SPECTRUM_Y'],
|
||||||
|
'PSSS incl gasd': ['SARFE10-PSSS059:SPECTRUM_Y', aramis_uncalibrated, aramis_calibrated],
|
||||||
|
'PSSS LB incl gasd': ['SARFE10-PSSS059-LB:SPECTRUM_Y', aramis_uncalibrated, aramis_calibrated],
|
||||||
|
'PMOS Maloja EEHG': ['SATOP21-PMOS127-2D:SPECTRUM_Y', eehg_spectrometer],
|
||||||
|
'PMOS Furka EEHG': ['SATOP31-PMOS132-2D:SPECTRUM_Y', eehg_spectrometer],
|
||||||
|
}
|
||||||
|
names = ['PSSS', 'PMOS Maloja', 'PMOS Furka', 'PSSS LB', 'PSSS incl gasd', 'PSSS LB incl gasd', 'PMOS Maloja EEHG','PMOS Furka EEHG']
|
||||||
|
|
||||||
class SpectralAnalysis:
|
class SpectralAnalysis:
|
||||||
"""
|
|
||||||
Wrapper class to bundle all daq/io needed for adaptive orbit feedback.
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.bs = BSCache(100000,receive_timeout=10000) # 100 second timeout, size for 10 second data taken
|
||||||
self.bs = BSCache(100000,10000) # 100 second timeout, size for 100 second data taken
|
|
||||||
self.bs.stop()
|
self.bs.stop()
|
||||||
|
self.channel = None
|
||||||
|
self.channels = [channel_dict[x] for x in names]
|
||||||
|
self.hasBStream=False
|
||||||
|
|
||||||
self.channel = ''
|
def connect_name(self, name):
|
||||||
self.channels = ['SARFE10-PSSS059:SPECTRUM_Y',
|
index = names.index(name)
|
||||||
'SATOP21-PMOS127-2D:SPECTRUM_Y',
|
self.connect(index)
|
||||||
'SATOP31-PMOS132-2D:SPECTRUM_Y']
|
|
||||||
self.isConnected = False
|
|
||||||
|
|
||||||
def connect(self,ich):
|
def connect(self,ich):
|
||||||
if ich < 0 or ich >= len(self.channels):
|
if ich < 0 or ich >= len(self.channels):
|
||||||
@ -25,25 +36,71 @@ class SpectralAnalysis:
|
|||||||
self.channel = self.channels[ich]
|
self.channel = self.channels[ich]
|
||||||
print('Connecting to BS-Channel:',self.channel)
|
print('Connecting to BS-Channel:',self.channel)
|
||||||
self.bs.channels.clear()
|
self.bs.channels.clear()
|
||||||
self.bs.get_var(self.channel) # this starts the stream into the cache
|
self.hasBStream=True
|
||||||
self.pv = PV(self.channel.replace('_Y','_X'))
|
try:
|
||||||
|
self.bs.get_vars(self.channel) # this starts the stream into the cache
|
||||||
|
except ValueError:
|
||||||
|
print('Cannot find requested channels in BS stream')
|
||||||
|
self.hasBStream=False
|
||||||
|
self.pv = PV(self.channel[0].replace('_Y','_X'))
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
print('Stopping BSStream Thread...')
|
print('Stopping BSStream Thread...')
|
||||||
self.bs.stop()
|
self.bs.stop()
|
||||||
self.bs.pt.running.clear() # for some reason I have to
|
self.bs.pt.running.clear() # for some reason I have to
|
||||||
|
self.pv.disconnect()
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
self.bs.flush()
|
self.bs.flush()
|
||||||
|
|
||||||
def read(self):
|
def read(self):
|
||||||
data=self.bs.__next__()
|
return next(self.bs)
|
||||||
return data['pid'],data[self.channel]
|
|
||||||
|
|
||||||
def readPV(self):
|
def read_spectrum_axis(self):
|
||||||
return self.pv.value
|
return self.pv.value
|
||||||
|
|
||||||
def getSpectrometerName(self):
|
def getSpectrometerName(self):
|
||||||
return self.channel
|
return self.channel
|
||||||
|
|
||||||
|
class SpectralAnalysis2:
|
||||||
|
def __init__(self):
|
||||||
|
self.bs1 = BSCache(100000, receive_timeout=10000)
|
||||||
|
self.bs2 = BSCache(100000, receive_timeout=10000)
|
||||||
|
self.bs1.stop()
|
||||||
|
self.bs2.stop()
|
||||||
|
self.hasBStream=False
|
||||||
|
|
||||||
|
def connect_name(self, name):
|
||||||
|
channels = channel_dict[name]
|
||||||
|
self.bs1.channels.clear()
|
||||||
|
self.hasBStream = True
|
||||||
|
try:
|
||||||
|
self.bs1.get_vars(channels[:1]) # this starts the stream into the cache
|
||||||
|
except ValueError:
|
||||||
|
print('Cannot find requested channel %s in BS stream' % channels[0])
|
||||||
|
self.hasBStream=False
|
||||||
|
if len(channels) > 1:
|
||||||
|
try:
|
||||||
|
self.bs2.get_vars(channels[1:]) # this starts the stream into the cache
|
||||||
|
except ValueError:
|
||||||
|
print('Cannot find requested channel %s in BS stream' % channels[1:])
|
||||||
|
self.hasBStream=False
|
||||||
|
self.pv = PV(channels[0].replace('_Y','_X'))
|
||||||
|
|
||||||
|
def read_spectrum_axis(self):
|
||||||
|
return self.pv.value
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
for _bs in self.bs1, self.bs2:
|
||||||
|
_bs.flush()
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
return next(self.bs1), next(self.bs2)
|
||||||
|
|
||||||
|
def terminate(self):
|
||||||
|
print('Stopping BSStream Thread...')
|
||||||
|
for _bs in self.bs1, self.bs2:
|
||||||
|
_bs.stop()
|
||||||
|
_bs.pt.running.clear() # for some reason I have to
|
||||||
|
self.pv.disconnect()
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class XTCAVStabilizer:
|
|||||||
self.PVPhase = PV('SATMA02-RSYS:SET-BEAM-PHASE')
|
self.PVPhase = PV('SATMA02-RSYS:SET-BEAM-PHASE')
|
||||||
|
|
||||||
# the BS channels
|
# the BS channels
|
||||||
self.bs = BSCache(100000,10000) # 100 second timeout, size for 100 second data taken
|
self.bs = BSCache(100000, receive_timeout=10000) # 100 second timeout, size for 10 second data taken
|
||||||
self.channels = ['SATBD02-DBPM040:X2','SATMA02-RLLE-DSP:PHASE-VS','SATBD02-DBPM040:X2-VALID']
|
self.channels = ['SATBD02-DBPM040:X2','SATMA02-RLLE-DSP:PHASE-VS','SATBD02-DBPM040:X2-VALID']
|
||||||
self.validation = self.channels[2]
|
self.validation = self.channels[2]
|
||||||
self.bs.get_vars(self.channels) # this starts the stream into the cache
|
self.bs.get_vars(self.channels) # this starts the stream into the cache
|
||||||
|
@ -2,3 +2,4 @@ from .magnet import Magnet
|
|||||||
from .camacquisition import CamAcquisition
|
from .camacquisition import CamAcquisition
|
||||||
from .counteradjustable import CounterAdjustable
|
from .counteradjustable import CounterAdjustable
|
||||||
from .bscacquisition import BSCAcquisition
|
from .bscacquisition import BSCAcquisition
|
||||||
|
from .pvcombiadjustable import PVCombiAdjustable
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
import h5py
|
import h5py
|
||||||
import numpy as np
|
#import numpy as np
|
||||||
|
|
||||||
from slic.core.acquisition.acquisition import Acquisition
|
from slic.core.acquisition.acquisition import Acquisition
|
||||||
|
|
||||||
@ -9,32 +8,37 @@ from slic.core.acquisition.acquisition import Acquisition
|
|||||||
|
|
||||||
class BSCAcquisition(Acquisition):
|
class BSCAcquisition(Acquisition):
|
||||||
|
|
||||||
|
def __init__(self, bscache, *args, use_channels=None, **kwargs):
|
||||||
|
self.bscache = bscache
|
||||||
|
self.use_channels = use_channels
|
||||||
|
self.grp = 0
|
||||||
|
super().__init__(*args, default_channels= self.use_channels or self.bscache.channels.keys(), **kwargs)
|
||||||
|
|
||||||
|
def setGroup(self,idx):
|
||||||
|
self.grp = idx
|
||||||
|
|
||||||
def _acquire(self, filename, channels=None, data_base_dir=None, scan_info=None, n_pulses=100, **kwargs):
|
def _acquire(self, filename, channels=None, data_base_dir=None, scan_info=None, n_pulses=100, **kwargs):
|
||||||
|
self.bscache.flush()
|
||||||
queue =channels[0] # abusing interface since BSAcquisition assume a list of channels
|
data = []
|
||||||
|
|
||||||
# allocating space
|
|
||||||
data={}
|
|
||||||
chns = queue.channels
|
|
||||||
for chn in chns:
|
|
||||||
data[chn]={'data':np.zeros((n_pulses))}
|
|
||||||
data['pulse_id']=np.zeros((n_pulses))
|
|
||||||
|
|
||||||
# clear the queue
|
|
||||||
queue.flush()
|
|
||||||
for i in range(n_pulses):
|
for i in range(n_pulses):
|
||||||
msg = queue.__next__() # pull data from cache
|
data.append(next(self.bscache))
|
||||||
for chn in chns:
|
|
||||||
data[chn]['data'][i] = msg[chn]
|
|
||||||
data['pulse_id'][i]=msg['pid']
|
|
||||||
|
|
||||||
# write out the data file
|
# write out the data file
|
||||||
hid = h5py.File(filename,'w')
|
use_channels = self.use_channels or self.bscache.channels.keys()
|
||||||
hid.create_dataset('pulse_id', data = data['pulse_id'])
|
with h5py.File(filename,'a') as hid:
|
||||||
for chn in chns:
|
# save the pulse ID
|
||||||
gid = hid.create_group(chn)
|
singledata = [ele['pid'] for ele in data]
|
||||||
for key in data[chn].keys():
|
pidname = 'pulse_id/group%d' % self.grp
|
||||||
gid.create_dataset(key, data = data[chn][key])
|
hid.create_dataset(pidname, data=singledata)
|
||||||
hid.close()
|
for chn in use_channels:
|
||||||
|
singledata = []
|
||||||
|
for ele in data:
|
||||||
|
if chn in ele:
|
||||||
|
singledata.append(ele[chn])
|
||||||
|
else:
|
||||||
|
print('%s not in data!' % chn)
|
||||||
|
if not chn == 'pid':
|
||||||
|
dname = chn.replace(':','/')+'/data'
|
||||||
|
hid.create_dataset(dname, data=singledata)
|
||||||
|
dpid = dname.replace('/data','/pid')
|
||||||
|
hid[dpid] = hid[pidname]
|
42
ext/pvcombiadjustable.py
Normal file
42
ext/pvcombiadjustable.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
from slic.core.adjustable import Adjustable,DummyAdjustable,PVAdjustable
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class PVCombiAdjustable(Adjustable):
|
||||||
|
def __init__(self, adjustables,values):
|
||||||
|
self.adjustables = adjustables
|
||||||
|
self.values = values # array or indiviual array values
|
||||||
|
|
||||||
|
|
||||||
|
def set_target_value(self, value):
|
||||||
|
print('##### Setvalue:',value)
|
||||||
|
# check if values are in range
|
||||||
|
for i,adj in enumerate(self.adjustables):
|
||||||
|
idx = int(value[i])
|
||||||
|
print('### Index',i, idx)
|
||||||
|
val=self.values[i][idx]
|
||||||
|
print('### Setting',adj.name,'to',val)
|
||||||
|
adj.set_target_value(val)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def units(self):
|
||||||
|
return ['m' for adj in self.adjustables]
|
||||||
|
# return [adj.units() for adj in self.adjustables if adj is not None]
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_value(self, readback=True):
|
||||||
|
return [adj.get_current_value() for adj in self.adjustables] # this is different for dummy elements
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
for adj in self.adjustbale:
|
||||||
|
adj.stop()
|
||||||
|
|
||||||
|
def is_moving(self):
|
||||||
|
return any([adj.is_moving() for adj in self.adjustables])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
from .snap import getSnap
|
from .snap import getSnap
|
||||||
|
from .snap import getSnapPV
|
||||||
|
from .snap import getSnapVal
|
||||||
from .snap import saveSnap
|
from .snap import saveSnap
|
||||||
from .snap import loadSnap
|
from .snap import loadSnap
|
||||||
from .snap import parseSnapShotReqYAML
|
from .snap import parseSnapShotReqYAML
|
||||||
@ -7,5 +9,7 @@ from .save import getDatasetFileName
|
|||||||
from .load import loadDataset
|
from .load import loadDataset
|
||||||
from .elog import writeElog
|
from .elog import writeElog
|
||||||
from .slic import SlicScan
|
from .slic import SlicScan
|
||||||
|
from .slic import importSlicScan
|
||||||
from .doocs import doocsread
|
from .doocs import doocsread
|
||||||
from .doocs import doocswrite
|
from .doocs import doocswrite
|
||||||
|
|
||||||
|
33
interface/doocs.py
Normal file
33
interface/doocs.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def doocsread(mystr):
|
||||||
|
""" mystr input can be a string or a list """
|
||||||
|
if isinstance(mystr, list): # it's a list
|
||||||
|
readCmd = ' '.join(mystr)
|
||||||
|
else:
|
||||||
|
readCmd = mystr
|
||||||
|
cmd = ['doocsget', '-c', readCmd]
|
||||||
|
MyOut = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
stdout, stderr = MyOut.communicate()
|
||||||
|
if b'result->error()' in stdout.split():
|
||||||
|
print('ERROR: reading error')
|
||||||
|
print(mystr)
|
||||||
|
return
|
||||||
|
result = [element.decode('utf-8') for element in stdout.split()]
|
||||||
|
if len(result) == 1: # one element only
|
||||||
|
try:
|
||||||
|
return float(result[0])
|
||||||
|
except Exception as e:
|
||||||
|
return result[0]
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
return [float(x) for x in result]
|
||||||
|
except Exception as e:
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def doocswrite(mystr, target):
|
||||||
|
cmd = ['doocsput', '-c', mystr, '-d', str(target)]
|
||||||
|
MyOut = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
stdout, stderr = MyOut.communicate()
|
@ -3,11 +3,26 @@ import h5py
|
|||||||
|
|
||||||
def loadDataset(filename):
|
def loadDataset(filename):
|
||||||
hid = h5py.File(filename, "r")
|
hid = h5py.File(filename, "r")
|
||||||
|
icount = 0
|
||||||
snap = loadSnap(hid)
|
snap = loadSnap(hid)
|
||||||
data = loadData(hid)
|
data={}
|
||||||
act = loadActuator(hid)
|
act= {}
|
||||||
|
maxID = 0
|
||||||
|
for key in hid.keys():
|
||||||
|
if 'scan' in key:
|
||||||
|
ID = int(key.split('_')[1])
|
||||||
|
if ID > maxID:
|
||||||
|
maxID = ID
|
||||||
|
print('Reading scan_%d' % ID)
|
||||||
|
data[ID]=loadData(hid,ID)
|
||||||
|
act[ID]=loadActuator(hid,ID)
|
||||||
|
icount +=1
|
||||||
hid.close()
|
hid.close()
|
||||||
return data,act,snap
|
if icount == 0:
|
||||||
|
return None, None, None
|
||||||
|
elif icount == 1:
|
||||||
|
return data[0], act[0],snap
|
||||||
|
return [data[j] for j in range(maxID+1)],[act[j] for j in range(maxID+1)],snap
|
||||||
|
|
||||||
def loadSnap(hid):
|
def loadSnap(hid):
|
||||||
snap={}
|
snap={}
|
||||||
|
153
interface/magnet.py
Normal file
153
interface/magnet.py
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
from time import sleep
|
||||||
|
from epics import PV,caget_many, caput_many
|
||||||
|
import numpy as np
|
||||||
|
from threading import Thread
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
#from onlinemodel.interface import SwissFELMagnet
|
||||||
|
|
||||||
|
class Magnet:
|
||||||
|
|
||||||
|
def __init__(self, beamline = 'ARAMIS',debug=False, signal = None, cal = None):
|
||||||
|
self.beamline = beamline
|
||||||
|
self.debug=debug
|
||||||
|
self.signal = signal
|
||||||
|
self.progress = None
|
||||||
|
# self.cal = SwissFELMagnet()
|
||||||
|
# getting the array
|
||||||
|
temp = np.sort(np.array(list(range(0, 11)) + [0.5, 1.5]))[::-1]
|
||||||
|
temp2 = -1. * temp
|
||||||
|
cyclingCurrents = np.ones(len(temp) * 2) * 0.
|
||||||
|
cyclingCurrents[::2] = temp
|
||||||
|
cyclingCurrents[1::2] = temp2
|
||||||
|
self.currents = cyclingCurrents[:-1]
|
||||||
|
self.cyclingPause = 3
|
||||||
|
self.pvcor = []
|
||||||
|
self.abort = False
|
||||||
|
|
||||||
|
def doAbort(self):
|
||||||
|
self.abort = True
|
||||||
|
|
||||||
|
def setMagnetI(self,maglist,vals):
|
||||||
|
if self.debug:
|
||||||
|
for i,ele in enumerate(maglist):
|
||||||
|
print('DEBUG: Setting %s to: %f A' % (ele,vals[i]))
|
||||||
|
return
|
||||||
|
caput_many(maglist,vals)
|
||||||
|
|
||||||
|
def setMagnets(self,maglist,magbd,erg):
|
||||||
|
for mag in maglist.keys():
|
||||||
|
Itar = self.cal.QuadrupoleKL2I(magbd[mag],maglist[mag],erg*1e6)
|
||||||
|
pv = PV('%s:I-SET' % mag)
|
||||||
|
if not Itar is None:
|
||||||
|
if self.debug:
|
||||||
|
self.signal.emit('DEBUG: Setting %s to %f' % (pv.pvname,Itar))
|
||||||
|
else:
|
||||||
|
pv.value = Itar
|
||||||
|
|
||||||
|
def scaleMagnets(self,maglist,magbg,EProfCur,EProfTar):
|
||||||
|
# get current from magnets
|
||||||
|
for i,mag in enumerate(maglist):
|
||||||
|
if 'SAR' in mag:
|
||||||
|
ecur = EProfCur[-1]
|
||||||
|
etar = EProfTar[-1]
|
||||||
|
elif 'S30' in mag:
|
||||||
|
idx = int(mag[5:7])
|
||||||
|
if idx >= len(EProfCur):
|
||||||
|
ecur = EProfCur[-1]
|
||||||
|
etar = EProfTar[-1]
|
||||||
|
else:
|
||||||
|
ecur = EProfCur[idx]
|
||||||
|
etar = EProfTar[idx]
|
||||||
|
if 'MQUA' in mag:
|
||||||
|
pv = PV('%s:I-SET' % mag)
|
||||||
|
valmag = pv.value
|
||||||
|
strength = self.cal.QuadrupoleI2KL(magbg[i],valmag,ecur*1e6)
|
||||||
|
Itar = self.cal.QuadrupoleKL2I(magbg[i],strength,etar*1e6)
|
||||||
|
elif 'MSEX' in mag:
|
||||||
|
pv = PV('%s:I-SET' % mag)
|
||||||
|
valmag = pv.value
|
||||||
|
strength = self.cal.SextupoleI2KL(magbg[i],valmag,ecur*1e6)
|
||||||
|
Itar = self.cal.SextupoleKL2I(magbg[i],strength,etar*1e6)
|
||||||
|
elif 'MBND' in mag:
|
||||||
|
pv = PV('%s:P-SET' % mag)
|
||||||
|
valmag=pv.value
|
||||||
|
strength = pv.value
|
||||||
|
Itar = valmag-EProfCur[-1]+etar
|
||||||
|
else:
|
||||||
|
strength = 0
|
||||||
|
if not Itar is None:
|
||||||
|
if self.debug:
|
||||||
|
self.signal.emit('DEBUG: Setting %s to %f' % (pv.pvname,Itar))
|
||||||
|
else:
|
||||||
|
pv.value = Itar
|
||||||
|
|
||||||
|
def cycleCorrector(self,QuadList=[],progress=None,done = None):
|
||||||
|
self.progress = progress
|
||||||
|
self.done = done # signal to indicate end of thread
|
||||||
|
self.pvcor = [PV(ele.replace('MQUA','MCRX')) for ele in QuadList]+[PV(ele.replace('MQUA','MCRY')) for ele in QuadList]
|
||||||
|
self.abort = False
|
||||||
|
Thread(name='CycleCor',target=self.TcycleCorrector).start() # starting thread which starts and monitors actual thread
|
||||||
|
|
||||||
|
def TcycleCorrector(self):
|
||||||
|
self.running = True
|
||||||
|
istep = 0
|
||||||
|
nstep = len(self.currents)
|
||||||
|
while self.running:
|
||||||
|
if self.progress:
|
||||||
|
self.progress.emit(istep,nstep)
|
||||||
|
if self.signal:
|
||||||
|
self.signal.emit('Setting corrector current to %5.1f A' % self.currents[istep])
|
||||||
|
if self.debug:
|
||||||
|
print('DEBUG: Setting Corrector Magnets to:',self.currents[istep])
|
||||||
|
else:
|
||||||
|
for pv in self.pvcor:
|
||||||
|
pv.value = cyclingCurrents[istep]
|
||||||
|
sleep(self.cyclingPause)
|
||||||
|
istep+=1
|
||||||
|
if istep == nstep or self.abort:
|
||||||
|
self.running = False
|
||||||
|
if self.progress:
|
||||||
|
self.progress.emit(nstep,nstep)
|
||||||
|
if self.done:
|
||||||
|
self.done.emit(not self.abort)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def cycleMagnets(self,maglist, progress = None, done = None):
|
||||||
|
if len(maglist) == 0:
|
||||||
|
done.emit(True)
|
||||||
|
return -1
|
||||||
|
self.progress = progress
|
||||||
|
self.done = done # signal to indicate end of thread
|
||||||
|
state = caget_many(['%s:CYCLE-STATE' % mag for mag in maglist])
|
||||||
|
magcyc = [mag for i,mag in enumerate(maglist) if not state[i] == 2]
|
||||||
|
time = caget_many(['%s:CYCLE-PROGFULL' % mag for mag in magcyc])
|
||||||
|
if len(time) == 0:
|
||||||
|
done.emit(True)
|
||||||
|
return -1 # no cycling needed
|
||||||
|
imax = np.argmax(time)
|
||||||
|
self.tcyc = time[imax]
|
||||||
|
print('Cycling Time:',self.tcyc,'sec for magnet',magcyc[imax])
|
||||||
|
if self.debug:
|
||||||
|
print('DEBUG: Cycle-SET magnets')
|
||||||
|
else:
|
||||||
|
caput_many(['%s:CYCLE' % mag for mag in magcyc],[2]*len(magcyc))
|
||||||
|
self.abort = False
|
||||||
|
Thread(name='CycleMag',target=self.TcycleMagnets).start()
|
||||||
|
return self.tcyc
|
||||||
|
|
||||||
|
def TcycleMagnets(self):
|
||||||
|
self.running = True
|
||||||
|
tcur = 0
|
||||||
|
while self.running:
|
||||||
|
sleep(1)
|
||||||
|
tcur += 1
|
||||||
|
if self.progress:
|
||||||
|
self.progress.emit(tcur,self.tcyc)
|
||||||
|
if tcur >= self.tcyc or self.abort:
|
||||||
|
self.running = False
|
||||||
|
if self.progress:
|
||||||
|
self.progress.emit(self.tcyc,self.tcyc)
|
||||||
|
if self.done:
|
||||||
|
self.done.emit(not self.abort)
|
112
interface/reprate.py
Normal file
112
interface/reprate.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
from time import sleep
|
||||||
|
from epics import PV
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class RepRate:
|
||||||
|
def __init__(self, beamline = 'ARAMIS',debug=False):
|
||||||
|
self.beamline = beamline
|
||||||
|
self.debug=debug
|
||||||
|
self.pv={}
|
||||||
|
self.pv['BeamDelayAR'] = PV('SIN-TIMAST-TMA:Bunch-1-OnDelay-Sel')
|
||||||
|
self.pv['BeamDelayAT'] = PV('SIN-TIMAST-TMA:Bunch-2-OnDelay-Sel')
|
||||||
|
self.pv['RFDelay'] = PV('SIN-TIMAST-TMA:Beam-RF-OnDelay-Sel')
|
||||||
|
self.pv['StopperAR'] = PV('SARMA02-MBNP100:REQUEST')
|
||||||
|
self.pv['StopperAT'] = PV('SATMA01-MBNP100:REQUEST')
|
||||||
|
self.pv['StopperAROut'] = PV('SARMA02-MBNP100:PLC_MOV_OUT')
|
||||||
|
self.pv['StopperATOut'] = PV('SATMA01-MBNP100:PLC_NOV_OUT')
|
||||||
|
self.pv['BeamRRAR'] = PV('SIN-TIMAST-TMA:Bunch-1-Freq-Sel')
|
||||||
|
self.pv['BeamRRAT'] = PV('SIN-TIMAST-TMA:Bunch-2-Freq-Sel')
|
||||||
|
self.pv['applyTiming'] = PV('SIN-TIMAST-TMA:Beam-Apply-Cmd.PROC')
|
||||||
|
self.rrReal = np.array([100., 50., 33.3, 25., 16.6, 12.5, 10., 8.3, 5., 2.5, 1.])
|
||||||
|
self.rrId = np.arange(0, 11)
|
||||||
|
|
||||||
|
|
||||||
|
def setStopper(self,doinsert):
|
||||||
|
if self.beamline == 'ARAMIS':
|
||||||
|
pv = self.pv['StopperAR']
|
||||||
|
else:
|
||||||
|
pv = self.pv['StopperAT']
|
||||||
|
if self.debug:
|
||||||
|
print('DEBUG: Setting beam stopper to:',doinsert)
|
||||||
|
return
|
||||||
|
if doinsert:
|
||||||
|
pv.value = 1
|
||||||
|
else:
|
||||||
|
pv.value = 0
|
||||||
|
|
||||||
|
def isStopperOpen(self):
|
||||||
|
if self.beamline == 'ARAMIS':
|
||||||
|
return self.pv['StopperAROut']
|
||||||
|
else:
|
||||||
|
return self.pv['StopperATOut']
|
||||||
|
|
||||||
|
|
||||||
|
def stopSF(self):
|
||||||
|
if self.debug:
|
||||||
|
print('DEBUG: Stopping Machine disabled')
|
||||||
|
return
|
||||||
|
if self.beamline == 'ARAMIS':
|
||||||
|
self.pv['BeamDelayAR'].value = 1
|
||||||
|
self.pv['BeamDelayAT'].value = 1
|
||||||
|
sleep(0.1)
|
||||||
|
self.pv['RFDelay'].value =1
|
||||||
|
sleep(0.1)
|
||||||
|
self.pv['applyTiming'].value = 1
|
||||||
|
|
||||||
|
def getRR(self):
|
||||||
|
if self.beamline == 'ARAMIS':
|
||||||
|
return self.rrReal[self.pv['BeamRRAR'].value]
|
||||||
|
else:
|
||||||
|
return self.rrReal[self.pv['BeamRRAT'].value]
|
||||||
|
|
||||||
|
|
||||||
|
def setRR(self,rr=1.):
|
||||||
|
"""
|
||||||
|
Possible RR as of 14/01/2020
|
||||||
|
0 100.00 Hz
|
||||||
|
1 50.00 Hz
|
||||||
|
2 33.33 Hz
|
||||||
|
3 25.00 Hz
|
||||||
|
4 16.66 Hz
|
||||||
|
5 12.50 Hz
|
||||||
|
6 10.00 Hz
|
||||||
|
7 8.33 Hz
|
||||||
|
8 5.00 Hz
|
||||||
|
9 2.50 Hz
|
||||||
|
10 1.00 Hz
|
||||||
|
11 Bunch Off
|
||||||
|
"""
|
||||||
|
|
||||||
|
findRR = abs(self.rrReal - rr) < 0.1
|
||||||
|
if findRR.sum(): # at least one rr is matching
|
||||||
|
rrSel = self.rrId[np.argmax(findRR)]
|
||||||
|
else:
|
||||||
|
print('Requested rep. rate %.3f is not available' % rr)
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.debug:
|
||||||
|
print('DEBUG: Setting beam rate to %d (%f Hz)' % (rrSel,rr))
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
if self.beamline == 'ARAMIS':
|
||||||
|
self.pv['BeamRRAR'].value = rrSel
|
||||||
|
sleep(0.1)
|
||||||
|
self.pv['BeamDelayAR'].value = 0 # 0 on beam, 1 on delay
|
||||||
|
rrAT = self.pv['BeamRRAT'].value
|
||||||
|
if rrAT < rrSel: # reduce athos at least to same rep rate as Aramis
|
||||||
|
self.pv['BeamRRAT'].value = rrSel
|
||||||
|
sleep(0.1)
|
||||||
|
self.pv['BeamDelayAT'].value = 0 # 0 on beam, 1 on delay
|
||||||
|
else:
|
||||||
|
self.pv['BeamRRAT'].value = rrSel
|
||||||
|
sleep(0.1)
|
||||||
|
self.pv['BeamDelayAT'].value = 0 # 0 on beam, 1 on delay
|
||||||
|
|
||||||
|
sleep(0.1)
|
||||||
|
if rrSel == 11:
|
||||||
|
self.pv['RFDelay'].value =1
|
||||||
|
else:
|
||||||
|
self.pv['RFDelay'].value = 0
|
||||||
|
sleep(0.1)
|
||||||
|
self.pv['applyTiming'].value = 1
|
60
interface/rf.py
Normal file
60
interface/rf.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
from epics import PV,caput_many
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class RF:
|
||||||
|
def __init__(self, beamline = 'ARAMIS',debug=False, signal = None):
|
||||||
|
self.beamline = beamline
|
||||||
|
self.debug=debug
|
||||||
|
self.signal = signal
|
||||||
|
if self.beamline == 'ARAMIS':
|
||||||
|
self.stations = ['S30CB%2.2d' % d for d in range(1,14)]
|
||||||
|
self.RFamp = [PV('%s-RSYS:SET-ACC-VOLT' % station) for station in self.stations]
|
||||||
|
self.RFphs = [PV('%s-RSYS:SET-BEAM-PHASE' % station) for station in self.stations]
|
||||||
|
self.RFon = [PV('%s-RSYS:REQUIRED-OP' % station) for station in self.stations]
|
||||||
|
self.ErgRange = [PV('SATSY01-MBND200:P-SET'),PV('SARCL02-MBND100:P-SET')]
|
||||||
|
self.EGain = PV('S30:SET-E-GAIN-OP')
|
||||||
|
self.EPhase= PV('S30:SET-BEAM-PHASE-OP')
|
||||||
|
self.Ns = 13
|
||||||
|
else:
|
||||||
|
self.EGain = ['S20:SET-E-GAIN-OP']
|
||||||
|
self.Ns = 0
|
||||||
|
|
||||||
|
def energyProfile(self):
|
||||||
|
if self.Ns == 0:
|
||||||
|
return np.array([0,0])
|
||||||
|
valAmp = [pv.value for pv in self.RFamp]
|
||||||
|
valPhs = [pv.value for pv in self.RFphs]
|
||||||
|
valOn = [pv.value for pv in self.RFon]
|
||||||
|
valErg = [pv.value for pv in self.ErgRange]
|
||||||
|
|
||||||
|
prof = np.zeros((self.Ns+1))
|
||||||
|
prof[0] = valErg[0]
|
||||||
|
for i in range(self.Ns):
|
||||||
|
dE = 0
|
||||||
|
if valOn[i] == 1:
|
||||||
|
dE = valAmp[i]*np.sin(np.pi*valPhs[i]/180.)
|
||||||
|
prof[i+1] = prof[i]+dE
|
||||||
|
prof = np.array(prof)
|
||||||
|
Egain = prof - prof[0]
|
||||||
|
scl = (valErg[1]-valErg[0])/np.max(Egain)
|
||||||
|
prof = Egain*scl+valErg[0]
|
||||||
|
return prof
|
||||||
|
|
||||||
|
def changeEnergyGain(self,dE):
|
||||||
|
if self.debug:
|
||||||
|
print('DEBUG: Changing energy gain of linac by:',dE)
|
||||||
|
return
|
||||||
|
self.EGain.value = dE
|
||||||
|
if dE > 0:
|
||||||
|
self.EPhase.value = 90.
|
||||||
|
else:
|
||||||
|
self.EPhase.value = -90.
|
||||||
|
|
||||||
|
def setRF(self,chns,vals):
|
||||||
|
if self.debug:
|
||||||
|
for i,ele in enumerate(chns):
|
||||||
|
print('DEBUG: RF-Settings %s: %f' % (ele,vals[i]))
|
||||||
|
return
|
||||||
|
caput_many(chns,vals)
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@ def getDatasetFileName(program='Unknown'):
|
|||||||
path = '%s/%s' % (path,day)
|
path = '%s/%s' % (path,day)
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
datetag = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S_%f')
|
datetag = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||||
filename=('%s/%s_%s' % (path, program.replace(' ','_'), datetag))
|
filename=('%s/%s_%s' % (path, program.replace(' ','_'), datetag))
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
@ -31,19 +31,19 @@ def saveDataset(program,data,actuator=None,snap=None,analysis=None,figures=None)
|
|||||||
# check if scan is multiple instances of a scan
|
# check if scan is multiple instances of a scan
|
||||||
if isinstance(data,list):
|
if isinstance(data,list):
|
||||||
for iscan,singledata in enumerate(data):
|
for iscan,singledata in enumerate(data):
|
||||||
writeData(hid,singledata,iscan)
|
writeData(hid,singledata,iscan+1)
|
||||||
else:
|
else:
|
||||||
writeData(hid,data,1)
|
writeData(hid,data,1)
|
||||||
# same for actuator
|
# same for actuator
|
||||||
if isinstance(actuator,list):
|
if isinstance(actuator,list):
|
||||||
for iscan,singleactuator in enumerate(actuator):
|
for iscan,singleactuator in enumerate(actuator):
|
||||||
writeActuator(hid,singleactuator,iscan)
|
writeActuator(hid,singleactuator,iscan+1)
|
||||||
else:
|
else:
|
||||||
writeActuator(hid,actuator,1)
|
writeActuator(hid,actuator,1)
|
||||||
# and same for analysis
|
# and same for analysis
|
||||||
if isinstance(analysis,list):
|
if isinstance(analysis,list):
|
||||||
for iscan,singleana in enumerate(analysis):
|
for iscan,singleana in enumerate(analysis):
|
||||||
writeAnalysis(hid,singleana,iscan)
|
writeAnalysis(hid,singleana,iscan+1)
|
||||||
else:
|
else:
|
||||||
writeAnalysis(hid,analysis,1)
|
writeAnalysis(hid,analysis,1)
|
||||||
# write aux data
|
# write aux data
|
||||||
@ -94,9 +94,13 @@ def writeData(hid, data, scanrun=1):
|
|||||||
dset.attrs['system'] = getDatasetSystem(name[0])
|
dset.attrs['system'] = getDatasetSystem(name[0])
|
||||||
dset.attrs['units'] = 'unknown'
|
dset.attrs['units'] = 'unknown'
|
||||||
# this part is obsolete - dimension should be given from the individual datasets
|
# this part is obsolete - dimension should be given from the individual datasets
|
||||||
if not 'pid' in data.keys():
|
shape = None
|
||||||
return
|
if 'pid' in data.keys():
|
||||||
shape = data['pid'].shape
|
shape = data['pid'].shape
|
||||||
|
if 'pulse_id' in data.keys():
|
||||||
|
shape = data['pulse_id'].shape
|
||||||
|
if shape is None:
|
||||||
|
return
|
||||||
ndim = len(shape)
|
ndim = len(shape)
|
||||||
nsam = shape[-1]
|
nsam = shape[-1]
|
||||||
nrec = 0
|
nrec = 0
|
||||||
|
@ -61,6 +61,26 @@ def getSnap(pvs=None):
|
|||||||
ret[pv]=float(val[i])
|
ret[pv]=float(val[i])
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def getSnapPV(pvs=None):
|
||||||
|
if not isinstance(pvs,list):
|
||||||
|
pvs = parseSnapShotReqYAML(pvs)
|
||||||
|
if not pvs:
|
||||||
|
return
|
||||||
|
return [epics.PV(pvname,auto_monitor = False) for pvname in pvs]
|
||||||
|
|
||||||
|
|
||||||
|
def getSnapVal(pvs=None):
|
||||||
|
if not pvs:
|
||||||
|
return None
|
||||||
|
ret={}
|
||||||
|
val = [pv.get(timeout=0.1) for pv in pvs]
|
||||||
|
for i,pv in enumerate(pvs):
|
||||||
|
if not val[i] is None: # filter out None values
|
||||||
|
ret[pv.pvname]=float(val[i])
|
||||||
|
else:
|
||||||
|
print('Timeout:',pv.pvname)
|
||||||
|
return ret
|
||||||
|
|
||||||
def saveSnap(pvs={},label="", comment = "generated by application",reqfile = "SF_settings.yaml"):
|
def saveSnap(pvs={},label="", comment = "generated by application",reqfile = "SF_settings.yaml"):
|
||||||
filename = datetime.datetime.now().strftime('/sf/data/applications/snapshot/SF_settings_%Y%m%d_%H%M%S.snap')
|
filename = datetime.datetime.now().strftime('/sf/data/applications/snapshot/SF_settings_%Y%m%d_%H%M%S.snap')
|
||||||
with open(filename,'w') as fid:
|
with open(filename,'w') as fid:
|
||||||
@ -85,7 +105,7 @@ def loadSnap(filename):
|
|||||||
if '.' in val:
|
if '.' in val:
|
||||||
res[pv]=float(val)
|
res[pv]=float(val)
|
||||||
else:
|
else:
|
||||||
res[pv]= val
|
res[pv]= val # might be string!!!!
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
38
util/simplecapture.py
Normal file
38
util/simplecapture.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from bstrd import BSCache
|
||||||
|
|
||||||
|
class SimpleCapture:
|
||||||
|
def __init__(self):
|
||||||
|
self.chn=None
|
||||||
|
self.bs = BSCache(100000, receive_timeout=100000) # 1000 second time out, capazity for 1000 second.
|
||||||
|
self.abort=False
|
||||||
|
|
||||||
|
def terminate(self):
|
||||||
|
self.bs.stop()
|
||||||
|
self.bs.pt.running.clear()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.abort=True
|
||||||
|
|
||||||
|
def initChannels(self,channels):
|
||||||
|
self.chn=channels
|
||||||
|
self.bs.get_vars(channels)
|
||||||
|
|
||||||
|
def acquire(self,N=1,reprate=-1,stop=False):
|
||||||
|
self.abort=False
|
||||||
|
data = np.zeros((N,len(self.chn)))
|
||||||
|
pid = np.zeros((N))
|
||||||
|
self.bs.flush()
|
||||||
|
idx = 0
|
||||||
|
while idx<N and not self.abort:
|
||||||
|
rec=self.bs.__next__()
|
||||||
|
pid[idx] = rec['pid']
|
||||||
|
data[idx,:] = np.array([rec[ch] for ch in self.chn])
|
||||||
|
idx += 1
|
||||||
|
ret={}
|
||||||
|
for i,ch in enumerate(self.chn):
|
||||||
|
ret[ch]=data[:,i]
|
||||||
|
ret['pid'] = pid
|
||||||
|
|
||||||
|
return ret
|
Reference in New Issue
Block a user