Files
PBSwissMX/python/shapepath.py

930 lines
40 KiB
Python
Executable File

#!/usr/bin/env python
# *-----------------------------------------------------------------------*
# | |
# | Copyright (c) 2016 by Paul Scherrer Institute (http://www.psi.ch) |
# | |
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
# *-----------------------------------------------------------------------*
'''
shape an optimal path with given points
verbose bits:
1 basic info
2 plot sorting steps
4 list program
4 upload progress
8 plot gather path
16 plot pvt trajectory (before motion)
32 print sync details
Gather motor order
idx 0 1 2 3 4 5 6
OLD Motor[3].ActPos Motor[2].ActPos Motor[1].ActPos Motor[3].DesPos Motor[2].DesPos Motor[1].DesPos Gate3[1].Chan[1].UserFlag
NEW Motor[1].ActPos Motor[2].ActPos Motor[1].DesPos Motor[2].DesPos Gate3[1].Chan[1].UserFlag
NEW y.ActPos x.ActPos y.DesPos x.DesPos Gate3[1].Chan[1].UserFlag
OLD->NEW
0->none
1->1
2->0
3->none
4->3
5->2
Mot 1: Stage Y Parker MX80L D11 25mm one pole cycle = 13mm = 2048 phase_step
Mot 2: Stage X Parker MX80L D11 25mm one pole cycle = 13mm = 2048 phase_step
Mot 3: Rotation stage LS Mecapion MDM-DC06DNC0H 32 poles = 1 rev = 16*2048=32768 phase_step
Mot 4: Stage X Stada Stepper 670mA 200 poles 1 rev = 100*2048 phase_step (2 stepper motor)
Mot 5: Stage Z Stada Stepper 670mA 200 poles 1 rev = 100*2048 phase_step (2 stepper motor)
Enc 6: Interferometer Y
Enc 7: Interferometer X
'''
from __future__ import print_function
import os, sys, time
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import subprocess as sprc
sys.path.insert(0,os.path.expanduser('~/Documents/prj/SwissFEL/PBTools/'))
#sys.path.insert(0,'/sf/bernina/config/swissmx/zamofing_t')
#sys.path.insert(0,'/sf/bernina/config/swissmx/zamofing_t/pbtools/misc/')
from pbtools.misc.pp_comm import PPComm
from pbtools.misc.gather import Gather
from MXMotion import MotionBase
def gen_pvt(p,v, p2pt, ts):
'''generates a pvt motion
p: position array
v: velocity array
t: time array
ts: servo cycle time
!!! it is assumed, that the time intervals are constant !!!
'''
n=int(p2pt/ts)
pvt=np.ndarray((p.shape[0]-1)*n)
tt=np.arange(0,p2pt,ts)[:n]
for i in range(p.shape[0]-1):
d=p[i]
c=v[i]
a=(-2*(p[i+1]-p[i]-v[i]*p2pt)+p2pt*(v[i+1]-v[i]))/p2pt**3
b=(3*p2pt*(p[i+1]-p[i]-v[i]*p2pt)-p2pt**2*(v[i+1]-v[i]))/p2pt**3
pvt[i*n:(i+1)*n]=a*tt**3+b*tt**2+c*tt+d
return pvt
class DebugPlot:
def __init__(self,obj=None):
if obj is None:
self.load_npz()
elif type(obj)==str:
self.load_npz(obj)
else:
self.set_data(obj)
def plot_gen_pvt(self,pv):
# pv is an array of posx posy velx vely
#pv=pv[5:10,:]
#pv=pv[5:-4,:]
p2pt=self.meta['pt2pt_time'] # ms step between samples
ts=self.meta['srv_per'] # sampling time in ms
n=int(p2pt/ts) # servo cycle between samples
k=pv.shape[0] # number of unique samples
t=np.arange(0, p2pt*k, p2pt) # time array of trajectory
ppx=gen_pvt(pv[:,0], pv[:,2], p2pt, ts)
ppy=gen_pvt(pv[:,1], pv[:,3], p2pt, ts)
tt=np.arange(0, n*(k-1))*ts # time array of trajectory
fig=plt.figure()
ax1=fig.add_subplot(2, 1, 1)
ax2=fig.add_subplot(2, 1, 2)
#ax.xaxis.set_ticks(t)
ax1.stem(t, pv[:,0], '-r')
ax2.stem(t, pv[:,1], '-g')
ax1.plot(tt, ppx, '-r', label='x')
ax2.plot(tt, ppy, '-g', label='y')
#ax.legend(loc='best')
ax=plt.figure().add_subplot(1, 1, 1)
ax.plot(pv[:,0], pv[:,1], '.r', label='pft')
ax.plot(ppx, ppy, '-c', label='pft')
ax.invert_xaxis()
ax.invert_yaxis()
plt.axis('equal')
ax.legend(loc='best')
plt.show(block=False)
# ### frequency plots ###
# fig=plt.figure()
# ax=fig.add_subplot(1,1,1)#ax=plt.gca()
#
# #remove linear slope
# sx=ppx-(pv[-1,0]-pv[0,0])*np.arange(ppx.shape[0])
# sy=ppy-(pv[-1,1]-pv[0,1])*np.arange(ppy.shape[0])
#
# #normalize with l -> value of k means amplitude of k at a given frequency
# ppxf=np.fft.rfft(sx)/(2*n)
# ppyf=np.fft.rfft(sy)/(2*n)
#
# f=np.fft.rfftfreq(ppx.shape[0], d=ts*1E-3)
# f=f[1:] #remove dc value frequency
#
# mag=abs(ppxf[1:])#; mag=20*np.log10(abs(mag))
# ax.semilogx(f,mag,'-b',label='ppx') # Bode magnitude plot
# mag=abs(ppyf[1:])#; mag=20*np.log10(abs(mag))
# ax.semilogx(f,mag,'-g',label='ppy') # Bode magnitude plot
# #ax.yaxis.set_label_text('dB ampl')
# ax.yaxis.set_label_text('ampl')
# ax.xaxis.set_label_text('frequency [Hz]')
# plt.grid(True)
#
# ax.legend(loc='best')
# plt.show(block=False)
return (tt,ppx,ppy)
#@staticmethod
#def onclick(event):
# print('button=%s, x=%d, y=%d, xdata=%f, ydata=%f'%(
# event.button, event.x, event.y, event.xdata, event.ydata))
# obj=event.canvas.figure.obj
@staticmethod
def plot_points(pts):
fig=plt.figure()
ax = fig.add_subplot(1,1,1)
ax.invert_xaxis();ax.invert_yaxis()
#hl=ax[0].plot(x, y, color=col)
hl=ax.plot(pts[:,0],pts[:,1],'r.')
hl=ax.plot(pts[:,0],pts[:,1],'y--')
#cid = fig.canvas.mpl_connect('button_press_event', self.onclick)
#fig.obj=self
plt.axis('equal')
#self.ax=ax
#self.hl=hl
def analyze_trigger(self):
if hasattr(self,'idxTrigger'): return
pts=self.pts # X,Y array
rec=self.rec # yA,xA,yD,xD,trig
lenRec=rec.shape[0]
lenPts=pts.shape[0]
idxTrigger=rec[:,4]
idxTrigger=np.where(np.diff(idxTrigger)==1)[0]+1
idxInPos=[] #first point at idx 0
idx=0
for i in range(lenPts):
l=rec[idx:,(3,2)]-pts[i,:]
l2=l[:,0]**2+l[:,1]**2
try:
ofs=l2.argmin()
except ValueError as e:
raise e #should never happen
break
idx+=ofs
idxInPos.append(idx)
idxInPos = np.array(idxInPos)
#select only triggers on a target point
i=max(0,np.abs(idxTrigger-idxInPos[1]).argmin()-1)
j=i+idxInPos.shape[0]
idxTrigger=idxTrigger[i:j]
self.idxInPos=idxInPos
self.idxTrigger=idxTrigger
def plot_trigger_jitter(self):
self.analyze_trigger()
ts=self.meta['srv_per']*self.meta['acq_per']
idxTrigger=self.idxTrigger
idxInPos=self.idxInPos
n=min(idxTrigger.shape[0],idxInPos.shape[0])-1
jitter = idxTrigger[1:n]-idxInPos[1:n]
pts=self.pts # X,Y array
rec=self.rec # yA,xA,yD,xD,trig
fig = plt.figure('trigger jitter')
ax = fig.add_subplot(1, 1, 1)
hl = []
hl += ax.plot(jitter * ts, 'b-', label='jitter')
ax.xaxis.set_label_text('position idx')
ax.yaxis.set_label_text('jitter motion (ms)')
rec = self.rec # yA,xA,yD,xD,trig
ts=self.meta['srv_per']*self.meta['acq_per']
fig = plt.figure('shot position error')
ax = fig.add_subplot(1, 1, 1)
#errx = rec[idxTrigger, 1] - rec[idxInPos, 3]
#erry = rec[idxTrigger, 0] - rec[idxInPos, 2]
n=idxTrigger.shape[0]
errx = rec[idxTrigger, 1] - pts[:n, 0]
erry = rec[idxTrigger, 0] - pts[:n, 1]
err = np.sqrt(errx ** 2 + erry ** 2)
hl = []
hl += ax.plot(errx, 'b-', label='x-error')
hl += ax.plot(erry, 'g-', label='y-error')
hl += ax.plot(err, 'r-', label='error')
ax.xaxis.set_label_text('target point index')
ax.yaxis.set_label_text('pos-error um')
legend = ax.legend(loc='best', shadow=True)
print('shot average error x %g um, y %g um, %g um' % (np.abs(errx).mean(), np.abs(erry).mean(), err.mean()))
plt.show(block=False)
plt.show(block=False)
def plot_pos_error(self):
rec = self.rec # yA,xA,yD,xD,trig
ts=self.meta['srv_per']*self.meta['acq_per']
fig = plt.figure('position error')
ax = fig.add_subplot(1, 1, 1)
t=np.arange(rec.shape[0],dtype=np.uint32)
errx = rec[:, 1] - rec[:, 3]
erry = rec[:, 0] - rec[:, 2]
err = np.sqrt(errx ** 2 + erry ** 2)
hl = []
hl += ax.plot(t, errx, 'b-', label='x-error')
hl += ax.plot(t, erry, 'g-', label='y-error')
hl += ax.plot(t, err, 'r-', label='error')
ax.xaxis.set_label_text('ms (timebase: %g ms per data point)' % ts)
ax.yaxis.set_label_text('pos-error um')
legend = ax.legend(loc='best', shadow=True)
print('motion average error x %g um, y %g um, %g um' % (np.abs(errx).mean(), np.abs(erry).mean(), err.mean()))
plt.show(block=False)
def plot_trajectory(self):
pts = self.pts # X,Y array
rec = self.rec # yA,xA,yD,xD,trig
fig = plt.figure('trajectory')
ax = fig.add_subplot(1, 1, 1)
ax.invert_xaxis()
ax.invert_yaxis()
# hl=ax[0].plot(x, y, color=col)
hl = ax.plot(pts[:, 0], pts[:, 1], 'r.', label='points')
hl += ax.plot(pts[:, 0], pts[:, 1], 'y--', label='direct')
hl += ax.plot(rec[:, 3], rec[:, 2], 'b-', label='DesPos') # desired path
hl += ax.plot(rec[:, 1], rec[:, 0], 'g-', label='ActPos') # actual path
try:
pvt = self.pvt
except AttributeError:
pass
else:
hl = ax.plot(pvt[1], pvt[2], 'c--', label='SimPos') # simulated path
fig2 = plt.figure('time line')
ax2 = fig2.add_subplot(1, 1, 1)
hl2 = ax2.plot(rec[:, 2], 'r-', label='desPos Mot1')
hl2 += ax2.plot(rec[:, 3], 'g-', label='desPos Mot2')
idxTrigger = rec[:, 4]
idxTrigger = np.where(np.diff(idxTrigger) == 1)[0] + 1
if idxTrigger.shape[0] > 0:
hl += ax.plot(rec[idxTrigger, 1], rec[idxTrigger, 0], 'xr', label='trig') # actual path
hl2 += ax2.plot(rec[:, 4], 'b-', label='trigger')
ax.xaxis.set_label_text('x-pos um')
ax.yaxis.set_label_text('y-pos um')
ax.axis('equal')
ax.legend(loc='best')
# cid = fig.canvas.mpl_connect('button_press_event', self.onclick)
# fig.obj=self
ax2.legend(loc='best')
plt.show(block=False)
def plot_gather(self,mode=255):
try:
meta=self.meta
pts=self.pts # X,Y array
rec = self.rec # yA,xA,yD,xD,trig
except AttributeError as e:
print('plot_gather(): '+str(e)+': no data acquired yet')
return
if mode&1:
self.plot_trajectory()
if mode&2:
self.plot_pos_error()
if mode&4:
self.plot_bode(xy=(3,1),mode=31,db=True) # FX
self.plot_bode(xy=(2,0),mode=31,db=True) # FY
if mode&8:
self.plot_trigger_jitter()
plt.show(block=False)
def plot_bode(self,xy=(0,1),mode=25,db=True):
'''displays a bode plot of the data
Y(s)=G(s)*X(s)
Y= output signal
X= input signal
xy are the row indexes of input and output signal
meta= meta information (dictionary) of data
mode bits: (+mean default)
+1: display time signal
2: display bode of X(s) signal
4: display bode of Y(s) signal
+8: display bode of G(s) signal
+16: clip frequencies out of minFrq,maxFrq
'''
meta=self.meta
pts=self.pts # X,Y array
rec = self.rec # yA,xA,yD,xD,trig
strMot=('FY.act','FX.act','FY.des','FX.des')
ts=self.meta['srv_per']*self.meta['acq_per']*1E-3 #0.2ms
num=rec.shape[0]
#rngMin=int(.01/ts);rngMax=int(num-1.001/ts) #0.01s from start 1.01 sec before end
rngMin=int(.01/ts);rngMax=rngMin+int((pts.shape[0]-2)*.01/ts)
num=rngMax-rngMin
minFrq=1/(num*ts)#minimal frq to show bode
maxFrq=1/(2*ts) #maximal frq to show bode
xIdx,yIdx=xy
#remove DC value
x=rec[rngMin:rngMax,xIdx]-rec[rngMin,xIdx]
y=rec[rngMin:rngMax,yIdx]-rec[rngMin,yIdx]
#make last value same as first (nice periodicity)
x=x-(x[-1]*np.arange(num)/(num-1.))
y=y-(y[-1]*np.arange(num)/(num-1.))
if mode&1:
t = ts*np.arange(num)
fig=plt.figure('raw {}->{}'.format(strMot[xIdx],strMot[yIdx]))
ax=fig.gca()
ax.plot(t,x,'b')
ax.plot(t,y,'g')
fig=plt.figure('bode {}->{}'.format(strMot[xIdx],strMot[yIdx]))
ax1=fig.add_subplot(2,1,1)
ax1.grid(True)
ax1.yaxis.set_label_text('Amplitude'+ (' [dB]' if db else ''))
ax1.axvline(minFrq,c='k');ax1.axvline(maxFrq,c='k')
ax2=fig.add_subplot(2,1,2, sharex = ax1)
ax2.grid(True)
ax2.xaxis.set_label_text('Frequency [Hz]')
ax2.yaxis.set_label_text('Phase [degree]')
ftX=np.fft.rfft(x)
ftY=np.fft.rfft(y)
fMax=.5/ts #fs=1/ts, fMax=1/2fs
n=ftX.shape[0]
f=np.arange(n)*fMax/(n-1)
if mode&16:
i=int(minFrq*num*ts); j=int(maxFrq*num*ts); #print(w[i],w[j])
f=f[i:j+1]
ftX=ftX[i:j+1]
ftY=ftY[i:j+1]
ftLst=[]
if mode&2:
ftLst.append((ftX,'b','input'))
if mode&4:
ftLst.append((ftY,'g','output'))
if mode&8:
ftLst.append((ftY/ftX,'r','out/inp'))
for ft,c,s in ftLst:
phase=np.angle(ft)
phase=np.degrees(np.unwrap(phase))
mag=np.abs(ft) #ftY)/np.abs(ftX)
if db:
magDb=20*np.log10(mag) #in decibel (20=10*2: factor 2 because rfft only half)
ax1.semilogx(f,magDb,c,label=s) # Bode magnitude plot
else:
ax1.semilogx(f, mag, c,label=s) # Bode magnitude plot
ax2.semilogx(f,phase,c,label=s) # Bode phase plot
ax2.set_ylim(-360,360)
ax2.legend(loc='best')
plt.show(block=False)
def load_npz(self,fn='/tmp/shapepath.npz'):
fh=np.load(fn)
for k,v in fh.iteritems():
setattr(self,k,v)
self.meta=self.meta.item()
def set_data(self,spObj):
self.meta=spObj.meta
self.pts=spObj.points
try: self.rec=spObj.rec
except AttributeError: pass
try: self.pvt=spObj.pvt
except AttributeError: pass
class ShapePath(MotionBase):
def __init__(self,comm, gather, verbose,**kwargs):
MotionBase.__init__(self,comm, gather, verbose, **kwargs)
def gen_swissmx_points(self,flipx=False,flipy=False,ofs=(0,0),width=1000):
'generathe a path that writes swissfel'
#string from inkscape path of the drawing
d="m 524.7061,637.31536 3.54883,0 3.54882,0 3.54883,0 0,-4.20801 0,-4.20801 0,-4.208 0,-4.20801 4.22949,0 4.22949,0 4.2295,0 4.22949,0 0,-3.55957 0,-3.55957 0,-3.55957 0,-3.55957 -4.22949,0 -4.2295,0 -4.22949,0 -4.22949,0 0,-4.22949 0,-4.2295 0,-4.22949 0,-4.22949 -3.54883,0 -3.54882,0 -3.54883,0 -3.54883,0 0,4.22949 0,4.22949 0,4.2295 0,4.22949 -4.20752,0 -4.20752,0 -4.20752,0 -4.20752,0 0,3.55957 0,3.55957 0,3.55957 0,3.55957 4.20752,0 4.20752,0 4.20752,0 4.20752,0 0,4.20801 0,4.208 0,4.20801 0,4.20801 -11.87126,0.36152 -12.12171,-0.13934 -2.52941,3.93977 -2.57238,3.94369 -2.50854,3.88614 -2.50731,3.91767 -2.49035,3.88268 -2.50987,3.91244 -2.50453,3.88732 -2.51897,3.9189 -6.39782,5.72802 -6.63782,6.70894 -3.21517,5.11464 -3.3404,5.32333 -3.08995,5.11464 -3.17343,5.15637 -16.69223,0.0698 5.55908,0 5.55909,0 5.55908,0 3.18604,-5.17432 3.18603,-5.17431 3.18604,-5.17432 3.18603,-5.17431 3.17481,5.17431 3.1748,5.17432 3.17481,5.17431 3.1748,5.17432 5.59229,0 5.59228,0 5.59229,0 5.59228,0 -2.74121,-4.15283 -2.74121,-4.15283 -2.74121,-4.15283 -2.74121,-4.15284 -2.74122,-4.15283 -2.74121,-4.15283 -2.74121,-4.15283 -2.74121,-4.15283 2.50488,-3.90015 2.50489,-3.90015 2.50488,-3.90014 2.50488,-3.90015 2.50488,-3.90015 2.50489,-3.90015 2.50488,-3.90014 2.50488,-3.90015 -5.42724,0 -5.42725,0 -5.42724,0 -5.42725,0 -2.76855,4.95508 -2.76856,4.95508 -2.76855,4.95508 -2.76856,4.95508 -2.85644,-4.95508 -2.85645,-4.95508 -2.85644,-4.95508 -2.85645,-4.95508 -5.48193,0 -5.48194,0 -5.48194,0 -5.48193,0 2.52686,3.8562 2.52685,3.8562 2.52686,3.8562 2.52686,3.85621 2.52685,3.8562 2.52686,3.8562 2.52685,3.8562 2.52686,3.8562 -2.77954,4.19678 -2.77954,4.19678 -2.77954,4.19677 -2.77955,4.19678 -2.77954,4.19678 -2.77954,4.19678 -2.77954,4.19677 -2.77954,4.19678 -4.91638,0 -4.91638,0 -4.91639,0 -4.91638,0 -4.91638,0 -4.91638,0 -4.91638,0 -4.91638,0 -4.91639,0 -4.91638,0 -4.91638,0 -4.91638,0 -4.91638,0 -4.91639,0 -4.91638,0 -4.91638,0 4.07568,0 4.07568,0 4.07569,0 4.07568,0 0,-6.14136 0,-6.14135 0,-6.14136 0,-6.14136 0,-6.14136 0,-6.14135 0,-6.14136 0,-6.14136 1.57105,6.14136 1.57104,6.14136 1.57104,6.14135 1.57105,6.14136 1.57105,6.14136 1.57104,6.14136 1.57104,6.14135 1.57105,6.14136 3.68066,0 3.68067,0 3.68067,0 3.68066,0 1.57642,-6.14136 1.57641,-6.14135 1.57642,-6.14136 1.57641,-6.14136 1.57642,-6.14136 1.57642,-6.14135 1.57641,-6.14136 1.57642,-6.14136 0,6.14136 0,6.14136 0,6.14135 0,6.14136 0,6.14136 0,6.14136 0,6.14135 0,6.14136 4.06494,0 4.06494,0 4.06494,0 4.06494,0 0,-8.05298 0,-8.05298 0,-8.05298 0,-8.05297 0,-8.05298 0,-8.05298 0,-8.05298 0,-8.05298 -6.52588,0 -6.52588,0 -6.52587,0 -6.52588,0 -1.25781,4.8999 -1.25782,4.89991 -1.25781,4.8999 -1.25781,4.8999 -1.25781,4.8999 -1.25782,4.89991 -1.25781,4.8999 -1.25781,4.8999 -1.26343,-4.8999 -1.26343,-4.8999 -1.26343,-4.89991 -1.26343,-4.8999 -1.26342,-4.8999 -1.26343,-4.8999 -1.26343,-4.89991 -1.26343,-4.8999 -6.54785,0 -6.54785,0 -6.54785,0 -6.54785,0 0,8.05298 0,8.05298 0,8.05298 0,8.05298 0,8.05297 0,8.05298 0,8.05298 -4.25755,8.13646 -8.40743,0.19687 -8.40743,0.19687 -8.40743,0.19687 -8.40743,0.19687 5.93521,0.22812 8.09742,-0.56079 6.18579,-1.6814 4.55883,-2.66919 3.13062,-3.43823 1.84571,-3.87866 0.61523,-3.98853 -0.58179,-3.83373 -1.74634,-3.50416 -2.802,-2.95581 -3.83472,-2.18676 -5.49316,-1.60401 -7.77832,-1.20849 -7.64649,-1.58204 -1.75781,-2.59179 1.36328,-2.59375 4.4375,-1.09766 5.09766,1.40625 2.19727,3.29492 4.24072,-0.41748 4.24073,-0.41748 4.24072,-0.41748 4.24072,-0.41748 -1.98804,-4.09741 -2.44946,-3.15259 -2.97778,-2.3291 -3.65894,-1.62598 -5.05371,-0.95629 -7.25098,-0.3191 -7.10766,0.41748 -5.50367,1.25244 -4.19677,2.05494 -3.18604,2.91186 -2.01099,3.65796 -0.67065,4.29517 0.61523,3.98852 1.84571,3.5271 2.78002,2.823 3.32935,1.87817 5.06421,1.42822 7.89868,1.56006 7.69141,1.84571 2.02148,2.98828 -1.53906,2.85742 -5.58008,1.53711 -5.27344,-1.36133 -3.07617,-4.52734 -4.43847,0.41748 -4.43848,0.41748 -4.43848,0.41748 -4.43847,0.41748 2.50488,5.95459 4.43848,4.4165 3.18313,1.59592 4.10031,1.14017 -3.65979,0.0939 -5.9713,6e-5 -5.97131,5e-5 -5.9713,6e-5 -5.9713,6e-5 -5.9713,5e-5 -5.97131,6e-5 -5.9713,5e-5 -5.9713,6e-5 5.34491,0.81842 8.09742,-0.56079 6.18579,-1.6814 4.55883,-2.66919 3.13062,-3.43823 1.84571,-3.87866 0.61523,-3.98853 -0.58179,-3.83373 -1.74634,-3.50416 -2.802,-2.95581 -3.83472,-2.18676 -5.49316,-1.60401 -7.77832,-1.20849 -7.64649,-1.58204 -1.75781,-2.59179 1.36328,-2.59375 4.4375,-1.09766 5.09766,1.40625 2.19727,3.29492 4.24072,-0.41748 4.24073,-0.41748 4.24072,-0.41748 4.24072,-0.41748 -1.98804,-4.09741 -2.44946,-3.15259 -2.97778,-2.3291 -3.65894,-1.62598 -5.05371,-0.95629 -7.25098,-0.3191 -7.10766,0.41748 -5.50367,1.25244 -4.19677,2.05494 -3.18604,2.91186 -2.01099,3.65796 -0.67065,4.29517 0.61523,3.98852 1.84571,3.5271 2.78002,2.823 3.32935,1.87817 5.06421,1.42822 7.89868,1.56006 7.69141,1.84571 2.02148,2.98828 -1.53906,2.85742 -5.58008,1.53711 -5.27344,-1.36133 -3.07617,-4.52734 -4.43847,0.41748 -4.43848,0.41748 -4.43848,0.41748 -4.43847,0.41748 2.50488,5.95459 4.43848,4.4165 3.18313,1.59592 4.10031,1.14017 -3.06953,-0.0416 -3.06952,-0.0416 -8.58102,-0.0261 -10.12782,-0.0261 -7.03422,-0.0261 -8.58102,-0.0261 4.47168,0 6.6151,0 2.32826,0 4.47168,0 0,-5.83374 0,-5.83374 0,-5.83374 0,-5.83374 0,-5.83374 0,-5.83374 0,-5.83374 0,-5.83374 -4.47168,0 -4.47168,0 -4.47168,0 0,-5.5796 4.47168,0 4.47168,0 4.47168,0 0,-6.08691 0,-6.08692 -4.47168,0 -4.47168,0 -4.47168,0 -4.47168,0 0,6.08692 0,6.08691 0,5.5796 0,5.83374 0,5.83374 0,5.83374 0,5.83374 0,5.83374 0,5.83374 0,5.83374 -3.67318,5.83374 -8.7308,0 -10.73079,0 -6.7308,0 -9.10563,0 -2.25201,0.007 -8.72971,0.0266 -7.53755,-0.0442 -9.68477,0.0107 -6.3443,0 3.99902,0 3.99902,0 3.99903,0 3.99902,0 2.28516,-7.02002 2.28516,-7.02002 2.28516,-7.02002 2.28516,-7.02002 2.36181,7.02002 2.36182,7.02002 2.36181,7.02002 2.36182,7.02002 3.97705,0 3.97705,0 3.97705,0 3.97705,0 2.14795,-5.83374 2.14795,-5.83374 2.14795,-5.83374 2.14795,-5.83374 2.14795,-5.83374 2.14795,-5.83374 2.14795,-5.83374 2.14795,-5.83374 -4.2959,0 -4.2959,0 -4.2959,0 -4.2959,0 -0.93921,3.67505 -0.93921,3.67505 -0.93921,3.67505 -0.93921,3.67505 -0.9392,3.67504 -0.93921,3.67505 -0.93921,3.67505 -0.93921,3.67505 -1.23047,-3.67505 -1.23047,-3.67505 -1.23047,-3.67505 -1.23047,-3.67504 -1.23046,-3.67505 -1.23047,-3.67505 -1.23047,-3.67505 -1.23047,-3.67505 -4.03223,0 -4.03222,0 -4.03223,0 -4.03223,0 -1.18652,3.67505 -1.18653,3.67505 -1.18652,3.67505 -1.18653,3.67505 -1.18652,3.67504 -1.18652,3.67505 -1.18653,3.67505 -1.18652,3.67505 -0.93921,-3.67505 -0.93921,-3.67505 -0.93921,-3.67505 -0.93921,-3.67504 -0.9392,-3.67505 -0.93921,-3.67505 -0.93921,-3.67505 -0.93921,-3.67505 -4.32862,0 -4.32861,0 -4.32862,0 -4.32861,0 2.16431,5.83374 2.1643,5.83374 2.16431,5.83374 2.16431,5.83374 2.16431,5.83374 2.1643,5.83374 2.16431,5.83374 -3.84635,5.83374 -5.60781,0.003 -5.6078,0.003 -5.60781,0.003 -5.6078,0.003 -5.4839,-1.59358 0,0 5.47119,-3.35034 4.10888,-4.60278 2.5708,-5.4712 0.85694,-5.95459 -0.64868,-5.02123 -1.94507,-4.51587 -3.32837,-3.91114 -4.88843,-3.20801 -7.482173,-2.87842 -5.1337,-1.42273 -6.06186,-1.41174 -6.67969,-2.37304 -1.44922,-2.76758 1.75782,-3.56055 5.22851,-1.49414 6.5918,1.97852 1.99951,2.5708 1.16455,3.75732 4.69141,-0.2749 4.691403,-0.2749 4.6914,-0.27491 4.69141,-0.2749 -0.94483,-4.66918 -1.604,-3.98804 -2.26318,-3.30688 -2.92236,-2.62574 -3.59802,-2.01858 -4.334103,-1.44162 -5.0702,-0.86484 -5.80627,-0.28824 -4.76547,0.1593 -4.23282,0.47791 -6.86695,1.91162 -5.04223,2.98828 -3.61401,3.95507 -2.14283,4.53687 -0.7146,4.82251 1.40625,6.88892 4.21875,5.54858 3.26035,2.31812 4.19986,2.07641 5.13919,1.83472 6.07834,1.59302 6.54785,1.81226 3.64746,1.92211 2.19727,4.48242 -2.33008,4.65821 -6.54688,1.97851 -5.05371,-0.97827 -3.73535,-2.93384 -1.57153,-2.9663 -0.93433,-4.06495 -4.73486,0.29688 -4.73487,0.29687 -4.73486,0.29688 -4.73486,0.29687 0.76065,4.6637 1.44711,4.23523 2.13376,3.80676 2.82059,3.3783 3.79577,2.76855 5.0592,1.97754 6.32264,1.18652 7.58606,0.39551 9.481626,-0.95145 -7.224723,-0.043 -7.224724,-0.043 -7.224723,-0.043 -7.224723,-0.043 -7.224723,-0.043 -7.224723,-0.043 -7.224724,-0.043 -7.224723,-0.043"
d=d.split()
pts=np.ndarray((len(d)-1,2),dtype=np.float)
for i in xrange(pts.shape[0]):
pts[i,:]=map(float,d[i+1].split(','))
pts[0,:]=(0,0)
pts=pts.cumsum(0)
pts=pts[::-1,:]
pts=pts-pts[0]
pts*=width/pts[:,0].max()
if flipx: pts[:,0]=-pts[:,0]
if not flipy: pts[:,1]=-pts[:,1]
pts+=ofs
self.points=pts
verb=self.verbose
if verb&2:
self.plot_points(pts)
plt.show()
def gen_swissfel_points(self,flipx=False,flipy=False,ofs=(0,0),width=1000):
'generathe a path that writes swissfel'
#string from inkscape path of the drawing
d="m 15.801613,951.54022 -1.655274,-0.17578 -1.809082,-0.52002 0,-1.52344 1.765137,0.76172 1.699219,0.25635 1.955566,-0.49805 0.688477,-1.4209 -0.498047,-1.25976 -1.618652,-0.68115 -0.900879,-0.17578 -1.426392,-0.42298 -0.968628,-0.60974 -0.739746,-1.95557 0.254516,-1.29638 0.76355,-0.98877 1.217652,-0.62622 1.602173,-0.20874 1.567383,0.13916 1.6333,0.41748 0,1.44287 -1.589355,-0.60059 -1.442871,-0.19775 -1.071167,0.11719 -0.796509,0.35156 -0.651856,1.33301 0.432129,1.09863 1.655274,0.59326 0.893555,0.18311 1.437377,0.43579 1.001587,0.67749 0.593262,0.92651 0.197754,1.19751 -0.267334,1.3971 -0.802002,1.01257 -1.311035,0.61523 2.995605,-0.004 2.995606,-0.004 -0.536499,-2.05078 -0.536499,-2.05078 -0.536499,-2.05079 -0.536499,-2.05078 1.347656,0 0.421142,1.60034 0.421143,1.60034 0.421143,1.60035 0.421142,1.60034 0.419312,-1.60034 0.419311,-1.60035 0.419312,-1.60034 0.419311,-1.60034 1.589356,0 0.421142,1.60034 0.421143,1.60034 0.421143,1.60035 0.421142,1.60034 0.419312,-1.60034 0.419311,-1.60035 0.419312,-1.60034 0.419311,-1.60034 1.347657,0 -0.536499,2.05078 -0.5365,2.05079 -0.536499,2.05078 -0.536499,2.05078 -1.589355,0 -0.441284,-1.68091 -0.441285,-1.68091 -0.441284,-1.6809 -0.441284,-1.68091 -0.443115,1.68091 -0.443116,1.6809 -0.443115,1.68091 -0.443115,1.68091 2.330933,-8e-5 2.330933,-8e-5 2.330932,-8e-5 2.330933,-8e-5 0,-2.05078 0,-2.05078 0,-2.05079 0,-2.05078 0.673828,-1.48681 0.673828,0 0,-0.85327 0,-0.85327 -0.673828,0 -0.673828,0 0,0.85327 0,0.85327 0.673828,1.48681 0.673828,0 0,2.05078 0,2.05079 0,2.05078 0,2.05078 2.545166,0.1062 2.545166,0.1062 -1.376953,-0.13183 -1.501465,-0.38086 0,-1.3916 1.472168,0.58593 1.435547,0.19043 1.464844,-0.32226 0.512695,-0.92285 -0.373535,-0.84229 -1.038789,-0.41935 -1.048614,-0.25448 -1.078491,-0.33325 -0.730591,-0.47241 -0.55664,-1.50147 0.205078,-1.02539 0.615234,-0.76172 0.99243,-0.47241 1.336672,-0.15747 1.40625,0.10986 1.21582,0.32959 0,1.27442 -1.186523,-0.43946 -1.274414,-0.14648 -1.508789,0.30762 -0.498047,0.92285 0.358886,0.73975 0.763094,0.30189 0.76857,0.22893 0.785513,0.20842 0.813927,0.24037 0.809326,0.49988 0.455932,0.66833 0.151978,0.89173 -0.227051,1.02355 -0.681152,0.78553 -1.071167,0.49988 3.205262,0.0833 3.205261,0.0833 -1.376953,-0.13183 -1.501465,-0.38086 0,-1.3916 1.472168,0.58593 1.435547,0.19043 1.464843,-0.32226 0.512696,-0.92285 -0.373536,-0.84229 -1.038789,-0.41935 -1.048613,-0.25448 -1.078491,-0.33325 -0.730591,-0.47241 -0.556641,-1.50147 0.205078,-1.02539 0.615235,-0.76172 0.99243,-0.47241 1.336672,-0.15747 1.40625,0.10986 1.21582,0.32959 0,1.27442 -1.186524,-0.43946 -1.274414,-0.14648 -1.508789,0.30762 -0.498047,0.92285 0.358887,0.73975 0.805073,0.3095 0.76935,0.22988 0.764915,0.20509 0.791765,0.23514 0.809327,0.49988 0.455932,0.66833 0.151978,0.89173 -0.227051,1.02355 -0.681152,0.78553 -1.071167,0.49988 2.095642,-0.0229 2.095642,-0.0229 0,-1.36688 0,-1.36688 0,-1.36689 0,-1.36688 0,-1.36688 0,-1.36688 0,-1.36689 0,-1.36688 1.571045,0 1.571045,0 1.571045,0 1.571045,0 0,1.24512 -1.201172,0 -1.201172,0 -1.201172,0 -1.201172,0 0,0.80566 0,0.80567 0,0.80566 0,0.80566 1.083984,0 1.083985,0 1.083984,0 1.083985,0 0,1.24512 -1.083985,0 -1.083984,0 -1.083985,0 -1.083984,0 0,1.30554 0,1.30555 0,1.30554 0,1.30554 3.581543,0 3.581543,0 0,-1.36688 0,-1.36688 0,-1.36689 0,-1.36688 0,-1.36688 0,-1.36688 0,-1.36689 0,-1.36688 1.728516,0 1.728516,0 1.728515,0 1.728516,0 0,1.24512 -1.358643,0 -1.358642,0 -1.358643,0 -1.358643,0 0,0.80932 0,0.80933 0,0.80933 0,0.80932 1.30188,0 1.30188,0 1.30188,0 1.30188,0 0,1.24512 -1.30188,0 -1.30188,0 -1.30188,0 -1.30188,0 0,0.9906 0,0.9906 0,0.9906 0,0.9906 1.391602,0 1.391601,0 1.391602,0 1.391602,0 0,1.24512 -3.587581,3.8e-4 -1.964972,0 3.702844,0 4.295998,0 0,-1.36733 0,-1.36688 0,-1.36689 0,-1.36688 0,-1.36688 0,-1.36689 0,-1.36688 0,-1.36688 1.479492,0 0,1.21124 0,1.21124 0,1.21125 0,1.21124 0,1.21124 0,1.21124 0,1.21125 0,1.21124 1.331177,0 1.331177,0 1.331176,0 1.331177,0 0,1.24512 -1.70105,0 -1.701049,0 -1.70105,0"
d=d.split()
pts=np.ndarray((len(d)-1,2),dtype=np.float)
for i in xrange(pts.shape[0]):
pts[i,:]=map(float,d[i+1].split(','))
pts[0,:]=(0,0)
pts=pts.cumsum(0)
pts=pts[::-1,:]
pts=pts-pts[0]
pts*=width/pts[:,0].max()
if flipx: pts[:,0]=-pts[:,0]
if not flipy: pts[:,1]=-pts[:,1]
pts+=ofs
self.points=pts
verb=self.verbose
if verb&2:
self.plot_points(pts)
plt.show()
def gen_rand_points(self,n=107,scale=1000,ofs=(0,0)):
'generate random distributed points'
np.random.seed(0)
#data=np.random.randint(0,1000,(30,2))
pts=np.random.rand(n,2)*scale
pts+=ofs
self.points=pts
def gen_grid_points(self,w=10,h=10,pitch=100,rnd=.2,ofs=(0,0)):
'generates points in a grid with a given pitch and a bit randomness'
np.random.seed(0)
xx,yy=np.meshgrid(range(w), range(h))
pts=np.array([xx.reshape(-1),yy.reshape(-1)],dtype=np.float).transpose()*pitch
if rnd != 0:
pts+=(np.random.rand(pts.shape[0],2)*(rnd*pitch))
pts+=ofs
self.points=pts
def gen_spiral_points(self,rStart=1.,rInc=.2,numSeg=4,numCir=6, ofs=(0, 0)):
#rInc radius increment per circle
r=rStart+np.arange(numSeg*numCir)*(float(rInc)/numSeg)
ang=2.*np.pi/numSeg*np.arange(numSeg*numCir)
pts=np.vstack((np.sin(ang)*r,np.cos(ang)*r)).T
pts+=ofs
self.points=pts
def gen_closed_shifted(self,pitch=100,shift=5,mult=3):
'from the given points, close the path, and runs 9 times with small pitch'
pts=self.points
pts = np.vstack((pts, pts[-1]+(0,-50)))#add a new point outside of the grid
mn=pts.min(0)
mx=pts.max(0)
d=pts[0,:]-pts[-1,:]
l=np.sum(d)
bk=[]
if abs(d[1])>pitch: #make a vertical back move
s=np.sign(d[1])
n=np.ceil(np.abs(d[1])/pitch)
p=np.ndarray((n,2))
p[:,0]=pts[-1, 0]
p[:,1]=pts[-1, 1]+np.arange(1,n+1)*s*pitch
pts=np.vstack((pts,p))
if abs(d[0])>pitch: #make a horizonlat back move
s=np.sign(d[0])
n=np.ceil(np.abs(d[0])/pitch)
p=np.ndarray((n,2))
p[:,0]=pts[-1, 0]+np.arange(1,n+1)*s*pitch
p[:,1]=pts[-1, 1]
pts[-1, :]
pts=np.vstack((pts,p))
stack=[]
for y in np.arange(mult)*shift:
for x in np.arange(mult)*shift:
stack.append(pts+(x,y))
pts=np.vstack(stack)
#xx,yy=np.meshgrid(range(w), range(h))
#pts=np.array([xx.reshape(-1),yy.reshape(-1)],dtype=np.float).transpose()*pitch
#if xy:
#else:
# smlpitch
#pts+=ofs
self.points=pts
def sort_points(self,xy=False,grp_sz=None):
pts=self.points
verb=self.verbose
cnt=pts.shape[0]
idx=np.ndarray(cnt,dtype=np.int32)
if grp_sz is None:
grp_cnt=int(np.sqrt(cnt))
grp_sz=int(np.ceil(float(cnt)/grp_cnt))
else:
grp_sz=int(grp_sz)
grp_cnt=int(np.ceil(float(cnt)/grp_sz))
if xy==True:
idxA=1;idxB=0
else:
idxA=0;idxB=1
#sort points along idxA
pts=pts[pts[:,idxA].argsort()]
#group sorting along idxB
for i in range(grp_cnt):
a=i*grp_sz
#print a,a+grp_sz
if i%2:
idx[a:a+grp_sz]=a+pts[a:a+grp_sz,idxB].argsort()[::-1]
else:
idx[a:a+grp_sz]=a+pts[a:a+grp_sz,idxB].argsort()
#print(idx)
pts=pts[idx]
if verb&2:
DebugPlot.plot_points(pts)
plt.show()
self.points=pts
def opt_pts(self,fn):
'''
trial to optimize path by mofing trajectory, uload real path and move the points
to finally go trough the desired points
'''
fh=np.load(fn)
#res=rot.ActPos,x.ActPos,y.ActPos,rot.DesPos,x.DesPos,y.DesPos
#idx 0 1 2 3 4 5
rec=fh['rec']
pts=fh['pts']
desPos=rec[:,(3,2)]
idx=np.ndarray(shape=len(pts),dtype=np.int32)
for i in range(len(pts)):
l=desPos-pts[i,:]
l2=l[:,0]**2+l[:,1]**2
idx[i]=np.argmin(l2)
recPts=rec[idx,:]
ptsCorr=(pts-recPts[:,(1,0)]+recPts[:,(3,2)])
self.points=pts
self.ptsCorr=ptsCorr
print(ptsCorr)
def setup_gather(self,acq_per=1):
'''
setup the channels to gather
kwargs:
acq_per : acquire period: acquire data all acq_per servo loops (default=1)
'''
if self.comm is None: return
comm=self.comm
gt=self.gather
gt.set_phasemode(False)
if self.meta['sync_flag']&2:
address=("Motor[1].ActPos","Motor[2].ActPos","Motor[1].DesPos","Motor[2].DesPos","Coord[1].Q[11]")
else:
address=("Motor[1].ActPos","Motor[2].ActPos","Motor[1].DesPos","Motor[2].DesPos","Gate3[1].Chan[1].UserFlag")
gt.set_address(*address)
gt.set_property(MaxSamples=1000000, Period=acq_per)
self.meta.update({'acq_per':acq_per,'address':address})
def setup_coord_trf(self):
if self.comm is None: return
comm = self.comm
gpascii = comm.gpascii
prg = '''&1a
#1-> Y
#2-> X
#3-> A
#4->0
#5->0
#6->0
#7->0
#8->0
#1..8j/
'''
gpascii.send_block(prg)
def setup_motion(self,prgId=2,fnPrg=None,mode=0,**kwargs):
'''
1. generates program <prgId> and saves to fnPrg
the type of generated program is defined by <mode>
2. runs the program on the deltatau
mode=1 pvt motion
kwargs:
scale : scaling velocity (default=1. value=0 would stop at the point
cnt : move path multiple times (default=1)
dwell : dwell time at end (default=100ms)
mode=3 pvt motion using inverse fft velocity
kwargs: same as pvt motion
numPad : number of padding points to reduce aliasing (default=16)
'''
prg=['close all buffers','open prog %d'%(prgId)]
comm=self.comm
if comm is not None:
gpascii=comm.gpascii
# this uses Coord[1].Tm and limits with MaxSpeed
if mode in (1,3): #### pvt motion
pt2pt_time=self.meta['pt2pt_time']
ts=self.meta['srv_per']
scale=kwargs.get('scale', 1.)
cnt=kwargs.get('cnt', 1) # move path multiple times
dwell=kwargs.get('dwell', 100) # synchronization mark all n points
CoordFeedTime=1000. #Defaut deltatau value
try:
pt=self.ptsCorr
except AttributeError:
pt=self.points
#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:
n=-numPad
pv[ 1:-1,(2,3)] = v[:n]*scale
verb=self.verbose
if verb&16:
dp=DebugPlot(self);self.pvt=dp.plot_gen_pvt(pv)
plt.show()
pv[1:-1, (2, 3)]*=CoordFeedTime #scaling for Deltatau
prg.append(' linear abs')
prg.append('X%g Y%g' % tuple(pv[0, (0,1)]))
prg.append('dwell 10')
try: prg.extend(self.sync_prg.split('\n'))
except AttributeError:
#print('no sync code available')
prg.append('Gather.Enable=2')
if cnt>1:
prg.append('P100=%d'%cnt)
prg.append('N100:')
prg.append(' pvt%g abs'%pt2pt_time) #100ms to next position
for idx in range(1,pv.shape[0]):
prg.append('X%g:%g Y%g:%g'%tuple(pv[idx,(0,2,1,3)]))
prg.append('X%g Y%g' % tuple(pv[-1, (0,1)]))
if cnt>1:
prg.append('dwell 10')
prg.append('P100=P100-1')
prg.append('if(P100>0)')
prg.append('{')
prg.append(' linear abs')
prg.append('X%g Y%g' % tuple(pv[0, (0,1)]))
prg.append('dwell %d' % dwell)
prg.append('goto 100')
prg.append('}')
else:
prg.append('dwell %d'%dwell)
prg.append('Gather.Enable=0')
prg.append('close')
#prg.append('&1\nb%dr\n'%prgId)
if self.verbose & 4:
for ln in prg:
print(ln)
if fnPrg is not None:
fh=open(fnPrg,'w')
fh.write('\n'.join(prg))
fh.close()
if comm is not None:
gpascii.send_block(prg)
self.prg=prg
def gather_upload(self,fnRec=None):
gt=self.gather
gt.wait_stopped(verbose=True)
self.rec=rec=gt.upload()
try:
syncShell=self.syncShell
except AttributeError: pass
else:
print(syncShell.sync())
del self.syncShell
pts=self.points
ofsy=-rec[0,2]+pts[0,1]
ofsx=-rec[0,3]+pts[0,0]
rec[:,(1,3)]+=ofsx
rec[:,(0,2)]+=ofsy
if fnRec:
np.savez_compressed(fnRec, rec=rec, pts=pts, meta=self.meta)
if __name__=='__main__':
#import logging
#logger = logging.getLogger(__name__)
#logger = logging.getLogger('pbtools.misc.pp_comm')
#logger.setLevel(logging.DEBUG)
#logging.basicConfig(format=('%(asctime)s %(name)-12s '
# '%(levelname)-8s %(message)s'),
# datefmt='%m-%d %H:%M',
# )
def unique_filename(fnBase):
i = 0;
while (True):
fn=fnBase+('%0.3d'%i)
i+=1
if not os.path.exists(fn+'.npz'):
print('save to '+fn+'.*')
break
return fn
def run_test(args):
#dp=DebugPlot();dp.plot_gather();return
#args.host=None
if args.host is None:
comm=gather=None
else:
comm = PPComm(host=args.host)
gather = Gather(comm)
#real start and frame trigger with sync
#sp = ShapePath(comm, gather, args.verbose)
# direct start
#sp = ShapePath(comm, gather, args.verbose,sync_mode=0)
#simulated start and frame trigger no sync
#sp = ShapePath(comm, gather, args.verbose,sync_mode=1,sync_flag=3)
#simulated start and frame trigger with sync
#sp = ShapePath(comm, gather, args.verbose,sync_mode=2,sync_flag=3)
#simulated start real frame trigger no sync
#sp = ShapePath(comm, gather, args.verbose,sync_mode=1,sync_flag=1)
#simulated start real frame trigger with sync
sp = ShapePath(comm, gather, args.verbose,sync_mode=2,sync_flag=1)
fn='/tmp/shapepath'
#fn =unique_filename('ShapePathAnalyser/records/19_01_24/spiral')
# Gather.MaxLines=116508
# ts=0.2ms
# max_num_points=(MaxLines*ts-1000ms)/(+acq_per*pt2pt_time*ts)
# pt2pt_time acq_per maxpts
# 40ms 1 555
# 40ms 2 1135
# 40ms 3 1715
# 40ms 4 2295
# 10ms 1 2220
# 10ms 2 4540
# 10ms 3 6860
# 10ms 4 9180
#xy=False
#sp.gen_grid_points(w=6,h=6,pitch=100,rnd=0,ofs=(0,0));sp.sort_points(False);
#sp.gen_grid_points(w=100,h=100,pitch=10,rnd=.2)
#sp.gen_swissfel_points(width=1000,ofs=(-500,0));sp.sort_points(xy=xy)
#sp.gen_grid_points(w=10,h=10,pitch=50,rnd=.2)
#sp.gen_grid_points(w=100,h=100,pitch=50,rnd=.2)
#sp.gen_closed_shifted()
#sp.gen_swissmx_points(width=1000,ofs=(-500,0))
#sp.gen_swissfel_points(width=1000,ofs=(-500,0))
#sp.gen_rand_points(n=14, scale=1000);sp.sort_points(xy=xy)
#sp.gen_swissmx_points(width=1000, ofs=(-500, 0));
#sp.gen_spiral_points(rStart=100,rInc=10,numSeg=4,numCir=60, ofs=(0, 0))
#sp.gen_spiral_points(rStart=100,rInc=130,numSeg=4,numCir=2, ofs=(0, 0))
#sp.gen_grid_points(w=10,h=10,pitch=100,rnd=0,ofs=(0,0));sp.sort_points(False);
#sp.gen_grid_points(w=1,h=10,pitch=100,rnd=0,ofs=(0,0))
sp.gen_spiral_points(rStart=100,rInc=20,numSeg=8,numCir=32, ofs=(0, 0))
#sp.gen_closed_shifted()
sp.setup_gather(acq_per=1)
sp.setup_sync(verbose=args.verbose&32)
sp.setup_coord_trf() # reset to shape path system
sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1,dwell=10)
#sp.setup_motion(fnPrg=fn + '.prg', mode=1, scale=1,dwell=10)
#sp.setup_motion(fnPrg=fn + '.prg', mode=1, scale=0,dwell=10)
sp.homing() #homing if needed
sp.run() #start motion program
sp.wait_armed() # wait until motors are at first position
sp.trigger(0.5) #send a start trigger (if needed) ater given time
while True:
p=sp.progress()
if p<0: break
print('progress %d'%p);time.sleep(.1)
sp.gather_upload(fnRec=fn+'.npz')
dp=DebugPlot(sp);dp.plot_gather(mode=11)
print('done')
plt.show(block=False)
raw_input('press return')
#sp.plot_points(sp.points);plt.show()
#>>>run gather and plot trajectory<<<
#return
from optparse import OptionParser, IndentedHelpFormatter
class MyFormatter(IndentedHelpFormatter):
'helper class for formating the OptionParser'
def __init__(self):
IndentedHelpFormatter.__init__(self)
def format_epilog(self, epilog):
if epilog:
return epilog
else:
return ""
def parse_args():
'main command line interpreter function'
#usage: gpasciiCommunicator.py --host=PPMACZT84 myPowerBRICK.cfg
(h, t)=os.path.split(sys.argv[0]);cmd='\n '+(t if len(h)>3 else sys.argv[0])+' '
exampleCmd=('-n',
'-v15'
)
epilog=__doc__+'''
Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
fmt=MyFormatter()
parser=OptionParser(epilog=epilog, formatter=fmt)
parser.add_option('-v', '--verbose', type="int", dest='verbose', help='verbosity bits (see below)', default=0)
parser.add_option('--host', help='hostname', default='SAR-CPPM-EXPMX1')
#parser.add_option('--host', help='hostname')
(args, other)=parser.parse_args()
args.other=other
run_test(args)
#------------------ Main Code ----------------------------------
#ssh_test()
ret=parse_args()
exit(ret)