Changes in / [b9c7379:a08c47f] in sasmodels
- Files:
-
- 8 added
- 6 deleted
- 59 edited
Legend:
- Unmodified
- Added
- Removed
-
README.rst
re30d645 r2a64722 10 10 is available. 11 11 12 Example 12 Install 13 13 ------- 14 15 The easiest way to use sasmodels is from `SasView <http://www.sasview.org/>`_. 16 17 You can also install sasmodels as a standalone package in python. Use 18 `miniconda <https://docs.conda.io/en/latest/miniconda.html>`_ 19 or `anaconda <https://www.anaconda.com/>`_ 20 to create a python environment with the sasmodels dependencies:: 21 22 $ conda create -n sasmodels -c conda-forge numpy scipy matplotlib pyopencl 23 24 The option ``-n sasmodels`` names the environment sasmodels, and the option 25 ``-c conda-forge`` selects the conda-forge package channel because pyopencl 26 is not part of the base anaconda distribution. 27 28 Activate the environment and install sasmodels:: 29 30 $ conda activate sasmodels 31 (sasmodels) $ pip install sasmodels 32 33 Install `bumps <https://github.com/bumps/bumps>`_ if you want to use it to fit 34 your data:: 35 36 (sasmodels) $ pip install bumps 37 38 Usage 39 ----- 40 41 Check that the works:: 42 43 (sasmodels) $ python -m sasmodels.compare cylinder 44 45 To show the orientation explorer:: 46 47 (sasmodels) $ python -m sasmodels.jitter 48 49 Documentation is available online as part of the SasView 50 `fitting perspective <http://www.sasview.org/docs/index.html>`_ 51 as well as separate pages for 52 `individual models <http://www.sasview.org/docs/user/sasgui/perspectives/fitting/models/index.html>`_. 53 Programming details for sasmodels are available in the 54 `developer documentation <http://www.sasview.org/docs/dev/dev.html>`_. 55 56 57 Fitting Example 58 --------------- 14 59 15 60 The example directory contains a radial+tangential data set for an oriented 16 61 rod-like shape. 17 62 18 The data is loaded by sas.dataloader from the sasview package, so sasview 19 is needed to run the example. 63 To load the example data, you will need the SAS data loader from the sasview 64 package. This is not yet available on PyPI, so you will need a copy of the 65 SasView source code to run it. Create a directory somewhere to hold the 66 sasview and sasmodels source code, which we will refer to as $SOURCE. 20 67 21 To run the example, you need sasview, sasmodels and bumps. Assuming these 22 repositories are installed side by side, change to the sasmodels/example 23 directory and enter:: 68 Use the following to install sasview, and the sasmodels examples:: 24 69 25 PYTHONPATH=..:../../sasview/src ../../bumps/run.py fit.py \ 26 cylinder --preview 70 (sasmodels) $ cd $SOURCE 71 (sasmodels) $ conda install git 72 (sasmodels) $ git clone https://github.com/sasview/sasview.git 73 (sasmodels) $ git clone https://github.com/sasview/sasmodels.git 27 74 28 See bumps documentation for instructions on running the fit. With the 29 python packages installed, e.g., into a virtual environment, then the 30 python path need not be set, and the command would be:: 75 Set the path to the sasview source on your python path within the sasmodels 76 environment. On Windows, this will be:: 31 77 32 bumps fit.py cylinder --preview 78 (sasmodels)> set PYTHONPATH="$SOURCE\sasview\src" 79 (sasmodels)> cd $SOURCE/sasmodels/example 80 (sasmodels)> python -m bumps.cli fit.py cylinder --preview 81 82 On Mac/Linux with the standard shell this will be:: 83 84 (sasmodels) $ export PYTHONPATH="$SOURCE/sasview/src" 85 (sasmodels) $ cd $SOURCE/sasmodels/example 86 (sasmodels) $ bumps fit.py cylinder --preview 33 87 34 88 The fit.py model accepts up to two arguments. The first argument is the … … 38 92 both radial and tangential simultaneously, use the word "both". 39 93 40 Notes 41 ----- 42 43 cylinder.c + cylinder.py is the cylinder model with renamed variables and 44 sld scaled by 1e6 so the numbers are nicer. The model name is "cylinder" 45 46 lamellar.py is an example of a single file model with embedded C code. 94 See `bumps documentation <https://bumps.readthedocs.io/>`_ for detailed 95 instructions on running the fit. 47 96 48 97 |TravisStatus|_ -
doc/guide/plugin.rst
r81751c2 r81751c2 744 744 erf, erfc, tgamma, lgamma: **do not use** 745 745 Special functions that should be part of the standard, but are missing 746 or inaccurate on some platforms. Use sas_erf, sas_erfc andsas_gamma747 instead (see below). Note: lgamma(x) has not yet been tested.746 or inaccurate on some platforms. Use sas_erf, sas_erfc, sas_gamma 747 and sas_lgamma instead (see below). 748 748 749 749 Some non-standard constants and functions are also provided: … … 812 812 Gamma function sas_gamma\ $(x) = \Gamma(x)$. 813 813 814 The standard math function, tgamma(x) is unstable for $x < 1$814 The standard math function, tgamma(x), is unstable for $x < 1$ 815 815 on some platforms. 816 816 817 817 :code:`source = ["lib/sas_gamma.c", ...]` 818 818 (`sas_gamma.c <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_gamma.c>`_) 819 820 sas_gammaln(x): 821 log gamma function sas_gammaln\ $(x) = \log \Gamma(|x|)$. 822 823 The standard math function, lgamma(x), is incorrect for single 824 precision on some platforms. 825 826 :code:`source = ["lib/sas_gammainc.c", ...]` 827 (`sas_gammainc.c <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_gammainc.c>`_) 828 829 sas_gammainc(a, x), sas_gammaincc(a, x): 830 Incomplete gamma function 831 sas_gammainc\ $(a, x) = \int_0^x t^{a-1}e^{-t}\,dt / \Gamma(a)$ 832 and complementary incomplete gamma function 833 sas_gammaincc\ $(a, x) = \int_x^\infty t^{a-1}e^{-t}\,dt / \Gamma(a)$ 834 835 :code:`source = ["lib/sas_gammainc.c", ...]` 836 (`sas_gammainc.c <https://github.com/SasView/sasmodels/tree/master/sasmodels/models/lib/sas_gammainc.c>`_) 819 837 820 838 sas_erf(x), sas_erfc(x): … … 854 872 If $n$ = 0 or 1, it uses sas_J0($x$) or sas_J1($x$), respectively. 855 873 874 Warning: JN(n,x) can be very inaccurate (0.1%) for x not in [0.1, 100]. 875 856 876 The standard math function jn(n, x) is not available on all platforms. 857 877 … … 862 882 Sine integral Si\ $(x) = \int_0^x \tfrac{\sin t}{t}\,dt$. 863 883 884 Warning: Si(x) can be very inaccurate (0.1%) for x in [0.1, 100]. 885 864 886 This function uses Taylor series for small and large arguments: 865 887 866 For large arguments ,888 For large arguments use the following Taylor series, 867 889 868 890 .. math:: … … 872 894 - \frac{\sin(x)}{x}\left(\frac{1}{x} - \frac{3!}{x^3} + \frac{5!}{x^5} - \frac{7!}{x^7}\right) 873 895 874 For small arguments ,896 For small arguments , 875 897 876 898 .. math:: -
doc/guide/scripting.rst
rbd7630d r23df833 188 188 python kernel. Once the kernel is in hand, we can then marshal a set of 189 189 parameters into a :class:`sasmodels.details.CallDetails` object and ship it to 190 the kernel using the :func:`sansmodels.direct_model.call_kernel` function. An 191 example should help, *example/cylinder_eval.py*:: 192 193 from numpy import logspace 190 the kernel using the :func:`sansmodels.direct_model.call_kernel` function. To 191 accesses the underlying $<F(q)>$ and $<F^2(q)>$, use 192 :func:`sasmodels.direct_model.call_Fq` instead. 193 194 The following example should 195 help, *example/cylinder_eval.py*:: 196 197 from numpy import logspace, sqrt 194 198 from matplotlib import pyplot as plt 195 199 from sasmodels.core import load_model 196 from sasmodels.direct_model import call_kernel 200 from sasmodels.direct_model import call_kernel, call_Fq 197 201 198 202 model = load_model('cylinder') 199 203 q = logspace(-3, -1, 200) 200 204 kernel = model.make_kernel([q]) 201 Iq = call_kernel(kernel, dict(radius=200.)) 202 plt.loglog(q, Iq) 205 pars = {'radius': 200, 'radius_pd': 0.1, 'scale': 2} 206 Iq = call_kernel(kernel, pars) 207 F, Fsq, Reff, V, Vratio = call_Fq(kernel, pars) 208 209 plt.loglog(q, Iq, label='2 I(q)') 210 plt.loglog(q, F**2/V, label='<F(q)>^2/V') 211 plt.loglog(q, Fsq/V, label='<F^2(q)>/V') 212 plt.xlabel('q (1/A)') 213 plt.ylabel('I(q) (1/cm)') 214 plt.title('Cylinder with radius 200.') 215 plt.legend() 203 216 plt.show() 204 217 205 On windows, this can be called from the cmd prompt using sasview as:: 218 .. figure:: direct_call.png 219 220 Comparison between $I(q)$, $<F(q)>$ and $<F^2(q)>$ for cylinder model. 221 222 This compares $I(q)$ with $<F(q)>$ and $<F^2(q)>$ for a cylinder 223 with *radius=200 +/- 20* and *scale=2*. Note that *call_Fq* does not 224 include scale and background, nor does it normalize by the average volume. 225 The definition of $F = \rho V \hat F$ scaled by the contrast and 226 volume, compared to the canonical cylinder $\hat F$, with $\hat F(0) = 1$. 227 Integrating over polydispersity and orientation, the returned values are 228 $\sum_{r,w\in N(r_o, r_o/10)} \sum_\theta w F(q,r_o,\theta)\sin\theta$ and 229 $\sum_{r,w\in N(r_o, r_o/10)} \sum_\theta w F^2(q,r_o,\theta)\sin\theta$. 230 231 On windows, this example can be called from the cmd prompt using sasview as 232 as the python interpreter:: 206 233 207 234 SasViewCom example/cylinder_eval.py -
example/cylinder_eval.py
r2e66ef5 r23df833 3 3 """ 4 4 5 from numpy import logspace 5 from numpy import logspace, sqrt 6 6 from matplotlib import pyplot as plt 7 7 from sasmodels.core import load_model 8 from sasmodels.direct_model import call_kernel 8 from sasmodels.direct_model import call_kernel, call_Fq 9 9 10 10 model = load_model('cylinder') 11 11 q = logspace(-3, -1, 200) 12 12 kernel = model.make_kernel([q]) 13 Iq = call_kernel(kernel, dict(radius=200.)) 14 plt.loglog(q, Iq) 13 pars = {'radius': 200, 'radius_pd': 0.1, 'scale': 2} 14 Iq = call_kernel(kernel, pars) 15 F, Fsq, Reff, V, Vratio = call_Fq(kernel, pars) 16 plt.loglog(q, Iq, label='2 I(q)') 17 plt.loglog(q, F**2/V, label='<F(q)>^2/V') 18 plt.loglog(q, Fsq/V, label='<F^2(q)>/V') 15 19 plt.xlabel('q (1/A)') 16 plt.ylabel('I(q) ')20 plt.ylabel('I(q) (1/cm)') 17 21 plt.title('Cylinder with radius 200.') 22 plt.legend() 18 23 plt.show() -
explore/beta/sasfit_compare.py
r2a12351b r119073a 505 505 } 506 506 507 Q, IQ = load_sasfit(data_file(' richard_test.txt'))508 Q, IQSD = load_sasfit(data_file(' richard_test2.txt'))509 Q, IQBD = load_sasfit(data_file(' richard_test3.txt'))507 Q, IQ = load_sasfit(data_file('sasfit_sphere_schulz_IQD.txt')) 508 Q, IQSD = load_sasfit(data_file('sasfit_sphere_schulz_IQSD.txt')) 509 Q, IQBD = load_sasfit(data_file('sasfit_sphere_schulz_IQBD.txt')) 510 510 target = Theory(Q=Q, F1=None, F2=None, P=IQ, S=None, I=IQSD, Seff=None, Ibeta=IQBD) 511 511 actual = sphere_r(Q, norm="sasfit", **pars) … … 526 526 } 527 527 528 Q, IQ = load_sasfit(data_file(' richard_test4.txt'))529 Q, IQSD = load_sasfit(data_file(' richard_test5.txt'))530 Q, IQBD = load_sasfit(data_file(' richard_test6.txt'))528 Q, IQ = load_sasfit(data_file('sasfit_ellipsoid_shulz_IQD.txt')) 529 Q, IQSD = load_sasfit(data_file('sasfit_ellipsoid_shulz_IQSD.txt')) 530 Q, IQBD = load_sasfit(data_file('sasfit_ellipsoid_shulz_IQBD.txt')) 531 531 target = Theory(Q=Q, F1=None, F2=None, P=IQ, S=None, I=IQSD, Seff=None, Ibeta=IQBD) 532 532 actual = ellipsoid_pe(Q, norm="sasfit", **pars) -
explore/precision.py
ree60aa7 rcd28947 95 95 neg: [-100,100] 96 96 97 For arbitrary range use "start:stop:steps:scale" where scale is 98 one of log, lin, or linear. 99 97 100 *diff* is "relative", "absolute" or "none" 98 101 … … 102 105 linear = not xrange.startswith("log") 103 106 if xrange == "zoom": 104 lin_min, lin_max, lin_steps = 1000, 1010, 2000107 start, stop, steps = 1000, 1010, 2000 105 108 elif xrange == "neg": 106 lin_min, lin_max, lin_steps = -100.1, 100.1, 2000109 start, stop, steps = -100.1, 100.1, 2000 107 110 elif xrange == "linear": 108 lin_min, lin_max, lin_steps = 1, 1000, 2000109 lin_min, lin_max, lin_steps = 0.001, 2, 2000111 start, stop, steps = 1, 1000, 2000 112 start, stop, steps = 0.001, 2, 2000 110 113 elif xrange == "log": 111 log_min, log_max, log_steps = -3, 5, 400114 start, stop, steps = -3, 5, 400 112 115 elif xrange == "logq": 113 log_min, log_max, log_steps = -4, 1, 400 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 114 124 else: 115 125 raise ValueError("unknown range "+xrange) … … 121 131 # value to x in the given precision. 122 132 if linear: 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')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') 127 137 qr = [mp.mpf(float(v)) for v in qrf] 128 #qr = mp.linspace( lin_min, lin_max, lin_steps)138 #qr = mp.linspace(start, stop, steps) 129 139 else: 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')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') 134 144 qr = [mp.mpf(float(v)) for v in qrf] 135 #qr = [10**v for v in mp.linspace( log_min, log_max, log_steps)]145 #qr = [10**v for v in mp.linspace(start, stop, steps)] 136 146 137 147 target = self.call_mpmath(qr, bits=500) … … 176 186 """ 177 187 if diff == "relative": 178 err = np.array([ abs((t-a)/t) for t, a in zip(target, actual)], 'd')188 err = np.array([(abs((t-a)/t) if t != 0 else a) for t, a in zip(target, actual)], 'd') 179 189 #err = np.clip(err, 0, 1) 180 190 pylab.loglog(x, err, '-', label=label) … … 197 207 return model_info 198 208 209 # Hack to allow second parameter A in the gammainc and gammaincc functions. 210 # Create a 2-D variant of the precision test if we need to handle other two 211 # parameter functions. 212 A = 1 213 def parse_extra_pars(): 214 """ 215 Parse the command line looking for the second parameter "A=..." for the 216 gammainc/gammaincc functions. 217 """ 218 global A 219 220 A_str = str(A) 221 pop = [] 222 for k, v in enumerate(sys.argv[1:]): 223 if v.startswith("A="): 224 A_str = v[2:] 225 pop.append(k+1) 226 if pop: 227 sys.argv = [v for k, v in enumerate(sys.argv) if k not in pop] 228 A = float(A_str) 229 230 parse_extra_pars() 231 199 232 200 233 # =============== FUNCTION DEFINITIONS ================ … … 297 330 ocl_function=make_ocl("return sas_gamma(q);", "sas_gamma", ["lib/sas_gamma.c"]), 298 331 limits=(-3.1, 10), 332 ) 333 add_function( 334 name="gammaln(x)", 335 mp_function=mp.loggamma, 336 np_function=scipy.special.gammaln, 337 ocl_function=make_ocl("return sas_gammaln(q);", "sas_gammaln", ["lib/sas_gammainc.c"]), 338 #ocl_function=make_ocl("return lgamma(q);", "sas_gammaln"), 339 ) 340 add_function( 341 # Note: "a" is given as A=... on the command line via parse_extra_pars 342 name="gammainc(x)", 343 mp_function=lambda x, a=A: mp.gammainc(a, a=0, b=x)/mp.gamma(a), 344 np_function=lambda x, a=A: scipy.special.gammainc(a, x), 345 ocl_function=make_ocl("return sas_gammainc(%.15g,q);"%A, "sas_gammainc", ["lib/sas_gammainc.c"]), 346 ) 347 add_function( 348 # Note: "a" is given as A=... on the command line via parse_extra_pars 349 name="gammaincc(x)", 350 mp_function=lambda x, a=A: mp.gammainc(a, a=x, b=mp.inf)/mp.gamma(a), 351 np_function=lambda x, a=A: scipy.special.gammaincc(a, x), 352 ocl_function=make_ocl("return sas_gammaincc(%.15g,q);"%A, "sas_gammaincc", ["lib/sas_gammainc.c"]), 299 353 ) 300 354 add_function( … … 465 519 lanczos_gamma = """\ 466 520 const double coeff[] = { 467 76.18009172947146, 468 24.01409824083091, 521 76.18009172947146, -86.50532032941677, 522 24.01409824083091, -1.231739572450155, 469 523 0.1208650973866179e-2,-0.5395239384953e-5 470 524 }; … … 477 531 """ 478 532 add_function( 479 name="log 533 name="loggamma(x)", 480 534 mp_function=mp.loggamma, 481 535 np_function=scipy.special.gammaln, … … 601 655 602 656 ALL_FUNCTIONS = set(FUNCTIONS.keys()) 603 ALL_FUNCTIONS.discard("loggamma") # OCL version not ready yet657 ALL_FUNCTIONS.discard("loggamma") # use cephes-based gammaln instead 604 658 ALL_FUNCTIONS.discard("3j1/x:taylor") 605 659 ALL_FUNCTIONS.discard("3j1/x:trig") … … 617 671 -r indicates that the relative error should be plotted (default), 618 672 -x<range> indicates the steps in x, where <range> is one of the following 619 log indicates log stepping in [10^-3, 10^5] (default) 620 logq indicates log stepping in [10^-4, 10^1] 621 linear indicates linear stepping in [1, 1000] 622 zoom indicates linear stepping in [1000, 1010] 623 neg indicates linear stepping in [-100.1, 100.1] 624 and name is "all" or one of: 673 log indicates log stepping in [10^-3, 10^5] (default) 674 logq indicates log stepping in [10^-4, 10^1] 675 linear indicates linear stepping in [1, 1000] 676 zoom indicates linear stepping in [1000, 1010] 677 neg indicates linear stepping in [-100.1, 100.1] 678 start:stop:n[:stepping] indicates an n-step plot in [start, stop] 679 or [10^start, 10^stop] if stepping is "log" (default n=400) 680 Some functions (notably gammainc/gammaincc) have an additional parameter A 681 which can be set from the command line as A=value. Default is A=1. 682 683 Name is one of: 625 684 """+names) 626 685 sys.exit(1) -
sasmodels/compare.py
r4de14584 r4de14584 1152 1152 'rel_err' : True, 1153 1153 'explore' : False, 1154 'use_demo' : True,1154 'use_demo' : False, 1155 1155 'zero' : False, 1156 1156 'html' : False, -
sasmodels/direct_model.py
r304c775 r5024a56 32 32 from .details import make_kernel_args, dispersion_mesh 33 33 from .modelinfo import DEFAULT_BACKGROUND 34 from .product import RADIUS_MODE_ID 34 35 35 36 # pylint: disable=unused-import … … 67 68 # type: (Kernel, ParameterSet, float, bool) -> np.ndarray 68 69 """ 69 Like :func:`call_kernel`, but returning F, F^2, R_eff, V, V_form/V_shell. 70 """ 71 R_eff_type = int(pars.pop('radius_effective_type', 1.0)) 70 Like :func:`call_kernel`, but returning F, F^2, R_eff, V_shell, V_form/V_shell. 71 72 For solid objects V_shell is equal to V_form and the volume ratio is 1. 73 74 Use parameter *radius_effective_mode* to select the effective radius 75 calculation. 76 """ 77 R_eff_type = int(pars.pop(RADIUS_MODE_ID, 1.0)) 72 78 mesh = get_mesh(calculator.info, pars, dim=calculator.dim, mono=mono) 73 79 #print("pars", list(zip(*mesh))[0]) … … 76 82 return calculator.Fq(call_details, values, cutoff, is_magnetic, R_eff_type) 77 83 78 def call_profile(model_info, **pars):79 # type: (ModelInfo, ...) -> Tuple[np.ndarray, np.ndarray, Tuple[str, str]]84 def call_profile(model_info, pars=None): 85 # type: (ModelInfo, ParameterSet) -> Tuple[np.ndarray, np.ndarray, Tuple[str, str]] 80 86 """ 81 87 Returns the profile *x, y, (xlabel, ylabel)* representing the model. 82 88 """ 89 if pars is None: 90 pars = {} 83 91 args = {} 84 92 for p in model_info.parameters.kernel_parameters: … … 324 332 325 333 # Need to pull background out of resolution for multiple scattering 326 background = pars.get('background', DEFAULT_BACKGROUND) 334 default_background = self._model.info.parameters.common_parameters[1].default 335 background = pars.get('background', default_background) 327 336 pars = pars.copy() 328 337 pars['background'] = 0. … … 377 386 Generate a plottable profile. 378 387 """ 379 return call_profile(self.model.info, **pars)388 return call_profile(self.model.info, pars) 380 389 381 390 def main(): -
sasmodels/generate.py
r39a06c9 rcd28947 703 703 """ 704 704 for code in source: 705 m = _FQ_PATTERN.search(code) 706 if m is not None: 705 if _FQ_PATTERN.search(code) is not None: 707 706 return True 708 707 return False … … 712 711 # type: (List[str]) -> bool 713 712 """ 714 Return True if C source defines " void Fq(".713 Return True if C source defines "double shell_volume(". 715 714 """ 716 715 for code in source: 717 m = _SHELL_VOLUME_PATTERN.search(code) 718 if m is not None: 716 if _SHELL_VOLUME_PATTERN.search(code) is not None: 719 717 return True 720 718 return False … … 1008 1006 pars = model_info.parameters.kernel_parameters 1009 1007 else: 1010 pars = model_info.parameters.COMMON + model_info.parameters.kernel_parameters 1008 pars = (model_info.parameters.common_parameters 1009 + model_info.parameters.kernel_parameters) 1011 1010 partable = make_partable(pars) 1012 1011 subst = dict(id=model_info.id.replace('_', '-'), -
sasmodels/jitter.py
r1198f90 r7d97437 15 15 pass 16 16 17 import matplotlib as mpl 17 18 import matplotlib.pyplot as plt 18 19 from matplotlib.widgets import Slider … … 746 747 pass 747 748 748 axcolor = 'lightgoldenrodyellow' 749 # CRUFT: use axisbg instead of facecolor for matplotlib<2 750 facecolor_prop = 'facecolor' if mpl.__version__ > '2' else 'axisbg' 751 props = {facecolor_prop: 'lightgoldenrodyellow'} 749 752 750 753 ## add control widgets to plot 751 axes_theta = plt.axes([0.1, 0.15, 0.45, 0.04], axisbg=axcolor)752 axes_phi = plt.axes([0.1, 0.1, 0.45, 0.04], axisbg=axcolor)753 axes_psi = plt.axes([0.1, 0.05, 0.45, 0.04], axisbg=axcolor)754 axes_theta = plt.axes([0.1, 0.15, 0.45, 0.04], **props) 755 axes_phi = plt.axes([0.1, 0.1, 0.45, 0.04], **props) 756 axes_psi = plt.axes([0.1, 0.05, 0.45, 0.04], **props) 754 757 stheta = Slider(axes_theta, 'Theta', -90, 90, valinit=theta) 755 758 sphi = Slider(axes_phi, 'Phi', -180, 180, valinit=phi) 756 759 spsi = Slider(axes_psi, 'Psi', -180, 180, valinit=psi) 757 760 758 axes_dtheta = plt.axes([0.75, 0.15, 0.15, 0.04], axisbg=axcolor)759 axes_dphi = plt.axes([0.75, 0.1, 0.15, 0.04], axisbg=axcolor)760 axes_dpsi = plt.axes([0.75, 0.05, 0.15, 0.04], axisbg=axcolor)761 axes_dtheta = plt.axes([0.75, 0.15, 0.15, 0.04], **props) 762 axes_dphi = plt.axes([0.75, 0.1, 0.15, 0.04], **props) 763 axes_dpsi = plt.axes([0.75, 0.05, 0.15, 0.04], **props) 761 764 # Note: using ridiculous definition of rectangle distribution, whose width 762 765 # in sasmodels is sqrt(3) times the given width. Divide by sqrt(3) to keep -
sasmodels/kernel.py
re44432d rcd28947 133 133 nout = 2 if self.info.have_Fq and self.dim == '1d' else 1 134 134 total_weight = self.result[nout*self.q_input.nq + 0] 135 # Note: total_weight = sum(weight > cutoff), with cutoff >= 0, so it 136 # is okay to test directly against zero. If weight is zero then I(q), 137 # etc. must also be zero. 135 138 if total_weight == 0.: 136 139 total_weight = 1. -
sasmodels/kernelcl.py
rf872fd1 rf872fd1 58 58 import time 59 59 60 try: 61 from time import perf_counter as clock 62 except ImportError: # CRUFT: python < 3.3 63 import sys 64 if sys.platform.count("darwin") > 0: 65 from time import time as clock 66 else: 67 from time import clock 68 60 69 import numpy as np # type: ignore 61 62 70 63 71 # Attempt to setup opencl. This may fail if the pyopencl package is not … … 611 619 #Call kernel and retrieve results 612 620 wait_for = None 613 last_nap = time.clock()621 last_nap = clock() 614 622 step = 1000000//self.q_input.nq + 1 615 623 for start in range(0, call_details.num_eval, step): … … 622 630 # Allow other processes to run 623 631 wait_for[0].wait() 624 current_time = time.clock()632 current_time = clock() 625 633 if current_time - last_nap > 0.5: 626 634 time.sleep(0.001) -
sasmodels/kernelpy.py
re44432d re44432d 42 42 self.info = model_info 43 43 self.dtype = np.dtype('d') 44 logger.info("make python model " + self.info.name) 44 45 45 46 def make_kernel(self, q_vectors): -
sasmodels/model_test.py
r7b5898f r5024a56 48 48 import sys 49 49 import unittest 50 import traceback 50 51 51 52 try: … … 77 78 # pylint: enable=unused-import 78 79 79 80 80 def make_suite(loaders, models): 81 81 # type: (List[str], List[str]) -> unittest.TestSuite … … 88 88 *models* is the list of models to test, or *["all"]* to test all models. 89 89 """ 90 ModelTestCase = _hide_model_case_from_nose()91 90 suite = unittest.TestSuite() 92 91 … … 97 96 skip = [] 98 97 for model_name in models: 99 if model_name in skip: 100 continue 101 model_info = load_model_info(model_name) 102 103 #print('------') 104 #print('found tests in', model_name) 105 #print('------') 106 107 # if ispy then use the dll loader to call pykernel 108 # don't try to call cl kernel since it will not be 109 # available in some environmentes. 110 is_py = callable(model_info.Iq) 111 112 # Some OpenCL drivers seem to be flaky, and are not producing the 113 # expected result. Since we don't have known test values yet for 114 # all of our models, we are instead going to compare the results 115 # for the 'smoke test' (that is, evaluation at q=0.1 for the default 116 # parameters just to see that the model runs to completion) between 117 # the OpenCL and the DLL. To do this, we define a 'stash' which is 118 # shared between OpenCL and DLL tests. This is just a list. If the 119 # list is empty (which it will be when DLL runs, if the DLL runs 120 # first), then the results are appended to the list. If the list 121 # is not empty (which it will be when OpenCL runs second), the results 122 # are compared to the results stored in the first element of the list. 123 # This is a horrible stateful hack which only makes sense because the 124 # test suite is thrown away after being run once. 125 stash = [] 126 127 if is_py: # kernel implemented in python 128 test_name = "%s-python"%model_name 129 test_method_name = "test_%s_python" % model_info.id 98 if model_name not in skip: 99 model_info = load_model_info(model_name) 100 _add_model_to_suite(loaders, suite, model_info) 101 102 return suite 103 104 def _add_model_to_suite(loaders, suite, model_info): 105 ModelTestCase = _hide_model_case_from_nose() 106 107 #print('------') 108 #print('found tests in', model_name) 109 #print('------') 110 111 # if ispy then use the dll loader to call pykernel 112 # don't try to call cl kernel since it will not be 113 # available in some environmentes. 114 is_py = callable(model_info.Iq) 115 116 # Some OpenCL drivers seem to be flaky, and are not producing the 117 # expected result. Since we don't have known test values yet for 118 # all of our models, we are instead going to compare the results 119 # for the 'smoke test' (that is, evaluation at q=0.1 for the default 120 # parameters just to see that the model runs to completion) between 121 # the OpenCL and the DLL. To do this, we define a 'stash' which is 122 # shared between OpenCL and DLL tests. This is just a list. If the 123 # list is empty (which it will be when DLL runs, if the DLL runs 124 # first), then the results are appended to the list. If the list 125 # is not empty (which it will be when OpenCL runs second), the results 126 # are compared to the results stored in the first element of the list. 127 # This is a horrible stateful hack which only makes sense because the 128 # test suite is thrown away after being run once. 129 stash = [] 130 131 if is_py: # kernel implemented in python 132 test_name = "%s-python"%model_info.name 133 test_method_name = "test_%s_python" % model_info.id 134 test = ModelTestCase(test_name, model_info, 135 test_method_name, 136 platform="dll", # so that 137 dtype="double", 138 stash=stash) 139 suite.addTest(test) 140 else: # kernel implemented in C 141 142 # test using dll if desired 143 if 'dll' in loaders or not use_opencl(): 144 test_name = "%s-dll"%model_info.name 145 test_method_name = "test_%s_dll" % model_info.id 130 146 test = ModelTestCase(test_name, model_info, 131 test_method_name,132 platform="dll", # so that133 dtype="double",134 stash=stash)147 test_method_name, 148 platform="dll", 149 dtype="double", 150 stash=stash) 135 151 suite.addTest(test) 136 else: # kernel implemented in C 137 138 # test using dll if desired 139 if 'dll' in loaders: 140 test_name = "%s-dll"%model_name 141 test_method_name = "test_%s_dll" % model_info.id 142 test = ModelTestCase(test_name, model_info, 143 test_method_name, 144 platform="dll", 145 dtype="double", 146 stash=stash) 147 suite.addTest(test) 148 149 # test using opencl if desired and available 150 if 'opencl' in loaders and use_opencl(): 151 test_name = "%s-opencl"%model_name 152 test_method_name = "test_%s_opencl" % model_info.id 153 # Using dtype=None so that the models that are only 154 # correct for double precision are not tested using 155 # single precision. The choice is determined by the 156 # presence of *single=False* in the model file. 157 test = ModelTestCase(test_name, model_info, 158 test_method_name, 159 platform="ocl", dtype=None, 160 stash=stash) 161 #print("defining", test_name) 162 suite.addTest(test) 163 164 # test using cuda if desired and available 165 if 'cuda' in loaders and use_cuda(): 166 test_name = "%s-cuda"%model_name 167 test_method_name = "test_%s_cuda" % model_info.id 168 # Using dtype=None so that the models that are only 169 # correct for double precision are not tested using 170 # single precision. The choice is determined by the 171 # presence of *single=False* in the model file. 172 test = ModelTestCase(test_name, model_info, 173 test_method_name, 174 platform="cuda", dtype=None, 175 stash=stash) 176 #print("defining", test_name) 177 suite.addTest(test) 178 179 return suite 152 153 # test using opencl if desired and available 154 if 'opencl' in loaders and use_opencl(): 155 test_name = "%s-opencl"%model_info.name 156 test_method_name = "test_%s_opencl" % model_info.id 157 # Using dtype=None so that the models that are only 158 # correct for double precision are not tested using 159 # single precision. The choice is determined by the 160 # presence of *single=False* in the model file. 161 test = ModelTestCase(test_name, model_info, 162 test_method_name, 163 platform="ocl", dtype=None, 164 stash=stash) 165 #print("defining", test_name) 166 suite.addTest(test) 167 168 # test using cuda if desired and available 169 if 'cuda' in loaders and use_cuda(): 170 test_name = "%s-cuda"%model_name 171 test_method_name = "test_%s_cuda" % model_info.id 172 # Using dtype=None so that the models that are only 173 # correct for double precision are not tested using 174 # single precision. The choice is determined by the 175 # presence of *single=False* in the model file. 176 test = ModelTestCase(test_name, model_info, 177 test_method_name, 178 platform="cuda", dtype=None, 179 stash=stash) 180 #print("defining", test_name) 181 suite.addTest(test) 182 180 183 181 184 def _hide_model_case_from_nose(): … … 384 387 for par in sorted(pars.keys()): 385 388 # special handling of R_eff mode, which is not a usual parameter 386 if par == 'radius_effective_type':389 if par == product.RADIUS_MODE_ID: 387 390 continue 388 391 parts = par.split('_pd') … … 404 407 return abs(target-actual)/shift < 1.5*10**-digits 405 408 406 def run_one(model): 407 # type: (str) -> str 408 """ 409 Run the tests for a single model, printing the results to stdout. 410 411 *model* can by a python file, which is handy for checking user defined 412 plugin models. 409 # CRUFT: old interface; should be deprecated and removed 410 def run_one(model_name): 411 # msg = "use check_model(model_info) rather than run_one(model_name)" 412 # warnings.warn(msg, category=DeprecationWarning, stacklevel=2) 413 try: 414 model_info = load_model_info(model_name) 415 except Exception: 416 output = traceback.format_exc() 417 return output 418 419 success, output = check_model(model_info) 420 return output 421 422 def check_model(model_info): 423 # type: (ModelInfo) -> str 424 """ 425 Run the tests for a single model, capturing the output. 426 427 Returns success status and the output string. 413 428 """ 414 429 # Note that running main() directly did not work from within the … … 424 439 425 440 # Build a test suite containing just the model 426 loader = 'opencl' if use_opencl() else 'cuda' if use_cuda() else 'dll' 427 models = [model] 428 try: 429 suite = make_suite([loader], models) 430 except Exception: 431 import traceback 432 stream.writeln(traceback.format_exc()) 433 return 441 loaders = ['opencl' if use_opencl() else 'cuda' if use_cuda() else 'dll'] 442 suite = unittest.TestSuite() 443 _add_model_to_suite(loaders, suite, model_info) 434 444 435 445 # Warn if there are no user defined tests. … … 446 456 for test in suite: 447 457 if not test.info.tests: 448 stream.writeln("Note: %s has no user defined tests."%model )458 stream.writeln("Note: %s has no user defined tests."%model_info.name) 449 459 break 450 460 else: … … 462 472 output = stream.getvalue() 463 473 stream.close() 464 return output474 return result.wasSuccessful(), output 465 475 466 476 -
sasmodels/modelinfo.py
r39a06c9 r39a06c9 404 404 parameters counted as n individual parameters p1, p2, ... 405 405 406 * *common_parameters* is the list of common parameters, with a unique 407 copy for each model so that structure factors can have a default 408 background of 0.0. 409 406 410 * *call_parameters* is the complete list of parameters to the kernel, 407 411 including scale and background, with vector parameters recorded as … … 416 420 parameters don't use vector notation, and instead use p1, p2, ... 417 421 """ 418 # scale and background are implicit parameters419 COMMON = [Parameter(*p) for p in COMMON_PARAMETERS]420 421 422 def __init__(self, parameters): 422 423 # type: (List[Parameter]) -> None 424 425 # scale and background are implicit parameters 426 # Need them to be unique to each model in case they have different 427 # properties, such as default=0.0 for structure factor backgrounds. 428 self.common_parameters = [Parameter(*p) for p in COMMON_PARAMETERS] 429 423 430 self.kernel_parameters = parameters 424 431 self._set_vector_lengths() … … 468 475 if p.polydisperse and p.type not in ('orientation', 'magnetic')) 469 476 self.pd_2d = set(p.name for p in self.call_parameters if p.polydisperse) 477 478 def set_zero_background(self): 479 """ 480 Set the default background to zero for this model. This is done for 481 structure factor models. 482 """ 483 # type: () -> None 484 # Make sure background is the second common parameter. 485 assert self.common_parameters[1].id == "background" 486 self.common_parameters[1].default = 0.0 487 self.defaults = self._get_defaults() 470 488 471 489 def check_angles(self): … … 567 585 def _get_call_parameters(self): 568 586 # type: () -> List[Parameter] 569 full_list = self. COMMON[:]587 full_list = self.common_parameters[:] 570 588 for p in self.kernel_parameters: 571 589 if p.length == 1: … … 670 688 671 689 # Gather the user parameters in order 672 result = control + self. COMMON690 result = control + self.common_parameters 673 691 for p in self.kernel_parameters: 674 692 if not is2d and p.type in ('orientation', 'magnetic'): … … 770 788 771 789 info = ModelInfo() 790 791 # Build the parameter table 772 792 #print("make parameter table", kernel_module.parameters) 773 793 parameters = make_parameter_table(getattr(kernel_module, 'parameters', [])) 794 795 # background defaults to zero for structure factor models 796 structure_factor = getattr(kernel_module, 'structure_factor', False) 797 if structure_factor: 798 parameters.set_zero_background() 799 800 # TODO: remove demo parameters 801 # The plots in the docs are generated from the model default values. 802 # Sascomp set parameters from the command line, and so doesn't need 803 # demo values for testing. 774 804 demo = expand_pars(parameters, getattr(kernel_module, 'demo', None)) 805 775 806 filename = abspath(kernel_module.__file__).replace('.pyc', '.py') 776 807 kernel_id = splitext(basename(filename))[0] -
sasmodels/models/barbell.c
rd42dd4a r99658f6 63 63 64 64 static double 65 radius_from_excluded_volume(double radius_bell, double radius, double length) 66 { 67 const double hdist = sqrt(square(radius_bell) - square(radius)); 68 const double length_tot = length + 2.0*(hdist+ radius); 69 return 0.5*cbrt(0.75*radius_bell*(2.0*radius_bell*length_tot + (radius_bell + length_tot)*(M_PI*radius_bell + length_tot))); 70 } 71 72 static double 65 73 radius_from_volume(double radius_bell, double radius, double length) 66 74 { … … 81 89 switch (mode) { 82 90 default: 83 case 1: // equivalent sphere 91 case 1: // equivalent cylinder excluded volume 92 return radius_from_excluded_volume(radius_bell, radius , length); 93 case 2: // equivalent volume sphere 84 94 return radius_from_volume(radius_bell, radius , length); 85 case 2: // radius95 case 3: // radius 86 96 return radius; 87 case 3: // half length97 case 4: // half length 88 98 return 0.5*length; 89 case 4: // half total length99 case 5: // half total length 90 100 return radius_from_totallength(radius_bell,radius,length); 91 101 } -
sasmodels/models/barbell.py
ree60aa7 r99658f6 79 79 .. [#] H Kaya and N R deSouza, *J. Appl. Cryst.*, 37 (2004) 508-509 (addenda 80 80 and errata) 81 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 81 82 82 83 Authorship and Verification … … 116 117 117 118 source = ["lib/polevl.c", "lib/sas_J1.c", "lib/gauss76.c", "barbell.c"] 118 have_Fq = True 119 have_Fq = True 119 120 effective_radius_type = [ 120 "equivalent sphere", "radius", "half length", "half total length",121 "equivalent cylinder excluded volume","equivalent volume sphere", "radius", "half length", "half total length", 121 122 ] 122 123 -
sasmodels/models/capped_cylinder.c
rd42dd4a r99658f6 85 85 86 86 static double 87 radius_from_excluded_volume(double radius, double radius_cap, double length) 88 { 89 const double hc = radius_cap - sqrt(radius_cap*radius_cap - radius*radius); 90 const double length_tot = length + 2.0*hc; 91 return 0.5*cbrt(0.75*radius*(2.0*radius*length_tot + (radius + length_tot)*(M_PI*radius + length_tot))); 92 } 93 94 static double 87 95 radius_from_volume(double radius, double radius_cap, double length) 88 96 { … … 103 111 switch (mode) { 104 112 default: 105 case 1: // equivalent sphere 113 case 1: // equivalent cylinder excluded volume 114 return radius_from_excluded_volume(radius, radius_cap, length); 115 case 2: // equivalent volume sphere 106 116 return radius_from_volume(radius, radius_cap, length); 107 case 2: // radius117 case 3: // radius 108 118 return radius; 109 case 3: // half length119 case 4: // half length 110 120 return 0.5*length; 111 case 4: // half total length121 case 5: // half total length 112 122 return radius_from_totallength(radius, radius_cap,length); 113 123 } -
sasmodels/models/capped_cylinder.py
ree60aa7 r99658f6 82 82 .. [#] H Kaya and N-R deSouza, *J. Appl. Cryst.*, 37 (2004) 508-509 (addenda 83 83 and errata) 84 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 84 85 85 86 Authorship and Verification … … 138 139 have_Fq = True 139 140 effective_radius_type = [ 140 "equivalent sphere", "radius", "half length", "half total length",141 "equivalent cylinder excluded volume", "equivalent volume sphere", "radius", "half length", "half total length", 141 142 ] 142 143 -
sasmodels/models/core_shell_bicelle.c
rd42dd4a r99658f6 37 37 38 38 static double 39 radius_from_excluded_volume(double radius, double thick_rim, double thick_face, double length) 40 { 41 const double radius_tot = radius + thick_rim; 42 const double length_tot = length + 2.0*thick_face; 43 return 0.5*cbrt(0.75*radius_tot*(2.0*radius_tot*length_tot + (radius_tot + length_tot)*(M_PI*radius_tot + length_tot))); 44 } 45 46 static double 39 47 radius_from_volume(double radius, double thick_rim, double thick_face, double length) 40 48 { … … 56 64 switch (mode) { 57 65 default: 58 case 1: // equivalent sphere 66 case 1: // equivalent cylinder excluded volume 67 return radius_from_excluded_volume(radius, thick_rim, thick_face, length); 68 case 2: // equivalent sphere 59 69 return radius_from_volume(radius, thick_rim, thick_face, length); 60 case 2: // outer rim radius70 case 3: // outer rim radius 61 71 return radius + thick_rim; 62 case 3: // half outer thickness72 case 4: // half outer thickness 63 73 return 0.5*length + thick_face; 64 case 4: // half diagonal74 case 5: // half diagonal 65 75 return radius_from_diagonal(radius,thick_rim,thick_face,length); 66 76 } -
sasmodels/models/core_shell_bicelle.py
ree60aa7 r99658f6 89 89 from Proquest <http://search.proquest.com/docview/304915826?accountid 90 90 =26379>`_ 91 92 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 91 93 92 94 Authorship and Verification … … 156 158 have_Fq = True 157 159 effective_radius_type = [ 158 "e quivalentsphere", "outer rim radius",160 "excluded volume","equivalent volume sphere", "outer rim radius", 159 161 "half outer thickness", "half diagonal", 160 162 ] -
sasmodels/models/core_shell_bicelle_elliptical.c
rd42dd4a r99658f6 8 8 { 9 9 return M_PI*(r_minor+thick_rim)*(r_minor*x_core+thick_rim)*(length+2.0*thick_face); 10 } 11 12 static double 13 radius_from_excluded_volume(double r_minor, double x_core, double thick_rim, double thick_face, double length) 14 { 15 const double r_equiv = sqrt((r_minor + thick_rim)*(r_minor*x_core + thick_rim)); 16 const double length_tot = length + 2.0*thick_face; 17 return 0.5*cbrt(0.75*r_equiv*(2.0*r_equiv*length_tot + (r_equiv + length_tot)*(M_PI*r_equiv + length_tot))); 10 18 } 11 19 … … 31 39 switch (mode) { 32 40 default: 33 case 1: // equivalent sphere 41 case 1: // equivalent cylinder excluded volume 42 return radius_from_excluded_volume(r_minor, x_core, thick_rim, thick_face, length); 43 case 2: // equivalent volume sphere 34 44 return radius_from_volume(r_minor, x_core, thick_rim, thick_face, length); 35 case 2: // outer rim average radius45 case 3: // outer rim average radius 36 46 return 0.5*r_minor*(1.0 + x_core) + thick_rim; 37 case 3: // outer rim min radius47 case 4: // outer rim min radius 38 48 return (x_core < 1.0 ? x_core*r_minor+thick_rim : r_minor+thick_rim); 39 case 4: // outer max radius49 case 5: // outer max radius 40 50 return (x_core > 1.0 ? x_core*r_minor+thick_rim : r_minor+thick_rim); 41 case 5: // half outer thickness51 case 6: // half outer thickness 42 52 return 0.5*length + thick_face; 43 case 6: // half diagonal53 case 7: // half diagonal 44 54 return radius_from_diagonal(r_minor,x_core,thick_rim,thick_face,length); 45 55 } -
sasmodels/models/core_shell_bicelle_elliptical.py
r304c775 r99658f6 100 100 101 101 .. [#] 102 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 102 103 103 104 Authorship and Verification … … 148 149 have_Fq = True 149 150 effective_radius_type = [ 150 "equivalent sphere", "outer rim average radius", "outer rim min radius",151 "equivalent cylinder excluded volume", "equivalent volume sphere", "outer rim average radius", "outer rim min radius", 151 152 "outer max radius", "half outer thickness", "half diagonal", 152 153 ] -
sasmodels/models/core_shell_bicelle_elliptical_belt_rough.c
rd42dd4a r99658f6 9 9 return M_PI*( (r_minor + thick_rim)*(r_minor*x_core + thick_rim)* length + 10 10 square(r_minor)*x_core*2.0*thick_face ); 11 } 12 13 static double 14 radius_from_excluded_volume(double r_minor, double x_core, double thick_rim, double thick_face, double length) 15 { 16 const double r_equiv = sqrt((r_minor + thick_rim)*(r_minor*x_core + thick_rim)); 17 const double length_tot = length + 2.0*thick_face; 18 return 0.5*cbrt(0.75*r_equiv*(2.0*r_equiv*length_tot + (r_equiv + length_tot)*(M_PI*r_equiv + length_tot))); 11 19 } 12 20 … … 32 40 switch (mode) { 33 41 default: 34 case 1: // equivalent sphere 42 case 1: // equivalent cylinder excluded volume 43 return radius_from_excluded_volume(r_minor, x_core, thick_rim, thick_face, length); 44 case 2: // equivalent sphere 35 45 return radius_from_volume(r_minor, x_core, thick_rim, thick_face, length); 36 case 2: // outer rim average radius46 case 3: // outer rim average radius 37 47 return 0.5*r_minor*(1.0 + x_core) + thick_rim; 38 case 3: // outer rim min radius48 case 4: // outer rim min radius 39 49 return (x_core < 1.0 ? x_core*r_minor+thick_rim : r_minor+thick_rim); 40 case 4: // outer max radius50 case 5: // outer max radius 41 51 return (x_core > 1.0 ? x_core*r_minor+thick_rim : r_minor+thick_rim); 42 case 5: // half outer thickness52 case 6: // half outer thickness 43 53 return 0.5*length + thick_face; 44 case 6: // half diagonal (this ignores the missing "corners", so may give unexpected answer if thick_face54 case 7: // half diagonal (this ignores the missing "corners", so may give unexpected answer if thick_face 45 55 // or thick_rim is extremely large) 46 56 return radius_from_diagonal(r_minor,x_core,thick_rim,thick_face,length); -
sasmodels/models/core_shell_bicelle_elliptical_belt_rough.py
r304c775 r99658f6 112 112 113 113 .. [#] 114 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 114 115 115 116 Authorship and Verification … … 161 162 have_Fq = True 162 163 effective_radius_type = [ 163 "equivalent sphere", "outer rim average radius", "outer rim min radius",164 "equivalent cylinder excluded volume", "equivalent volume sphere", "outer rim average radius", "outer rim min radius", 164 165 "outer max radius", "half outer thickness", "half diagonal", 165 166 ] -
sasmodels/models/core_shell_cylinder.c
rd42dd4a r99658f6 11 11 { 12 12 return M_PI*square(radius+thickness)*(length+2.0*thickness); 13 } 14 15 static double 16 radius_from_excluded_volume(double radius, double thickness, double length) 17 { 18 const double radius_tot = radius + thickness; 19 const double length_tot = length + 2.0*thickness; 20 return 0.5*cbrt(0.75*radius_tot*(2.0*radius_tot*length_tot + (radius_tot + length_tot)*(M_PI*radius_tot + length_tot))); 13 21 } 14 22 … … 33 41 switch (mode) { 34 42 default: 35 case 1: // equivalent sphere 43 case 1: //cylinder excluded volume 44 return radius_from_excluded_volume(radius, thickness, length); 45 case 2: // equivalent volume sphere 36 46 return radius_from_volume(radius, thickness, length); 37 case 2: // outer radius47 case 3: // outer radius 38 48 return radius + thickness; 39 case 3: // half outer length49 case 4: // half outer length 40 50 return 0.5*length + thickness; 41 case 4: // half min outer length51 case 5: // half min outer length 42 52 return (radius < 0.5*length ? radius + thickness : 0.5*length + thickness); 43 case 5: // half max outer length53 case 6: // half max outer length 44 54 return (radius > 0.5*length ? radius + thickness : 0.5*length + thickness); 45 case 6: // half outer diagonal55 case 7: // half outer diagonal 46 56 return radius_from_diagonal(radius,thickness,length); 47 57 } -
sasmodels/models/core_shell_cylinder.py
ree60aa7 r99658f6 70 70 1445-1452 71 71 .. [#kline] S R Kline, *J Appl. Cryst.*, 39 (2006) 895 72 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 72 73 73 74 Authorship and Verification … … 133 134 have_Fq = True 134 135 effective_radius_type = [ 135 "equivalent sphere", "outer radius", "half outer length", 136 "half min outer dimension", "half max outer dimension", 137 "half outer diagonal", 136 "excluded volume", "equivalent volume sphere", "outer radius", "half outer length", 137 "half min outer dimension", "half max outer dimension", "half outer diagonal", 138 138 ] 139 139 -
sasmodels/models/core_shell_ellipsoid.c
rd42dd4a r99658f6 75 75 switch (mode) { 76 76 default: 77 case 1: // equivalent sphere 77 case 1: // average outer curvature 78 return radius_from_curvature(radius_equat_core, x_core, thick_shell, x_polar_shell); 79 case 2: // equivalent volume sphere 78 80 return radius_from_volume(radius_equat_core, x_core, thick_shell, x_polar_shell); 79 case 2: // average outer curvature80 return radius_from_curvature(radius_equat_core, x_core, thick_shell, x_polar_shell);81 81 case 3: // min outer radius 82 82 return (radius_polar_tot < radius_equat_tot ? radius_polar_tot : radius_equat_tot); -
sasmodels/models/core_shell_ellipsoid.py
ree60aa7 r99658f6 147 147 have_Fq = True 148 148 effective_radius_type = [ 149 " equivalent sphere", "average outer curvature",149 "average outer curvature", "equivalent volume sphere", 150 150 "min outer radius", "max outer radius", 151 151 ] -
sasmodels/models/core_shell_parallelepiped.c
rd42dd4a r99658f6 28 28 29 29 static double 30 radius_from_excluded_volume(double length_a, double length_b, double length_c, 31 double thick_rim_a, double thick_rim_b, double thick_rim_c) 32 { 33 double r_equiv, length; 34 double lengths[3] = {length_a+thick_rim_a, length_b+thick_rim_b, length_c+thick_rim_c}; 35 double lengthmax = fmax(lengths[0],fmax(lengths[1],lengths[2])); 36 double length_1 = lengthmax; 37 double length_2 = lengthmax; 38 double length_3 = lengthmax; 39 40 for(int ilen=0; ilen<3; ilen++) { 41 if (lengths[ilen] < length_1) { 42 length_2 = length_1; 43 length_1 = lengths[ilen]; 44 } else { 45 if (lengths[ilen] < length_2) { 46 length_2 = lengths[ilen]; 47 } 48 } 49 } 50 if(length_2-length_1 > length_3-length_2) { 51 r_equiv = sqrt(length_2*length_3/M_PI); 52 length = length_1; 53 } else { 54 r_equiv = sqrt(length_1*length_2/M_PI); 55 length = length_3; 56 } 57 58 return 0.5*cbrt(0.75*r_equiv*(2.0*r_equiv*length + (r_equiv + length)*(M_PI*r_equiv + length))); 59 } 60 61 static double 30 62 radius_from_volume(double length_a, double length_b, double length_c, 31 63 double thick_rim_a, double thick_rim_b, double thick_rim_c) … … 48 80 switch (mode) { 49 81 default: 50 case 1: // equivalent sphere 82 case 1: // equivalent cylinder excluded volume 83 return radius_from_excluded_volume(length_a, length_b, length_c, thick_rim_a, thick_rim_b, thick_rim_c); 84 case 2: // equivalent volume sphere 51 85 return radius_from_volume(length_a, length_b, length_c, thick_rim_a, thick_rim_b, thick_rim_c); 52 case 2: // half outer length a86 case 3: // half outer length a 53 87 return 0.5 * length_a + thick_rim_a; 54 case 3: // half outer length b88 case 4: // half outer length b 55 89 return 0.5 * length_b + thick_rim_b; 56 case 4: // half outer length c90 case 5: // half outer length c 57 91 return 0.5 * length_c + thick_rim_c; 58 case 5: // equivalent circular cross-section92 case 6: // equivalent circular cross-section 59 93 return radius_from_crosssection(length_a, length_b, thick_rim_a, thick_rim_b); 60 case 6: // half outer ab diagonal94 case 7: // half outer ab diagonal 61 95 return 0.5*sqrt(square(length_a+ 2.0*thick_rim_a) + square(length_b+ 2.0*thick_rim_b)); 62 case 7: // half outer diagonal96 case 8: // half outer diagonal 63 97 return 0.5*sqrt(square(length_a+ 2.0*thick_rim_a) + square(length_b+ 2.0*thick_rim_b) + square(length_c+ 2.0*thick_rim_c)); 64 98 } -
sasmodels/models/core_shell_parallelepiped.py
ree60aa7 r99658f6 173 173 from Proquest <http://search.proquest.com/docview/304915826?accountid 174 174 =26379>`_ 175 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 175 176 176 177 Authorship and Verification … … 228 229 have_Fq = True 229 230 effective_radius_type = [ 230 "equivalent sphere", 231 "equivalent cylinder excluded volume", 232 "equivalent volume sphere", 231 233 "half outer length_a", "half outer length_b", "half outer length_c", 232 234 "equivalent circular cross-section", -
sasmodels/models/cylinder.c
rd42dd4a r99658f6 11 11 { 12 12 return sas_2J1x_x(qab*radius) * sas_sinx_x(qc*0.5*length); 13 } 14 15 static double 16 radius_from_excluded_volume(double radius, double length) 17 { 18 return 0.5*cbrt(0.75*radius*(2.0*radius*length + (radius + length)*(M_PI*radius + length))); 13 19 } 14 20 … … 31 37 default: 32 38 case 1: 39 return radius_from_excluded_volume(radius, length); 40 case 2: 33 41 return radius_from_volume(radius, length); 34 case 2:42 case 3: 35 43 return radius; 36 case 3:44 case 4: 37 45 return 0.5*length; 38 case 4:46 case 5: 39 47 return (radius < 0.5*length ? radius : 0.5*length); 40 case 5:48 case 6: 41 49 return (radius > 0.5*length ? radius : 0.5*length); 42 case 6:50 case 7: 43 51 return radius_from_diagonal(radius,length); 44 52 } -
sasmodels/models/cylinder.py
r304c775 r99658f6 98 98 J. S. Pedersen, Adv. Colloid Interface Sci. 70, 171-210 (1997). 99 99 G. Fournet, Bull. Soc. Fr. Mineral. Cristallogr. 74, 39-113 (1951). 100 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 100 101 """ 101 102 … … 140 141 have_Fq = True 141 142 effective_radius_type = [ 142 "e quivalentsphere", "radius",143 "excluded volume", "equivalent volume sphere", "radius", 143 144 "half length", "half min dimension", "half max dimension", "half diagonal", 144 145 ] … … 185 186 radius, length = parameters[2][2], parameters[3][2] 186 187 tests.extend([ 187 ({'radius_effective_type': 0}, 0.1, None, None, 0., pi*radius**2*length, 1.0), 188 ({'radius_effective_type': 1}, 0.1, None, None, (0.75*radius**2*length)**(1./3.), None, None), 189 ({'radius_effective_type': 2}, 0.1, None, None, radius, None, None), 190 ({'radius_effective_type': 3}, 0.1, None, None, length/2., None, None), 191 ({'radius_effective_type': 4}, 0.1, None, None, min(radius, length/2.), None, None), 192 ({'radius_effective_type': 5}, 0.1, None, None, max(radius, length/2.), None, None), 193 ({'radius_effective_type': 6}, 0.1, None, None, np.sqrt(4*radius**2 + length**2)/2., None, None), 188 ({'radius_effective_mode': 0}, 0.1, None, None, 0., pi*radius**2*length, 1.0), 189 ({'radius_effective_mode': 1}, 0.1, None, None, 0.5*(0.75*radius*(2.0*radius*length + (radius + length)*(pi*radius + length)))**(1./3.), None, None), 190 ({'radius_effective_mode': 2}, 0.1, None, None, (0.75*radius**2*length)**(1./3.), None, None), 191 ({'radius_effective_mode': 3}, 0.1, None, None, radius, None, None), 192 ({'radius_effective_mode': 4}, 0.1, None, None, length/2., None, None), 193 ({'radius_effective_mode': 5}, 0.1, None, None, min(radius, length/2.), None, None), 194 ({'radius_effective_mode': 6}, 0.1, None, None, max(radius, length/2.), None, None), 195 ({'radius_effective_mode': 7}, 0.1, None, None, np.sqrt(4*radius**2 + length**2)/2., None, None), 194 196 ]) 195 197 del radius, length -
sasmodels/models/ellipsoid.c
rd42dd4a r99658f6 36 36 switch (mode) { 37 37 default: 38 case 1: // equivalent sphere 38 case 1: // average curvature 39 return radius_from_curvature(radius_polar, radius_equatorial); 40 case 2: // equivalent volume sphere 39 41 return radius_from_volume(radius_polar, radius_equatorial); 40 case 2: // average curvature41 return radius_from_curvature(radius_polar, radius_equatorial);42 42 case 3: // min radius 43 43 return (radius_polar < radius_equatorial ? radius_polar : radius_equatorial); -
sasmodels/models/ellipsoid.py
ree60aa7 r99658f6 170 170 have_Fq = True 171 171 effective_radius_type = [ 172 " equivalent sphere", "average curvature", "min radius", "max radius",172 "average curvature", "equivalent volume sphere", "min radius", "max radius", 173 173 ] 174 174 -
sasmodels/models/elliptical_cylinder.c
rd42dd4a r99658f6 3 3 { 4 4 return M_PI * radius_minor * radius_minor * r_ratio * length; 5 } 6 7 static double 8 radius_from_excluded_volume(double radius_minor, double r_ratio, double length) 9 { 10 const double r_equiv = sqrt(radius_minor*radius_minor*r_ratio); 11 return 0.5*cbrt(0.75*r_equiv*(2.0*r_equiv*length + (r_equiv + length)*(M_PI*r_equiv + length))); 5 12 } 6 13 … … 38 45 switch (mode) { 39 46 default: 40 case 1: // equivalent sphere 47 case 1: // equivalent cylinder excluded volume 48 return radius_from_excluded_volume(radius_minor, r_ratio, length); 49 case 2: // equivalent volume sphere 41 50 return radius_from_volume(radius_minor, r_ratio, length); 42 case 2: // average radius51 case 3: // average radius 43 52 return 0.5*radius_minor*(1.0 + r_ratio); 44 case 3: // min radius53 case 4: // min radius 45 54 return (r_ratio > 1.0 ? radius_minor : r_ratio*radius_minor); 46 case 4: // max radius55 case 5: // max radius 47 56 return (r_ratio < 1.0 ? radius_minor : r_ratio*radius_minor); 48 case 5: // equivalent circular cross-section57 case 6: // equivalent circular cross-section 49 58 return sqrt(radius_minor*radius_minor*r_ratio); 50 case 6: // half length59 case 7: // half length 51 60 return 0.5*length; 52 case 7: // half min dimension61 case 8: // half min dimension 53 62 return radius_from_min_dimension(radius_minor,r_ratio,0.5*length); 54 case 8: // half max dimension63 case 9: // half max dimension 55 64 return radius_from_max_dimension(radius_minor,r_ratio,0.5*length); 56 case 9: // half diagonal65 case 10: // half diagonal 57 66 return radius_from_diagonal(radius_minor,r_ratio,length); 58 67 } -
sasmodels/models/elliptical_cylinder.py
ree60aa7 r99658f6 88 88 L A Feigin and D I Svergun, *Structure Analysis by Small-Angle X-Ray and 89 89 Neutron Scattering*, Plenum, New York, (1987) [see table 3.4] 90 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 90 91 91 92 Authorship and Verification … … 124 125 have_Fq = True 125 126 effective_radius_type = [ 126 "equivalent sphere", "average radius", "min radius", "max radius",127 "equivalent cylinder excluded volume", "equivalent volume sphere", "average radius", "min radius", "max radius", 127 128 "equivalent circular cross-section", 128 129 "half length", "half min dimension", "half max dimension", "half diagonal", -
sasmodels/models/hardsphere.py
r304c775 r304c775 162 162 return pars 163 163 164 demo = dict(radius_effective=200, volfraction=0.2,165 radius_effective_pd=0.1, radius_effective_pd_n=40)166 164 # Q=0.001 is in the Taylor series, low Q part, so add Q=0.1, 167 165 # assuming double precision sasview is correct -
sasmodels/models/hollow_cylinder.c
rd42dd4a r99658f6 11 11 { 12 12 return M_PI*length*square(radius+thickness); 13 } 14 15 static double 16 radius_from_excluded_volume(double radius, double thickness, double length) 17 { 18 const double radius_tot = radius + thickness; 19 return 0.5*cbrt(0.75*radius_tot*(2.0*radius_tot*length + (radius_tot + length)*(M_PI*radius_tot + length))); 13 20 } 14 21 … … 31 38 switch (mode) { 32 39 default: 33 case 1: // equivalent sphere 40 case 1: // excluded volume 41 return radius_from_excluded_volume(radius, thickness, length); 42 case 2: // equivalent volume sphere 34 43 return radius_from_volume(radius, thickness, length); 35 case 2: // outer radius44 case 3: // outer radius 36 45 return radius + thickness; 37 case 3: // half length46 case 4: // half length 38 47 return 0.5*length; 39 case 4: // half outer min dimension48 case 5: // half outer min dimension 40 49 return (radius + thickness < 0.5*length ? radius + thickness : 0.5*length); 41 case 5: // half outer max dimension50 case 6: // half outer max dimension 42 51 return (radius + thickness > 0.5*length ? radius + thickness : 0.5*length); 43 case 6: // half outer diagonal52 case 7: // half outer diagonal 44 53 return radius_from_diagonal(radius,thickness,length); 45 54 } -
sasmodels/models/hollow_cylinder.py
r304c775 r99658f6 60 60 .. [#] L A Feigin and D I Svergun, *Structure Analysis by Small-Angle X-Ray and 61 61 Neutron Scattering*, Plenum Press, New York, (1987) 62 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 62 63 63 64 Authorship and Verification … … 102 103 have_Fq = True 103 104 effective_radius_type = [ 104 "e quivalentsphere", "outer radius", "half length",105 "excluded volume", "equivalent outer volume sphere", "outer radius", "half length", 105 106 "half outer min dimension", "half outer max dimension", 106 107 "half outer diagonal", … … 140 141 [{}, 0.00005, 1764.926], 141 142 [{}, 0.1, None, None, 142 (3./4*(radius+thickness)**2*length)**(1./3), # R_eff fromvolume143 0.5*(0.75*(radius+thickness)*(2.0*(radius+thickness)*length + ((radius+thickness) + length)*(pi*(radius+thickness) + length)))**(1./3.), # R_eff from excluded volume 143 144 pi*((radius+thickness)**2-radius**2)*length, # shell volume 144 145 (radius+thickness)**2/((radius+thickness)**2 - radius**2), # form:shell ratio -
sasmodels/models/hollow_rectangular_prism.c
rd42dd4a r99658f6 22 22 23 23 static double 24 radius_from_excluded_volume(double length_a, double b2a_ratio, double c2a_ratio) 25 { 26 const double r_equiv = sqrt(length_a*length_a*b2a_ratio/M_PI); 27 const double length_c = length_a*c2a_ratio; 28 return 0.5*cbrt(0.75*r_equiv*(2.0*r_equiv*length_c + (r_equiv + length_c)*(M_PI*r_equiv + length_c))); 29 } 30 31 static double 24 32 effective_radius(int mode, double length_a, double b2a_ratio, double c2a_ratio, double thickness) 25 33 // NOTE length_a is external dimension! … … 27 35 switch (mode) { 28 36 default: 29 case 1: // equivalent sphere 37 case 1: // equivalent cylinder excluded volume 38 return radius_from_excluded_volume(length_a, b2a_ratio, c2a_ratio); 39 case 2: // equivalent outer volume sphere 30 40 return cbrt(cube(length_a)*b2a_ratio*c2a_ratio/M_4PI_3); 31 case 2: // half length_a41 case 3: // half length_a 32 42 return 0.5 * length_a; 33 case 3: // half length_b43 case 4: // half length_b 34 44 return 0.5 * length_a*b2a_ratio; 35 case 4: // half length_c45 case 5: // half length_c 36 46 return 0.5 * length_a*c2a_ratio; 37 case 5: // equivalent outer circular cross-section47 case 6: // equivalent outer circular cross-section 38 48 return length_a*sqrt(b2a_ratio/M_PI); 39 case 6: // half ab diagonal49 case 7: // half ab diagonal 40 50 return 0.5*sqrt(square(length_a) * (1.0 + square(b2a_ratio))); 41 case 7: // half diagonal51 case 8: // half diagonal 42 52 return 0.5*sqrt(square(length_a) * (1.0 + square(b2a_ratio) + square(c2a_ratio))); 43 53 } -
sasmodels/models/hollow_rectangular_prism.py
ree60aa7 r99658f6 98 98 99 99 .. [#Nayuk2012] R Nayuk and K Huber, *Z. Phys. Chem.*, 226 (2012) 837-854 100 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 100 101 101 102 … … 150 151 have_Fq = True 151 152 effective_radius_type = [ 152 "equivalent sphere", "half length_a", "half length_b", "half length_c", 153 "equivalent cylinder excluded volume", "equivalent outer volume sphere", 154 "half length_a", "half length_b", "half length_c", 153 155 "equivalent outer circular cross-section", 154 156 "half ab diagonal", "half diagonal", -
sasmodels/models/hollow_rectangular_prism_thin_walls.c
rd42dd4a r99658f6 18 18 19 19 static double 20 radius_from_excluded_volume(double length_a, double b2a_ratio, double c2a_ratio) 21 { 22 const double r_equiv = sqrt(length_a*length_a*b2a_ratio/M_PI); 23 const double length_c = length_a*c2a_ratio; 24 return 0.5*cbrt(0.75*r_equiv*(2.0*r_equiv*length_c + (r_equiv + length_c)*(M_PI*r_equiv + length_c))); 25 } 26 27 static double 20 28 effective_radius(int mode, double length_a, double b2a_ratio, double c2a_ratio) 21 29 { 22 30 switch (mode) { 23 31 default: 24 case 1: // equivalent sphere 32 case 1: // equivalent cylinder excluded volume 33 return radius_from_excluded_volume(length_a, b2a_ratio, c2a_ratio); 34 case 2: // equivalent outer volume sphere 25 35 return cbrt(cube(length_a)*b2a_ratio*c2a_ratio/M_4PI_3); 26 case 2: // half length_a36 case 3: // half length_a 27 37 return 0.5 * length_a; 28 case 3: // half length_b38 case 4: // half length_b 29 39 return 0.5 * length_a*b2a_ratio; 30 case 4: // half length_c40 case 5: // half length_c 31 41 return 0.5 * length_a*c2a_ratio; 32 case 5: // equivalent outer circular cross-section42 case 6: // equivalent outer circular cross-section 33 43 return length_a*sqrt(b2a_ratio/M_PI); 34 case 6: // half ab diagonal44 case 7: // half ab diagonal 35 45 return 0.5*sqrt(square(length_a) * (1.0 + square(b2a_ratio))); 36 case 7: // half diagonal46 case 8: // half diagonal 37 47 return 0.5*sqrt(square(length_a) * (1.0 + square(b2a_ratio) + square(c2a_ratio))); 38 48 } -
sasmodels/models/hollow_rectangular_prism_thin_walls.py
ree60aa7 r99658f6 72 72 73 73 .. [#Nayuk2012] R Nayuk and K Huber, *Z. Phys. Chem.*, 226 (2012) 837-854 74 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 74 75 75 76 … … 110 111 have_Fq = True 111 112 effective_radius_type = [ 112 "equivalent sphere", "half length_a", "half length_b", "half length_c", 113 "equivalent cylinder excluded volume", "equivalent outer volume sphere", 114 "half length_a", "half length_b", "half length_c", 113 115 "equivalent outer circular cross-section", 114 116 "half ab diagonal", "half diagonal", -
sasmodels/models/parallelepiped.c
rd42dd4a r99658f6 6 6 7 7 static double 8 radius_from_excluded_volume(double length_a, double length_b, double length_c) 9 { 10 double r_equiv, length; 11 double lengths[3] = {length_a, length_b, length_c}; 12 double lengthmax = fmax(lengths[0],fmax(lengths[1],lengths[2])); 13 double length_1 = lengthmax; 14 double length_2 = lengthmax; 15 double length_3 = lengthmax; 16 17 for(int ilen=0; ilen<3; ilen++) { 18 if (lengths[ilen] < length_1) { 19 length_2 = length_1; 20 length_1 = lengths[ilen]; 21 } else { 22 if (lengths[ilen] < length_2) { 23 length_2 = lengths[ilen]; 24 } 25 } 26 } 27 if(length_2-length_1 > length_3-length_2) { 28 r_equiv = sqrt(length_2*length_3/M_PI); 29 length = length_1; 30 } else { 31 r_equiv = sqrt(length_1*length_2/M_PI); 32 length = length_3; 33 } 34 35 return 0.5*cbrt(0.75*r_equiv*(2.0*r_equiv*length + (r_equiv + length)*(M_PI*r_equiv + length))); 36 } 37 38 static double 8 39 effective_radius(int mode, double length_a, double length_b, double length_c) 9 40 { 10 41 switch (mode) { 11 42 default: 12 case 1: // equivalent sphere 43 case 1: // equivalent cylinder excluded volume 44 return radius_from_excluded_volume(length_a,length_b,length_c); 45 case 2: // equivalent volume sphere 13 46 return cbrt(length_a*length_b*length_c/M_4PI_3); 14 case 2: // half length_a47 case 3: // half length_a 15 48 return 0.5 * length_a; 16 case 3: // half length_b49 case 4: // half length_b 17 50 return 0.5 * length_b; 18 case 4: // half length_c51 case 5: // half length_c 19 52 return 0.5 * length_c; 20 case 5: // equivalent circular cross-section53 case 6: // equivalent circular cross-section 21 54 return sqrt(length_a*length_b/M_PI); 22 case 6: // half ab diagonal55 case 7: // half ab diagonal 23 56 return 0.5*sqrt(length_a*length_a + length_b*length_b); 24 case 7: // half diagonal57 case 8: // half diagonal 25 58 return 0.5*sqrt(length_a*length_a + length_b*length_b + length_c*length_c); 26 59 } -
sasmodels/models/parallelepiped.py
ree60aa7 r99658f6 180 180 14 (1961) 185-211 181 181 .. [#] R Nayuk and K Huber, *Z. Phys. Chem.*, 226 (2012) 837-854 182 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 182 183 183 184 Authorship and Verification … … 232 233 have_Fq = True 233 234 effective_radius_type = [ 234 "equivalent sphere", "half length_a", "half length_b", "half length_c", 235 "equivalent cylinder excluded volume", "equivalent volume sphere", 236 "half length_a", "half length_b", "half length_c", 235 237 "equivalent circular cross-section", "half ab diagonal", "half diagonal", 236 238 ] -
sasmodels/models/pearl_necklace.c
r3f853beb r9b5fd42 40 40 const double si = sas_sinx_x(q*A_s); 41 41 const double omsi = 1.0 - si; 42 const double pow_si = pow (si, num_pearls);42 const double pow_si = pown(si, num_pearls); 43 43 44 44 // form factor for num_pearls … … 67 67 } 68 68 69 double form_volume(double radius, double edge_sep, 70 double thick_string, double fp_num_pearls) 69 double form_volume(double radius, double edge_sep, double thick_string, double fp_num_pearls) 71 70 { 72 71 const int num_pearls = (int)(fp_num_pearls + 0.5); //Force integer number of pearls … … 77 76 78 77 return volume; 78 } 79 80 static double 81 radius_from_volume(double radius, double edge_sep, double thick_string, double fp_num_pearls) 82 { 83 const double vol_tot = form_volume(radius, edge_sep, thick_string, fp_num_pearls); 84 return cbrt(vol_tot/M_4PI_3); 85 } 86 87 static double 88 effective_radius(int mode, double radius, double edge_sep, double thick_string, double fp_num_pearls) 89 { 90 switch (mode) { 91 default: 92 case 1: 93 return radius_from_volume(radius, edge_sep, thick_string, fp_num_pearls); 94 } 79 95 } 80 96 -
sasmodels/models/pearl_necklace.py
r2cc8aa2 rcf3d0ce 53 53 R Schweins and K Huber, *Particle Scattering Factor of Pearl Necklace Chains*, 54 54 *Macromol. Symp.* 211 (2004) 25-42 2004 55 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 55 56 """ 56 57 … … 95 96 source = ["lib/sas_Si.c", "lib/sas_3j1x_x.c", "pearl_necklace.c"] 96 97 single = False # use double precision unless told otherwise 97 98 def volume(radius, edge_sep, thick_string, num_pearls): 99 """ 100 Calculates the total particle volume of the necklace. 101 Redundant with form_volume. 102 """ 103 num_pearls = int(num_pearls + 0.5) 104 number_of_strings = num_pearls - 1.0 105 string_vol = edge_sep * pi * pow((thick_string / 2.0), 2.0) 106 pearl_vol = 4.0 /3.0 * pi * pow(radius, 3.0) 107 total_vol = number_of_strings * string_vol 108 total_vol += num_pearls * pearl_vol 109 return total_vol 110 111 def ER(radius, edge_sep, thick_string, num_pearls): 112 """ 113 Calculation for effective radius. 114 """ 115 num_pearls = int(num_pearls + 0.5) 116 tot_vol = volume(radius, edge_sep, thick_string, num_pearls) 117 rad_out = (tot_vol/(4.0/3.0*pi)) ** (1./3.) 118 return rad_out 119 98 effective_radius_type = [ 99 "equivalent volume sphere", 100 ] 101 120 102 def random(): 121 103 radius = 10**np.random.uniform(1, 3) # 1 - 1000 -
sasmodels/models/pringle.c
rd42dd4a r99658f6 105 105 106 106 static double 107 radius_from_excluded_volume(double radius, double thickness) 108 { 109 return 0.5*cbrt(0.75*radius*(2.0*radius*thickness + (radius + thickness)*(M_PI*radius + thickness))); 110 } 111 112 static double 107 113 effective_radius(int mode, double radius, double thickness, double alpha, double beta) 108 114 { 109 115 switch (mode) { 110 116 default: 111 case 1: // equivalent sphere 117 case 1: // equivalent cylinder excluded volume 118 return radius_from_excluded_volume(radius, thickness); 119 case 2: // equivalent volume sphere 112 120 return cbrt(M_PI*radius*radius*thickness/M_4PI_3); 113 case 2: // radius121 case 3: // radius 114 122 return radius; 115 123 } -
sasmodels/models/pringle.py
ree60aa7 r99658f6 42 42 Karen Edler, Universtiy of Bath, Private Communication. 2012. 43 43 Derivation by Stefan Alexandru Rautu. 44 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 44 45 45 46 * **Author:** Andrew Jackson **Date:** 2008 … … 74 75 source = ["lib/polevl.c", "lib/sas_J0.c", "lib/sas_J1.c", 75 76 "lib/sas_JN.c", "lib/gauss76.c", "pringle.c"] 76 effective_radius_type = ["equivalent sphere", "radius"]77 effective_radius_type = ["equivalent cylinder excluded volume", "equivalent volume sphere", "radius"] 77 78 78 79 def random(): -
sasmodels/models/rectangular_prism.c
rd42dd4a r99658f6 6 6 7 7 static double 8 radius_from_excluded_volume(double length_a, double b2a_ratio, double c2a_ratio) 9 { 10 double const r_equiv = sqrt(length_a*length_a*b2a_ratio/M_PI); 11 double const length_c = c2a_ratio*length_a; 12 return 0.5*cbrt(0.75*r_equiv*(2.0*r_equiv*length_c + (r_equiv + length_c)*(M_PI*r_equiv + length_c))); 13 } 14 15 static double 8 16 effective_radius(int mode, double length_a, double b2a_ratio, double c2a_ratio) 9 17 { 10 18 switch (mode) { 11 19 default: 12 case 1: // equivalent sphere 20 case 1: // equivalent cylinder excluded volume 21 return radius_from_excluded_volume(length_a,b2a_ratio,c2a_ratio); 22 case 2: // equivalent volume sphere 13 23 return cbrt(cube(length_a)*b2a_ratio*c2a_ratio/M_4PI_3); 14 case 2: // half length_a24 case 3: // half length_a 15 25 return 0.5 * length_a; 16 case 3: // half length_b26 case 4: // half length_b 17 27 return 0.5 * length_a*b2a_ratio; 18 case 4: // half length_c28 case 5: // half length_c 19 29 return 0.5 * length_a*c2a_ratio; 20 case 5: // equivalent circular cross-section30 case 6: // equivalent circular cross-section 21 31 return length_a*sqrt(b2a_ratio/M_PI); 22 case 6: // half ab diagonal32 case 7: // half ab diagonal 23 33 return 0.5*sqrt(square(length_a) * (1.0 + square(b2a_ratio))); 24 case 7: // half diagonal34 case 8: // half diagonal 25 35 return 0.5*sqrt(square(length_a) * (1.0 + square(b2a_ratio) + square(c2a_ratio))); 26 36 } -
sasmodels/models/rectangular_prism.py
ree60aa7 r99658f6 99 99 100 100 R Nayuk and K Huber, *Z. Phys. Chem.*, 226 (2012) 837-854 101 102 L. Onsager, Ann. New York Acad. Sci. 51, 627-659 (1949). 103 101 104 """ 102 105 … … 137 140 have_Fq = True 138 141 effective_radius_type = [ 139 "equivalent sphere", "half length_a", "half length_b", "half length_c", 142 "equivalent cylinder excluded volume", "equivalent volume sphere", 143 "half length_a", "half length_b", "half length_c", 140 144 "equivalent circular cross-section", "half ab diagonal", "half diagonal", 141 145 ] -
sasmodels/models/triaxial_ellipsoid.c
rd42dd4a r99658f6 5 5 { 6 6 return M_4PI_3*radius_equat_minor*radius_equat_major*radius_polar; 7 } 8 9 static double 10 radius_from_curvature(double radius_equat_minor, double radius_equat_major, double radius_polar) 11 { 12 // Trivial cases 13 if (radius_equat_minor == radius_equat_major == radius_polar) return radius_polar; 14 if (radius_equat_minor * radius_equat_major * radius_polar == 0.) return 0.; 15 16 17 double r_equat_equiv, r_polar_equiv; 18 double radii[3] = {radius_equat_minor, radius_equat_major, radius_polar}; 19 double radmax = fmax(radii[0],fmax(radii[1],radii[2])); 20 21 double radius_1 = radmax; 22 double radius_2 = radmax; 23 double radius_3 = radmax; 24 25 for(int irad=0; irad<3; irad++) { 26 if (radii[irad] < radius_1) { 27 radius_3 = radius_2; 28 radius_2 = radius_1; 29 radius_1 = radii[irad]; 30 } else { 31 if (radii[irad] < radius_2) { 32 radius_2 = radii[irad]; 33 } 34 } 35 } 36 if(radius_2-radius_1 > radius_3-radius_2) { 37 r_equat_equiv = sqrt(radius_2*radius_3); 38 r_polar_equiv = radius_1; 39 } else { 40 r_equat_equiv = sqrt(radius_1*radius_2); 41 r_polar_equiv = radius_3; 42 } 43 44 // see equation (26) in A.Isihara, J.Chem.Phys. 18(1950)1446-1449 45 const double ratio = (r_polar_equiv < r_equat_equiv 46 ? r_polar_equiv / r_equat_equiv 47 : r_equat_equiv / r_polar_equiv); 48 const double e1 = sqrt(1.0 - ratio*ratio); 49 const double b1 = 1.0 + asin(e1) / (e1 * ratio); 50 const double bL = (1.0 + e1) / (1.0 - e1); 51 const double b2 = 1.0 + 0.5 * ratio * ratio / e1 * log(bL); 52 const double delta = 0.75 * b1 * b2; 53 const double ddd = 2.0 * (delta + 1.0) * r_polar_equiv * r_equat_equiv * r_equat_equiv; 54 return 0.5 * cbrt(ddd); 7 55 } 8 56 … … 32 80 switch (mode) { 33 81 default: 34 case 1: // equivalent sphere 82 case 1: // equivalent biaxial ellipsoid average curvature 83 return radius_from_curvature(radius_equat_minor,radius_equat_major, radius_polar); 84 case 2: // equivalent volume sphere 35 85 return radius_from_volume(radius_equat_minor,radius_equat_major, radius_polar); 36 case 2: // min radius86 case 3: // min radius 37 87 return radius_from_min_dimension(radius_equat_minor,radius_equat_major, radius_polar); 38 case 3: // max radius88 case 4: // max radius 39 89 return radius_from_max_dimension(radius_equat_minor,radius_equat_major, radius_polar); 40 90 } -
sasmodels/models/triaxial_ellipsoid.py
ree60aa7 r99658f6 158 158 source = ["lib/sas_3j1x_x.c", "lib/gauss76.c", "triaxial_ellipsoid.c"] 159 159 have_Fq = True 160 effective_radius_type = ["equivalent sphere", "min radius", "max radius"]160 effective_radius_type = ["equivalent biaxial ellipsoid average curvature", "equivalent volume sphere", "min radius", "max radius"] 161 161 162 162 def random(): -
sasmodels/product.py
r39a06c9 r99658f6 37 37 #] 38 38 39 STRUCTURE_MODE_ID = "structure_factor_mode" 40 RADIUS_MODE_ID = "radius_effective_mode" 39 41 RADIUS_ID = "radius_effective" 40 42 VOLFRAC_ID = "volfraction" … … 43 45 if p_info.have_Fq: 44 46 par = parse_parameter( 45 "structure_factor_mode",47 STRUCTURE_MODE_ID, 46 48 "", 47 49 0, … … 52 54 if p_info.effective_radius_type is not None: 53 55 par = parse_parameter( 54 "radius_effective_mode",56 RADIUS_MODE_ID, 55 57 "", 56 0,58 1, 57 59 [["unconstrained"] + p_info.effective_radius_type], 58 60 "", -
sasmodels/resolution.py
r9e7837a re2592f0 445 445 q = np.sort(q) 446 446 if q_min + 2*MINIMUM_RESOLUTION < q[0]: 447 n_low = np.ceil((q[0]-q_min) / (q[1]-q[0])) if q[1] > q[0] else 15447 n_low = int(np.ceil((q[0]-q_min) / (q[1]-q[0]))) if q[1] > q[0] else 15 448 448 q_low = np.linspace(q_min, q[0], n_low+1)[:-1] 449 449 else: 450 450 q_low = [] 451 451 if q_max - 2*MINIMUM_RESOLUTION > q[-1]: 452 n_high = np.ceil((q_max-q[-1]) / (q[-1]-q[-2])) if q[-1] > q[-2] else 15452 n_high = int(np.ceil((q_max-q[-1]) / (q[-1]-q[-2]))) if q[-1] > q[-2] else 15 453 453 q_high = np.linspace(q[-1], q_max, n_high+1)[1:] 454 454 else: … … 499 499 q_min = q[0]*MINIMUM_ABSOLUTE_Q 500 500 n_low = log_delta_q * (log(q[0])-log(q_min)) 501 q_low = np.logspace(log10(q_min), log10(q[0]), np.ceil(n_low)+1)[:-1]501 q_low = np.logspace(log10(q_min), log10(q[0]), int(np.ceil(n_low))+1)[:-1] 502 502 else: 503 503 q_low = [] 504 504 if q_max > q[-1]: 505 505 n_high = log_delta_q * (log(q_max)-log(q[-1])) 506 q_high = np.logspace(log10(q[-1]), log10(q_max), np.ceil(n_high)+1)[1:]506 q_high = np.logspace(log10(q[-1]), log10(q_max), int(np.ceil(n_high))+1)[1:] 507 507 else: 508 508 q_high = [] -
sasmodels/sasview_model.py
r39a06c9 r3a1afed 382 382 hidden.add('scale') 383 383 hidden.add('background') 384 self._model_info.parameters.defaults['background'] = 0.385 384 386 385 # Update the parameter lists to exclude any hidden parameters … … 695 694 return self._calculate_Iq(qx, qy) 696 695 697 def _calculate_Iq(self, qx, qy=None , Fq=False, effective_radius_type=1):696 def _calculate_Iq(self, qx, qy=None): 698 697 if self._model is None: 699 698 self._model = core.build_model(self._model_info) … … 715 714 #print("values", values) 716 715 #print("is_mag", is_magnetic) 717 if Fq:718 result = calculator.Fq(call_details, values, cutoff=self.cutoff,719 magnetic=is_magnetic,720 effective_radius_type=effective_radius_type)721 716 result = calculator(call_details, values, cutoff=self.cutoff, 722 717 magnetic=is_magnetic) … … 736 731 Calculate the effective radius for P(q)*S(q) 737 732 733 *mode* is the R_eff type, which defaults to 1 to match the ER 734 calculation for sasview models from version 3.x. 735 738 736 :return: the value of the effective radius 739 737 """ 740 Fq = self._calculate_Iq([0.1], True, mode) 741 return Fq[2] 738 # ER and VR are only needed for old multiplication models, based on 739 # sas.sascalc.fit.MultiplicationModel. Fail for now. If we want to 740 # continue supporting them then add some test cases so that the code 741 # is exercised. We can access ER/VR using the kernel Fq function by 742 # extending _calculate_Iq so that it calls: 743 # if er_mode > 0: 744 # res = calculator.Fq(call_details, values, cutoff=self.cutoff, 745 # magnetic=False, effective_radius_type=mode) 746 # R_eff, form_shell_ratio = res[2], res[4] 747 # return R_eff, form_shell_ratio 748 # Then use the following in calculate_ER: 749 # ER, VR = self._calculate_Iq(q=[0.1], er_mode=mode) 750 # return ER 751 # Similarly, for calculate_VR: 752 # ER, VR = self._calculate_Iq(q=[0.1], er_mode=1) 753 # return VR 754 # Obviously a combined calculate_ER_VR method would be better, but 755 # we only need them to support very old models, so ignore the 2x 756 # performance hit. 757 raise NotImplementedError("ER function is no longer available.") 742 758 743 759 def calculate_VR(self): … … 748 764 :return: the value of the form:shell volume ratio 749 765 """ 750 Fq = self._calculate_Iq([0.1], True, mode)751 r eturn Fq[4]766 # See comments in calculate_ER. 767 raise NotImplementedError("VR function is no longer available.") 752 768 753 769 def set_dispersion(self, parameter, dispersion): … … 819 835 return value, [value], [1.0] 820 836 837 @classmethod 838 def runTests(cls): 839 """ 840 Run any tests built into the model and captures the test output. 841 842 Returns success flag and output 843 """ 844 from .model_test import check_model 845 return check_model(cls._model_info) 846 821 847 def test_cylinder(): 822 848 # type: () -> float … … 849 875 P = _make_standard_model('cylinder')() 850 876 model = MultiplicationModel(P, S) 851 model.setParam( 'radius_effective_mode', 1.0)877 model.setParam(product.RADIUS_MODE_ID, 1.0) 852 878 value = model.evalDistribution([0.1, 0.1]) 853 879 if np.isnan(value): … … 904 930 CylinderModel().evalDistribution([0.1, 0.1]) 905 931 932 def test_structure_factor_background(): 933 # type: () -> None 934 """ 935 Check that sasview model and direct model match, with background=0. 936 """ 937 from .data import empty_data1D 938 from .core import load_model_info, build_model 939 from .direct_model import DirectModel 940 941 model_name = "hardsphere" 942 q = [0.0] 943 944 sasview_model = _make_standard_model(model_name)() 945 sasview_value = sasview_model.evalDistribution(np.array(q))[0] 946 947 data = empty_data1D(q) 948 model_info = load_model_info(model_name) 949 model = build_model(model_info) 950 direct_model = DirectModel(data, model) 951 direct_value_zero_background = direct_model(background=0.0) 952 953 assert sasview_value == direct_value_zero_background 954 955 # Additionally check that direct value background defaults to zero 956 direct_value_default = direct_model() 957 assert sasview_value == direct_value_default 958 959 906 960 def magnetic_demo(): 907 961 Model = _make_standard_model('sphere') … … 924 978 #print("rpa:", test_rpa()) 925 979 #test_empty_distribution() 980 #test_structure_factor_background() -
sasmodels/special.py
rdf69efa rfba9ca0 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 single 120 precision on some platforms. 121 122 sas_gammainc(a, x), sas_gammaincc(a, x): 123 Incomplete gamma function 124 sas_gammainc\ $(a, x) = \int_0^x t^{a-1}e^{-t}\,dt / \Gamma(a)$ 125 and complementary incomplete gamma function 126 sas_gammaincc\ $(a, x) = \int_x^\infty t^{a-1}e^{-t}\,dt / \Gamma(a)$ 115 127 116 128 sas_erf(x), sas_erfc(x): … … 207 219 from numpy import pi, nan, inf 208 220 from scipy.special import gamma as sas_gamma 221 from scipy.special import gammaln as sas_gammaln 222 from scipy.special import gammainc as sas_gammainc 223 from scipy.special import gammaincc as sas_gammaincc 209 224 from scipy.special import erf as sas_erf 210 225 from scipy.special import erfc as sas_erfc -
sasmodels/weights.py
r3d58247 re2592f0 23 23 default = dict(npts=35, width=0, nsigmas=3) 24 24 def __init__(self, npts=None, width=None, nsigmas=None): 25 self.npts = self.default['npts'] if npts is None else npts25 self.npts = self.default['npts'] if npts is None else int(npts) 26 26 self.width = self.default['width'] if width is None else width 27 27 self.nsigmas = self.default['nsigmas'] if nsigmas is None else nsigmas
Note: See TracChangeset
for help on using the changeset viewer.