source: sasmodels/sasmodels/models/guinier_porod.py @ d86f0fc

core_shell_microgelsmagnetic_modelticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since d86f0fc was 2d81cfe, checked in by Paul Kienzle <pkienzle@…>, 6 years ago

lint

  • Property mode set to 100644
File size: 4.2 KB
Line 
1r"""
2Calculates the scattering for a generalized Guinier/power law object.
3This is an empirical model that can be used to determine the size
4and dimensionality of scattering objects, including asymmetric objects
5such as rods or platelets, and shapes intermediate between spheres
6and rods or between rods and platelets, and overcomes some of the
7deficiencies of the (Beaucage) Unified_Power_Rg model (see Hammouda, 2010).
8
9Definition
10----------
11
12The following functional form is used
13
14.. math::
15
16    I(q) = \begin{cases}
17    \frac{G}{Q^s}\ \exp{\left[\frac{-Q^2R_g^2}{3-s} \right]} & Q \leq Q_1 \\
18    D / Q^m  & Q \geq Q_1
19    \end{cases}
20
21This is based on the generalized Guinier law for such elongated objects
22(see the Glatter reference below). For 3D globular objects (such as spheres),
23$s = 0$ and one recovers the standard Guinier formula. For 2D symmetry
24(such as for rods) $s = 1$, and for 1D symmetry (such as for lamellae or
25platelets) $s = 2$. A dimensionality parameter ($3-s$) is thus defined,
26and is 3 for spherical objects, 2 for rods, and 1 for plates.
27
28Enforcing the continuity of the Guinier and Porod functions and their
29derivatives yields
30
31.. math::
32
33    Q_1 = \frac{1}{R_g} \sqrt{(m-s)(3-s)/2}
34
35and
36
37.. math::
38
39    D &= G \ \exp{ \left[ \frac{-Q_1^2 R_g^2}{3-s} \right]} \ Q_1^{m-s}
40
41      &= \frac{G}{R_g^{m-s}} \ \exp \left[ -\frac{m-s}{2} \right]
42          \left( \frac{(m-s)(3-s)}{2} \right)^{\frac{m-s}{2}}
43
44
45Note that the radius of gyration for a sphere of radius $R$ is given
46by $R_g = R \sqrt{3/5}$. For a cylinder of radius $R$ and length $L$,
47$R_g^2 = \frac{L^2}{12} + \frac{R^2}{2}$ from which the cross-sectional
48radius of gyration for a randomly oriented thin cylinder is $R_g = R/\sqrt{2}$
49and the cross-sectional radius of gyration of a randomly oriented lamella
50of thickness $T$ is given by $R_g = T / \sqrt{12}$.
51
52For 2D data: The 2D scattering intensity is calculated in the same way as 1D,
53where the q vector is defined as
54
55.. math::
56    q = \sqrt{q_x^2+q_y^2}
57
58
59Reference
60---------
61
62B Hammouda, *A new Guinier-Porod model, J. Appl. Cryst.*, (2010), 43, 716-719
63
64B Hammouda, *Analysis of the Beaucage model, J. Appl. Cryst.*, (2010), 43, 1474-1478
65"""
66
67import numpy as np
68from numpy import inf, sqrt, exp, errstate
69
70name = "guinier_porod"
71title = "Guinier-Porod function"
72description = """\
73         I(q) = scale/q^s* exp ( - R_g^2 q^2 / (3-s) ) for q<= ql
74         = scale/q^porod_exp*exp((-ql^2*Rg^2)/(3-s))*ql^(porod_exp-s) for q>=ql
75                        where ql = sqrt((porod_exp-s)(3-s)/2)/Rg.
76                        List of parameters:
77                        scale = Guinier Scale
78                        s = Dimension Variable
79                        Rg = Radius of Gyration [A]
80                        porod_exp = Porod Exponent
81                        background  = Background [1/cm]"""
82
83category = "shape-independent"
84
85# pylint: disable=bad-whitespace, line-too-long
86#             ["name", "units", default, [lower, upper], "type","description"],
87parameters = [["rg", "Ang", 60.0, [0, inf], "", "Radius of gyration"],
88              ["s",  "",    1.0,  [0, inf], "", "Dimension variable"],
89              ["porod_exp",  "",    3.0,  [0, inf], "", "Porod exponent"]]
90# pylint: enable=bad-whitespace, line-too-long
91
92# pylint: disable=C0103
93def Iq(q, rg, s, porod_exp):
94    """
95    @param q: Input q-value
96    """
97    n = 3.0 - s
98    ms = 0.5*(porod_exp-s) # =(n-3+porod_exp)/2
99
100    # preallocate return value
101    iq = 0.0*q
102
103    # Take care of the singular points
104    if rg <= 0.0 or ms <= 0.0:
105        return iq
106
107    # Do the calculation and return the function value
108    idx = q < sqrt(n*ms)/rg
109    with errstate(divide='ignore'):
110        iq[idx] = q[idx]**-s * exp(-(q[idx]*rg)**2/n)
111        iq[~idx] = q[~idx]**-porod_exp * (exp(-ms) * (n*ms/rg**2)**ms)
112    return iq
113
114Iq.vectorized = True # Iq accepts an array of q values
115
116def random():
117    rg = 10**np.random.uniform(1, 5)
118    s = np.random.uniform(0, 3)
119    porod_exp = s + np.random.uniform(0, 3)
120    pars = dict(
121        #scale=1, background=0,
122        rg=rg,
123        s=s,
124        porod_exp=porod_exp,
125    )
126    return pars
127
128demo = dict(scale=1.5, background=0.5, rg=60, s=1.0, porod_exp=3.0)
129
130tests = [[{'scale': 1.5, 'background':0.5}, 0.04, 5.290096890253155]]
Note: See TracBrowser for help on using the repository browser.