## Find background

This example demonstrates how to introduce a background in the simulation and fit its value. Here we are simulating cylinders on top of a substrate without interference. The simulation builder function, defined at line 42, requires 4 parameters:

• the height of the cylinders
• the radius of the cylinders
• the value of the constant background
• a scale factor for the beam’s intensity

The radius and height of the cylinders are passed to the function constructing the multi layer while the scale and background values are used to initialize the instrument.

  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  #!/usr/bin/env python3 """ Fitting example: looking for background and scale factors. Real data contains some "unknown" background and scale factor. In the fit we are trying to find cylinder radius and height, scale and background factors. """ import numpy as np from matplotlib import pyplot as plt import bornagain as ba from bornagain import deg, angstrom, nm def get_sample(params): """ Build the sample representing cylinders on top of substrate without interference. """ radius = params["radius"] height = params["height"] m_vacuum = ba.HomogeneousMaterial("Vacuum", 0, 0) m_substrate = ba.HomogeneousMaterial("Substrate", 6e-6, 2e-8) m_particle = ba.HomogeneousMaterial("Particle", 6e-4, 2e-8) cylinder_ff = ba.FormFactorCylinder(radius, height) cylinder = ba.Particle(m_particle, cylinder_ff) layout = ba.ParticleLayout() layout.addParticle(cylinder) vacuum_layer = ba.Layer(m_vacuum) vacuum_layer.addLayout(layout) substrate_layer = ba.Layer(m_substrate, 0) multi_layer = ba.MultiLayer() multi_layer.addLayer(vacuum_layer) multi_layer.addLayer(substrate_layer) return multi_layer def get_simulation(params): """ Create and return GISAXS simulation with beam and detector defined """ background = params["background"] scale = params["scale"] simulation = ba.GISASSimulation() simulation.setDetectorParameters(100, -1*deg, 1*deg, 100, 0, 2*deg) simulation.setBeamParameters(1*angstrom, 0.2*deg, 0) simulation.beam().setIntensity(1e12*scale) simulation.setBackground(ba.ConstantBackground(background)) simulation.setSample(get_sample(params)) return simulation def create_real_data(): """ Generating "real" data by adding noise, background and scale to the simulated data. Cylinder radius is set to 5nm, cylinder height to 10nm. During the fit we will try to find cylinder height and radius and scale, background factors. """ params = { 'radius': 5*nm, 'height': 10*nm, 'scale': 2, 'background': 1000 } simulation = get_simulation(params) simulation.runSimulation() # retrieving simulated data in the form of numpy array return simulation.result().array() def run_fitting(): """ main function to run fitting """ real_data = create_real_data() fit_objective = ba.FitObjective() fit_objective.addSimulationAndData(get_simulation, real_data, 1) fit_objective.initPrint(10) fit_objective.initPlot(10) params = ba.Parameters() params.add("radius", 5.*nm, vary=False) params.add("height", 9.*nm, min=8.*nm, max=12.*nm) params.add("scale", 1.5, min=1, max=3) params.add("background", 200, min=100, max=2000, step=100) minimizer = ba.Minimizer() result = minimizer.minimize(fit_objective.evaluate, params) fit_objective.finalize(result) if __name__ == '__main__': run_fitting() plt.show() 
find_background.py