source: sasmodels/sasmodels/models/unified_power_Rg.py @ d57b06c

Last change on this file since d57b06c was d57b06c, checked in by Paul Kienzle <pkienzle@…>, 5 years ago

Merge remote-tracking branch 'origin/master' into ticket-1263-source-link

  • Property mode set to 100644
File size: 4.6 KB
Line 
1r"""
2Definition
3----------
4
5This model employs the empirical multiple level unified Exponential/Power-law
6fit method developed by Beaucage. Four functions are included so that 1, 2, 3,
7or 4 levels can be used. In addition a 0 level has been added which simply
8calculates
9
10.. math::
11
12    I(q) = \text{scale} / q + \text{background}
13
14The Beaucage method is able to reasonably approximate the scattering from
15many different types of particles, including fractal clusters, random coils
16(Debye equation), ellipsoidal particles, etc.
17
18The model works best for mass fractal systems characterized by Porod exponents
19between 5/3 and 3. It should not be used for surface fractal systems. Hammouda
20(2010) has pointed out a deficiency in the way this model handles the
21transitioning between the Guinier and Porod regimes and which can create
22artefacts that appear as kinks in the fitted model function.
23
24Also see the :ref:`guinier-porod` model.
25
26The empirical fit function is:
27
28.. math::
29
30    I(q) = \text{background}
31    + \sum_{i=1}^N \Bigl[
32        G_i \exp\Bigl(-\frac{q^2R_{gi}^2}{3}\Bigr)
33       + B_i \exp\Bigl(-\frac{q^2R_{g(i+1)}^2}{3}\Bigr)
34             \Bigl(\frac{1}{q_i^*}\Bigr)^{P_i} \Bigr]
35
36where
37
38.. math::
39
40    q_i^* = q \left[\operatorname{erf}
41            \left(\frac{q R_{gi}}{\sqrt{6}}\right)
42        \right]^{-3}
43
44
45For each level, the four parameters $G_i$, $R_{gi}$, $B_i$ and $P_i$ must
46be chosen.  Beaucage has an additional factor $k$ in the definition of
47$q_i^*$ which is ignored here.
48
49For example, to approximate the scattering from random coils (Debye equation),
50set $R_{gi}$ as the Guinier radius, $P_i = 2$, and $B_i = 2 G_i / R_{gi}$
51
52See the references for further information on choosing the parameters.
53
54For 2D data: The 2D scattering intensity is calculated in the same way as 1D,
55where the $q$ vector is defined as
56
57.. math::
58
59    q = \sqrt{q_x^2 + q_y^2}
60
61
62References
63----------
64
65.. [#] G Beaucage, *J. Appl. Cryst.*, 28 (1995) 717-728
66.. [#] G Beaucage, *J. Appl. Cryst.*, 29 (1996) 134-146
67.. [#] B Hammouda, *Analysis of the Beaucage model, J. Appl. Cryst.*, (2010), 43, 1474-1478
68
69Authorship and Verification
70----------------------------
71
72* **Author:**
73* **Last Modified by:**
74* **Last Reviewed by:**
75"""
76
77from __future__ import division
78
79import numpy as np
80from numpy import inf, exp, sqrt, errstate
81from scipy.special import erf, gamma
82
83category = "shape-independent"
84name = "unified_power_Rg"
85title = "Unified Power Rg"
86description = """
87        The Beaucage model employs the empirical multiple level unified
88        Exponential/Power-law fit method developed by G. Beaucage. Four functions
89        are included so that 1, 2, 3, or 4 levels can be used.
90        """
91
92# pylint: disable=bad-whitespace, line-too-long
93parameters = [
94    ["level",     "",     1,      [1, 6], "", "Level number"],
95    ["rg[level]", "Ang",  15.8,   [0, inf], "", "Radius of gyration"],
96    ["power[level]", "",  4,      [-inf, inf], "", "Power"],
97    ["B[level]",  "1/cm", 4.5e-6, [-inf, inf], "", ""],
98    ["G[level]",  "1/cm", 400,    [0, inf], "", ""],
99    ]
100# pylint: enable=bad-whitespace, line-too-long
101
102def Iq(q, level, rg, power, B, G):
103    """Return I(q) for unified power Rg model."""
104    level = int(level + 0.5)
105    if level == 0:
106        with errstate(divide='ignore'):
107            return 1./q
108
109    with errstate(divide='ignore', invalid='ignore'):
110        result = np.zeros(q.shape, 'd')
111        for i in range(level):
112            exp_now = exp(-(q*rg[i])**2/3.)
113            pow_now = (erf(q*rg[i]/sqrt(6.))**3/q)**power[i]
114            if i < level-1:
115                exp_next = exp(-(q*rg[i+1])**2/3.)
116            else:
117                exp_next = 1
118            result += G[i]*exp_now + B[i]*exp_next*pow_now
119
120    result[q == 0] = np.sum(G[:level])
121    return result
122
123Iq.vectorized = True
124
125def random():
126    """Return a random parameter set for the model."""
127    level = np.minimum(np.random.poisson(0.5) + 1, 6)
128    n = level
129    power = np.random.uniform(1.6, 3, n)
130    rg = 10**np.random.uniform(1, 5, n)
131    G = np.random.uniform(0.1, 10, n)**2 * 10**np.random.uniform(0.3, 3, n)
132    B = G * power / rg**power * gamma(power/2)
133    scale = 10**np.random.uniform(1, 4)
134    pars = dict(
135        #background=0,
136        scale=scale,
137        level=level,
138    )
139    pars.update(("power%d"%(k+1), v) for k, v in enumerate(power))
140    pars.update(("rg%d"%(k+1), v) for k, v in enumerate(rg))
141    pars.update(("B%d"%(k+1), v) for k, v in enumerate(B))
142    pars.update(("G%d"%(k+1), v) for k, v in enumerate(G))
143    return pars
144
145demo = dict(
146    level=2,
147    rg=[15.8, 21],
148    power=[4, 2],
149    B=[4.5e-6, 0.0006],
150    G=[400, 3],
151    scale=1.,
152    background=0.,
153)
Note: See TracBrowser for help on using the repository browser.