Analysing non-spin flip data (mark2)
refnx
recently added the ability to perform polarised neutron reflectometry analysis in v0.1.51. Here we analyse datasets that uses magnetic films and PNR as an extra contrast. The datasets of interest have the structure:
Si | SiO2 | Permalloy | Au | 2-mercaptoethanol | D2O
# some necessary imports
import os.path
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import refnx
from refnx.analysis import Parameter, Objective, CurveFitter, GlobalObjective
from refnx.reflect import (
SLD,
Slab,
Structure,
MagneticSlab,
PolarisedReflectModel,
SpinChannel,
)
from refnx.dataset import Data1D
# create datasets from the NSF PNR data
pth = os.path.dirname(refnx.__file__)
dd = "c_PLP0007882.dat"
uu = "c_PLP0007885.dat"
file_path_uu = os.path.join(pth, "reflect", "test", uu)
file_path_dd = os.path.join(pth, "reflect", "test", dd)
data_uu = Data1D(file_path_uu)
data_dd = Data1D(file_path_dd)
# create SLD (Scattering Length Density) objects for each of the materials
si = SLD(2.07, name="Si")
sio2 = SLD(3.47, name="SiO2")
au = SLD(4.66, name="Au")
mercapto = SLD(3.49, name="2-mercaptoethanol")
d2o = SLD(6.35, name="d2o")
py = SLD(9.0, name="permalloy")
# Now make Slabs that describe each layer. These can either be made from SLD objects,
# or by using the `Slab` constructor directly.
# sio2 slab has a thickness of 20 and roughness of 4 with the Si fronting medium
sio2_l = sio2(20, 4)
au_l = au(215, 4)
mercapto_l = mercapto(8, 4)
d2o_l = d2o(0, 4)
Now let’s make the Permalloy layer. To do this we need to utilise a MagneticSlab
Component. The value of 1.75 represents a magnetic SLD correction of $1.75\times 10^{-6}\A^{-2}$. The value of thetaM=90
(degrees) represents the angle of the magnetic moment in the plane of the sample. For the applied magnetic field to be the plane of the sample Aguide=270
or 90
. For the magnetic moment to be parallel or antiparallel to the applied field thetaM=90
or 270
degrees respectively.
# now make the Py layer
py_thickness = Parameter(50, name="Py thickness")
py_roughness = Parameter(5, name="Py roughness")
py_l = MagneticSlab(py_thickness, py, py_roughness, 1.75, 90.0, name="Py slab")
s = si | sio2_l | py_l | au_l | mercapto_l | d2o_l
# Note that we're using the same structure to describe both spin channels.
model_dd = PolarisedReflectModel(s, spin=SpinChannel.DOWN_DOWN, Aguide=270)
model_uu = PolarisedReflectModel(s, spin=SpinChannel.UP_UP, Aguide=270)
objective_dd = Objective(model_dd, data_dd)
objective_uu = Objective(model_uu, data_uu)
global_objective = GlobalObjective([objective_dd, objective_uu])
# select the parameters to be fitted and their bounds
model_uu.scale.setp(vary=True, bounds=(0.9, 1.1))
model_uu.bkg.setp(vary=True, bounds=(1e-7, 5e-6))
model_dd.scale.setp(vary=True, bounds=(0.9, 1.1))
model_dd.bkg.setp(vary=True, bounds=(1e-7, 5e-6))
sio2_l.thick.setp(vary=True, bounds=(10, 25))
sio2_l.rough.setp(vary=True, bounds=(1, 8))
py_thickness.setp(vary=True, bounds=(38, 55))
py_roughness.setp(vary=True, bounds=(1, 8))
py.real.setp(vary=True, bounds=(9, 9.5))
py_l.rhoM.setp(vary=True, bounds=(1.5, 3.0))
au_l.thick.setp(vary=True, bounds=(200, 240))
au_l.rough.setp(vary=True, bounds=(1, 8))
au.real.setp(vary=True, bounds=(4.5, 4.66))
mercapto_l.thick.setp(vary=True, bounds=(5, 15))
mercapto_l.rough.setp(vary=True, bounds=(1, 8))
mercapto.real.setp(vary=True, bounds=(3, 4))
d2o_l.rough.setp(vary=True, bounds=(1, 8))
d2o.real.setp(vary=True, bounds=(6.2, 6.36))
fitter = CurveFitter(global_objective)
fitter.fit("differential_evolution", seed=1);
-1271.4413157228305: : 62it [02:51, 2.76s/it]
fig, ax = plt.subplots()
plt.scatter(data_dd.x, data_dd.y, label="dd", s=4)
plt.plot(data_dd.x, objective_dd.generative())
plt.scatter(data_uu.x, data_uu.y, label="uu", s=4)
plt.plot(data_uu.x, objective_uu.generative())
plt.ylabel("R")
plt.xlabel("Q / $\\AA^{-1}$")
plt.yscale("log")
plt.xscale("log")
plt.legend();