diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/python/data/prog_1.npz b/python/data/prog_1.npz new file mode 100644 index 0000000..9c3b682 Binary files /dev/null and b/python/data/prog_1.npz differ diff --git a/python/move_record.py b/python/move_record.py new file mode 100755 index 0000000..e4e312e --- /dev/null +++ b/python/move_record.py @@ -0,0 +1,275 @@ +#!/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 + 4 list program + 4 upload progress + 8 plot gather path + +#config file example: +{ + "points": [ + [100,523],[635,632],[756,213], + "sequencer":[ + 'gen_grid_points(w=10,h=10,pitch=100,rnd=.2)', + 'sort_points()', + 'gen_prog(file="'+fn+'.prg")', + 'plot_gather("'+fn+'.npz")'] +} + +Sequencer functions are: + - generate points (if not in the 'points' configuration) + gen_rand_points(self,n=107,scale=1000) + gen_grid_points(w=10,h=10,pitch=100,rnd=.2) + - sorting points: + sort_points(self) + - generate/download/execute motion progran, upload trace of motors (gather data) + gen_prog(self,prgId=2,file=None,host=None) + if host=None nothing will be downloaded/executed and trace of motors will not be uploaded + if file=None the program will not be saved and nothing will be executed + gen_prog modes: + -1 jog a 10mm square + 0 linear motion + 1 pvt motion + 2 spline motion + + + - plot gathered data + plot_gather("'+fn+'.npz") + this makes only sence, if motion has been executed and data can be gathered from the powerbrick + +Acquired time is:MaxSamples*Period*.2 +''' + +import os, sys, json +import numpy as np +import matplotlib as mpl +import matplotlib.pyplot as plt +import subprocess as sprc +import telnetlib +from utilities import * + +os.environ['PATH']='/home/zamofing_t/scripts/:'+os.environ['PATH'] + +class MoveRecord: + def __init__(self,args): + fn='/tmp/moverecord' + self.fnPrg=fn+'.prg' + self.fnNpz=fn+'.npz' + #cfg = {"sequencer": ['prog_1(host="SAROP11-CPPM-MOT6871",acq_per=10)', 'plot_1()']} + cfg = {"sequencer": ['plot_1()']} + self.cfg=dotdict(cfg) + self.args=args + + def run(self): + print('args='+str(self.args)) + print('cfg='+str(self.cfg)) + try: + sequencer= self.cfg.pop('sequencer') + except KeyError: + print('no command sequence to execute') + else: + for cmd in sequencer: + print '>'*5+' '+cmd+' '+'<'*5 + eval('self.' + cmd) + + def prg_prolog(self): + prg=self.prg + gather=self.gather + channels=self.channels + prg.append('Gather.Enable=0') + prg.append('Gather.Items=%d'%len(channels)) + for k,v in gather.iteritems(): + prg.append('Gather.%s=%d'%(k,v)) + for i,c in enumerate(channels): + prg.append('Gather.Addr[%d]=%s.a'%(i,c)) + prg.append('open prog %d'%(self.prgId)) + + def prg_epilog(self): + fnPrg=self.fnPrg + fnNpz=self.fnNpz + host=self.host + prg=self.prg + + prg.append('close') + prg.append('&1\nb%dr\n'%self.prgId) + if self.args.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 host is not None: + cmd ='gpasciiCommander --host '+host+' '+ fnPrg + print cmd + p = sprc.Popen(cmd, shell=True)#, stdout=sprc.PIPE, stderr=sprc.STDOUT) + #res=p.stdout.readlines(); print res + retval = p.wait() + #gather -u /var/ftp/gather/out.txt + cmd ='PBGatherPlot -m24 -v7 --host '+host + print cmd + p = sprc.Popen(cmd, shell=True)#, stdout=sprc.PIPE, stderr=sprc.STDOUT) + retval = p.wait() + + meta = self.meta + channels = self.channels + fnLoc='/tmp/gather.txt' + rec = np.genfromtxt(fnLoc, delimiter=' ') + # rec=Motor[1].ActPos,Motor[2].ActPos,Motor[3].ActPos,Motor[1].DesPos,Motor[2].DesPos,Motor[3].DesPos + # res=rot.ActPos,y.ActPos,x.ActPos,rot.DesPos,y.DesPos,x.DesPos + # idx 0 1 2 3 4 5 + if fnNpz: + np.savez_compressed(fnNpz, rec=rec, prg=self.prg, channels=self.channels, meta=meta) + + def prog_1(self,prgId=2,host=None,acq_per=1): + ''' + kwargs: + acq_per : acquire period: acquire data all acq_per servo loops (default=1) + prgId : used program number + file : used filename to save if None, not saved + host : host to send and execute program, if None, nothing is executed + ''' + ServoPeriod= .2 #0.2ms Sys.ServoPeriod is dependent of !common() macro + + self.prgId=prgId + self.file=file + self.host=host + self.gather={"MaxSamples":1000000, "Period":acq_per} + self.channels=["Motor[3].ActPos","Motor[3].DesPos","Motor[3].PhasePos","Motor[3].idMeas","Motor[3].iqMeas"] + self.meta=meta = {'timebase': ServoPeriod*self.gather['Period']} + + self.prg=prg=[] + #prg.append('#1..3$') + #prg.append('#1..3j/') + + self.prg_prolog() + prg=self.prg + + prg.append(' linear abs') + prg.append('jog3=1000') + prg.append('dwell 100') + prg.append('Gather.Enable=2') + for spd in (5,10,20,30,40): + prg.append('Motor[3].JogSpeed=%d'%spd) + prg.append('jog3=27000') + prg.append('dwell 100') + prg.append('jog3=1000') + prg.append('dwell 100') + prg.append('Gather.Enable=0') + + self.prg_epilog() + # &1 #1->0 + # &1 #2->0 + # #3$ + # an anschlag (kabel) bewegen + # #3hmz + # Motor[3].PhasePos=1200 + # #3j/ + # &1p + + + #folgende parameter setzen: Motor[3].HomePos + meta['HomePos']=-223.8 #Motor[3].HomePos + meta['PhasePos']=1200 #Motor[3].PhasePos + + @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 + + def plot_1(self): + try: + rec=self.rec + prg=self.prg + channels=self.channels + meta=self.meta + except AttributeError: + fh=np.load(self.fnNpz) + rec=fh['rec'] + prg=list(fh['prg']) + channels=list(fh['channels']) + meta=fh['meta'].item() + + time=np.arange(0,rec.shape[0])*meta['timebase'] + + fig=plt.figure(); + fig.obj=self; cid=fig.canvas.mpl_connect('button_press_event', self.onclick) + fig.canvas.set_window_title('position') + ax = fig.add_subplot(1,1,1) + hl=[] + hl+=ax.plot(time,rec[:,0],'r-',label=channels[0]) + hl+=ax.plot(time,rec[:,1],'g-',label=channels[1]) + hl+=ax.plot(time,rec[:,2],'b-',label=channels[2]) + ax.xaxis.set_label_text('ms') + ax.yaxis.set_label_text('um') + legend = ax.legend(loc='upper right', shadow=True) + + fig=plt.figure(); + fig.obj=self; cid=fig.canvas.mpl_connect('button_press_event', self.onclick) + fig.canvas.set_window_title('current') + ax = fig.add_subplot(1,1,1) + hl=[] + sz=100; weights = np.repeat(1.0, sz) / sz + v = np.convolve(rec[:,3], weights, 'same') + hl+=ax.plot(time,v,'r-',label=channels[3]) + v = np.convolve(rec[:, 4], weights, 'same') + hl+=ax.plot(time,v,'g-',label=channels[4]) + ax.xaxis.set_label_text('ms') + ax.yaxis.set_label_text('current in bits') + legend = ax.legend(loc='upper right', shadow=True) + print 'abs average ',channels[4], np.abs(rec[:, 4]).mean() + + + plt.show() + +if __name__=='__main__': + 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=('--host=PPMAC1391 -m 63 --cfg gather.cfg', + 'samplePowerBrick.cfg', + '-n stackCheck1.cfg', + '--host=PPMACZT84 stackCheck1.cfg', + '--host=PPMACZT84 stackCheck1.cfg -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) + (args, other)=parser.parse_args() + args.other=other + + mr=MoveRecord(args) + mr.run() +#------------------ Main Code ---------------------------------- + #ssh_test() + ret=parse_args() + exit(ret) diff --git a/python/shapepath.py b/python/shapepath.py index aa6f98d..bbc448c 100755 --- a/python/shapepath.py +++ b/python/shapepath.py @@ -83,10 +83,10 @@ class ShapePath: #cfg = {"points": [[0, 0],[100, 0],[200, 0],[300, 0],[400, 0],[400, 100],[300, 100],[200, 100],[100, 100],[0, 100],[10, 200],[100, 200],[200, 200],[300, 200],[400, 200],[410, 300],[300, 300],[200, 300],[100, 300],[0, 300],[0, 400],[100, 400],[200, 400],[300, 400],[400, 400]],"sequencer": ['gen_prog(file="'+fn+'.prg",host="SAROP11-CPPM-MOT6871",mode=0)', 'plot_gather("'+fn+'.npz")']} #cfg = {"sequencer": ['gen_grid_points(w=2,h=2,pitch=10000,rnd=0)', 'sort_points()','gen_prog(file="'+fn+'.prg",host="SAROP11-CPPM-MOT6871",mode=-1)', 'plot_gather("'+fn+'.npz")']} #cfg = {"sequencer": ['gen_grid_points(w=2,h=2,pitch=10000,rnd=0)', 'sort_points()','gen_prog(file="'+fn+'.prg",host="SAROP11-CPPM-MOT6871",mode=1,pt2pt_time=1000)', 'plot_gather("'+fn+'.npz")']} - cfg = {"sequencer": ['gen_grid_points(w=20,h=20,pitch=100,rnd=0.2)', 'sort_points()','gen_prog(file="'+fn+'.prg",host="SAROP11-CPPM-MOT6871",mode=1,pt2pt_time=10,acq_per=10)', 'plot_gather("'+fn+'.npz")']} + cfg = {"sequencer": ['gen_grid_points(w=20,h=20,pitch=50,rnd=0.2)', 'sort_points()','gen_prog(file="'+fn+'.prg",host="SAROP11-CPPM-MOT6871",mode=1,pt2pt_time=10,acq_per=10)', 'plot_gather("'+fn+'.npz")']} #cfg = {"sequencer": ['gen_rand_points(n=400, scale=1000)', 'sort_points()','gen_prog(file="'+fn+'.prg",host="SAROP11-CPPM-MOT6871",mode=1,pt2pt_time=10)', 'plot_gather("'+fn+'.npz")']} #cfg = {"sequencer": ['gen_grid_points(w=5,h=5,pitch=100,rnd=0.2)', 'sort_points()','gen_prog(file="'+fn+'.prg",host="SAROP11-CPPM-MOT6871",mode=2,pt2pt_time=10)', 'plot_gather("'+fn+'.npz")']} - #cfg = {"sequencer":['gen_rand_points(n=400, scale=1000)','sort_points()','gen_prog(file="'+fn+'.prg",host="SAROP11-CPPM-MOT6871",mode=1,pt2pt_time=10)','plot_gather("'+fn+'.npz")']} + #cfg = {"sequencer":['gen_rand_points(n=400, scale=1000)','sort_points()','gen_prog(file="'+fn+'.prg",host="SAROP11-CPPM-MOT6871",mode=1,pt2pt_time=10,acq_per=1)','plot_gather("'+fn+'.npz")']} self.cfg=dotdict(cfg) self.args=args @@ -130,8 +130,8 @@ class ShapePath: pt2pt_time : time to move from one point to the next point ''' prg=[] - acq_frq=kwargs.get('acq_frq',1) - gather={"MaxSamples":1000000, "Period":acq_frq} + acq_per=kwargs.get('acq_per',1) + gather={"MaxSamples":1000000, "Period":acq_per} #Sys.ServoPeriod is dependent of !common() macro ServoPeriod= .2 #0.2ms #ServoPeriod = .05