Changeset d86f0fc in sasmodels for sasmodels/jitter.py
- Timestamp:
- Mar 26, 2018 3:52:24 PM (6 years ago)
- Branches:
- master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- 802c412
- Parents:
- f4ae8c4
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/jitter.py
r199bd07 rd86f0fc 7 7 """ 8 8 from __future__ import division, print_function 9 10 import sys, os11 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))12 9 13 10 import argparse … … 50 47 def draw_ellipsoid(ax, size, view, jitter, steps=25, alpha=1): 51 48 """Draw an ellipsoid.""" 52 a, b,c = size49 a, b, c = size 53 50 u = np.linspace(0, 2 * np.pi, steps) 54 51 v = np.linspace(0, np.pi, steps) … … 61 58 62 59 draw_labels(ax, view, jitter, [ 63 ('c+', [ 0, 0, c], [ 1, 0,0]),64 ('c-', [ 0, 0,-c], [ 0, 0,-1]),65 ('a+', [ a, 0, 0], [ 0, 0,1]),66 ('a-', [-a, 0, 0], [ 0, 0,-1]),67 ('b+', [ 0, b, 0], [-1, 0,0]),68 ('b-', [ 0,-b, 0], [-1, 0,0]),60 ('c+', [+0, +0, +c], [+1, +0, +0]), 61 ('c-', [+0, +0, -c], [+0, +0, -1]), 62 ('a+', [+a, +0, +0], [+0, +0, +1]), 63 ('a-', [-a, +0, +0], [+0, +0, -1]), 64 ('b+', [+0, +b, +0], [-1, +0, +0]), 65 ('b-', [+0, -b, +0], [-1, +0, +0]), 69 66 ]) 70 67 71 68 def draw_sc(ax, size, view, jitter, steps=None, alpha=1): 69 """Draw points for simple cubic paracrystal""" 72 70 atoms = _build_sc() 73 71 _draw_crystal(ax, size, view, jitter, atoms=atoms) 74 72 75 73 def draw_fcc(ax, size, view, jitter, steps=None, alpha=1): 74 """Draw points for face-centered cubic paracrystal""" 76 75 # Build the simple cubic crystal 77 76 atoms = _build_sc() … … 88 87 89 88 def draw_bcc(ax, size, view, jitter, steps=None, alpha=1): 89 """Draw points for body-centered cubic paracrystal""" 90 90 # Build the simple cubic crystal 91 91 atoms = _build_sc() … … 127 127 """Draw a parallelepiped.""" 128 128 a, b, c = size 129 x = a*np.array([ 1,-1, 1,-1, 1,-1, 1,-1])130 y = b*np.array([ 1, 1,-1,-1, 1, 1,-1,-1])131 z = c*np.array([ 1, 1, 1, 1,-1,-1,-1,-1])129 x = a*np.array([+1, -1, +1, -1, +1, -1, +1, -1]) 130 y = b*np.array([+1, +1, -1, -1, +1, +1, -1, -1]) 131 z = c*np.array([+1, +1, +1, +1, -1, -1, -1, -1]) 132 132 tri = np.array([ 133 133 # counter clockwise triangles 134 134 # z: up/down, x: right/left, y: front/back 135 [0, 1,2], [3,2,1], # top face136 [6, 5,4], [5,6,7], # bottom face137 [0, 2,6], [6,4,0], # right face138 [1, 5,7], [7,3,1], # left face139 [2, 3,6], [7,6,3], # front face140 [4, 1,0], [5,1,4], # back face135 [0, 1, 2], [3, 2, 1], # top face 136 [6, 5, 4], [5, 6, 7], # bottom face 137 [0, 2, 6], [6, 4, 0], # right face 138 [1, 5, 7], [7, 3, 1], # left face 139 [2, 3, 6], [7, 6, 3], # front face 140 [4, 1, 0], [5, 1, 4], # back face 141 141 ]) 142 142 … … 149 149 # rotate that face. 150 150 if 1: 151 x = a*np.array([ 1,-1, 1,-1, 1,-1, 1,-1])152 y = b*np.array([ 1, 1,-1,-1, 1, 1,-1,-1])153 z = c*np.array([ 1, 1, 1, 1,-1,-1,-1,-1])151 x = a*np.array([+1, -1, +1, -1, +1, -1, +1, -1]) 152 y = b*np.array([+1, +1, -1, -1, +1, +1, -1, -1]) 153 z = c*np.array([+1, +1, +1, +1, -1, -1, -1, -1]) 154 154 x, y, z = transform_xyz(view, jitter, x, y, abs(z)+0.001) 155 ax.plot_trisurf(x, y, triangles=tri, Z=z, color=[1, 0.6,0.6], alpha=alpha)155 ax.plot_trisurf(x, y, triangles=tri, Z=z, color=[1, 0.6, 0.6], alpha=alpha) 156 156 157 157 draw_labels(ax, view, jitter, [ 158 ('c+', [ 0, 0, c], [ 1, 0,0]),159 ('c-', [ 0, 0,-c], [ 0, 0,-1]),160 ('a+', [ a, 0, 0], [ 0, 0,1]),161 ('a-', [-a, 0, 0], [ 0, 0,-1]),162 ('b+', [ 0, b, 0], [-1, 0,0]),163 ('b-', [ 0,-b, 0], [-1, 0,0]),158 ('c+', [+0, +0, +c], [+1, +0, +0]), 159 ('c-', [+0, +0, -c], [+0, +0, -1]), 160 ('a+', [+a, +0, +0], [+0, +0, +1]), 161 ('a-', [-a, +0, +0], [+0, +0, -1]), 162 ('b+', [+0, +b, +0], [-1, +0, +0]), 163 ('b-', [+0, -b, +0], [-1, +0, +0]), 164 164 ]) 165 165 … … 187 187 cloud = [ 188 188 [-1, -1, -1], 189 [-1, -1, 190 [-1, -1, 191 [-1, 192 [-1, 0,0],193 [-1, 0,1],194 [-1, 195 [-1, 1,0],196 [-1, 1,1],197 [ 198 [ 0, -1,0],199 [ 0, -1,1],200 [ 0,0, -1],201 [ 0, 0,0],202 [ 0, 0,1],203 [ 0,1, -1],204 [ 0, 1,0],205 [ 0, 1,1],206 [ 207 [ 1, -1,0],208 [ 1, -1,1],209 [ 1,0, -1],210 [ 1, 0,0],211 [ 1, 0,1],212 [ 1,1, -1],213 [ 1, 1,0],214 [ 1, 1,1],189 [-1, -1, +0], 190 [-1, -1, +1], 191 [-1, +0, -1], 192 [-1, +0, +0], 193 [-1, +0, +1], 194 [-1, +1, -1], 195 [-1, +1, +0], 196 [-1, +1, +1], 197 [+0, -1, -1], 198 [+0, -1, +0], 199 [+0, -1, +1], 200 [+0, +0, -1], 201 [+0, +0, +0], 202 [+0, +0, +1], 203 [+0, +1, -1], 204 [+0, +1, +0], 205 [+0, +1, +1], 206 [+1, -1, -1], 207 [+1, -1, +0], 208 [+1, -1, +1], 209 [+1, +0, -1], 210 [+1, +0, +0], 211 [+1, +0, +1], 212 [+1, +1, -1], 213 [+1, +1, +0], 214 [+1, +1, +1], 215 215 ] 216 216 dtheta, dphi, dpsi = jitter … … 228 228 for v in 'xyz': 229 229 a, b, c = size 230 lim = np.sqrt(a**2 +b**2+c**2)230 lim = np.sqrt(a**2 + b**2 + c**2) 231 231 getattr(ax, 'set_'+v+'lim')([-lim, lim]) 232 232 getattr(ax, v+'axis').label.set_text(v) … … 297 297 Should allow free movement in theta, but phi is distorted. 298 298 """ 299 theta, phi, psi = view300 dtheta, dphi, dpsi = jitter301 302 299 t = np.linspace(-1, 1, n) 303 300 weights = np.ones_like(t) … … 314 311 315 312 if projection == 'equirectangular': #define PROJECTION 1 316 def rotate(theta_i, phi_j):313 def _rotate(theta_i, phi_j): 317 314 return Rx(phi_j)*Ry(theta_i) 318 def weight(theta_i, phi_j, wi, wj):315 def _weight(theta_i, phi_j, wi, wj): 319 316 return wi*wj*abs(cos(radians(theta_i))) 320 317 elif projection == 'sinusoidal': #define PROJECTION 2 321 def rotate(theta_i, phi_j):318 def _rotate(theta_i, phi_j): 322 319 latitude = theta_i 323 320 scale = cos(radians(latitude)) … … 325 322 #print("(%+7.2f, %+7.2f) => (%+7.2f, %+7.2f)"%(theta_i, phi_j, latitude, longitude)) 326 323 return Rx(longitude)*Ry(latitude) 327 def weight(theta_i, phi_j, wi, wj):324 def _weight(theta_i, phi_j, wi, wj): 328 325 latitude = theta_i 329 326 scale = cos(radians(latitude)) … … 331 328 return w*wi*wj 332 329 elif projection == 'guyou': #define PROJECTION 3 (eventually?) 333 def rotate(theta_i, phi_j):330 def _rotate(theta_i, phi_j): 334 331 from guyou import guyou_invert 335 332 #latitude, longitude = guyou_invert([theta_i], [phi_j]) 336 333 longitude, latitude = guyou_invert([phi_j], [theta_i]) 337 334 return Rx(longitude[0])*Ry(latitude[0]) 338 def weight(theta_i, phi_j, wi, wj):335 def _weight(theta_i, phi_j, wi, wj): 339 336 return wi*wj 340 337 elif projection == 'azimuthal_equidistance': # Note: Rz Ry, not Rx Ry 341 def rotate(theta_i, phi_j):338 def _rotate(theta_i, phi_j): 342 339 latitude = sqrt(theta_i**2 + phi_j**2) 343 340 longitude = degrees(np.arctan2(phi_j, theta_i)) 344 341 #print("(%+7.2f, %+7.2f) => (%+7.2f, %+7.2f)"%(theta_i, phi_j, latitude, longitude)) 345 342 return Rz(longitude)*Ry(latitude) 346 def weight(theta_i, phi_j, wi, wj):343 def _weight(theta_i, phi_j, wi, wj): 347 344 # Weighting for each point comes from the integral: 348 345 # \int\int I(q, lat, log) sin(lat) dlat dlog … … 377 374 return w*wi*wj if latitude < 180 else 0 378 375 elif projection == 'azimuthal_equal_area': 379 def rotate(theta_i, phi_j):376 def _rotate(theta_i, phi_j): 380 377 R = min(1, sqrt(theta_i**2 + phi_j**2)/180) 381 378 latitude = 180-degrees(2*np.arccos(R)) … … 383 380 #print("(%+7.2f, %+7.2f) => (%+7.2f, %+7.2f)"%(theta_i, phi_j, latitude, longitude)) 384 381 return Rz(longitude)*Ry(latitude) 385 def weight(theta_i, phi_j, wi, wj):382 def _weight(theta_i, phi_j, wi, wj): 386 383 latitude = sqrt(theta_i**2 + phi_j**2) 387 384 w = sin(radians(latitude))/latitude if latitude != 0 else 1 … … 391 388 392 389 # mesh in theta, phi formed by rotating z 390 dtheta, dphi, dpsi = jitter 393 391 z = np.matrix([[0], [0], [radius]]) 394 points = np.hstack([ rotate(theta_i, phi_j)*z392 points = np.hstack([_rotate(theta_i, phi_j)*z 395 393 for theta_i in dtheta*t 396 394 for phi_j in dphi*t]) 397 395 # select just the active points (i.e., those with phi < 180 398 w = np.array([ weight(theta_i, phi_j, wi, wj)396 w = np.array([_weight(theta_i, phi_j, wi, wj) 399 397 for wi, theta_i in zip(weights, dtheta*t) 400 398 for wj, phi_j in zip(weights, dphi*t)]) 401 399 #print(max(w), min(w), min(w[w>0])) 402 points = points[:, w >0]403 w = w[w >0]400 points = points[:, w > 0] 401 w = w[w > 0] 404 402 w /= max(w) 405 403 … … 469 467 x, y, z = [np.asarray(v) for v in (x, y, z)] 470 468 shape = x.shape 471 points = np.matrix([x.flatten(), y.flatten(),z.flatten()])469 points = np.matrix([x.flatten(), y.flatten(), z.flatten()]) 472 470 points = apply_jitter(jitter, points) 473 471 points = orient_relative_to_beam(view, points) … … 543 541 theta, phi, psi = view 544 542 theta_pd, phi_pd, psi_pd = [scale*v for v in jitter] 545 theta_pd_n, phi_pd_n, psi_pd_n = PD_N_TABLE[(theta_pd >0, phi_pd>0, psi_pd>0)]543 theta_pd_n, phi_pd_n, psi_pd_n = PD_N_TABLE[(theta_pd > 0, phi_pd > 0, psi_pd > 0)] 546 544 ## increase pd_n for testing jitter integration rather than simple viz 547 545 #theta_pd_n, phi_pd_n, psi_pd_n = [5*v for v in (theta_pd_n, phi_pd_n, psi_pd_n)] … … 571 569 if 0: 572 570 level = np.asarray(255*(Iqxy - vmin)/(vmax - vmin), 'i') 573 level[level <0] = 0571 level[level < 0] = 0 574 572 colors = plt.get_cmap()(level) 575 573 ax.plot_surface(qx, qy, -1.1, rstride=1, cstride=1, facecolors=colors) … … 618 616 return calculator 619 617 620 def select_calculator(model_name, n=150, size=(10, 40,100)):618 def select_calculator(model_name, n=150, size=(10, 40, 100)): 621 619 """ 622 620 Create a model calculator for the given shape. … … 641 639 radius = 0.5*c 642 640 calculator = build_model('sc_paracrystal', n=n, dnn=dnn, 643 644 641 d_factor=d_factor, radius=(1-d_factor)*radius, 642 background=0) 645 643 elif model_name == 'fcc_paracrystal': 646 644 a = b = c … … 650 648 radius = sqrt(2)/4 * c 651 649 calculator = build_model('fcc_paracrystal', n=n, dnn=dnn, 652 653 650 d_factor=d_factor, radius=(1-d_factor)*radius, 651 background=0) 654 652 elif model_name == 'bcc_paracrystal': 655 653 a = b = c … … 659 657 radius = sqrt(3)/2 * c 660 658 calculator = build_model('bcc_paracrystal', n=n, dnn=dnn, 661 662 659 d_factor=d_factor, radius=(1-d_factor)*radius, 660 background=0) 663 661 elif model_name == 'cylinder': 664 662 calculator = build_model('cylinder', n=n, qmax=0.3, radius=b, length=c) … … 685 683 'cylinder', 686 684 'fcc_paracrystal', 'bcc_paracrystal', 'sc_paracrystal', 687 685 ] 688 686 689 687 DRAW_SHAPES = { … … 761 759 762 760 ## add control widgets to plot 763 axtheta 761 axtheta = plt.axes([0.1, 0.15, 0.45, 0.04], axisbg=axcolor) 764 762 axphi = plt.axes([0.1, 0.1, 0.45, 0.04], axisbg=axcolor) 765 763 axpsi = plt.axes([0.1, 0.05, 0.45, 0.04], axisbg=axcolor) … … 768 766 spsi = Slider(axpsi, 'Psi', -180, 180, valinit=psi) 769 767 770 axdtheta 768 axdtheta = plt.axes([0.75, 0.15, 0.15, 0.04], axisbg=axcolor) 771 769 axdphi = plt.axes([0.75, 0.1, 0.15, 0.04], axisbg=axcolor) 772 axdpsi = plt.axes([0.75, 0.05, 0.15, 0.04], axisbg=axcolor)770 axdpsi = plt.axes([0.75, 0.05, 0.15, 0.04], axisbg=axcolor) 773 771 # Note: using ridiculous definition of rectangle distribution, whose width 774 772 # in sasmodels is sqrt(3) times the given width. Divide by sqrt(3) to keep … … 797 795 798 796 ## bind control widgets to view updater 799 stheta.on_changed(lambda v: update(v, 'theta'))797 stheta.on_changed(lambda v: update(v, 'theta')) 800 798 sphi.on_changed(lambda v: update(v, 'phi')) 801 799 spsi.on_changed(lambda v: update(v, 'psi')) … … 815 813 formatter_class=argparse.ArgumentDefaultsHelpFormatter, 816 814 ) 817 parser.add_argument('-p', '--projection', choices=PROJECTIONS, default=PROJECTIONS[0], help='coordinate projection') 818 parser.add_argument('-s', '--size', type=str, default='10,40,100', help='a,b,c lengths') 819 parser.add_argument('-d', '--distribution', choices=DISTRIBUTIONS, default=DISTRIBUTIONS[0], help='jitter distribution') 820 parser.add_argument('-m', '--mesh', type=int, default=30, help='#points in theta-phi mesh') 821 parser.add_argument('shape', choices=SHAPES, nargs='?', default=SHAPES[0], help='oriented shape') 815 parser.add_argument('-p', '--projection', choices=PROJECTIONS, 816 default=PROJECTIONS[0], 817 help='coordinate projection') 818 parser.add_argument('-s', '--size', type=str, default='10,40,100', 819 help='a,b,c lengths') 820 parser.add_argument('-d', '--distribution', choices=DISTRIBUTIONS, 821 default=DISTRIBUTIONS[0], 822 help='jitter distribution') 823 parser.add_argument('-m', '--mesh', type=int, default=30, 824 help='#points in theta-phi mesh') 825 parser.add_argument('shape', choices=SHAPES, nargs='?', default=SHAPES[0], 826 help='oriented shape') 822 827 opts = parser.parse_args() 823 828 size = tuple(int(v) for v in opts.size.split(','))
Note: See TracChangeset
for help on using the changeset viewer.