Changeset c9e31e2 in sasmodels for sasmodels/kernelpy.py
- Timestamp:
- Mar 6, 2015 10:54:22 AM (9 years ago)
- Branches:
- master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- 9f6f2f8, ab87a12
- Parents:
- d60b433 (diff), 3c56da87 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/kernelpy.py
r6edb74a r3c56da87 1 1 import numpy as np 2 from numpy import pi, sin, cos, sqrt 3 4 from .generate import F32, F64 2 from numpy import pi, cos 3 4 from .generate import F64 5 6 class PyModel(object): 7 def __init__(self, info): 8 self.info = info 9 10 def __call__(self, q_input): 11 kernel = self.info['Iqxy'] if q_input.is_2D else self.info['Iq'] 12 return PyKernel(kernel, self.info, q_input) 13 14 # pylint: disable=no-self-use 15 def make_input(self, q_vectors): 16 return PyInput(q_vectors, dtype=F64) 17 18 def release(self): 19 pass 5 20 6 21 class PyInput(object): … … 27 42 self.dtype = dtype 28 43 self.is_2D = (len(q_vectors) == 2) 29 self.q_vectors = [np.ascontiguousarray(q, self.dtype) for q in q_vectors]44 self.q_vectors = [np.ascontiguousarray(q, self.dtype) for q in q_vectors] 30 45 self.q_pointers = [q.ctypes.data for q in q_vectors] 31 46 … … 41 56 *info* is the module information 42 57 43 * input* is the DllInput q vectors at which the kernel should be58 *q_input* is the DllInput q vectors at which the kernel should be 44 59 evaluated. 45 60 … … 52 67 Call :meth:`release` when done with the kernel instance. 53 68 """ 54 def __init__(self, kernel, info, input):69 def __init__(self, kernel, info, q_input): 55 70 self.info = info 56 self. input =input57 self.res = np.empty( input.nq,input.dtype)58 dim = '2d' if input.is_2D else '1d'71 self.q_input = q_input 72 self.res = np.empty(q_input.nq, q_input.dtype) 73 dim = '2d' if q_input.is_2D else '1d' 59 74 # Loop over q unless user promises that the kernel is vectorized by 60 75 # taggining it with vectorized=True … … 62 77 if dim == '2d': 63 78 def vector_kernel(qx, qy, *args): 64 return np.array([kernel(qxi,qyi,*args) for qxi,qyi in zip(qx,qy)]) 79 return np.array([kernel(qxi, qyi, *args) 80 for qxi, qyi in zip(qx, qy)]) 65 81 else: 66 82 def vector_kernel(q, *args): 67 return np.array([kernel(qi,*args) for qi in q]) 83 return np.array([kernel(qi, *args) 84 for qi in q]) 68 85 self.kernel = vector_kernel 69 86 else: 70 87 self.kernel = kernel 71 fixed_pars = info['partype']['fixed-' +dim]72 pd_pars = info['partype']['pd-' +dim]88 fixed_pars = info['partype']['fixed-' + dim] 89 pd_pars = info['partype']['pd-' + dim] 73 90 vol_pars = info['partype']['volume'] 74 91 75 92 # First two fixed pars are scale and background 76 93 pars = [p[0] for p in info['parameters'][2:]] 77 offset = len(self.input.q_vectors) 78 self.args = self.input.q_vectors + [None]*len(pars) 79 self.fixed_index = np.array([pars.index(p)+offset for p in fixed_pars[2:] ]) 80 self.pd_index = np.array([pars.index(p)+offset for p in pd_pars]) 81 self.vol_index = np.array([pars.index(p)+offset for p in vol_pars]) 82 try: self.theta_index = pars.index('theta')+offset 94 offset = len(self.q_input.q_vectors) 95 self.args = self.q_input.q_vectors + [None] * len(pars) 96 self.fixed_index = np.array([pars.index(p) + offset 97 for p in fixed_pars[2:]]) 98 self.pd_index = np.array([pars.index(p) + offset 99 for p in pd_pars]) 100 self.vol_index = np.array([pars.index(p) + offset 101 for p in vol_pars]) 102 try: self.theta_index = pars.index('theta') + offset 83 103 except ValueError: self.theta_index = -1 84 104 … … 94 114 # First two fixed 95 115 scale, background = fixed[:2] 96 for index, value in zip(self.fixed_index, fixed[2:]):116 for index, value in zip(self.fixed_index, fixed[2:]): 97 117 args[index] = float(value) 98 res = _loops(form, form_volume, cutoff, scale, background, 118 res = _loops(form, form_volume, cutoff, scale, background, args, 99 119 pd, self.pd_index, self.vol_index, self.theta_index) 100 120 … … 102 122 103 123 def release(self): 104 self. input = None124 self.q_input = None 105 125 106 126 def _loops(form, form_volume, cutoff, scale, background, … … 134 154 """ 135 155 136 ########################################################## 137 # #138 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #139 # !! !! #140 # !! KEEP THIS CODE CONSISTENT WITH GENERATE.PY!! #141 # !! !! #142 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #143 # #144 ########################################################## 156 ################################################################ 157 # # 158 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # 159 # !! !! # 160 # !! KEEP THIS CODE CONSISTENT WITH KERNEL_TEMPLATE.C !! # 161 # !! !! # 162 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # 163 # # 164 ################################################################ 145 165 146 166 weight = np.empty(len(pd), 'd') … … 164 184 stride = np.array([1]) 165 185 vol_weight_index = slice(None, None) 186 # keep lint happy 187 fast_value = [None] 188 fast_weight = [None] 166 189 167 190 ret = np.zeros_like(args[0]) … … 171 194 for k in range(stride[-1]): 172 195 # update polydispersity parameter values 173 fast_index = k %stride[0]196 fast_index = k % stride[0] 174 197 if fast_index == 0: # bottom loop complete ... check all other loops 175 198 if weight.size > 0: 176 for i, index, in enumerate(k%stride):199 for i, index, in enumerate(k % stride): 177 200 args[pd_index[i]] = pd[i][0][index] 178 201 weight[i] = pd[i][1][index] … … 180 203 args[pd_index[0]] = fast_value[fast_index] 181 204 weight[0] = fast_weight[fast_index] 182 # This computes the weight, and if it is sufficient, calls the scattering183 # function and adds it to the total. If there is a volume normalization,184 # it will also be added here.205 # This computes the weight, and if it is sufficient, calls the 206 # scattering function and adds it to the total. If there is a volume 207 # normalization, it will also be added here. 185 208 # Note: make sure this is consistent with the code in PY_LOOP_BODY!! 186 209 # Note: can precompute w1*w2*...*wn … … 188 211 if w > cutoff: 189 212 I = form(*args) 190 positive = (I>=0.0) 191 192 # Note: can precompute spherical correction if theta_index is not the fast index 193 # Correction factor for spherical integration p(theta) I(q) sin(theta) dtheta 194 #spherical_correction = abs(sin(pi*args[theta_index])) if theta_index>=0 else 1.0 195 #spherical_correction = abs(cos(pi*args[theta_index]))*pi/2 if theta_index>=0 else 1.0 196 spherical_correction = 1.0 197 ret += w*I*spherical_correction*positive 198 norm += w*positive 213 positive = (I >= 0.0) 214 215 # Note: can precompute spherical correction if theta_index is not 216 # the fast index. Correction factor for spherical integration 217 #spherical_correction = abs(cos(pi*args[phi_index])) if phi_index>=0 else 1.0 218 spherical_correction = (abs(cos(pi * args[theta_index])) * pi / 2 219 if theta_index >= 0 else 1.0) 220 #spherical_correction = 1.0 221 ret += w * I * spherical_correction * positive 222 norm += w * positive 199 223 200 224 # Volume normalization. 201 # If there are "volume" polydispersity parameters, then these will be used202 # to call the form_volume function from the user supplied kernel, and accumulate203 # a normalized weight.204 # Note: can precompute volume norm if the fast index is not a volume index225 # If there are "volume" polydispersity parameters, then these 226 # will be used to call the form_volume function from the user 227 # supplied kernel, and accumulate a normalized weight. 228 # Note: can precompute volume norm if fast index is not a volume 205 229 if form_volume: 206 230 vol_args = [args[index] for index in vol_index] 207 231 vol_weight = np.prod(weight[vol_weight_index]) 208 vol += vol_weight *form_volume(*vol_args)*positive209 vol_norm += vol_weight *positive210 211 positive = (vol *vol_norm != 0.0)232 vol += vol_weight * form_volume(*vol_args) * positive 233 vol_norm += vol_weight * positive 234 235 positive = (vol * vol_norm != 0.0) 212 236 ret[positive] *= vol_norm[positive] / vol[positive] 213 result = scale *ret/norm+background237 result = scale * ret / norm + background 214 238 return result
Note: See TracChangeset
for help on using the changeset viewer.