- Timestamp:
- Feb 12, 2018 8:24:15 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:
- a2ca6e5
- Parents:
- e309e23 (diff), f6fd413 (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/12/18 20:24:15)
- git-committer:
- GitHub <noreply@…> (02/12/18 20:24:15)
- Location:
- sasmodels
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/compare.py
r2a7e20e r3221de0 40 40 from . import core 41 41 from . import kerneldll 42 from . import kernelcl 42 43 from .data import plot_theory, empty_data1D, empty_data2D, load_data 43 44 from .direct_model import DirectModel, get_mesh … … 623 624 624 625 626 def time_calculation(calculator, pars, evals=1): 627 # type: (Calculator, ParameterSet, int) -> Tuple[np.ndarray, float] 628 """ 629 Compute the average calculation time over N evaluations. 630 631 An additional call is generated without polydispersity in order to 632 initialize the calculation engine, and make the average more stable. 633 """ 634 # initialize the code so time is more accurate 635 if evals > 1: 636 calculator(**suppress_pd(pars)) 637 toc = tic() 638 # make sure there is at least one eval 639 value = calculator(**pars) 640 for _ in range(evals-1): 641 value = calculator(**pars) 642 average_time = toc()*1000. / evals 643 #print("I(q)",value) 644 return value, average_time 645 646 def make_data(opts): 647 # type: (Dict[str, Any]) -> Tuple[Data, np.ndarray] 648 """ 649 Generate an empty dataset, used with the model to set Q points 650 and resolution. 651 652 *opts* contains the options, with 'qmax', 'nq', 'res', 653 'accuracy', 'is2d' and 'view' parsed from the command line. 654 """ 655 qmin, qmax, nq, res = opts['qmin'], opts['qmax'], opts['nq'], opts['res'] 656 if opts['is2d']: 657 q = np.linspace(-qmax, qmax, nq) # type: np.ndarray 658 data = empty_data2D(q, resolution=res) 659 data.accuracy = opts['accuracy'] 660 set_beam_stop(data, qmin) 661 index = ~data.mask 662 else: 663 if opts['view'] == 'log' and not opts['zero']: 664 q = np.logspace(math.log10(qmin), math.log10(qmax), nq) 665 else: 666 q = np.linspace(qmin, qmax, nq) 667 if opts['zero']: 668 q = np.hstack((0, q)) 669 data = empty_data1D(q, resolution=res) 670 index = slice(None, None) 671 return data, index 672 625 673 DTYPE_MAP = { 626 674 'half': '16', … … 643 691 Return a model calculator using the OpenCL calculation engine. 644 692 """ 645 if not core.HAVE_OPENCL:646 raise RuntimeError("OpenCL not available")647 model = core.build_model(model_info, dtype=dtype, platform="ocl")648 calculator = DirectModel(data, model, cutoff=cutoff)649 calculator.engine = "OCL%s"%DTYPE_MAP[str(model.dtype)]650 return calculator651 693 652 694 def eval_ctypes(model_info, data, dtype='double', cutoff=0.): … … 660 702 return calculator 661 703 662 def time_calculation(calculator, pars, evals=1):663 # type: (Calculator, ParameterSet, int) -> Tuple[np.ndarray, float]664 """665 Compute the average calculation time over N evaluations.666 667 An additional call is generated without polydispersity in order to668 initialize the calculation engine, and make the average more stable.669 """670 # initialize the code so time is more accurate671 if evals > 1:672 calculator(**suppress_pd(pars))673 toc = tic()674 # make sure there is at least one eval675 value = calculator(**pars)676 for _ in range(evals-1):677 value = calculator(**pars)678 average_time = toc()*1000. / evals679 #print("I(q)",value)680 return value, average_time681 682 def make_data(opts):683 # type: (Dict[str, Any]) -> Tuple[Data, np.ndarray]684 """685 Generate an empty dataset, used with the model to set Q points686 and resolution.687 688 *opts* contains the options, with 'qmax', 'nq', 'res',689 'accuracy', 'is2d' and 'view' parsed from the command line.690 """691 qmin, qmax, nq, res = opts['qmin'], opts['qmax'], opts['nq'], opts['res']692 if opts['is2d']:693 q = np.linspace(-qmax, qmax, nq) # type: np.ndarray694 data = empty_data2D(q, resolution=res)695 data.accuracy = opts['accuracy']696 set_beam_stop(data, qmin)697 index = ~data.mask698 else:699 if opts['view'] == 'log' and not opts['zero']:700 q = np.logspace(math.log10(qmin), math.log10(qmax), nq)701 else:702 q = np.linspace(qmin, qmax, nq)703 if opts['zero']:704 q = np.hstack((0, q))705 data = empty_data1D(q, resolution=res)706 index = slice(None, None)707 return data, index708 709 704 def make_engine(model_info, data, dtype, cutoff, ngauss=0): 710 705 # type: (ModelInfo, Data, str, float) -> Calculator … … 718 713 set_integration_size(model_info, ngauss) 719 714 720 if dtype is None or not dtype.endswith('!'): 721 return eval_opencl(model_info, data, dtype=dtype, cutoff=cutoff) 722 else: 723 return eval_ctypes(model_info, data, dtype=dtype[:-1], cutoff=cutoff) 715 if dtype != "default" and not dtype.endswith('!') and not kernelcl.use_opencl(): 716 raise RuntimeError("OpenCL not available " + kernelcl.OPENCL_ERROR) 717 718 model = core.build_model(model_info, dtype=dtype, platform="ocl") 719 calculator = DirectModel(data, model, cutoff=cutoff) 720 engine_type = calculator._model.__class__.__name__.replace('Model','').upper() 721 bits = calculator._model.dtype.itemsize*8 722 precision = "fast" if getattr(calculator._model, 'fast', False) else str(bits) 723 calculator.engine = "%s[%s]" % (engine_type, precision) 724 return calculator 724 725 725 726 def _show_invalid(data, theory): -
sasmodels/convert.py
r2d81cfe ra69d8cd 633 633 def test_backward_forward(): 634 634 from .core import list_models 635 L = lambda name: _check_one(name, seed=1) 635 636 for name in list_models('all'): 636 L = lambda: _check_one(name, seed=1) 637 L.description = name 638 yield L 637 yield L, name -
sasmodels/core.py
r7a516d0 r3221de0 21 21 from . import mixture 22 22 from . import kernelpy 23 from . import kernelcl 23 24 from . import kerneldll 24 25 from . import custom 25 26 if os.environ.get("SAS_OPENCL", "").lower() == "none":27 HAVE_OPENCL = False28 else:29 try:30 from . import kernelcl31 HAVE_OPENCL = True32 except Exception:33 HAVE_OPENCL = False34 35 CUSTOM_MODEL_PATH = os.environ.get('SAS_MODELPATH', "")36 if CUSTOM_MODEL_PATH == "":37 CUSTOM_MODEL_PATH = joinpath(os.path.expanduser("~"), ".sasmodels", "custom_models")38 if not os.path.isdir(CUSTOM_MODEL_PATH):39 os.makedirs(CUSTOM_MODEL_PATH)40 26 41 27 # pylint: disable=unused-import … … 47 33 pass 48 34 # pylint: enable=unused-import 35 36 CUSTOM_MODEL_PATH = os.environ.get('SAS_MODELPATH', "") 37 if CUSTOM_MODEL_PATH == "": 38 CUSTOM_MODEL_PATH = joinpath(os.path.expanduser("~"), ".sasmodels", "custom_models") 39 if not os.path.isdir(CUSTOM_MODEL_PATH): 40 os.makedirs(CUSTOM_MODEL_PATH) 49 41 50 42 # TODO: refactor composite model support … … 276 268 if platform is None: 277 269 platform = "ocl" 278 if platform == "ocl" and not HAVE_OPENCLor not model_info.opencl:270 if not kernelcl.use_opencl() or not model_info.opencl: 279 271 platform = "dll" 280 272 … … 320 312 print("\n".join(list_models(kind))) 321 313 322 def test_load(): 323 # type: () -> None 324 """Check that model load works""" 314 def test_composite_order(): 325 315 def test_models(fst, snd): 326 316 """Confirm that two models produce the same parameters""" 327 317 fst = load_model(fst) 328 318 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 319 # Un-disambiguate parameter names so that we can check if the same 320 # parameters are in a pair of composite models. Since each parameter in 321 # the mixture model is tagged as e.g., A_sld, we ought to use a 322 # regex subsitution s/^[A-Z]+_/_/, but removing all uppercase letters 323 # is good enough. 332 324 fst = [[x for x in p.name if x == x.lower()] for p in fst.info.parameters.kernel_parameters] 333 325 snd = [[x for x in p.name if x == x.lower()] for p in snd.info.parameters.kernel_parameters] 334 326 assert sorted(fst) == sorted(snd), "{} != {}".format(fst, snd) 335 327 336 337 test_models( 328 def build_test(first, second): 329 test = lambda description: test_models(first, second) 330 description = first + " vs. " + second 331 return test, description 332 333 yield build_test( 338 334 "cylinder+sphere", 339 335 "sphere+cylinder") 340 test_models(336 yield build_test( 341 337 "cylinder*sphere", 342 338 "sphere*cylinder") 343 test_models(339 yield build_test( 344 340 "cylinder@hardsphere*sphere", 345 341 "sphere*cylinder@hardsphere") 346 test_models(342 yield build_test( 347 343 "barbell+sphere*cylinder@hardsphere", 348 344 "sphere*cylinder@hardsphere+barbell") 349 test_models(345 yield build_test( 350 346 "barbell+cylinder@hardsphere*sphere", 351 347 "cylinder@hardsphere*sphere+barbell") 352 test_models(348 yield build_test( 353 349 "barbell+sphere*cylinder@hardsphere", 354 350 "barbell+cylinder@hardsphere*sphere") 355 test_models(351 yield build_test( 356 352 "sphere*cylinder@hardsphere+barbell", 357 353 "cylinder@hardsphere*sphere+barbell") 358 test_models(354 yield build_test( 359 355 "barbell+sphere*cylinder@hardsphere", 360 356 "cylinder@hardsphere*sphere+barbell") 361 test_models(357 yield build_test( 362 358 "barbell+cylinder@hardsphere*sphere", 363 359 "sphere*cylinder@hardsphere+barbell") 364 360 361 def test_composite(): 362 # type: () -> None 363 """Check that model load works""" 365 364 #Test the the model produces the parameters that we would expect 366 365 model = load_model("cylinder@hardsphere*sphere") -
sasmodels/jitter.py
r0d5a655 r42158d2 13 13 import argparse 14 14 15 import mpl_toolkits.mplot3d # Adds projection='3d' option to subplot 15 try: # CRUFT: travis-ci does not support mpl_toolkits.mplot3d 16 import mpl_toolkits.mplot3d # Adds projection='3d' option to subplot 17 except ImportError: 18 pass 19 16 20 import matplotlib.pyplot as plt 17 21 from matplotlib.widgets import Slider, CheckButtons -
sasmodels/kernelcl.py
r2d81cfe rb4272a2 58 58 import numpy as np # type: ignore 59 59 60 61 # Attempt to setup opencl. This may fail if the opencl package is not 62 # installed or if it is installed but there are no devices available. 60 63 try: 61 #raise NotImplementedError("OpenCL not yet implemented for new kernel template")62 64 import pyopencl as cl # type: ignore 65 from pyopencl import mem_flags as mf 66 from pyopencl.characterize import get_fast_inaccurate_build_options 63 67 # Ask OpenCL for the default context so that we know that one exists 64 68 cl.create_some_context(interactive=False) 69 HAVE_OPENCL = True 70 OPENCL_ERROR = "" 65 71 except Exception as exc: 66 warnings.warn("OpenCL startup failed with ***" 67 + str(exc) + "***; using C compiler instead") 68 raise RuntimeError("OpenCL not available") 69 70 from pyopencl import mem_flags as mf 71 from pyopencl.characterize import get_fast_inaccurate_build_options 72 HAVE_OPENCL = False 73 OPENCL_ERROR = str(exc) 72 74 73 75 from . import generate … … 102 104 cl._DEFAULT_INCLUDE_OPTIONS = [quote_path(v) for v in cl._DEFAULT_INCLUDE_OPTIONS] 103 105 104 fix_pyopencl_include() 105 106 if HAVE_OPENCL: 107 fix_pyopencl_include() 106 108 107 109 # The max loops number is limited by the amount of local memory available … … 128 130 """ 129 131 132 def use_opencl(): 133 return HAVE_OPENCL and os.environ.get("SAS_OPENCL", "").lower() != "none" 130 134 131 135 ENV = None 136 def reset_environment(): 137 """ 138 Call to create a new OpenCL context, such as after a change to SAS_OPENCL. 139 """ 140 global ENV 141 ENV = GpuEnvironment() if use_opencl() else None 142 132 143 def environment(): 133 144 # type: () -> "GpuEnvironment" … … 137 148 This provides an OpenCL context and one queue per device. 138 149 """ 139 global ENV140 150 if ENV is None: 141 ENV = GpuEnvironment() 151 if not HAVE_OPENCL: 152 raise RuntimeError("OpenCL startup failed with ***" 153 + OPENCL_ERROR + "***; using C compiler instead") 154 reset_environment() 155 if ENV is None: 156 raise RuntimeError("SAS_OPENCL=None in environment") 142 157 return ENV 143 158 -
sasmodels/model_test.py
r2d81cfe r3221de0 62 62 from .exception import annotate_exception 63 63 from .modelinfo import expand_pars 64 from .kernelcl import use_opencl 64 65 65 66 # pylint: disable=unused-import … … 123 124 124 125 if is_py: # kernel implemented in python 125 test_name = " Model: %s, Kernel:python"%model_name126 test_name = "%s-python"%model_name 126 127 test_method_name = "test_%s_python" % model_info.id 127 128 test = ModelTestCase(test_name, model_info, … … 134 135 135 136 # test using dll if desired 136 if 'dll' in loaders or not core.HAVE_OPENCL:137 test_name = " Model: %s, Kernel:dll"%model_name137 if 'dll' in loaders or not use_opencl(): 138 test_name = "%s-dll"%model_name 138 139 test_method_name = "test_%s_dll" % model_info.id 139 140 test = ModelTestCase(test_name, model_info, … … 145 146 146 147 # test using opencl if desired and available 147 if 'opencl' in loaders and core.HAVE_OPENCL:148 test_name = " Model: %s, Kernel: OpenCL"%model_name148 if 'opencl' in loaders and use_opencl(): 149 test_name = "%s-opencl"%model_name 149 150 test_method_name = "test_%s_opencl" % model_info.id 150 151 # Using dtype=None so that the models that are only … … 160 161 161 162 return suite 162 163 163 164 164 def _hide_model_case_from_nose(): … … 368 368 369 369 # Build a test suite containing just the model 370 loaders = ['opencl'] if core.HAVE_OPENCLelse ['dll']370 loaders = ['opencl'] if use_opencl() else ['dll'] 371 371 models = [model] 372 372 try: … … 425 425 verbosity = 1 426 426 if models and models[0] == 'opencl': 427 if not core.HAVE_OPENCL:427 if not use_opencl(): 428 428 print("opencl is not available") 429 429 return 1 … … 435 435 models = models[1:] 436 436 elif models and models[0] == 'opencl_and_dll': 437 loaders = ['opencl', 'dll'] if core.HAVE_OPENCLelse ['dll']437 loaders = ['opencl', 'dll'] if use_opencl() else ['dll'] 438 438 models = models[1:] 439 439 else: 440 loaders = ['opencl', 'dll'] if core.HAVE_OPENCLelse ['dll']440 loaders = ['opencl', 'dll'] if use_opencl() else ['dll'] 441 441 if not models: 442 442 print("""\ … … 467 467 Run "nosetests sasmodels" on the command line to invoke it. 468 468 """ 469 loaders = ['opencl', 'dll'] if core.HAVE_OPENCLelse ['dll']469 loaders = ['opencl', 'dll'] if use_opencl() else ['dll'] 470 470 tests = make_suite(loaders, ['all']) 471 for test_i in tests: 472 # In order for nosetest to see the correct test name, need to set 473 # the description attribute of the returned function. Since we 474 # can't do this for the returned instance, wrap it in a lambda and 475 # set the description on the lambda. Otherwise we could just do: 476 # yield test_i.run_all 477 L = lambda: test_i.run_all() 478 L.description = test_i.test_name 479 yield L 471 def build_test(test): 472 # In order for nosetest to show the test name, wrap the test.run_all 473 # instance in function that takes the test name as a parameter which 474 # will be displayed when the test is run. Do this as a function so 475 # that it properly captures the context for tests that captured and 476 # run later. If done directly in the for loop, then the looping 477 # variable test will be shared amongst all the tests, and we will be 478 # repeatedly testing vesicle. 479 480 # Note: in sasview sas.sasgui.perspectives.fitting.gpu_options 481 # requires that the test.description field be set. 482 wrap = lambda: test.run_all() 483 wrap.description = test.test_name 484 return wrap 485 # The following would work with nosetests and pytest: 486 # return lambda name: test.run_all(), test.test_name 487 488 for test in tests: 489 yield build_test(test) 480 490 481 491 -
sasmodels/sasview_model.py
r2d81cfe r3221de0 665 665 666 666 def _calculate_Iq(self, qx, qy=None): 667 #core.HAVE_OPENCL = False668 667 if self._model is None: 669 668 self._model = core.build_model(self._model_info) … … 859 858 # type: () -> None 860 859 """ 861 Load and run cylinder model from sas.models.CylinderModel860 Load and run cylinder model as sas-models-CylinderModel 862 861 """ 863 862 if not SUPPORT_OLD_STYLE_PLUGINS: -
sasmodels/kernel_iq.c
r924a119 raadec17 93 93 // Compute the magnetic sld 94 94 static double mag_sld( 95 const int xs, // 0=dd, 1=du real, 2=ud real, 3=uu, 4=du imag, 5=up imag95 const unsigned int xs, // 0=dd, 1=du real, 2=ud real, 3=uu, 4=du imag, 5=up imag 96 96 const double qx, const double qy, 97 97 const double px, const double py, … … 103 103 const double perp = qy*mx - qx*my; 104 104 switch (xs) { 105 default: // keep compiler happy; condition ensures xs in [0,1,2,3] 105 106 case 0: // uu => sld - D M_perpx 106 107 return sld - px*perp; … … 659 660 660 661 // loop over uu, ud real, du real, dd, ud imag, du imag 661 for ( int xs=0; xs<6; xs++) {662 for (unsigned int xs=0; xs<6; xs++) { 662 663 const double xs_weight = spins[xs]; 663 664 if (xs_weight > 1.e-8) { -
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
Note: See TracChangeset
for help on using the changeset viewer.