## Experiment at GALAXI

This is an example of a real data fit. We use our own measurements performed at the laboratory diffractometer GALAXI in Forschungszentrum Jülich.

• The sample represents a 4 layer system (substrate, teflon, hmdso and air) with Ag nanoparticles placed inside the hmdso layer on top of the teflon layer.
• The sample is generated with the help of a SampleBuilder, which is able to create samples depending on parameters defined in the constructor and passed through to the create_sample method.
• The nanoparticles have a broad log-normal size distribution.
• The rectangular detector is created to represent the PILATUS detector from the experiment (line 19).
• In the simulation settings the beam is initialized and the detector is assigned to the simulation. A region of interest is assigned at line 39 to simulate only a small rectangular window. Additionally, a rectangular mask is added to exclude the reflected beam from the analysis (line 40).
• The real data is loaded from a tiff file into a histogram representing the detector’s channels.
• The run_fitting() function contains the initialization of the fitting kernel: loading experimental data, assignment of fit pair, fit parameters selection (line 62).
  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 = ba.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.InBeam(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() 
Examples/fit/scatter2d/expfit_galaxi.py