smooth image update: use monitor callbacks to avoid block of ui when waiting for frame
This commit is contained in:
30
camera.py
30
camera.py
@@ -107,6 +107,7 @@ class epics_cam(object):
|
|||||||
print('camera.new_frame_pv_cb')
|
print('camera.new_frame_pv_cb')
|
||||||
|
|
||||||
def get_image(self):
|
def get_image(self):
|
||||||
|
_log.warning('this can be very slow. Use callbacks if possible.')
|
||||||
try:
|
try:
|
||||||
pv_pic=self.getPv('FPICTURE')
|
pv_pic=self.getPv('FPICTURE')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@@ -120,13 +121,7 @@ class epics_cam(object):
|
|||||||
pv_pic=self.getPv('FPICTURE')
|
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])
|
||||||
f=np.array(((0, 0, 0, 0, 0),
|
epics_cam.set_fiducial(pic,255)
|
||||||
(0, 1, 1, 1, 0),
|
|
||||||
(0, 1, 0, 0, 0),
|
|
||||||
(0, 1, 1, 0, 0),
|
|
||||||
(0, 1, 0, 0, 0),
|
|
||||||
(0, 0, 0, 0, 0),), pic.dtype)
|
|
||||||
pic[0:6, 0:5]=f*255
|
|
||||||
|
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
_log.warning("failed to fetch image")
|
_log.warning("failed to fetch image")
|
||||||
@@ -219,6 +214,16 @@ class epics_cam(object):
|
|||||||
pv_cam.put(CameraStatus.RUNNING, wait=True)
|
pv_cam.put(CameraStatus.RUNNING, wait=True)
|
||||||
self.update_size()
|
self.update_size()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_fiducial(pic,val):
|
||||||
|
# fiducial test
|
||||||
|
f=np.array(((0, 0, 0, 0, 0),
|
||||||
|
(0, 1, 1, 1, 0),
|
||||||
|
(0, 1, 0, 0, 0),
|
||||||
|
(0, 1, 1, 0, 0),
|
||||||
|
(0, 1, 0, 0, 0),
|
||||||
|
(0, 0, 0, 0, 0),), pic.dtype)
|
||||||
|
pic[0:6, 0:5]=f*pic.max()
|
||||||
|
|
||||||
def sim_gen(self,sz=(1500,1000),t=100,mode=0):
|
def sim_gen(self,sz=(1500,1000),t=100,mode=0):
|
||||||
'generate simulation data'
|
'generate simulation data'
|
||||||
@@ -257,15 +262,8 @@ class epics_cam(object):
|
|||||||
assert(img.mode=='L') # 8 bit grayscale
|
assert(img.mode=='L') # 8 bit grayscale
|
||||||
assert(sz==img.size)
|
assert(sz==img.size)
|
||||||
imgSeq[i,:,:]=np.array(img.getdata()).reshape(sz[::-1])
|
imgSeq[i,:,:]=np.array(img.getdata()).reshape(sz[::-1])
|
||||||
f=np.array(((0,0,0,0,0),
|
pic=imgSeq[i]
|
||||||
(0,1,1,1,0),
|
epics_cam.set_fiducial(pic, 255)
|
||||||
(0,1,0,0,0),
|
|
||||||
(0,1,1,0,0),
|
|
||||||
(0,1,0,0,0),
|
|
||||||
(0,0,0,0,0),),imgSeq.dtype)
|
|
||||||
imgSeq[i,0:6,0:5]=f*255
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self._sim['imgSeq']=imgSeq
|
self._sim['imgSeq']=imgSeq
|
||||||
self._sim['imgIdx']=0
|
self._sim['imgIdx']=0
|
||||||
|
|||||||
75
swissmx.py
75
swissmx.py
@@ -395,12 +395,32 @@ class Main(QMainWindow, Ui_MainWindow):
|
|||||||
app=QApplication.instance()
|
app=QApplication.instance()
|
||||||
app._camera.pause()
|
app._camera.pause()
|
||||||
|
|
||||||
def updateImage(self, pause=False):
|
def new_frame_sim_cb(self, **kwargs):
|
||||||
#if not sample_camera.is_paused(): #ZAC: orig. code
|
|
||||||
app=QApplication.instance()
|
app=QApplication.instance()
|
||||||
img = app._camera.get_image()
|
sim=app._camera._sim
|
||||||
if img is not None:
|
imgSeq=sim['imgSeq']
|
||||||
self.img.setImage(img)
|
idx=sim['imgIdx']
|
||||||
|
sim['imgIdx']=(idx+1)%imgSeq.shape[0]
|
||||||
|
# _log.info('simulated idx:{}'.format(idx))
|
||||||
|
pic=imgSeq[idx]
|
||||||
|
self.img.setImage(pic)
|
||||||
|
|
||||||
|
delay=500 # ms -> 2fps
|
||||||
|
QtCore.QTimer.singleShot(delay, self.new_frame_sim_cb)
|
||||||
|
|
||||||
|
def new_frame_pv_cb(self, **kwargs):
|
||||||
|
app=QApplication.instance()
|
||||||
|
sz=app._camera._sz
|
||||||
|
if kwargs['count']==sz[0]*sz[1]:
|
||||||
|
pic=kwargs['value'].reshape(sz[::-1])
|
||||||
|
else:
|
||||||
|
sz=self.update_size()
|
||||||
|
pic=kwargs['value'].reshape(sz[::-1])
|
||||||
|
_log.debug('new_frame_pv_cb count {}'.format(kwargs['count']))
|
||||||
|
if pic.dtype==np.int16:
|
||||||
|
pic.dtype=np.uint16
|
||||||
|
camera.epics_cam.set_fiducial(pic, 255)
|
||||||
|
self.img.setImage(pic)
|
||||||
|
|
||||||
def init_settings_tracker(self):
|
def init_settings_tracker(self):
|
||||||
_log.info("configuring widget persistence")
|
_log.info("configuring widget persistence")
|
||||||
@@ -527,15 +547,13 @@ class Main(QMainWindow, Ui_MainWindow):
|
|||||||
self.timer.timeout.connect(self.check_zescape)
|
self.timer.timeout.connect(self.check_zescape)
|
||||||
self.timer.start(20)
|
self.timer.start(20)
|
||||||
else:
|
else:
|
||||||
#zescape.stop_listening() #ZAC: orig. code
|
app=QApplication.instance()
|
||||||
_log.warning("re-starting timer on camera update")
|
|
||||||
try:
|
try:
|
||||||
self.timer.stop()
|
self.new_frame_sim_cb()
|
||||||
except:
|
except AttributeError:
|
||||||
pass
|
app._camera.run(self.new_frame_pv_cb)
|
||||||
self.timer = QtCore.QTimer(self)
|
|
||||||
self.timer.timeout.connect(self.updateImage)
|
|
||||||
self.timer.start(10)
|
|
||||||
|
|
||||||
def check_zescape(self):
|
def check_zescape(self):
|
||||||
msg = zescape.check()
|
msg = zescape.check()
|
||||||
@@ -3156,28 +3174,31 @@ class Main(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
def really_quit(self):
|
def really_quit(self):
|
||||||
"""called when user Ctrl-Q the app"""
|
"""called when user Ctrl-Q the app"""
|
||||||
global user, just_quit
|
if QMessageBox.question(self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes:
|
||||||
if (just_quit
|
|
||||||
or QMessageBox.question(self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes
|
|
||||||
):
|
|
||||||
self._do_quit = True
|
self._do_quit = True
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
"""this is called when the user clicks the window's cross icon"""
|
"""this is called when the user clicks the window's cross icon"""
|
||||||
global user, just_quit
|
|
||||||
if (
|
if (
|
||||||
just_quit
|
self._do_quit
|
||||||
or self._do_quit
|
|
||||||
or QMessageBox.question( self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes
|
or QMessageBox.question( self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes
|
||||||
):
|
):
|
||||||
sample_camera.disconnect()
|
app=QApplication.instance()
|
||||||
|
try:
|
||||||
|
pv=app._camera._pv['pic']
|
||||||
|
pv.clear_auto_monitor() # disconnect PV monitor callback -> program exit faster.
|
||||||
|
except AttributeError:
|
||||||
|
_log.warning('disconnect PV callback failed.')
|
||||||
|
|
||||||
|
_log.info('disconnect PV callback')
|
||||||
settings.setValue("window/geometry", self.saveGeometry())
|
settings.setValue("window/geometry", self.saveGeometry())
|
||||||
settings.setValue("window/windowState", self.saveState())
|
settings.setValue("window/windowState", self.saveState())
|
||||||
settings.setValue("window/main_splitter", self._main_splitter.sizes())
|
settings.setValue("window/main_splitter", self._main_splitter.sizes())
|
||||||
settings.setValue("last_active", time.time())
|
settings.setValue("last_active", time.time())
|
||||||
|
_log.info('save settings')
|
||||||
QMainWindow.closeEvent(self, event)
|
#QMainWindow.closeEvent(self, event)
|
||||||
|
_log.info('closeEvent done')
|
||||||
else:
|
else:
|
||||||
event.ignore()
|
event.ignore()
|
||||||
|
|
||||||
@@ -3220,7 +3241,10 @@ def sigint_handler(*args):
|
|||||||
def main():
|
def main():
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
#(h, t)=os.path.split(sys.argv[0]);cmd='\n '+(t if len(h)>20 else sys.argv[0])+' '
|
||||||
|
#exampleCmd=('', '-m0xf -v0')
|
||||||
|
epilog=__doc__ #+'\nExamples:'+''.join(map(lambda s:cmd+s, exampleCmd))+'\n'
|
||||||
|
parser=argparse.ArgumentParser(epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
parser.add_argument("--sim", "-s", type=lambda x: int(x,0), help="simulate devices (see bitmasks) default=0x%(default)x", default=0)
|
parser.add_argument("--sim", "-s", type=lambda x: int(x,0), help="simulate devices (see bitmasks) default=0x%(default)x", default=0)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
_log.info('Arguments:{}'.format(args.__dict__))
|
_log.info('Arguments:{}'.format(args.__dict__))
|
||||||
@@ -3250,10 +3274,9 @@ def main():
|
|||||||
if args.sim&0x08:
|
if args.sim&0x08:
|
||||||
app._camera = camera.epics_cam(None)
|
app._camera = camera.epics_cam(None)
|
||||||
app._camera.sim_gen(mode=1)
|
app._camera.sim_gen(mode=1)
|
||||||
app._camera.run()
|
|
||||||
else:
|
else:
|
||||||
app._camera = camera.epics_cam()
|
app._camera = camera.epics_cam()
|
||||||
app._camera.run()
|
#app._camera.run() is called in center_piece_update
|
||||||
|
|
||||||
app_icon = QtGui.QIcon()
|
app_icon = QtGui.QIcon()
|
||||||
app_icon.addFile("artwork/logo/16x16.png", QtCore.QSize(16, 16))
|
app_icon.addFile("artwork/logo/16x16.png", QtCore.QSize(16, 16))
|
||||||
|
|||||||
Reference in New Issue
Block a user