Changeset 9eb3632 in sasmodels for sasmodels/details.py
- Timestamp:
- Jul 23, 2016 12:54:17 AM (8 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:
- 7b7da6b
- Parents:
- 6a0d6aa
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/details.py
r32e3c9b r9eb3632 2 2 3 3 import numpy as np # type: ignore 4 from numpy import pi, cos, sin 5 6 try: 7 np.meshgrid([]) 8 meshgrid = np.meshgrid 9 except ValueError: 10 # CRUFT: np.meshgrid requires multiple vectors 11 def meshgrid(*args): 12 if len(args) > 1: 13 return np.meshgrid(*args) 14 else: 15 return [np.asarray(v) for v in args] 4 16 5 17 try: … … 80 92 print("pd_stride", self.pd_stride) 81 93 94 82 95 def mono_details(model_info): 83 96 call_details = CallDetails(model_info) 84 97 call_details.pd_prod = 1 98 call_details.pd_sum = model_info.parameters.nvalues 99 call_details.pd_par[:] = np.arange(0, model_info.parameters.max_pd) 100 call_details.pd_length[:] = 1 101 call_details.pd_offset[:] = np.arange(0, model_info.parameters.max_pd) 102 call_details.pd_stride[:] = 1 85 103 return call_details 104 86 105 87 106 def poly_details(model_info, weights): … … 90 109 91 110 # Decreasing list of polydispersity lengths 92 pd_length = np.array([len(w) for w in weights]) 111 #print([p.id for p in model_info.parameters.call_parameters]) 112 pd_length = np.array([len(w) for w in weights[2:2+model_info.parameters.npars]]) 93 113 num_active = np.sum(pd_length>1) 94 if num_active > model_info.parameters.max_pd: 114 max_pd = model_info.parameters.max_pd 115 if num_active > max_pd: 95 116 raise ValueError("Too many polydisperse parameters") 96 117 … … 100 121 #print("off:",pd_offset) 101 122 # Note: the reversing view, x[::-1], does not require a copy 102 idx = np.argsort(pd_length)[::-1][:num_active] 103 par_length = np.array([len(w) for w in weights]) 104 pd_stride = np.cumprod(np.hstack((1, par_length[idx]))) 123 idx = np.argsort(pd_length)[::-1][:max_pd] 124 pd_stride = np.cumprod(np.hstack((1, pd_length[idx]))) 105 125 106 126 call_details = CallDetails(model_info) 107 call_details.pd_par[: num_active] = idx - 2 # skip background & scale108 call_details.pd_length[: num_active] = pd_length[idx]109 call_details.pd_offset[: num_active] = pd_offset[idx]110 call_details.pd_stride[: num_active] = pd_stride[:-1]127 call_details.pd_par[:max_pd] = idx 128 call_details.pd_length[:max_pd] = pd_length[idx] 129 call_details.pd_offset[:max_pd] = pd_offset[idx] 130 call_details.pd_stride[:max_pd] = pd_stride[:-1] 111 131 call_details.pd_prod = pd_stride[-1] 112 call_details.pd_sum = np.sum(par_length)132 call_details.pd_sum = sum(len(w) for w in weights) 113 133 call_details.num_active = num_active 114 134 #call_details.show() 115 135 return call_details 136 137 138 def dispersion_mesh(model_info, pars): 139 """ 140 Create a mesh grid of dispersion parameters and weights. 141 142 Returns [p1,p2,...],w where pj is a vector of values for parameter j 143 and w is a vector containing the products for weights for each 144 parameter set in the vector. 145 """ 146 value, weight = zip(*pars) 147 weight = [w if w else [1.] for w in weight] 148 weight = np.vstack([v.flatten() for v in meshgrid(*weight)]) 149 weight = np.prod(weight, axis=0) 150 value = [v.flatten() for v in meshgrid(*value)] 151 lengths = [par.length for par in model_info.parameters.kernel_parameters 152 if par.type == 'volume'] 153 if any(n > 1 for n in lengths): 154 pars = [] 155 offset = 0 156 for n in lengths: 157 pars.append(np.vstack(value[offset:offset+n]) if n > 1 else value[offset]) 158 offset += n 159 value = pars 160 return value, weight 161 162 163 164 def build_details(kernel, pairs): 165 # type: (Kernel, Tuple[List[np.ndarray], List[np.ndarray]]) -> Tuple[CallDetails, np.ndarray, bool] 166 """ 167 Converts (value, weight) pairs into parameters for the kernel call. 168 169 Returns a CallDetails object indicating the polydispersity, a data object 170 containing the different values, and the magnetic flag indicating whether 171 any magnetic magnitudes are non-zero. Magnetic vectors (M0, phi, theta) are 172 converted to rectangular coordinates (mx, my, mz). 173 """ 174 values, weights = zip(*pairs) 175 scalars = [v[0] for v in values] 176 if all(len(w)==1 for w in weights): 177 call_details = mono_details(kernel.info) 178 data = np.array(scalars+scalars+[1]*len(scalars), dtype=kernel.dtype) 179 else: 180 call_details = poly_details(kernel.info, weights) 181 data = np.hstack(scalars+list(values)+list(weights)).astype(kernel.dtype) 182 is_magnetic = convert_magnetism(kernel.info.parameters, data) 183 #call_details.show() 184 return call_details, data, is_magnetic 185 186 def convert_magnetism(parameters, values): 187 """ 188 Convert magnetism in value table from polar to rectangular coordinates. 189 190 Returns True if any magnetism is present. 191 """ 192 mag = values[parameters.nvalues-3*parameters.nmagnetic:parameters.nvalues] 193 mag = mag.reshape(-1, 3) 194 M0 = mag[:,0] 195 if np.any(M0): 196 theta, phi = mag[:,1]*pi/180., mag[:,2]*pi/180. 197 cos_theta = cos(theta) 198 mx = M0*cos_theta*cos(phi) 199 my = M0*sin(theta) 200 mz = -M0*cos_theta*sin(phi) 201 mag[:,0], mag[:,1], mag[:,2] = mx, my, mz 202 return True 203 else: 204 return False
Note: See TracChangeset
for help on using the changeset viewer.