Effect of S(Q) extrapolation to zero on resulting PDFs

We are going to load a data pattern and background Pattern of \(Mg_2SiO_4\). The data is not optimal since it was not corrected for self-absorption or oblique x-ray incidence on the detector. A way to try to correct for this artificially is using an optimization method described in Eggert et al. (2002). This is very useful for the data analysis of total scattering experiments from a sample loaded in a diamond anvil cell were the background might change with compression and therefore almost never is perfect.

[1]:
%matplotlib inline
import matplotlib.pyplot as plt

from glassure.calc import calculate_fr, calculate_sq, calculate_gr
from glassure.normalization import normalize_fit, normalize
from glassure.optimization import optimize_sq
from glassure.utility import extrapolate_to_zero_linear, convert_density_to_atoms_per_cubic_angstrom, \
  calculate_f_mean_squared, calculate_f_squared_mean, calculate_incoherent_scattering, calculate_s0
from glassure import Pattern
from tests import data_path

1. Effect on S(Q)

We are going to compare three different S(Q) pattern:

  • “raw”: pattern which is just the collected diffraction data subtracted by its background

  • “opt”: pattern optimized for an \(r_{cutoff}\) of 1.5 and using 5 iterations

  • “extr_opt”: raw pattern which was extrapolated to zero using a polynomial function and then optimized by the same parameters as “opt”

[2]:
data_pattern = Pattern.from_file(data_path('Mg2SiO4_ambient.xy'))
bkg_pattern = Pattern.from_file(data_path('Mg2SiO4_ambient_bkg.xy'))
sample_pattern = data_pattern - bkg_pattern

composition = {'Mg': 2, 'Si':1, 'O':4}
density = 2.9
atomic_density = convert_density_to_atoms_per_cubic_angstrom(composition, density)


limited_pattern = sample_pattern.limit(0, 20)

f_squared_mean = calculate_f_squared_mean(composition, limited_pattern.x)
f_mean_squared = calculate_f_mean_squared(composition, limited_pattern.x)
incoherent_scattering = calculate_incoherent_scattering(composition, limited_pattern.x)

params, normalized_pattern = normalize_fit(limited_pattern, f_squared_mean, incoherent_scattering, 5)

n, normalize_pattern = normalize(limited_pattern, atomic_density, f_squared_mean, f_mean_squared, incoherent_scattering)

s0 = calculate_s0(composition)

sq = calculate_sq(normalized_pattern, f_squared_mean, f_mean_squared)
sq_opt = optimize_sq(sq, 1.4, 5, atomic_density)
sq_extr= extrapolate_to_zero_linear(sq, s0)
sq_extr_opt = optimize_sq(sq_extr, 1.4, 10, atomic_density)

plt.figure(figsize=(12, 15))
plt.subplot(2,1,1)
plt.plot(*sq.data, label='raw')
plt.plot(*sq_opt.data, label='opt')
plt.plot(*sq_extr_opt.data, label='extra_opt')
plt.xlabel('Q $(\\AA^{-1})$')
plt.ylabel('S(Q)')
plt.legend()
plt.subplot(2,1,2)
plt.plot(*sq.data, label='raw')
plt.plot(*sq_opt.data, label='opt')
plt.plot(*sq_extr_opt.data, label='extra_opt')
plt.xlabel('Q $(\\AA^{-1})$')
plt.ylabel('S(Q)')
plt.xlim(0, 7)

plt.legend(loc='best');

../_images/notebooks_Effect_of_extrapolation_and_optimization_3_0.png

The two plots clearly show that the optimization on a not extrapolated S(Q) results in an artificial lower intensity of the first sharp diffraction peak. Pointing to that extrapolation is needed for a sensible data analysis.

2. Effect on F(r) and g(r)

In this section we are going to compare F(r) and g(r) for 4 different data analysis methods:

  • “raw”: using S(Q) from the original data without any modification

  • “raw_extr”: using “raw” S(Q) which was extrapolated to zero Q using a polynomial function

  • “opt”: using S(Q) optimized for an \(r_{cutoff}\) of 1.5 and using 10 iterations

  • “extr_opt”: using “opt” S(Q) which additionally was extrapolated to zero Q using a polynomial function and then optimized by the same parameters as “opt”

[3]:
fr = calculate_fr(sq, use_modification_fcn=True)
fr_extr = calculate_fr(sq_extr, use_modification_fcn=True)
fr_opt = calculate_fr(sq_opt, use_modification_fcn=True)
fr_extr_opt = calculate_fr(sq_extr_opt, use_modification_fcn=True)

gr = calculate_gr(fr, atomic_density)
gr_extr = calculate_gr(fr_extr, atomic_density)
gr_opt = calculate_gr(fr_opt, atomic_density)
gr_extr_opt = calculate_gr(fr_extr_opt, atomic_density)

plt.figure(figsize=(12,8))
plt.subplot(1, 2, 1)
plt.plot(*fr.data, label='raw', color='k', ls='-')
plt.plot(*fr_extr.data, label='raw_extr',  color='r', ls='-')
plt.plot(*fr_opt.data, label='opt', color='k', ls='--')
plt.plot(*fr_extr_opt.data, label='extr_opt', color='r', ls='--')
plt.xlim(0,5)
plt.legend(loc='best')
plt.xlabel('r $(\\AA)$')
plt.ylabel('F(r)')
plt.subplot(1, 2, 2)
plt.plot(*gr.data, label='raw', color='k', ls='-')
plt.plot(*gr_extr.data, label='raw_extr',  color='r', ls='-')
plt.plot(*gr_opt.data, label='opt', color='k', ls='--')
plt.plot(*gr_extr_opt.data, label='extr_opt', color='r', ls='--')
plt.ylim(-0.2, 2)
plt.xlim(0, 5)
plt.legend(loc='best')
plt.xlabel('r $(\\AA)$')
plt.ylabel('g(r)');

../_images/notebooks_Effect_of_extrapolation_and_optimization_6_0.png

The two plots show that the intensity of the first peaks strongly depend on whether the S(Q) was extrapolated or not. This has a huge effect on the resulting coordination numbers. Another important fact is that the “raw_extr” is below an r value of 1.4 very close to the optimized transformed data, however the non extrapolated “raw” data has a huge offset, which is further indicating that one should use extrapolation of the S(Q) to zero in order to get meaningful results.