From 681d42dc2eb5a203c5579f2b53cef2dc6f9225b2 Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Wed, 10 Jan 2024 16:19:30 +0100 Subject: [PATCH] SFELPHOTON-927: Beamtime Feb24 --- Readme.md | 12 +-------- pyqtUsrObj.py | 68 ++++++++++++++++++++++++++------------------------- swissmx.py | 48 +++++++++++++++++++++++++++++------- 3 files changed, 75 insertions(+), 53 deletions(-) diff --git a/Readme.md b/Readme.md index 2257909..25a7b30 100644 --- a/Readme.md +++ b/Readme.md @@ -386,17 +386,6 @@ s.a. ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/Readme.md -> EVR - - - - - - - - - - - ----------------------------------- SCRATCH ----------------------------------- -0.952 @@ -547,3 +536,4 @@ test shapepath cd ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX ./shapepath.py --host=localhost:10001:10002 ``` + diff --git a/pyqtUsrObj.py b/pyqtUsrObj.py index 83ee2de..9fe187f 100644 --- a/pyqtUsrObj.py +++ b/pyqtUsrObj.py @@ -203,7 +203,7 @@ class Fiducial(UsrROI): def __repr__(self): ctr=self.ctr() - s=f'{self.__class__.__name__}:(ctr:{itr2str(ctr)}, size:{itr2str(self.size())}}}' + s=f'{self.__class__.__name__}:(ctr:{itr2str(ctr)}, size:{itr2str(self.size())})' return s def obj2json(self,encoder): @@ -219,8 +219,9 @@ class Fiducial(UsrROI): class Grid(UsrROI): '''a grid''' - def __init__( self, pos=(0,0), size=(30,20), cnt=(6,4), fiducialSize=.2, **kargs): - pg.ROI.__init__(self, pos, size, **kargs) + def __init__( self, pos=(0,0), size=(30,20), cnt=(6,4), fiducialSize=.2, **kwargs): + self._param=kwargs + pg.ROI.__init__(self, pos, size)#, **kwargs) self._cnt=cnt self._fidSz=fiducialSize self.addScaleHandle([1, 1], [0, 0]) @@ -258,7 +259,7 @@ class Grid(UsrROI): #p.drawRect(0, 0, 1, 1) def __repr__(self): - s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, cnt:{self._cnt}, fidSize:{self._fidSz}}}' + s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, cnt:{self._cnt}, fidSize:{self._fidSz}, param:{self._param})' return s def obj2json(self,encoder): @@ -269,27 +270,33 @@ class Grid(UsrROI): 'cnt':self._cnt, 'fiducialSize':self._fidSz } + jsn.update(self._param) 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' + scan=1 # snake motion Y fast, X slow (default) #pos=np.array(self.pos()) cnt=np.array(self._cnt,np.int32) sz=np.array(self.size()) pitch=sz/cnt xx, yy=np.meshgrid(range(cnt[0]), range(cnt[1])) - if mode&0x01: #modify x scaning forward backward each line + + + if scan==0: # snake motion X fast, Y slow for i in range(1,cnt[1],2): xx[i]=xx[i][::-1] - if mode&0x02: # modify y scaning forward backward each line + else: # scan==1 # snake motion Y fast, X slow (default) xx=xx.T yy=yy.T for i in range(1, cnt[0], 2): yy[i]=yy[i][::-1] - pts=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float64).transpose()*pitch #pts+=pos - return pts + param={'points':pts} + param.update(self._param) + assert(param.get('code_gen',0)==0) # this provides fully x,y motor coordinates + return param class Path(UsrROI): @@ -302,9 +309,9 @@ class Path(UsrROI): a cross is plot at the fiducial positions ''' 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._param=kwargs + pg.ROI.__init__(self, pos, size)#, **kwargs) self.szOrig=size if type(path)==list: path=np.array(path) @@ -365,8 +372,7 @@ class Path(UsrROI): p.drawLines(lh,lv) def __repr__(self): - s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, numFid:{self._fiducial.shape[0]}, numPts:{self._path.shape[0]}, ficucialScale:{self._fidScl}}}' - + s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, numFid:{self._fiducial.shape[0]}, numPts:{self._path.shape[0]}, ficucialScale:{self._fidScl}, param:{self._param})' return s def obj2json(self,encoder): @@ -374,11 +380,11 @@ class Path(UsrROI): '__class__':self.__class__.__name__, 'pos':tuple(self.pos()), 'size':tuple(self.szOrig), - 'code_gen':self.code_gen, 'fiducial': self._fiducial.tolist(), 'ficucialScale':self._fidScl, 'path':self._path.tolist(), } + jsn.update(self._param) trf=self.transform() if not trf.isIdentity(): #obj_info(trf) @@ -386,12 +392,8 @@ class Path(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=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 @@ -401,7 +403,8 @@ class Path(UsrROI): 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 + param={'points':self._path,'trf':trf} + param.update(self._param) return param class FixTargetFrame(UsrROI): @@ -448,9 +451,8 @@ 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) - assert(kwargs==dict()) + self._param=kwargs pg.ROI.__init__(self, pos, size)#, **kwargs) if trf is not None: t=self.transform() @@ -533,7 +535,7 @@ class FixTargetFrame(UsrROI): assert('unknown feducial type') def __repr__(self): - s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, dscr:{self._dscr}}}' + s=f'{self.__class__.__name__}:(pos:{itr2str(self.pos())}, size:{itr2str(self.size())}, dscr:{self._dscr}, param:{self._param})' return s def obj2json(self,encoder): @@ -541,9 +543,9 @@ class FixTargetFrame(UsrROI): '__class__':self.__class__.__name__, 'pos':tuple(self.pos()), 'size':tuple(self.size()), - 'code_gen':self.code_gen, - 'dscr': self._dscr + 'dscr': self._dscr, } + jsn.update(self._param) trf=self.transform() if not trf.isIdentity(): #obj_info(trf) @@ -553,7 +555,7 @@ class FixTargetFrame(UsrROI): def get_scan_param(self): 'returns scan parameters for scanning with deltatau. the format is as used for shapepath' - scan=0x2 #default fast y axis + scan=1 # snake motion Y fast, X slow (default) grid=self._dscr['grid'] self._dscr['size'] #pos=np.array(self.pos()) @@ -561,10 +563,10 @@ class FixTargetFrame(UsrROI): #pos =np.array(grid['pos'],np.float64) #pitch=np.array(grid['pitch'],np.float64) xx, yy=np.meshgrid(range(cnt[0]), range(cnt[1])) - if scan&0x01: #modify x scaning forward backward each line + if scan==0: # snake motion X fast, Y slow for i in range(1,cnt[1],2): xx[i]=xx[i][::-1] - if scan&0x02: # modify y scaning forward backward each line + else: # scan==1 # snake motion Y fast, X slow (default) xx=xx.T yy=yy.T for i in range(1, cnt[0], 2): @@ -572,8 +574,6 @@ class FixTargetFrame(UsrROI): pts=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float64).transpose() #*pitch - param={'grid':grid, 'points':pts, 'code_gen': self.code_gen} - # TODO: simplify !!! t=self.transform() #obj_info(t) p=np.array(self.pos()) @@ -582,14 +582,16 @@ class FixTargetFrame(UsrROI): trf[2,:]=p # shift origin 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 - pos=np.array(param['grid']['pos']) # in um - pitch=np.array(param['grid']['pitch']) # in um + pos=np.array(grid['pos']) # in um + pitch=np.array(grid['pitch']) # in um trf2=np.asmatrix(np.identity(3)) trf2[:, :2]=trf trf2*=np.asmatrix(((1000, 0, 0), (0, 1000, 0), (0, 0, 1))) trf3=np.asmatrix(((pitch[0], 0, 0), (0, pitch[1], 0), (pos[0], pos[1], 1))) trf=(trf3*trf2)[:, :2] - param['trf']=trf + param={'grid':grid, 'points':pts, 'trf':trf} + param.update(self._param) + # trf*'gridpos' -> motor pos in mm # {'pos': [2080, 2080], 'pitch': [120, 120], 'count': [162, 162]} #np.array((0,0,1))*trf grid 0,0 (top left) diff --git a/swissmx.py b/swissmx.py index 8458b56..73500b5 100755 --- a/swissmx.py +++ b/swissmx.py @@ -1992,7 +1992,7 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) mft.setAccessibleName(TASK_FIX_TARGET) self._tabs_daq_methods.setCurrentWidget(mft) #set this as the active tabs - mft._cbType.addItems(["Fiducial", "FixTarget(12.5x12.5)", "FixTarget(23.0x23.0)", "FixTarget()", "Grid()", "SwissMX()", "SwissFEL()"]) + mft._cbType.addItems(["Fiducial", "FixTarget(12.5x12.5)", "FixTarget(23.0x23.0)", "FixTarget(test)", "Grid()", "SwissMX()", "SwissFEL()"]) mft._btnAdd.clicked.connect(self.module_fix_target_add_obj) mft._btnDelAll.clicked.connect(self.module_fix_target_del_all_obj) mft._btnFit.clicked.connect(self.module_fix_target_fit_fiducial) @@ -2110,15 +2110,38 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) #bm_pos_eu=self._goBeamMarker._pos_eu #bm_size_eu=self._goBeamMarker._size_eu try: - pLst=param.split(',') - pStr='{' + #parse the parameters: 'key:value [,key:value]' + # as key value separator : and = are allowed + #examples: + #Fiducial: + # no param + #FixTarget(12.5x12.5), FixTarget(23.0x23.0), FixTarget(test): + # code_gen:2 + # code_gen=3 | tmove=10 | twait=30 + #Grid(): + # size:(30, 20) + # cnt:(30, 22) + # fiducialSize:0.1 + #SwissMX(): + # ofs:(.2, .2) + # width:10 + # fidScl:.02 + # fiducial:((.1, .1), (.1, 2.7), (10.3, .1), (10.3, 2.7)) + #SwissFEL(): + # ofs:(.2, .2) + # width:10 + # fidScl:.02 + # fiducial:((.1, .1), (.1, 2.2), (10.3, .1), (10.3, 2.2)) + + pLst=param.split('|') + pStr=list() for p in pLst: if not p: continue m=re.match('\s*(.*?)\s*[=:]\s*(.*)\s*', p) k, v=m.groups() v=v.replace('(', '[').replace(')', ']') - pStr+=f'"{k}":{v}' - pStr+='}' + pStr.append(f'"{k}":{v}') + pStr='{'+','.join(pStr)+'}' param=json.loads(pStr) # "ofs":[10, 5],"width":200,"fidScl":0.5,"fiducial":[[18,7],[25,16],[70, 20]] except json.decoder.JSONDecodeError as e: _log.error(f'{e}:{param}') @@ -2162,9 +2185,9 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) fidScl=param.pop('fidScl',.02) fiducial=param.pop('fiducial',((.1, .1), (.1, 2.2), (10.3, .1), (10.3, 2.2))) fiducial=np.array(fiducial) - gp=psi_device.shapepath.GenPath(); gp.swissfel(ofs=ofs, width=width,flipy=True,**param) + gp=psi_device.shapepath.GenPath(); gp.swissfel(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) + go=UsrGO.Path((fx-sz[0]/2, fy-sz[1]/2), sz, gp.points, fiducial, fidScl,**param) else: _log.error('index not handeled') @@ -2258,6 +2281,11 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) code_gen: 0 pvt motion using ptsTrf 1 pvt motion using trf and points 2 pvt motion, compact grid code + 3 pvt motion, compact grid code move and wait + tmove: time to move + twait: time to wait + + grid: grid dictionary with orig, pitch, count trf: transformation matrix points: list of points without transformation @@ -2301,7 +2329,7 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) #dlg.show() dlg.setLabelText("Setup Gather/Sync");dlg+=5 num_pts=kwargs['num_pts'] - code_gen=kwargs['code_gen'] + code_gen=kwargs.get('code_gen',0) sp.setup_gather(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 @@ -2310,7 +2338,9 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch) elif code_gen==1: sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10, points=kwargs['points'],trf=kwargs['trf']) elif code_gen==2: - sp.setup_motion(fnPrg=fn+'.prg', mode=4, scale=1., dwell=10, grid=kwargs['grid'],trf=kwargs['trf']) + sp.setup_motion(fnPrg=fn+'.prg', mode=4, scale=1., dwell=10, grid=kwargs['grid'], trf=kwargs['trf']) + elif code_gen==3: + sp.setup_motion(fnPrg=fn+'.prg', mode=5, dwell=10, tmove=kwargs['tmove'] ,twait=kwargs['twait'], grid=kwargs['grid'],trf=kwargs['trf']) try: p=geo._fitPlane # TODO: Cleanup