diff --git a/python/PBTuning.py b/python/PBTuning.py new file mode 100755 index 0000000..bad529e --- /dev/null +++ b/python/PBTuning.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +# *-----------------------------------------------------------------------* +# | | +# | Copyright (c) 2016 by Paul Scherrer Institute (http://www.psi.ch) | +# | | +# | Author Thierry Zamofing (thierry.zamofing@psi.ch) | +# *-----------------------------------------------------------------------* +''' +tuning functions for deltatau: +For now it does 10 step move and uploads the data +other available tuning progs on the powerbrick are: + analyzerautotunemove + autotunecalc + autotunemove + chirpmove + currentautotunecalc + currentstep + filtercalculation + openloopchirp + openloopsine + openlooptestmove + othertrajectory + parabolicmove + randommove + sinesweep + sinusoidal + stepmove + user_gantry_crosscoupled.h + usertrajectory + +TODO: +use openloopsine to create a bode diagram of the 'strecke' +''' + +import os, sys, json, time +import numpy as np +import matplotlib as mpl +#mpl.use('GTKAgg') +import matplotlib.pyplot as plt +import subprocess as sprc +import telnetlib +from utilities import * + +class PBTuning: + tuneDir='/opt/ppmac/tune/' + + def __init__(self,args): + self.args=args + + def do_command(self,cmd,*param): + args=self.args + host=args.host + cmd=('ssh','root@'+host, self.tuneDir+cmd)+tuple(map(str,param)) + p=sprc.Popen(cmd, shell=False, stdin=sprc.PIPE, stdout=sprc.PIPE, stderr=sprc.PIPE) + res=p.wait() + print(res) + print(p.stderr.read()) + print(p.stdout.read()) + PBGatherPlot='/home/zamofing_t/scripts/PBGatherPlot' + try: + fnLoc=self.fnLoc + except AttributeError: + fnLoc = '/tmp/gather.txt' + cmd=(PBGatherPlot,'-m24','-v0','--host',host,'--dat',fnLoc) + p = sprc.Popen(cmd, shell=False, stdin=sprc.PIPE, stdout=sprc.PIPE, stderr=sprc.PIPE) + retval = p.wait() + print(p.stderr.read()) + #print(p.stdout.read()) + + #self.meta = {'timebase': ServoPeriod*gather['Period']} + self.data = np.genfromtxt(fnLoc, delimiter=' ') + return self.data + + def phase_amp(self,frq,rep): + try: + ax1=self.ax1 + ax2=self.ax2 + ax1.clear() + ax2.clear() + except AttributeError: + fig = plt.figure(); self.ax1=ax1 = fig.add_subplot(1, 1, 1) + fig = plt.figure(); self.ax2=ax2 = fig.add_subplot(1, 1, 1) + n = self.data.shape[0] + w=np.hamming(n) + res=np.ndarray((2,2)) + col=('b-','g-') + for i in (0,1): + data=self.data[:,i] + data=(data-data[0])*w + ax1.plot(data, col[i]) + f = np.fft.fft(data) + ax2.plot(np.absolute(f) , col[i]) + idx = int(rep) + bias = np.absolute(f[0] / n) + phase = np.angle(f[idx]) + #ampl = np.absolute(f[idx]) * 2 / n + ampl = np.absolute(f[idx]) * 2 / w.sum() + res[i,:]=(ampl,phase) + plt.pause(.05) + return (res[1,0]/res[0,0],res[1,1]-res[0,1]) + + def bode_gather(self,motor=1,minFrq=1,maxFrq= 100,numFrq= 100,amp=10,file='/tmp/bode.npz'): + #amp= percentage of maximum amplitude + fig = plt.figure() + ax = fig.add_subplot(1, 1, 1) + frqLst=np.logspace(np.log10(minFrq),np.log10(maxFrq),numFrq) + n=len(frqLst) + #frqLst=(10,15,20,25,30) + bode=np.ndarray((n,3)) + bode[:, 0]=frqLst + for i in range(n): + frq=frqLst[i] + t=1 + rep=max(1,frq*t) + self.fnLoc='/tmp/gather%d.txt'%i + data=self.do_command('openloopsine',motor,amp,frq,rep,0) + ax.clear() + ax.plot(data[:, 0]-data[0, 0] , 'b-', label='input') + ax.plot(data[:, 1]-data[0, 1], 'g-', label='output') + plt.pause(.05) + bode[i,1:]=self.phase_amp(frq, rep) + print('frq %g ampl %g phase %g'%tuple(bode[i,:])) + plt.draw_all() + + fig = plt.figure() + ax = fig.add_subplot(2, 1, 1) + ax.semilogx(frqLst, bode[:,0]) # Bode magnitude plot + #ax.loglog(frqLst, bode[:,0],'.-') # Bode magnitude plot + ax = fig.add_subplot(2, 1, 2) + ax.semilogx(frqLst, bode[:,1]) # Bode phase plot + plt.show() + meta={'motor':motor,'date':time.asctime()} + np.savez_compressed(file, bode=bode, meta=meta) + + def bode_plot(self,file): + f=np.load(file) + bode=f['bode'] + meta=f('meta') + frq=bode[:,0] + db_mag=20*np.log10(bode[:,1]) + phase=np.unwrap(bode[:,2])# numpy.unwrap(p, discont=3.141592653589793, axis=-1) + fig = plt.figure() + ax = fig.add_subplot(2, 1, 1) + ax.semilogx(frq, db_mag,'.-') # Bode magnitude plot + ax.xaxis.set_label_text('dB Mag.') + #ax.loglog(frqLst, bode[:,0],'.-') # Bode magnitude plot + ax = fig.add_subplot(2, 1, 2) + ax.semilogx(frq, phase,'.-') # Bode phase plot + ax.xaxis.set_label_text('phase') + plt.show() + + +if __name__=='__main__': + from argparse import ArgumentParser,RawDescriptionHelpFormatter + 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 ' + + parser=ArgumentParser(epilog=epilog,formatter_class=RawDescriptionHelpFormatter) + + parser.add_argument('--host', help='hostname', metavar='HOST', required=True) + parser.add_argument('--verbose', '-v', type=int, help='verbosity bits (see below)', default=0) + parser.add_argument('--dryrun', '-n', action='store_true', help='dryrun to stdout') + args=parser.parse_args() + + plt.ion() + tune=PBTuning(args) + base='/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/data/' + file=sys.path.join(base,'bode1.npz') + tune.bode(file=file,motor=1) + tune.bode_plot(file) + #tune.do_command('stepmove',1,100,500,0,0) + #------------------ Main Code ---------------------------------- + #ssh_test() + ret=parse_args() + exit(ret) diff --git a/python/shapepath.py b/python/shapepath.py index 89431ef..1dfc3f7 100755 --- a/python/shapepath.py +++ b/python/shapepath.py @@ -86,7 +86,7 @@ class ShapePath: #cfg = {"sequencer": ['gen_grid_points(w=20,h=20,pitch=50,rnd=0.2)', 'sort_points()','gen_prog(file="'+fn+'.prg",host="SAR-CPPM-EXPMX1",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="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=10)', 'plot_gather("'+fn+'.npz")']} cfg = {"sequencer": ['gen_grid_points(w=40,h=40,pitch=100,rnd=0.4)', 'sort_points()','gen_prog(file="'+fn+'.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=10,cnt=1)', 'plot_gather("'+fn+'.npz")']} - #cfg = {"sequencer":['gen_rand_points(n=400, scale=1000)','sort_points()','gen_prog(file="'+fn+'.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=20,acq_per=10)','plot_gather("'+fn+'.npz")']} + cfg = {"sequencer":['gen_rand_points(n=900, scale=1000)','sort_points()','gen_prog(file="'+fn+'.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=40,acq_per=10)','plot_gather("'+fn+'.npz")']} #cfg = {"sequencer": ['gen_swissfel_points(scale=300)','gen_prog(file="'+fn+'.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=100,acq_per=10)', 'plot_gather("'+fn+'.npz")']} #cfg = {"sequencer": ['opt_pts("'+fn+'.npz")','gen_prog(file="'+fn+'_corr.prg",host="SAR-CPPM-EXPMX1",mode=1,pt2pt_time=10,cnt=1)', 'plot_gather("'+fn+'_corr.npz")']} #cfg = {"sequencer": ['opt_pts("'+fn+'.npz")','gen_prog(file="'+fn+'.prg",mode=1,pt2pt_time=10,cnt=1)']}