try to cleanup stuff(1)

This commit is contained in:
2024-11-27 15:23:52 +01:00
parent 9888377e13
commit 54ba58f657

View File

@@ -192,7 +192,8 @@ class DebugPlot:
def plot_points(pts): def plot_points(pts):
fig=plt.figure() fig=plt.figure()
ax = fig.add_subplot(1,1,1) ax = fig.add_subplot(1,1,1)
ax.invert_xaxis();ax.invert_yaxis() #ax.invert_xaxis()
ax.invert_yaxis()
#hl=ax[0].plot(x, y, color=col) #hl=ax[0].plot(x, y, color=col)
hl=ax.plot(pts[:,0],pts[:,1],'r.') hl=ax.plot(pts[:,0],pts[:,1],'r.')
hl=ax.plot(pts[:,0],pts[:,1],'y--') hl=ax.plot(pts[:,0],pts[:,1],'y--')
@@ -707,187 +708,197 @@ class ShapePath(MotionBase):
the type of generated program is defined by <mode>$ the type of generated program is defined by <mode>$
-> the list af all points that will be moved at, is in 'mot_pts' -> the list af all points that will be moved at, is in 'mot_pts'
(m)= mandatory
(o)= optional
common kwargs: common kwargs:
scale : scaling velocity (default=1. value=0 would stop at each point scale : (o) scaling velocity (default=1. value=0 would stop at each point
cnt : move path multiple times (default=1) cnt : (o) move path multiple times (default=1)
dwell : dwell time at end (default=100ms) dwell : (o) dwell time at end (default=100ms)
mode:0 unused mode:0 unused
mode:1 pvt motion mode:1 pvt motion point list
common kwargs plus: common kwargs plus:
points : point list points : (m) point list
trf : optional transformation that will be done on 'points', mot_pts=trf*points trf : (o) transformation that will be done on 'points', mot_pts=trf*points
mode:2 unused mode:2 unused
mode:3 pvt motion using inverse fft velocity mode:3 pvt motion point list using inverse fft velocity
common kwargs plus: common kwargs plus:
points : point list points : (m) point list
trf : optional transformation that will be done on 'points', mot_pts=trf*points trf : (o) transformation that will be done on 'points', mot_pts=trf*points
numPad : number of padding points to reduce aliasing (default=16) numPad : (o) number of padding points to reduce aliasing (default=16)
mode:4 pvt motion short code using grid parameters mode:4 pvt motion short code using grid parameters
common kwargs plus: common kwargs plus:
trf : transformation that will be done on 'grid points' trf : (o) transformation that will be done on 'grid points'
grid: grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0} grid: (m) grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0}
mode:5 pvt motion 'stop and go' short code using grid parameters. mode:5 pvt motion 'stop and go' short code using grid parameters.
Instead of continous motion it moves and waits as given in the parameters Instead of continous motion it moves and waits as given in the parameters
common kwargs plus: common kwargs plus:
trf : transformation that will be done on 'grid points' trf : (o) transformation that will be done on 'grid points'
grid: grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0} grid: (m) grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0}
tmove: time to move in ms (move start on FEL-trigger tmove: (m) time to move in ms (move start on FEL-trigger
twait: time to wait in ms twait: (m) time to wait in ms
(tmove+twait will be rounded to a multiple of fel_per) (tmove+twait will be rounded to a multiple of fel_per)
mode:6 pvt motion 'hit and return using grid parameters. continous motion on 2n ells to pump then same 2n wells to probe, then go 2 rows down mode:6 pvt motion 'hit and return using grid parameters. continous motion on 2n ells to pump then same 2n wells to probe, then go 2 rows down
common kwargs plus: common kwargs plus:
trf : transformation that will be done on 'grid points' trf : (o) transformation that will be done on 'grid points'
grid : grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0} grid : (m) grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0}
ssz : section size (in wells) ssz : (m) section size (in wells)
smv : time(in num of shots) to move to next section (horiz/vert) smv : (o) time(in num of shots) to move to next section (horiz/vert)
default is (ssz[0]-1,ssz[1]) default is (ssz[0]-1,ssz[1])
sdelay: shots count of delay. Default is ssz[0]*ssz[1] sdelay: (o) shots count of delay. Default is ssz[0]*ssz[1]
''' '''
#scan=0 # snake motion X fast, Y slow if mode not in (1,3,4,5,6): #### pvt motion
scan=1 # snake motion Y fast, X slow (default) raise ValueError(f'unsupported mode:{mode}')
prg=f'close all buffers\nopen prog {prgId}\n Coord[1].DesTimeBase=Sys.ServoPeriod\n'
verb=self.verbose
comm=self.comm
meta=self.meta
try: try:
self.sync_prg self.sync_prg
except AttributeError: except AttributeError:
_log.warning('missing motion sync code!') _log.warning('missing motion sync code!')
# this uses Coord[1].Tm and limits with MaxSpeed
if mode in (1,3,4,5,6): #### pvt motion verb=self.verbose
if mode!=5: comm=self.comm
pt2pt_time=meta['pt2pt_time']=meta['fel_per'] meta=self.meta
scale=kwargs.get('scale', 1.) #scan=0 # snake motion X fast, Y slow
cnt=kwargs.get('cnt', 1) # move path multiple times scan=1 # snake motion Y fast, X slow (default)
dwell=kwargs.get('dwell', 100) # wait time at end of motion
CoordFeedTime=1000. #Defaut deltatau value argsStr=[f'mode:{mode}']
if mode in (1, 3): #### pvt motion, using points for k,v in kwargs.items():
pt=kwargs['points'] if type(v) in (np.ndarray,np.matrix):
try: argsStr.append(f'{k}:{type(v).__name__}({v.shape})')
trf=kwargs['trf'] else:
except KeyError as e: argsStr.append(f'{k}:{v}')
self.mot_pts=pt prg='// '+' '.join(argsStr)
prg+=f'\n\nclose all buffers\nopen prog {prgId}\n Coord[1].DesTimeBase=Sys.ServoPeriod\n'
scale=kwargs.get('scale', 1.)
cnt=kwargs.get('cnt', 1) # move path multiple times
dwell=kwargs.get('dwell', 100) # wait time at end of motion
CoordFeedTime=1000. #Defaut deltatau value
if mode!=5:
pt2pt_time=meta['pt2pt_time']=meta['fel_per']
if mode in (1, 3): #### pvt motion, using points
pt=kwargs['points']
try:
trf=kwargs['trf']
except KeyError as e:
self.mot_pts=pt
else:
self.mot_pts=(np.hstack((pt, np.ones((pt.shape[0], 1))))*np.asmatrix(trf)).A # pt*trf
#pv is an array of posx posy velx vely
pv=np.ndarray(shape=(pt.shape[0]+2,4),dtype=pt.dtype)
pv[:]=np.NaN
pv[ 0,(0,1)]=pt[0,:]
pv[ 1:-1,(0,1)]=pt
pv[ -1,(0,1)]=pt[-1,:]
pv[(0,0,-1,-1),(2,3,2,3)]=0
if mode==1: # set velocity to average from prev to next point
dist=pv[2:,(0,1)] - pv[:-2,(0,1)]
pv[ 1:-1,(2,3)] = dist/(2.*pt2pt_time)*scale #um/ms
else: # mode==3: # set velocity to the reconstructed inverse fourier transformation
numPad=kwargs.get('numPad', 16)
p=np.hstack((pt.T,pt[-1,:].repeat(numPad).reshape(2,-1)))
k=p.shape[1]
stp=((p[:,-1]-p[:,0])/(k-1)) #calculate steepness point to point
#stp*=0
p[0,:]-=stp[0]*np.arange(k)
p[1,:]-=stp[1]*np.arange(k)
f=np.fft.fftfreq(k, d=1.)
pf=np.fft.fft(p)
pfd=pf*f*1j # differentiate in fourier
pd=np.fft.ifft(pfd)
v=pd.real.T/pt2pt_time*np.pi*2+stp/pt2pt_time
if numPad==0:
n=None
else: else:
self.mot_pts=(np.hstack((pt, np.ones((pt.shape[0], 1))))*np.asmatrix(trf)).A # pt*trf n=-numPad
#pv is an array of posx posy velx vely pv[ 1:-1,(2,3)] = v[:n]*scale
pv=np.ndarray(shape=(pt.shape[0]+2,4),dtype=pt.dtype) if verb&0x20:
pv[:]=np.NaN if 'trf' in kwargs:
pv[ 0,(0,1)]=pt[0,:] _log.warning('correct plotting of pvt only works without transformation !')
pv[ 1:-1,(0,1)]=pt
pv[ -1,(0,1)]=pt[-1,:]
pv[(0,0,-1,-1),(2,3,2,3)]=0
if mode==1: # set velocity to average from prev to next point
dist=pv[2:,(0,1)] - pv[:-2,(0,1)]
pv[ 1:-1,(2,3)] = dist/(2.*pt2pt_time)*scale #um/ms
else: # mode==3: # set velocity to the reconstructed inverse fourier transformation
numPad=kwargs.get('numPad', 16)
p=np.hstack((pt.T,pt[-1,:].repeat(numPad).reshape(2,-1)))
k=p.shape[1]
stp=((p[:,-1]-p[:,0])/(k-1)) #calculate steepness point to point
#stp*=0
p[0,:]-=stp[0]*np.arange(k)
p[1,:]-=stp[1]*np.arange(k)
f=np.fft.fftfreq(k, d=1.)
pf=np.fft.fft(p)
pfd=pf*f*1j # differentiate in fourier
pd=np.fft.ifft(pfd)
v=pd.real.T/pt2pt_time*np.pi*2+stp/pt2pt_time
if numPad==0:
n=None
else:
n=-numPad
pv[ 1:-1,(2,3)] = v[:n]*scale
if verb&0x20:
if 'trf' in kwargs:
_log.warning('correct ploting of pvt only works without transformation !')
else:
dp=DebugPlot(self);self.pvt=dp.plot_gen_pvt(pv)
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)])
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))
if scan==0: # snake motion X fast, Y slow
for i in range(1,ny,2):
xx[i]=xx[i][::-1]
else: #scan==1 snake motion Y fast, X slow
xx=xx.T
yy=yy.T
for i in range(1, nx, 2):
yy[i]=yy[i][::-1]
pt=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float64).transpose() #*pitch
try:
trf=kwargs['trf']
except KeyError as e:
ox, oy=g['pos']
px, py=g['pitch']
#self.mot_pts=pt
self.mot_pts=pt*np.array(g['pitch'], np.float)+np.array(g['pos'], np.float)
else: else:
ox, oy=(0,0) dp=DebugPlot(self);self.pvt=dp.plot_gen_pvt(pv)
px, py=(1,1) plt.show(block=False)
self.mot_pts=(np.hstack((pt, np.ones((pt.shape[0], 1))))*np.asmatrix(trf)).A # pt*trf pv[1:-1, (2, 3)]*=CoordFeedTime #scaling for Deltatau
#prg+=f' linear abs\n X{ox:g} Y{oy:g}\n' prg+=' linear abs\n X%g Y%g\n' % tuple(pv[0, (0,1)])
prg+=f' linear abs\n X{ox-px:g} Y{oy-py:g}\n' # start one position out of grid elif mode in (4,5): #### pvt motion, short code using grid parameters
else: #mode==6: #### pvt motion, hit and return using grid parameters g=kwargs['grid']
g=kwargs['grid'] nx, ny=g['count']
nx,ny=g['count'] #total count of wells xx, yy=np.meshgrid(range(nx), range(ny))
#TODO: rework pt calculation if scan==0: # snake motion X fast, Y slow
hrs=HitReturnSim() for i in range(1,ny,2):
pt=hrs.sim_motion(mode=0xff if verb&0x20 else 0x00 , **kwargs) xx[i]=xx[i][::-1]
pt=np.array(pt)[:,:2] else: #scan==1 snake motion Y fast, X slow
try: xx=xx.T
trf=kwargs['trf'] yy=yy.T
except KeyError as e: for i in range(1, nx, 2):
ox, oy=g['pos'] yy[i]=yy[i][::-1]
px, py=g['pitch'] pt=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float64).transpose() #*pitch
self.mot_pts=pt*np.array(g['pitch'], np.float)+np.array(g['pos'], np.float) try:
else: trf=kwargs['trf']
ox, oy=(0,0) except KeyError as e:
px, py=(1,1) ox, oy=g['pos']
self.mot_pts=(np.hstack((pt, np.ones((pt.shape[0], 1))))*np.asmatrix(trf)).A # pt*trf px, py=g['pitch']
sx,sy=kwargs['ssz'] #section size (in wells) #self.mot_pts=pt
try: self.mot_pts=pt*np.array(g['pitch'], np.float)+np.array(g['pos'], np.float)
tsx,tsy=kwargs['smv'] #time(in num of shots) to move to next section (horiz/vert) else:
except KeyError as e: ox, oy=(0,0)
tsx=sx-1 px, py=(1,1)
tsy=sy self.mot_pts=(np.hstack((pt, np.ones((pt.shape[0], 1))))*np.asmatrix(trf)).A # pt*trf
try: #prg+=f' linear abs\n X{ox:g} Y{oy:g}\n'
tsd=kwargs['sdelay'] prg+=f' linear abs\n X{ox-px:g} Y{oy-py:g}\n' # start one position out of grid
except KeyError as e: else: #mode==6: #### pvt motion, hit and return using grid parameters
tsd=sx*sy g=kwargs['grid']
tsd+=1-sx*sy # sdl are shots to wait at position #(6) nx,ny=g['count'] #total count of wells
prg+=f' linear abs\n X{ox-px:g} Y{oy-py:g}\n' # start one position out of grid #TODO: rework pt calculation
prg+=' dwell 10\n' hrs=HitReturnSim()
try: prg+=self.sync_prg pt=hrs.sim_motion(mode=0xff if verb&0x20 else 0x00 , **kwargs)
except AttributeError: pt=np.array(pt)[:,:2]
#print('no sync code available') try:
prg+=' Gather.Enable=2\n' trf=kwargs['trf']
if cnt>1: except KeyError as e:
prg+=' P100=%d\n'%cnt ox, oy=g['pos']
prg+='N100:\n' px, py=g['pitch']
if mode in (1,3): self.mot_pts=pt*np.array(g['pitch'], np.float)+np.array(g['pos'], np.float)
prg+=f'''\ else:
ox, oy=(0,0)
px, py=(1,1)
self.mot_pts=(np.hstack((pt, np.ones((pt.shape[0], 1))))*np.asmatrix(trf)).A # pt*trf
sx,sy=kwargs['ssz'] #section size (in wells)
try:
tsx,tsy=kwargs['smv'] #time(in num of shots) to move to next section (horiz/vert)
except KeyError as e:
tsx=sx-1
tsy=sy
try:
tsd=kwargs['sdelay']
except KeyError as e:
tsd=sx*sy
tsd+=1-sx*sy # sdl are shots to wait at position #(6)
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
except AttributeError:
#print('no sync code available')
prg+=' Gather.Enable=2\n'
if cnt>1:
prg+=' P100=%d\n'%cnt
prg+='N100:\n'
if mode in (1,3):
prg+=f'''\
//mode {mode}: pvt motion with each point in program code //mode {mode}: pvt motion with each point in program code
pvt{pt2pt_time} abs pvt{pt2pt_time} abs
''' '''
for idx in range(1,pv.shape[0]): for idx in range(1,pv.shape[0]):
#prg+=f'N{idx} ' + 'X%g:%g Y%g:%g\n'%tuple(pv[idx,(0,2,1,3)]) #prg+=f'N{idx} ' + 'X%g:%g Y%g:%g\n'%tuple(pv[idx,(0,2,1,3)])
prg+=f' X%g:%g Y%g:%g\n'%tuple(pv[idx, (0, 2, 1, 3)]) prg+=f' X%g:%g Y%g:%g\n'%tuple(pv[idx, (0, 2, 1, 3)])
prg+=f' X{pv[-1, 0]:g} Y{pv[-1, 1]:g}\n' prg+=f' X{pv[-1, 0]:g} Y{pv[-1, 1]:g}\n'
elif mode==4: elif mode==4:
if scan==0: if scan==0:
raise Exception('scan=0 not supported') raise Exception('scan=0 not supported')
pass pass
else: # scan=1 else: # scan=1
vx=px/(pt2pt_time)*scale*CoordFeedTime #scaling for Deltatau vx=px/(pt2pt_time)*scale*CoordFeedTime #scaling for Deltatau
vy=py/(pt2pt_time)*scale*CoordFeedTime #scaling for Deltatau vy=py/(pt2pt_time)*scale*CoordFeedTime #scaling for Deltatau
prg+=f'''\ prg+=f'''\
//mode 4: grid pvt motion //mode 4: grid pvt motion
pvt{pt2pt_time} abs pvt{pt2pt_time} abs
L1=0 //slow loop x L1=0 //slow loop x
@@ -934,22 +945,22 @@ class ShapePath(MotionBase):
X({ox}+L1*{px}):{0:g} Y({oy}+L0*{py}):{0:g} X({ox}+L1*{px}):{0:g} Y({oy}+L0*{py}):{0:g}
''' '''
elif mode==5: elif mode==5:
if scan==0: if scan==0:
raise Exception('scan=0 not supported') raise Exception('scan=0 not supported')
pass pass
else: # scan=1 else: # scan=1
if meta['sync_mode']==2: if meta['sync_mode']==2:
_log.error('sync_mode=2 not allowed for stop-and-go motion !') _log.error('sync_mode=2 not allowed for stop-and-go motion !')
tmove=kwargs['tmove'] tmove=kwargs['tmove']
twait=kwargs['twait'] twait=kwargs['twait']
fel_per=meta['fel_per'] fel_per=meta['fel_per']
pt2tp_felpulse=round((tmove+twait)/fel_per) # number of fel-pulses for a whole cycle (tmove+twait) pt2tp_felpulse=round((tmove+twait)/fel_per) # number of fel-pulses for a whole cycle (tmove+twait)
meta['pt2pt_time']=fel_per*pt2tp_felpulse meta['pt2pt_time']=fel_per*pt2tp_felpulse
twait_=round((tmove+twait)/fel_per)*fel_per-tmove twait_=round((tmove+twait)/fel_per)*fel_per-tmove
if twait!=twait_: if twait!=twait_:
_log.warning(f'adjust twait({twait}) to {twait_} to match multiple of fel-cycles') _log.warning(f'adjust twait({twait}) to {twait_} to match multiple of fel-cycles')
syncPlc=f'''\ syncPlc=f'''\
close all buffers close all buffers
disable plc 2 disable plc 2
open plc 2 open plc 2
@@ -967,8 +978,8 @@ open plc 2
close close
enable plc 2 enable plc 2
''' '''
comm.gpascii.send_block(syncPlc, verb&0x08) if comm: comm.gpascii.send_block(syncPlc, verb&0x08)
prg+=f'''\ prg+=f'''\
//mode 5: grid pvt motion //mode 5: grid pvt motion
pvt{tmove} abs pvt{tmove} abs
L1=0 //slow loop x L1=0 //slow loop x
@@ -1023,31 +1034,31 @@ enable plc 2
while(Sys.Udata[2]==Sys.Udata[1]){{}};Sys.Udata[2]=Sys.Udata[1] // wait motion trigger while(Sys.Udata[2]==Sys.Udata[1]){{}};Sys.Udata[2]=Sys.Udata[1] // wait motion trigger
''' '''
elif mode==6: elif mode==6:
if scan==0: if scan==0:
raise Exception('scan=0 not supported') raise Exception('scan=0 not supported')
pass pass
else: # scan=1 else: # scan=1
vsx=px/(pt2pt_time)*scale*CoordFeedTime # scaling for Deltatau vsx=px/(pt2pt_time)*scale*CoordFeedTime # scaling for Deltatau
vsy=py/(pt2pt_time)*scale*CoordFeedTime # scaling for Deltatau vsy=py/(pt2pt_time)*scale*CoordFeedTime # scaling for Deltatau
#g=kwargs['grid'] #g=kwargs['grid']
#ox,oy=g['pos'] #origin position in um (or counts if scaled) #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) #px,py=g['pitch'] #pitch to next position in um (or 1 if scaled)
#nx,ny=g['count'] #total count of wells #nx,ny=g['count'] #total count of wells
#sx,sy=kwargs['ssz'] #section size (in wells) #sx,sy=kwargs['ssz'] #section size (in wells)
#tsx, tsy, tsd #time scale to pvt move to (next horiz|next vert| after position #6) #tsx, tsy, tsd #time scale to pvt move to (next horiz|next vert| after position #6)
tx,ty=nx//sx,ny//sy #total sections tx,ty=nx//sx,ny//sy #total sections
#variables #variables
cx,cy,dx,dy,n,k,t,vx,vy,x,x0,y,y0=map(lambda x: f'L{x}',range(13)) cx,cy,dx,dy,n,k,t,vx,vy,x,x0,y,y0=map(lambda x: f'L{x}',range(13))
# replace in python code of hit_and_return.py setup_motion: # replace in python code of hit_and_return.py setup_motion:
# (cx|cy|dx|dy|n|k|sx|sy|tsd|tsx|tsy|tx|ty|vsx|vsy|vx|vy|x|x0|y|y0) -> {\1} # (cx|cy|dx|dy|n|k|sx|sy|tsd|tsx|tsy|tx|ty|vsx|vsy|vx|vy|x|x0|y|y0) -> {\1}
# if ([^:]*): -> if \(\1\){{ # if ([^:]*): -> if \(\1\){{
# else: -> }}else{{ # else: -> }}else{{
# elif ([^:]*): -> }}else if \(\1\){{ # elif ([^:]*): -> }}else if \(\1\){{
prg+=f'''\ prg+=f'''\
//mode 6: hit-and-return pvt motion //mode 6: hit-and-return pvt motion
{t}=1 // motion pvt tome scaling {t}=1 // motion pvt tome scaling
@@ -1143,11 +1154,9 @@ enable plc 2
}} }}
''' '''
else: #common code to repeat the motion multiple times
raise ValueError('unsupported mode') if cnt>1:
#common code to repeat the motion multiple times prg+=f'''\
if cnt>1:
prg+=f'''\
dwell 10 dwell 10
P100=P100-1 P100=P100-1
f(P100>0) f(P100>0)
@@ -1157,9 +1166,8 @@ f(P100>0)
dwell {dwell} dwell {dwell}
goto 100 goto 100
}}\n''' }}\n'''
else: else:
prg+=f' dwell {dwell}\n Gather.Enable=0\nclose\n' prg+=f' dwell {dwell}\n Gather.Enable=0\nclose\n'
#prg+='&1\nb%dr\n'%prgId)
if verb&0x02: if verb&0x02:
DebugPlot.plot_points(self.mot_pts) DebugPlot.plot_points(self.mot_pts)