From 158150a95412fdeb4754bd3f2de0d3bc4729899d Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Tue, 20 Sep 2022 12:33:41 +0200 Subject: [PATCH] work on config, fiducial, autofocus --- app_config.py | 128 ++++++++++++++++++++++---------------------------- geometry.py | 2 +- swissmx.py | 33 ++++++------- 3 files changed, 73 insertions(+), 90 deletions(-) diff --git a/app_config.py b/app_config.py index 33b04c6..5d40194 100644 --- a/app_config.py +++ b/app_config.py @@ -44,6 +44,9 @@ class AppCfg(QSettings): GEO_CAM_PARAM="geometry/cam_param" GEO_CAM_TRF="geometry/cam_trf" + GEO_FND_FID="geometry/find_fiducial" + GEO_AUTOFOC="geometry/autofocus" + WINDOW_GEOMETRY="window/geometry" WINDOW_SPLITTER="window/splitter" WINDOW_STATE= "window/state" @@ -81,82 +84,57 @@ class AppCfg(QSettings): #set default keys if not existing + dflt=[] + if AppCfg.GBL_MISC not in keys: + dflt.append((AppCfg.GBL_MISC,{'img_trace_len':4})) if AppCfg.GBL_DEV_PREFIX not in keys: - _log.warning(f'{AppCfg.GBL_DEV_PREFIX} not defined. set default') - self.setValue(AppCfg.GBL_DEV_PREFIX, ['SAR-EXPMX','SARES30-ESBMX']) #prefix deltatau,smaract - + dflt.append((AppCfg.GBL_DEV_PREFIX, ['SAR-EXPMX','SARES30-ESBMX'])) if AppCfg.GEO_BEAM_SZ not in keys: - _log.warning(f'{AppCfg.GEO_BEAM_SZ} not defined. set default') - self.setValue(AppCfg.GEO_BEAM_SZ, [30.2, 25.6]) #([40, 20) -> tuples are not supported natively - + dflt.append((AppCfg.GEO_BEAM_SZ, [30.2, 25.6])) if AppCfg.GEO_BEAM_POS not in keys: - _log.warning(f'{AppCfg.GEO_BEAM_POS} not defined. set default') - self.setValue(AppCfg.GEO_BEAM_POS, [23.4, -54.2]) # beam position relativ to optical center in mm - + dflt.append((AppCfg.GEO_BEAM_POS, [23.4, -54.2])) + if AppCfg.GEO_FND_FID not in keys: + dflt.append((AppCfg.GEO_FND_FID, {'sz':101, 'brd':8, 'pitch':120, 'mode':0})) + if AppCfg.GEO_AUTOFOC not in keys: + dflt.append((AppCfg.GEO_AUTOFOC, {'range':.4, 'vel':0.3, 'steps':40, 'mode':0})) + if AppCfg.GEO_OPT_CTR not in keys: + dflt.append((AppCfg.GEO_OPT_CTR, np.array([603.28688025, 520.01112846]) )) + if AppCfg.GEO_CAM_TRF not in keys: + dflt.append((AppCfg.GEO_CAM_TRF, np.array(((-1, 0, 0), (0, -1, 0), (0, 0, 1))) )) if AppCfg.GEO_PIX2POS not in keys: - _log.warning(f'{AppCfg.GEO_PIX2POS} not defined. use default') - #lut_pix2pos=(np.array([1., 200., 400., 600., 800., 1000.]), - # np.array([[[ 2.42827273e-03, -9.22117396e-05], - # [-1.10489804e-04, -2.42592492e-03]], - # [[ 1.64346103e-03, -7.52341417e-05], - # [-6.60711165e-05, -1.64190224e-03]], - # [[ 9.91307639e-04, -4.02008751e-05], - # [-4.23878232e-05, -9.91563507e-04]], - # [[ 5.98443038e-04, -2.54046255e-05], - # [-2.76831563e-05, -6.02738142e-04]], - # [[ 3.64418977e-04, -1.41389267e-05], - # [-1.55708176e-05, -3.66233567e-04]], - # [[ 2.16526433e-04, -8.23070130e-06], - # [-9.29894004e-06, -2.16842976e-04]]])) # rough data for binning=1,1 z=np.array((1.0, 200.0, 400.0, 600.0, 800.0, 1000.0)) t1=np.array(([1, 0.0000], [0.0000, -1])).reshape(1, -1) t2=np.array((0.001214,0.000821,0.000495,0.000299,0.000182,0.000108)).reshape(-1, 1) trf=(t1*t2).reshape((-1, 2, 2)) lut_pix2pos=(z, trf) - - self.setValue(AppCfg.GEO_PIX2POS, lut_pix2pos) - - if AppCfg.GEO_OPT_CTR not in keys: - _log.warning(f'{AppCfg.GEO_OPT_CTR} not defined. use default') - opt_ctr=np.array([603.28688025, 520.01112846]) - self.setValue(AppCfg.GEO_OPT_CTR, opt_ctr) - - if AppCfg.GEO_CAM_TRF not in keys: - _log.warning(f'{AppCfg.GEO_CAM_TRF} not defined. use default') - trf=np.array(((-1,0,0),(0,-1,0),(0,0,1))) - self.setValue(AppCfg.GEO_CAM_TRF, trf) + dflt.append((AppCfg.GEO_PIX2POS, lut_pix2pos)) if AppCfg.DT_HOST not in keys: - _log.warning(f'{AppCfg.DT_HOST} not defined. use default') - self.setValue(AppCfg.DT_HOST,'SAR-CPPM-EXPMX1') - #self.setValue(AppCfg.DT_HOST,'localhost:10001:10002') + dflt.append((AppCfg.DT_HOST, 'SAR-CPPM-EXPMX1')) + if AppCfg.DT_MISC not in keys: + dflt.append((AppCfg.DT_MISC,{'show_plots':True, 'vel_scl':1.0, 'pt2pt_time':10.0, 'sync_mode':1, 'sync_flag':3, 'verbose':0xff})) + + for k,v in dflt: + _log.warning(f'{k} not defined. use default') + self.setValue(k,v) #if AppCfg.ACTIVATE_PULSE_PICKER not in keys: # self.setValue(AppCfg.ACTIVATE_PULSE_PICKER, False) - #if AppCfg.SKIP_ESCAPE_TRANSITIONS_IF_SAFE not in keys: # self.setValue(AppCfg.SKIP_ESCAPE_TRANSITIONS_IF_SAFE, False) def sync(self): super(AppCfg, self).sync() - #import numpy as np - #a=np.array(((1,2,3),(4,5,6))) - #self._yamlFn=fn=os.path.expanduser('~/.config/PSI/SwissMX.yaml') - #_yaml = [{'name': 'John Doe', 'occupation': 'gardener'}, - # {'name': 'Lucy Black', 'occupation': 'teacher'}] - #_yaml = {'name': 'John Doe', 'occupation': 'gardener','A':(1,2,3),'B':{1,2,3},'C': {1:(1,2,3),2:'df',3:'dddd'},4:a } - #with open(self._yamlFn, 'w') as f: - # data = yaml.dump(_yaml, f) - # print(data) 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,AppCfg.GEO_CAM_TRF): val=json.dumps(val, cls=MyJsonEncoder) - elif key in (AppCfg.GBL_MISC, + elif key in (AppCfg.GBL_MISC, # for all these keys convert to json and change " to ' AppCfg.GEO_CAM_PARAM, + AppCfg.GEO_FND_FID, AppCfg.GEO_AUTOFOC, AppCfg.DFT_POS_DET,AppCfg.DFT_POS_PST,AppCfg.DFT_POS_COL,AppCfg.DFT_POS_BKLGT, AppCfg.DT_MISC): val=json.dumps(val, cls=MyJsonEncoder) @@ -178,23 +156,18 @@ class AppCfg(QSettings): val=np.array(val) elif key in (AppCfg.GBL_MISC, AppCfg.GEO_CAM_PARAM, + AppCfg.GEO_FND_FID, AppCfg.GEO_AUTOFOC, AppCfg.DFT_POS_DET,AppCfg.DFT_POS_PST,AppCfg.DFT_POS_COL,AppCfg.DFT_POS_BKLGT, AppCfg.DT_MISC): if val is not None: val=val.replace("'",'"') val=json.loads(val) # , object_hook=MyJsonDecoder) else: - if key==AppCfg.DT_MISC: - val={'show_plots': True, 'vel_scl': 1.0, 'pt2pt_time': 10.0,'sync_mode':1,'sync_flag':3,'verbose':0xff} - elif key==AppCfg.GBL_MISC: - val={'img_trace_len':4,'af_range':1,'af_steps':10} - else: - val={} - elif key in (AppCfg.GEO_BEAM_SZ,AppCfg.GEO_BEAM_POS,): - val=np.array(tuple(map(float, val))) - elif key in (AppCfg.GEO_OPT_CTR): + val={} + elif key in (AppCfg.GEO_BEAM_SZ,AppCfg.GEO_BEAM_POS,AppCfg.GEO_OPT_CTR): val=np.array(tuple(map(float, val))) return val + #@property #def value(self): # return super(AppCfg, self).value @@ -225,9 +198,12 @@ class WndParameter(QMainWindow): #GEO_PIX2POS #GEO_BEAM_POS #GEO_CAM_PARAM - gbl_misc = cfg.value(AppCfg.GBL_MISC) + gbl_misc = cfg.value(AppCfg.GBL_MISC) gbl_dev_prefix = cfg.value(AppCfg.GBL_DEV_PREFIX) geo_beam_sz = cfg.value(AppCfg.GEO_BEAM_SZ) + geo_af = cfg.value(AppCfg.GEO_AUTOFOC) + geo_fnd_fid = cfg.value(AppCfg.GEO_FND_FID) + dft_pos_pst = cfg.value(AppCfg.DFT_POS_PST) dft_pos_col = cfg.value(AppCfg.DFT_POS_COL) dft_pos_bklgt = cfg.value(AppCfg.DFT_POS_BKLGT) @@ -269,6 +245,7 @@ verbose bits: 0x40 print sync details ''' + params=[ {'name':'various', 'type':'group','expanded':False, 'children':[ {'name':AppCfg.GBL_DEV_PREFIX, 'title':'device prefix', 'type':'group', 'expanded':False, 'children':[ @@ -277,8 +254,6 @@ verbose bits: ]}, {'name':AppCfg.GBL_MISC, 'title':'miscellaneous', 'type':'group', 'children':[ {'name':'img_trace_len', 'value':gbl_misc['img_trace_len'], 'type':'int', 'tip':tip_sync_flag}, - {'name':'af_range', 'value':gbl_misc['af_range'], 'type':'float', 'limits':(0 ,3 ),'step':0.05,'suffix':'mm','decimals':3,'tip':'autofocus range (-rng/2 mm..+rng/2 mm..'}, - {'name':'af_steps', 'value':gbl_misc['af_steps'], 'type':'int', 'limits':(0 ,50),'tip':'numbers of measurements in the range'}, #{'name':'verbose', 'value':gbl_misc['verbose'], 'type':'int', 'tip':tip_verbose}, ]}, # {'name':AppCfg.GEO_CAM_TRF, 'value':cfg.value(AppCfg.GEO_CAM_TRF), 'type':'str'}, @@ -297,17 +272,29 @@ verbose bits: {'name':'roi', 'value':geo_cam_param.get('roi'), 'type':'str'}, {'name':'mono8', 'value':geo_cam_param.get('mono8'), 'type':'bool'}, ]}, + {'name':AppCfg.GEO_FND_FID, 'title':'find fiducial parameters', 'type':'group', 'expanded':True, 'children':[ + {'name':'size', 'value':geo_fnd_fid['sz'], 'type':'float', 'step':1, 'suffix':'um'}, + {'name':'border', 'value':geo_fnd_fid['brd'], 'type':'float', 'step':1, 'suffix':'um'}, + {'name':'pitch', 'value':geo_fnd_fid['pitch'], 'type':'float', 'step':1, 'suffix':'um','tip':'feature not yet used!'}, + {'name':'mode', 'value':geo_fnd_fid['mode'], 'type':'int', 'step':1,'tip':'feature not yet used!'}, + ]}, + {'name':AppCfg.GEO_AUTOFOC, 'title':'autofocus parameters', 'type':'group', 'expanded':True, 'children':[ + {'name':'range', 'value':geo_af['range'], 'type':'float', 'limits':(0 ,3 ),'step':0.05,'suffix':'mm','decimals':3,'tip':'autofocus range (-rng/2 mm..+rng/2 mm..'}, + {'name':'velocity', 'value':geo_af['vel'] , 'type':'float', 'limits':(0 ,2), 'step':0.05,'suffix':'mm/s','decimals':3}, + {'name':'steps', 'value':geo_af['steps'], 'type':'int', 'limits':(0 ,50),'tip':'numbers of measurements in the range'}, + {'name':'mode', 'value':geo_af['mode'], 'type':'int', 'step':1,'tip':'feature not yet used!'}, + ]}, ]}, {'name': AppCfg.DFT_POS_PST, 'title':'post sample tube reference positions','type':'group','expanded':False,'children':[ - {'name':'x_in_us', 'title':'in X upstream' ,'value':dft_pos_pst.get('x_in_us' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, - {'name':'y_in_us', 'title':'in Y upstream' ,'value':dft_pos_pst.get('y_in_us' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, - {'name':'x_in_ds', 'title':'in X downstream' ,'value':dft_pos_pst.get('x_in_ds' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, - {'name':'y_in_ds', 'title':'in Y downstream' ,'value':dft_pos_pst.get('y_in_ds' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, - {'name':'x_out_delta','title':'out X delta' ,'value':dft_pos_pst.get('x_out_delta',0),'type':'float','limits':(-32,32),'step':0.1,'decimals':5,'suffix':' mm'}, - {'name':'y_out_delta','title':'out Y delta' ,'value':dft_pos_pst.get('y_out_delta',0),'type':'float','limits':(-32,32),'step':0.1,'decimals':5,'suffix':' mm'}, - {'name':'z_in', 'title':'in Z' ,'value':dft_pos_pst.get('z_in' ,0),'type':'float','limits':(-8 ,5 ),'step':0.1,'decimals':5,'suffix':' mm'}, - {'name':'z_out', 'title':'out Z' ,'value':dft_pos_pst.get('z_out' ,0),'type':'float','limits':(-8 ,5 ),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'x_in_us', 'title':'in X upstream', 'value':dft_pos_pst.get('x_in_us' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'y_in_us', 'title':'in Y upstream', 'value':dft_pos_pst.get('y_in_us' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'x_in_ds', 'title':'in X downstream', 'value':dft_pos_pst.get('x_in_ds' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'y_in_ds', 'title':'in Y downstream', 'value':dft_pos_pst.get('y_in_ds' ,0),'type':'float','limits':(-45,15),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'x_out_delta','title':'out X delta', 'value':dft_pos_pst.get('x_out_delta',0),'type':'float','limits':(-32,32),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'y_out_delta','title':'out Y delta', 'value':dft_pos_pst.get('y_out_delta',0),'type':'float','limits':(-32,32),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'z_in', 'title':'in Z', 'value':dft_pos_pst.get('z_in' ,0),'type':'float','limits':(-8 ,5 ),'step':0.1,'decimals':5,'suffix':' mm'}, + {'name':'z_out', 'title':'out Z', 'value':dft_pos_pst.get('z_out' ,0),'type':'float','limits':(-8 ,5 ),'step':0.1,'decimals':5,'suffix':' mm'}, {'name':'set_in', 'title':'use current position as "in"', 'type':'action'}, {'name':'set_out', 'title':'use current position as "out"', 'type':'action'}, ]}, @@ -330,7 +317,7 @@ verbose bits: {'name':'set_out', 'title':'use current position as "out"', 'type':'action'}, ]}, {'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':'show_plots', 'value':dt_misc['show_plots'], 'type':'bool', 'title':'show plots after collection'}, {'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)"}, @@ -348,7 +335,6 @@ verbose bits: # ]}, #]}, ] - self._p=p=Parameter.create(name='params', type='group', children=params) p.sigTreeStateChanged.connect(lambda a,b: self.cb_change(a,b)) # Too lazy for recursion: diff --git a/geometry.py b/geometry.py index 7d5e805..2f7e362 100755 --- a/geometry.py +++ b/geometry.py @@ -456,7 +456,7 @@ class autofocus: mtr[idx,:]=(p,m) _log.debug(f'{args} {kwargs} p:{p} mtr={m}') print(p) - if abs(p-self._pDst)<0.01: + if abs(p-self._pDst)<0.01 or idx>mtr.shape[0]: _log.debug(f'DONE->{self._idx}') del cam.process print(mtr[:idx,:]) diff --git a/swissmx.py b/swissmx.py index e572256..4216c21 100755 --- a/swissmx.py +++ b/swissmx.py @@ -1611,37 +1611,34 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) def cb_autofocus(self): app=QApplication.instance() - cfg=app._cfg + cfg=app._cfg.value(AppCfg.GEO_AUTOFOC) geo=app._geometry #geo.autofocus(app._camera, self.tweakers['base_z'],rng=(-1, 1), n=30,saveImg=True) - misc=cfg.value(AppCfg.GBL_MISC) - af_range=misc['af_range'] - n=misc['af_steps'] + af_range=cfg['range'] + n=cfg['steps'] + vel=cfg['vel'] rng=(-af_range/2, af_range/2) #geo.autofocus(app._camera, self.tweakers['base_z'],rng, n,dlg) - af= geometry.autofocus(app._camera, self.tweakers['base_z']) + af=geometry.autofocus(app._camera, self.tweakers['base_z']) # af.run(rng, n, dlg) - #with pg.ProgressDialog('Progress', 0, n) as dlg: - af.run_continous(rng=(-.5, .5), velo=0.3) + af.run_continous(rng=rng, velo=vel) def cb_find_fiducial(self): app=QApplication.instance() geo=app._geometry - #geo.autofocus(app._camera, self.tweakers['base_z'],rng=(-1, 1), n=30,saveImg=True) - pos,corr=geo.find_fiducial(app._camera, sz=(210,210),brd=(20,20)) + cfg=app._cfg.value(AppCfg.GEO_FND_FID) - fx=self.tweakers["fast_x"].get_rbv() - fy=self.tweakers["fast_y"].get_rbv() + scl=np.linalg.norm(geo.pos2pix((.001,0))) #pix/um + sz=int(cfg['sz']*scl) + brd=int(cfg['brd']*scl) + # sz=( 84, 84); brd=( 7, 7) # zoom 001 + # sz=(128, 128); brd=( 9, 9) # zoom 200 + # sz=(200, 200); brd=(13, 13) # zoom 400 + _log.debug(f'sz:{sz} brd:{brd}') + pos,corr=geo.find_fiducial(app._camera, sz=(sz,sz),brd=(brd,brd)) bz=self.tweakers["base_z"].get_rbv() - - #oc=geo._opt_ctr - #bm_pos=self._goBeamMarker.pos() - #bm_sz=self._goBeamMarker.size() - #pos_eu=geo.pix2pos(pos) - #pImg=pg.Point(self._goImg.mapFromScene(pos)) - #pTrk=pg.Point(self._goTracked.mapFromScene(pos)) pos_scn=self._goImg.mapToScene(pg.Point(pos)) pos_eu=self._goTracked.mapFromScene(pos_scn)