- Timestamp:
- Feb 4, 2018 9:40:01 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:
- aadec17
- Parents:
- 032646d (diff), 72e41a0 (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. - git-author:
- Paul Butler <butlerpd@…> (02/04/18 21:40:01)
- git-committer:
- GitHub <noreply@…> (02/04/18 21:40:01)
- Location:
- sasmodels
- Files:
-
- 4 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/weights.py
r2d81cfe r3d58247 97 97 return x, px 98 98 99 class UniformDispersion(Dispersion): 100 r""" 101 Uniform dispersion, with width $\sigma$. 102 103 .. math:: 104 105 w = 1 106 """ 107 type = "uniform" 108 default = dict(npts=35, width=0, nsigmas=None) 109 def _weights(self, center, sigma, lb, ub): 110 x = np.linspace(center-sigma, center+sigma, self.npts) 111 x = x[(x >= lb) & (x <= ub)] 112 return x, np.ones_like(x) 99 113 100 114 class RectangleDispersion(Dispersion): … … 107 121 """ 108 122 type = "rectangle" 109 default = dict(npts=35, width=0, nsigmas=1.70325) 110 def _weights(self, center, sigma, lb, ub): 111 x = self._linspace(center, sigma, lb, ub) 112 x = x[np.fabs(x-center) <= np.fabs(sigma)*sqrt(3.0)] 113 return x, np.ones_like(x) 114 123 default = dict(npts=35, width=0, nsigmas=1.73205) 124 def _weights(self, center, sigma, lb, ub): 125 x = self._linspace(center, sigma, lb, ub) 126 x = x[np.fabs(x-center) <= np.fabs(sigma)*sqrt(3.0)] 127 return x, np.ones_like(x) 115 128 116 129 class LogNormalDispersion(Dispersion): … … 190 203 return x, px 191 204 205 class BoltzmannDispersion(Dispersion): 206 r""" 207 Boltzmann dispersion, with $\sigma=k T/E$. 208 209 .. math:: 210 211 w = \exp\left( -|x - c|/\sigma\right) 212 """ 213 type = "boltzmann" 214 default = dict(npts=35, width=0, nsigmas=3) 215 def _weights(self, center, sigma, lb, ub): 216 x = self._linspace(center, sigma, lb, ub) 217 px = np.exp(-np.abs(x-center) / np.abs(sigma)) 218 return x, px 192 219 193 220 # dispersion name -> disperser lookup table. … … 196 223 MODELS = OrderedDict((d.type, d) for d in ( 197 224 RectangleDispersion, 225 UniformDispersion, 198 226 ArrayDispersion, 199 227 LogNormalDispersion, 200 228 GaussianDispersion, 201 229 SchulzDispersion, 230 BoltzmannDispersion 202 231 )) 203 232 -
sasmodels/core.py
r2d81cfe r7a516d0 148 148 used with functions in generate to build the docs or extract model info. 149 149 """ 150 if '@' in model_string: 151 parts = model_string.split('@') 152 if len(parts) != 2: 153 raise ValueError("Use P@S to apply a structure factor S to model P") 154 P_info, Q_info = [load_model_info(part) for part in parts] 155 return product.make_product_info(P_info, Q_info) 156 157 product_parts = [] 158 addition_parts = [] 159 160 addition_parts_names = model_string.split('+') 161 if len(addition_parts_names) >= 2: 162 addition_parts = [load_model_info(part) for part in addition_parts_names] 163 elif len(addition_parts_names) == 1: 164 product_parts_names = model_string.split('*') 165 if len(product_parts_names) >= 2: 166 product_parts = [load_model_info(part) for part in product_parts_names] 167 elif len(product_parts_names) == 1: 168 if "custom." in product_parts_names[0]: 169 # Extract ModelName from "custom.ModelName" 170 pattern = "custom.([A-Za-z0-9_-]+)" 171 result = re.match(pattern, product_parts_names[0]) 172 if result is None: 173 raise ValueError("Model name in invalid format: " + product_parts_names[0]) 174 model_name = result.group(1) 175 # Use ModelName to find the path to the custom model file 176 model_path = joinpath(CUSTOM_MODEL_PATH, model_name + ".py") 177 if not os.path.isfile(model_path): 178 raise ValueError("The model file {} doesn't exist".format(model_path)) 179 kernel_module = custom.load_custom_kernel_module(model_path) 180 return modelinfo.make_model_info(kernel_module) 181 # Model is a core model 182 kernel_module = generate.load_kernel_module(product_parts_names[0]) 183 return modelinfo.make_model_info(kernel_module) 184 185 model = None 186 if len(product_parts) > 1: 187 model = mixture.make_mixture_info(product_parts, operation='*') 188 if len(addition_parts) > 1: 189 if model is not None: 190 addition_parts.append(model) 191 model = mixture.make_mixture_info(addition_parts, operation='+') 192 return model 150 if "+" in model_string: 151 parts = [load_model_info(part) 152 for part in model_string.split("+")] 153 return mixture.make_mixture_info(parts, operation='+') 154 elif "*" in model_string: 155 parts = [load_model_info(part) 156 for part in model_string.split("*")] 157 return mixture.make_mixture_info(parts, operation='*') 158 elif "@" in model_string: 159 p_info, q_info = [load_model_info(part) 160 for part in model_string.split("@")] 161 return product.make_product_info(p_info, q_info) 162 # We are now dealing with a pure model 163 elif "custom." in model_string: 164 pattern = "custom.([A-Za-z0-9_-]+)" 165 result = re.match(pattern, model_string) 166 if result is None: 167 raise ValueError("Model name in invalid format: " + model_string) 168 model_name = result.group(1) 169 # Use ModelName to find the path to the custom model file 170 model_path = joinpath(CUSTOM_MODEL_PATH, model_name + ".py") 171 if not os.path.isfile(model_path): 172 raise ValueError("The model file {} doesn't exist".format(model_path)) 173 kernel_module = custom.load_custom_kernel_module(model_path) 174 return modelinfo.make_model_info(kernel_module) 175 kernel_module = generate.load_kernel_module(model_string) 176 return modelinfo.make_model_info(kernel_module) 193 177 194 178 … … 336 320 print("\n".join(list_models(kind))) 337 321 322 def test_load(): 323 # type: () -> None 324 """Check that model load works""" 325 def test_models(fst, snd): 326 """Confirm that two models produce the same parameters""" 327 fst = load_model(fst) 328 snd = load_model(snd) 329 # Remove the upper case characters frin the parameters, since 330 # they lasndel the order of events and we specfically are 331 # changin that aspect 332 fst = [[x for x in p.name if x == x.lower()] for p in fst.info.parameters.kernel_parameters] 333 snd = [[x for x in p.name if x == x.lower()] for p in snd.info.parameters.kernel_parameters] 334 assert sorted(fst) == sorted(snd), "{} != {}".format(fst, snd) 335 336 337 test_models( 338 "cylinder+sphere", 339 "sphere+cylinder") 340 test_models( 341 "cylinder*sphere", 342 "sphere*cylinder") 343 test_models( 344 "cylinder@hardsphere*sphere", 345 "sphere*cylinder@hardsphere") 346 test_models( 347 "barbell+sphere*cylinder@hardsphere", 348 "sphere*cylinder@hardsphere+barbell") 349 test_models( 350 "barbell+cylinder@hardsphere*sphere", 351 "cylinder@hardsphere*sphere+barbell") 352 test_models( 353 "barbell+sphere*cylinder@hardsphere", 354 "barbell+cylinder@hardsphere*sphere") 355 test_models( 356 "sphere*cylinder@hardsphere+barbell", 357 "cylinder@hardsphere*sphere+barbell") 358 test_models( 359 "barbell+sphere*cylinder@hardsphere", 360 "cylinder@hardsphere*sphere+barbell") 361 test_models( 362 "barbell+cylinder@hardsphere*sphere", 363 "sphere*cylinder@hardsphere+barbell") 364 365 #Test the the model produces the parameters that we would expect 366 model = load_model("cylinder@hardsphere*sphere") 367 actual = [p.name for p in model.info.parameters.kernel_parameters] 368 target = ("sld sld_solvent radius length theta phi volfraction" 369 " A_sld A_sld_solvent A_radius").split() 370 assert target == actual, "%s != %s"%(target, actual) 371 338 372 if __name__ == "__main__": 339 373 list_models_main() -
sasmodels/jitter.py
r8cfb486 r0d5a655 1 1 #!/usr/bin/env python 2 2 """ 3 Application to explore the difference between sasview 3.x orientation 4 dispersity and possible replacement algorithms. 3 Jitter Explorer 4 =============== 5 6 Application to explore orientation angle and angular dispersity. 5 7 """ 6 8 from __future__ import division, print_function … … 124 126 def draw_parallelepiped(ax, size, view, jitter, steps=None, alpha=1): 125 127 """Draw a parallelepiped.""" 126 a, b,c = size128 a, b, c = size 127 129 x = a*np.array([ 1,-1, 1,-1, 1,-1, 1,-1]) 128 130 y = b*np.array([ 1, 1,-1,-1, 1, 1,-1,-1]) … … 141 143 x, y, z = transform_xyz(view, jitter, x, y, z) 142 144 ax.plot_trisurf(x, y, triangles=tri, Z=z, color='w', alpha=alpha) 145 146 # Draw pink face on box. 147 # Since I can't control face color, instead draw a thin box situated just 148 # in front of the "a+" face. 149 if 1: 150 x = a*np.array([ 1,-1, 1,-1, 1,-1, 1,-1]) 151 y = b*np.array([ 1, 1,-1,-1, 1, 1,-1,-1]) 152 z = c*np.array([ 1, 1, 1, 1,-1,-1,-1,-1]) 153 x, y, z = transform_xyz(view, jitter, abs(x)*1.05, y, z) 154 ax.plot_trisurf(x, y, triangles=tri, Z=z, color=[1,0.6,0.6], alpha=alpha) 143 155 144 156 draw_labels(ax, view, jitter, [ … … 608 620 Show an interactive orientation and jitter demo. 609 621 610 *model_name* is one of the models available in :func:`select_model`. 622 *model_name* is one of: sphere, cylinder, ellipsoid, parallelepiped, 623 triaxial_ellipsoid, or bcc_paracrystal. 624 625 *size* gives the dimensions (a, b, c) of the shape. 626 627 *dist* is the type of dispersition: gaussian, rectangle, or uniform. 628 629 *mesh* is the number of points in the dispersion mesh. 630 631 *projection* is the map projection to use for the mesh: equirectangular, 632 sinusoidal, guyou, azimuthal_equidistance, or azimuthal_equal_area. 611 633 """ 612 634 # projection number according to 1-order position in list, but -
sasmodels/mixture.py
r2d81cfe recf895e 94 94 # If model is a sum model, each constituent model gets its own scale parameter 95 95 scale_prefix = prefix 96 if prefix == '' and part.operation== '*':96 if prefix == '' and getattr(part, "operation", '') == '*': 97 97 # `part` is a composition product model. Find the prefixes of 98 # it's parameters to form a new prefix for the scale , eg:99 # a model with A*B*C will have ABC_scale98 # it's parameters to form a new prefix for the scale. 99 # For example, a model with A*B*C will have ABC_scale. 100 100 sub_prefixes = [] 101 101 for param in part.parameters.kernel_parameters: … … 233 233 return self 234 234 235 def next(self):235 def __next__(self): 236 236 # type: () -> Tuple[List[Callable], CallDetails, np.ndarray] 237 237 if self.part_num >= len(self.parts): … … 251 251 252 252 return kernel, call_details, values 253 254 # CRUFT: py2 support 255 next = __next__ 253 256 254 257 def _part_details(self, info, par_index): -
sasmodels/modelinfo.py
r108e70e r95498a3 69 69 processed.append(parse_parameter(*p)) 70 70 partable = ParameterTable(processed) 71 partable.check_angles() 71 72 return partable 72 73 … … 421 422 # type: (List[Parameter]) -> None 422 423 self.kernel_parameters = parameters 423 self._check_angles()424 424 self._set_vector_lengths() 425 425 … … 471 471 self.pd_2d = set(p.name for p in self.call_parameters if p.polydisperse) 472 472 473 def _check_angles(self): 473 def check_angles(self): 474 """ 475 Check that orientation angles are theta, phi and possibly psi. 476 """ 474 477 theta = phi = psi = -1 475 478 for k, p in enumerate(self.kernel_parameters): … … 494 497 if psi >= 0 and psi != phi+1: 495 498 raise TypeError("psi must follow phi") 496 #if (psi >= 0 and psi != last_par) or (psi < 0 and phi != last_par):497 #raise TypeError("orientation parameters must appear at the "498 #"end of the parameter table")499 if (psi >= 0 and psi != last_par) or (psi < 0 and phi != last_par): 500 raise TypeError("orientation parameters must appear at the " 501 "end of the parameter table") 499 502 elif theta >= 0 or phi >= 0 or psi >= 0: 500 503 raise TypeError("oriented shapes must have both theta and phi and maybe psi")
Note: See TracChangeset
for help on using the changeset viewer.