massive move and cleanup
@@ -1,142 +0,0 @@
|
||||
% FK/IK using homogenous matrices %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%
|
||||
% This script demonstrates how homogenous matrices can be used to create
|
||||
% both a forward kinematics (FK)and an inverse kinematics (IK) model of
|
||||
% a serial kinematics manipulator, with 5 % motors (q1,q2,q3,q4,q5)
|
||||
% and 4 user coordinates (X,Y,Z,theta).
|
||||
%
|
||||
% The script uses a chain of Homogenous Transformation Matrices to create
|
||||
% the FK model. And the Moore-Penrose Pseudo-Inverse of the Jacobian
|
||||
% to iteratively solve the IK model (Newton-Raphson).
|
||||
%
|
||||
% 5.10.2017 Wayne Glettig
|
||||
|
||||
clear all;
|
||||
syms offsetX offsetY offsetZ ...
|
||||
alpha beta gamma...
|
||||
q1 q2 q3 q4 q5;
|
||||
|
||||
%% Here the Transformation Matrix HBA is constructed from a translation
|
||||
% matrix and 3 rotation matrices, using symbolic variables.
|
||||
%Translation:
|
||||
HXYZ = [1,0,0,offsetX;...
|
||||
0,1,0,offsetY;...
|
||||
0,0,1,offsetZ;...
|
||||
0,0,0,1];
|
||||
%Rot around X:
|
||||
HRX = [1,0 ,0 ,0;...
|
||||
0,cos(alpha),-sin(alpha),0;...
|
||||
0,sin(alpha), cos(alpha),0;...
|
||||
0,0 ,0 ,1];
|
||||
%Rot around Y:
|
||||
HRY = [ cos(beta),0,sin(beta),0;...
|
||||
0 ,1,0 ,0;...
|
||||
-sin(beta),0,cos(beta),0;...
|
||||
0 ,0,0 ,1];
|
||||
%Rot around Z:
|
||||
HRZ = [cos(gamma),-sin(gamma),0,0;...
|
||||
sin(gamma), cos(gamma),0,0;...
|
||||
0 ,0 ,1,0;...
|
||||
0 ,0 ,0,1];
|
||||
%Create HBA (first rotation then translation)
|
||||
HBA=HXYZ*HRZ*HRY*HRX;
|
||||
%Create HAB (inverse)
|
||||
HAB=inv(HBA);
|
||||
|
||||
|
||||
%% Here the Kinematic Chain is created (q1,q2,q3,q4,q5 are motor coordinates)
|
||||
%Essentially the HBA matrix above is filled with the offsetXYZ and angle
|
||||
%values to assemble the chain. The chain consists here of the reference
|
||||
%frames 0-1-2-3-4-5-6-7:
|
||||
%Frame 0: MATLAB darstellungsframe (for plot3)
|
||||
%Frame 1: Beamline UCS
|
||||
%Frame 2: on Z Stage
|
||||
%Frame 3: on X Stage
|
||||
%Frame 4: on RX Stage
|
||||
%Frame 5: on Fast X Stage
|
||||
%Frame 6: on Fast Y Stage
|
||||
%Frame 7: Sample pos
|
||||
|
||||
H10 = subs(HBA,[offsetX,offsetY,offsetZ,alpha,beta,gamma],...
|
||||
[0,0,0,90/180*pi,0/180*pi,90/180*pi]);
|
||||
H21 = subs(HBA,[offsetX,offsetY,offsetZ,alpha,beta,gamma],...
|
||||
[0,0,q1,0,0,0]); %Z Stage
|
||||
H32 = subs(HBA,[offsetX,offsetY,offsetZ,alpha,beta,gamma],...
|
||||
[q2,0,0,0,0,0]); %X Stage
|
||||
H43 = subs(HBA,[offsetX,offsetY,offsetZ,alpha,beta,gamma],...
|
||||
[0,0,0,0,q3/180*pi,0]); %Rotation RY
|
||||
H54 = subs(HBA,[offsetX,offsetY,offsetZ,alpha,beta,gamma],...
|
||||
[q4,0,0,0,0,0]); %Fast Stage X
|
||||
H65 = subs(HBA,[offsetX,offsetY,offsetZ,alpha,beta,gamma],...
|
||||
[0,q5,0,0,0,0]); %Fast Stage Y
|
||||
H76 = subs(HBA,[offsetX,offsetY,offsetZ,alpha,beta,gamma],...
|
||||
[0,0,0,0,0,0]); %sample Offset
|
||||
H70 = H10*H21*H32*H43*H54*H65*H76;
|
||||
H07 = inv(H70);
|
||||
|
||||
%% The FK model (forward kinematics) can be defined as
|
||||
% [X;Y;Z;theta] = f(q1,q2,q3,q4,q5)
|
||||
H71 = H21*H32*H43*H54*H65*H76; %UCS: reference frame 1
|
||||
f= H71*[0;0;0;1]; %XYZ position of orgin of reference frame 7
|
||||
f(4)=q3; %theta angle directly connected to q3
|
||||
|
||||
%% The IK model is more difficult to find. Different IK solution methods
|
||||
% exist, this is one of the basic ones, using the Pseudo-inverse of the
|
||||
% Jacobian matrix to converge a solution towards a solution
|
||||
% (Newton-Raphson)
|
||||
|
||||
% Jacobian of FK f function derived over motor coordinates
|
||||
J= jacobian(f,[q1,q2,q3,q4,q5]);
|
||||
Jinv = pinv(J);
|
||||
|
||||
tic
|
||||
% Algorithm for IK (q are motor coords, x are user coords)
|
||||
xt=[2;1;0;32]; %SET TARGET USER COORDS
|
||||
q0=[0;0;0;0;0]; %motor start values
|
||||
qc = q0; %set current q values for loop
|
||||
loopcond = 1;
|
||||
loopcounter=0;
|
||||
while loopcond
|
||||
xc = vpa(subs(f, [q1,q2,q3,q4,q5], qc')); %get current x values based on q
|
||||
deltax=xt-xc; %get x error (target - current)
|
||||
if abs(deltax)<1e-9 %if abs error small enough, get out of loop
|
||||
loopcond=0;
|
||||
end
|
||||
Jinvc=vpa(subs(Jinv, [q1,q2,q3,q4,q5], qc')); %inv Jacobian with current q
|
||||
deltaq=Jinvc*deltax; %By multiplying the x error with Jinv, a q correction can be deduced
|
||||
qc = qc+deltaq;%update current motor values
|
||||
loopcounter=loopcounter+1;
|
||||
end
|
||||
q = qc %output q as the motor coordinates
|
||||
toc
|
||||
|
||||
%% Plot the results (construct sample position using motors)
|
||||
Oin1 = [0;0;0;1];
|
||||
e1in1 = [1;0;0;1];
|
||||
e2in1 = [0;1;0;1];
|
||||
e3in1 = [0;0;1;1];
|
||||
|
||||
clf;
|
||||
hold on;
|
||||
grid on;
|
||||
axis vis3d;
|
||||
axis([-10 10 -10 10 -10 10]);
|
||||
title('Sample Position, constructed with (q1,q2,q3,q4,q5)');
|
||||
xlabel('Beamline Z-Axis');
|
||||
ylabel('Beamline X-Axis');
|
||||
zlabel('Beamline Y-Axis');
|
||||
|
||||
|
||||
for i= 0:1
|
||||
H60c = subs(H70, [q1 q2 q3, q4, q5], q');
|
||||
|
||||
Oin0 = H60c*Oin1;
|
||||
e1in0 = H60c*e1in1;
|
||||
e2in0 = H60c*e2in1;
|
||||
e3in0 = H60c*e3in1;
|
||||
|
||||
plot3([Oin0(1),e1in0(1)],[Oin0(2),e1in0(2)],[Oin0(3),e1in0(3)],'r-');
|
||||
plot3([Oin0(1),e2in0(1)],[Oin0(2),e2in0(2)],[Oin0(3),e2in0(3)],'g-');
|
||||
plot3([Oin0(1),e3in0(1)],[Oin0(2),e3in0(2)],[Oin0(3),e3in0(3)],'b-');
|
||||
plot3([-10,0],[0,0],[0,0],'r-')
|
||||
end
|
||||
@@ -208,9 +208,10 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
|
||||
args=parser.parse_args()
|
||||
|
||||
#plt.ion()
|
||||
comm = PPComm(host=args.host)
|
||||
gt = Gather(comm)
|
||||
tune=MXTuning(comm,gt)
|
||||
#comm = PPComm(host=args.host)
|
||||
#gt = Gather(comm)
|
||||
#tune=MXTuning(comm,gt)
|
||||
tune = MXTuning(None,None)
|
||||
base='MXTuning'
|
||||
if args.dir is not None:
|
||||
base=args.dir
|
||||
@@ -258,7 +259,7 @@ Examples:'''+''.join(map(lambda s:cmd+s, exampleCmd))+'\n '
|
||||
for ext,amp,minFrq,maxFrq,tSec in (('a',100, 1, 200,15),
|
||||
('b', 20,10, 300,5),
|
||||
('c', 5,10, 300,5),
|
||||
('d', 1,10, 600,5),
|
||||
('d', 1,10,1000,5),
|
||||
):
|
||||
f=fcrp+ext+'.npz'
|
||||
if not os.path.isfile(f): tune.init_stage();plt.close('all')
|
||||
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -20,7 +20,7 @@ class Path():
|
||||
path=symPath
|
||||
path=os.path.abspath(path)
|
||||
path=os.path.dirname(path)
|
||||
return os.path.join(path,'images')
|
||||
return path
|
||||
|
||||
class StopWatch():
|
||||
@classmethod
|
||||
@@ -1,366 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# *-----------------------------------------------------------------------*
|
||||
# | |
|
||||
# | Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
# | |
|
||||
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
||||
# *-----------------------------------------------------------------------*
|
||||
'''
|
||||
tools to check kinematics
|
||||
'''
|
||||
import os, sys, json
|
||||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
import matplotlib.pyplot as plt
|
||||
import mpl_toolkits.mplot3d as plt3d
|
||||
import matplotlib.animation as anim
|
||||
from matplotlib.widgets import Slider
|
||||
import subprocess as sprc
|
||||
from utilities import *
|
||||
import telnetlib
|
||||
|
||||
class GpasciiCommunicator():
|
||||
'''Communicates with the Delta Tau gpascii programm
|
||||
'''
|
||||
gpascii_ack="\x06\r\n"
|
||||
gpascii_inp='Input\r\n'
|
||||
|
||||
def connect(self, host, username='root', password='deltatau',prompt='ppmac# ',verbose=0):
|
||||
p=telnetlib.Telnet(host)
|
||||
s=p.read_until('login: ')
|
||||
if verbose: print(s)
|
||||
p.write(username+'\n')
|
||||
s =p.read_until('Password: ')
|
||||
if verbose: print(s)
|
||||
p.write(password+'\n')
|
||||
s =p.read_until(prompt) # command prompt
|
||||
if verbose: print(s)
|
||||
p.write('gpascii -2\n') # execute gpascii command
|
||||
s=p.read_until(self.gpascii_inp)
|
||||
if verbose: print(s)
|
||||
return p
|
||||
|
||||
|
||||
class CoordTrf:
|
||||
def __init__(self,**kwargs):
|
||||
for k,v in kwargs.iteritems():
|
||||
setattr(self,k,v)
|
||||
pass
|
||||
|
||||
def show_vel(self):
|
||||
rec=self.rec
|
||||
fig = plt.figure()
|
||||
#y = np.diff(rec[:, 2])
|
||||
y = np.diff(rec,axis=0)
|
||||
mx=y.max(0)
|
||||
mn=y.min(0)
|
||||
scl=np.maximum(mx,-mn)
|
||||
scl=np.where(scl==0, 1, scl) # replace 0 by 1
|
||||
y/=scl
|
||||
x = np.arange(0, y.shape[0]);
|
||||
x= x.reshape(-1,1).dot(np.ones((1,y.shape[1])))
|
||||
lbl=('cx','cz','w','fy')
|
||||
#plt.plot(x, y,label=lbl)
|
||||
for i in range(y.shape[1]):
|
||||
plt.plot(x[:,i], y[:,i],label=lbl[i])
|
||||
|
||||
plt.legend()
|
||||
|
||||
def show_pos(self):
|
||||
rec=self.rec
|
||||
y = rec
|
||||
#plt.ion()
|
||||
fig = plt.figure(figsize=(20,6))
|
||||
c='bg'
|
||||
lbl=('q1','q2')
|
||||
dx=.1/len(lbl)
|
||||
for i in range(rec.shape[1]):
|
||||
if i==0:
|
||||
ax = fig.add_axes([.1, .05, .85, .90])
|
||||
axl =[ax,]
|
||||
else:
|
||||
ax = fig.add_axes(axl[0].get_position(), sharex=ax)
|
||||
ax.spines['top'].set_visible(False)
|
||||
ax.spines['bottom'].set_visible(False)
|
||||
ax.xaxis.set_visible(False)
|
||||
ax.patch.set_visible(False)
|
||||
ax.spines['left'].set_position(('axes', -dx*i))
|
||||
axl.append(ax)
|
||||
ax.set_ylabel(lbl[i], color=c[i])
|
||||
ax.tick_params(axis='y', colors=c[i])
|
||||
|
||||
x = np.arange(0, y.shape[0]);
|
||||
h=[]
|
||||
for i in range(rec.shape[1]):
|
||||
h+=axl[i].plot(x, y[:,i],c[i],label=lbl[i])
|
||||
plt.legend(handles=h)
|
||||
cid = fig.canvas.mpl_connect('motion_notify_event', self.onmove)
|
||||
fig.obj=self
|
||||
fig.data=y
|
||||
|
||||
|
||||
@staticmethod
|
||||
def onmove(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
|
||||
data = event.canvas.figure.data
|
||||
if(event.xdata):
|
||||
idx=round(event.xdata)
|
||||
msg='%d: q1:%.3f q2:%.3f'%((idx,)+tuple(data[idx,:]))
|
||||
#print msg
|
||||
event.canvas.toolbar.set_message(msg)
|
||||
|
||||
def download_code(self, prg, file=None, gather=False):
|
||||
host=self.host
|
||||
if self.verbose & 4:
|
||||
for ln in prg:
|
||||
print(ln)
|
||||
if file is not None:
|
||||
fh = open(file, 'w')
|
||||
fh.write('\n'.join(prg))
|
||||
fh.close()
|
||||
if host is not None:
|
||||
cmd = 'gpasciiCommander --host ' + host + ' ' + file
|
||||
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
|
||||
if gather:
|
||||
# ***wait program finished P1000=1***
|
||||
com=GpasciiCommunicator().connect(host,prompt='# ')
|
||||
ack=GpasciiCommunicator.gpascii_ack
|
||||
sys.stdout.write('wait execution...');sys.stdout.flush()
|
||||
while(True):
|
||||
#Gather.MaxLines calculates maximum numbewr of gathering into memory
|
||||
com.write('P1000\n')
|
||||
val=com.read_until(ack)
|
||||
#print val
|
||||
val=int(val[val.find('=')+1:].rstrip(ack))
|
||||
if val==1:break
|
||||
#com.write('Gather.Index\n')
|
||||
#val=com.read_until(ack)
|
||||
#print val
|
||||
time.sleep(.2)
|
||||
sys.stdout.write('.');sys.stdout.flush()
|
||||
fnRmt = '/var/ftp/gather/out.txt'
|
||||
fnLoc = '/tmp/gather.txt'
|
||||
print('\ngather data to %s...' % fnRmt)
|
||||
p = sprc.Popen(('ssh', 'root@' + host, 'gather ', '-u', fnRmt), shell=False, stdin=sprc.PIPE, stdout=sprc.PIPE,
|
||||
stderr=sprc.PIPE)
|
||||
res = p.wait()
|
||||
if res:
|
||||
print('ssh failed. ssh root@%s to open a session' % host)
|
||||
return
|
||||
|
||||
print('transfer data to %s...' % fnLoc)
|
||||
p = sprc.Popen(('scp', 'root@' + host + ':' + fnRmt, fnLoc), shell=False, stdin=sprc.PIPE, stdout=sprc.PIPE,
|
||||
stderr=sprc.PIPE)
|
||||
res = p.wait()
|
||||
self.rec = np.genfromtxt(fnLoc, delimiter=' ')
|
||||
#plt.ion()
|
||||
self.show_pos();self.show_vel()
|
||||
plt.show()
|
||||
|
||||
|
||||
|
||||
|
||||
def gen_code(self, mode):
|
||||
prg=[]
|
||||
file='/tmp/prg%d.cfg'%mode
|
||||
gather=True
|
||||
if mode==0:
|
||||
gather=False
|
||||
prg.append('''
|
||||
$$$***
|
||||
!common()
|
||||
!encoder_sim(enc=1,tbl=1,mot=1)
|
||||
!motor(mot=1,dirCur=0,contCur=100,peakCur=100,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True)
|
||||
Motor[1].pLimits=0;Motor[1].AmpFaultLevel=0;Motor[1].pAmpEnable=0;Motor[1].pAmpFault=0
|
||||
|
||||
!encoder_sim(enc=2,tbl=2,mot=2)
|
||||
!motor(mot=2,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True)
|
||||
Motor[2].pLimits=0;Motor[2].AmpFaultLevel=0;Motor[2].pAmpEnable=0;Motor[2].pAmpFault=0
|
||||
|
||||
!encoder_sim(enc=3,tbl=3,mot=3)
|
||||
!motor(mot=3,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True)
|
||||
Motor[3].pLimits=0;Motor[3].AmpFaultLevel=0;Motor[3].pAmpEnable=0;Motor[3].pAmpFault=0
|
||||
|
||||
!encoder_sim(enc=4,tbl=4,mot=4)
|
||||
!motor(mot=4,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True)
|
||||
Motor[4].pLimits=0;Motor[4].AmpFaultLevel=0;Motor[4].pAmpEnable=0;Motor[4].pAmpFault=0
|
||||
|
||||
!encoder_sim(enc=5,tbl=5,mot=5)
|
||||
!motor(mot=5,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True)
|
||||
Motor[5].pLimits=0;Motor[5].AmpFaultLevel=0;Motor[5].pAmpEnable=0;Motor[5].pAmpFault=0
|
||||
|
||||
!encoder_sim(enc=6,tbl=6,mot=6)
|
||||
!motor(mot=6,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True)
|
||||
Motor[6].pLimits=0;Motor[6].AmpFaultLevel=0;Motor[6].pAmpEnable=0;Motor[6].pAmpFault=0
|
||||
|
||||
!encoder_sim(enc=7,tbl=7,mot=7)
|
||||
!motor(mot=7,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True)
|
||||
Motor[7].pLimits=0;Motor[7].AmpFaultLevel=0;Motor[7].pAmpEnable=0;Motor[7].pAmpFault=0
|
||||
|
||||
!encoder_sim(enc=8,tbl=8,mot=8)
|
||||
!motor(mot=8,dirCur=0,contCur=100,peakCur=1000,timeAtPeak=1,JogSpeed=8.,numPhase=3,invDir=True)
|
||||
Motor[8].pLimits=0;Motor[8].AmpFaultLevel=0;Motor[8].pAmpEnable=0;Motor[8].pAmpFault=0
|
||||
|
||||
Motor[3].JogSpeed=1000 //used for joging
|
||||
Motor[3].MaxSpeed=1000 //used for motion program
|
||||
#1..8j/
|
||||
''')
|
||||
if mode==1:
|
||||
gather=False
|
||||
prg.append('''
|
||||
#1..2j=0
|
||||
|
||||
Gather.Enable=0
|
||||
Gather.Items=2
|
||||
Gather.MaxSamples=1000000
|
||||
Gather.Period=10
|
||||
Gather.Addr[0]=Motor[1].ActPos.a
|
||||
Gather.Addr[1]=Motor[2].ActPos.a
|
||||
|
||||
open prog 1
|
||||
jog1=0
|
||||
dwell100
|
||||
P1000=0
|
||||
nofrax
|
||||
linearabs
|
||||
Gather.Enable=2
|
||||
Y2.0
|
||||
dwell100
|
||||
Y4.0
|
||||
dwell100
|
||||
Y6.0
|
||||
dwell100
|
||||
Y8.0
|
||||
dwell100
|
||||
Gather.Enable=0
|
||||
P1000=1
|
||||
close
|
||||
|
||||
open prog 2
|
||||
jog1=0
|
||||
dwell100
|
||||
P1000=0
|
||||
nofrax
|
||||
Gather.Enable=2
|
||||
pvt100abs
|
||||
Y0:0
|
||||
Y2:20
|
||||
Y4:20
|
||||
Y6:20
|
||||
Y8:0
|
||||
dwell100
|
||||
Gather.Enable=0
|
||||
P1000=1
|
||||
close
|
||||
''')
|
||||
if mode==2:
|
||||
gather=False
|
||||
prg.append('''
|
||||
//motors CX CZ RY FY
|
||||
// 4 5 3 1
|
||||
&1
|
||||
a
|
||||
#1->0
|
||||
#2->0
|
||||
#3->0
|
||||
#4->0
|
||||
#5->0
|
||||
#6->0
|
||||
#7->0
|
||||
#8->0
|
||||
|
||||
#1->Y
|
||||
open forward
|
||||
close
|
||||
open inverse
|
||||
close
|
||||
''')
|
||||
if mode==3:
|
||||
gather=False
|
||||
prg.append('''
|
||||
// Set the motors as inverse kinematic axes in CS 1
|
||||
//motors CX CZ RY FY
|
||||
// 4 5 3 1
|
||||
&1
|
||||
a
|
||||
#1->0
|
||||
#2->0
|
||||
#3->0
|
||||
#4->0
|
||||
#5->0
|
||||
#6->0
|
||||
#7->0
|
||||
#8->0
|
||||
|
||||
#1->I
|
||||
|
||||
open forward
|
||||
define(q1='L1')
|
||||
define(Y='C7')
|
||||
//coord Y
|
||||
send 1"forward D0: %f \\n",D0
|
||||
if(D0>0) callsub 100
|
||||
D0=$00000080; //B=$2 X=$40 Y=$80 Z=$100 hex(2+int('40',16)+int('80',16)+int('100',16)) -> 0x1c2
|
||||
N100:
|
||||
Y=q1
|
||||
send 1"forward result %f\\n",Y
|
||||
P1001+=1
|
||||
close
|
||||
|
||||
open inverse
|
||||
define(q1='L1', vq1='R1')
|
||||
define(Y='C7',vY='C39')
|
||||
//coord Y
|
||||
send 1"inverse D0:%f _Y:%f:%f\\n",D0,Y,vY
|
||||
//D0 is set to $000001c2
|
||||
define(q1='L1')
|
||||
q1=Y
|
||||
if(D0>0)
|
||||
{
|
||||
vq1=vY // THIS LINE IS USED FOR PVT MOVE !!!
|
||||
send 1"inverse result _q1:%f:%f\\n",q1,vq1
|
||||
}
|
||||
else
|
||||
{
|
||||
send 1"inverse result %f\\n",q1
|
||||
}
|
||||
P1002+=1
|
||||
close
|
||||
''')
|
||||
self.download_code(prg, file, gather)
|
||||
|
||||
def test(self):
|
||||
file='/tmp/prg.cfg'
|
||||
#self.gen_code(0) #motor config
|
||||
self.gen_code(1) #program code
|
||||
|
||||
self.gen_code(2) #simple coord trf
|
||||
#self.download_code(['&1;b1r',], file, True)
|
||||
self.download_code(['&1;b2r',], file, True)
|
||||
|
||||
self.gen_code(3) #fwd/inv kinematics
|
||||
#prg.append(' Coord[1].AltFeedRate=0') # allow maximum speed
|
||||
#prg.append(' Coord[1].SegMoveTime=0') # turn off segmented mode
|
||||
|
||||
#self.download_code(['&1;b1r',], file, True)
|
||||
#self.download_code(['Coord[1].AltFeedRate=100','Coord[1].SegMoveTime=0','&1;b2r',], file, True)
|
||||
self.download_code(['Coord[1].AltFeedRate=0','Coord[1].SegMoveTime=0','&1;b2r',], file, True)
|
||||
#self.download_code(['Coord[1].AltFeedRate=1','Coord[1].SegMoveTime=.1','&1;b2r',], file, True)
|
||||
#self.download_code(['Coord[1].AltFeedRate=0','Coord[1].SegMoveTime=.1','&1;b2r',], file, True)
|
||||
#self.download_code(['&1;b3r',], file, True)
|
||||
|
||||
|
||||
# *** READ USER MANUAL P 455 ***
|
||||
# Inverse-Kinematic Program for PVT Mode, No Segmentation
|
||||
#
|
||||
|
||||
if __name__=='__main__':
|
||||
ct=CoordTrf(verbose=255,host='MOTTEST-CPPM-CRM0485')
|
||||
ct.test()
|
||||
|
||||
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
551
python/imgAnalysis/imgStack.py
Normal file
@@ -0,0 +1,551 @@
|
||||
#!/usr/bin/env python
|
||||
#*-----------------------------------------------------------------------*
|
||||
#| |
|
||||
#| Copyright (c) 2013 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
#| |
|
||||
#| Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
||||
#*-----------------------------------------------------------------------*
|
||||
'''
|
||||
implements an image view to show a colored image of a hdf5 dataset.
|
||||
'''
|
||||
|
||||
if __name__ == '__main__':
|
||||
#Used to guarantee to use at least Wx2.8
|
||||
import wxversion
|
||||
wxversion.ensureMinimal('2.8')
|
||||
import wx
|
||||
import matplotlib as mpl
|
||||
if __name__ == '__main__':
|
||||
mpl.use('WXAgg')
|
||||
#or mpl.use('WX')
|
||||
#matplotlib.get_backend()
|
||||
|
||||
import os
|
||||
import numpy as np
|
||||
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
|
||||
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
|
||||
import pylab as plt #used for the colormaps
|
||||
|
||||
|
||||
class SliderGroup():
|
||||
def __init__(self, parent, label, range=(0,100),val=0):
|
||||
self.sliderLabel = wx.StaticText(parent, label=label)
|
||||
self.sliderText = wx.TextCtrl(parent, -1, style=wx.TE_PROCESS_ENTER)
|
||||
self.slider = wx.Slider(parent, -1)
|
||||
self.slider.SetRange(range[0],range[1])
|
||||
sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer.Add(self.sliderLabel, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=2)
|
||||
sizer.Add(self.sliderText, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=2)
|
||||
sizer.Add(self.slider, 1, wx.EXPAND)
|
||||
self.sizer = sizer
|
||||
self.slider.Bind(wx.EVT_SLIDER, self.sliderHandler)
|
||||
self.sliderText.Bind(wx.EVT_TEXT_ENTER, self.sliderTextHandler)
|
||||
self.SetValue(val)
|
||||
|
||||
def SetValue(self, value):
|
||||
self.value = value
|
||||
self.slider.SetValue(value)
|
||||
self.sliderText.SetValue(str(value))
|
||||
|
||||
def SetCallback(self,funcCB,usrData):
|
||||
self.cbFuncData=(funcCB,usrData)
|
||||
|
||||
def Callback(self,value,msg):
|
||||
try:
|
||||
(funcCB,usrData)=self.cbFuncData
|
||||
except BaseException as e:
|
||||
pass
|
||||
else:
|
||||
funcCB(usrData,value,msg)
|
||||
|
||||
def sliderHandler(self, evt):
|
||||
value = evt.GetInt()
|
||||
self.sliderText.SetValue(str(value))
|
||||
self.value=value
|
||||
self.Callback(value,0)
|
||||
|
||||
def sliderTextHandler(self, evt):
|
||||
value = int(self.sliderText.GetValue())
|
||||
self.slider.SetValue(value)
|
||||
value = self.slider.Value
|
||||
self.sliderText.SetValue(str(value))
|
||||
self.value=value
|
||||
self.Callback(value,0)
|
||||
|
||||
|
||||
def AddToolbar(parent,sizer):
|
||||
toolbar = NavigationToolbar(parent)
|
||||
toolbar.Realize()
|
||||
if wx.Platform == '__WXMAC__':
|
||||
# Mac platform (OSX 10.3, MacPython) does not seem to cope with
|
||||
# having a toolbar in a sizer. This work-around gets the buttons
|
||||
# back, but at the expense of having the toolbar at the top
|
||||
parent.SetToolBar(toolbar)
|
||||
else:
|
||||
# On Windows platform, default window size is incorrect, so set
|
||||
# toolbar width to figure width.
|
||||
tw, th = toolbar.GetSizeTuple()
|
||||
fw, fh = parent.GetSizeTuple()
|
||||
# By adding toolbar in sizer, we are able to put it at the bottom
|
||||
# of the frame - so appearance is closer to GTK version.
|
||||
# As noted above, doesn't work for Mac.
|
||||
toolbar.SetSize(wx.Size(fw, th))
|
||||
sizer.Add(toolbar, 0, wx.LEFT | wx.EXPAND)
|
||||
# update the axes menu on the toolbar
|
||||
toolbar.update()
|
||||
return toolbar
|
||||
|
||||
|
||||
#class ShiftedLogNorm(mpl.colors.Normalize):
|
||||
class ShiftedLogNorm(mpl.colors.LogNorm):
|
||||
#copied and modified from LogNorm
|
||||
def __call__(self, value, clip=None):
|
||||
#print value.shape,self.vmin,self.vmax,self.clip,clip
|
||||
if clip is None:
|
||||
clip = self.clip
|
||||
ofs0=1-self.vmin
|
||||
ofs1=1./(np.log(self.vmax+1-self.vmin))
|
||||
result=np.log(value+ofs0)*ofs1
|
||||
result = np.ma.masked_less_equal(result, 0, copy=False)
|
||||
return result
|
||||
def inverse(self, value):
|
||||
if not self.scaled():
|
||||
raise ValueError("Not invertible until scaled")
|
||||
vmin, vmax = self.vmin, self.vmax
|
||||
ofs0=1-vmin
|
||||
if mpl.cbook.iterable(value):
|
||||
val = np.ma.asarray(value)
|
||||
return vmin * np.ma.power((vmax/vmin), val)-ofs0
|
||||
else:
|
||||
return vmin * pow((vmax/vmin), value)-ofs0
|
||||
def autoscale_None(self, A):
|
||||
if self.vmin is None:
|
||||
self.vmin = np.ma.min(A)
|
||||
if self.vmax is None:
|
||||
self.vmax = np.ma.max(A)
|
||||
pass
|
||||
def autoscale(self, A):
|
||||
pass
|
||||
|
||||
class MPLCanvasImg(FigureCanvas):
|
||||
def __init__(self,parent,SetStatusCB=None):
|
||||
if SetStatusCB:
|
||||
self.SetStatusCB=SetStatusCB
|
||||
fig = mpl.figure.Figure()
|
||||
ax = fig.add_axes([0.075,0.1,0.75,0.85])
|
||||
FigureCanvas.__init__(self,parent, -1, fig)
|
||||
self.mpl_connect('motion_notify_event', self.OnMotion)
|
||||
self.mpl_connect('button_press_event', self.OnBtnPress)
|
||||
self.mpl_connect('button_release_event', self.OnBtnRelease)
|
||||
self.mpl_connect('scroll_event', self.OnBtnScroll)
|
||||
self.mpl_connect('key_press_event',self.OnKeyPress)
|
||||
self.fig=fig
|
||||
self.ax=ax
|
||||
|
||||
def InitChild(self,data):
|
||||
if data.dtype==np.complex128:
|
||||
self.dataRaw=data
|
||||
#data=np.angle(data)
|
||||
data=np.absolute(data)
|
||||
|
||||
fig=self.fig
|
||||
ax=self.ax
|
||||
|
||||
msk=~np.isnan(data);msk=data[msk]
|
||||
avg=np.average(msk); std=np.std(msk)
|
||||
vmin=np.min(msk);vmax=np.max(msk)
|
||||
vmin=max(vmin,avg-3*std);vmax=min(vmax,avg+3*std)
|
||||
if vmin==0:vmin=1
|
||||
if vmax<=vmin:
|
||||
vmax=vmin+1
|
||||
|
||||
#norm=ShiftedLogNorm()
|
||||
norm=mpl.colors.Normalize()
|
||||
#img = ax.imshow(data,interpolation='nearest',cmap=mpl.cm.jet, norm=ShiftedLogNorm(vmin=vmin, vmax=vmax))
|
||||
|
||||
img = ax.imshow(data,interpolation='nearest',cmap=mpl.cm.jet, vmin=vmin, vmax=vmax)
|
||||
colBar=fig.colorbar(img,orientation='vertical',norm=norm)
|
||||
#colBar.norm=ShiftedLogNorm(vmin=vmin, vmax=vmax)
|
||||
colBar.norm=mpl.colors.Normalize(vmin=vmin, vmax=vmax)
|
||||
img.set_norm(colBar.norm)
|
||||
img.cmap._init();bg=img.cmap._lut[0].copy();bg[:-1]/=4
|
||||
ax.set_axis_bgcolor(bg)
|
||||
|
||||
|
||||
self.colBar=colBar
|
||||
self.colCycle = sorted([i for i in dir(plt.cm) if hasattr(getattr(plt.cm,i),'N')])
|
||||
self.colIndex = self.colCycle.index(colBar.get_cmap().name)
|
||||
self.img=img
|
||||
|
||||
def OnMotion(self,event):
|
||||
#print event,event.x,event.y,event.inaxes,event.xdata,event.ydata
|
||||
if event.inaxes==self.ax:
|
||||
x=int(round(event.xdata))
|
||||
y=int(round(event.ydata))
|
||||
try:
|
||||
v=self.img.get_array()[y,x]
|
||||
except IndexError as e:
|
||||
pass
|
||||
else:
|
||||
#print x,y,v
|
||||
self.SetStatusCB(self.Parent,0,(x,y,v))
|
||||
elif event.inaxes==self.colBar.ax:
|
||||
colBar=self.colBar
|
||||
pt=colBar.ax.bbox.get_points()[:,1]
|
||||
nrm=colBar.norm
|
||||
vmin,vmax,p0,p1,pS = (nrm.vmin,nrm.vmax,pt[0],pt[1],event.y)
|
||||
if isinstance(colBar.norm,mpl.colors.LogNorm):#type(colBar.norm)==mpl.colors.LogNorm does not work...
|
||||
vS=0
|
||||
else:#scale around point
|
||||
vS=vmin+(vmax-vmin)/(p1-p0)*(pS-p0)
|
||||
self.SetStatusCB(self.Parent,1,vS)
|
||||
try:
|
||||
vmin,vmax,p0,p1,pS=self.colBarPressed
|
||||
except AttributeError:
|
||||
return
|
||||
#if event.inaxes != self.cbar.ax: return
|
||||
colBar=self.colBar
|
||||
#print vmin,vmax,p0,p1,pS,type(colBar.norm)
|
||||
#print 'x0=%f, xpress=%f, event.xdata=%f, dx=%f, x0+dx=%f'%(x0, xpress, event.xdata, dx, x0+dx)
|
||||
|
||||
if isinstance(colBar.norm,mpl.colors.LogNorm):#type(colBar.norm)==mpl.colors.LogNorm does not work...
|
||||
if event.button==1:
|
||||
#colBar.norm.vmin=.1
|
||||
colBar.norm.vmax=vmax*np.exp((pS-event.y)/100)
|
||||
#scale= np.exp((event.y-pS)/100)
|
||||
elif event.button==1:#move top,bottom,both
|
||||
pD = event.y - pS
|
||||
vD=(vmax-vmin)/(p1-p0)*(pS-event.y)
|
||||
colBar.norm.vmin = vmin+vD
|
||||
colBar.norm.vmax = vmax+vD
|
||||
elif event.button==3:#scale around point
|
||||
scale= np.exp((pS-event.y)/100)
|
||||
vS=vmin+(vmax-vmin)/(p1-p0)*(pS-p0)
|
||||
#print scale,vS
|
||||
colBar.norm.vmin = vS-scale*(vS-vmin)
|
||||
colBar.norm.vmax = vS-scale*(vS-vmax)
|
||||
self.img.set_norm(colBar.norm)#force image to redraw
|
||||
colBar.patch.figure.canvas.draw()
|
||||
|
||||
def OnBtnPress(self, event):
|
||||
"""on button press we will see if the mouse is over us and store some data"""
|
||||
#print dir(event.guiEvent)
|
||||
if event.inaxes == self.colBar.ax:
|
||||
#if event.guiEvent.LeftDClick()==True:
|
||||
# print dlg
|
||||
pt=self.colBar.ax.bbox.get_points()[:,1]
|
||||
nrm=self.colBar.norm
|
||||
self.colBarPressed = (nrm.vmin,nrm.vmax,pt[0],pt[1],event.y)
|
||||
#self.colBarPressed = event.x, event.y
|
||||
#print self.colBarPressed
|
||||
#self.OnMouse(event)
|
||||
pass
|
||||
|
||||
def OnBtnRelease(self, event):
|
||||
"""on release we reset the press data"""
|
||||
#self.OnMouse(event)
|
||||
try: del self.colBarPressed
|
||||
except AttributeError: pass
|
||||
|
||||
def OnBtnScroll(self, event):
|
||||
#self.OnMouse(event)
|
||||
colBar=self.colBar
|
||||
if event.inaxes==colBar.ax:
|
||||
pt=colBar.ax.bbox.get_points()[:,1]
|
||||
nrm=colBar.norm
|
||||
vmin,vmax,p0,p1,pS = (nrm.vmin,nrm.vmax,pt[0],pt[1],event.y)
|
||||
if isinstance(colBar.norm,mpl.colors.LogNorm):#type(colBar.norm)==mpl.colors.LogNorm does not work...
|
||||
scale= np.exp((-event.step)/10)
|
||||
colBar.norm.vmax=vmax*scale
|
||||
else:#scale around point
|
||||
scale= np.exp((-event.step)/10)
|
||||
vS=vmin+(vmax-vmin)/(p1-p0)*(pS-p0)
|
||||
#print scale,vS
|
||||
colBar.norm.vmin = vS-scale*(vS-vmin)
|
||||
colBar.norm.vmax = vS-scale*(vS-vmax)
|
||||
self.img.set_norm(colBar.norm)#force image to redraw
|
||||
colBar.patch.figure.canvas.draw()
|
||||
|
||||
def OnKeyPress(self, event):
|
||||
colCycle=self.colCycle
|
||||
colBar=self.colBar
|
||||
if event.key=='down':
|
||||
self.colIndex += 1
|
||||
elif event.key=='up':
|
||||
self.colIndex -= 1
|
||||
self.colIndex%=len(colCycle)
|
||||
cmap = colCycle[self.colIndex]
|
||||
colBar.set_cmap(cmap)
|
||||
colBar.draw_all()
|
||||
self.img.set_cmap(cmap)
|
||||
self.img.get_axes().set_title(cmap)
|
||||
colBar.patch.figure.canvas.draw()
|
||||
|
||||
def OnMouse(self, event):
|
||||
for k in dir(event):
|
||||
if k[0]!='_':
|
||||
print k,getattr(event,k)
|
||||
|
||||
|
||||
class DlgColBarSetup(wx.Dialog):
|
||||
def __init__(self,parent):
|
||||
wx.Dialog.__init__(self,parent,-1,'Colormap Setup')
|
||||
colBar=parent.canvas.colBar
|
||||
cmap=colBar.cmap
|
||||
nrm=colBar.norm
|
||||
|
||||
txtVMin=wx.StaticText(self,-1,'vmin')
|
||||
txtVMax=wx.StaticText(self,-1,'vmax')
|
||||
txtColMap=wx.StaticText(self,-1,'colormap')
|
||||
self.edVMin=edVMin=wx.TextCtrl(self,-1,'%g'%nrm.vmin,style=wx.TE_PROCESS_ENTER)
|
||||
self.edVMax=edVMax=wx.TextCtrl(self,-1,'%g'%nrm.vmax,style=wx.TE_PROCESS_ENTER)
|
||||
|
||||
txtTxrFunc=wx.StaticText(self,-1,'function')
|
||||
self.cbtxrFunc=cbtxrFunc=wx.ComboBox(self, -1, choices=('linear','logarithmic'), style=wx.CB_READONLY)
|
||||
cbtxrFunc.SetSelection(0 if nrm.__class__==mpl.colors.Normalize else 1)
|
||||
|
||||
#colMapLst=('Accent', 'Blues', 'BrBG', 'BuGn', 'BuPu', 'Dark2', 'GnBu', 'Greens', 'Greys', 'OrRd', 'Oranges', 'PRGn', 'Paired',
|
||||
#'Pastel1', 'Pastel2', 'PiYG', 'PuBu', 'PuBuGn', 'PuOr', 'PuRd', 'Purples', 'RdBu', 'RdGy', 'RdPu', 'RdYlBu', 'RdYlGn', 'Reds',
|
||||
#'Set1', 'Set2', 'Set3', 'Spectral', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd', 'afmhot', 'autumn', 'binary', 'bone', 'brg', 'bwr',
|
||||
#'cool', 'coolwarm', 'copper', 'cubehelix', 'flag', 'gist_earth', 'gist_gray', 'gist_heat', 'gist_ncar', 'gist_rainbow', 'gist_stern',
|
||||
#'gist_yarg', 'gnuplot', 'gnuplot2', 'gray', 'hot', 'hsv', 'jet', 'ocean', 'pink', 'prism', 'rainbow', 'seismic', 'spectral',
|
||||
#'spring', 'summer', 'terrain', 'winter')
|
||||
|
||||
colMapLst=('hot','spectral','jet','gray','RdYlBu','hsv','gist_stern','gist_ncar','BrBG','RdYlBu','brg','gnuplot2',
|
||||
'prism','rainbow',)
|
||||
|
||||
self.cbColMap=cbColMap=wx.ComboBox(self, -1, choices=colMapLst, style=wx.CB_READONLY)
|
||||
cbColMap.Value=cmap.name
|
||||
|
||||
sizer=wx.BoxSizer(wx.VERTICAL)
|
||||
fgs=wx.FlexGridSizer(4,2,5,5)
|
||||
fgs.Add(txtVMin,0,wx.ALIGN_RIGHT)
|
||||
fgs.Add(edVMin,0,wx.EXPAND)
|
||||
fgs.Add(txtVMax,0,wx.ALIGN_RIGHT)
|
||||
fgs.Add(edVMax,0,wx.EXPAND)
|
||||
fgs.Add(txtTxrFunc,0,wx.ALIGN_RIGHT)
|
||||
fgs.Add(cbtxrFunc,0,wx.EXPAND)
|
||||
fgs.Add(txtColMap,0,wx.ALIGN_RIGHT)
|
||||
fgs.Add(cbColMap,0,wx.EXPAND)
|
||||
sizer.Add(fgs,0,wx.EXPAND|wx.ALL,5)
|
||||
|
||||
edVMin.SetFocus()
|
||||
|
||||
btns = self.CreateButtonSizer(wx.OK|wx.CANCEL)
|
||||
btnApply=wx.Button(self, -1, 'Apply')
|
||||
btns.Add(btnApply, 0, wx.ALL, 5)
|
||||
sizer.Add(btns,0,wx.EXPAND|wx.ALL,5)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnModify, id=wx.ID_OK)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnModify, btnApply)
|
||||
#self.Bind(wx.EVT_TEXT_ENTER, self.OnModify, edVMin)
|
||||
#self.Bind(wx.EVT_TEXT_ENTER, self.OnModify, edVMax)
|
||||
self.Bind(wx.EVT_TEXT, self.OnModify, edVMin)
|
||||
self.Bind(wx.EVT_TEXT, self.OnModify, edVMax)
|
||||
self.Bind(wx.EVT_COMBOBOX, self.OnModify, cbtxrFunc)
|
||||
self.Bind(wx.EVT_COMBOBOX, self.OnModify, cbColMap)
|
||||
|
||||
self.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
|
||||
def OnModify(self, event):
|
||||
#print 'OnModify'
|
||||
parent=self.GetParent()
|
||||
canvas=parent.canvas
|
||||
colBar=canvas.colBar
|
||||
cmap=colBar.cmap
|
||||
nrm=colBar.norm
|
||||
img=canvas.img
|
||||
ax=img.get_axes()
|
||||
data=img.get_array()
|
||||
|
||||
v=self.cbColMap.Value
|
||||
if v!=cmap.name:
|
||||
cmap=getattr(mpl.cm,v)
|
||||
colBar.set_cmap(cmap)
|
||||
colBar.draw_all()
|
||||
img.set_cmap(cmap)
|
||||
ax.set_title(cmap.name)
|
||||
colBar.patch.figure.canvas.draw()
|
||||
|
||||
vmin,vmax=(float(self.edVMin.Value),float(self.edVMax.Value))
|
||||
nrm.vmin=vmin; nrm.vmax=vmax
|
||||
v=self.cbtxrFunc.GetCurrentSelection()
|
||||
func=(mpl.colors.Normalize,ShiftedLogNorm)
|
||||
if nrm.__class__!=func[v]:
|
||||
if v==0: #linear mapping
|
||||
colBar.norm = mpl.colors.Normalize(vmin, vmax)
|
||||
elif v==1: #log mapping
|
||||
img.cmap._init();bg=img.cmap._lut[0].copy();bg[:-1]/=4
|
||||
ax.set_axis_bgcolor(bg)
|
||||
vmin=1
|
||||
colBar.norm = mpl.colors.LogNorm(vmin,vmax)
|
||||
img.set_norm(colBar.norm)
|
||||
colBar.patch.figure.canvas.draw()
|
||||
parent.Refresh(False)
|
||||
if event.GetId()==wx.ID_OK:
|
||||
event.Skip()#do not consume (use event to close the window and sent return code)
|
||||
|
||||
class HdfImageFrame(wx.Frame):
|
||||
def __init__(self, parent,lbl,ims):
|
||||
wx.Frame.__init__(self, parent, title=lbl, size=wx.Size(850, 650))
|
||||
|
||||
canvas = MPLCanvasImg(self,self.SetStatusCB)
|
||||
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer.Add(canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
toolbar=AddToolbar(canvas,sizer)
|
||||
|
||||
l=len(ims)
|
||||
wxAxCtrl=SliderGroup(self, label='Axis:%d'%0,range=(0,l-1))
|
||||
sizer.Add(wxAxCtrl.sizer, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5)
|
||||
wxAxCtrl.SetCallback(HdfImageFrame.OnSetView,wxAxCtrl)
|
||||
|
||||
idx=wxAxCtrl.value
|
||||
data=ims[idx]
|
||||
canvas.InitChild(data)
|
||||
|
||||
#self.Fit()
|
||||
self.Centre()
|
||||
|
||||
self.BuildMenu(data.dtype)
|
||||
self.canvas=canvas
|
||||
self.sizer=sizer
|
||||
self.toolbar=toolbar
|
||||
self.ims=ims
|
||||
self.wxAxCtrl=wxAxCtrl
|
||||
|
||||
def BuildMenu(self,dtype):
|
||||
mnBar = wx.MenuBar()
|
||||
|
||||
#-------- Edit Menu --------
|
||||
mn = wx.Menu()
|
||||
mnItem=mn.Append(wx.ID_ANY, 'Setup Colormap', 'Setup the color mapping ');self.Bind(wx.EVT_MENU, self.OnColmapSetup, mnItem)
|
||||
mnItem=mn.Append(wx.ID_ANY, 'Invert X-Axis', kind=wx.ITEM_CHECK);self.Bind(wx.EVT_MENU, self.OnInvertAxis, mnItem)
|
||||
self.mnIDxAxis=mnItem.GetId()
|
||||
mnItem=mn.Append(wx.ID_ANY, 'Invert Y-Axis', kind=wx.ITEM_CHECK);self.Bind(wx.EVT_MENU, self.OnInvertAxis, mnItem)
|
||||
mnItem=mn.Append(wx.ID_ANY, 'Tomo Normalize', 'Multiplies each pixel with a normalization factor. Assumes there exist an array exchange/data_white', kind=wx.ITEM_CHECK);self.Bind(wx.EVT_MENU, self.OnTomoNormalize, mnItem)
|
||||
self.mnItemTomoNormalize=mnItem
|
||||
|
||||
if dtype==np.complex128:
|
||||
mnItem=mn.Append(wx.ID_ANY, 'Complex: Phase', kind=wx.ITEM_CHECK);self.Bind(wx.EVT_MENU, self.OnSetComplexData, mnItem)
|
||||
|
||||
|
||||
mnBar.Append(mn, '&Edit')
|
||||
mn = wx.Menu()
|
||||
mnItem=mn.Append(wx.ID_ANY, 'Help', 'How to use the image viewer');self.Bind(wx.EVT_MENU, self.OnHelp, mnItem)
|
||||
mnBar.Append(mn, '&Help')
|
||||
|
||||
self.SetMenuBar(mnBar)
|
||||
self.CreateStatusBar()
|
||||
|
||||
def SetIdxXY(self,x,y):
|
||||
self.idxXY=(x,y)
|
||||
|
||||
@staticmethod
|
||||
def SetStatusCB(obj,mode,v):
|
||||
if mode==0:
|
||||
obj.SetStatusText( "x= %d y=%d val=%g"%v,0)
|
||||
elif mode==1:
|
||||
obj.SetStatusText( "Colormap Value %d (drag to scale)"%v,0)
|
||||
else:
|
||||
raise KeyError('wrong mode')
|
||||
|
||||
@staticmethod
|
||||
def OnSetView(usrData,value,msg):
|
||||
'called when a slice is selected with the slider controls'
|
||||
imgFrm=usrData.slider.Parent
|
||||
#imgFrm.img.set_array(imgFrm.data[usrData.value,...])
|
||||
idx=imgFrm.wxAxCtrl.value
|
||||
data=imgFrm.ims[idx]
|
||||
try:
|
||||
tomoNorm=imgFrm.tomoNorm
|
||||
except AttributeError:
|
||||
imgFrm.canvas.img.set_array(data)
|
||||
else:
|
||||
data=data*tomoNorm
|
||||
imgFrm.canvas.img.set_array(data)
|
||||
|
||||
imgFrm.canvas.draw()
|
||||
pass
|
||||
|
||||
|
||||
def OnTomoNormalize(self,event):
|
||||
if event.IsChecked():
|
||||
#try to find white image
|
||||
#calculate average
|
||||
#show white normalize factors
|
||||
white=self.data.parent['data_white']
|
||||
tomoNorm=white[1,:,:]
|
||||
#tomoNorm=white[:,:,:].mean(axis=0)
|
||||
#np.iinfo(tomoNorm.dtype).max
|
||||
#tomoNorm=float(np.iinfo(tomoNorm.dtype).max/2)/tomoNorm
|
||||
tomoNorm=tomoNorm.mean()/tomoNorm
|
||||
#tomoNorm=tomoNorm/float(np.iinfo(tomoNorm.dtype).max)
|
||||
data=self.canvas.img.get_array()
|
||||
data*=tomoNorm
|
||||
#data/=tomoNorm
|
||||
self.tomoNorm=tomoNorm
|
||||
self.canvas.img.set_array(data)
|
||||
else:
|
||||
tomoNorm=self.tomoNorm
|
||||
data=self.canvas.img.get_array()
|
||||
data/=tomoNorm
|
||||
self.canvas.img.set_array(data)
|
||||
del self.tomoNorm
|
||||
self.canvas.draw()
|
||||
|
||||
def OnSetComplexData(self, event):
|
||||
if event.IsChecked():
|
||||
data=np.angle(self.canvas.dataRaw)
|
||||
else:
|
||||
data=np.absolute(self.canvas.dataRaw)
|
||||
self.canvas.img.set_array(data)
|
||||
self.canvas.draw()
|
||||
|
||||
def OnHelp(self,event):
|
||||
msg='''to change the image selection:
|
||||
use the toolbar at the bottom to pan and zoom the image
|
||||
use the scrollbars at the bottom (if present) to select an other slice
|
||||
|
||||
to change the colorscale:
|
||||
drag with left mouse button to move the colorbar up and down
|
||||
drag with right mouse button to zoom in/out the colorbar at a given point
|
||||
use mouse weel to zoom in/out the colorbar at a given point
|
||||
double click left mouse button to set maximum and minimun colorbar values
|
||||
use cursor up and down to use a different colormap'''
|
||||
dlg = wx.MessageDialog(self, msg, 'Help', wx.OK|wx.ICON_INFORMATION)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
def OnColmapSetup(self,event):
|
||||
dlg=DlgColBarSetup(self)
|
||||
if dlg.ShowModal()==wx.ID_OK:
|
||||
pass
|
||||
dlg.Destroy()
|
||||
|
||||
def OnInvertAxis(self,event):
|
||||
ax=self.canvas.ax
|
||||
#event.Checked()
|
||||
if self.mnIDxAxis==event.GetId():
|
||||
ax.invert_xaxis()
|
||||
else:
|
||||
ax.invert_yaxis()
|
||||
self.canvas.draw()
|
||||
pass
|
||||
|
||||
class ImgStackApp(wx.App):
|
||||
def OnInit(self):
|
||||
#parser=GetParser(False) # debug with exampleCmd
|
||||
return True
|
||||
|
||||
def OnExit(self):
|
||||
pass
|
||||
|
||||
def Run(ims):
|
||||
app=ImgStackApp()
|
||||
frame=HdfImageFrame(None, 'Title', ims)
|
||||
frame.Show()
|
||||
app.SetTopWindow(frame)
|
||||
app.MainLoop()
|
||||
@@ -1,44 +0,0 @@
|
||||
#plot and calculate rms values of sine, six state trapezoidal etc.
|
||||
|
||||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
import matplotlib.pyplot as pyplot
|
||||
pyplot.figure()
|
||||
x=np.arange(360.)
|
||||
y=np.sin(x/360.*2.*np.pi)
|
||||
y1=x.copy()
|
||||
y1[0: 60]=x[0:60]/60
|
||||
y1[ 60:120]=1
|
||||
y1[120:180]=1-x[0:60]/60
|
||||
y1[180:240]=-x[0:60]/60
|
||||
y1[240:300]=-1
|
||||
y1[300:360]=-1+x[0:60]/60
|
||||
|
||||
y2=x.copy()
|
||||
y2[0: 30]=0
|
||||
y2[30:150]=1
|
||||
y2[150:210]=0
|
||||
y2[210:330]=-1
|
||||
y2[330:360]=0
|
||||
|
||||
y3=x.copy()
|
||||
y3[0: 60]=.5
|
||||
y3[60:120]=1
|
||||
y3[120:180]=.5
|
||||
y3[180:240]=-.5
|
||||
y3[240:300]=-1
|
||||
y3[300:360]=-.5
|
||||
|
||||
pyplot.plot(x,y,x,y1,x,y2,x,y3);pyplot.show()
|
||||
|
||||
rms=np.sqrt(np.mean(y**2))
|
||||
b=np.sqrt(2)/2
|
||||
rms1=np.sqrt(np.mean(y1**2))
|
||||
rms2=np.sqrt(np.mean(y2**2))
|
||||
rms3=np.sqrt(np.mean(y3**2))
|
||||
print rms,rms1,rms2,rms3,b
|
||||
|
||||
print 0.8/rms, 0.8/rms1, 0.8/rms2, 0.8/rms3
|
||||
|
||||
|
||||
#https://e2e.ti.com/blogs_/b/motordrivecontrol/archive/2013/11/08/generate-your-own-commutation-table-trapezoidal-control-3-phase-bldc-motors-using-hall-sensors
|
||||
@@ -1,91 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#*-----------------------------------------------------------------------*
|
||||
#| |
|
||||
#| Copyright (c) 2016 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
#| |
|
||||
#| Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
||||
#*-----------------------------------------------------------------------*
|
||||
'''
|
||||
utilities classes
|
||||
'''
|
||||
import json
|
||||
import numpy as np
|
||||
import time,os
|
||||
|
||||
|
||||
class dotdict(dict):
|
||||
"""dot.notation access to dictionary attributes"""
|
||||
def __init__(self,arg=None,**kwargs):
|
||||
if arg!=None:
|
||||
self.__fill__(arg)
|
||||
self.__fill__(kwargs)
|
||||
|
||||
def __fill__(self,kw):
|
||||
for k,v in kw.iteritems():
|
||||
if type(v)==dict:
|
||||
self[k]=dotdict(v)
|
||||
else:
|
||||
self[k]=v
|
||||
if type(v)==list:
|
||||
for i,w in enumerate(v):
|
||||
if type(w)==dict:
|
||||
v[i]=dotdict(w)
|
||||
pass
|
||||
|
||||
def __dir__(self):
|
||||
l=dir(object)
|
||||
#l.extend(self.keys())
|
||||
l.extend(map(str,self.keys()))
|
||||
return l
|
||||
|
||||
def __getattr__(self, attr):
|
||||
#return self.get(attr)
|
||||
try:
|
||||
return self[attr]
|
||||
except KeyError as e:
|
||||
raise AttributeError("%r instance has no attribute %r" % (self.__class__, attr))
|
||||
|
||||
def __repr__(self):
|
||||
return '<' + dict.__repr__(self)[1:-1] + '>'
|
||||
|
||||
def PrettyPrint(self,indent=0):
|
||||
for k,v in self.iteritems():
|
||||
if type(v)==dotdict:
|
||||
print ' '*indent,str(k)+':'
|
||||
v.PrettyPrint(indent+2)
|
||||
else:
|
||||
print ' '*indent+str(k)+'\t'+str(v)
|
||||
|
||||
__setattr__= dict.__setitem__
|
||||
__delattr__= dict.__delitem__
|
||||
#__getattr__= dict.__getattr__
|
||||
|
||||
|
||||
def ConvUtf8(s):
|
||||
'convert unicoded json object to ASCII encoded'
|
||||
#http://stackoverflow.com/questions/956867/how-to-get-string-objects-instead-of-unicode-ones-from-json-in-python
|
||||
if isinstance(s, dict):
|
||||
return {ConvUtf8(key): ConvUtf8(value) for key, value in s.iteritems()}
|
||||
elif isinstance(s, list):
|
||||
return [ConvUtf8(element) for element in s]
|
||||
elif isinstance(s, unicode):
|
||||
return s.encode('utf-8')
|
||||
else:
|
||||
return s
|
||||
|
||||
class GpasciiCommunicator():
|
||||
'''Communicates with the Delta Tau gpascii programm
|
||||
'''
|
||||
gpascii_ack="\x06\r\n"
|
||||
gpascii_inp='Input\r\n'
|
||||
|
||||
def connect(self, host, username='root', password='deltatau',prompt='ppmac# '):
|
||||
p=telnetlib.Telnet(host)
|
||||
print p.read_until('login: ')
|
||||
p.write(username+'\n')
|
||||
print p.read_until('Password: ')
|
||||
p.write(password+'\n')
|
||||
print p.read_until(prompt) # command prompt
|
||||
p.write('gpascii -2\n') # execute gpascii command
|
||||
print p.read_until(self.gpascii_inp)
|
||||
return p
|
||||