Changes in / [168052c:ed82794] in sasmodels
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
extra/pylint.rc
r37a7252 rd4666ca 7 7 # pygtk.require(). 8 8 #init-hook='import os, sys; sys.path.extend([os.getcwd(),os.path.join(os.getcwd(),"extra")])' 9 init-hook='import sys; sys.path.append('extra') 9 10 10 11 # Profiled execution. … … 64 65 star-args, 65 66 unbalanced-tuple-unpacking, 67 locally-enabled, 66 68 locally-disabled, 67 69 … … 107 109 good-names=_, 108 110 input, 109 i,j,k,n,x,y,z,111 h,i,j,k,n,w,x,y,z, 110 112 q,qx,qy,qz, 111 113 dt,dx,dy,dz,id, 112 Iq,dIq,Qx,Qy,Qz, 114 Iq,dIq,Qx,Qy,Qz,Iqxy, 113 115 p, 114 116 ER, call_ER, VR, call_VR, 117 Rmax, SElength, 115 118 116 119 # Bad variable names which should always be refused, separated by a comma … … 335 338 336 339 # Maximum number of arguments for function / method 337 max-args= 5340 max-args=15 338 341 339 342 # Argument names that match this expression will be ignored. Default to name … … 342 345 343 346 # Maximum number of locals for function / method body 344 max-locals= 15347 max-locals=25 345 348 346 349 # Maximum number of return / yield for function / method body -
sasmodels/bumps_model.py
r37a7252 r190fc2b 12 12 """ 13 13 14 import warnings 15 16 import numpy as np 17 18 from .data import plot_theory 19 from .direct_model import DataMixin 20 14 21 __all__ = [ 15 22 "Model", "Experiment", 16 23 ] 17 18 import warnings19 20 import numpy as np21 22 from .data import plot_theory23 from .direct_model import DataMixin24 24 25 25 # CRUFT: old style bumps wrapper which doesn't separate data and model -
sasmodels/compare.py
rd15a908 r190fc2b 28 28 29 29 from __future__ import print_function 30 31 import sys 32 import math 33 from os.path import basename, dirname, join as joinpath 34 import glob 35 import datetime 36 import traceback 37 38 import numpy as np 39 40 from . import core 41 from . import kerneldll 42 from . import generate 43 from .data import plot_theory, empty_data1D, empty_data2D 44 from .direct_model import DirectModel 45 from .convert import revert_model, constrain_new_to_old 30 46 31 47 USAGE = """ … … 80 96 + USAGE) 81 97 82 83 84 import sys 85 import math 86 from os.path import basename, dirname, join as joinpath 87 import glob 88 import datetime 89 import traceback 90 91 import numpy as np 92 98 kerneldll.ALLOW_SINGLE_PRECISION_DLLS = True 99 100 # List of available models 93 101 ROOT = dirname(__file__) 94 sys.path.insert(0, ROOT) # Make sure sasmodels is first on the path95 96 97 from . import core98 from . import kerneldll99 from . import generate100 from .data import plot_theory, empty_data1D, empty_data2D101 from .direct_model import DirectModel102 from .convert import revert_model, constrain_new_to_old103 kerneldll.ALLOW_SINGLE_PRECISION_DLLS = True104 105 # List of available models106 102 MODELS = [basename(f)[:-3] 107 103 for f in sorted(glob.glob(joinpath(ROOT, "models", "[a-zA-Z]*.py")))] … … 117 113 return dt.total_seconds() 118 114 115 116 class push_seed(object): 117 """ 118 Set the seed value for the random number generator. 119 120 When used in a with statement, the random number generator state is 121 restored after the with statement is complete. 122 123 :Parameters: 124 125 *seed* : int or array_like, optional 126 Seed for RandomState 127 128 :Example: 129 130 Seed can be used directly to set the seed:: 131 132 >>> from numpy.random import randint 133 >>> push_seed(24) 134 <...push_seed object at...> 135 >>> print(randint(0,1000000,3)) 136 [242082 899 211136] 137 138 Seed can also be used in a with statement, which sets the random 139 number generator state for the enclosed computations and restores 140 it to the previous state on completion:: 141 142 >>> with push_seed(24): 143 ... print(randint(0,1000000,3)) 144 [242082 899 211136] 145 146 Using nested contexts, we can demonstrate that state is indeed 147 restored after the block completes:: 148 149 >>> with push_seed(24): 150 ... print(randint(0,1000000)) 151 ... with push_seed(24): 152 ... print(randint(0,1000000,3)) 153 ... print(randint(0,1000000)) 154 242082 155 [242082 899 211136] 156 899 157 158 The restore step is protected against exceptions in the block:: 159 160 >>> with push_seed(24): 161 ... print(randint(0,1000000)) 162 ... try: 163 ... with push_seed(24): 164 ... print(randint(0,1000000,3)) 165 ... raise Exception() 166 ... except: 167 ... print("Exception raised") 168 ... print(randint(0,1000000)) 169 242082 170 [242082 899 211136] 171 Exception raised 172 899 173 """ 174 def __init__(self, seed=None): 175 self._state = np.random.get_state() 176 np.random.seed(seed) 177 178 def __enter__(self): 179 return None 180 181 def __exit__(self, *args): 182 np.random.set_state(self._state) 119 183 120 184 def tic(): … … 179 243 return [0, (2*v if v > 0 else 1)] 180 244 245 181 246 def _randomize_one(p, v): 182 247 """ … … 188 253 return np.random.uniform(*parameter_range(p, v)) 189 254 255 190 256 def randomize_pars(pars, seed=None): 191 257 """ … … 197 263 :func:`constrain_pars` needs to be called afterward.. 198 264 """ 199 np.random.seed(seed)200 # Note: the sort guarantees order `of calls to random number generator201 pars = dict((p, _randomize_one(p, v))202 for p, v in sorted(pars.items()))265 with push_seed(seed): 266 # Note: the sort guarantees order `of calls to random number generator 267 pars = dict((p, _randomize_one(p, v)) 268 for p, v in sorted(pars.items())) 203 269 return pars 204 270 … … 463 529 if Nbase > 0: 464 530 if Ncomp > 0: plt.subplot(131) 465 plot_theory(data, base_value, view=view, plot_data=False, limits=limits)531 plot_theory(data, base_value, view=view, use_data=False, limits=limits) 466 532 plt.title("%s t=%.1f ms"%(base.engine, base_time)) 467 533 #cbar_title = "log I" 468 534 if Ncomp > 0: 469 535 if Nbase > 0: plt.subplot(132) 470 plot_theory(data, comp_value, view=view, plot_data=False, limits=limits)536 plot_theory(data, comp_value, view=view, use_data=False, limits=limits) 471 537 plt.title("%s t=%.1f ms"%(comp.engine, comp_time)) 472 538 #cbar_title = "log I" … … 478 544 err, errstr, errview = abs(relerr), "rel err", "log" 479 545 #err,errstr = base/comp,"ratio" 480 plot_theory(data, None, resid=err, view=errview, plot_data=False)546 plot_theory(data, None, resid=err, view=errview, use_data=False) 481 547 plt.title("max %s = %.3g"%(errstr, max(abs(err)))) 482 548 #cbar_title = errstr if errview=="linear" else "log "+errstr -
sasmodels/compare_many.py
rd15a908 r4f2478e 261 261 262 262 if __name__ == "__main__": 263 #from .compare import push_seed 264 #with push_seed(1): main() 263 265 main() -
sasmodels/core.py
rd15a908 r190fc2b 2 2 Core model handling routines. 3 3 """ 4 __all__ = [5 "list_models", "load_model_definition", "precompile_dll",6 "load_model", "make_kernel", "call_kernel", "call_ER", "call_VR",7 ]8 4 9 5 from os.path import basename, dirname, join as joinpath … … 24 20 HAVE_OPENCL = False 25 21 22 __all__ = [ 23 "list_models", "load_model_definition", "precompile_dll", 24 "load_model", "make_kernel", "call_kernel", "call_ER", "call_VR", 25 ] 26 26 27 27 def list_models(): -
sasmodels/data.py
rd15a908 r69ec80f 90 90 self.x, self.y, self.dx, self.dy = x, y, dx, dy 91 91 self.dxl = None 92 self.filename = None 93 self.qmin = x.min() if x is not None else np.NaN 94 self.qmax = x.max() if x is not None else np.NaN 95 self.mask = np.isnan(y) if y is not None else None 96 self._xaxis, self._xunit = "x", "" 97 self._yaxis, self._yunit = "y", "" 92 98 93 99 def xaxis(self, label, unit): … … 108 114 109 115 class Data2D(object): 110 def __init__(self): 116 def __init__(self, x=None, y=None, z=None, dx=None, dy=None, dz=None): 117 self.qx_data, self.dqx_data = x, dx 118 self.qy_data, self.dqy_data = y, dy 119 self.data, self.err_data = z, dz 120 self.mask = ~np.isnan(z) if z is not None else None 121 self.q_data = np.sqrt(x**2 + y**2) 122 self.qmin = 1e-16 123 self.qmax = np.inf 111 124 self.detector = [] 112 125 self.source = Source() 126 self.Q_unit = "1/A" 127 self.I_unit = "1/cm" 128 self.xaxis("Q_x", "A^{-1}") 129 self.yaxis("Q_y", "A^{-1}") 130 self.zaxis("Intensity", r"\text{cm}^{-1}") 131 self._xaxis, self._xunit = "x", "" 132 self._yaxis, self._yunit = "y", "" 133 self._zaxis, self._zunit = "z", "" 134 self.x_bins, self.y_bins = None, None 113 135 114 136 def xaxis(self, label, unit): … … 139 161 140 162 class Detector(object): 163 """ 164 Detector attributes. 165 """ 166 def __init__(self, pixel_size=(None, None), distance=None): 167 self.pixel_size = Vector(*pixel_size) 168 self.distance = distance 169 170 class Source(object): 171 """ 172 Beam attributes. 173 """ 141 174 def __init__(self): 142 self.pixel_size = Vector() 143 144 class Source(object): 145 pass 175 self.wavelength = np.NaN 176 self.wavelength_unit = "A" 146 177 147 178 … … 158 189 data = Data1D(q, Iq, dx=resolution * q, dy=dIq) 159 190 data.filename = "fake data" 160 data.qmin, data.qmax = q.min(), q.max()161 data.mask = np.zeros(len(q), dtype='bool')162 191 return data 163 192 … … 173 202 if qy is None: 174 203 qy = qx 204 # 5% dQ/Q resolution 175 205 Qx, Qy = np.meshgrid(qx, qy) 176 206 Qx, Qy = Qx.flatten(), Qy.flatten() 177 207 Iq = 100 * np.ones_like(Qx) 178 208 dIq = np.sqrt(Iq) 179 mask = np.ones(len(Iq), dtype='bool')180 181 data = Data2D()182 data.filename = "fake data"183 data.qx_data = Qx184 data.qy_data = Qy185 data.data = Iq186 data.err_data = dIq187 data.mask = mask188 data.qmin = 1e-16189 data.qmax = np.inf190 191 # 5% dQ/Q resolution192 209 if resolution != 0: 193 210 # https://www.ncnr.nist.gov/staff/hammouda/distance_learning/chapter_15.pdf … … 197 214 # radial (which instead it should be inverse). 198 215 Q = np.sqrt(Qx**2 + Qy**2) 199 d ata.dqx_data= resolution * Q200 d ata.dqy_data= resolution * Q216 dqx = resolution * Q 217 dqy = resolution * Q 201 218 else: 202 data.dqx_data = data.dqy_data = None 203 204 detector = Detector() 205 detector.pixel_size.x = 5 # mm 206 detector.pixel_size.y = 5 # mm 207 detector.distance = 4 # m 208 data.detector.append(detector) 219 dqx = dqy = None 220 221 data = Data2D(x=Qx, y=Qy, z=Iq, dx=dqx, dy=dqy, dz=dIq) 209 222 data.x_bins = qx 210 223 data.y_bins = qy 224 data.filename = "fake data" 225 226 # pixel_size in mm, distance in m 227 detector = Detector(pixel_size=(5, 5), distance=4) 228 data.detector.append(detector) 211 229 data.source.wavelength = 5 # angstroms 212 230 data.source.wavelength_unit = "A" 213 data.Q_unit = "1/A"214 data.I_unit = "1/cm"215 data.q_data = np.sqrt(Qx ** 2 + Qy ** 2)216 data.xaxis("Q_x", "A^{-1}")217 data.yaxis("Q_y", "A^{-1}")218 data.zaxis("Intensity", r"\text{cm}^{-1}")219 231 return data 220 232 … … 228 240 # do not repeat. 229 241 if hasattr(data, 'lam'): 230 _plot_result_sesans(data, None, None, plot_data=True, limits=limits)242 _plot_result_sesans(data, None, None, use_data=True, limits=limits) 231 243 elif hasattr(data, 'qx_data'): 232 _plot_result2D(data, None, None, view, plot_data=True, limits=limits)244 _plot_result2D(data, None, None, view, use_data=True, limits=limits) 233 245 else: 234 _plot_result1D(data, None, None, view, plot_data=True, limits=limits)246 _plot_result1D(data, None, None, view, use_data=True, limits=limits) 235 247 236 248 237 249 def plot_theory(data, theory, resid=None, view='log', 238 plot_data=True, limits=None):250 use_data=True, limits=None): 239 251 if hasattr(data, 'lam'): 240 _plot_result_sesans(data, theory, resid, plot_data=True, limits=limits)252 _plot_result_sesans(data, theory, resid, use_data=True, limits=limits) 241 253 elif hasattr(data, 'qx_data'): 242 _plot_result2D(data, theory, resid, view, plot_data, limits=limits)254 _plot_result2D(data, theory, resid, view, use_data, limits=limits) 243 255 else: 244 _plot_result1D(data, theory, resid, view, plot_data, limits=limits)256 _plot_result1D(data, theory, resid, view, use_data, limits=limits) 245 257 246 258 … … 251 263 except: 252 264 traceback.print_exc() 253 pass254 265 255 266 return wrapper … … 257 268 258 269 @protect 259 def _plot_result1D(data, theory, resid, view, plot_data, limits=None):270 def _plot_result1D(data, theory, resid, view, use_data, limits=None): 260 271 """ 261 272 Plot the data and residuals for 1D data. … … 264 275 from numpy.ma import masked_array, masked 265 276 266 plot_theory = theory is not None267 plot_resid = residis not None268 269 if data.y is None:270 plot_data = False 277 use_data = use_data and data.y is not None 278 use_theory = theory is not None 279 use_resid = resid is not None 280 num_plots = (use_data or use_theory) + use_resid 281 271 282 scale = data.x**4 if view == 'q4' else 1.0 272 283 273 if plot_data or plot_theory: 274 if plot_resid: 275 plt.subplot(121) 276 284 if use_data or use_theory: 277 285 #print(vmin, vmax) 278 286 all_positive = True 279 287 some_present = False 280 if plot_data:288 if use_data: 281 289 mdata = masked_array(data.y, data.mask.copy()) 282 290 mdata[~np.isfinite(mdata)] = masked … … 288 296 289 297 290 if plot_theory:298 if use_theory: 291 299 mtheory = masked_array(theory, data.mask.copy()) 292 300 mtheory[~np.isfinite(mtheory)] = masked … … 299 307 if limits is not None: 300 308 plt.ylim(*limits) 309 310 if num_plots > 1: 311 plt.subplot(1, num_plots, 1) 301 312 plt.xscale('linear' if not some_present else view) 302 313 plt.yscale('linear' … … 306 317 plt.ylabel('$I(q)$') 307 318 308 if plot_resid: 309 if plot_data or plot_theory: 310 plt.subplot(122) 311 319 if use_resid: 312 320 mresid = masked_array(resid, data.mask.copy()) 313 321 mresid[~np.isfinite(mresid)] = masked 314 322 some_present = (mresid.count() > 0) 323 324 if num_plots > 1: 325 plt.subplot(1, num_plots, (use_data or use_theory) + 1) 315 326 plt.plot(data.x/10, mresid, '-') 316 327 plt.xlabel("$q$/nm$^{-1}$") … … 320 331 321 332 @protect 322 def _plot_result_sesans(data, theory, resid, plot_data, limits=None):333 def _plot_result_sesans(data, theory, resid, use_data, limits=None): 323 334 import matplotlib.pyplot as plt 324 if data.y is None:325 plot_data = False326 plot_theory = theoryis not None327 plot_resid = resid is not None328 329 if plot_data or plot_theory:330 if plot_resid:331 plt.subplot(1 21)332 if plot_data:335 use_data = use_data and data.y is not None 336 use_theory = theory is not None 337 use_resid = resid is not None 338 num_plots = (use_data or use_theory) + use_resid 339 340 if use_data or use_theory: 341 if num_plots > 1: 342 plt.subplot(1, num_plots, 1) 343 if use_data: 333 344 plt.errorbar(data.x, data.y, yerr=data.dy) 334 345 if theory is not None: … … 340 351 341 352 if resid is not None: 342 if plot_data or plot_theory: 343 plt.subplot(122) 344 353 if num_plots > 1: 354 plt.subplot(1, num_plots, (use_data or use_theory) + 1) 345 355 plt.plot(data.x, resid, 'x') 346 356 plt.xlabel('spin echo length (nm)') … … 349 359 350 360 @protect 351 def _plot_result2D(data, theory, resid, view, plot_data, limits=None):361 def _plot_result2D(data, theory, resid, view, use_data, limits=None): 352 362 """ 353 363 Plot the data and residuals for 2D data. 354 364 """ 355 365 import matplotlib.pyplot as plt 356 if data.data is None:357 plot_data = False358 plot_theory = theoryis not None359 plot_resid = resid is not None366 use_data = use_data and data.data is not None 367 use_theory = theory is not None 368 use_resid = resid is not None 369 num_plots = use_data + use_theory + use_resid 360 370 361 371 # Put theory and data on a common colormap scale 362 if limits is None: 363 vmin, vmax = np.inf, -np.inf 364 if plot_data: 365 target = data.data[~data.mask] 366 datamin = target[target>0].min() if view == 'log' else target.min() 367 datamax = target.max() 368 vmin = min(vmin, datamin) 369 vmax = max(vmax, datamax) 370 if plot_theory: 371 theorymin = theory[theory>0].min() if view=='log' else theory.min() 372 theorymax = theory.max() 373 vmin = min(vmin, theorymin) 374 vmax = max(vmax, theorymax) 375 else: 372 vmin, vmax = np.inf, -np.inf 373 if use_data: 374 target = data.data[~data.mask] 375 datamin = target[target > 0].min() if view == 'log' else target.min() 376 datamax = target.max() 377 vmin = min(vmin, datamin) 378 vmax = max(vmax, datamax) 379 if use_theory: 380 theorymin = theory[theory > 0].min() if view == 'log' else theory.min() 381 theorymax = theory.max() 382 vmin = min(vmin, theorymin) 383 vmax = max(vmax, theorymax) 384 385 # Override data limits from the caller 386 if limits is not None: 376 387 vmin, vmax = limits 377 388 378 if plot_data: 379 if plot_theory and plot_resid: 380 plt.subplot(131) 381 elif plot_theory or plot_resid: 382 plt.subplot(121) 389 # Plot data 390 if use_data: 391 if num_plots > 1: 392 plt.subplot(1, num_plots, 1) 383 393 _plot_2d_signal(data, target, view=view, vmin=vmin, vmax=vmax) 384 394 plt.title('data') … … 386 396 h.set_label('$I(q)$') 387 397 388 if plot_theory: 389 if plot_data and plot_resid: 390 plt.subplot(132) 391 elif plot_data: 392 plt.subplot(122) 393 elif plot_resid: 394 plt.subplot(121) 398 # plot theory 399 if use_theory: 400 if num_plots > 1: 401 plt.subplot(1, num_plots, use_data+1) 395 402 _plot_2d_signal(data, theory, view=view, vmin=vmin, vmax=vmax) 396 403 plt.title('theory') … … 400 407 else '$I(q)$') 401 408 402 #if plot_data or plot_theory: 403 # plt.colorbar() 404 405 if plot_resid: 406 if plot_data and plot_theory: 407 plt.subplot(133) 408 elif plot_data or plot_theory: 409 plt.subplot(122) 409 # plot resid 410 if use_resid: 411 if num_plots > 1: 412 plt.subplot(1, num_plots, use_data+use_theory+1) 410 413 _plot_2d_signal(data, resid, view='linear') 411 414 plt.title('residuals') -
sasmodels/generate.py
re66c9f9 r190fc2b 197 197 # TODO: identify model files which have changed since loading and reload them. 198 198 199 __all__ = ["make", "doc", "sources", "convert_type"]200 201 199 import sys 202 200 from os.path import abspath, dirname, join as joinpath, exists, basename, \ … … 206 204 207 205 import numpy as np 206 207 __all__ = ["make", "doc", "sources", "convert_type"] 208 208 209 C_KERNEL_TEMPLATE_PATH = joinpath(dirname(__file__), 'kernel_template.c') 209 210 … … 216 217 F128 = None 217 218 218 219 219 # Scale and background, which are parameters common to every form factor 220 220 COMMON_PARAMETERS = [ … … 222 222 ["background", "1/cm", 0, [0, np.inf], "", "Source background"], 223 223 ] 224 225 224 226 225 # Conversion from units defined in the parameter table for each model … … 266 265 267 266 def format_units(units): 267 """ 268 Convert units into ReStructured Text format. 269 """ 268 270 return "string" if isinstance(units, list) else RST_UNITS.get(units, units) 269 271 … … 335 337 """ 336 338 Convert code from double precision to the desired type. 339 340 Floating point constants are tagged with 'f' for single precision or 'L' 341 for long double precision. 337 342 """ 338 343 if dtype == F16: … … 350 355 351 356 def _convert_type(source, type_name, constant_flag): 357 """ 358 Replace 'double' with *type_name* in *source*, tagging floating point 359 constants with *constant_flag*. 360 """ 352 361 # Convert double keyword to float/long double/half. 353 362 # Accept an 'n' # parameter for vector # values, where n is 2, 4, 8 or 16. … … 625 634 %re.escape(string.punctuation)) 626 635 def _convert_section_titles_to_boldface(lines): 636 """ 637 Do the actual work of identifying and converting section headings. 638 """ 627 639 prior = None 628 640 for line in lines: … … 642 654 yield prior 643 655 644 def convert_section_titles_to_boldface(string): 645 return "\n".join(_convert_section_titles_to_boldface(string.split('\n'))) 656 def convert_section_titles_to_boldface(s): 657 """ 658 Use explicit bold-face rather than section headings so that the table of 659 contents is not polluted with section names from the model documentation. 660 661 Sections are identified as the title line followed by a line of punctuation 662 at least as long as the title line. 663 """ 664 return "\n".join(_convert_section_titles_to_boldface(s.split('\n'))) 646 665 647 666 def doc(kernel_module): … … 666 685 667 686 def demo_time(): 687 """ 688 Show how long it takes to process a model. 689 """ 668 690 from .models import cylinder 669 691 import datetime … … 674 696 675 697 def main(): 698 """ 699 Program which prints the source produced by the model. 700 """ 676 701 if len(sys.argv) <= 1: 677 702 print("usage: python -m sasmodels.generate modelname") -
sasmodels/models/lamellarCailleHG.py
rd18f8a8 rd4666ca 92 92 93 93 parameters = [ 94 95 96 [ "tail_length", "Ang",10, [0, inf], "volume",97 "Tail thickness"],98 [ "head_length", "Ang",2, [0, inf], "volume",99 "head thickness"],100 [ "Nlayers", "",30, [0, inf], "",101 "Number of layers"],102 [ "spacing", "Ang", 40., [0.0,inf], "volume",103 "d-spacing of Caille S(Q)"],104 [ "Caille_parameter", "", 0.001, [0.0,0.8], "",105 "Caille parameter"],106 [ "sld", "1e-6/Ang^2", 0.4, [-inf,inf], "",107 "Tail scattering length density"],108 [ "head_sld", "1e-6/Ang^2", 2.0, [-inf,inf], "",109 "Head scattering length density"],110 [ "solvent_sld", "1e-6/Ang^2", 6, [-inf,inf], "",111 "Solvent scattering length density"],94 # [ "name", "units", default, [lower, upper], "type", 95 # "description" ], 96 ["tail_length", "Ang", 10, [0, inf], "volume", 97 "Tail thickness"], 98 ["head_length", "Ang", 2, [0, inf], "volume", 99 "head thickness"], 100 ["Nlayers", "", 30, [0, inf], "", 101 "Number of layers"], 102 ["spacing", "Ang", 40., [0.0, inf], "volume", 103 "d-spacing of Caille S(Q)"], 104 ["Caille_parameter", "", 0.001, [0.0, 0.8], "", 105 "Caille parameter"], 106 ["sld", "1e-6/Ang^2", 0.4, [-inf, inf], "", 107 "Tail scattering length density"], 108 ["head_sld", "1e-6/Ang^2", 2.0, [-inf, inf], "", 109 "Head scattering length density"], 110 ["solvent_sld", "1e-6/Ang^2", 6, [-inf, inf], "", 111 "Solvent scattering length density"], 112 112 ] 113 113 114 source = [ 114 source = ["lamellarCailleHG_kernel.c"] 115 115 116 116 # No volume normalization despite having a volume parameter … … 128 128 129 129 demo = dict( 130 scale=1, background=0, 131 Nlayers=20, 132 spacing=200., Caille_parameter=0.05, 133 tail_length=15,head_length=10, 134 #sld=-1, head_sld=4.0, solvent_sld=6.0, 135 sld=-1, head_sld=4.1, solvent_sld=6.0, 136 tail_length_pd= 0.1, tail_length_pd_n=20, 137 head_length_pd= 0.05, head_length_pd_n=30, 138 spacing_pd= 0.2, spacing_pd_n=40 139 ) 130 scale=1, background=0, 131 Nlayers=20, spacing=200., Caille_parameter=0.05, 132 tail_length=15, head_length=10, 133 #sld=-1, head_sld=4.0, solvent_sld=6.0, 134 sld=-1, head_sld=4.1, solvent_sld=6.0, 135 tail_length_pd=0.1, tail_length_pd_n=20, 136 head_length_pd=0.05, head_length_pd_n=30, 137 spacing_pd=0.2, spacing_pd_n=40, 138 ) 140 139 141 140 oldname = 'LamellarPSHGModel' 142 oldpars = dict(tail_length='deltaT',head_length='deltaH',Nlayers='n_plates',Caille_parameter='caille', sld='sld_tail', head_sld='sld_head',solvent_sld='sld_solvent') 141 oldpars = dict( 142 tail_length='deltaT', head_length='deltaH', Nlayers='n_plates', 143 Caille_parameter='caille', sld='sld_tail', head_sld='sld_head', 144 solvent_sld='sld_solvent') -
sasmodels/models/lib/sph_j1c.c
r9c461c7 ra3e78c3 1 1 /** 2 * Spherical Bessel function j1(x)/x2 * Spherical Bessel function 3*j1(x)/x 3 3 * 4 4 * Used for low q to avoid cancellation error. … … 8 8 * requires the first 3 terms. Double precision requires the 4th term. 9 9 * The fifth term is not needed, and is commented out. 10 * Taylor expansion: 11 * 1.0 + q2*(-3./30. + q2*(3./840.))+ q2*(-3./45360. + q2*(3./3991680.)))) 12 * Expression returned from Herbie (herbie.uwpise.org/demo): 13 * const double t = ((1. + 3.*q2*q2/5600.) - q2/20.); 14 * return t*t; 10 15 */ 11 16 … … 18 23 SINCOS(q, sin_q, cos_q); 19 24 20 const double bessel = (q < 1.e-1) ?21 1.0 + q2*(-3./30. + q2*(3./840. + q2*(-3./45360.))) // + q2*(3./3991680.)))25 const double bessel = (q < 0.384038453352533) 26 ? (1.0 + q2*(-3./30. + q2*(3./840.))) 22 27 : 3.0*(sin_q/q - cos_q)/q2; 23 28 24 29 return bessel; 30 31 /* 32 // Code to test various expressions 33 if (sizeof(q2) > 4) { 34 return 3.0*(sin_q/q - cos_q)/q2; 35 } else if (q < 0.384038453352533) { 36 //const double t = ((1. + 3.*q2*q2/5600.) - q2/20.); return t*t; 37 return 1.0 + q2*q2*(3./840.) - q2*(3./30.); 38 //return 1.0 + q2*(-3./30. + q2*(3./840.)); 39 //return 1.0 + q2*(-3./30. + q2*(3./840. + q2*(-3./45360.))); 40 //return 1.0 + q2*(-3./30. + q2*(3./840. + q2*(-3./45360. + q2*(3./3991680.)))); 41 } else { 42 return 3.0*(sin_q/q - cos_q)/q2; 43 } 44 */ 25 45 } -
sasmodels/models/pearl_necklace.py
rcf404cb r841753c 1 1 r""" 2 This model provides the form factor for a pearl necklace composed of two 3 elements: *N* pearls (homogeneous spheres of radius *R*) freely jointed by *M* 2 This model provides the form factor for a pearl necklace composed of two 3 elements: *N* pearls (homogeneous spheres of radius *R*) freely jointed by *M* 4 4 rods (like strings - with a total mass *Mw* = *M* \* *m*\ :sub:`r` + *N* \* *m*\ 5 :sub:`s`, and the string segment length (or edge separation) *l* 5 :sub:`s`, and the string segment length (or edge separation) *l* 6 6 (= *A* - 2\ *R*)). *A* is the center-to-center pearl separation distance. 7 7 … … 13 13 ---------- 14 14 15 The output of the scattering intensity function for the PearlNecklaceModel is 15 The output of the scattering intensity function for the PearlNecklaceModel is 16 16 given by (Schweins, 2004) 17 17 … … 37 37 \beta(q) &= \frac{\int_{qR}^{q(A-R)}\frac{sin(t)}{t}dt}{ql} 38 38 39 where the mass *m*\ :sub:`i` is (SLD\ :sub:`i` - SLD\ :sub:`solvent`) \* 39 where the mass *m*\ :sub:`i` is (SLD\ :sub:`i` - SLD\ :sub:`solvent`) \* 40 40 (volume of the *N* pearls/rods). *V* is the total volume of the necklace. 41 41 42 The 2D scattering intensity is the same as $P(q)$ above, regardless of the 42 The 2D scattering intensity is the same as $P(q)$ above, regardless of the 43 43 orientation of the *q* vector. 44 44 … … 54 54 REFERENCE 55 55 56 R Schweins and K Huber, *Particle Scattering Factor of Pearl Necklace Chains*, 56 R Schweins and K Huber, *Particle Scattering Factor of Pearl Necklace Chains*, 57 57 *Macromol. Symp.* 211 (2004) 25-42 2004 58 58 """ … … 79 79 80 80 # ["name", "units", default, [lower, upper], "type","description"], 81 parameters = [["radius", "Angstrom", 80.0, [0, inf], "volume", 81 parameters = [["radius", "Angstrom", 80.0, [0, inf], "volume", 82 82 "Mean radius of the chained spheres"], 83 ["edge_separation", "Angstrom", 350.0, [0, inf], "volume", 83 ["edge_separation", "Angstrom", 350.0, [0, inf], "volume", 84 84 "Mean separation of chained particles"], 85 ["string_thickness", "Angstrom", 2.5, [0, inf], "volume", 85 ["string_thickness", "Angstrom", 2.5, [0, inf], "volume", 86 86 "Thickness of the chain linkage"], 87 ["number_of_pearls", "none", 3, [0, inf], "volume", 87 ["number_of_pearls", "none", 3, [0, inf], "volume", 88 88 "Mean number of pearls in each necklace"], 89 ["sld", "Angstrom^2", 1.0, [-inf, inf], "", 89 ["sld", "Angstrom^2", 1.0, [-inf, inf], "", 90 90 "Scattering length density of the chained spheres"], 91 ["string_sld", "Angstrom^2", 1.0, [-inf, inf], "", 91 ["string_sld", "Angstrom^2", 1.0, [-inf, inf], "", 92 92 "Scattering length density of the chain linkage"], 93 ["solvent_sld", "Angstrom^2", 6.3, [-inf, inf], "", 93 ["solvent_sld", "Angstrom^2", 6.3, [-inf, inf], "", 94 94 "Scattering length density of the solvent"], 95 95 ] 96 96 97 97 source = ["lib/Si.c", "pearl_necklace.c"] … … 110 110 # names and the target sasview model name. 111 111 oldname = 'PearlNecklaceModel' 112 oldpars = dict(scale='scale', background='background',radius='radius',112 oldpars = dict(scale='scale', background='background', radius='radius', 113 113 number_of_pearls='num_pearls', solvent_sld='sld_solv', 114 114 string_thickness='thick_string', sld='sld_pearl', -
sasmodels/models/power_law.py
reb69cce r841753c 12 12 I(q) = \text{scale} \cdot q^{-\text{power}} + \text{background} 13 13 14 Note the minus sign in front of the exponent. The exponent *power* 14 Note the minus sign in front of the exponent. The exponent *power* 15 15 should therefore be entered as a **positive** number for fitting. 16 16 17 Also note that unlike many other models, *scale* in this model 18 is NOT explicitly related to a volume fraction. Be careful if 17 Also note that unlike many other models, *scale* in this model 18 is NOT explicitly related to a volume fraction. Be careful if 19 19 combining this model with other models. 20 20 … … 31 31 from numpy import inf, sqrt 32 32 33 name = 33 name = "power_law" 34 34 title = "Simple power law with a flat background" 35 35 36 description = """ \37 38 39 40 36 description = """ 37 Evaluates the function 38 I(q) = scale * q^(-power) + background 39 NB: enter power as a positive number! 40 """ 41 41 category = "shape-independent" 42 42 … … 45 45 46 46 # NB: Scale and Background are implicit parameters on every model 47 def Iq(q,power): 47 def Iq(q, power): 48 # pylint: disable=missing-docstring 48 49 inten = (q**-power) 49 50 return inten … … 51 52 52 53 def Iqxy(qx, qy, *args): 54 # pylint: disable=missing-docstring 53 55 return Iq(sqrt(qx ** 2 + qy ** 2), *args) 54 56 Iqxy.vectorized = True # Iqxy accepts an array of qx, qy values … … 64 66 65 67 tests = [ 66 [ {'scale': 1.0, 'power': 4.0, 'background' : 0.0}, [0.0106939, 0.469418], [7.64644e+07, 20.5949]] 67 ] 68 [{'scale': 1.0, 'power': 4.0, 'background' : 0.0}, 69 [0.0106939, 0.469418], [7.64644e+07, 20.5949]], 70 ] -
sasmodels/resolution.py
rfdc538a r190fc2b 5 5 """ 6 6 from __future__ import division 7 8 from scipy.special import erf 9 from numpy import sqrt, log, log10 10 import numpy as np 7 11 8 12 __all__ = ["Resolution", "Perfect1D", "Pinhole1D", "Slit1D", … … 11 15 "interpolate", "linear_extrapolation", "geometric_extrapolation", 12 16 ] 13 14 from scipy.special import erf15 from numpy import sqrt, log, log1016 import numpy as np17 17 18 18 MINIMUM_RESOLUTION = 1e-8 -
sasmodels/resolution2d.py
r9404dd3 r841753c 2 2 #This software was developed by the University of Tennessee as part of the 3 3 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 4 #project funded by the US National Science Foundation. 4 #project funded by the US National Science Foundation. 5 5 #See the license text in license.txt 6 6 """ … … 19 19 ## Defaults 20 20 NR = {'xhigh':10, 'high':5, 'med':5, 'low':3} 21 NPHI = {'xhigh':20, 'high':12, 'med':6, 'low':4}21 NPHI = {'xhigh':20, 'high':12, 'med':6, 'low':4} 22 22 23 23 class Pinhole2D(Resolution): … … 25 25 Gaussian Q smearing class for SAS 2d data 26 26 """ 27 27 28 28 def __init__(self, data=None, index=None, 29 29 nsigma=NSIGMA, accuracy='Low', coords='polar'): 30 30 """ 31 31 Assumption: equally spaced bins in dq_r, dq_phi space. 32 32 33 33 :param data: 2d data used to set the smearing parameters 34 34 :param index: 1d array with len(data) to define the range … … 42 42 ## number of bins in r axis for over-sampling 43 43 self.nr = NR[accuracy.lower()] 44 ## number of bins in phi axis for over-sampling 44 ## number of bins in phi axis for over-sampling 45 45 self.nphi = NPHI[accuracy.lower()] 46 46 ## maximum nsigmas 47 self.nsigma = nsigma47 self.nsigma = nsigma 48 48 self.coords = coords 49 49 self._init_data(data, index) … … 85 85 def _calc_res(self): 86 86 """ 87 Over sampling of r_nbins times phi_nbins, calculate Gaussian weights, 87 Over sampling of r_nbins times phi_nbins, calculate Gaussian weights, 88 88 then find smeared intensity 89 """ 89 """ 90 90 nr, nphi = self.nr, self.nphi 91 91 # Total number of bins = # of bins … … 143 143 if self.coords == 'polar': 144 144 q_r = sqrt(qx**2 + qy**2) 145 qx_res = ( 145 qx_res = ((dqx*cos(dphi) + q_r) * cos(-q_phi) + 146 146 dqy*sin(dphi) * sin(-q_phi)) 147 147 qy_res = (-(dqx*cos(dphi) + q_r) * sin(-q_phi) + … … 167 167 else: 168 168 return theory 169 170 """171 if __name__ == '__main__':172 ## Test w/ 2D linear function173 x = 0.001*np.arange(1, 11)174 dx = np.ones(len(x))*0.0003175 y = 0.001*np.arange(1, 11)176 dy = np.ones(len(x))*0.001177 z = np.ones(10)178 dz = sqrt(z)179 180 from sas.dataloader import Data2D181 #for i in range(10): print(i, 0.001 + i*0.008/9.0)182 #for i in range(100): print(i, int(math.floor( (i/ (100/9.0)) )))183 out = Data2D()184 out.data = z185 out.qx_data = x186 out.qy_data = y187 out.dqx_data = dx188 out.dqy_data = dy189 out.q_data = sqrt(dx * dx + dy * dy)190 index = np.ones(len(x), dtype = bool)191 out.mask = index192 from sas.models.LineModel import LineModel193 model = LineModel()194 model.setParam("A", 0)195 196 smear = Smearer2D(out, model, index)197 #smear.set_accuracy('Xhigh')198 value = smear.get_value()199 ## All data are ones, so the smeared should also be ones.200 print("Data length =", len(value))201 print(" 2D linear function, I = 0 + 1*qy")202 text = " Gaussian weighted averaging on a 2D linear function will "203 text += "provides the results same as without the averaging."204 print(text)205 print("qx_data", "qy_data", "I_nonsmear", "I_smeared")206 for ind in range(len(value)):207 print(x[ind], y[ind], model.evalDistribution([x, y])[ind], value[ind])208 209 210 if __name__ == '__main__':211 ## Another Test w/ constant function212 x = 0.001*np.arange(1,11)213 dx = np.ones(len(x))*0.001214 y = 0.001*np.arange(1,11)215 dy = np.ones(len(x))*0.001216 z = np.ones(10)217 dz = sqrt(z)218 219 from DataLoader import Data2D220 #for i in range(10): print(i, 0.001 + i*0.008/9.0)221 #for i in range(100): print(i, int(math.floor( (i/ (100/9.0)) )))222 out = Data2D()223 out.data = z224 out.qx_data = x225 out.qy_data = y226 out.dqx_data = dx227 out.dqy_data = dy228 index = np.ones(len(x), dtype = bool)229 out.mask = index230 from sas.models.Constant import Constant231 model = Constant()232 233 value = Smearer2D(out,model,index).get_value()234 ## All data are ones, so the smeared values should also be ones.235 print("Data length =",len(value), ", Data=",value)236 """ -
sasmodels/sesans.py
r384d114 r190fc2b 43 43 *I* [cm$^{-1}$] is the value of the SANS model at *q* 44 44 """ 45 G = np.zeros (len(SElength), 'd')46 for i in range(len(SElength)):47 integr = besselj(0, q*SElength[i])*Iq*q48 G[i] = np.sum(integr )45 G = np.zeros_like(SElength, 'd') 46 for i, SElength_i in enumerate(SElength): 47 integral = besselj(0, q*SElength_i)*Iq*q 48 G[i] = np.sum(integral) 49 49 50 50 # [m^-1] step size in q, needed for integration 51 dq =(q[1]-q[0])*1e1051 dq = (q[1]-q[0])*1e10 52 52 53 53 # integration step, convert q into [m**-1] and 2 pi circle integration
Note: See TracChangeset
for help on using the changeset viewer.