source: sasmodels/explore/angular_pd.py @ ac995be

Last change on this file since ac995be was 8267e0b, checked in by Paul Kienzle <pkienzle@…>, 8 years ago

orientation: update orientational dispersion demo app with theta=0 along the beam

  • Property mode set to 100644
File size: 5.1 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_sphere(ax, radius=10., steps=100):
14    u = np.linspace(0, 2 * np.pi, steps)
15    v = np.linspace(0, np.pi, steps)
16
17    x = radius * np.outer(np.cos(u), np.sin(v))
18    y = radius * np.outer(np.sin(u), np.sin(v))
19    z = radius * np.outer(np.ones(np.size(u)), np.cos(v))
20    ax.plot_surface(x, y, z, rstride=4, cstride=4, color='w')
21
22def draw_mesh_current(ax, theta, dtheta, phi, dphi, radius=10., dist='gauss'):
23    theta = radians(theta)
24    phi = radians(phi)
25    dtheta = radians(dtheta)
26    dphi = radians(dphi)
27
28    # 10 point 3-sigma gaussian weights
29    t = np.linspace(-3., 3., 11)
30    if dist == 'gauss':
31        weights = exp(-0.5*t**2)
32    elif dist == 'rect':
33        weights = np.ones_like(t)
34    else:
35        raise ValueError("expected dist to be 'gauss' or 'rect'")
36    theta = theta + dtheta*t
37    phi = phi + dphi*t
38
39    x = radius * np.outer(cos(phi), cos(theta))
40    y = radius * np.outer(sin(phi), cos(theta))
41    z = radius * np.outer(np.ones_like(phi), sin(theta))
42    w = np.outer(weights, weights*abs(cos(theta)))
43
44    x,y,z,w = [v.flatten() for v in (x,y,z,w)]
45
46    ax.scatter(x, y, z, c=w, marker='o', vmin=0., vmax=1.0)
47
48def draw_mesh_new(ax, theta, dtheta, phi, dphi, flow, radius=10., dist='gauss'):
49    theta_center = radians(90-theta)
50    phi_center = radians(phi)
51    flow_center = radians(flow)
52    dtheta = radians(dtheta)
53    dphi = radians(dphi)
54
55    # 10 point 3-sigma gaussian weights
56    t = np.linspace(-3., 3., 11)
57    if dist == 'gauss':
58        weights = exp(-0.5*t**2)
59    elif dist == 'rect':
60        weights = np.ones_like(t)
61    else:
62        raise ValueError("expected dist to be 'gauss' or 'rect'")
63    theta = dtheta*t
64    phi = dphi*t
65
66    x = radius * np.outer(cos(phi), cos(theta))
67    y = radius * np.outer(sin(phi), cos(theta))
68    z = radius * np.outer(np.ones_like(phi), sin(theta))
69    #w = np.outer(weights, weights*abs(cos(dtheta*t)))
70    w = np.outer(weights, weights*abs(cos(theta)))
71
72    x, y, z, w = [v.flatten() for v in (x,y,z,w)]
73    x, y, z = rotate(x, y, z, phi_center, theta_center, flow_center)
74
75    ax.scatter(x, y, z, c=w, marker='o', vmin=0., vmax=1.)
76
77def rotate(x, y, z, phi, theta, psi):
78    R = rotation_matrix(psi, theta, phi)
79    p = np.vstack([x,y,z])
80    q = np.dot(R,p)
81    return q
82
83def rotation_matrix(xa,ya,za):
84    Rz = [[cos(za), -sin(za), 0.],
85          [sin(za),  cos(za), 0.],
86          [0., 0., 1.]]
87    Ry = [[cos(ya), 0., -sin(ya)],
88          [0., 1., 0.],
89          [sin(ya), 0.,  cos(ya)]]
90    Rx = [[1., 0., 0.],
91          [0.,  cos(xa), sin(xa)],
92          [0., -sin(xa), cos(xa)]]
93    R = np.dot(np.dot(Rz, Ry), Rx)
94    return R
95
96def main():
97    plt.hold(True)
98    plt.set_cmap('gist_earth')
99    plt.clf()
100    #gs = gridspec.GridSpec(2,1,height_ratios=[4,1])
101    #ax = plt.subplot(gs[0], projection='3d')
102    ax = plt.axes([0.0, 0.2, 1.0, 0.8], projection='3d')
103
104    phi, dphi = -45., 3.
105    theta, dtheta = 70., 10.
106    flow = 0.
107    #dist = 'rect'
108    dist = 'gauss'
109
110    axcolor = 'lightgoldenrodyellow'
111    axphi = plt.axes([0.1, 0.1, 0.45, 0.04], axisbg=axcolor)
112    axtheta  = plt.axes([0.1, 0.15, 0.45, 0.04], axisbg=axcolor)
113    sphi = Slider(axphi, 'Phi', -180, 180, valinit=phi)
114    stheta = Slider(axtheta, 'Theta', -180, 180, valinit=theta)
115    axdphi = plt.axes([0.75, 0.1, 0.15, 0.04], axisbg=axcolor)
116    axdtheta  = plt.axes([0.75, 0.15, 0.15, 0.04], axisbg=axcolor)
117    sdphi = Slider(axdphi, 'dPhi', 0, 30, valinit=dphi)
118    sdtheta = Slider(axdtheta, 'dTheta', 0, 30, valinit=dtheta)
119
120    axflow = plt.axes([0.1, 0.05, 0.45, 0.04], axisbg=axcolor)
121    sflow = Slider(axflow, 'Flow', -180, 180, valinit=flow)
122    axusenew= plt.axes([0.75, 0.05, 0.15, 0.04], axisbg=axcolor)
123    susenew = CheckButtons(axusenew, ['New'], [True])
124
125    def update(val, axis=None):
126        phi, theta = sphi.val, stheta.val
127        dphi, dtheta = sdphi.val, sdtheta.val
128        flow = sflow.val
129        use_new = susenew.lines[0][0].get_visible()
130        ax.cla()
131        draw_sphere(ax)
132        if use_new:
133            draw_mesh_new(ax, theta=theta, dtheta=dtheta, phi=phi, dphi=dphi,
134                          flow=flow, radius=11., dist=dist)
135        else:
136            draw_mesh_current(ax, theta=theta, dtheta=dtheta, phi=phi, dphi=dphi,
137                              radius=11., dist=dist)
138        if not axis.startswith('d'):
139            ax.view_init(elev=90-theta if use_new else theta, azim=phi)
140        plt.gcf().canvas.draw()
141
142    stheta.on_changed(lambda v: update(v,'theta'))
143    sphi.on_changed(lambda v: update(v, 'phi'))
144    sdtheta.on_changed(lambda v: update(v, 'dtheta'))
145    sdphi.on_changed(lambda v: update(v, 'dphi'))
146    sflow.on_changed(lambda v: update(v, 'dflow'))
147    susenew.on_clicked(lambda v: update(v, 'use_new'))
148
149    update(None, 'phi')
150
151    plt.show()
152
153if __name__ == "__main__":
154    main()
Note: See TracBrowser for help on using the repository browser.