1 | r""" |
---|
2 | This model calculates an empirical functional form for SAS data using SpericalSLD profile |
---|
3 | |
---|
4 | Similarly to the OnionExpShellModel, this model provides the form factor, P(q), for a multi-shell sphere, |
---|
5 | where the interface between the each neighboring shells can be described by one of a number of functions |
---|
6 | including error, power-law, and exponential functions. This model is to calculate the scattering intensity |
---|
7 | by building a continuous custom SLD profile against the radius of the particle. The SLD profile is composed |
---|
8 | of a flat core, a flat solvent, a number (up to 9 ) flat shells, and the interfacial layers between |
---|
9 | the adjacent flat shells (or core, and solvent) (see below). |
---|
10 | Unlike the OnionExpShellModel (using an analytical integration), |
---|
11 | the interfacial layers here are sub-divided and numerically integrated assuming each of the sub-layers are described |
---|
12 | by a line function. The number of the sub-layer can be given by users by setting the integer values of npts_inter |
---|
13 | in the GUI. The form factor is normalized by the total volume of the sphere. |
---|
14 | |
---|
15 | Definition |
---|
16 | ---------- |
---|
17 | |
---|
18 | The scattering intensity $I(q)$ in 1D is calculated as: |
---|
19 | |
---|
20 | .. math:: |
---|
21 | |
---|
22 | P(q) = \frac{f^2}{V_\text{particle}} |
---|
23 | f = f_\text{core} + \sum_{\text{inter}_i=0}^N f_text{inter}_i + |
---|
24 | \sum_{\text{flat}_i=0}^N f_text{flat}_i +f_\text{solvent} |
---|
25 | |
---|
26 | where, for a spherically symmetric particle with a particle density \rho(r) |
---|
27 | |
---|
28 | |
---|
29 | The scaling of the second power law region (coefficent C) is then automatically scaled to |
---|
30 | match the first by following formula |
---|
31 | |
---|
32 | .. math:: |
---|
33 | C = \frac{A}{qc^{-m1} qc^{-m2}} |
---|
34 | |
---|
35 | .. note:: |
---|
36 | Be sure to enter the power law exponents as positive values! |
---|
37 | |
---|
38 | For 2D data the scattering intensity is calculated in the same way as 1D, |
---|
39 | where the $q$ vector is defined as |
---|
40 | |
---|
41 | .. math:: |
---|
42 | |
---|
43 | q = \sqrt{q_x^2 + q_y^2} |
---|
44 | |
---|
45 | |
---|
46 | .. figure:: img/two_power_law_1d.jpg |
---|
47 | |
---|
48 | 1D plot using the default values (w/500 data point). |
---|
49 | |
---|
50 | References |
---|
51 | ---------- |
---|
52 | L A Feigin and D I Svergun, Structure Analysis by Small-Angle X-Ray and Neutron Scattering, Plenum Press, New York, (1987) |
---|
53 | |
---|
54 | """ |
---|
55 | |
---|
56 | from numpy import inf |
---|
57 | |
---|
58 | name = "spherical_sld" |
---|
59 | title = "Sperical SLD intensity calculation" |
---|
60 | description = """ |
---|
61 | I(q) = |
---|
62 | background = Incoherent background [1/cm] |
---|
63 | """ |
---|
64 | category = "shere-based" |
---|
65 | |
---|
66 | # pylint: disable=bad-whitespace, line-too-long |
---|
67 | # ["name", "units", default, [lower, upper], "type", "description"], |
---|
68 | parameters = [["n_shells", "", 1, [0, 9], "", "number of shells"], |
---|
69 | ["npts_imter", "", 35, [0, inf], "", "number of points in each sublayer"], |
---|
70 | ["sld_solv", "1/Ang^2", 1E-6,[-inf, inf], "","sld function solvent"], |
---|
71 | ["func_inter_0", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
72 | ["nu_inter_0", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
73 | ["thick_inter_0", "Ang", 50, [-inf, inf], "", "intern layer thickness"], |
---|
74 | ["sld_core_0", "1/Ang^2", 2.07E-6, [-inf, inf],"", "sld function flat"], |
---|
75 | ["thick_flat_0", "Ang", 100, [-inf, inf], "", "flat layer_thickness"], |
---|
76 | ["func_inter_1", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
77 | ["nu_inter_1", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
78 | ["thick_inter_1", "Ang", 50.0, [-inf, inf], "", "intern layer thickness"], |
---|
79 | ["sld_flat_1", "1/Ang^2", 4.06E-6, [-inf, inf],"", "sld function flat"], |
---|
80 | ["thick_flat_1", "Ang", 100.0, [-inf, inf], "", "flat layer_thickness"], |
---|
81 | ["func_inter_2", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
82 | ["nu_inter_2", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
83 | ["thick_inter_2", "Ang", 50.0, [-inf, inf], "", "intern layer thickness"], |
---|
84 | ["sld_flat_2", "1/Ang^2", 3.56E-6, [-inf, inf],"", "sld function flat"], |
---|
85 | ["thick_flat_2", "Ang", 100.0, [-inf, inf], "", "flat layer_thickness"], |
---|
86 | ["func_inter_3", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
87 | ["nu_inter_3", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
88 | ["thick_inter_3", "Ang", 50.0, [-inf, inf], "", "intern layer thickness"], |
---|
89 | ["sld_flat_3", "1/Ang^2", 4.06E-6, [-inf, inf],"", "sld function flat"], |
---|
90 | ["thick_flat_3", "Ang", 100.0, [-inf, inf], "", "flat layer_thickness"], |
---|
91 | ["func_inter_4", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
92 | ["nu_inter_4", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
93 | ["thick_inter_4", "Ang", 50.0, [-inf, inf], "", "intern layer thickness"], |
---|
94 | ["sld_flat_4", "1/Ang^2", 3.5E-6, [-inf, inf],"", "sld function flat"], |
---|
95 | ["thick_flat_4", "Ang", 100.0, [-inf, inf], "", "flat layer_thickness"], |
---|
96 | ["func_inter_5", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
97 | ["nu_inter_5", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
98 | ["thick_inter_5", "Ang", 50.0, [-inf, inf], "", "intern layer thickness"], |
---|
99 | ["sld_flat_5", "1/Ang^2", 4.06E-6, [-inf, inf],"", "sld function flat"], |
---|
100 | ["thick_flat_5", "Ang", 100.0, [-inf, inf], "", "flat layer_thickness"], |
---|
101 | ["func_inter_6", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
102 | ["nu_inter_6", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
103 | ["thick_inter_6", "Ang", 50.0, [-inf, inf], "", "intern layer thickness"], |
---|
104 | ["sld_flat_6", "1/Ang^2", 3.5E-6, [-inf, inf],"", "sld function flat"], |
---|
105 | ["thick_flat_6", "Ang", 100.0, [-inf, inf], "", "flat layer_thickness"], |
---|
106 | ["func_inter_7", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
107 | ["nu_inter_7", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
108 | ["thick_inter_7", "Ang", 50.0, [-inf, inf], "", "intern layer thickness"], |
---|
109 | ["sld_flat_7", "1/Ang^2", 4.06E-6, [-inf, inf],"", "sld function flat"], |
---|
110 | ["thick_flat_7", "Ang", 100.0, [-inf, inf], "", "flat layer_thickness"], |
---|
111 | ["func_inter_8", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
112 | ["nu_inter_8", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
113 | ["thick_inter_8", "Ang", 50.0, [-inf, inf], "", "intern layer thickness"], |
---|
114 | ["sld_flat_8", "1/Ang^2", 3.5E-6, [-inf, inf],"", "sld function flat"], |
---|
115 | ["thick_flat_8", "Ang", 100.0, [-inf, inf], "", "flat layer_thickness"], |
---|
116 | ["func_inter_9", "", 0, [0, 4], "", "'Erf(|nu|*z)':0, 'RPower(z^|nu|)':1, 'LPower(z^|nu|)':2, 'RExp(-|nu|*z)':3, 'LExp(-|nu|*z)':4"], |
---|
117 | ["nu_inter_9", "", 2.5, [-inf, inf], "", "steepness parameter"], |
---|
118 | ["thick_inter_9", "Ang", 50.0, [-inf, inf], "", "intern layer thickness"], |
---|
119 | ["sld_flat_9", "1/Ang^2", 4.06E-6, [-inf, inf],"", "sld function flat"], |
---|
120 | ["thick_flat_9", "Ang", 100.0, [-inf, inf], "", "flat layer_thickness"], |
---|
121 | ] |
---|
122 | # pylint: enable=bad-whitespace, line-too-long |
---|
123 | source = ["lib/librefl.c", "spherical_sld.c"] |
---|
124 | |
---|
125 | |
---|
126 | #TODO: Not clear if dispersion function is needed |
---|
127 | #def _set_dispersion(self): |
---|
128 | # """ |
---|
129 | # Setting dispersion for all shells |
---|
130 | # """ |
---|
131 | # ##set dispersion from model |
---|
132 | # for name , value in self.model.dispersion.iteritems(): |
---|
133 | # |
---|
134 | # nshell = -1 |
---|
135 | # if name.split('_')[0] == 'thick': |
---|
136 | # while nshell < 1: |
---|
137 | # nshell += 1 |
---|
138 | # if name.split('_')[1] == 'inter%s' % str(nshell): |
---|
139 | # self.dispersion[name] = value |
---|
140 | # else: |
---|
141 | # continue |
---|
142 | # else: |
---|
143 | # self.dispersion[name] = value |
---|
144 | |
---|
145 | |
---|
146 | def ER(radius): |
---|
147 | """ |
---|
148 | Calculate the effective radius for P(q)*S(q) |
---|
149 | Tale different radius values from corresponding shells |
---|
150 | |
---|
151 | :return: the value of the effective radius |
---|
152 | """ |
---|
153 | |
---|
154 | return radius |
---|
155 | |
---|
156 | |
---|
157 | demo = dict(scale=1, background=0.1, |
---|
158 | n_shells=1, |
---|
159 | npts_inter=35, |
---|
160 | sld_solv=1E-6, |
---|
161 | func_inter_1=0.0, |
---|
162 | nu_inter_1=2.5, |
---|
163 | thick_inter_1=50, |
---|
164 | sld_flat_1=4E-6, |
---|
165 | thick_flat_1=100, |
---|
166 | func_inter_0=0.0, |
---|
167 | nu_inter_0=2.5, |
---|
168 | rad_core_0=50.0, |
---|
169 | std_core_0=2.07E-6, |
---|
170 | thick_core_0=50 |
---|
171 | ) |
---|
172 | |
---|
173 | oldname = "SphericalSLDModel" |
---|
174 | oldpars = dict( |
---|
175 | npts_inter='npts_imter', |
---|
176 | sld_solv='sld_solv', |
---|
177 | func_inter_1='func_inter_1', |
---|
178 | nu_inter_1='nu_inter', |
---|
179 | thick_inter_1='thick_inter1', |
---|
180 | sld_flat_1='sld_flat1', |
---|
181 | thick_flat_1='thick_flat1', |
---|
182 | func_inter_0='nu_inter0', |
---|
183 | nu_inter_0='nu_inter0', |
---|
184 | rad_core_0='rad_core0', |
---|
185 | std_core_0='std_core0', |
---|
186 | thick_core_0='thick_core0', |
---|
187 | background='background') |
---|
188 | |
---|
189 | tests = [ |
---|
190 | # Accuracy tests based on content in test/utest_extra_models.py |
---|
191 | [{'npts_iter':35, |
---|
192 | 'sld_solv':1E-6, |
---|
193 | 'func_inter_1':0.0, |
---|
194 | 'nu_inter':2.5, |
---|
195 | 'thick_inter_1':50, |
---|
196 | 'sld_flat_1':4E-6, |
---|
197 | 'thick_flat_1':100, |
---|
198 | 'func_inter_0':0.0, |
---|
199 | 'nu_inter_0':2.5, |
---|
200 | 'rad_core_0':50.0, |
---|
201 | 'std_core_0':2.07E-6, |
---|
202 | 'thick_core':50, |
---|
203 | 'background': 0.0, |
---|
204 | }, 0.001, 1000], |
---|
205 | ] |
---|