From c0ded6f6834ae5282965aed5d712b1c4fe73e752 Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Thu, 21 Nov 2024 12:22:10 +0100 Subject: [PATCH] hit return motion code gen --- python/hit_return_evaluation.py | 35 +++++----- python/shapepath.py | 114 +++++++++++++++++++++++++++++--- 2 files changed, 124 insertions(+), 25 deletions(-) diff --git a/python/hit_return_evaluation.py b/python/hit_return_evaluation.py index 3501a9f..3d97fa8 100755 --- a/python/hit_return_evaluation.py +++ b/python/hit_return_evaluation.py @@ -20,13 +20,13 @@ import matplotlib.pyplot as plt class HitReturnEval: def initPlt(self,grid): - cx,cy=grid['count'] + nx,ny=grid['count'] fig=plt.figure() ax = fig.add_subplot(1,1,1) #ax.invert_xaxis() ax.invert_yaxis() #hl=ax[0].plot(x, y, color=col) - pts=np.array(((0,0),(cx-1,0),(cx-1,cy-1),(0,cy-1),(0,0))) + pts=np.array(((0,0),(nx-1,0),(nx-1,ny-1),(0,ny-1),(0,0))) h3=ax.plot(pts[:,0],pts[:,1],'g-') h2=ax.plot(pts[:,0],pts[:,1],'y-') h1=ax.plot(pts[:,0],pts[:,1],'r.') @@ -53,11 +53,14 @@ class HitReturnEval: #vgrid: grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0} #vp0: x/y koordinates of well to start (default 0,0) #vsz: size of wells to cycle (must be 2n x m) - grid=kwargs['grid'] - ox, oy=grid['pos'] #origin position in um (or counts if scaled) - px, py=grid['pitch'] #pitch to next position in um (or 1 if scaled) - cx,cy=grid['count'] #total count of wells - rx,ry=kwargs['sz'] #region size of wells (sign shows direction) + g=kwargs['grid'] + ox,oy=g['pos'] #origin position in um (or counts if scaled) + px,py=g['pitch'] #pitch to next position in um (or 1 if scaled) + nx,ny=g['count'] #total count of wells + sx,sy=kwargs['ssz'] #section size (in wells) + #smv=kwargs['smv'] #time(in num of shots) to move to next section (horiz/vert) + #swait=kwargs['smv'] #wait after section for motion trigger. swait=0:never wait + #fast y (up/down) slow x(left/right) # 8 # 7 8 8 @@ -79,22 +82,22 @@ class HitReturnEval: print(f'{x0+x1} {y0+y1} ({dx}|{dy}|{n})') mv.append((x0+x1+.1*n,y0+y1+.1*n,n)) self.updatePlt(mv) - if y0==ry-1: + if y0==sy-1: if dy==1: #(1) dx,dy=1,0 else: dx,dy=0,-1#(2) - elif y0==1 and x0 section for motion trigger. swait=0:never wait ''' #scan=0 # snake motion X fast, Y slow scan=1 # snake motion Y fast, X slow (default) @@ -751,7 +751,7 @@ class ShapePath(MotionBase): except AttributeError: _log.warning('missing motion sync code!') # this uses Coord[1].Tm and limits with MaxSpeed - if mode in (1,3,4,5): #### pvt motion + if mode in (1,3,4,5,6): #### pvt motion if mode!=5: pt2pt_time=meta['pt2pt_time']=meta['fel_per'] scale=kwargs.get('scale', 1.) @@ -802,7 +802,7 @@ class ShapePath(MotionBase): plt.show(block=False) pv[1:-1, (2, 3)]*=CoordFeedTime #scaling for Deltatau prg+=' linear abs\n X%g Y%g\n' % tuple(pv[0, (0,1)]) - else: # mode==(4,5): #### pvt motion, short code using grid parameters + elif mode in (4,5): #### pvt motion, short code using grid parameters g=kwargs['grid'] nx, ny=g['count'] xx, yy=np.meshgrid(range(nx), range(ny)) @@ -827,6 +827,22 @@ class ShapePath(MotionBase): px, py=(1,1) self.mot_pts=(np.hstack((pt, np.ones((pt.shape[0], 1))))*np.asmatrix(trf)).A # pt*trf #prg+=f' linear abs\n X{ox:g} Y{oy:g}\n' + prg+=f' linear abs\n X{ox-px:g} Y{oy-py:g}\n' # start one position out of grid + else: #mode==6: #### pvt motion, hit and return using grid parameters + g=kwargs['grid'] + try: + trf=kwargs['trf'] + except KeyError as e: + ox, oy=g['pos'] + px, py=g['pitch'] + else: + ox, oy=(0,0) + px, py=(1,1) + nx,ny=g['count'] #total count of wells + sx,sy=kwargs['ssz'] #section size (in wells) + tmx,tmy=kwargs['smv'] #time(in num of shots) to move to next section (horiz/vert) + swait=kwargs['smv'] #wait after section for motion trigger. swait=0:never wait + prg+=f' linear abs\n X{ox-px:g} Y{oy-py:g}\n' # start one position out of grid prg+=' dwell 10\n' try: prg+=self.sync_prg @@ -897,7 +913,6 @@ class ShapePath(MotionBase): X({ox}+L1*{px}):{0:g} Y({oy}+L0*{py}):{0:g} ''' - elif mode==5: if scan==0: raise Exception('scan=0 not supported') @@ -988,7 +1003,76 @@ enable plc 2 while(Sys.Udata[2]==Sys.Udata[1]){{}};Sys.Udata[2]=Sys.Udata[1] // wait motion trigger ''' + elif mode==6: + if scan==0: + raise Exception('scan=0 not supported') + pass + else: # scan=1 + vsx=px/(pt2pt_time)*scale*CoordFeedTime # scaling for Deltatau + vsy=py/(pt2pt_time)*scale*CoordFeedTime # scaling for Deltatau + #variables + m,x0,y0,n,dx,dy,x1,y1,t,vx,vy=map(lambda x: f'L{x}',range(11)) + prg+=f'''\ + //hit-and-return pvt motion + {m}=0 + {x0}=0;{y0}=-1;{n}=0 // counter well in region + {dx}=0;{dy}=1 // motion pitch + {x1}=0;{y1}=0 // counter region start + {t}=1 // motion pvt tome scaling + pvt{pt2pt_time} abs + while(1){{ + {x0}+={dx};{y0}+={dy} + //send 1"A:move(%d) X%g:%g Y%g:%g",{n},{ox}+{x0}+{x1}*{px},{dx},{oy}+{y0}+{y1}*{py},{dy} + X({ox}+({x0}+{x1})*{px}):({vx}) Y({oy}+({y0}+{y1})*{py}):({vy}) + if ({t}!=1){{ + pvt{pt2pt_time} abs;{t}=1 + }} + if ({y0}=={sy}-1){{ + if ({dy}==1){{ // (1) + {dx}=1;{dy}=0 + {vx}={vsx};{vy}=0 + }}else{{ + {dx}=0;{dy}=-1// (2) + {vx}=0;{vy}=-{vsy} + }} + }}else if ({y0}==1 && {x0}<{sx}-1){{ + if ({dy}==-1){{ // (3) + {dx}=1;{dy}=0 + {vx}={vsx};{vy}=0 + }}else{{ + {dx}=0;{dy}=1 // (4) + {vx}=0;{vy}={vsy} + }} + }}else if ({y0}==0){{ + if ({n}==1 && {x0}==1){{ // (7 or 8) + if ({x1}+2*{sx}<={nx}){{// (7) + {x1}+={sx} + {vx}={vsx};{vy}=0 + pvt{pt2pt_time*tmx} abs;{t}={tmx} + }}else if ({y1}+2*{sy}<={ny}){{// (8) + {x1}=0;{y1}+={sy} + {vx}=0;{vy}={vsy} + pvt{pt2pt_time*tmy} abs;{t}={tmy} + }}else{{ + break // finished whole grid + }} + //send 1"next regionA" + {x0}=0;{y0}=0;{n}=0 + {dx}=0;{dy}=0 + }}else if ({x0}==1){{ // (6) + {dx}=-1;{dy}=0;{n}+=1 + {vx}=-{vsx};{vy}=0 + }}else if ({x0}==0){{ // (0) + {dx}=0;{dy}=1 + {vx}=0;{vy}={vsy} + }}else{{ // (5) + {dx}=-1;{dy}=0 + {vx}=-{vsx};{vy}=0 + }} + }} + }} +''' else: raise ValueError('unsupported mode') #common code to repeat the motion multiple times @@ -1168,6 +1252,15 @@ if __name__=='__main__': num_pts=gp.points.shape[0] except AttributeError as e: num_pts=np.array(grid['count'], np.int32).prod() + if mode==6: + ssz=(4,5) # section size (in wells) + smv=(4-1,grid['count'][0]//2) # time(in num of shots) to move to next section (horiz/vert) + swait=0 # wait after section for motion trigger. swait=0:never wait + try: + num_pts=gp.points.shape[0] + except AttributeError as e: + num_pts=np.array(grid['count'], np.int32).prod() + if sp.comm: sp.setup_sync(verbose=args.verbose&0x40,timeOfs=0.03,timeCor=0.0005) @@ -1180,7 +1273,10 @@ if __name__=='__main__': elif mode==4: sp.setup_motion(fnPrg=fn+'.prg',scale=1.,cnt=1,dwell=100,mode=4,grid=grid) elif mode==5: - sp.setup_motion(fnPrg=fn+'.prg',scale=1.,cnt=1,dwell=100,mode=5,tmove=tmove, twait=twait, grid=grid) + sp.setup_motion(fnPrg=fn+'.prg',scale=1.,cnt=1,dwell=100,mode=5,grid=grid,tmove=tmove,twait=twait) + elif mode==6: + sp.setup_motion(fnPrg=fn+'.prg',scale=1.,cnt=1,dwell=100,mode=6,grid=grid,ssz=ssz,smv=smv,swait=swait) + _log.info('terurns just for testing');return else: raise(ValueError(f'unsupported mode:{mode}'))