In this notebook we demonstrate implementation of model for calculation of the small angle scattering X-ray data from disperse gold nanoparticles. The experiment details and data files can be found in the original publication (see Example 1)
import escape as esc
esc.require('0.9.6')
import warnings
warnings.filterwarnings("ignore")
import numpy as np
from escape.utils import show
As usual we start with definition of model parameters. The scatterers are homogeneous gold nanoparticles with spherical shape. Below are the required parameters.
# Mean radius
R0 = esc.par("Mean_Radius", 4.48, units="nm")
#We still need a normal radius parameter to perform integration of intensity
R = esc.par("Radius", 4.48, units="nm")
#widths of radius distribution
s_R = esc.par("Sigma_RA", 0.48)
#contrast with water
eta = esc.par("Contrast", 1.13, scale=1e12,
fixed=True, units = "cm^-2")
#Represent number concentration of particles
N = esc.par("NA", 7.68, scale=1e-30)
#Background
B = esc.par("Background", 0, userlim=[0, 1], fixed=True)
Next we implement the form-factor.
#variable is important, you should use the same variable instance for all functors
q = esc.var("q")
#form-factor
P = esc.pow(4.0/3.0 * np.pi * esc.pow(R, 3) * eta *
(3 * (esc.sin(q*R)-q*R*esc.cos(q*R))/esc.pow(q*R, 3.0)), 2)
qrange = np.linspace(0, 5, 1000)
show(P, coordinates=qrange, ylog=True, xlog=True, xlable="Q, 1/nm", ylabel="P(Q)")
After implementing of the form-factor and checking its curve we can finalize our model and to implement integration over size distribution. Here we had to reformulate the expressions, because in ESCAPE there is no Gaussian number-weighted size distribution. For that purposes we introduced expression for $C$ normalization constant which we will use as multipliers for the form-factor expressions.
#ESCAPE Gaussian distribution requires FWHM
fwhm_R = s_R*2.355
#Normalization constant for number size Gaussian distribution
C = 2.0*N/(1.0+esc.erf(R0/(np.sqrt(2.0)*s_R)))
#integration over size distribution
Pr=esc.average_normal(C*P, fwhm_R, R, R0, epsabs=1e-8, epsrel=1e-8, maxiter=30, numpoints=61, numstd=7)
#final intensity
I = Pr + B
show(I, coordinates=qrange, ylog=True, xlog=True, xlabel="Q, 1/nm", ylabel="I")
We are ready now to perform fitting of experimental data. To do that we need to open the data file, which was taken from the supplementary material to the original article. To open the file we will use the numpy library and the loadtxt function. The data will be loaded into the arrays x, y, err. Then we create a data object Escape dobj. The next step is to create a model. Here everything is simple, we will use the function model. The arguments residuals_scale and weight_type are relevant to the calculation of the cost function. Weight_type set to "data" means that the data errors will be used for the weights.
x, y, err=np.loadtxt("data/GoldS2843.pdh", unpack=True)
dobj = esc.data("GoldS2843.pdh", x, y, err, copy=True)
#model
mobj = esc.model("Model", I, dobj, residuals_scale="none", weight_type="data")
It's a good time to create and run an optimizer. We will start by testing the well-known Levenberg-Marquardt optimizer by shaking out the initial parameter values beforehand.
opt = esc.levmar("LM", mobj, maxiter=50, xtol=1e-15, ftol=1e-15, gtol=1e-15, nupdate=1)
opt.shake()
opt()
show(opt, ylog=True, xlog=True, xlabel="Q, 1/nm", ylabel="I")
opt
Name: LM Parameters number: 5 Parameter Value +- Error Units Fixed Mean_Radius 4.4817 +- 0.04777 nm 0 Sigma_RA 0.43678 +- 0.052848 0 NA 7.6931 +- 0.27875 x1e-30 0 Contrast 1.13 +- 0 x1e+12 cm^-2 1 Background 0 +- 0 1
#Differential evolution fit with final polishing of parameters with LMA optimizer
opt = esc.diffevol("DiffEvol", mobj, maxiter=80, polish_final_maxiter=50,
polish_candidate_maxiter=0, minconv=1e-5, nupdate=1)
opt.shake()
opt()
show(opt, ylog=True, xlog=True, xlabel="Q, 1/nm", ylabel="I")
opt
Name: DiffEvol Parameters number: 5 Parameter Value +- Error Units Fixed Mean_Radius 4.4817 +- 0.04777 nm 0 Sigma_RA 0.43678 +- 0.052848 0 NA 7.6931 +- 0.27875 x1e-30 0 Contrast 1.13 +- 0 x1e+12 cm^-2 1 Background 0 +- 0 1
The results of LM and DE optimizers for the presented data are in a good agreement with results presented in the original paper.