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,12 +330,12 @@ 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},
]}, ]},
]}, ]},
#{'name':'Save/Restore functionality', 'type':'group','expanded':False, 'children':[ #{'name':'Save/Restore functionality', 'type':'group','expanded':False, 'children':[

View File

@@ -109,35 +109,28 @@ 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:
sz=self._sz pic=self._pic
pic = pv_pic.get(count=sz[0]*sz[1], as_numpy=True).reshape(sz[::-1])
epics_cam.set_fiducial(pic,255)
except AttributeError as e:
_log.warning("failed to fetch image")
else:
if pic.dtype==np.int16:
pic.dtype=np.uint16
try:
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
except AttributeError as e:
pass
pv_pic=self.getPv('FPICTURE')
sz=self._sz
pic = pv_pic.get(count=sz[0]*sz[1], as_numpy=True).reshape(sz[::-1])
epics_cam.set_fiducial(pic,255)
if pic.dtype==np.int16:
pic.dtype=np.uint16
self._pic=pic
return pic
def stop(self,v=CameraStatus.IDLE): def stop(self,v=CameraStatus.IDLE):
if 'pic' in self._pv: if 'pic' in self._pv:

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,33 +2065,53 @@ 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']
sp.setup_gather() with pg.ProgressDialog('Progress', 0, 100) as dlg:
sp.setup_sync(verbose=sp.verbose&0x20, timeOfs=0.05) dlg.setWindowModality(Qt.WindowModal)
try: #dlg.setRange(0, 0)
p=geo._fitPlane #dlg.setCancelButtonText("Abort Acquisition")
sp.setup_coord_trf(cz=f'{p[0]:+.18g}X{p[1]:+.18g}Y{p[2]:+.18g}') # reset to shape path system #dlg.canceled.connect(self.complete_daq)
except AttributeError: #dlg.setAutoClose(True)
_log.warning('no plane fitting done. z does not move') #dlg.show()
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 dlg.setLabelText("Setup Gather/Sync");dlg+=5
sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10) sp.setup_gather()
sp.homing() # homing if needed sp.setup_sync(verbose=sp.verbose&0x40, timeOfs=0.05)
sp.run() # start motion program try:
sp.wait_armed() # wait until motors are at first position p=geo._fitPlane
sp.trigger(0.5) # send a start trigger (if needed) after given time sp.setup_coord_trf(cz=f'{p[0]:+.18g}X{p[1]:+.18g}Y{p[2]:+.18g}') # reset to shape path system
jf.acquire('filename.tmp',sp.points.shape[0]) except AttributeError:
if not dt._comm is None: _log.warning('no plane fitting done. z does not move')
while True: sp.setup_coord_trf() # reset to shape path system
p=sp.progress() # sp.meta['pt2pt_time']=10 #put between setup_sync and setup_motion to have more motion points than FEL syncs
if p<0: break dlg.setLabelText("Download motion program");dlg+=5
_log.info(f'progress {p}/{sp.points.shape[0]}') sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10)
time.sleep(.1) dlg.setLabelText("Homing and get ready");dlg+=35
sp.gather_upload(fnRec=fn+'.npz') sp.homing() # homing if needed
if dt_misc['show_plots']: sp.run() # start motion program
dp=deltatau.shapepath.DebugPlot(sp) sp.wait_armed() # wait until motors are at first position
dp.plot_gather(mode=11) sp.trigger(0.5) # send a start trigger (if needed) after given time
plt.show(block=False) #PV with the current pulse
#plt.show(block=True) # [sf-lc7a ~]$ caget
jf.acquire('filename.tmp',sp.points.shape[0])
if not dt._comm is None:
dlg.setLabelText("run motion/acquisition")
dlg.setMaximum(sp.points.shape[0])
while True:
p=sp.progress()
if p<0 or dlg.wasCanceled():
break
#_log.info(f'progress {p}/{sp.points.shape[0]}')
dlg.setValue(p)
time.sleep(.1)
if not dlg.wasCanceled():
jf.gather_upload()
dlg.setLabelText("upload gather data")
sp.gather_upload(fnRec=fn+'.npz')
if dt_misc['show_plots']:
dp=psi_device.shapepath.DebugPlot(sp)
dp.plot_gather(mode=11)
plt.show(block=False)
#plt.show(block=True)
def esc_run_steps(self, steps, title, esc_state): def esc_run_steps(self, steps, title, esc_state):
self._esc_state ="busy" self._esc_state ="busy"

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()}')