diff --git a/pyqtUsrObj.py b/pyqtUsrObj.py index 47b5ed2..67cb8fe 100644 --- a/pyqtUsrObj.py +++ b/pyqtUsrObj.py @@ -301,8 +301,11 @@ class Path(UsrROI): a circle is plot at the path positions a cross is plot at the fiducial positions ''' - def __init__( self, pos=(0,0), path=np.array(((6,4),(16,24),(-5,7),(3,12))), fiducial=None, ficucialScale=5, **kwargs): + def __init__( self, pos=(0,0), size=(30,20), path=np.array(((6,4),(16,24),(-5,7),(3,12))), fiducial=None, ficucialScale=5, **kwargs): + self.code_gen=kwargs.pop('code_gen',0) trf=kwargs.pop('trf',None) + pg.ROI.__init__(self, pos, size, **kwargs) + self.szOrig=size if type(path)==list: path=np.array(path) if fiducial is None: @@ -310,12 +313,7 @@ class Path(UsrROI): else: if type(fiducial)==list: fiducial=np.array(fiducial) - all=np.vstack((fiducial,path)) - mn=all.min(0) - mx=all.max(0) - size=self.szOrig=mx-mn - pg.ROI.__init__(self, pos, size, **kwargs) if trf is not None: t=self.transform() t.setMatrix(trf[0][0], trf[0][1], 0, @@ -326,7 +324,7 @@ class Path(UsrROI): self._fiducial=fiducial self._path=path self._fidScl=ficucialScale - self._rect=r=QtCore.QRectF(mn[0]-5*ficucialScale, mn[1]-5*ficucialScale, size[0]+10*ficucialScale, size[1]+10*ficucialScale) + self._rect=r=QtCore.QRectF(0, 0, size[0], size[1]) self._qpath=qPth=QPolygonF() for pt in path: qPth.append(QPointF(*pt)) @@ -375,20 +373,37 @@ class Path(UsrROI): jsn= { '__class__':self.__class__.__name__, 'pos':tuple(self.pos()), + 'size':tuple(self.szOrig), + 'code_gen':self.code_gen, 'fiducial': self._fiducial.tolist(), - 'path': self._path.tolist(), - 'ficucialScale':self._fidScl + 'ficucialScale':self._fidScl, + 'path':self._path.tolist(), } - so=pg.Point(self.szOrig) - sn=self.size() trf=self.transform() - if not trf.isIdentity() or so!=sn: - scl=sn/so + if not trf.isIdentity(): #obj_info(trf) - trf=((trf.m11()*scl[0],trf.m12()*scl[0]),(trf.m21()*scl[1],trf.m22()*scl[1])) + trf=((trf.m11(),trf.m12()),(trf.m21(),trf.m22())) jsn['trf']=trf return jsn + def get_scan_param(self,mode=0x2): + 'returns scan parameters for scanning with deltatau. the format is as used for shapepath' + #mode=pvt + #param={'points':pts, 'mode':mode} + param={'points':self._path, 'code_gen': self.code_gen} + + t=self.transform() + p=np.array(self.pos()) + s=self.size()/self.szOrig + trf=np.array(((t.m11(),t.m12()),(t.m21(),t.m22()),(0,0))) + trf[2,:]=p # shift origin + #trf[:2, 0]*=s[0];trf[:2, 1]*=s[1] #scaling (before rotation shear) + trf[:2,:]=(trf[:2,:].T*s).T # same as np.asmatrix(np.diag(s))*trf[:2,:], trf[:2,:]*=s not working, scale before rot / shear + + # trf*'gridpos in um' -> motor pos in mm + param['trf']=trf + return param + class FixTargetFrame(UsrROI): '''fixed target frame''' tpl={ @@ -433,6 +448,7 @@ class FixTargetFrame(UsrROI): } def __init__( self, pos=(0,0), size=(100,100), tpl='test', dscr=None, **kwargs): + self.code_gen=kwargs.pop('code_gen',0) trf=kwargs.pop('trf',None) pg.ROI.__init__(self, pos, size, **kwargs) if trf is not None: @@ -524,6 +540,7 @@ class FixTargetFrame(UsrROI): '__class__':self.__class__.__name__, 'pos':tuple(self.pos()), 'size':tuple(self.size()), + 'code_gen':self.code_gen, 'dscr': self._dscr } trf=self.transform() @@ -533,8 +550,9 @@ class FixTargetFrame(UsrROI): jsn['trf']=trf return jsn - def get_scan_param(self,mode=0x2): + def get_scan_param(self): 'returns scan parameters for scanning with deltatau. the format is as used for shapepath' + mode=0x2 #default fast y axis grid=self._dscr['grid'] self._dscr['size'] #pos=np.array(self.pos()) @@ -553,7 +571,8 @@ class FixTargetFrame(UsrROI): pts=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float).transpose() #*pitch - param={'grid':grid, 'points':pts, 'mode':mode} + param={'grid':grid, 'points':pts, 'code_gen': self.code_gen} + t=self.transform() p=np.array(self.pos()) s=self.size()/self._dscr['size'] diff --git a/swissmx.py b/swissmx.py index ed7e7db..ea0447a 100755 --- a/swissmx.py +++ b/swissmx.py @@ -1421,8 +1421,9 @@ class WndSwissMx(QMainWindow, Ui_MainWindow): for go in cldLst: if type(go)==UsrGO.Fiducial: continue - if type(go)!=UsrGO.FixTargetFrame: - _log.warning(f'for now: ONLY FixTargetFrame are supported ->skipped:{go}') + t=type(go) + if t not in(UsrGO.FixTargetFrame,UsrGO.Path): + _log.warning(f'{t} not supported for FixTargetFrame ->skipped:{go}') continue try: param=go.get_scan_param() #points in coordinate system of ROI @@ -1431,23 +1432,19 @@ class WndSwissMx(QMainWindow, Ui_MainWindow): continue p=param['points'] trf=np.asmatrix(param['trf']*1000) #fix shear/rotation mm->um - pos=np.array(param['grid']['pos']) #in um - pitch=np.array(param['grid']['pitch']) #in um + trf[:,0]*=-1 #X axis has inverted sign ! + if t==UsrGO.FixTargetFrame: + pos=np.array(param['grid']['pos']) #in um + pitch=np.array(param['grid']['pitch']) #in um + m=np.hstack((p*pitch+pos,np.ones((p.shape[0],1)))) + p=(np.asmatrix(m)*trf).A + param['pts_trf']=p # transformed points + else: + m=np.hstack((p,np.ones((p.shape[0],1)))) + p=(np.asmatrix(m)*trf).A + param['pts_trf']=p # transformed points - #t=np.matrix((0,0,1)).T - #for i in range(p.shape[0]): - # t.A[:2,0]=pos+p[i,:]*pitch - # p[i,:]=(trf*t).A.ravel() - # Same but much faster ! - m=np.hstack((p*pitch+pos,np.ones((p.shape[0],1)))) - p=(np.asmatrix(m)*trf).A - - p[:,0]*=-1 #X axis has inverted sign ! - param['ptsTrf']=p # transformed points - param['numPts']=p.shape[0] - #param['points']=p - - # add up to 100 test fiducial + param['num_pts']=p.shape[0] vb=self.vb grp=self._goTracked mft=self._moduleFixTarget @@ -1475,9 +1472,6 @@ class WndSwissMx(QMainWindow, Ui_MainWindow): #_log.debug(f'step to 2nd point:{p[1,:]-p[0,:]}') #print('DEBUG: difference from point to point:') #print(np.diff(p, axis=0)) - #param['codeGen']=0 - param['codeGen']=1 - param['codeGen']=2 self.daq_collect(**param) elif task == TASK_GRID: @@ -2037,26 +2031,25 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) w,h=(30, 22) go=UsrGO.Grid((fx-w/2,fy-h/2), (w, h), (30, 22), .1) elif idx==5: - ofs=(0, 0); - width=10; - fidScl=.02 - fiducial=((-.2, -.2), (-.2, 2.4), (10.2, -.2), (10.2, 2.4)) + ofs=(.2, .2); width=10; fidScl=.02 + fiducial=((.1, .1), (.1, 2.7), (10.3, .1), (10.3, 2.7)) if param: p=json.loads('{'+param+'}') # "ofs":[10, 5],"width":200,"fidScl":0.5,"fiducial":[[18,7],[25,16],[70, 20]] locals().update(p) fiducial=np.array(fiducial) - gp=psi_device.shapepath.GenPath(); - gp.swissmx_points(ofs=ofs, width=width, flipy=True) - go=UsrGO.Path((fx-width/2, fy-1.2), gp.points, fiducial, fidScl) + gp=psi_device.shapepath.GenPath(); gp.swissmx_points(ofs=ofs, width=width, flipy=True) + sz=gp.points.max(0)+np.array(ofs)*2 + go=UsrGO.Path((fx-sz[0]/2, fy-sz[1]/2), sz, gp.points, fiducial, fidScl) elif idx==6: - ofs=(0, 0); width=10; fidScl=.02 - fiducial=((-.2, -.2), (-.2, 2.0), (10.2, -.2), (10.2, 2.0)) + ofs=(.2, .2); width=10; fidScl=.02 + fiducial=((.1, .1), (.1, 2.2), (10.3, .1), (10.3, 2.2)) if param: p=json.loads('{'+param+'}') # "ofs":[10, 5],"width":200,"fidScl":0.5,"fiducial":[[18,7],[25,16],[70, 20]] locals().update(p) fiducial=np.array(fiducial) - gp=psi_device.shapepath.GenPath();gp.swissfel_points(ofs=ofs, width=width,flipy=True) - go=UsrGO.Path((fx-width/2,fy-1.2), gp.points, fiducial, fidScl) + gp=psi_device.shapepath.GenPath(); gp.swissfel_points(ofs=ofs, width=width,flipy=True) + sz=gp.points.max(0)+np.array(ofs)*2 + go=UsrGO.Path((fx-sz[0]/2, fy-sz[1]/2), sz, gp.points, fiducial, fidScl) else: _log.error('index not handeled') @@ -2146,13 +2139,13 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) def daq_collect(self, **kwargs):# points, visualizer_method, visualizer_params): ''' kwargs: - codeGen: 0 pvt motion using ptsTrf - 1 pvt motion using trf and points - 2 pvt motion, compact grid code - grid: grid dictionary with orig, pitch, count - trf: transformation matrix - points: list of points without transformation - ptsTrf: list of points with transformation + code_gen: 0 pvt motion using ptsTrf + 1 pvt motion using trf and points + 2 pvt motion, compact grid code + grid: grid dictionary with orig, pitch, count + trf: transformation matrix + points: list of points without transformation + pts_trf: list of points with transformation ''' app = QApplication.instance() cfg = app._cfg @@ -2184,12 +2177,12 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) #dlg.setAutoClose(True) #dlg.show() dlg.setLabelText("Setup Gather/Sync");dlg+=5 - sp.setup_gather(kwargs['numPts']) + sp.setup_gather(kwargs['num_pts']) sp.setup_sync(verbose=sp.verbose&0x40, timeOfs=dt_misc['time_ofs'], timeCor=dt_misc['time_cor']) dlg.setLabelText("Download motion program");dlg+=5 - codeGen=kwargs['codeGen'] + codeGen=kwargs['code_gen'] if codeGen==0: - sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10, points=kwargs['ptsTrf']) + sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10, points=kwargs['pts_trf']) elif codeGen==1: sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10, points=kwargs['points']) elif codeGen==2: @@ -2201,17 +2194,23 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) # Z is in um -> therefore the offset must be multiplied with 1000 ! Z motor has opposite sign ! cz=f'{+p[0]:+.18g}X{-p[1]:+.18g}Y{-p[2]*1000:+.18g}' else: - trf=kwargs['trf'] cz=f'{+p[0]:+.18g}X{-p[1]:+.18g}Y{-p[2]*1000:+.18g}' except AttributeError: cz='0' - if codeGen==0: - fx='X';fy='Y' - else: - trf=kwargs['trf']*1000#fix shear/rotation mm->um - fx=f'{trf[0,0]:+.18g}X{trf[1,0]:+.18g}Y{trf[2,0]:+.18g}' - fy=f'{trf[0,1]:+.18g}X{trf[1,1]:+.18g}Y{trf[2,1]:+.18g}' _log.warning('no plane fitting done. z does not move') + + trf=kwargs['trf']*1000 # fix shear/rotation mm->um + trf[:, 0]*=-1 # X axis has inverted sign ! + if codeGen==0: + fx='X';fy='Y' + else: + fx=f'{trf[0,0]:+.18g}X{trf[1,0]:+.18g}Y{trf[2,0]:+.18g}' + fy=f'{trf[0,1]:+.18g}X{trf[1,1]:+.18g}Y{trf[2,1]:+.18g}' + + print(f'pts_trf[0,:]={kwargs["pts_trf"][0, :]}') + print(f'points[0,:]={kwargs["points"][0, :]}') + print(f'trf=\n{trf}') + sp.setup_coord_trf(fx, fy, cz) # reset to shape path system try: