minimizer_settings.py 3.78 KB
Newer Older
1
#!/usr/bin/env python3
2
3
4
5
6
7
8
"""
Fitting example: running same fit using various minimizer and their settings.
"""
import bornagain as ba
from bornagain import deg, angstrom, nm


9
def get_sample(params):
10
11
12
    """
    Returns a sample with uncorrelated cylinders and prisms on a substrate.
    """
13
14
15
16
17
    cylinder_height = params["cylinder_height"]
    cylinder_radius = params["cylinder_radius"]
    prism_height = params["prism_height"]
    prism_base_edge = params["prism_base_edge"]

18
    # defining materials
19
20
21
    m_vacuum = ba.RefractiveMaterial("Vacuum", 0, 0)
    m_substrate = ba.RefractiveMaterial("Substrate", 6e-6, 2e-8)
    m_particle = ba.RefractiveMaterial("Particle", 6e-4, 2e-8)
22
23

    # collection of particles
24
    cylinder_ff = ba.Cylinder(cylinder_radius, cylinder_height)
25
    cylinder = ba.Particle(m_particle, cylinder_ff)
26
    prism_ff = ba.Prism3(prism_base_edge, prism_height)
27
    prism = ba.Particle(m_particle, prism_ff)
28
29
30
    layout = ba.ParticleLayout()
    layout.addParticle(cylinder, 0.5)
    layout.addParticle(prism, 0.5)
31
32
    interference = ba.InterferenceNone()
    layout.setInterference(interference)
33

34
35
36
    # vacuum layer with particles and substrate form multi layer
    vacuum_layer = ba.Layer(m_vacuum)
    vacuum_layer.addLayout(layout)
37
    substrate_layer = ba.Layer(m_substrate, 0)
38
39
40
41
    sample = ba.MultiLayer()
    sample.addLayer(vacuum_layer)
    sample.addLayer(substrate_layer)
    return sample
42
43


44
def get_simulation(params):
45
46
47
    """
    Returns a GISAXS simulation with beam and detector defined
    """
48
    beam = ba.InBeam(1e8, 1*angstrom, 0.2*deg)
49
    n = 100 # bp.simargs['n']
50
    detector = ba.SphericalDetector(n, -1*deg, 1*deg, n, 0, 2*deg)
51
    return ba.ScatteringSimulation(beam, get_sample(params), detector)
52
53


54
55
def create_real_data():
    """
Pospelov, Gennady's avatar
Pospelov, Gennady committed
56
    Generating "real" data from simulated image with default parameters.
57
58
    """

59
    params = {
Wuttke, Joachim's avatar
Wuttke, Joachim committed
60
61
62
63
        'cylinder_height': 5*nm,
        'cylinder_radius': 5*nm,
        'prism_height': 5*nm,
        'prism_base_edge': 5*nm
64
    }
65
66

    simulation = get_simulation(params)
67
    result = simulation.simulate()
68

69
    return result.array()
70
71


72
73
def run_fitting():
    """
74
    main function to run fitting
75
76
    """

77
78
    real_data = create_real_data()

79
    # prints info about available minimizers
80
    print(ba.MinimizerFactory().catalogToString())
81
82

    # prints detailed info about available minimizers and their options
83
    print(ba.MinimizerFactory().catalogDetailsToString())
84

85
    fit_objective = ba.FitObjective()
Wuttke, Joachim's avatar
Wuttke, Joachim committed
86
    fit_objective.addSimulationAndData(get_simulation, real_data, 1)
87
    fit_objective.initPrint(10)
88

89
    params = ba.Parameters()
90
91
92
93
    params.add("cylinder_height", 4.*nm, min=0.01)
    params.add("cylinder_radius", 6.*nm, min=0.01)
    params.add("prism_height", 4.*nm, min=0.01)
    params.add("prism_base_edge", 12.*nm, min=0.01)
94

95
    minimizer = ba.Minimizer()
96
97

    # Uncomment one of the line below to adjust minimizer settings
98
99
100
101
102
103
104
    """
    Setting Minuit2 minimizer with Migrad algorithm, limiting number of iterations.
    Minimization will try to respect MaxFunctionCalls value.
    """
    # minimizer.setMinimizer("Minuit2", "Migrad", "MaxFunctionCalls=50")
    """
    Setting two options at once.
105
    Strategy=2 promises more accurate fit.
106
107
108
109
110
111
112
113
114
115
    """
    # minimizer.setMinimizer("Minuit2", "Migrad", "MaxFunctionCalls=500;Strategy=2")
    """
    Setting Minuit2 minimizer with Fumili algorithm.
    """
    # minimizer.setMinimizer("Minuit2", "Fumili")
    """
    Setting Levenberg-Marquardt algorithm.
    """
    # minimizer.setMinimizer("GSLLMA")
116

117
    result = minimizer.minimize(fit_objective.evaluate_residuals, params)
118

119
    fit_objective.finalize(result)
120
121

    print("Fitting completed.")
122
123
124
125
    print("chi2:", result.minValue())
    for fitPar in result.parameters():
        print(fitPar.name(), fitPar.value, fitPar.error)

126
127
128

if __name__ == '__main__':
    run_fitting()