source: sasmodels/explore/shimmy.py @ 782dd1f

core_shell_microgelscostrafo411magnetic_modelticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 782dd1f was 782dd1f, checked in by Paul Kienzle <pkienzle@…>, 7 years ago

new angular explorer with polydispersity

  • Property mode set to 100644
File size: 7.2 KB
Line 
1"""
2Application to explore the difference between sasview 3.x orientation
3dispersity and possible replacement algorithms.
4"""
5import mpl_toolkits.mplot3d   # Adds projection='3d' option to subplot
6import matplotlib.pyplot as plt
7from matplotlib.widgets import Slider, CheckButtons
8from matplotlib import cm
9
10import numpy as np
11from numpy import pi, cos, sin, sqrt, exp, degrees, radians
12
13def draw_beam(ax):
14    #ax.plot([0,0],[0,0],[1,-1])
15    #ax.scatter([0]*100,[0]*100,np.linspace(1, -1, 100), alpha=0.8)
16
17    steps = 25
18    u = np.linspace(0, 2 * np.pi, steps)
19    v = np.linspace(-1, 1, steps)
20
21    r = 0.02
22    x = r*np.outer(np.cos(u), np.ones_like(v))
23    y = r*np.outer(np.sin(u), np.ones_like(v))
24    z = np.outer(np.ones_like(u), v)
25
26    ax.plot_surface(x, y, z, rstride=4, cstride=4, color='y', alpha=0.5)
27   
28def draw_shimmy(ax, theta, phi, psi, dtheta, dphi, dpsi):
29    size=[0.1, 0.4, 1.0] 
30    view=[theta, phi, psi]
31    shimmy=[0,0,0]
32    #draw_shape = draw_parallelepiped
33    draw_shape = draw_ellipsoid
34   
35    #np.random.seed(10)
36    #cloud = np.random.randn(10,3)
37    cloud = [
38        [-1, -1, -1],
39        [-1, -1,  0],
40        [-1, -1,  1],
41        [-1,  0, -1],
42        [-1,  0,  0],
43        [-1,  0,  1],
44        [-1,  1, -1],
45        [-1,  1,  0],
46        [-1,  1,  1],
47        [ 0, -1, -1],
48        [ 0, -1,  0],
49        [ 0, -1,  1],
50        [ 0,  0, -1],
51        [ 0,  0,  0],
52        [ 0,  0,  1],
53        [ 0,  1, -1],
54        [ 0,  1,  0],
55        [ 0,  1,  1],
56        [ 1, -1, -1],
57        [ 1, -1,  0],
58        [ 1, -1,  1],
59        [ 1,  0, -1],
60        [ 1,  0,  0],
61        [ 1,  0,  1],
62        [ 1,  1, -1],
63        [ 1,  1,  0],
64        [ 1,  1,  1],
65    ]
66    draw_shape(ax, size, view, shimmy, steps=100, alpha=0.8)
67    cloud = []
68    for point in cloud:
69        shimmy=[dtheta*point[0], dphi*point[1], dpsi*point[2]]
70        draw_shape(ax, size, view, shimmy, alpha=0.8)
71    for v in 'xyz':
72        a, b, c = size
73        lim = np.sqrt(a**2+b**2+c**2)
74        getattr(ax, 'set_'+v+'lim')([-lim, lim])
75        getattr(ax, v+'axis').label.set_text(v)
76
77def draw_ellipsoid(ax, size, view, shimmy, steps=25, alpha=1):
78    a,b,c = size
79    theta, phi, psi = view
80    dtheta, dphi, dpsi = shimmy
81
82    u = np.linspace(0, 2 * np.pi, steps)
83    v = np.linspace(0, np.pi, steps)
84    x = a*np.outer(np.cos(u), np.sin(v))
85    y = b*np.outer(np.sin(u), np.sin(v))
86    z = c*np.outer(np.ones_like(u), np.cos(v))
87
88    shape = x.shape
89    points = np.matrix([x.flatten(),y.flatten(),z.flatten()])
90    points = Rz(dpsi)*Ry(dtheta)*Rx(dphi)*points
91    points = Rz(phi)*Ry(theta)*Rz(psi)*points
92    x,y,z = [v.reshape(shape) for v in points]
93
94    ax.plot_surface(x, y, z, rstride=4, cstride=4, color='w', alpha=alpha)
95
96def draw_parallelepiped(ax, size, view, shimmy, alpha=1):
97    a,b,c = size
98    theta, phi, psi = view
99    dtheta, dphi, dpsi = shimmy
100
101    x = a*np.array([ 1,-1, 1,-1, 1,-1, 1,-1])
102    y = b*np.array([ 1, 1,-1,-1, 1, 1,-1,-1])
103    z = c*np.array([ 1, 1, 1, 1,-1,-1,-1,-1])
104    tri = np.array([
105        # counter clockwise triangles
106        # z: up/down, x: right/left, y: front/back
107        [0,1,2], [3,2,1], # top face
108        [6,5,4], [5,6,7], # bottom face
109        [0,2,6], [6,4,0], # right face
110        [1,5,7], [7,3,1], # left face
111        [2,3,6], [7,6,3], # front face
112        [4,1,0], [5,1,4], # back face
113    ])
114
115    points = np.matrix([x,y,z])
116    points = Rz(dpsi)*Ry(dtheta)*Rx(dphi)*points
117    points = Rz(phi)*Ry(theta)*Rz(psi)*points
118       
119    x,y,z = [np.array(v).flatten() for v in points]
120    ax.plot_trisurf(x, y, triangles=tri, Z=z, color='w', alpha=alpha)
121
122def draw_sphere(ax, radius=10., steps=100):
123    u = np.linspace(0, 2 * np.pi, steps)
124    v = np.linspace(0, np.pi, steps)
125
126    x = radius * np.outer(np.cos(u), np.sin(v))
127    y = radius * np.outer(np.sin(u), np.sin(v))
128    z = radius * np.outer(np.ones(np.size(u)), np.cos(v))
129    ax.plot_surface(x, y, z, rstride=4, cstride=4, color='w')
130
131def draw_mesh_new(ax, theta, dtheta, phi, dphi, flow, radius=10., dist='gauss'):
132    theta_center = radians(theta)
133    phi_center = radians(phi)
134    flow_center = radians(flow)
135    dtheta = radians(dtheta)
136    dphi = radians(dphi)
137
138    # 10 point 3-sigma gaussian weights
139    t = np.linspace(-3., 3., 11)
140    if dist == 'gauss':
141        weights = exp(-0.5*t**2)
142    elif dist == 'rect':
143        weights = np.ones_like(t)
144    else:
145        raise ValueError("expected dist to be 'gauss' or 'rect'")
146    theta = dtheta*t
147    phi = dphi*t
148
149    x = radius * np.outer(cos(phi), cos(theta))
150    y = radius * np.outer(sin(phi), cos(theta))
151    z = radius * np.outer(np.ones_like(phi), sin(theta))
152    #w = np.outer(weights, weights*abs(cos(dtheta*t)))
153    w = np.outer(weights, weights*abs(cos(theta)))
154
155    x, y, z, w = [v.flatten() for v in (x,y,z,w)]
156    x, y, z = rotate(x, y, z, phi_center, theta_center, flow_center)
157
158    ax.scatter(x, y, z, c=w, marker='o', vmin=0., vmax=1.)
159
160def rotate(x, y, z, phi, theta, psi):
161    R = Rz(phi)*Ry(theta)*Rz(psi)
162    p = np.vstack([x,y,z])
163    return R*p
164
165def Rx(angle):
166    a = radians(angle)
167    R = [[1., 0., 0.],
168         [0.,  cos(a), sin(a)],
169         [0., -sin(a), cos(a)]]
170    return np.matrix(R)
171
172def Ry(angle):
173    a = radians(angle)
174    R = [[cos(a), 0., -sin(a)],
175         [0., 1., 0.],
176         [sin(a), 0.,  cos(a)]]
177    return np.matrix(R)
178
179def Rz(angle):
180    a = radians(angle)
181    R = [[cos(a), -sin(a), 0.],
182         [sin(a),  cos(a), 0.],
183         [0., 0., 1.]]
184    return np.matrix(R)
185
186def main():
187    #plt.hold(True)
188    plt.set_cmap('gist_earth')
189    plt.clf()
190    #gs = gridspec.GridSpec(2,1,height_ratios=[4,1])
191    #ax = plt.subplot(gs[0], projection='3d')
192    ax = plt.axes([0.0, 0.2, 1.0, 0.8], projection='3d')
193
194    theta, dtheta = 70., 10.
195    phi, dphi = -45., 3.
196    psi, dpsi = -45., 3.
197    theta, phi, psi = 0, 0, 0
198    #dist = 'rect'
199    dist = 'gauss'
200
201    axcolor = 'lightgoldenrodyellow'
202    axtheta  = plt.axes([0.1, 0.15, 0.45, 0.04], axisbg=axcolor)
203    axphi = plt.axes([0.1, 0.1, 0.45, 0.04], axisbg=axcolor)
204    axpsi = plt.axes([0.1, 0.05, 0.45, 0.04], axisbg=axcolor)
205    stheta = Slider(axtheta, 'Theta', -180, 180, valinit=theta)
206    sphi = Slider(axphi, 'Phi', -180, 180, valinit=phi)
207    spsi = Slider(axpsi, 'Psi', -180, 180, valinit=psi)
208    axdtheta  = plt.axes([0.75, 0.15, 0.15, 0.04], axisbg=axcolor)
209    axdphi = plt.axes([0.75, 0.1, 0.15, 0.04], axisbg=axcolor)
210    axdpsi= plt.axes([0.75, 0.05, 0.15, 0.04], axisbg=axcolor)
211    sdtheta = Slider(axdtheta, 'dTheta', 0, 30, valinit=dtheta)
212    sdphi = Slider(axdphi, 'dPhi', 0, 30, valinit=dphi)
213    sdpsi = Slider(axdpsi, 'dPsi', 0, 30, valinit=dphi)
214
215    def update(val, axis=None):
216        theta, phi, psi = stheta.val, sphi.val, spsi.val
217        dtheta, dphi, dpsi = sdtheta.val, sdphi.val, sdpsi.val
218        ax.cla()
219        draw_beam(ax)
220        draw_shimmy(ax, theta, phi, psi, dtheta, dphi, dpsi)
221        #if not axis.startswith('d'):
222        #    ax.view_init(elev=theta, azim=phi)
223        plt.gcf().canvas.draw()
224
225    stheta.on_changed(lambda v: update(v,'theta'))
226    sphi.on_changed(lambda v: update(v, 'phi'))
227    spsi.on_changed(lambda v: update(v, 'psi'))
228    sdtheta.on_changed(lambda v: update(v, 'dtheta'))
229    sdphi.on_changed(lambda v: update(v, 'dphi'))
230    sdpsi.on_changed(lambda v: update(v, 'dpsi'))
231
232    update(None, 'phi')
233
234    plt.show()
235
236if __name__ == "__main__":
237    main()
Note: See TracBrowser for help on using the repository browser.