From a54e5806647dbb5d4dca43b49b05b7c1ce19de24 Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Thu, 1 Sep 2022 13:29:57 +0200 Subject: [PATCH] wip --- app_config.py | 15 +++++-- camera.py | 48 ++++++++++++++++++++++ swissmx.py | 107 +++++++++++++++++++++++++++++--------------------- 3 files changed, 121 insertions(+), 49 deletions(-) diff --git a/app_config.py b/app_config.py index b5c52b0..77bfbab 100644 --- a/app_config.py +++ b/app_config.py @@ -32,13 +32,13 @@ class MyJsonEncoder(json.JSONEncoder): class AppCfg(QSettings): GBL_FLD_SCR_SHOT="global/folder_screenshot" - GEO_OPT_CTR='geometry/opt_ctr' GEO_PIX2POS='geometry/pix2pos' GEO_BEAM_SZ="geometry/beam_size" GEO_BEAM_POS="geometry/beam_pos" + GEO_CAM_PARAM="geometry/cam_param" WINDOW_GEOMETRY="window/geometry" WINDOW_SPLITTER="window/splitter" @@ -147,19 +147,26 @@ class AppCfg(QSettings): def setValue(self, key: str, val): #overload to debug # only simple lists, str, int, float can not be serialized nicely t=type(val) - if key in (AppCfg.GEO_PIX2POS): + if key in (AppCfg.GEO_PIX2POS,): val=json.dumps(val, cls=MyJsonEncoder) + elif key in (AppCfg.GEO_CAM_PARAM,): + val=json.dumps(val, cls=MyJsonEncoder) + val=val.replace('"',"'") elif key in (AppCfg.GEO_OPT_CTR,AppCfg.GEO_BEAM_SZ,AppCfg.GEO_BEAM_POS,): - val=val.tolist() + if type(val)==np.ndarray: + val=val.tolist() elif type(val)==tuple: val=list(val) return super(AppCfg, self).setValue(key,val) def value(self,key,*vargs,**kwargs): #overload to debug val=super(AppCfg, self).value(key,*vargs,**kwargs) - if key in (AppCfg.GEO_PIX2POS): + if key in (AppCfg.GEO_PIX2POS,): val=json.loads(val)#, object_hook=MyJsonDecoder) val=(np.array(val[0]),np.array(val[1])) + if key in (AppCfg.GEO_CAM_PARAM,): + val=val.replace("'",'"') + val=json.loads(val) # , object_hook=MyJsonDecoder) elif key in (AppCfg.GEO_BEAM_SZ,AppCfg.GEO_BEAM_POS,): val=np.array(tuple(map(float, val)))/1000 elif key in (AppCfg.GEO_OPT_CTR): diff --git a/camera.py b/camera.py index 57d203c..b64325e 100755 --- a/camera.py +++ b/camera.py @@ -169,6 +169,54 @@ class epics_cam(object): pv_w=self.getPv('WIDTH');pv_h=self.getPv('HEIGHT') self._sz=(int(pv_w.value), int(pv_h.value)) + def get_param(self): + param=dict() + pv_gain=self.getPv('AMPGAIN') + pv_exp=self.getPv('EXPOSURE') + pv_bx=self.getPv('BINX');pv_by=self.getPv('BINY') + pv_rxs=self.getPv('REGIONX_START');pv_rxe=self.getPv('REGIONX_END') + pv_rys=self.getPv('REGIONY_START');pv_rye=self.getPv('REGIONY_END') + pv_mono8=self.getPv('FORCEMONO8') + + + param['gain']=pv_gain.get() + param['exposure']=pv_exp.get() + param['binning']=(pv_bx.get(),pv_by.get()) + xs=pv_rxs.get();xe=pv_rxe.get() + ys=pv_rys.get();ye=pv_rye.get() + param['roi']=(xs,ys,xe-xs,ye-ys) + param['mono8']=pv_mono8.get() + return param + + def set_param(self,**kwargs): + param=[] + for k,v in kwargs: + if k=='gain': + pv_gain=self.getPv('AMPGAIN') + param.append((pv_gain,v)) + elif k=='exposure': + pv_exp=self.getPv('EXPOSURE') + param.append((pv_exp,v)) + elif k=='binning': + pv_bx=self.getPv('BINX');pv_by=self.getPv('BINY') + param.append((pv_bx,v[0])) + param.append((pv_by,v[1])) + elif k=='roi': + pv_rxs=self.getPv('REGIONX_START');pv_rxe=self.getPv('REGIONX_END') + pv_rys=self.getPv('REGIONY_START');pv_rye=self.getPv('REGIONY_END') + pv_rxs.put(v[0], wait=False) + pv_rxe.put(v[0]+v[2], wait=False) + pv_rys.put(v[1], wait=False) + pv_rye.put(v[1]+v[3], wait=False) + param.append((pv_rxs,v[0])) + param.append((pv_rxe,v[0]+v[2])) + param.append((pv_rys,v[1])) + param.append((pv_rye,v[1]+v[3])) + elif k=='mono8': + pv_mono8=self.getPv('FORCEMONO8') + param.append((pv_mono8,vv)) + self.update_params(param) + def set_exposure(self,exp): try: pv_exp=self.getPv('EXPOSURE') diff --git a/swissmx.py b/swissmx.py index 58e35a7..082820a 100755 --- a/swissmx.py +++ b/swissmx.py @@ -86,7 +86,7 @@ import qtawesome import qutilities from PyQt5 import QtCore, QtGui from PyQt5.QtCore import Qt, pyqtSlot, QSize, QRegExp, pyqtSignal, QObject, QThread -from PyQt5.QtGui import QKeySequence, QPixmap, QRegExpValidator +from PyQt5.QtGui import QKeySequence, QPixmap, QRegExpValidator, QFont from PyQt5.QtWidgets import ( QAction, QApplication, QDoubleSpinBox, QFileDialog, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPlainTextEdit, QProgressBar, QProgressDialog, QPushButton, QShortcut, QSizePolicy, QSpinBox, @@ -302,9 +302,10 @@ class WndSwissMx(QMainWindow, Ui_MainWindow): self._message_critical_fault = QLabel(None) self._message_critical_fault.setAccessibleName("device_fault") self.statusbar.insertWidget(0, self._message_critical_fault) - self._lb_coords = QLabel(None) - self._lb_coords.setText("coords") - self.statusbar.addPermanentWidget(self._lb_coords) + self._lb_coords=lbl=QLabel(None) + #f=QFont('monospace', 10) + #lbl.setFont(f) + self.statusbar.addPermanentWidget(lbl) self._fel_status = QLabel(None) self._fel_status.setAccessibleName("fel_status_statusbar") @@ -645,7 +646,25 @@ class WndSwissMx(QMainWindow, Ui_MainWindow): self.cb_new_frame_sim() except AttributeError: self.sigNewCamImg.connect(self.cb_update_img) - app._camera.run(self.cb_new_frame_pv) + cam=app._camera + cfg=app._cfg + param=cam.get_param() + try: + paramSv=cfg.value(AppCfg.GEO_CAM_PARAM) + except AttributeError as e: + cfg.setValue(AppCfg.GEO_CAM_PARAM, param) + else: + for k,v in param.items(): + if v!=paramSv[k]: + if type(v)==tuple: + if v==tuple(paramSv[k]): + continue + #cam.set_param(paramSv) + #cfg.setValue(AppCfg.GEO_CAM_PARAM, param) + #break + _log.debug(f'diff:{k},{v} != {paramSv[k]}') + + cam.run(self.cb_new_frame_pv) def cb_new_frame_pv(self, **kwargs): #thrd=threading.current_thread() @@ -932,47 +951,40 @@ class WndSwissMx(QMainWindow, Ui_MainWindow): def cb_mouse_move(self, pos): app = QApplication.instance() - self._mouse_pos = pos + geo = app._geometry + #pos = pixel position on the widget task = self.active_task() - xy = self._goImg.mapFromScene(pos) z = app._zoom.get_val() - #_log.debug('mouse_pos:{} scene_pos:{} zoom:{}'.format(pos,xy,z)) - #TODO: implement mouse handling - # if self._ppm_toolbox._force_ppm > 0: - # ppm = self._ppm_toolbox._force_ppm - # else: - try: - ppm = self.ppm_fitter(z) - except: - ppm = 1E3 - x, y = xy.x(), xy.y() - try: - bx, by = self.get_beam_mark_on_camera_xy() - except: - bx, by = 500, 500 - dx = (x - bx) / ppm - dy = -(y - by) / ppm - try: - fx = self.tweakers["fast_x"].motor.get_position() - fy = self.tweakers["fast_y"].motor.get_position() - fx += dx - fy += dy - except: - fx=fy=0 - self._lb_coords.setText( - "\u23FA{:>}:{:>6.0f} {:<.0f}" - "\u23FA{:>}:{:>6.0f} {:<.0f}" - "\u23FA{:>}:{:<.0f}" - "\u23FA{:>}:{:>6.1f} {:<.1f} \u00B5" - "\u23FA{:>}:{:>7.3f} {:<.3f} mm".format( - "Beam at", bx, by, - "Pixel coord ", x, y, - "PPM", ppm, - "Distance to beam", 1000 * dx, 1000 * dy, - "Stage", fx, fy, - ) - ) + #bm=self._goBeamMarker + #pos=event.scenePos() + pImg=pg.Point(self._goImg.mapFromScene(pos)) + pTrk=pg.Point(self._goTracked.mapFromScene(pos)) + fx=self.tweakers["fast_x"].get_val() + fy=self.tweakers["fast_y"].get_val() + pTrk=pTrk-(fx,fy) + #s=f'pImg{pImg} pTrk{pTrk} bm._pos_eu{bm._pos_eu}' + + + s=\ + f'img pix ({pImg[0]:>0.1f} {pImg[1]:>0.1f})px \u23A2 ' \ + f'dist to beam ({pTrk[0]:>0.6g} {pTrk[1]:>0.6g}mm) ' + + _log.debug(s) + self._lb_coords.setText(s) + #self._lb_coords.setText( + # "\u23FA{:>}:{:>6.0f} {:<.0f}" + # "\u23FA{:>}:{:>6.0f} {:<.0f}" + # "\u23FA{:>}:{:<.0f}" + # "\u23FA{:>}:{:>6.1f} {:<.1f} \u00B5" + # "\u23FA{:>}:{:>7.3f} {:<.3f} mm".format( + # "Beam at", bx, by, + # "Pixel coord ", x, y, + # "PPM", ppm, + # "Distance to beam", 1000 * dx, 1000 * dy, + # "Stage", fx, fy, + # ) + #) def cb_mouse_click(self, event): #_log.debug("{}".format(event)) @@ -983,7 +995,8 @@ class WndSwissMx(QMainWindow, Ui_MainWindow): #_log.debug(f"vb pos {self.vb.mapFromScene(p)}") #pixel position on the scene (including black frame) #for o in self.vb.childGroup.childItems(): # _log.debug(f"{type(o)} pos {o.mapFromScene(p)}") #pixel position on the scene (including black frame) - _log.debug(f"currentItem:{event.currentItem}") + + #_log.debug(f"currentItem:{event.currentItem}") task = self.active_task() if task==TASK_SETUP_GEOMETRY_CALIB: self.mouse_click_event_geometry_calib(event) @@ -1270,7 +1283,11 @@ class WndSwissMx(QMainWindow, Ui_MainWindow): import PIL.Image #img=PIL.Image.fromarray(cam.pic.astype(np.uint8)) try: - pic=cam.pic + pic=cam._pic + mx=pic.max() + if pic.max()>255: + scl=2**int(round(np.log2(mx)-8)) + pic=np.array(pic/scl,dtype=np.uint8) except AttributeError: sim=app._camera._sim pic=cam._sim['imgSeq'][sim['imgIdx']]