Changes in / [9890053:59c4c4e] in sasmodels
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
extra/pylint.rc
r49f92c1 r6c8db9e 57 57 58 58 # Disable the message(s) with the given id(s). 59 disable=W0702,W0613 59 disable=W0702,W0613,W0703,W0142 60 60 61 61 [REPORTS] … … 343 343 344 344 # Minimum number of public methods for a class (see R0903). 345 min-public-methods= 2345 min-public-methods=0 346 346 347 347 # Maximum number of public methods for a class (see R0904). -
sasmodels/generate.py
ra5d0d00 r33e91b1 201 201 # Scale and background, which are parameters common to every form factor 202 202 COMMON_PARAMETERS = [ 203 [ "scale", "", 1, [0, np.inf], "", "Source intensity"],204 [ "background", "1/cm", 0, [0, np.inf], "", "Source background"],203 ["scale", "", 1, [0, np.inf], "", "Source intensity"], 204 ["background", "1/cm", 0, [0, np.inf], "", "Source background"], 205 205 ] 206 206 … … 233 233 # description and its parameter table. The remainder of the doc comes 234 234 # from the module docstring. 235 DOC_HEADER =""".. _%(name)s:235 DOC_HEADER = """.. _%(name)s: 236 236 237 237 %(label)s … … 259 259 ] 260 260 column_widths = [max(w, len(h)) 261 for w, h in zip(column_widths, PARTABLE_HEADERS)]261 for w, h in zip(column_widths, PARTABLE_HEADERS)] 262 262 263 263 sep = " ".join("="*w for w in column_widths) 264 264 lines = [ 265 265 sep, 266 " ".join("%-*s" %(w,h) for w,h in zip(column_widths, PARTABLE_HEADERS)),266 " ".join("%-*s" % (w, h) for w, h in zip(column_widths, PARTABLE_HEADERS)), 267 267 sep, 268 268 ] 269 269 for p in pars: 270 270 lines.append(" ".join([ 271 "%-*s" %(column_widths[0],p[0]),272 "%-*s" %(column_widths[1],p[-1]),273 "%-*s" %(column_widths[2],RST_UNITS[p[1]]),274 "%*g" %(column_widths[3],p[2]),271 "%-*s" % (column_widths[0], p[0]), 272 "%-*s" % (column_widths[1], p[-1]), 273 "%-*s" % (column_widths[2], RST_UNITS[p[1]]), 274 "%*g" % (column_widths[3], p[2]), 275 275 ])) 276 276 lines.append(sep) … … 287 287 if exists(target): 288 288 return target 289 raise ValueError("%r not found in %s" %(filename, search_path))289 raise ValueError("%r not found in %s" % (filename, search_path)) 290 290 291 291 def sources(info): … … 293 293 Return a list of the sources file paths for the module. 294 294 """ 295 search_path = [ 296 abspath(joinpath(dirname(__file__),'models'))]295 search_path = [dirname(info['filename']), 296 abspath(joinpath(dirname(__file__), 'models'))] 297 297 return [_search(search_path, f) for f in info['source']] 298 298 … … 333 333 334 334 for p in pars: 335 name, ptype = p[0],p[4]335 name, ptype = p[0], p[4] 336 336 if ptype == 'volume': 337 337 partype['pd-1d'].append(name) … … 346 346 partype['fixed-2d'].append(name) 347 347 else: 348 raise ValueError("unknown parameter type %r" %ptype)348 raise ValueError("unknown parameter type %r" % ptype) 349 349 partype[ptype].append(name) 350 350 … … 356 356 """ 357 357 spaces = " "*depth 358 sep = "\n" +spaces358 sep = "\n" + spaces 359 359 return spaces + sep.join(s.split("\n")) 360 360 … … 366 366 Returns loop opening and loop closing 367 367 """ 368 LOOP_OPEN ="""\368 LOOP_OPEN = """\ 369 369 for (int %(name)s_i=0; %(name)s_i < N%(name)s; %(name)s_i++) { 370 370 const double %(name)s = loops[2*(%(name)s_i%(offset)s)]; … … 376 376 loop_end = [] 377 377 for name in pd_pars: 378 subst = { 'name': name, 'offset': offset}379 loop_head.append(indent(LOOP_OPEN %subst, depth))378 subst = {'name': name, 'offset': offset} 379 loop_head.append(indent(LOOP_OPEN % subst, depth)) 380 380 loop_end.insert(0, (" "*depth) + "}") 381 offset += '+N' +name381 offset += '+N' + name 382 382 depth += 2 383 383 return "\n".join(loop_head), "\n".join(loop_end) 384 384 385 C_KERNEL_TEMPLATE =None385 C_KERNEL_TEMPLATE = None 386 386 def make_model(info): 387 387 """ … … 416 416 417 417 iq_parameters = [p[0] 418 for p in info['parameters'][2:] # skip scale, background419 if p[0] in set(fixed_1d+pd_1d)]418 for p in info['parameters'][2:] # skip scale, background 419 if p[0] in set(fixed_1d + pd_1d)] 420 420 iqxy_parameters = [p[0] 421 for p in info['parameters'][2:] # skip scale, background422 if p[0] in set(fixed_2d+pd_2d)]421 for p in info['parameters'][2:] # skip scale, background 422 if p[0] in set(fixed_2d + pd_2d)] 423 423 volume_parameters = [p[0] 424 for p in info['parameters']425 if p[4]=='volume']424 for p in info['parameters'] 425 if p[4] == 'volume'] 426 426 427 427 # Fill in defintions for volume parameters … … 430 430 ','.join(volume_parameters))) 431 431 defines.append(('VOLUME_WEIGHT_PRODUCT', 432 '*'.join(p +'_w' for p in volume_parameters)))432 '*'.join(p + '_w' for p in volume_parameters))) 433 433 434 434 # Generate form_volume function from body only 435 435 if info['form_volume'] is not None: 436 436 if volume_parameters: 437 vol_par_decl = ', '.join('double ' +p for p in volume_parameters)437 vol_par_decl = ', '.join('double ' + p for p in volume_parameters) 438 438 else: 439 439 vol_par_decl = 'void' … … 445 445 %(body)s 446 446 } 447 """ %{'body':info['form_volume']}447 """ % {'body':info['form_volume']} 448 448 source.append(fn) 449 449 450 450 # Fill in definitions for Iq parameters 451 defines.append(('IQ_KERNEL_NAME', info['name'] +'_Iq'))451 defines.append(('IQ_KERNEL_NAME', info['name'] + '_Iq')) 452 452 defines.append(('IQ_PARAMETERS', ', '.join(iq_parameters))) 453 453 if fixed_1d: 454 454 defines.append(('IQ_FIXED_PARAMETER_DECLARATIONS', 455 ', \\\n '.join('const double %s' %p for p in fixed_1d)))455 ', \\\n '.join('const double %s' % p for p in fixed_1d))) 456 456 if pd_1d: 457 457 defines.append(('IQ_WEIGHT_PRODUCT', 458 '*'.join(p +'_w' for p in pd_1d)))458 '*'.join(p + '_w' for p in pd_1d))) 459 459 defines.append(('IQ_DISPERSION_LENGTH_DECLARATIONS', 460 ', \\\n '.join('const int N%s' %p for p in pd_1d)))460 ', \\\n '.join('const int N%s' % p for p in pd_1d))) 461 461 defines.append(('IQ_DISPERSION_LENGTH_SUM', 462 '+'.join('N' +p for p in pd_1d)))462 '+'.join('N' + p for p in pd_1d))) 463 463 open_loops, close_loops = build_polydispersity_loops(pd_1d) 464 464 defines.append(('IQ_OPEN_LOOPS', 465 open_loops.replace('\n', ' \\\n')))465 open_loops.replace('\n', ' \\\n'))) 466 466 defines.append(('IQ_CLOSE_LOOPS', 467 close_loops.replace('\n', ' \\\n')))467 close_loops.replace('\n', ' \\\n'))) 468 468 if info['Iq'] is not None: 469 469 defines.append(('IQ_PARAMETER_DECLARATIONS', 470 ', '.join('double '+p for p in iq_parameters)))470 ', '.join('double ' + p for p in iq_parameters))) 471 471 fn = """\ 472 472 double Iq(double q, IQ_PARAMETER_DECLARATIONS); … … 474 474 %(body)s 475 475 } 476 """ %{'body':info['Iq']}476 """ % {'body':info['Iq']} 477 477 source.append(fn) 478 478 479 479 # Fill in definitions for Iqxy parameters 480 defines.append(('IQXY_KERNEL_NAME', info['name'] +'_Iqxy'))480 defines.append(('IQXY_KERNEL_NAME', info['name'] + '_Iqxy')) 481 481 defines.append(('IQXY_PARAMETERS', ', '.join(iqxy_parameters))) 482 482 if fixed_2d: 483 483 defines.append(('IQXY_FIXED_PARAMETER_DECLARATIONS', 484 ', \\\n '.join('const double %s' %p for p in fixed_2d)))484 ', \\\n '.join('const double %s' % p for p in fixed_2d))) 485 485 if pd_2d: 486 486 defines.append(('IQXY_WEIGHT_PRODUCT', 487 '*'.join(p +'_w' for p in pd_2d)))487 '*'.join(p + '_w' for p in pd_2d))) 488 488 defines.append(('IQXY_DISPERSION_LENGTH_DECLARATIONS', 489 ', \\\n '.join('const int N%s' %p for p in pd_2d)))489 ', \\\n '.join('const int N%s' % p for p in pd_2d))) 490 490 defines.append(('IQXY_DISPERSION_LENGTH_SUM', 491 '+'.join('N' +p for p in pd_2d)))491 '+'.join('N' + p for p in pd_2d))) 492 492 open_loops, close_loops = build_polydispersity_loops(pd_2d) 493 493 defines.append(('IQXY_OPEN_LOOPS', 494 open_loops.replace('\n', ' \\\n')))494 open_loops.replace('\n', ' \\\n'))) 495 495 defines.append(('IQXY_CLOSE_LOOPS', 496 close_loops.replace('\n', ' \\\n')))496 close_loops.replace('\n', ' \\\n'))) 497 497 if info['Iqxy'] is not None: 498 498 defines.append(('IQXY_PARAMETER_DECLARATIONS', 499 ', '.join('double '+p for p in iqxy_parameters)))499 ', '.join('double ' + p for p in iqxy_parameters))) 500 500 fn = """\ 501 501 double Iqxy(double qx, double qy, IQXY_PARAMETER_DECLARATIONS); … … 503 503 %(body)s 504 504 } 505 """ %{'body':info['Iqxy']}505 """ % {'body':info['Iqxy']} 506 506 source.append(fn) 507 507 … … 513 513 514 514 #for d in defines: print d 515 DEFINES ='\n'.join('#define %s %s'%(k,v) for k,v in defines)516 SOURCES ='\n\n'.join(source)517 return C_KERNEL_TEMPLATE %{515 DEFINES = '\n'.join('#define %s %s' % (k, v) for k, v in defines) 516 SOURCES = '\n\n'.join(source) 517 return C_KERNEL_TEMPLATE % { 518 518 'DEFINES':DEFINES, 519 519 'SOURCES':SOURCES, … … 531 531 #print kernelfile 532 532 info = dict( 533 filename =abspath(kernel_module.__file__),534 name =kernel_module.name,535 title =kernel_module.title,536 description =kernel_module.description,537 parameters =COMMON_PARAMETERS + kernel_module.parameters,538 source =getattr(kernel_module, 'source', []),539 oldname =kernel_module.oldname,540 oldpars =kernel_module.oldpars,533 filename=abspath(kernel_module.__file__), 534 name=kernel_module.name, 535 title=kernel_module.title, 536 description=kernel_module.description, 537 parameters=COMMON_PARAMETERS + kernel_module.parameters, 538 source=getattr(kernel_module, 'source', []), 539 oldname=kernel_module.oldname, 540 oldpars=kernel_module.oldpars, 541 541 ) 542 542 # Fill in attributes which default to None 543 info.update((k, getattr(kernel_module, k, None))543 info.update((k, getattr(kernel_module, k, None)) 544 544 for k in ('ER', 'VR', 'form_volume', 'Iq', 'Iqxy')) 545 545 # Fill in the derived attributes 546 info['limits'] = dict((p[0], p[3]) for p in info['parameters'])546 info['limits'] = dict((p[0], p[3]) for p in info['parameters']) 547 547 info['partype'] = categorize_parameters(info['parameters']) 548 info['defaults'] = dict((p[0], p[2]) for p in info['parameters'])548 info['defaults'] = dict((p[0], p[2]) for p in info['parameters']) 549 549 550 550 # Assume if one part of the kernel is python then all parts are. … … 556 556 Return the documentation for the model. 557 557 """ 558 subst = dict(name=kernel_module.name.replace('_', '-'),558 subst = dict(name=kernel_module.name.replace('_', '-'), 559 559 label=" ".join(kernel_module.name.split('_')).capitalize(), 560 560 title=kernel_module.title, 561 561 parameters=make_partable(kernel_module.parameters), 562 562 docs=kernel_module.__doc__) 563 return DOC_HEADER %subst563 return DOC_HEADER % subst 564 564 565 565 … … 568 568 import datetime 569 569 from .models import cylinder 570 toc = lambda: (datetime.datetime.now()-tic).total_seconds()571 570 tic = datetime.datetime.now() 572 source, info = make(cylinder) 573 print "time:",toc() 571 toc = lambda: (datetime.datetime.now() - tic).total_seconds() 572 make(cylinder) 573 print "time:", toc() 574 574 575 575 def main(): … … 579 579 name = sys.argv[1] 580 580 import sasmodels.models 581 __import__('sasmodels.models.' +name)581 __import__('sasmodels.models.' + name) 582 582 model = getattr(sasmodels.models, name) 583 source, info = make(model); print source584 #print doc(model)583 source, _ = make(model) 584 print source 585 585 586 586 if __name__ == "__main__": -
sasmodels/kernelcl.py
r664c8e7 rc85db69 32 32 context = cl.create_some_context(interactive=False) 33 33 del context 34 except Exception, exc:34 except Exception, exc: 35 35 warnings.warn(str(exc)) 36 36 raise RuntimeError("OpenCL not available") … … 39 39 40 40 from . import generate 41 from .kernelpy import Py Input, PyModel41 from .kernelpy import PyModel 42 42 43 43 F64_DEFS = """\ … … 63 63 """ 64 64 source, info = generate.make(kernel_module) 65 if callable(info.get('Iq', None)):65 if callable(info.get('Iq', None)): 66 66 return PyModel(info) 67 67 ## for debugging, save source to a .cl file, edit it, and reload as model … … 110 110 device.min_data_type_align_size//4. 111 111 """ 112 remainder = vector.size %boundary112 remainder = vector.size % boundary 113 113 if remainder != 0: 114 114 size = vector.size + (boundary - remainder) 115 vector = np.hstack((vector, [extra] *(size-vector.size)))115 vector = np.hstack((vector, [extra] * (size - vector.size))) 116 116 return np.ascontiguousarray(vector, dtype=dtype) 117 117 … … 126 126 """ 127 127 dtype = np.dtype(dtype) 128 if dtype ==generate.F64 and not all(has_double(d) for d in context.devices):128 if dtype == generate.F64 and not all(has_double(d) for d in context.devices): 129 129 raise RuntimeError("Double precision not supported for devices") 130 130 … … 135 135 if context.devices[0].type == cl.device_type.GPU: 136 136 header += "#define USE_SINCOS\n" 137 program = cl.Program(context, header+source).build()137 program = cl.Program(context, header + source).build() 138 138 return program 139 139 … … 173 173 try: 174 174 self.context = cl.create_some_context(interactive=False) 175 except Exception, exc:175 except Exception, exc: 176 176 warnings.warn(str(exc)) 177 177 warnings.warn("pyopencl.create_some_context() failed") … … 230 230 self.__dict__ = state.copy() 231 231 232 def __call__(self, input ):233 if self.dtype != input .dtype:232 def __call__(self, input_value): 233 if self.dtype != input_value.dtype: 234 234 raise TypeError("data and kernel have different types") 235 235 if self.program is None: 236 self.program = environment().compile_program(self.info['name'], self.source, self.dtype)237 kernel_name = generate.kernel_name(self.info, input .is_2D)236 self.program = environment().compile_program(self.info['name'], self.source, self.dtype) 237 kernel_name = generate.kernel_name(self.info, input_value.is_2D) 238 238 kernel = getattr(self.program, kernel_name) 239 return GpuKernel(kernel, self.info, input )239 return GpuKernel(kernel, self.info, input_value) 240 240 241 241 def release(self): … … 285 285 self.q_vectors = [_stretch_input(q, self.dtype, 32) for q in q_vectors] 286 286 self.q_buffers = [ 287 cl.Buffer(env.context, 287 cl.Buffer(env.context, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=q) 288 288 for q in self.q_vectors 289 289 ] … … 320 320 self.res = np.empty(input.nq, input.dtype) 321 321 dim = '2d' if input.is_2D else '1d' 322 self.fixed_pars = info['partype']['fixed-' +dim]323 self.pd_pars = info['partype']['pd-' +dim]322 self.fixed_pars = info['partype']['fixed-' + dim] 323 self.pd_pars = info['partype']['pd-' + dim] 324 324 325 325 # Inputs and outputs for each kernel call … … 327 327 env = environment() 328 328 self.loops_b = [cl.Buffer(env.context, mf.READ_WRITE, 329 2 *MAX_LOOPS*input.dtype.itemsize)329 2 * MAX_LOOPS * input.dtype.itemsize) 330 330 for _ in env.queues] 331 331 self.res_b = [cl.Buffer(env.context, mf.READ_WRITE, 332 input.global_size[0] *input.dtype.itemsize)332 input.global_size[0] * input.dtype.itemsize) 333 333 for _ in env.queues] 334 334 … … 344 344 cutoff = real(cutoff) 345 345 loops_N = [np.uint32(len(p[0])) for p in pd_pars] 346 loops = np.hstack(pd_pars) if pd_pars else np.empty(0, dtype=self.input.dtype)346 loops = np.hstack(pd_pars) if pd_pars else np.empty(0, dtype=self.input.dtype) 347 347 loops = np.ascontiguousarray(loops.T, self.input.dtype).flatten() 348 348 #print "loops",Nloops, loops … … 350 350 #import sys; print >>sys.stderr,"opencl eval",pars 351 351 #print "opencl eval",pars 352 if len(loops) > 2 *MAX_LOOPS:352 if len(loops) > 2 * MAX_LOOPS: 353 353 raise ValueError("too many polydispersity points") 354 354 -
sasmodels/kernelpy.py
rf734e7d rc85db69 1 1 import numpy as np 2 from numpy import pi, sin, cos, sqrt3 4 from .generate import F 32, F642 from numpy import pi, cos 3 4 from .generate import F64 5 5 6 6 class PyModel(object): 7 7 def __init__(self, info): 8 8 self.info = info 9 def __call__(self, input ):10 kernel = self.info['Iqxy'] if input .is_2D else self.info['Iq']11 return PyKernel(kernel, self.info, input )9 def __call__(self, input_value): 10 kernel = self.info['Iqxy'] if input_value.is_2D else self.info['Iq'] 11 return PyKernel(kernel, self.info, input_value) 12 12 def make_input(self, q_vectors): 13 13 return PyInput(q_vectors, dtype=F64) … … 38 38 self.dtype = dtype 39 39 self.is_2D = (len(q_vectors) == 2) 40 self.q_vectors = [np.ascontiguousarray(q, self.dtype) for q in q_vectors]40 self.q_vectors = [np.ascontiguousarray(q, self.dtype) for q in q_vectors] 41 41 self.q_pointers = [q.ctypes.data for q in q_vectors] 42 42 … … 73 73 if dim == '2d': 74 74 def vector_kernel(qx, qy, *args): 75 return np.array([kernel(qxi, qyi,*args) for qxi,qyi in zip(qx,qy)])75 return np.array([kernel(qxi, qyi, *args) for qxi, qyi in zip(qx, qy)]) 76 76 else: 77 77 def vector_kernel(q, *args): 78 return np.array([kernel(qi, *args) for qi in q])78 return np.array([kernel(qi, *args) for qi in q]) 79 79 self.kernel = vector_kernel 80 80 else: 81 81 self.kernel = kernel 82 fixed_pars = info['partype']['fixed-' +dim]83 pd_pars = info['partype']['pd-' +dim]82 fixed_pars = info['partype']['fixed-' + dim] 83 pd_pars = info['partype']['pd-' + dim] 84 84 vol_pars = info['partype']['volume'] 85 85 … … 87 87 pars = [p[0] for p in info['parameters'][2:]] 88 88 offset = len(self.input.q_vectors) 89 self.args = self.input.q_vectors + [None] *len(pars)90 self.fixed_index = np.array([pars.index(p) +offset for p in fixed_pars[2:]])91 self.pd_index = np.array([pars.index(p) +offset for p in pd_pars])92 self.vol_index = np.array([pars.index(p) +offset for p in vol_pars])93 try: self.theta_index = pars.index('theta') +offset89 self.args = self.input.q_vectors + [None] * len(pars) 90 self.fixed_index = np.array([pars.index(p) + offset for p in fixed_pars[2:]]) 91 self.pd_index = np.array([pars.index(p) + offset for p in pd_pars]) 92 self.vol_index = np.array([pars.index(p) + offset for p in vol_pars]) 93 try: self.theta_index = pars.index('theta') + offset 94 94 except ValueError: self.theta_index = -1 95 95 … … 105 105 # First two fixed 106 106 scale, background = fixed[:2] 107 for index, value in zip(self.fixed_index, fixed[2:]):107 for index, value in zip(self.fixed_index, fixed[2:]): 108 108 args[index] = float(value) 109 res = _loops(form, form_volume, cutoff, scale, background, 109 res = _loops(form, form_volume, cutoff, scale, background, args, 110 110 pd, self.pd_index, self.vol_index, self.theta_index) 111 111 … … 185 185 for k in range(stride[-1]): 186 186 # update polydispersity parameter values 187 fast_index = k %stride[0]187 fast_index = k % stride[0] 188 188 if fast_index == 0: # bottom loop complete ... check all other loops 189 189 if weight.size > 0: 190 for i, index, in enumerate(k%stride):190 for i, index, in enumerate(k % stride): 191 191 args[pd_index[i]] = pd[i][0][index] 192 192 weight[i] = pd[i][1][index] … … 202 202 if w > cutoff: 203 203 I = form(*args) 204 positive = (I >=0.0)204 positive = (I >= 0.0) 205 205 206 206 # Note: can precompute spherical correction if theta_index is not the fast index 207 207 # Correction factor for spherical integration p(theta) I(q) sin(theta) dtheta 208 208 #spherical_correction = abs(sin(pi*args[theta_index])) if theta_index>=0 else 1.0 209 spherical_correction = abs(cos(pi *args[theta_index]))*pi/2 if theta_index>=0 else 1.0209 spherical_correction = abs(cos(pi * args[theta_index])) * pi / 2 if theta_index >= 0 else 1.0 210 210 #spherical_correction = 1.0 211 ret += w *I*spherical_correction*positive212 norm += w *positive211 ret += w * I * spherical_correction * positive 212 norm += w * positive 213 213 214 214 # Volume normalization. … … 220 220 vol_args = [args[index] for index in vol_index] 221 221 vol_weight = np.prod(weight[vol_weight_index]) 222 vol += vol_weight *form_volume(*vol_args)*positive223 vol_norm += vol_weight *positive224 225 positive = (vol *vol_norm != 0.0)222 vol += vol_weight * form_volume(*vol_args) * positive 223 vol_norm += vol_weight * positive 224 225 positive = (vol * vol_norm != 0.0) 226 226 ret[positive] *= vol_norm[positive] / vol[positive] 227 result = scale *ret/norm+background227 result = scale * ret / norm + background 228 228 return result -
sasmodels/models/parallelepiped.py
r9890053 r9890053 9 9 ---------- 10 10 11 This model provides the form factor, *P(q)*, for a rectangular parallelepiped 12 (below) where the form factor is normalized by the volume of the 13 parallelepiped. If you need to apply polydispersity, see also the 11 This model provides the form factor, *P(q)*, for a rectangular parallelepiped 12 (below) where the form factor is normalized by the volume of the 13 parallelepiped. If you need to apply polydispersity, see also the 14 14 RectangularPrismModel_. 15 15 … … 20 20 P(Q) = {\text{scale} \over V} F^2(Q) + \text{background} 21 21 22 where the volume *V* = *A B C* and the averaging < > is applied over all 22 where the volume *V* = *A B C* and the averaging < > is applied over all 23 23 orientations for 1D. 24 24 … … 27 27 *Figure. Parallelepiped with the corresponding Definition of sides. 28 28 29 The edge of the solid must satisfy the condition that** *A* < *B* < *C*. 30 Then, assuming *a* = *A* / *B* < 1, *b* = *B* / *B* = 1, and 29 The edge of the solid must satisfy the condition that** *A* < *B* < *C*. 30 Then, assuming *a* = *A* / *B* < 1, *b* = *B* / *B* = 1, and 31 31 *c* = *C* / *B* > 1, the form factor is 32 32 33 33 .. math:: 34 34 35 P(q) = \frac{\textstyle{scale}}{V}\int_0^1 \phi(\mu \sqrt{1-\sigma^2},a) 35 P(q) = \frac{\textstyle{scale}}{V}\int_0^1 \phi(\mu \sqrt{1-\sigma^2},a) 36 36 [S(\mu c \sigma/2)]^2 d\sigma 37 37 … … 40 40 .. math:: 41 41 42 \phi(\mu,a) = \int_0^1 \{S[\frac{\mu}{2}\cos(\frac{\pi}{2}u)] 42 \phi(\mu,a) = \int_0^1 \{S[\frac{\mu}{2}\cos(\frac{\pi}{2}u)] 43 43 S[\frac{\mu a}{2}\sin(\frac{\pi}{2}u)]\}^2 du 44 44 45 45 S(x) = \frac{\sin x}{x} 46 46 47 47 \mu = qB 48 48 … … 53 53 \Delta\rho = \rho_{\textstyle p} - \rho_{\textstyle solvent} 54 54 55 The scattering intensity per unit volume is returned in units of |cm^-1|; 55 The scattering intensity per unit volume is returned in units of |cm^-1|; 56 56 ie, *I(q)* = |phi| *P(q)*\ . 57 57 58 NB: The 2nd virial coefficient of the parallelpiped is calculated based on 59 the averaged effective radius (= sqrt(*short_a* \* *short_b* / |pi|)) and 58 NB: The 2nd virial coefficient of the parallelpiped is calculated based on 59 the averaged effective radius (= sqrt(*short_a* \* *short_b* / |pi|)) and 60 60 length(= *long_c*) values, and used as the effective radius for 61 61 *S(Q)* when *P(Q)* \* *S(Q)* is applied. 62 62 63 To provide easy access to the orientation of the parallelepiped, we define 63 To provide easy access to the orientation of the parallelepiped, we define 64 64 three angles |theta|, |phi| and |bigpsi|. The definition of |theta| and |phi| 65 is the same as for the cylinder model (see also figures below). 66 The angle |bigpsi| is the rotational angle around the *long_c* axis against 67 the *q* plane. For example, |bigpsi| = 0 when the *short_b* axis is parallel 65 is the same as for the cylinder model (see also figures below). 66 The angle |bigpsi| is the rotational angle around the *long_c* axis against 67 the *q* plane. For example, |bigpsi| = 0 when the *short_b* axis is parallel 68 68 to the *x*-axis of the detector. 69 69 … … 83 83 ---------- 84 84 85 Validation of the code was done by comparing the output of the 1D calculation 86 to the angular average of the output of a 2D calculation over all possible 87 angles. The Figure below shows the comparison where the solid dot refers to 88 averaged 2D while the line represents the result of the 1D calculation (for 89 the averaging, 76, 180, 76 points are taken for the angles of |theta|, |phi|, 85 Validation of the code was done by comparing the output of the 1D calculation 86 to the angular average of the output of a 2D calculation over all possible 87 angles. The Figure below shows the comparison where the solid dot refers to 88 averaged 2D while the line represents the result of the 1D calculation (for 89 the averaging, 76, 180, 76 points are taken for the angles of |theta|, |phi|, 90 90 and |psi| respectively). 91 91 … … 96 96 *Figure. Comparison between 1D and averaged 2D.* 97 97 98 This model reimplements the form factor calculations implemented in a c-library 98 This model reimplements the form factor calculations implemented in a c-library 99 99 provided by the NIST Center for Neutron Research (Kline, 2006). 100 100 … … 108 108 P(q)= scale/V*integral from 0 to 1 of ... 109 109 phi(mu*sqrt(1-sigma^2),a) * S(mu*c*sigma/2)^2 * dsigma 110 110 111 111 phi(mu,a) = integral from 0 to 1 of .. 112 112 (S((mu/2)*cos(pi*u/2))*S((mu*a/2)*sin(pi*u/2)))^2 * du 113 113 S(x) = sin(x)/x 114 114 mu = q*B 115 115 """ 116 116 category = "shape:parallelpiped" 117 117 118 118 parameters = [ 119 # [ "name", "units", default, [lower, upper], "type",120 # "description" ],121 [ "sld", "1e-6/Ang^2", 4, [-inf,inf], "",122 "Parallelepiped scattering length density"],123 [ "solvent_sld", "1e-6/Ang^2", 1, [-inf,inf], "",124 "Solvent scattering length density"],125 [ "a_side", "Ang",35, [0, inf], "volume",126 "Shorter side of the parallelepiped"],127 [ "b_side", "Ang",75, [0, inf], "volume",128 "Second side of the parallelepiped"],129 [ "c_side", "Ang",400, [0, inf], "volume",130 "Larger side of the parallelepiped"],131 [ 132 "In plane angle"],133 [ 134 "Out of plane angle"],135 [ 136 "Rotation angle around its own c axis against q plane"],119 # [ "name", "units", default, [lower, upper], "type", 120 # "description" ], 121 ["sld", "1e-6/Ang^2", 4, [-inf, inf], "", 122 "Parallelepiped scattering length density"], 123 ["solvent_sld", "1e-6/Ang^2", 1, [-inf, inf], "", 124 "Solvent scattering length density"], 125 ["a_side", "Ang", 35, [0, inf], "volume", 126 "Shorter side of the parallelepiped"], 127 ["b_side", "Ang", 75, [0, inf], "volume", 128 "Second side of the parallelepiped"], 129 ["c_side", "Ang", 400, [0, inf], "volume", 130 "Larger side of the parallelepiped"], 131 ["theta", "degrees", 60, [-inf, inf], "orientation", 132 "In plane angle"], 133 ["phi", "degrees", 60, [-inf, inf], "orientation", 134 "Out of plane angle"], 135 ["psi", "degrees", 60, [-inf, inf], "orientation", 136 "Rotation angle around its own c axis against q plane"], 137 137 ] 138 138 139 source = [ "lib/J1.c", "lib/gauss76.c", "parallelepiped.c"]139 source = ["lib/J1.c", "lib/gauss76.c", "parallelepiped.c"] 140 140 141 141 def ER(a_side, b_side, c_side): … … 148 148 b = 0.5 * c_side 149 149 t1 = a * a * b 150 t2 = 1.0 + (b /a)*(1.0+a/b/2.0)*(1.0+pi*a/b/2.0)150 t2 = 1.0 + (b / a) * (1.0 + a / b / 2.0) * (1.0 + pi * a / b / 2.0) 151 151 ddd = 3.0 * t1 * t2 152 152 153 return 0.5 * (ddd) **(1./3.)153 return 0.5 * (ddd) ** (1. / 3.) 154 154 155 155 # parameters for demo … … 169 169 # For testing against the old sasview models, include the converted parameter 170 170 # names and the target sasview model name. 171 oldname ='ParallelepipedModel'172 oldpars =dict(theta='parallel_theta', phi='parallel_phi', psi='parallel_psi',173 a_side='short_a', b_side='short_b', c_side='long_c',174 sld='sldPipe', solvent_sld='sldSolv')171 oldname = 'ParallelepipedModel' 172 oldpars = dict(theta='parallel_theta', phi='parallel_phi', psi='parallel_psi', 173 a_side='short_a', b_side='short_b', c_side='long_c', 174 sld='sldPipe', solvent_sld='sldSolv') 175 175 -
sasmodels/sasview_model.py
r0a82216 rde0c4ba 26 26 try: 27 27 from .kernelcl import load_model 28 except ImportError, exc:28 except ImportError, exc: 29 29 warnings.warn(str(exc)) 30 30 warnings.warn("using ctypes instead") … … 41 41 will produce a class with a name compatible with SasView 42 42 """ 43 model = 43 model = load_model(kernel_module, dtype=dtype) 44 44 def __init__(self, multfactor=1): 45 45 SasviewModel.__init__(self, model) 46 46 attrs = dict(__init__=__init__) 47 ConstructedModel = type(model.info[namestyle], 47 ConstructedModel = type(model.info[namestyle], (SasviewModel,), attrs) 48 48 return ConstructedModel 49 49 … … 69 69 self.dispersion = dict() 70 70 partype = model.info['partype'] 71 for name, units,default,limits,ptype,description in model.info['parameters']:71 for name, units, default, limits, ptype, description in model.info['parameters']: 72 72 self.params[name] = default 73 self.details[name] = [units] +limits73 self.details[name] = [units] + limits 74 74 75 75 for name in partype['pd-2d']: … … 83 83 self.orientation_params = ( 84 84 partype['orientation'] 85 + [n +'.width' for n in partype['orientation']]85 + [n + '.width' for n in partype['orientation']] 86 86 + partype['magnetic']) 87 87 self.magnetic_params = partype['magnetic'] 88 self.fixed = [n +'.width' for n in partype['pd-2d']]88 self.fixed = [n + '.width' for n in partype['pd-2d']] 89 89 self.non_fittable = [] 90 90 91 91 ## independent parameter name and unit [string] 92 self.input_name = model.info.get("input_name", "Q")93 self.input_unit = model.info.get("input_unit", "A^{-1}")94 self.output_name = model.info.get("output_name", "Intensity")95 self.output_unit = model.info.get("output_unit", "cm^{-1}")92 self.input_name = model.info.get("input_name", "Q") 93 self.input_unit = model.info.get("input_unit", "A^{-1}") 94 self.output_name = model.info.get("output_name", "Intensity") 95 self.output_unit = model.info.get("output_unit", "cm^{-1}") 96 96 97 97 ## _persistency_dict is used by sas.perspectives.fitting.basepage … … 139 139 # Look for dispersion parameters 140 140 toks = name.split('.') 141 if len(toks) ==2:141 if len(toks) == 2: 142 142 for item in self.dispersion.keys(): 143 if item.lower() ==toks[0].lower():143 if item.lower() == toks[0].lower(): 144 144 for par in self.dispersion[item]: 145 145 if par.lower() == toks[1].lower(): … … 149 149 # Look for standard parameter 150 150 for item in self.params.keys(): 151 if item.lower() ==name.lower():151 if item.lower() == name.lower(): 152 152 self.params[item] = value 153 153 return … … 164 164 # Look for dispersion parameters 165 165 toks = name.split('.') 166 if len(toks) ==2:166 if len(toks) == 2: 167 167 for item in self.dispersion.keys(): 168 if item.lower() ==toks[0].lower():168 if item.lower() == toks[0].lower(): 169 169 for par in self.dispersion[item]: 170 170 if par.lower() == toks[1].lower(): … … 173 173 # Look for standard parameter 174 174 for item in self.params.keys(): 175 if item.lower() ==name.lower():175 if item.lower() == name.lower(): 176 176 return self.params[item] 177 177 … … 182 182 Return a list of all available parameters for the model 183 183 """ 184 list = self.params.keys()184 param_list = self.params.keys() 185 185 # WARNING: Extending the list with the dispersion parameters 186 list.extend(self.getDispParamList())187 return list186 param_list.extend(self.getDispParamList()) 187 return param_list 188 188 189 189 def getDispParamList(self): … … 192 192 """ 193 193 # TODO: fix test so that parameter order doesn't matter 194 ret = ['%s.%s' %(d.lower(), p)194 ret = ['%s.%s' % (d.lower(), p) 195 195 for d in self._model.info['partype']['pd-2d'] 196 196 for p in ('npts', 'nsigmas', 'width')] … … 212 212 **DEPRECATED**: use calculate_Iq instead 213 213 """ 214 if isinstance(x, (list, tuple)):214 if isinstance(x, (list, tuple)): 215 215 q, phi = x 216 216 return self.calculate_Iq([q * math.cos(phi)], … … 230 230 **DEPRECATED**: use calculate_Iq instead 231 231 """ 232 if isinstance(x, (list, tuple)):233 return self.calculate_Iq([float(x[0])], [float(x[1])])[0]232 if isinstance(x, (list, tuple)): 233 return self.calculate_Iq([float(x[0])], [float(x[1])])[0] 234 234 else: 235 235 return self.calculate_Iq([float(x)])[0] … … 265 265 :param qdist: ndarray of scalar q-values or list [qx,qy] where qx,qy are 1D ndarrays 266 266 """ 267 if isinstance(qdist, (list, tuple)):267 if isinstance(qdist, (list, tuple)): 268 268 # Check whether we have a list of ndarrays [qx,qy] 269 269 qx, qy = qdist 270 270 partype = self._model.info['partype'] 271 271 if not partype['orientation'] and not partype['magnetic']: 272 return self.calculate_Iq(np.sqrt(qx **2+qy**2))272 return self.calculate_Iq(np.sqrt(qx ** 2 + qy ** 2)) 273 273 else: 274 274 return self.calculate_Iq(qx, qy) … … 279 279 280 280 else: 281 raise TypeError("evalDistribution expects q or [qx, qy], not %r" %type(qdist))281 raise TypeError("evalDistribution expects q or [qx, qy], not %r" % type(qdist)) 282 282 283 283 def calculate_Iq(self, *args): … … 313 313 fv = ER(*values) 314 314 #print values[0].shape, weights.shape, fv.shape 315 return np.sum(weights *fv) / np.sum(weights)315 return np.sum(weights * fv) / np.sum(weights) 316 316 317 317 def calculate_VR(self): … … 327 327 vol_pars = self._model.info['partype']['volume'] 328 328 values, weights = self._dispersion_mesh(vol_pars) 329 whole, part = VR(*values)330 return np.sum(weights *part)/np.sum(weights*whole)329 whole, part = VR(*values) 330 return np.sum(weights * part) / np.sum(weights * whole) 331 331 332 332 def set_dispersion(self, parameter, dispersion): … … 373 373 374 374 def _get_weights(self, par): 375 """ 376 Return dispersion weights 377 :param par parameter name 378 """ 375 379 from . import weights 376 380 … … 378 382 limits = self._model.info['limits'] 379 383 dis = self.dispersion[par] 380 v, w = weights.get_weights(384 v, w = weights.get_weights( 381 385 dis['type'], dis['npts'], dis['width'], dis['nsigmas'], 382 386 self.params[par], limits[par], par in relative) 383 return v, w/w.max()384 387 return v, w / w.max() 388
Note: See TracChangeset
for help on using the changeset viewer.