1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
#!/usr/bin/env python3
"""
Fitting experimental data: spherical nanoparticles with size distribution
in 3 layers system (experiment at GALAXI).
"""
import os
import bornagain as ba
from bornagain import nm, ba_fitmonitor
from matplotlib import pyplot as plt
wavelength = 1.34*ba.angstrom
alpha_i = 0.463*ba.deg
# detector setup as given from instrument responsible
pilatus_npx, pilatus_npy = 981, 1043
pilatus_pixel_size = 0.172 # in mm
detector_distance = 1730.0 # in mm
beam_xpos, beam_ypos = 597.1, 323.4 # in pixels
datadir = os.getenv('BA_EXAMPLE_DATA_DIR', '')
if not datadir:
raise Exception("Environment variable BA_EXAMPLE_DATA_DIR not set")
# sample model
radius = 5.75*ba.nm
sigma = 0.4
distance = 53.6*ba.nm
disorder = 10.5*ba.nm
kappa = 17.5
ptfe_thickness = 22.1*ba.nm
hmdso_thickness = 18.5*ba.nm
def get_sample(params):
radius = params["radius"]
sigma = params["sigma"]
distance = params["distance"]
# defining materials
m_vacuum = ba.RefractiveMaterial("Vacuum", 0, 0)
m_Si = ba.RefractiveMaterial("Si", 5.7816e-6, 1.0229e-7)
m_Ag = ba.RefractiveMaterial("Ag", 2.2475e-5, 1.6152e-6)
m_PTFE = ba.RefractiveMaterial("PTFE", 5.20509e-6, 1.9694e-8)
m_HMDSO = ba.RefractiveMaterial("HMDSO", 2.0888e-6, 1.3261e-8)
# collection of particles with size distribution
nparticles = 20
nfwhm = 2.0
sphere_ff = ba.Sphere(radius)
sphere = ba.Particle(m_Ag, sphere_ff)
position = R3(0, 0, -1*hmdso_thickness)
sphere.translate(position)
# ln_distr = ba.DistributionLogNormal(radius, sigma)
# par_distr = ba.ParameterDistribution(
# "/Particle/Sphere/Radius", ln_distr, nparticles, nfwhm,
# part_coll = ba.ParticleDistribution(sphere, par_distr)
# interference function
interference = ba.InterferenceRadialParacrystal(
distance, 1e6*ba.nm)
interference.setKappa(kappa)
interference.setDomainSize(2e4*nm)
pdf = ba.Profile1DGauss(disorder)
interference.setProbabilityDistribution(pdf)
# assembling particle layout
layout = ba.ParticleLayout()
layout.addParticle(sphere, 1)
layout.setInterference(interference)
layout.setTotalParticleSurfaceDensity(1)
# roughness
r_ptfe = ba.LayerRoughness(2.3*ba.nm, 0.3, 5*ba.nm)
r_hmdso = ba.LayerRoughness(1.1*ba.nm, 0.3, 5*ba.nm)
# layers
vacuum_layer = ba.Layer(m_vacuum)
hmdso_layer = ba.Layer(m_HMDSO, hmdso_thickness)
hmdso_layer.addLayout(layout)
ptfe_layer = ba.Layer(m_PTFE, ptfe_thickness)
substrate_layer = ba.Layer(m_Si)
# assembling sample
sample = ba.MultiLayer()
sample.addLayer(vacuum_layer)
sample.addLayerWithTopRoughness(hmdso_layer, r_hmdso)
sample.addLayerWithTopRoughness(ptfe_layer, r_ptfe)
sample.addLayer(substrate_layer)
return sample
def create_detector():
"""
Returns a model of the GALAXY detector
"""
u0 = beam_xpos*pilatus_pixel_size # in mm
v0 = beam_ypos*pilatus_pixel_size # in mm
detector = ba.RectangularDetector(pilatus_npx,
pilatus_npx*pilatus_pixel_size,
pilatus_npy,
pilatus_npy*pilatus_pixel_size)
detector.setPerpendicularToDirectBeam(detector_distance, u0, v0)
return detector
def create_simulation(params):
"""
Creates and returns GISAS simulation with beam and detector defined
"""
beam = ba.Beam(1.2e7, wavelength, alpha_i)
sample = get_sample(params)
detector = create_detector()
simulation = ba.ScatteringSimulation(beam, sample, detector)
simulation.setRegionOfInterest(85, 70, 120, 92.)
# beamstop:
simulation.addMask(ba.Rectangle(101.9, 82.1, 103.7, 85.2), True)
return simulation
def load_real_data(filename):
"""
Loads experimental data and returns numpy array.
"""
filepath = os.path.join(datadir, filename)
return ba.IOFactory.readDatafield(filepath).npArray()
def run_fitting():
real_data = load_real_data("galaxi_data.tif.gz")
fit_objective = ba.FitObjective()
fit_objective.addSimulationAndData(create_simulation, real_data, 1)
fit_objective.initPrint(10)
observer = ba_fitmonitor.PlotterGISAS()
fit_objective.initPlot(10, observer)
params = ba.Parameters()
params.add("radius", 5.*nm, min=4, max=6, step=0.1*nm)
params.add("sigma", 0.55, min=0.2, max=0.8, step=0.01)
params.add("distance", 27.*nm, min=20, max=70)
minimizer = ba.Minimizer()
result = minimizer.minimize(fit_objective.evaluate, params)
fit_objective.finalize(result)
if __name__ == '__main__':
run_fitting()
plt.show()
|