diff --git a/Examples/python/fitting/ex10_FitGALAXIData/FitGALAXIData_new.py b/Examples/python/fitting/ex10_FitGALAXIData/FitGALAXIData_new.py index a9d158af52deb5eb00275a4dfe18b984e032268e..c68f50e9cfad9a4c1892742d182e8991bcd6bbed 100644 --- a/Examples/python/fitting/ex10_FitGALAXIData/FitGALAXIData_new.py +++ b/Examples/python/fitting/ex10_FitGALAXIData/FitGALAXIData_new.py @@ -5,7 +5,8 @@ import matplotlib from matplotlib import pyplot as plt import numpy import bornagain as ba -from SampleBuilder import MySampleBuilder +from bornagain import nm as nm +from SampleBuilder_new import MySampleBuilder wavelength = 1.34*ba.angstrom alpha_i = 0.463*ba.deg @@ -29,7 +30,7 @@ def create_detector(): return detector -def create_simulation(): +def create_simulation(params): """ Creates and returns GISAS simulation with beam and detector defined """ @@ -47,6 +48,11 @@ def create_simulation(): # beam divergence # alpha_distr = ba.DistributionGaussian(alpha_i, 0.02*ba.deg) # simulation.addParameterDistribution("*/Beam/Alpha", alpha_distr, 5) + + sample_builder = MySampleBuilder() + sample = sample_builder.create_sample(params) + simulation.setSample(sample) + return simulation @@ -55,47 +61,27 @@ def load_real_data(filename="galaxi_data.tif.gz"): Fill histogram representing our detector with intensity data from tif file. Returns cropped version of it, which represent the area we are interested in. """ - hist = ba.IHistogram.createFrom(filename) + hist = ba.IHistogram.createFrom(filename).array() return hist def run_fitting(): - simulation = create_simulation() - sample_builder = MySampleBuilder() - simulation.setSampleBuilder(sample_builder) - real_data = load_real_data() - fit_suite = ba.FitSuite() - draw_observer = ba.DefaultFitObserver(draw_every_nth=10) - fit_suite.attachObserver(draw_observer) - fit_suite.initPrint(10) - fit_suite.addSimulationAndRealData(simulation, real_data) - - # setting fitting parameters with starting values - fit_suite.addFitParameter( - "*radius", 5.0*ba.nm, ba.AttLimits.limited(4.0, 6.0), - 0.1*ba.nm) - fit_suite.addFitParameter( - "*sigma", 0.55, ba.AttLimits.limited(0.2, 0.8), 0.01*ba.nm) - fit_suite.addFitParameter( - "*distance", 27.*ba.nm, ba.AttLimits.limited(20, 70), - 0.1*ba.nm) - - use_two_minimizers_strategy = False - if use_two_minimizers_strategy: - strategy1 = ba.AdjustMinimizerStrategy("Genetic") - fit_suite.addFitStrategy(strategy1) - - # Second fit strategy will use another algorithm. - # It will use best parameters found from previous minimization round. - strategy2 = ba.AdjustMinimizerStrategy("Minuit2", "Migrad") - fit_suite.addFitStrategy(strategy2) - - # running fit - fit_suite.runFit() - - plt.show() + fit_objective = ba.FitObjective() + fit_objective.addSimulationAndData(create_simulation, real_data, 1.0) + fit_objective.initPrint(10) + fit_objective.initPlot(10) + + params = ba.Parameters() + params.add("radius", 5.*nm, min=4.0, max=6.0, 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.0, max=70.0) + + minimizer = ba.Minimizer() + result = minimizer.minimize(fit_objective.evaluate, params) + fit_objective.finalize(result) + if __name__ == '__main__': run_fitting() diff --git a/Examples/python/fitting/ex10_FitGALAXIData/SampleBuilder_new.py b/Examples/python/fitting/ex10_FitGALAXIData/SampleBuilder_new.py index 4561e114cb4ad1245f096b13a20c3e26da34d234..7cb141e5f99df8505c0845ce32e0b6d2498b5cd8 100644 --- a/Examples/python/fitting/ex10_FitGALAXIData/SampleBuilder_new.py +++ b/Examples/python/fitting/ex10_FitGALAXIData/SampleBuilder_new.py @@ -3,37 +3,30 @@ Air layer is populated with spheres with some size distribution. """ import bornagain as ba -import ctypes -class MySampleBuilder(ba.IMultiLayerBuilder): +class MySampleBuilder(): """ """ def __init__(self): - ba.IMultiLayerBuilder.__init__(self) - self.sample = None - # parameters describing the sample - self.radius = ctypes.c_double(5.75*ba.nm) - self.sigma = ctypes.c_double(0.4) - self.distance = ctypes.c_double(53.6*ba.nm) - self.disorder = ctypes.c_double(10.5*ba.nm) - self.kappa = ctypes.c_double(17.5) - self.ptfe_thickness = ctypes.c_double(22.1*ba.nm) - self.hmdso_thickness = ctypes.c_double(18.5*ba.nm) + self.radius = 5.75*ba.nm + self.sigma = 0.4 + self.distance = 53.6*ba.nm + self.disorder = 10.5*ba.nm + self.kappa = 17.5 + self.ptfe_thickness = 22.1*ba.nm + self.hmdso_thickness = 18.5*ba.nm - # register parameters - self.registerParameter("radius", ctypes.addressof(self.radius)) - self.registerParameter("sigma", ctypes.addressof(self.sigma)) - self.registerParameter("distance", ctypes.addressof(self.distance)) - self.registerParameter("disorder", ctypes.addressof(self.disorder)) - self.registerParameter("kappa", ctypes.addressof(self.kappa)) - self.registerParameter("tptfe", ctypes.addressof(self.ptfe_thickness)) - self.registerParameter("thmdso", ctypes.addressof(self.hmdso_thickness)) + def create_sample(self, params): + self.radius = params["radius"] + self.sigma = params["sigma"] + self.distance = params["distance"] + return self.multilayer() # constructs the sample for current values of parameters - def buildSample(self): + def multilayer(self): # defining materials m_air = ba.HomogeneousMaterial("Air", 0.0, 0.0) m_Si = ba.HomogeneousMaterial("Si", 5.78164736e-6, 1.02294578e-7) @@ -44,18 +37,18 @@ class MySampleBuilder(ba.IMultiLayerBuilder): # collection of particles with size distribution nparticles = 20 nfwhm = 2.0 - sphere_ff = ba.FormFactorFullSphere(self.radius.value) + sphere_ff = ba.FormFactorFullSphere(self.radius) # sphere_ff = ba.FormFactorTruncatedSphere( - # self.radius.value, self.radius.value*1.5) + # self.radius, self.radius*1.5) sphere = ba.Particle(m_Ag, sphere_ff) position = ba.kvector_t(0*ba.nm, 0*ba.nm, - -1.0*self.hmdso_thickness.value) + -1.0*self.hmdso_thickness) sphere.setPosition(position) - ln_distr = ba.DistributionLogNormal(self.radius.value, self.sigma.value) + ln_distr = ba.DistributionLogNormal(self.radius, self.sigma) par_distr = ba.ParameterDistribution( "/Particle/FullSphere/Radius", ln_distr, nparticles, nfwhm, - ba.RealLimits.limited(0.0, self.hmdso_thickness.value/2.0)) + ba.RealLimits.limited(0.0, self.hmdso_thickness/2.0)) # par_distr = ba.ParameterDistribution( # "/Particle/TruncatedSphere/Radius", ln_distr, nparticles, nfwhm) # par_distr.linkParameter("/Particle/TruncatedSphere/Height") @@ -63,10 +56,10 @@ class MySampleBuilder(ba.IMultiLayerBuilder): # interference function interference = ba.InterferenceFunctionRadialParaCrystal( - self.distance.value, 1e6*ba.nm) - interference.setKappa(self.kappa.value) + self.distance, 1e6*ba.nm) + interference.setKappa(self.kappa) interference.setDomainSize(20000.0) - pdf = ba.FTDistribution1DGauss(self.disorder.value) + pdf = ba.FTDistribution1DGauss(self.disorder) interference.setProbabilityDistribution(pdf) # assembling particle layout @@ -82,9 +75,9 @@ class MySampleBuilder(ba.IMultiLayerBuilder): # layers air_layer = ba.Layer(m_air) - hmdso_layer = ba.Layer(m_HMDSO, self.hmdso_thickness.value) + hmdso_layer = ba.Layer(m_HMDSO, self.hmdso_thickness) hmdso_layer.addLayout(particle_layout) - ptfe_layer = ba.Layer(m_PTFE, self.ptfe_thickness.value) + ptfe_layer = ba.Layer(m_PTFE, self.ptfe_thickness) substrate_layer = ba.Layer(m_Si) # assembling multilayer