Improved snapshot interface with saving snapshot files in the OP configuration. Added app support for stabilizing XTCAV. Added a BSacquisition based on BSCache

This commit is contained in:
2023-07-05 09:16:18 +02:00
parent a54abd383e
commit 0c928a8bb1
7 changed files with 79 additions and 11 deletions

View File

@ -2,3 +2,4 @@ from .adaptiveorbit import AdaptiveOrbit
from .spectralanalysis import SpectralAnalysis from .spectralanalysis import SpectralAnalysis
from .hero import LaserPower,EnergyModulation from .hero import LaserPower,EnergyModulation
from .dispersiontools import Dispersion from .dispersiontools import Dispersion
from .xtcavstabilizer import XTCAVStabilizer

View File

@ -9,6 +9,7 @@ from slic.core.adjustable import PVAdjustable
from slic.core.acquisition import BSAcquisition, PVAcquisition from slic.core.acquisition import BSAcquisition, PVAcquisition
from slic.core.scanner import Scanner from slic.core.scanner import Scanner
from sfbd.ext import CounterAdjustable from sfbd.ext import CounterAdjustable
from sfbd.ext import BSCAcquisition
def getAux(pvs=None): def getAux(pvs=None):
if not pvs: if not pvs:
@ -95,7 +96,7 @@ class Dispersion:
sensor1 = getBSChannels('SATBD02-DBPM.*:Y2$') sensor1 = getBSChannels('SATBD02-DBPM.*:Y2$')
sensor2 = getBSChannels('SATCB.*-RLLE-DSP:.*-VS$') sensor2 = getBSChannels('SATCB.*-RLLE-DSP:.*-VS$')
self.sensor = sensor1+sensor2 self.sensor = sensor1+sensor2
self.acq = [BSAcquisition(".",pgroup, default_channels=self.sensor)] self.acq = [BSCAcquisition(".",pgroup, default_channels=self.sensor)]
# auxiliar data to be read one # auxiliar data to be read one
self.aux = self.getRFCalibrationChannels(sensor2,'SATCL01-MBND100:ENERGY-OP') self.aux = self.getRFCalibrationChannels(sensor2,'SATCL01-MBND100:ENERGY-OP')
@ -159,7 +160,7 @@ class Dispersion:
def setup(self,scl = 1, Nsteps=5, Nsamples=5): def setup(self,scl = 1, Nsteps=5, Nsamples=5):
val = self.adj.get_current_value(readback=False) val = self.adj.get_current_value(readback=False)
dval = self.amp*scl dval = self.amp*scl
dval = 0 dval = 0 ######## edit this
self.N = Nsteps self.N = Nsteps
self.Ns= Nsamples self.Ns= Nsamples
self.values=np.linspace(val-dval,val+dval,num=self.N) self.values=np.linspace(val-dval,val+dval,num=self.N)
@ -179,10 +180,10 @@ class Dispersion:
self.sc=self.scanner.ascan_list(self.adj,self.values, self.sc=self.scanner.ascan_list(self.adj,self.values,
filename=self.branch,start_immediately = False, filename=self.branch,start_immediately = False,
n_pulses=self.Ns,return_to_initial_values=True) n_pulses=self.Ns,return_to_initial_values=True)
self.preaction() # self.preaction() ######
self.sc.run() self.sc.run()
self.auxdata = getAux(self.aux) self.auxdata = getAux(self.aux)
self.postaction() # self.postaction() #######
def stop(self): def stop(self):

View File

@ -2,18 +2,29 @@ import time
import numpy as np import numpy as np
from bstrd import BSCache from bstrd import BSCache
from epics import PV
class XTCAVStabilizer: class XTCAVStabilizer:
""" """
Wrapper class to bundle all daq/io needed for stabilizing the XTCAV Wrapper class to bundle all daq/io needed for stabilizing the XTCAV
""" """
def __init__(self): def __init__(self):
# the PV
self.PVTCAV = PV('SATMA02-RMSM:SM-GET',connection_timeout=0.9, callback=self.stateChanged)
self.state=self.PVTCAV.value == 9
# the BS channels
self.bs = BSCache(100000,10000) # 100 second timeout, size for 100 second data taken self.bs = BSCache(100000,10000) # 100 second timeout, size for 100 second data taken
self.channels = ['SATBD02-DBPM040:X2','SATMA02-RLLE-DSP:PHASE-VS'] self.channels = ['SATBD02-DBPM040:X2','SATMA02-RLLE-DSP:PHASE-VS','SATBD02-DBPM040:X2-VALID']
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
self.bs.stop() self.bs.stop()
def stateChanged(self,pvname=None, value=0, **kws):
self.state = value == 9
def terminate(self): def terminate(self):
print('Stopping BSStream Thread...') print('Stopping BSStream Thread...')
self.bs.stop() self.bs.stop()
@ -23,7 +34,7 @@ class XTCAVStabilizer:
self.bs.flush() self.bs.flush()
def read(self): def read(self):
data=self.bs.__next__() return self.bs.__next__()
return data['pid'],data[self.channels[0]],data[self.channels[1]] # returns PID, BPM reading, TCAV Phase

View File

@ -1,3 +1,4 @@
from .magnet import Magnet from .magnet import Magnet
from .camacquisition import CamAcquisition from .camacquisition import CamAcquisition
from .counteradjustable import CounterAdjustable from .counteradjustable import CounterAdjustable
from .bscacquisition import BSCAcquisition

42
ext/bscacquisition.py Normal file
View File

@ -0,0 +1,42 @@
import zmq
import h5py
from bstrd import BSCache
from slic.core.acquisition.acquisition import Acquisition
from slic.core.acquisition import BSAcquisition, PVAcquisition
# class using the BSQueue to avoid to reestablish a stream for each step.
class BSCAcquisition(Acquisition):
def release(self):
if not self.queue == None:
del self.queue
self.queue = None
def _acquire(self, filename, channels=None, data_base_dir=None, scan_info=None, n_pulses=100, **kwargs):
if not hasattr(self,'queue'):
self.queue = getStream(channels)
elif not self.queue:
self.queue = getStream(channels)
self.queue.flush()
print('Acquiring',n_pulses,'samples')
data = []
for i in range(n_pulses):
data.append(self.queue.__next__())
hid = h5py.File(filename,'w')
gid = hid.create_group(channels[0])
for key in data[0].keys():
gid.create_dataset(key, data = [rec[key].value for rec in data])
hid.close()
def getStream(channels):
print('Generating stream with channels:',channels)
bs = BSCache(100000,10000) # 1 second time out, capazity for 100 second.
bs.get_vars(channels)
return bs

View File

@ -1,4 +1,5 @@
from .snap import getSnap from .snap import getSnap
from .snap import saveSnap
from .save import saveDataset from .save import saveDataset
from .load import loadDataset from .load import loadDataset
from .elog import writeElog from .elog import writeElog

View File

@ -1,13 +1,12 @@
import numpy as np import numpy as np
import yaml import yaml
import os import os
import datetime
import epics import epics
# things to do: # things to do:
# 1. Read a snapshot file (not request file) # 1. Read a snapshot file (not request file)
# 2. Save a snapshot file # 2. add parameters and performance channels (e.g. AT photon energies)
# 3. add parameters and performance channels (e.g. AT photon energies)
def parseSnapShotReqYAML(filename): def parseSnapShotReqYAML(filename):
# read the snapshot request file # read the snapshot request file
@ -63,6 +62,18 @@ def getSnap(pvs=None):
epics.ca.clear_cache() epics.ca.clear_cache()
return ret return ret
def saveSnap(pvs={},label="", comment = "generated by application"):
filename = datetime.datetime.now().strftime('/sf/data/applications/snapshot/SF_settings_%Y%m%d_%H%M%S.snap')
with open(filename,'w') as fid:
fid.write('#{"labels":["%s"],"comment":"%s", "machine_parms":{}, "save_time": 0.0, "req_file_name": "SF_settings.yaml"}\n' % (label,comment))
for key in pvs.keys():
if isinstance(pvs[key],int):
fid.write('%s,{"val": %d}\n' % (key,pvs[key]))
elif isinstance(pvs[key],float):
fid.write('%s,{"val": %f}\n' % (key,pvs[key]))
elif isinstance(pvs[key],str):
fid.write('%s,{"val": %s}\n' % (key,pvs[key]))