Changeset 32c160a in sasmodels
- Timestamp:
- Aug 25, 2014 12:55:08 AM (10 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:
- 13d86bc
- Parents:
- 1f21edf
- Files:
-
- 3 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
CylinderModel.py
rce27e21 r32c160a 5 5 """ 6 6 from sasmodels.sasview_model import make_class 7 CylinderModel = make_class('cylinder_clone','CylinderModel') 7 from sasmodels.models import cylinder_clone as cylinder 8 CylinderModel = make_class(cylinder, dtype='single') -
sasmodels/core.py
rce27e21 r32c160a 8 8 import numpy as np 9 9 10 def load_model(modelname): 11 from os.path import abspath, join as joinpath, dirname 12 from sasmodels import gen 13 modelpath = abspath(joinpath(dirname(gen.__file__), 'models', 14 modelname+'.c')) 15 return gen.make(modelpath) 16 17 18 19 def opencl_model(modelname, dtype="single"): 20 from sasmodels import gpu 21 22 source, info, _ = load_model(modelname) 23 # for debugging, save source to a .cl file, edit it, and reload as model 10 11 def opencl_model(kernel_module, dtype="single"): 12 from sasmodels import gen, gpu 13 14 source, info = gen.make(kernel_module) 15 ## for debugging, save source to a .cl file, edit it, and reload as model 24 16 #open(modelname+'.cl','w').write(source) 25 17 #source = open(modelname+'.cl','r').read() … … 42 34 43 35 44 def dll_model( modelname):36 def dll_model(kernel_module): 45 37 import os 46 from sasmodels import dll 47 48 source, info, _ = load_model(modelname) 38 import tempfile 39 from sasmodels import gen, dll 40 41 source, info = gen.make(kernel_module) 49 42 dllpath = dll_path(info) 50 43 if not os.path.exists(dllpath) \ 51 44 or (os.path.getmtime(dllpath) < os.path.getmtime(info['filename'])): 52 45 # Replace with a proper temp file 53 srcfile = '/tmp/%s.c'%modelname46 srcfile = tempfile.mkstemp(suffix=".c",prefix="sas_"+info['name']) 54 47 open(srcfile, 'w').write(source) 55 48 os.system(COMPILE%(srcfile, dllpath)) 49 ## comment the following to keep the generated c file 50 #os.unlink(srcfile) 56 51 return dll.DllModel(dllpath, info) 57 52 -
sasmodels/gen.py
rce27e21 r32c160a 316 316 return "\n".join(lines) 317 317 318 def make_doc(kernelfile, info, doc): 319 doc = doc%{'parameters': make_partable(info)} 320 return doc 321 322 def make_model(kernelfile, info, source): 318 def _search(search_path, filename): 319 """ 320 Find *filename* in *search_path*. 321 322 Raises ValueError if file does not exist. 323 """ 324 for path in search_path: 325 target = os.path.join(path, filename) 326 if os.path.exists(target): 327 return target 328 raise ValueError("%r not found in %s"%(filename, search_path)) 329 330 def make_model(search_path, info): 323 331 kernel_Iq = make_kernel(info, is_2D=False) 324 332 kernel_Iqxy = make_kernel(info, is_2D=True) 325 path = os.path.dirname(kernelfile) 326 extra = [open("%s/%s"%(path,f)).read() for f in info['include']] 327 kernel = "\n\n".join([KERNEL_HEADER]+extra+[source, kernel_Iq, kernel_Iqxy]) 333 source = [open(_search(search_path, f)).read() for f in info['source']] 334 kernel = "\n\n".join([KERNEL_HEADER]+source+[kernel_Iq, kernel_Iqxy]) 328 335 return kernel 329 330 def parse_file(kernelfile):331 source = open(kernelfile).read()332 333 # select parameters out of the source file334 parts = source.split("PARAMETERS")335 if len(parts) != 3:336 raise ValueError("PARAMETERS block missing from %r"%kernelfile)337 info_source = parts[1].strip()338 try:339 info = relaxed_loads(info_source)340 except:341 print "in json text:"342 print "\n".join("%2d: %s"%(i+1,s)343 for i,s in enumerate(info_source.split('\n')))344 raise345 #raise ValueError("PARAMETERS block could not be parsed from %r"%kernelfile)346 347 # select documentation out of the source file348 parts = source.split("DOCUMENTATION")349 if len(parts) == 3:350 doc = make_doc(kernelfile, info, parts[1].strip())351 elif len(parts) == 1:352 raise ValueError("DOCUMENTATION block is missing from %r"%kernelfile)353 else:354 raise ValueError("DOCUMENTATION block incorrect from %r"%kernelfile)355 356 return source, info, doc357 336 358 337 def categorize_parameters(pars): … … 408 387 return partype 409 388 410 def make(kernel file):389 def make(kernel_module): 411 390 """ 412 391 Build an OpenCL function from the source in *kernelfile*. … … 415 394 will be a JSON definition containing 416 395 """ 396 # TODO: allow Iq and Iqxy to be defined in python 397 from os.path import abspath, dirname, join as joinpath 417 398 #print kernelfile 418 source, info, doc = parse_file(kernelfile) 419 info['filename'] = kernelfile 420 info['parameters'] = COMMON_PARAMETERS + info['parameters'] 399 info = dict( 400 filename = abspath(kernel_module.__file__), 401 name = kernel_module.name, 402 title = kernel_module.title, 403 source = kernel_module.source, 404 description = kernel_module.description, 405 parameters = COMMON_PARAMETERS + kernel_module.parameters, 406 ER = getattr(kernel_module, 'ER', None), 407 VR = getattr(kernel_module, 'VR', None), 408 ) 409 info['limits'] = dict((p[0],p[3]) for p in info['parameters']) 421 410 info['partype'] = categorize_parameters(info['parameters']) 422 info['limits'] = dict((p[0],p[3]) for p in info['parameters']) 423 doc = make_doc(kernelfile, info, doc) 424 model = make_model(kernelfile, info, source) 425 return model, info, doc 411 412 search_path = [ dirname(info['filename']), 413 abspath(joinpath(dirname(__file__),'models')) ] 414 source = make_model(search_path, info) 415 416 return source, info 426 417 427 418 -
sasmodels/models/cylinder_clone.c
r1f21edf r32c160a 1 /* PARAMETERS2 {3 name: "CylinderModel",4 title: "Cylinder with uniform scattering length density",5 include: [ "lib/J1.c", "lib/gauss76.c", "lib/cylkernel.c"],6 parameters: [7 // [ "name", "units", default, [lower, upper], "type", "description" ],8 [ "sldCyl", "1e-6/Ang^2", 4e-6, [-Infinity,Infinity], "",9 "Cylinder scattering length density" ],10 [ "sldSolv", "1e-6/Ang^2", 1e-6, [-Infinity,Infinity], "",11 "Solvent scattering length density" ],12 [ "radius", "Ang", 20, [0, Infinity], "volume",13 "Cylinder radius" ],14 [ "length", "Ang", 400, [0, Infinity], "volume",15 "Cylinder length" ],16 [ "cyl_theta", "degrees", 60, [-Infinity, Infinity], "orientation",17 "In plane angle" ],18 [ "cyl_phi", "degrees", 60, [-Infinity, Infinity], "orientation",19 "Out of plane angle" ],20 ],21 description: "f(q)= 2*(sldCyl - sldSolv)*V*sin(qLcos(alpha/2))/[qLcos(alpha/2)]*J1(qRsin(alpha/2))/[qRsin(alpha)]",22 }23 PARAMETERS END24 25 DOCUMENTATION26 .. _CylinderModel:27 28 CylinderModel29 =============30 31 This model provides the form factor for a right circular cylinder with uniform32 scattering length density. The form factor is normalized by the particle volume.33 34 For information about polarised and magnetic scattering, click here_.35 36 Definition37 ----------38 39 The output of the 2D scattering intensity function for oriented cylinders is40 given by (Guinier, 1955)41 42 .. math::43 44 P(q,\alpha) = \frac{\text{scale}}{V}f^2(q) + \text{bkg}45 46 where47 48 .. math::49 50 f(q) = 2 (\Delta \rho) V51 \frac{\sin (q L/2 \cos \alpha)}{q L/2 \cos \alpha}52 \frac{J_1 (q r \sin \alpha)}{q r \sin \alpha}53 54 and $\alpha$ is the angle between the axis of the cylinder and $\vec q$, $V$55 is the volume of the cylinder, $L$ is the length of the cylinder, $r$ is the56 radius of the cylinder, and $d\rho$ (contrast) is the scattering length density57 difference between the scatterer and the solvent. $J_1$ is the first order58 Bessel function.59 60 To provide easy access to the orientation of the cylinder, we define the61 axis of the cylinder using two angles $\theta$ and $\phi$. Those angles62 are defined in Figure :num:`figure #CylinderModel-orientation`.63 64 .. _CylinderModel-orientation:65 66 .. figure:: img/image061.JPG67 68 Definition of the angles for oriented cylinders.69 70 .. figure:: img/image062.JPG71 72 Examples of the angles for oriented pp against the detector plane.73 74 NB: The 2nd virial coefficient of the cylinder is calculated based on the75 radius and length values, and used as the effective radius for $S(Q)$76 when $P(Q) \cdot S(Q)$ is applied.77 78 The returned value is scaled to units of |cm^-1| and the parameters of79 the CylinderModel are the following:80 81 %(parameters)s82 83 The output of the 1D scattering intensity function for randomly oriented84 cylinders is then given by85 86 .. math::87 88 P(q) = \frac{\text{scale}}{V}89 \int_0^{\pi/2} f^2(q,\alpha) \sin \alpha d\alpha + \text{background}90 91 The *theta* and *phi* parameters are not used for the 1D output. Our92 implementation of the scattering kernel and the 1D scattering intensity93 use the c-library from NIST.94 95 Validation of the CylinderModel96 -------------------------------97 98 Validation of our code was done by comparing the output of the 1D model99 to the output of the software provided by the NIST (Kline, 2006).100 Figure :num:`figure #CylinderModel-compare` shows a comparison of101 the 1D output of our model and the output of the NIST software.102 103 .. _CylinderModel-compare:104 105 .. figure:: img/image065.JPG106 107 Comparison of the SasView scattering intensity for a cylinder with the108 output of the NIST SANS analysis software.109 The parameters were set to: *Scale* = 1.0, *Radius* = 20 |Ang|,110 *Length* = 400 |Ang|, *Contrast* = 3e-6 |Ang^-2|, and111 *Background* = 0.01 |cm^-1|.112 113 In general, averaging over a distribution of orientations is done by114 evaluating the following115 116 .. math::117 118 P(q) = \int_0^{\pi/2} d\phi119 \int_0^\pi p(\theta, \phi) P_0(q,\alpha) \sin \theta d\theta120 121 122 where $p(\theta,\phi)$ is the probability distribution for the orientation123 and $P_0(q,\alpha)$ is the scattering intensity for the fully oriented124 system. Since we have no other software to compare the implementation of125 the intensity for fully oriented cylinders, we can compare the result of126 averaging our 2D output using a uniform distribution $p(\theta, \phi) = 1.0$.127 Figure :num:`figure #CylinderModel-crosscheck` shows the result of128 such a cross-check.129 130 .. _CylinderModel-crosscheck:131 132 .. figure:: img/image066.JPG133 134 Comparison of the intensity for uniformly distributed cylinders135 calculated from our 2D model and the intensity from the NIST SANS136 analysis software.137 The parameters used were: *Scale* = 1.0, *Radius* = 20 |Ang|,138 *Length* = 400 |Ang|, *Contrast* = 3e-6 |Ang^-2|, and139 *Background* = 0.0 |cm^-1|.140 141 DOCUMENTATION END142 */143 1 real form_volume(real radius, real length); 144 2 real Iq(real q, real sld, real solvent_sld, real radius, real length); 145 3 real Iqxy(real qx, real qy, real sld, real solvent_sld, real radius, real length, real theta, real phi); 146 147 4 148 5 real form_volume(real radius, real length) … … 173 30 return REAL(1.0e8) * form * s * s; 174 31 } 175 176 32 177 33 real Iqxy(real qx, real qy, -
sasmodels/sasview_model.py
r1780d59 r32c160a 4 4 import numpy as np 5 5 6 def make_class( name, class_name=None, dtype='single'):6 def make_class(kernel_module, dtype='single'): 7 7 from .core import opencl_model 8 if class_name is None: 9 class_name = "".join(part.capitalize() for part in name.split('_')+['model']) 10 model = opencl_model(name, dtype=dtype) 11 class ConstructedModel(SasviewModel): 12 kernel = model 13 def __init__(self, multfactor=1): 14 SasviewModel.__init__(self, self.kernel) 15 ConstructedModel.__name__ = class_name 8 model = opencl_model(kernel_module, dtype=dtype) 9 def __init__(self, multfactor=1): 10 SasviewModel.__init__(self, self.kernel) 11 attrs = dict(__init__=__init__, kernel=model) 12 ConstructedModel = type(model.info['name'], (SasviewModel,), attrs) 13 #class ConstructedModel(SasviewModel): 14 # kernel = model 15 # def __init__(self, multfactor=1): 16 # SasviewModel.__init__(self, self.kernel) 17 #ConstructedModel.__name__ = model.info['name'] 16 18 return ConstructedModel 17 19 … … 267 269 values, weights = self._dispersion_mesh(vol_pars) 268 270 fv = ER(*values) 271 #print values[0].shape, weights.shape, fv.shape 269 272 return np.sum(weights*fv) / np.sum(weights) 270 273 … … 275 278 :return: the value of the volf ratio 276 279 """ 277 VR = self._model.info.get(' ER', None)280 VR = self._model.info.get('VR', None) 278 281 if VR is None: 279 282 return 1.0 … … 323 326 values = [v.flatten() for v in np.meshgrid(*values)] 324 327 weights = np.vstack([v.flatten() for v in np.meshgrid(*weights)]) 325 weights = np.prod(weights, axis= 1)328 weights = np.prod(weights, axis=0) 326 329 return values, weights 327 330
Note: See TracChangeset
for help on using the changeset viewer.