various fixes

This commit is contained in:
2022-09-16 12:25:36 +02:00
parent 6a7b5ab91e
commit ba4f5feecb
7 changed files with 141 additions and 87 deletions

View File

@@ -263,10 +263,10 @@ verbose bits:
0x01 basic info 0x01 basic info
0x02 plot sorting steps 0x02 plot sorting steps
0x04 list program 0x04 list program
0x04 upload progress 0x08 upload progress
0x08 plot gather path 0x10 plot gather path
0x10 plot pvt trajectory (before motion) 0x20 plot pvt trajectory (before motion)
0x20 print sync details 0x40 print sync details
''' '''
params=[ params=[
@@ -330,9 +330,9 @@ verbose bits:
{'name':'Delta Tau Parameters', 'type':'group','expanded':False, 'children':[ {'name':'Delta Tau Parameters', 'type':'group','expanded':False, 'children':[
{'name':AppCfg.DT_HOST ,'title':'host name (host[:port:port_gather])','value':dt_host ,'type':'str'} , {'name':AppCfg.DT_HOST ,'title':'host name (host[:port:port_gather])','value':dt_host ,'type':'str'} ,
{'name':AppCfg.DT_MISC, 'title':'miscellaneous', 'type':'group', 'children':[ {'name':AppCfg.DT_MISC, 'title':'miscellaneous', 'type':'group', 'children':[
{'name':'show plots after collection', 'value':dt_misc['show_plots'], 'type':'bool','tip':"This is a checkbox"}, {'name':'show_plots', 'value':dt_misc['show_plots'], 'type':'bool', 'title':'show plots after collection'},
{'name':'velocity_scale', 'value':dt_misc['vel_scl'], 'type':'float', 'limits':(0, 1), 'step':0.1, 'tip':"This is a checkbox"}, {'name':'vel_scl', 'value':dt_misc['vel_scl'], 'type':'float', 'limits':(0, 1), 'step':0.1, 'title':'velocity_scale', 'tip':"scale between smooth(1.0) and stop and go(0.0)"},
{'name':'pt2pt_time', 'value':dt_misc['pt2pt_time'],'type':'float', 'step':0.1,'tip':"This is a checkbox"}, {'name':'pt2pt_time', 'value':dt_misc['pt2pt_time'], 'type':'float', 'step':0.1,'tip':"time in ms from point to point"},
{'name':'sync_mode', 'value':dt_misc['sync_mode'], 'type':'int', 'tip':tip_sync_mode}, {'name':'sync_mode', 'value':dt_misc['sync_mode'], 'type':'int', 'tip':tip_sync_mode},
{'name':'sync_flag', 'value':dt_misc['sync_flag'], 'type':'int', 'tip':tip_sync_flag}, {'name':'sync_flag', 'value':dt_misc['sync_flag'], 'type':'int', 'tip':tip_sync_flag},
{'name':'verbose', 'value':dt_misc['verbose'], 'type':'int', 'tip':tip_verbose}, {'name':'verbose', 'value':dt_misc['verbose'], 'type':'int', 'tip':tip_verbose},

View File

@@ -109,34 +109,27 @@ class epics_cam(object):
def get_image(self): def get_image(self):
_log.warning('this can be very slow. Use callbacks if possible.') _log.warning('this can be very slow. Use callbacks if possible.')
try: try:
pv_pic=self.getPv('FPICTURE') imgSeq=self._sim['imgSeq']
except AttributeError: except AttributeError: pass
else:
imgSeq=self._sim['imgSeq'] imgSeq=self._sim['imgSeq']
idx=self._sim['imgIdx'] idx=self._sim['imgIdx']
self._sim['imgIdx']=(idx + 1) % imgSeq.shape[0] self._sim['imgIdx']=(idx + 1) % imgSeq.shape[0]
#_log.debug('simulated idx:{}'.format(idx)) #_log.debug('simulated idx:{}'.format(idx))
self.pic=pic=imgSeq[idx] self._pic=pic=imgSeq[idx]
return pic return pic
try: try:
pic=self._pic
return pic
except AttributeError as e:
pass
pv_pic=self.getPv('FPICTURE')
sz=self._sz sz=self._sz
pic = pv_pic.get(count=sz[0]*sz[1], as_numpy=True).reshape(sz[::-1]) pic = pv_pic.get(count=sz[0]*sz[1], as_numpy=True).reshape(sz[::-1])
epics_cam.set_fiducial(pic,255) epics_cam.set_fiducial(pic,255)
except AttributeError as e:
_log.warning("failed to fetch image")
else:
if pic.dtype==np.int16: if pic.dtype==np.int16:
pic.dtype=np.uint16 pic.dtype=np.uint16
try: self._pic=pic
trf=self._transformation
except AttributeError as e:
pass
else:
if trf[1,0]==0:
pic=pic[::trf[0,0],::trf[1,1]]
else:
pic=pic[::trf[0,1],::trf[1,0]].T
self.pic=pic
return pic return pic
def stop(self,v=CameraStatus.IDLE): def stop(self,v=CameraStatus.IDLE):

View File

@@ -256,13 +256,13 @@ class geometry:
_log.debug('least square data:\nK:{}\nAA:{}'.format(K, AA)) _log.debug('least square data:\nK:{}\nAA:{}'.format(K, AA))
@staticmethod @staticmethod
def autofocus(cam,mot,rng=(-1,1),n=30,saveImg=False): def autofocus(cam,mot,rng=(-1,1),n=30,progressDlg=None,saveImg=False):
# cam camera object # cam camera object
# mot motor object # mot motor object (e.g. SimMotorTweak)
# rng region (min max relative to current position) to seek # rng region (min max relative to current position) to seek
# n number of images to take in region # n number of images to take in region
# roi region of interrest to calculate sharpness # progressDlg a pg.ProgressDialog to allow to abort the function call
# mode mode to calculate sharpness (sum/max-min/hist? of edge detection in roi)
if mot is not None: if mot is not None:
p0=mot.get_rbv() p0=mot.get_rbv()
else: else:
@@ -295,13 +295,19 @@ class geometry:
img=np.asarray(img) img=np.asarray(img)
else: else:
mot.move_abs(p, wait=True) mot.move_abs(p, wait=True)
img=cam._pic # get_image() img=cam.get_image() # get latest image
img16=np.array(img, np.int16) img16=np.array(img, np.int16)
msk=np.array(((1, 0, -1), (2, 0, -2), (1, 0, -1)), np.int16) msk=np.array(((1, 0, -1), (2, 0, -2), (1, 0, -1)), np.int16)
sb1=signal.convolve2d(img16, msk, mode='same', boundary='fill', fillvalue=0) sb1=signal.convolve2d(img16, msk, mode='same', boundary='fill', fillvalue=0)
sb2=signal.convolve2d(img16, msk.T, mode='same', boundary='fill', fillvalue=0) sb2=signal.convolve2d(img16, msk.T, mode='same', boundary='fill', fillvalue=0)
sb=np.abs(sb1)+np.abs(sb2) sb=np.abs(sb1)+np.abs(sb2)
mtr[i]=sb.sum() mtr[i]=sb.sum()
try:
progressDlg+=1
if progressDlg.wasCanceled():
return
except TypeError as e:
pass
_log.debug(f'{i}/{p:.4g} -> {mtr[i]:.4g}') _log.debug(f'{i}/{p:.4g} -> {mtr[i]:.4g}')
mx=mtr.argmax() mx=mtr.argmax()
@@ -333,8 +339,7 @@ class geometry:
img=PIL.Image.open(cam) img=PIL.Image.open(cam)
img=np.asarray(img) img=np.asarray(img)
else: else:
img=cam._pic # get_image() img=cam.get_image() # get latest image
img16=np.array(img, np.int16)
fid=np.ones((sz[1]+2*brd[1],sz[0]+2*brd[0]),dtype=np.uint8)*255 fid=np.ones((sz[1]+2*brd[1],sz[0]+2*brd[0]),dtype=np.uint8)*255
fid[brd[1]:sz[1]+brd[1],brd[0]:sz[0]+brd[0]]=0 fid[brd[1]:sz[1]+brd[1],brd[0]:sz[0]+brd[0]]=0

View File

@@ -15,7 +15,7 @@ _log=logging.getLogger(__name__)
from PyQt5.QtWidgets import (QApplication,) from PyQt5.QtWidgets import (QApplication,)
from app_config import AppCfg #settings, option, toggle_option from app_config import AppCfg #settings, option, toggle_option
import epics
from pbtools.misc.pp_comm import PPComm from pbtools.misc.pp_comm import PPComm
from pbtools.misc.gather import Gather from pbtools.misc.gather import Gather
import shapepath import shapepath
@@ -25,6 +25,7 @@ try:
except ImportError as e: except ImportError as e:
_log.warning(e) _log.warning(e)
class Deltatau: class Deltatau:
def __init__(self): def __init__(self):
app=QApplication.instance() app=QApplication.instance()
@@ -83,7 +84,14 @@ class Jungfrau:
except NameError as e: except NameError as e:
_log.warning(f'Jungfrau not connected: {e}') _log.warning(f'Jungfrau not connected: {e}')
self._daq=None self._daq=None
self._pv_pulse_id=epics.PV('SAR-EXPMX-EVR0:RX-PULSEID')
def acquire(self,run_name, n_pulses, wait=False): def acquire(self,run_name, n_pulses, wait=False):
if self._daq is not None: if self._daq is not None:
self._pulse_id_start=self._pv_pulse_id.value
self._daq.acquire( run_name, n_pulses=n_pulses, wait=False) self._daq.acquire( run_name, n_pulses=n_pulses, wait=False)
def gather_upload(self):
self._pulse_id_end=self._pv_pulse_id.value

View File

@@ -30,6 +30,7 @@ logging.getLogger('matplotlib').setLevel(logging.INFO)
logging.getLogger('PIL').setLevel(logging.INFO) logging.getLogger('PIL').setLevel(logging.INFO)
logging.getLogger('illumination').setLevel(logging.INFO) logging.getLogger('illumination').setLevel(logging.INFO)
logging.getLogger('zoom').setLevel(logging.INFO) logging.getLogger('zoom').setLevel(logging.INFO)
logging.getLogger('pbtools.misc.pp_comm').setLevel(logging.INFO)
_log = logging.getLogger("swissmx") _log = logging.getLogger("swissmx")
#_log.setLevel(logging.INFO) #_log.setLevel(logging.INFO)
@@ -47,6 +48,8 @@ import sys, os, time
import json, re import json, re
import random, signal, subprocess import random, signal, subprocess
import matplotlib as mpl import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.use('Qt5Agg') # needed to avoid blocking of ui ! mpl.use('Qt5Agg') # needed to avoid blocking of ui !
TASK_JUNGFRAU_SETTINGS = "jungfrau_settings" TASK_JUNGFRAU_SETTINGS = "jungfrau_settings"
@@ -1595,7 +1598,10 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch)
app=QApplication.instance() app=QApplication.instance()
geo=app._geometry geo=app._geometry
#geo.autofocus(app._camera, self.tweakers['base_z'],rng=(-1, 1), n=30,saveImg=True) #geo.autofocus(app._camera, self.tweakers['base_z'],rng=(-1, 1), n=30,saveImg=True)
geo.autofocus(app._camera, self.tweakers['base_z'],rng=(-1, 1), n=10) n=10
rng=(-1, 1)
with pg.ProgressDialog('Progress', 0, n) as dlg:
geo.autofocus(app._camera, self.tweakers['base_z'],rng, n,dlg)
def cb_find_fiducial(self): def cb_find_fiducial(self):
app=QApplication.instance() app=QApplication.instance()
@@ -2059,8 +2065,17 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch)
sp.verbose=dt_misc['verbose'] sp.verbose=dt_misc['verbose']
sp.points=kwargs['points'] sp.points=kwargs['points']
sp.meta['pt2pt_time']=dt_misc['pt2pt_time'] sp.meta['pt2pt_time']=dt_misc['pt2pt_time']
with pg.ProgressDialog('Progress', 0, 100) as dlg:
dlg.setWindowModality(Qt.WindowModal)
#dlg.setRange(0, 0)
#dlg.setCancelButtonText("Abort Acquisition")
#dlg.canceled.connect(self.complete_daq)
#dlg.setAutoClose(True)
#dlg.show()
dlg.setLabelText("Setup Gather/Sync");dlg+=5
sp.setup_gather() sp.setup_gather()
sp.setup_sync(verbose=sp.verbose&0x20, timeOfs=0.05) sp.setup_sync(verbose=sp.verbose&0x40, timeOfs=0.05)
try: try:
p=geo._fitPlane p=geo._fitPlane
sp.setup_coord_trf(cz=f'{p[0]:+.18g}X{p[1]:+.18g}Y{p[2]:+.18g}') # reset to shape path system sp.setup_coord_trf(cz=f'{p[0]:+.18g}X{p[1]:+.18g}Y{p[2]:+.18g}') # reset to shape path system
@@ -2068,21 +2083,32 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch)
_log.warning('no plane fitting done. z does not move') _log.warning('no plane fitting done. z does not move')
sp.setup_coord_trf() # reset to shape path system sp.setup_coord_trf() # reset to shape path system
# sp.meta['pt2pt_time']=10 #put between setup_sync and setup_motion to have more motion points than FEL syncs # sp.meta['pt2pt_time']=10 #put between setup_sync and setup_motion to have more motion points than FEL syncs
dlg.setLabelText("Download motion program");dlg+=5
sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10) sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10)
dlg.setLabelText("Homing and get ready");dlg+=35
sp.homing() # homing if needed sp.homing() # homing if needed
sp.run() # start motion program sp.run() # start motion program
sp.wait_armed() # wait until motors are at first position sp.wait_armed() # wait until motors are at first position
sp.trigger(0.5) # send a start trigger (if needed) after given time sp.trigger(0.5) # send a start trigger (if needed) after given time
#PV with the current pulse
# [sf-lc7a ~]$ caget
jf.acquire('filename.tmp',sp.points.shape[0]) jf.acquire('filename.tmp',sp.points.shape[0])
if not dt._comm is None: if not dt._comm is None:
dlg.setLabelText("run motion/acquisition")
dlg.setMaximum(sp.points.shape[0])
while True: while True:
p=sp.progress() p=sp.progress()
if p<0: break if p<0 or dlg.wasCanceled():
_log.info(f'progress {p}/{sp.points.shape[0]}') break
#_log.info(f'progress {p}/{sp.points.shape[0]}')
dlg.setValue(p)
time.sleep(.1) time.sleep(.1)
if not dlg.wasCanceled():
jf.gather_upload()
dlg.setLabelText("upload gather data")
sp.gather_upload(fnRec=fn+'.npz') sp.gather_upload(fnRec=fn+'.npz')
if dt_misc['show_plots']: if dt_misc['show_plots']:
dp=deltatau.shapepath.DebugPlot(sp) dp=psi_device.shapepath.DebugPlot(sp)
dp.plot_gather(mode=11) dp.plot_gather(mode=11)
plt.show(block=False) plt.show(block=False)
#plt.show(block=True) #plt.show(block=True)

View File

@@ -107,9 +107,9 @@ class autofocus(QtGui.QMainWindow):
# fft[300:700,400:800]=0 # fft[300:700,400:800]=0
# v[i,1]=fft.sum() # v[i,1]=fft.sum()
self._imv1.setImage(sb,autoRange=auto,autoLevels=auto,autoHistogramRange=auto) self._imv1.setImage(img,autoRange=auto,autoLevels=auto,autoHistogramRange=auto)
#self._imv2.setImage(sb,autoRange=auto,autoLevels=auto,autoHistogramRange=auto) self._imv2.setImage(sb,autoRange=auto,autoLevels=auto,autoHistogramRange=auto)
self._imv2.setImage(sbLut,autoRange=auto,autoLevels=auto,autoHistogramRange=auto) #self._imv2.setImage(sbLut,autoRange=auto,autoLevels=auto,autoHistogramRange=auto)
mtr=self._metrics mtr=self._metrics
mtr[i, 0]=img.std() mtr[i, 0]=img.std()

View File

@@ -69,13 +69,26 @@ class fiducial(QtGui.QMainWindow):
self._imgLst=imgLst=sorted(glob.glob("../scratch/fiducial/*.png")) self._imgLst=imgLst=sorted(glob.glob("../scratch/fiducial/*.png"))
self._metrics=mtr=np.ndarray(shape=(len(imgLst), 5)) self._metrics=mtr=np.ndarray(shape=(len(imgLst), 5))
mtr[:]=0 mtr[:]=0
self._sld=sld=QtGui.QSlider(QtCore.Qt.Horizontal) self._sldImgIdx=sld1=QtGui.QSlider(QtCore.Qt.Horizontal)
sld.setMinimum(0) sld1.setMinimum(0)
sld.setMaximum(len(imgLst)-1) sld1.setMaximum(len(imgLst)-1)
sld.setValue(0) sld1.setValue(0)
sld.setTickPosition(QtGui.QSlider.TicksBelow) sld1.setTickPosition(QtGui.QSlider.TicksBelow)
sld.setTickInterval(1) sld1.setTickInterval(1)
sld.valueChanged.connect(self.cb_sld_change) sld1.valueChanged.connect(self.cb_sld_change)
self._sldTplSz=sld2=QtGui.QSlider(QtCore.Qt.Horizontal)
sld2.setMinimum(0)
sld2.setMaximum(300)
sld2.setValue(90)
sld2.valueChanged.connect(self.cb_sld_change)
self._sldTplBrd=sld3=QtGui.QSlider(QtCore.Qt.Horizontal)
sld3.setMinimum(3)
sld3.setMaximum(50)
sld3.setValue(20)
sld3.valueChanged.connect(self.cb_sld_change)
self._imv1=imv1=pg.ImageView() self._imv1=imv1=pg.ImageView()
self._imv2=imv2=pg.ImageView() self._imv2=imv2=pg.ImageView()
@@ -91,10 +104,12 @@ class fiducial(QtGui.QMainWindow):
pw.resize(100,100) pw.resize(100,100)
pw.setMaximumSize(2000,200) pw.setMaximumSize(2000,200)
l.addWidget(sld, 0, 0) l.addWidget(sld1, 0, 0)
l.addWidget(imv1, 1, 0) l.addWidget(sld2, 1, 0)
l.addWidget(imv2, 2, 0) l.addWidget(sld3, 2, 0)
l.addWidget(pw, 3, 0) l.addWidget(imv1, 3, 0)
l.addWidget(imv2, 4, 0)
l.addWidget(pw, 5, 0)
## Display the data ## Display the data
self.cb_sld_change(0,True) self.cb_sld_change(0,True)
@@ -108,7 +123,7 @@ class fiducial(QtGui.QMainWindow):
self._imv2.setLevels(0, 1) self._imv2.setLevels(0, 1)
def cb_sld_change(self,val,auto=False): def cb_sld_change(self,val,auto=False):
i=self._sld.value() i=self._sldImgIdx.value()
_log.debug(f'{i}') _log.debug(f'{i}')
fn= self._imgLst[i] fn= self._imgLst[i]
img=PIL.Image.open(fn) img=PIL.Image.open(fn)
@@ -134,15 +149,17 @@ class fiducial(QtGui.QMainWindow):
#fid=np.ones((250,250),dtype=np.uint8)*255 #fid=np.ones((250,250),dtype=np.uint8)*255
#fid[20:230,20:230]=0 #fid[20:230,20:230]=0
sz=(90, 90); brd=(20, 20) # zoom 001 #sz=( 84, 84); brd=( 7, 7) # zoom 001
#sz=(130, 130); brd=(20, 20) # zoom 200 #sz=(128, 128); brd=( 9, 9) # zoom 200
#sz=(210, 210); brd=(20, 20) # zoom 400 #sz=(200, 200); brd=(13, 13) # zoom 400
v=self._sldTplSz.value(); sz=(v,v)
v=self._sldTplBrd.value(); brd=(v,v)
fid=np.ones((sz[1]+2*brd[1],sz[0]+2*brd[0]),dtype=np.uint8)*255 fid=np.ones((sz[1]+2*brd[1],sz[0]+2*brd[0]),dtype=np.uint8)*255
fid[brd[1]:sz[1]+brd[1],brd[0]:sz[0]+brd[0]]=0 fid[brd[1]:sz[1]+brd[1],brd[0]:sz[0]+brd[0]]=0
mask=np.ones((sz[1]+2*brd[1],sz[0]+2*brd[0]),dtype=np.uint8)*255 mask=np.ones((sz[1]+2*brd[1],sz[0]+2*brd[0]),dtype=np.uint8)*255
mask[2*brd[1]:sz[1],2*brd[0]:sz[0]]=0 mask[2*brd[1]:sz[1],2*brd[0]:sz[0]]=0
#https://docs.opencv.org/4.5.2/d4/dc6/tutorial_py_template_matching.html #https://docs.opencv.org/4.5.2/d4/dc6/tutorial_py_template_matching.html
#res = cv.matchTemplate(img,fid,cv.TM_CCORR_NORMED ) #res = cv.matchTemplate(img,fid,cv.TM_CCORR_NORMED )
res = cv.matchTemplate(img,fid,cv.TM_CCORR_NORMED,mask=mask) res = cv.matchTemplate(img,fid,cv.TM_CCORR_NORMED,mask=mask)
@@ -177,6 +194,11 @@ class fiducial(QtGui.QMainWindow):
self._imv1.setImage(img,autoRange=auto,autoLevels=auto,autoHistogramRange=auto) self._imv1.setImage(img,autoRange=auto,autoLevels=auto,autoHistogramRange=auto)
self._imv2.setImage(res,autoRange=auto,autoLevels=auto,autoHistogramRange=auto) self._imv2.setImage(res,autoRange=auto,autoLevels=auto,autoHistogramRange=auto)
pos=mtr.mean(0)[::-1]+(fw2,fh2) pos=mtr.mean(0)[::-1]+(fw2,fh2)
print(fid)
print(mask)
print(corr)
print(mtr)
print(f'TplSz:{sz} TplBrd:{brd}')
_log.debug(f'position: {pos} correlation:{corr.mean()}') _log.debug(f'position: {pos} correlation:{corr.mean()}')