Changes in explore/realspace.py [362a66f:5778279] in sasmodels
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
explore/realspace.py
r362a66f r5778279 9 9 import numpy as np 10 10 from numpy import pi, radians, sin, cos, sqrt 11 from numpy.random import poisson, uniform, randn, rand 11 from numpy.random import poisson, uniform, randn, rand, randint 12 12 from numpy.polynomial.legendre import leggauss 13 13 from scipy.integrate import simps … … 78 78 79 79 80 I3 = np.matrix([[1., 0, 0], [0, 1, 0], [0, 0, 1]]) 81 80 82 class Shape: 81 rotation = np.matrix([[1., 0, 0], [0, 1, 0], [0, 0, 1]])83 rotation = I3 82 84 center = np.array([0., 0., 0.])[:, None] 83 85 r_max = None 86 lattice_size = np.array((1, 1, 1)) 87 lattice_spacing = np.array((1., 1., 1.)) 88 lattice_distortion = 0.0 89 lattice_rotation = 0.0 90 lattice_type = "" 84 91 85 92 def volume(self): … … 96 103 97 104 def rotate(self, theta, phi, psi): 98 self.rotation = rotation(theta, phi, psi) * self.rotation 105 if theta != 0. or phi != 0. or psi != 0.: 106 self.rotation = rotation(theta, phi, psi) * self.rotation 99 107 return self 100 108 … … 103 111 return self 104 112 113 def lattice(self, size=(1, 1, 1), spacing=(2, 2, 2), type="sc", 114 distortion=0.0, rotation=0.0): 115 self.lattice_size = np.asarray(size, 'i') 116 self.lattice_spacing = np.asarray(spacing, 'd') 117 self.lattice_type = type 118 self.lattice_distortion = distortion 119 self.lattice_rotation = rotation 120 105 121 def _adjust(self, points): 106 points = np.asarray(self.rotation * np.matrix(points.T)) + self.center 122 if self.rotation is I3: 123 points = points.T + self.center 124 else: 125 points = np.asarray(self.rotation * np.matrix(points.T)) + self.center 126 if self.lattice_type: 127 points = self._apply_lattice(points) 107 128 return points.T 108 129 109 def r_bins(self, q, over_sampling=1, r_step=0.): 110 r_max = min(2 * pi / q[0], self.r_max) 130 def r_bins(self, q, over_sampling=10, r_step=0.): 131 if self.lattice_type: 132 r_max = np.sqrt(np.sum(self.lattice_size*self.lattice_spacing*self.dims)**2)/2 133 else: 134 r_max = self.r_max 135 #r_max = min(2 * pi / q[0], r_max) 111 136 if r_step == 0.: 112 137 r_step = 2 * pi / q[-1] / over_sampling 113 138 #r_step = 0.01 114 139 return np.arange(r_step, r_max, r_step) 140 141 def _apply_lattice(self, points): 142 """Spread points to different lattice positions""" 143 size = self.lattice_size 144 spacing = self.lattice_spacing 145 shuffle = self.lattice_distortion 146 rotate = self.lattice_rotation 147 lattice = self.lattice_type 148 149 if rotate != 0: 150 # To vectorize the rotations we will need to unwrap the matrix multiply 151 raise NotImplementedError("don't handle rotations yet") 152 153 # Determine the number of lattice points in the lattice 154 shapes_per_cell = 2 if lattice == "bcc" else 4 if lattice == "fcc" else 1 155 number_of_lattice_points = np.prod(size) * shapes_per_cell 156 157 # For each point in the original shape, figure out which lattice point 158 # to translate it to. This is both cell index (i*ny*nz + j*nz + k) as 159 # well as the point in the cell (corner, body center or face center). 160 nsamples = points.shape[1] 161 lattice_point = randint(number_of_lattice_points, size=nsamples) 162 163 # Translate the cell index into the i,j,k coordinates of the senter 164 cell_index = lattice_point // shapes_per_cell 165 center = np.vstack((cell_index//(size[1]*size[2]), 166 (cell_index%(size[1]*size[2]))//size[2], 167 cell_index%size[2])) 168 center = np.asarray(center, dtype='d') 169 if lattice == "bcc": 170 center[:, lattice_point % shapes_per_cell == 1] += [[0.5], [0.5], [0.5]] 171 elif lattice == "fcc": 172 center[:, lattice_point % shapes_per_cell == 1] += [[0.0], [0.5], [0.5]] 173 center[:, lattice_point % shapes_per_cell == 2] += [[0.5], [0.0], [0.5]] 174 center[:, lattice_point % shapes_per_cell == 3] += [[0.5], [0.5], [0.0]] 175 176 # Each lattice point has its own displacement from the ideal position. 177 # Not checking that shapes do not overlap if displacement is too large. 178 offset = shuffle*(randn(3, number_of_lattice_points) if shuffle < 0.3 179 else rand(3, number_of_lattice_points)) 180 center += offset[:, cell_index] 181 182 # Each lattice point has its own rotation. Rotate the point prior to 183 # applying any displacement. 184 # rotation = rotate*(randn(size=(shapes, 3)) if shuffle < 30 else rand(size=(nsamples, 3))) 185 # for k in shapes: points[k] = rotation[k]*points[k] 186 points += center*(np.array([spacing])*np.array(self.dims)).T 187 return points 115 188 116 189 class Composite(Shape): … … 669 742 Iq = 100 * np.ones_like(qx) 670 743 data = Data2D(x=qx, y=qy, z=Iq, dx=None, dy=None, dz=np.sqrt(Iq)) 671 data.x_bins = qx[0, :]672 data.y_bins = qy[:, 0]744 data.x_bins = qx[0, :] 745 data.y_bins = qy[:, 0] 673 746 data.filename = "fake data" 674 747 … … 695 768 return shape, fn, fn_xy 696 769 697 def build_sphere(radius=125, rho=2): 770 DEFAULT_SPHERE_RADIUS = 125 771 DEFAULT_SPHERE_CONTRAST = 2 772 def build_sphere(radius=DEFAULT_SPHERE_RADIUS, rho=DEFAULT_SPHERE_CONTRAST): 698 773 shape = TriaxialEllipsoid(radius, radius, radius, rho) 699 774 fn = lambda q: sphere_Iq(q, radius)*rho**2 … … 751 826 return shape, fn, fn_xy 752 827 753 def build_ cubic_lattice(shape, nx=1, ny=1, nz=1, dx=2, dy=2, dz=2,754 shuffle=0, rotate=0):828 def build_sc_lattice(shape, nx=1, ny=1, nz=1, dx=2, dy=2, dz=2, 829 shuffle=0, rotate=0): 755 830 a, b, c = shape.dims 756 shapes= [copy(shape)831 corners= [copy(shape) 757 832 .shift((ix+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 758 833 (iy+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, … … 762 837 for iy in range(ny) 763 838 for iz in range(nz)] 764 lattice = Composite( shapes)839 lattice = Composite(corners) 765 840 return lattice 766 841 842 def build_bcc_lattice(shape, nx=1, ny=1, nz=1, dx=2, dy=2, dz=2, 843 shuffle=0, rotate=0): 844 a, b, c = shape.dims 845 corners = [copy(shape) 846 .shift((ix+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 847 (iy+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 848 (iz+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 849 .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 850 for ix in range(nx) 851 for iy in range(ny) 852 for iz in range(nz)] 853 centers = [copy(shape) 854 .shift((ix+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 855 (iy+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 856 (iz+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 857 .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 858 for ix in range(nx) 859 for iy in range(ny) 860 for iz in range(nz)] 861 lattice = Composite(corners + centers) 862 return lattice 863 864 def build_fcc_lattice(shape, nx=1, ny=1, nz=1, dx=2, dy=2, dz=2, 865 shuffle=0, rotate=0): 866 a, b, c = shape.dims 867 corners = [copy(shape) 868 .shift((ix+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 869 (iy+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 870 (iz+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 871 .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 872 for ix in range(nx) 873 for iy in range(ny) 874 for iz in range(nz)] 875 faces_a = [copy(shape) 876 .shift((ix+0.0+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 877 (iy+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 878 (iz+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 879 .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 880 for ix in range(nx) 881 for iy in range(ny) 882 for iz in range(nz)] 883 faces_b = [copy(shape) 884 .shift((ix+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 885 (iy+0.0+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 886 (iz+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 887 .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 888 for ix in range(nx) 889 for iy in range(ny) 890 for iz in range(nz)] 891 faces_c = [copy(shape) 892 .shift((ix+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dx*a, 893 (iy+0.5+(randn() if shuffle < 0.3 else rand())*shuffle)*dy*b, 894 (iz+0.0+(randn() if shuffle < 0.3 else rand())*shuffle)*dz*c) 895 .rotate(*((randn(3) if rotate < 30 else rand(3))*rotate)) 896 for ix in range(nx) 897 for iy in range(ny) 898 for iz in range(nz)] 899 lattice = Composite(corners + faces_a + faces_b + faces_c) 900 return lattice 767 901 768 902 SHAPE_FUNCTIONS = OrderedDict([ … … 775 909 ]) 776 910 SHAPES = list(SHAPE_FUNCTIONS.keys()) 911 LATTICE_FUNCTIONS = OrderedDict([ 912 ("sc", build_sc_lattice), 913 ("bcc", build_bcc_lattice), 914 ("fcc", build_fcc_lattice), 915 ]) 916 LATTICE_TYPES = list(LATTICE_FUNCTIONS.keys()) 777 917 778 918 def check_shape(title, shape, fn=None, show_points=False, … … 783 923 r = shape.r_bins(q, r_step=r_step) 784 924 sampling_density = samples / shape.volume 925 print("sampling points") 785 926 rho, points = shape.sample(sampling_density) 927 print("calculating Pr") 786 928 t0 = time.time() 787 929 Pr = calc_Pr(r, rho-rho_solvent, points) … … 792 934 import pylab 793 935 if show_points: 794 936 plot_points(rho, points); pylab.figure() 795 937 plot_calc(r, Pr, q, Iq, theory=theory, title=title) 796 938 pylab.gcf().canvas.set_window_title(title) … … 806 948 Qx, Qy = np.meshgrid(qx, qy) 807 949 sampling_density = samples / shape.volume 950 print("sampling points") 808 951 t0 = time.time() 809 952 rho, points = shape.sample(sampling_density) … … 844 987 help='lattice size') 845 988 parser.add_argument('-z', '--spacing', type=str, default='2,2,2', 846 help='lattice spacing') 989 help='lattice spacing (relative to shape)') 990 parser.add_argument('-t', '--type', choices=LATTICE_TYPES, 991 default=LATTICE_TYPES[0], 992 help='lattice type') 847 993 parser.add_argument('-r', '--rotate', type=float, default=0., 848 994 help="rotation relative to lattice, gaussian < 30 degrees, uniform otherwise") … … 858 1004 nx, ny, nz = [int(v) for v in opts.lattice.split(',')] 859 1005 dx, dy, dz = [float(v) for v in opts.spacing.split(',')] 860 shuffle, rotate= opts.shuffle, opts.rotate1006 distortion, rotation = opts.shuffle, opts.rotate 861 1007 shape, fn, fn_xy = SHAPE_FUNCTIONS[opts.shape](**pars) 862 if nx > 1 or ny > 1 or nz > 1: 863 shape = build_cubic_lattice(shape, nx, ny, nz, dx, dy, dz, shuffle, rotate) 1008 view = tuple(float(v) for v in opts.view.split(',')) 1009 # If comparing a sphere in a cubic lattice, compare against the 1010 # corresponding paracrystalline model. 1011 if opts.shape == "sphere" and dx == dy == dz and nx*ny*nz > 1: 1012 radius = pars.get('radius', DEFAULT_SPHERE_RADIUS) 1013 model_name = opts.type + "_paracrystal" 1014 model_pars = { 1015 "scale": 1., 1016 "background": 0., 1017 "lattice_spacing": 2*radius*dx, 1018 "lattice_distortion": distortion, 1019 "radius": radius, 1020 "sld": pars.get('rho', DEFAULT_SPHERE_CONTRAST), 1021 "sld_solvent": 0., 1022 "theta": view[0], 1023 "phi": view[1], 1024 "psi": view[2], 1025 } 1026 fn, fn_xy = wrap_sasmodel(model_name, **model_pars) 1027 if nx*ny*nz > 1: 1028 if rotation != 0: 1029 print("building %s lattice"%opts.type) 1030 build_lattice = LATTICE_FUNCTIONS[opts.type] 1031 shape = build_lattice(shape, nx, ny, nz, dx, dy, dz, 1032 distortion, rotation) 1033 else: 1034 shape.lattice(size=(nx, ny, nz), spacing=(dx, dy, dz), 1035 type=opts.type, 1036 rotation=rotation, distortion=distortion) 1037 864 1038 title = "%s(%s)" % (opts.shape, " ".join(opts.pars)) 865 1039 if opts.dim == 1: … … 867 1041 mesh=opts.mesh, qmax=opts.qmax, samples=opts.samples) 868 1042 else: 869 view = tuple(float(v) for v in opts.view.split(','))870 1043 check_shape_2d(title, shape, fn_xy, view=view, show_points=opts.plot, 871 1044 mesh=opts.mesh, qmax=opts.qmax, samples=opts.samples)
Note: See TracChangeset
for help on using the changeset viewer.