Support for various app and slic wrapper
This commit is contained in:
@ -1,2 +1,4 @@
|
|||||||
from .adaptiveorbit import AdaptiveOrbit
|
from .adaptiveorbit import AdaptiveOrbit
|
||||||
from .spectralanalysis import SpectralAnalysis
|
from .spectralanalysis import SpectralAnalysis
|
||||||
|
from .hero import LaserPower,EnergyModulation
|
||||||
|
from .dispersiontools import Dispersion
|
||||||
|
@ -39,7 +39,7 @@ class AdaptiveOrbit:
|
|||||||
|
|
||||||
def initBSStream(self,channels):
|
def initBSStream(self,channels):
|
||||||
print("Initializing BSstream")
|
print("Initializing BSstream")
|
||||||
bs = BSCache()
|
bs = BSCache(100000,10000) # 1 second time out, capazity for 100 second.
|
||||||
bs.stop()
|
bs.stop()
|
||||||
for cnl in channels[1:]:
|
for cnl in channels[1:]:
|
||||||
if not is_available(cnl):
|
if not is_available(cnl):
|
||||||
@ -63,10 +63,8 @@ class AdaptiveOrbit:
|
|||||||
return pvs
|
return pvs
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
with self.bsAR.pt.queue.mutex:
|
self.bsAR.flush()
|
||||||
self.bsAR.pt.queue.queue.clear()
|
self.bsAT.flush()
|
||||||
with self.bsAT.pt.queue.mutex:
|
|
||||||
self.bsAT.pt.queue.queue.clear()
|
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
print('Stopping BSStream Thread...')
|
print('Stopping BSStream Thread...')
|
||||||
|
175
app/dispersiontools.py
Normal file
175
app/dispersiontools.py
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
import datetime
|
||||||
|
import re
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from bsread import dispatcher
|
||||||
|
import epics
|
||||||
|
|
||||||
|
from slic.core.adjustable import PVAdjustable
|
||||||
|
from slic.core.acquisition import BSAcquisition
|
||||||
|
from slic.core.scanner import Scanner
|
||||||
|
|
||||||
|
|
||||||
|
def getAux(pvs=None):
|
||||||
|
if not pvs:
|
||||||
|
return
|
||||||
|
ret={}
|
||||||
|
val = epics.caget_many(pvs)
|
||||||
|
for i,pv in enumerate(pvs):
|
||||||
|
if val[i]: # filter out None values
|
||||||
|
ret[pv]=float(val[i])
|
||||||
|
epics.ca.clear_cache()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def getBSChannels(regexp):
|
||||||
|
prog = re.compile(regexp)
|
||||||
|
res = []
|
||||||
|
for bs in dispatcher.get_current_channels():
|
||||||
|
if prog.match(bs['name']):
|
||||||
|
res.append(bs['name'])
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
class Dispersion:
|
||||||
|
def __init__(self, branch = 'Aramis'):
|
||||||
|
self.scanname = 'Dispersion'
|
||||||
|
self.branch = 'None'
|
||||||
|
dirpath= datetime.datetime.now().strftime('/sf/data/measurements/%Y/%m/%d/slic_sfbd')
|
||||||
|
self.scandir='%s/%s' % (dirpath,self.scanname)
|
||||||
|
|
||||||
|
self.setBranch()
|
||||||
|
self.sc = None
|
||||||
|
self.Nsteps = 2
|
||||||
|
self.Nsamples = 1
|
||||||
|
|
||||||
|
|
||||||
|
def setBranch(self,branch = 'Aramis'):
|
||||||
|
if branch == 'Athos Dump':
|
||||||
|
self.setupAthosDump()
|
||||||
|
elif branch == 'Aramis':
|
||||||
|
self.setupAramis()
|
||||||
|
else:
|
||||||
|
self.branch = 'None'
|
||||||
|
|
||||||
|
|
||||||
|
def setupAramis(self):
|
||||||
|
# pre-scan item
|
||||||
|
self.pre = {}
|
||||||
|
self.pre['SFB_BEAM_DUMP_AR:ONOFF1']={'Val':0,'InitVal':0}
|
||||||
|
self.pre['SFB_BEAM_ENERGY_ECOL_AR:ONOFF1']={'Val':0,'InitVal':0}
|
||||||
|
self.pre['SFB_ORBIT_S30:ONOFF1']={'Val':0,'InitVal':0}
|
||||||
|
self.pre['SFB_ORBIT_SAR:ONOFF1']={'Val':0,'InitVal':0}
|
||||||
|
for pv in self.pre.keys():
|
||||||
|
self.pre[pv]['adj']=PVAdjustable(pv)
|
||||||
|
# adjustable
|
||||||
|
self.adjSV = 'S30:SET-E-GAIN-OP'
|
||||||
|
self.adjRB = 'S30:GET-E-GAIN-OP'
|
||||||
|
self.adj = PVAdjustable(self.adjSV,pvname_readback = self.adjRB, accuracy = 0.1)
|
||||||
|
self.amp = 20 # the amplitude of the scan, which can be scaled
|
||||||
|
# acquisition
|
||||||
|
sensor1 = getBSChannels('SAR.*DBPM.*:[XY]1$')
|
||||||
|
sensor2 = getBSChannels('S[23].*-RLLE-DSP:.*-VS$')
|
||||||
|
self.sensor = sensor1+sensor2
|
||||||
|
self.acq = [BSAcquisition("machine","sfbd", default_channels=self.sensor)]
|
||||||
|
# auxiliar data to be read one
|
||||||
|
self.aux=[]
|
||||||
|
for sen in sensor2:
|
||||||
|
if 'PHASE-VS' in sen:
|
||||||
|
self.aux.append(sen.replace('PHASE-VS','GET-VSUM-PHASE-OFFSET').replace('RLLE-DSP','RSYS'))
|
||||||
|
self.aux.append(sen.replace('PHASE-VS','GET-VSUM-AMPLT-SCALE').replace('RLLE-DSP','RSYS'))
|
||||||
|
self.aux.append(sen.replace('PHASE-VS','SM-SET').replace('RLLE-DSP','RMSM'))
|
||||||
|
self.aux.append('S10BC02-MBND100:ENERGY-OP')
|
||||||
|
|
||||||
|
# scanner
|
||||||
|
self.branch='Aramis'
|
||||||
|
self.path = '%s-%s' % (self.scanname,self.branch)
|
||||||
|
self.scanner = Scanner(data_base_dir=self.path,scan_info_dir=self.path,
|
||||||
|
make_scan_sub_dir=True,
|
||||||
|
default_acquisitions=self.acq)
|
||||||
|
|
||||||
|
def setupAthosDump(self):
|
||||||
|
# pre-scan item
|
||||||
|
self.pre = {}
|
||||||
|
self.pre['SFB_BEAM_DUMP_AT:ONOFF1']={'Val':0,'InitVal':0}
|
||||||
|
self.pre['SFB_ORBIT_SAT:ONOFF1']={'Val':0,'InitVal':0}
|
||||||
|
for i in range(1,5):
|
||||||
|
self.pre['SFB_ORBIT_SAT_%2.2d:ONOFF1' % i ]={'Val':0,'InitVal':0}
|
||||||
|
for pv in self.pre.keys():
|
||||||
|
self.pre[pv]['adj']=PVAdjustable(pv)
|
||||||
|
# adjustable
|
||||||
|
self.adjSV = 'SATCB01-RSYS:SET-BEAM-PHASE'
|
||||||
|
self.adjRB = 'SATCB01-RSYS:GET-BEAM-PHASE'
|
||||||
|
self.adj = PVAdjustable(self.adjSV,pvname_readback = self.adjRB, accuracy = 0.1)
|
||||||
|
self.amp = 20 # the amplitude of the scan, which can be scaled
|
||||||
|
# acquisition
|
||||||
|
self.sensor = ['SATBD02-DBPM010:Y2','SATBD02-DBPM040:Y2']
|
||||||
|
self.acq = [BSAcquisition("machine","sfbd", default_channels=self.sensor)]
|
||||||
|
# auxiliar data to be read one
|
||||||
|
aux = ['SATCL01-MBND100:ENERGY-OP']
|
||||||
|
# scanner
|
||||||
|
self.branch='Athos_Dump'
|
||||||
|
self.path = '%s-%s' % (self.scanname,self.branch)
|
||||||
|
self.scanner = Scanner(data_base_dir=self.path,scan_info_dir=self.path,
|
||||||
|
make_scan_sub_dir=True,
|
||||||
|
default_acquisitions=self.acq)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def setup(self,scl = 1, Nsteps=5, Nsamples=5):
|
||||||
|
val = self.adj.get_current_value(readback=False)
|
||||||
|
dval = self.amp*scl
|
||||||
|
self.N = Nsteps
|
||||||
|
self.Ns= Nsamples
|
||||||
|
self.values=np.linspace(val-dval,val+dval,num=self.N)
|
||||||
|
|
||||||
|
|
||||||
|
def preaction(self):
|
||||||
|
for key in self.pre.keys():
|
||||||
|
self.pre[key]['InitVal'] = self.pre[key]['adj'].get_current_value(readback = False)
|
||||||
|
self.pre[key]['adj'].set_target_value(self.pre[key]['Val'])
|
||||||
|
|
||||||
|
def postaction(self):
|
||||||
|
for key in self.pre.keys():
|
||||||
|
self.pre[key]['adj'].set_target_value(self.pre[key]['InitVal'])
|
||||||
|
|
||||||
|
|
||||||
|
def scan(self):
|
||||||
|
self.sc=self.scanner.ascan_list(self.adj,self.values,
|
||||||
|
filename=self.scanname,start_immediately = False,
|
||||||
|
n_pulses=self.Ns,return_to_initial_values=True)
|
||||||
|
self.preaction()
|
||||||
|
self.sc.run()
|
||||||
|
self.auxdata = getAux(self.aux)
|
||||||
|
self.postaction()
|
||||||
|
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self.sc is None:
|
||||||
|
return
|
||||||
|
self.sc.stop()
|
||||||
|
|
||||||
|
def running(self):
|
||||||
|
return self.sc.running
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
si = self.sc.scan_info.to_dict()
|
||||||
|
steps = 0
|
||||||
|
if 'scan_values' in si:
|
||||||
|
steps=len(si['scan_values'])
|
||||||
|
return steps,self.N
|
||||||
|
|
||||||
|
def info(self):
|
||||||
|
return self.sc.scan_info.to_dict()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
111
app/hero.py
Normal file
111
app/hero.py
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import datetime
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from slic.core.acquisition import PVAcquisition
|
||||||
|
from slic.core.acquisition import BSAcquisition
|
||||||
|
from slic.devices.general import motor
|
||||||
|
from slic.core.scanner import Scanner
|
||||||
|
from sfbd.ext import CamAcquisition
|
||||||
|
|
||||||
|
# some temporary wrapper
|
||||||
|
class PollingPVAcquisition(PVAcquisition):
|
||||||
|
def _acquire(self, *args, polling=True, **kwargs):
|
||||||
|
return super()._acquire(*args, polling=polling, **kwargs)
|
||||||
|
|
||||||
|
class LaserScanBase:
|
||||||
|
def __init__(self):
|
||||||
|
print('Init Base Class')
|
||||||
|
self.SV= 'SSL-LMOT-M1104:MOT'
|
||||||
|
self.pol = motor.Motor(self.SV)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self.sc is None:
|
||||||
|
return
|
||||||
|
self.sc.stop()
|
||||||
|
|
||||||
|
def running(self):
|
||||||
|
return self.sc.running
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
si = self.sc.scan_info.to_dict()
|
||||||
|
steps = 0
|
||||||
|
if 'scan_values' in si:
|
||||||
|
steps=len(si['scan_values'])
|
||||||
|
return steps,self.N
|
||||||
|
|
||||||
|
def info(self):
|
||||||
|
return self.sc.scan_info.to_dict()
|
||||||
|
|
||||||
|
def setup(self,amax=21,Nsteps=5,Nsamples=5):
|
||||||
|
amin = 0
|
||||||
|
self.N = Nsteps
|
||||||
|
self.Ns= Nsamples
|
||||||
|
self.values=np.linspace(19,21,num=self.N) # needs a change
|
||||||
|
|
||||||
|
# measuring the pulse energy as a function of the controling PV. Note that the power should be limited to 300 uJ
|
||||||
|
# thus limiting the value of the actuaor defining the lase rpulse energy in the EnergyModulaiton class.
|
||||||
|
|
||||||
|
class LaserPower(LaserScanBase):
|
||||||
|
def __init__(self):
|
||||||
|
super(LaserPower,self).__init__()
|
||||||
|
|
||||||
|
self.scanname = 'HEROLaserEnergy'
|
||||||
|
dirpath= datetime.datetime.now().strftime('/sf/data/measurements/%Y/%m/%d/slic_sfbd')
|
||||||
|
self.scandir='%s/%s' % (dirpath,self.scanname)
|
||||||
|
|
||||||
|
self.RB = 'SSL-LENG-SLNK1:VAL_GET'
|
||||||
|
self.erg = PollingPVAcquisition("machine","sfbd", default_channels=[self.RB])
|
||||||
|
|
||||||
|
self.scanner = Scanner(data_base_dir=self.scandir,scan_info_dir=self.scandir,make_scan_sub_dir=True,
|
||||||
|
default_acquisitions=[self.erg])
|
||||||
|
|
||||||
|
def scan(self):
|
||||||
|
self.sc=self.scanner.ascan_list(self.pol,self.values,
|
||||||
|
filename=self.scanname,start_immediately = False,
|
||||||
|
n_pulses=self.Ns,return_to_initial_values=True)
|
||||||
|
self.sc.run()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# measuring the coherent emission/space charge blow-up as a function of the hero energy modulation
|
||||||
|
|
||||||
|
class EnergyModulation(LaserScanBase):
|
||||||
|
def __init__(self, acq = 0):
|
||||||
|
super(EnergyModulation,self).__init__()
|
||||||
|
self.scanname = 'HEROEnergyModulation'
|
||||||
|
dirpath= datetime.datetime.now().strftime('/sf/data/measurements/%Y/%m/%d/slic_sfbd')
|
||||||
|
self.scandir='%s/%s' % (dirpath,self.scanname)
|
||||||
|
|
||||||
|
self.acq = acq
|
||||||
|
if self.acq == 0:
|
||||||
|
self.RB ='SATFE10-PEPG046-EVR0:CALCI'
|
||||||
|
self.erg = BSAcquisition("machine","sfbd", default_channels=[self.RB])
|
||||||
|
elif self.acq == 1:
|
||||||
|
self.RB ='SATBD02-DBPM040:Y2'
|
||||||
|
self.erg = BSAcquisition("machine","sfbd", default_channels=[self.RB])
|
||||||
|
elif self.acq == 2:
|
||||||
|
self.RB = 'SATBD01-DSCR210'
|
||||||
|
self.erg = CamAcquisition("machine","sfbd", default_channels=[self.RB])
|
||||||
|
self.erg.getConnection(self.RB)
|
||||||
|
else:
|
||||||
|
self.RB = 'SATBD02-DSCR050'
|
||||||
|
self.erg = CamAcquisition("machine","sfbd", default_channels=[self.RB])
|
||||||
|
self.erg.getConnection(self.RB)
|
||||||
|
|
||||||
|
self.scanner = Scanner(data_base_dir=self.scandir,scan_info_dir=self.scandir,make_scan_sub_dir=True,
|
||||||
|
default_acquisitions=[self.erg])
|
||||||
|
|
||||||
|
def scan(self):
|
||||||
|
self.sc=self.scanner.ascan_list(self.pol,self.values,
|
||||||
|
filename=self.scanname,start_immediately = False,
|
||||||
|
n_pulses=self.Ns,return_to_initial_values=True)
|
||||||
|
self.sc.run()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ class SpectralAnalysis:
|
|||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.bs = BSCache()
|
self.bs = BSCache(100000,10000) # 100 second timeout, size for 100 second data taken
|
||||||
self.bs.stop()
|
self.bs.stop()
|
||||||
|
|
||||||
self.channel = ''
|
self.channel = ''
|
||||||
@ -35,8 +35,7 @@ class SpectralAnalysis:
|
|||||||
self.bs.pt.running.clear() # for some reason I have to
|
self.bs.pt.running.clear() # for some reason I have to
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
with self.bs.pt.queue.mutex:
|
self.bs.flush()
|
||||||
self.bs.pt.queue.queue.clear()
|
|
||||||
|
|
||||||
def read(self):
|
def read(self):
|
||||||
data=self.bs.__next__()
|
data=self.bs.__next__()
|
||||||
|
@ -1 +1,3 @@
|
|||||||
from .reichebscombined import ReicheBSCombined
|
from .magnet import Magnet
|
||||||
|
from .camacquisition import CamAcquisition
|
||||||
|
from .counteradjustable import CounterAdjustable
|
||||||
|
41
ext/camacquisition.py
Normal file
41
ext/camacquisition.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
from time import sleep
|
||||||
|
from tqdm import trange
|
||||||
|
import h5py
|
||||||
|
|
||||||
|
from cam_server_client import PipelineClient
|
||||||
|
from cam_server_client.utils import get_host_port_from_stream_address
|
||||||
|
from bsread import source, SUB
|
||||||
|
|
||||||
|
|
||||||
|
from slic.core.acquisition.acquisition import Acquisition
|
||||||
|
class CamAcquisition(Acquisition):
|
||||||
|
|
||||||
|
def getConnection(self,cam):
|
||||||
|
pipeline_client = PipelineClient()
|
||||||
|
cam_instance_name = str(cam) + "_sp1"
|
||||||
|
stream_address = pipeline_client.get_instance_stream(cam_instance_name)
|
||||||
|
self.host, self.port = get_host_port_from_stream_address(stream_address)
|
||||||
|
print(self.host,self.port)
|
||||||
|
|
||||||
|
def _acquire(self, filename, channels=None, data_base_dir=None, scan_info=None, n_pulses=100, **kwargs):
|
||||||
|
print("my routine")
|
||||||
|
print("extra kwargs:", kwargs)
|
||||||
|
args = (filename, n_pulses, channels)
|
||||||
|
args = ", ".join(repr(i) for i in args)
|
||||||
|
print("acquire({})".format(args))
|
||||||
|
print(f"dummy acquire to {filename}:")
|
||||||
|
|
||||||
|
# stream_host,stream_port = getPipeLine(channels[0])
|
||||||
|
# time.wait(1)
|
||||||
|
data= []
|
||||||
|
with source(host=self.host, port=self.port, mode=SUB) as input_stream:
|
||||||
|
input_stream.connect()
|
||||||
|
for i in range(n_pulses):
|
||||||
|
print('Camera Images', i)
|
||||||
|
message = input_stream.receive()
|
||||||
|
data.append(message.data.data)
|
||||||
|
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()
|
23
ext/counteradjustable.py
Normal file
23
ext/counteradjustable.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from slic.core.adjustable import Adjustable
|
||||||
|
|
||||||
|
class CounterAdjustable(Adjustable):
|
||||||
|
def __init__(self, adjustable1, adjustable2):
|
||||||
|
self.adj1=adjustable1
|
||||||
|
self.adj2=adjustable2
|
||||||
|
self.ref_values() # implementation needs reference values to convert absolute scan to relative scan
|
||||||
|
|
||||||
|
def ref_value(self):
|
||||||
|
self.val1 = self.adj1.get_current_value(readback = False)
|
||||||
|
self.val2 = self.adj2.get_current_value(readback = False)
|
||||||
|
|
||||||
|
def set_target_value(self, value):
|
||||||
|
t1 = self.adj1.set_target_value(self.val1 + value)
|
||||||
|
t2 = self.adj2.set_target_value(self.val2 - value)
|
||||||
|
t1.wait()
|
||||||
|
t2.wait()
|
||||||
|
|
||||||
|
def get_current_value(self):
|
||||||
|
return self.adj1.get_current_value()
|
||||||
|
|
||||||
|
def is_moving(self):
|
||||||
|
return any([self.adj1.is_moving(),self.adj2.is_moving()])
|
21
ext/magnet.py
Normal file
21
ext/magnet.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from slic.core.adjustable import PVAdjustable
|
||||||
|
from slic.utils import typename
|
||||||
|
|
||||||
|
class Magnet(PVAdjustable):
|
||||||
|
|
||||||
|
def __init__(self,name):
|
||||||
|
self.name=name
|
||||||
|
pvsv='%s:I-SET' % name
|
||||||
|
pvrb='%s:I-READ' % name
|
||||||
|
tol = 0.075
|
||||||
|
super().__init__(pvsv,pvname_readback=pvrb,accuracy=tol,internal=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def status(self):
|
||||||
|
return "Cycling"
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
tn = typename(self)
|
||||||
|
return f"{tn} \"{self.name}\" is {self.status}"
|
@ -1,12 +0,0 @@
|
|||||||
from slic.core.sensor.bsmonitor import BSMonitor
|
|
||||||
|
|
||||||
class ReicheBSCombined(BSMonitor):
|
|
||||||
|
|
||||||
# Du brauchst kein extra init. BSMonitor tut schon das richtige...
|
|
||||||
|
|
||||||
def _unpack(self, data):
|
|
||||||
# data ist ein dict mit allen Deinen Kanälen
|
|
||||||
pid = data["pid"] # der effektive Channel-Name der Pulse ID
|
|
||||||
# hier dein Code
|
|
||||||
# am Ende sollte eine Zahl rauskommen:
|
|
||||||
return data
|
|
@ -2,3 +2,4 @@ from .snap import getSnap
|
|||||||
from .save import saveDataset
|
from .save import saveDataset
|
||||||
from .load import loadDataset
|
from .load import loadDataset
|
||||||
from .elog import writeElog
|
from .elog import writeElog
|
||||||
|
from .slic import SlicScan
|
||||||
|
@ -50,7 +50,8 @@ def saveDataset(program,data,actuator=None,snap=None,analysis=None,figures=None)
|
|||||||
writeSnap(hid,snap)
|
writeSnap(hid,snap)
|
||||||
hid.close()
|
hid.close()
|
||||||
|
|
||||||
writeFigure(filename,figures)
|
if figures:
|
||||||
|
writeFigure(filename,figures)
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
@ -83,6 +84,16 @@ def openDataset(program):
|
|||||||
|
|
||||||
|
|
||||||
def writeData(hid, data, scanrun=1):
|
def writeData(hid, data, scanrun=1):
|
||||||
|
# write the sensor raw value
|
||||||
|
for ele in data.keys():
|
||||||
|
name=ele.split(':')
|
||||||
|
if len(name)>1:
|
||||||
|
dset=hid.create_dataset('scan_%d/data/%s/%s' % (scanrun, name[0], name[1]), data=data[ele])
|
||||||
|
else:
|
||||||
|
dset=hid.create_dataset('scan_%d/data/%s' % (scanrun, name[0]), data=data[ele])
|
||||||
|
dset.attrs['system'] = getDatasetSystem(name[0])
|
||||||
|
dset.attrs['units'] = 'unknown'
|
||||||
|
# this part is obsolete - dimension should be given from the individual datasets
|
||||||
if not 'pid' in data.keys():
|
if not 'pid' in data.keys():
|
||||||
return
|
return
|
||||||
shape = data['pid'].shape
|
shape = data['pid'].shape
|
||||||
@ -95,15 +106,7 @@ def writeData(hid, data, scanrun=1):
|
|||||||
hid.create_dataset("scan_%d/method/samples" % scanrun,data=[nsam])
|
hid.create_dataset("scan_%d/method/samples" % scanrun,data=[nsam])
|
||||||
hid.create_dataset("scan_%d/method/dimension" % scanrun,data=[ndim])
|
hid.create_dataset("scan_%d/method/dimension" % scanrun,data=[ndim])
|
||||||
hid.create_dataset("scan_%d/method/reducedData" % scanrun,data=[0]) # indicating that there is at least a 2D array for scalar data
|
hid.create_dataset("scan_%d/method/reducedData" % scanrun,data=[0]) # indicating that there is at least a 2D array for scalar data
|
||||||
# write the sensor raw value
|
|
||||||
for ele in data.keys():
|
|
||||||
name=ele.split(':')
|
|
||||||
if len(name)>1:
|
|
||||||
dset=hid.create_dataset('scan_%d/data/%s/%s' % (scanrun, name[0], name[1]), data=data[ele])
|
|
||||||
else:
|
|
||||||
dset=hid.create_dataset('scan_%d/data/%s' % (scanrun, name[0]), data=data[ele])
|
|
||||||
dset.attrs['system'] = getDatasetSystem(name[0])
|
|
||||||
dset.attrs['units'] = 'unknown'
|
|
||||||
|
|
||||||
def writeActuator(hid,act,scanrun=1):
|
def writeActuator(hid,act,scanrun=1):
|
||||||
if not act:
|
if not act:
|
||||||
|
93
interface/slic.py
Normal file
93
interface/slic.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import h5py
|
||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
from threading import Thread
|
||||||
|
from PyQt5.QtCore import QObject, pyqtSignal
|
||||||
|
|
||||||
|
# to do:
|
||||||
|
# 1 - check if scan thread is running
|
||||||
|
# 2 - import of BSread data
|
||||||
|
|
||||||
|
from sfbd.interface import getSnap
|
||||||
|
|
||||||
|
class SlicScan(QObject):
|
||||||
|
|
||||||
|
siginc = pyqtSignal(int, int) # signal for increment
|
||||||
|
sigterm = pyqtSignal(int) # signal for termination
|
||||||
|
sigsnap = pyqtSignal(bool)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
QObject.__init__(self)
|
||||||
|
self.clear()
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self.daq = None
|
||||||
|
self.data = None
|
||||||
|
self.act = None
|
||||||
|
self.snap = None
|
||||||
|
|
||||||
|
def start(self,daq,snap=False):
|
||||||
|
self.clear()
|
||||||
|
Thread(target=self.Tmonitor).start()
|
||||||
|
self.startSnap(snap)
|
||||||
|
|
||||||
|
def startSnap(self,snap=False):
|
||||||
|
if not snap:
|
||||||
|
Thread(target=self.Tsnap).start()
|
||||||
|
|
||||||
|
def Tsnap(self):
|
||||||
|
self.snap = getSnap()
|
||||||
|
self.sigsnap.emit(True)
|
||||||
|
|
||||||
|
def Tmonitor(self):
|
||||||
|
mythread = Thread(target=self.Tscanner).start()
|
||||||
|
time.sleep(1)
|
||||||
|
ostep = -1
|
||||||
|
while(self.daq.running()):
|
||||||
|
istep,nstep=self.daq.status()
|
||||||
|
if istep>ostep:
|
||||||
|
ostep=istep
|
||||||
|
self.siginc.emit(istep,nstep)
|
||||||
|
time.sleep(1)
|
||||||
|
if not mythread == None: # wait till scanning thread is done
|
||||||
|
mythread.join()
|
||||||
|
istep,nstep=self.daq.status()
|
||||||
|
self.siginc.emit(istep,nstep)
|
||||||
|
self.data,self.act = importSlicScan(self.daq.info())
|
||||||
|
if hasattr(self.daq,'auxdata'):
|
||||||
|
self.data.update(self.daq.auxdata)
|
||||||
|
self.sigterm.emit(istep==nstep)
|
||||||
|
|
||||||
|
def Tscanner(self):
|
||||||
|
self.daq.scan()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.daq.stop()
|
||||||
|
|
||||||
|
|
||||||
|
def importSlicScan(scan_info):
|
||||||
|
if not isinstance(scan_info,dict):
|
||||||
|
return None,None
|
||||||
|
if not 'scan_files' in scan_info.keys():
|
||||||
|
return None,None
|
||||||
|
sfiles = scan_info['scan_files']
|
||||||
|
data = {}
|
||||||
|
for istep, sfile in enumerate(sfiles):
|
||||||
|
hid = h5py.File(sfile[0],'r')
|
||||||
|
for name, h5obj in hid.items():
|
||||||
|
if isinstance(h5obj,h5py.Dataset): # pv channels
|
||||||
|
data[name] = addDatasetToData(data,name,h5obj)
|
||||||
|
elif isinstance(h5obj,h5py.Group): # bs read channels
|
||||||
|
if 'data' in h5obj:
|
||||||
|
data[name] = addDatasetToData(data,name,h5obj['data'])
|
||||||
|
actuator = {}
|
||||||
|
name = scan_info['scan_parameters']['name'][0]
|
||||||
|
actuator[name]=np.array(scan_info['scan_values'])
|
||||||
|
data[name]=np.array(scan_info['scan_readbacks'])
|
||||||
|
return data,actuator
|
||||||
|
|
||||||
|
def addDatasetToData(data,name,h5obj):
|
||||||
|
if not name in data:
|
||||||
|
return np.array([h5obj[()]])
|
||||||
|
else:
|
||||||
|
return np.append(data[name],np.array([h5obj[()]]),axis=0)
|
Reference in New Issue
Block a user