Changes in / [599993b9:2a12d8d8] in sasmodels
- Files:
-
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/guide/plugin.rst
r57c609b r2015f02 428 428 def random(): 429 429 ... 430 431 This function provides a model-specific random parameter set which shows model 432 features in the USANS to SANS range. For example, core-shell sphere sets the 433 outer radius of the sphere logarithmically in `[20, 20,000]`, which sets the Q 434 value for the transition from flat to falling. It then uses a beta distribution 435 to set the percentage of the shape which is shell, giving a preference for very 436 thin or very thick shells (but never 0% or 100%). Using `-sets=10` in sascomp 437 should show a reasonable variety of curves over the default sascomp q range. 438 The parameter set is returned as a dictionary of `{parameter: value, ...}`. 439 Any model parameters not included in the dictionary will default according to 430 431 This function provides a model-specific random parameter set which shows model 432 features in the USANS to SANS range. For example, core-shell sphere sets the 433 outer radius of the sphere logarithmically in `[20, 20,000]`, which sets the Q 434 value for the transition from flat to falling. It then uses a beta distribution 435 to set the percentage of the shape which is shell, giving a preference for very 436 thin or very thick shells (but never 0% or 100%). Using `-sets=10` in sascomp 437 should show a reasonable variety of curves over the default sascomp q range. 438 The parameter set is returned as a dictionary of `{parameter: value, ...}`. 439 Any model parameters not included in the dictionary will default according to 440 440 the code in the `_randomize_one()` function from sasmodels/compare.py. 441 441 … … 701 701 erf, erfc, tgamma, lgamma: **do not use** 702 702 Special functions that should be part of the standard, but are missing 703 or inaccurate on some platforms. Use sas_erf, sas_erfc ,sas_gamma704 and sas_lgamma instead (see below).703 or inaccurate on some platforms. Use sas_erf, sas_erfc and sas_gamma 704 instead (see below). Note: lgamma(x) has not yet been tested. 705 705 706 706 Some non-standard constants and functions are also provided: … … 769 769 Gamma function sas_gamma\ $(x) = \Gamma(x)$. 770 770 771 The standard math function, tgamma(x) ,is unstable for $x < 1$771 The standard math function, tgamma(x) is unstable for $x < 1$ 772 772 on some platforms. 773 773 774 774 :code:`source = ["lib/sas_gamma.c", ...]` 775 775 (`sas_gamma.c <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_gamma.c>`_) 776 777 sas_gammaln(x):778 log gamma function sas_gammaln\ $(x) = \log \Gamma(|x|)$.779 780 The standard math function, lgamma(x), is incorrect for single781 precision on some platforms.782 783 :code:`source = ["lib/sas_gammainc.c", ...]`784 (`sas_gammainc.c <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_gammainc.c>`_)785 786 sas_gammainc(a, x), sas_gammaincc(a, x):787 Incomplete gamma function788 sas_gammainc\ $(a, x) = \int_0^x t^{a-1}e^{-t}\,dt / \Gamma(a)$789 and complementary incomplete gamma function790 sas_gammaincc\ $(a, x) = \int_x^\infty t^{a-1}e^{-t}\,dt / \Gamma(a)$791 792 :code:`source = ["lib/sas_gammainc.c", ...]`793 (`sas_gammainc.c <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_gammainc.c>`_)794 776 795 777 sas_erf(x), sas_erfc(x): … … 829 811 If $n$ = 0 or 1, it uses sas_J0($x$) or sas_J1($x$), respectively. 830 812 831 Warning: JN(n,x) can be very inaccurate (0.1%) for x not in [0.1, 100].832 833 813 The standard math function jn(n, x) is not available on all platforms. 834 814 … … 839 819 Sine integral Si\ $(x) = \int_0^x \tfrac{\sin t}{t}\,dt$. 840 820 841 Warning: Si(x) can be very inaccurate (0.1%) for x in [0.1, 100].842 843 821 This function uses Taylor series for small and large arguments: 844 822 845 For large arguments use the following Taylor series,823 For large arguments, 846 824 847 825 .. math:: … … 851 829 - \frac{\sin(x)}{x}\left(\frac{1}{x} - \frac{3!}{x^3} + \frac{5!}{x^5} - \frac{7!}{x^7}\right) 852 830 853 For small arguments 831 For small arguments, 854 832 855 833 .. math:: -
explore/precision.py
rfba9ca0 r2a7e20e 95 95 neg: [-100,100] 96 96 97 For arbitrary range use "start:stop:steps:scale" where scale is98 one of log, lin, or linear.99 100 97 *diff* is "relative", "absolute" or "none" 101 98 … … 105 102 linear = not xrange.startswith("log") 106 103 if xrange == "zoom": 107 start, stop,steps = 1000, 1010, 2000104 lin_min, lin_max, lin_steps = 1000, 1010, 2000 108 105 elif xrange == "neg": 109 start, stop,steps = -100.1, 100.1, 2000106 lin_min, lin_max, lin_steps = -100.1, 100.1, 2000 110 107 elif xrange == "linear": 111 start, stop,steps = 1, 1000, 2000112 start, stop,steps = 0.001, 2, 2000108 lin_min, lin_max, lin_steps = 1, 1000, 2000 109 lin_min, lin_max, lin_steps = 0.001, 2, 2000 113 110 elif xrange == "log": 114 start, stop,steps = -3, 5, 400111 log_min, log_max, log_steps = -3, 5, 400 115 112 elif xrange == "logq": 116 start, stop, steps = -4, 1, 400 117 elif ':' in xrange: 118 parts = xrange.split(':') 119 linear = parts[3] != "log" if len(parts) == 4 else True 120 steps = int(parts[2]) if len(parts) > 2 else 400 121 start = float(parts[0]) 122 stop = float(parts[1]) 123 113 log_min, log_max, log_steps = -4, 1, 400 124 114 else: 125 115 raise ValueError("unknown range "+xrange) … … 131 121 # value to x in the given precision. 132 122 if linear: 133 start = max(start, self.limits[0])134 stop = min(stop, self.limits[1])135 qrf = np.linspace( start, stop,steps, dtype='single')136 #qrf = np.linspace( start, stop,steps, dtype='double')123 lin_min = max(lin_min, self.limits[0]) 124 lin_max = min(lin_max, self.limits[1]) 125 qrf = np.linspace(lin_min, lin_max, lin_steps, dtype='single') 126 #qrf = np.linspace(lin_min, lin_max, lin_steps, dtype='double') 137 127 qr = [mp.mpf(float(v)) for v in qrf] 138 #qr = mp.linspace( start, stop,steps)128 #qr = mp.linspace(lin_min, lin_max, lin_steps) 139 129 else: 140 start = np.log10(max(10**start, self.limits[0]))141 stop = np.log10(min(10**stop, self.limits[1]))142 qrf = np.logspace( start, stop,steps, dtype='single')143 #qrf = np.logspace( start, stop,steps, dtype='double')130 log_min = np.log10(max(10**log_min, self.limits[0])) 131 log_max = np.log10(min(10**log_max, self.limits[1])) 132 qrf = np.logspace(log_min, log_max, log_steps, dtype='single') 133 #qrf = np.logspace(log_min, log_max, log_steps, dtype='double') 144 134 qr = [mp.mpf(float(v)) for v in qrf] 145 #qr = [10**v for v in mp.linspace( start, stop,steps)]135 #qr = [10**v for v in mp.linspace(log_min, log_max, log_steps)] 146 136 147 137 target = self.call_mpmath(qr, bits=500) … … 186 176 """ 187 177 if diff == "relative": 188 err = np.array([ (abs((t-a)/t) if t != 0 else a) for t, a in zip(target, actual)], 'd')178 err = np.array([abs((t-a)/t) for t, a in zip(target, actual)], 'd') 189 179 #err = np.clip(err, 0, 1) 190 180 pylab.loglog(x, err, '-', label=label) … … 207 197 return model_info 208 198 209 # Hack to allow second parameter A in two parameter functions210 A = 1211 def parse_extra_pars():212 global A213 214 A_str = str(A)215 pop = []216 for k, v in enumerate(sys.argv[1:]):217 if v.startswith("A="):218 A_str = v[2:]219 pop.append(k+1)220 if pop:221 sys.argv = [v for k, v in enumerate(sys.argv) if k not in pop]222 A = float(A_str)223 224 parse_extra_pars()225 226 199 227 200 # =============== FUNCTION DEFINITIONS ================ … … 324 297 ocl_function=make_ocl("return sas_gamma(q);", "sas_gamma", ["lib/sas_gamma.c"]), 325 298 limits=(-3.1, 10), 326 )327 add_function(328 name="gammaln(x)",329 mp_function=mp.loggamma,330 np_function=scipy.special.gammaln,331 ocl_function=make_ocl("return sas_gammaln(q);", "sas_gammaln", ["lib/sas_gammainc.c"]),332 #ocl_function=make_ocl("return lgamma(q);", "sas_gammaln"),333 )334 add_function(335 name="gammainc(x)",336 mp_function=lambda x, a=A: mp.gammainc(a, a=0, b=x)/mp.gamma(a),337 np_function=lambda x, a=A: scipy.special.gammainc(a, x),338 ocl_function=make_ocl("return sas_gammainc(%.15g,q);"%A, "sas_gammainc", ["lib/sas_gammainc.c"]),339 )340 add_function(341 name="gammaincc(x)",342 mp_function=lambda x, a=A: mp.gammainc(a, a=x, b=mp.inf)/mp.gamma(a),343 np_function=lambda x, a=A: scipy.special.gammaincc(a, x),344 ocl_function=make_ocl("return sas_gammaincc(%.15g,q);"%A, "sas_gammaincc", ["lib/sas_gammainc.c"]),345 299 ) 346 300 add_function( … … 509 463 lanczos_gamma = """\ 510 464 const double coeff[] = { 511 76.18009172947146, -86.50532032941677,512 24.01409824083091, -1.231739572450155,465 76.18009172947146, -86.50532032941677, 466 24.01409824083091, -1.231739572450155, 513 467 0.1208650973866179e-2,-0.5395239384953e-5 514 468 }; … … 521 475 """ 522 476 add_function( 523 name="log gamma(x)",477 name="log gamma(x)", 524 478 mp_function=mp.loggamma, 525 479 np_function=scipy.special.gammaln, … … 645 599 646 600 ALL_FUNCTIONS = set(FUNCTIONS.keys()) 647 ALL_FUNCTIONS.discard("loggamma") # use cephes-based gammaln instead601 ALL_FUNCTIONS.discard("loggamma") # OCL version not ready yet 648 602 ALL_FUNCTIONS.discard("3j1/x:taylor") 649 603 ALL_FUNCTIONS.discard("3j1/x:trig") … … 661 615 -r indicates that the relative error should be plotted (default), 662 616 -x<range> indicates the steps in x, where <range> is one of the following 663 log indicates log stepping in [10^-3, 10^5] (default) 664 logq indicates log stepping in [10^-4, 10^1] 665 linear indicates linear stepping in [1, 1000] 666 zoom indicates linear stepping in [1000, 1010] 667 neg indicates linear stepping in [-100.1, 100.1] 668 start:stop:n[:stepping] indicates an n-step plot in [start, stop] 669 or [10^start, 10^stop] if stepping is "log" (default n=400) 670 Some functions (notably gammainc/gammaincc) have an additional parameter A 671 which can be set from the command line as A=value. Default is A=1. 672 673 Name is one of: 617 log indicates log stepping in [10^-3, 10^5] (default) 618 logq indicates log stepping in [10^-4, 10^1] 619 linear indicates linear stepping in [1, 1000] 620 zoom indicates linear stepping in [1000, 1010] 621 neg indicates linear stepping in [-100.1, 100.1] 622 and name is "all" or one of: 674 623 """+names) 675 624 sys.exit(1) -
sasmodels/kernelpy.py
r91bd550 r91bd550 37 37 self.info = model_info 38 38 self.dtype = np.dtype('d') 39 logger.info("make python model " + self.info.name)40 39 41 40 def make_kernel(self, q_vectors): -
sasmodels/model_test.py
r12eec1e r012cd34 47 47 import sys 48 48 import unittest 49 import traceback50 49 51 50 try: … … 75 74 # pylint: enable=unused-import 76 75 76 77 77 def make_suite(loaders, models): 78 78 # type: (List[str], List[str]) -> unittest.TestSuite … … 86 86 *models* is the list of models to test, or *["all"]* to test all models. 87 87 """ 88 ModelTestCase = _hide_model_case_from_nose() 88 89 suite = unittest.TestSuite() 89 90 … … 94 95 skip = [] 95 96 for model_name in models: 96 if model_name not in skip: 97 model_info = load_model_info(model_name) 98 _add_model_to_suite(loaders, suite, model_info) 97 if model_name in skip: 98 continue 99 model_info = load_model_info(model_name) 100 101 #print('------') 102 #print('found tests in', model_name) 103 #print('------') 104 105 # if ispy then use the dll loader to call pykernel 106 # don't try to call cl kernel since it will not be 107 # available in some environmentes. 108 is_py = callable(model_info.Iq) 109 110 # Some OpenCL drivers seem to be flaky, and are not producing the 111 # expected result. Since we don't have known test values yet for 112 # all of our models, we are instead going to compare the results 113 # for the 'smoke test' (that is, evaluation at q=0.1 for the default 114 # parameters just to see that the model runs to completion) between 115 # the OpenCL and the DLL. To do this, we define a 'stash' which is 116 # shared between OpenCL and DLL tests. This is just a list. If the 117 # list is empty (which it will be when DLL runs, if the DLL runs 118 # first), then the results are appended to the list. If the list 119 # is not empty (which it will be when OpenCL runs second), the results 120 # are compared to the results stored in the first element of the list. 121 # This is a horrible stateful hack which only makes sense because the 122 # test suite is thrown away after being run once. 123 stash = [] 124 125 if is_py: # kernel implemented in python 126 test_name = "%s-python"%model_name 127 test_method_name = "test_%s_python" % model_info.id 128 test = ModelTestCase(test_name, model_info, 129 test_method_name, 130 platform="dll", # so that 131 dtype="double", 132 stash=stash) 133 suite.addTest(test) 134 else: # kernel implemented in C 135 136 # test using dll if desired 137 if 'dll' in loaders or not use_opencl(): 138 test_name = "%s-dll"%model_name 139 test_method_name = "test_%s_dll" % model_info.id 140 test = ModelTestCase(test_name, model_info, 141 test_method_name, 142 platform="dll", 143 dtype="double", 144 stash=stash) 145 suite.addTest(test) 146 147 # test using opencl if desired and available 148 if 'opencl' in loaders and use_opencl(): 149 test_name = "%s-opencl"%model_name 150 test_method_name = "test_%s_opencl" % model_info.id 151 # Using dtype=None so that the models that are only 152 # correct for double precision are not tested using 153 # single precision. The choice is determined by the 154 # presence of *single=False* in the model file. 155 test = ModelTestCase(test_name, model_info, 156 test_method_name, 157 platform="ocl", dtype=None, 158 stash=stash) 159 #print("defining", test_name) 160 suite.addTest(test) 99 161 100 162 return suite 101 102 def _add_model_to_suite(loaders, suite, model_info):103 ModelTestCase = _hide_model_case_from_nose()104 105 #print('------')106 #print('found tests in', model_name)107 #print('------')108 109 # if ispy then use the dll loader to call pykernel110 # don't try to call cl kernel since it will not be111 # available in some environmentes.112 is_py = callable(model_info.Iq)113 114 # Some OpenCL drivers seem to be flaky, and are not producing the115 # expected result. Since we don't have known test values yet for116 # all of our models, we are instead going to compare the results117 # for the 'smoke test' (that is, evaluation at q=0.1 for the default118 # parameters just to see that the model runs to completion) between119 # the OpenCL and the DLL. To do this, we define a 'stash' which is120 # shared between OpenCL and DLL tests. This is just a list. If the121 # list is empty (which it will be when DLL runs, if the DLL runs122 # first), then the results are appended to the list. If the list123 # is not empty (which it will be when OpenCL runs second), the results124 # are compared to the results stored in the first element of the list.125 # This is a horrible stateful hack which only makes sense because the126 # test suite is thrown away after being run once.127 stash = []128 129 if is_py: # kernel implemented in python130 test_name = "%s-python"%model_info.name131 test_method_name = "test_%s_python" % model_info.id132 test = ModelTestCase(test_name, model_info,133 test_method_name,134 platform="dll", # so that135 dtype="double",136 stash=stash)137 suite.addTest(test)138 else: # kernel implemented in C139 140 # test using dll if desired141 if 'dll' in loaders or not use_opencl():142 test_name = "%s-dll"%model_info.name143 test_method_name = "test_%s_dll" % model_info.id144 test = ModelTestCase(test_name, model_info,145 test_method_name,146 platform="dll",147 dtype="double",148 stash=stash)149 suite.addTest(test)150 151 # test using opencl if desired and available152 if 'opencl' in loaders and use_opencl():153 test_name = "%s-opencl"%model_info.name154 test_method_name = "test_%s_opencl" % model_info.id155 # Using dtype=None so that the models that are only156 # correct for double precision are not tested using157 # single precision. The choice is determined by the158 # presence of *single=False* in the model file.159 test = ModelTestCase(test_name, model_info,160 test_method_name,161 platform="ocl", dtype=None,162 stash=stash)163 #print("defining", test_name)164 suite.addTest(test)165 166 163 167 164 def _hide_model_case_from_nose(): … … 351 348 return abs(target-actual)/shift < 1.5*10**-digits 352 349 353 # CRUFT: old interface; should be deprecated and removed 354 def run_one(model_name): 355 # msg = "use check_model(model_info) rather than run_one(model_name)" 356 # warnings.warn(msg, category=DeprecationWarning, stacklevel=2) 357 try: 358 model_info = load_model_info(model_name) 359 except Exception: 360 output = traceback.format_exc() 361 return output 362 363 success, output = check_model(model_info) 364 return output 365 366 def check_model(model_info): 367 # type: (ModelInfo) -> str 368 """ 369 Run the tests for a single model, capturing the output. 370 371 Returns success status and the output string. 350 def run_one(model): 351 # type: (str) -> str 352 """ 353 Run the tests for a single model, printing the results to stdout. 354 355 *model* can by a python file, which is handy for checking user defined 356 plugin models. 372 357 """ 373 358 # Note that running main() directly did not work from within the … … 384 369 # Build a test suite containing just the model 385 370 loaders = ['opencl'] if use_opencl() else ['dll'] 386 suite = unittest.TestSuite() 387 _add_model_to_suite(loaders, suite, model_info) 371 models = [model] 372 try: 373 suite = make_suite(loaders, models) 374 except Exception: 375 import traceback 376 stream.writeln(traceback.format_exc()) 377 return 388 378 389 379 # Warn if there are no user defined tests. … … 400 390 for test in suite: 401 391 if not test.info.tests: 402 stream.writeln("Note: %s has no user defined tests."%model _info.name)392 stream.writeln("Note: %s has no user defined tests."%model) 403 393 break 404 394 else: … … 416 406 output = stream.getvalue() 417 407 stream.close() 418 return result.wasSuccessful(),output408 return output 419 409 420 410 -
sasmodels/sasview_model.py
rbd547d0 rbd547d0 803 803 return value, [value], [1.0] 804 804 805 @classmethod806 def runTests(cls):807 """808 Run any tests built into the model and captures the test output.809 810 Returns success flag and output811 """812 from .model_test import check_model813 return check_model(cls._model_info)814 815 805 def test_cylinder(): 816 806 # type: () -> float -
sasmodels/special.py
rfba9ca0 rdf69efa 113 113 The standard math function, tgamma(x) is unstable for $x < 1$ 114 114 on some platforms. 115 116 sas_gammaln(x):117 log gamma function sas_gammaln\ $(x) = \log \Gamma(|x|)$.118 119 The standard math function, lgamma(x), is incorrect for single120 precision on some platforms.121 122 sas_gammainc(a, x), sas_gammaincc(a, x):123 Incomplete gamma function124 sas_gammainc\ $(a, x) = \int_0^x t^{a-1}e^{-t}\,dt / \Gamma(a)$125 and complementary incomplete gamma function126 sas_gammaincc\ $(a, x) = \int_x^\infty t^{a-1}e^{-t}\,dt / \Gamma(a)$127 115 128 116 sas_erf(x), sas_erfc(x): … … 219 207 from numpy import pi, nan, inf 220 208 from scipy.special import gamma as sas_gamma 221 from scipy.special import gammaln as sas_gammaln222 from scipy.special import gammainc as sas_gammainc223 from scipy.special import gammaincc as sas_gammaincc224 209 from scipy.special import erf as sas_erf 225 210 from scipy.special import erfc as sas_erfc
Note: See TracChangeset
for help on using the changeset viewer.