Commit fed039a2 authored by Wuttke, Joachim's avatar Wuttke, Joachim
Browse files

Merge branch 'ex3' into 'develop'

Repair fit examples

See merge request !12
parents b8ff8811 24d11a55
Pipeline #33460 passed with stage
in 20 minutes and 33 seconds
...@@ -9,6 +9,7 @@ BornAgain-1.19.0, released 2021.01.xx ...@@ -9,6 +9,7 @@ BornAgain-1.19.0, released 2021.01.xx
* Remove old R&T computations from API (now in Code/Legacy and Tests) * Remove old R&T computations from API (now in Code/Legacy and Tests)
* Make Python plot API entirely keyword based * Make Python plot API entirely keyword based
* Add support for q offset in QSpecScan (redmine 2496) * Add support for q offset in QSpecScan (redmine 2496)
* Remove default Python fit monitor, user must choose between GISAS and specular plotter
> GUI changes: > GUI changes:
* Add top-level menu View, with functionality moved in from other places * Add top-level menu View, with functionality moved in from other places
* Add accelerator keys to menus * Add accelerator keys to menus
......
#!/usr/bin/env python3
import bornagain as ba
def rosenbrock(params):
x = params["x"].value
y = params["y"].value
tmp1 = y - x * x
tmp2 = 1 - x
return 100 * tmp1 * tmp1 + tmp2 * tmp2
params = ba.Parameters()
params.add("x", value=-1.2, min=-5.0, max=5.0, step=0.01)
params.add("y", value=1.0, min=-5.0, max=5.0, step=0.01)
minimizer = ba.Minimizer()
result = minimizer.minimize(rosenbrock, params)
print(result.toString())
...@@ -7,6 +7,7 @@ Fake experimental data are generated by gisas_fake1. ...@@ -7,6 +7,7 @@ Fake experimental data are generated by gisas_fake1.
import gisas_model1 as model import gisas_model1 as model
import bornagain as ba import bornagain as ba
import ba_fitmonitor
import numpy as np import numpy as np
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
...@@ -18,7 +19,8 @@ def run_fitting(): ...@@ -18,7 +19,8 @@ def run_fitting():
fit_objective.addSimulationAndData(model.get_simulation, real_data) fit_objective.addSimulationAndData(model.get_simulation, real_data)
fit_objective.initPrint(10) # Print on every 10th iteration. fit_objective.initPrint(10) # Print on every 10th iteration.
fit_objective.initPlot(10) # Plot on every 10th iteration. Slow! observer = ba_fitmonitor.PlotterGISAS()
fit_objective.initPlot(10, observer) # Plot every 10th, slow!
minimizer = ba.Minimizer() minimizer = ba.Minimizer()
params = model.start_parameters_1() params = model.start_parameters_1()
......
...@@ -10,6 +10,7 @@ after that to find precise minimum location. ...@@ -10,6 +10,7 @@ after that to find precise minimum location.
import numpy as np import numpy as np
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
import bornagain as ba import bornagain as ba
import ba_fitmonitor
from bornagain import deg, angstrom, nm from bornagain import deg, angstrom, nm
...@@ -80,7 +81,8 @@ def run_fitting(): ...@@ -80,7 +81,8 @@ def run_fitting():
fit_objective = ba.FitObjective() fit_objective = ba.FitObjective()
fit_objective.addSimulationAndData(get_simulation, real_data, 1) fit_objective.addSimulationAndData(get_simulation, real_data, 1)
fit_objective.initPrint(10) fit_objective.initPrint(10)
fit_objective.initPlot(10) observer = ba_fitmonitor.PlotterGISAS()
fit_objective.initPlot(10, observer)
""" """
Setting fitting parameters with starting values. Setting fitting parameters with starting values.
Here we select starting values being quite far from true values Here we select starting values being quite far from true values
......
...@@ -10,6 +10,7 @@ scale and background factors. ...@@ -10,6 +10,7 @@ scale and background factors.
import numpy as np import numpy as np
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
import bornagain as ba import bornagain as ba
import ba_fitmonitor
from bornagain import deg, angstrom, nm from bornagain import deg, angstrom, nm
...@@ -90,7 +91,8 @@ def run_fitting(): ...@@ -90,7 +91,8 @@ def run_fitting():
fit_objective.addSimulationAndData(get_simulation, real_data, 1) fit_objective.addSimulationAndData(get_simulation, real_data, 1)
fit_objective.initPrint(10) fit_objective.initPrint(10)
fit_objective.initPlot(10) observer = ba_fitmonitor.PlotterGISAS()
fit_objective.initPlot(10, observer)
params = ba.Parameters() params = ba.Parameters()
params.add("radius", 5.*nm, vary=False) params.add("radius", 5.*nm, vary=False)
......
...@@ -5,6 +5,7 @@ Fitting example: fit along slices ...@@ -5,6 +5,7 @@ Fitting example: fit along slices
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
import bornagain as ba import bornagain as ba
import ba_plot
from bornagain import deg, angstrom, nm from bornagain import deg, angstrom, nm
phi_slice_value = 0.0 # position of vertical slice in deg phi_slice_value = 0.0 # position of vertical slice in deg
...@@ -93,7 +94,7 @@ class PlotObserver: ...@@ -93,7 +94,7 @@ class PlotObserver:
representing slices on top. representing slices on top.
""" """
plt.subplots_adjust(wspace=0.2, hspace=0.2) plt.subplots_adjust(wspace=0.2, hspace=0.2)
ba.plot_histogram(data, title="Experimental data") ba_plot.plot_histogram(data, title="Experimental data")
# line representing vertical slice # line representing vertical slice
plt.plot([phi_slice_value, phi_slice_value], plt.plot([phi_slice_value, phi_slice_value],
[data.getYmin(), data.getYmax()], [data.getYmin(), data.getYmax()],
......
...@@ -7,6 +7,7 @@ import numpy as np ...@@ -7,6 +7,7 @@ import numpy as np
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
import bornagain as ba import bornagain as ba
from bornagain import deg, angstrom, nm from bornagain import deg, angstrom, nm
import ba_fitmonitor
def get_sample(params): def get_sample(params):
...@@ -118,7 +119,8 @@ def run_fitting(): ...@@ -118,7 +119,8 @@ def run_fitting():
fit_objective = ba.FitObjective() fit_objective = ba.FitObjective()
fit_objective.addSimulationAndData(get_simulation, real_data, 1) fit_objective.addSimulationAndData(get_simulation, real_data, 1)
fit_objective.initPrint(10) fit_objective.initPrint(10)
fit_objective.initPlot(10) observer = ba_fitmonitor.PlotterGISAS()
fit_objective.initPlot(10, observer)
params = ba.Parameters() params = ba.Parameters()
params.add("radius", 6.*nm, min=4, max=8) params.add("radius", 6.*nm, min=4, max=8)
......
...@@ -7,8 +7,8 @@ import numpy as np ...@@ -7,8 +7,8 @@ import numpy as np
import matplotlib import matplotlib
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
import bornagain as ba import bornagain as ba
from bornagain import deg, angstrom, nm from bornagain import deg, nm
import ba_plot as bp
def get_sample(params): def get_sample(params):
""" """
...@@ -46,7 +46,7 @@ def get_simulation(params): ...@@ -46,7 +46,7 @@ def get_simulation(params):
simulation = ba.GISASSimulation() simulation = ba.GISASSimulation()
simulation.setDetectorParameters(50, -1.5*deg, 1.5*deg, 50, 0, 2*deg) simulation.setDetectorParameters(50, -1.5*deg, 1.5*deg, 50, 0, 2*deg)
simulation.setBeamParameters(1*angstrom, incident_angle, 0) simulation.setBeamParameters(0.1*nm, incident_angle, 0)
simulation.beam().setIntensity(1e+08) simulation.beam().setIntensity(1e+08)
simulation.setSample(get_sample(params)) simulation.setSample(get_sample(params))
return simulation return simulation
...@@ -108,24 +108,24 @@ class PlotObserver(): ...@@ -108,24 +108,24 @@ class PlotObserver():
zmax = real_data.histogram2d().getMaximum() zmax = real_data.histogram2d().getMaximum()
plt.subplot(canvas[i_dataset*3]) plt.subplot(canvas[i_dataset*3])
ba.plot_colormap(real_data, bp.plot_colormap(real_data,
title="\"Real\" data - #" + title="\"Real\" data - #" +
str(i_dataset + 1), str(i_dataset + 1),
zmin=1, intensity_min=1,
zmax=zmax, intensity_max=zmax,
zlabel="") zlabel="")
plt.subplot(canvas[1 + i_dataset*3]) plt.subplot(canvas[1 + i_dataset*3])
ba.plot_colormap(simul_data, bp.plot_colormap(simul_data,
title="Simulated data - #" + title="Simulated data - #" +
str(i_dataset + 1), str(i_dataset + 1),
zmin=1, intensity_min=1,
zmax=zmax, intensity_max=zmax,
zlabel="") zlabel="")
plt.subplot(canvas[2 + i_dataset*3]) plt.subplot(canvas[2 + i_dataset*3])
ba.plot_colormap(chi2_map, bp.plot_colormap(chi2_map,
title="Chi2 map - #" + str(i_dataset + 1), title="Chi2 map - #" + str(i_dataset + 1),
zmin=0.001, intensity_min=0.001,
zmax=10, intensity_max=10,
zlabel="") zlabel="")
@staticmethod @staticmethod
......
...@@ -53,7 +53,7 @@ def get_sample(params): ...@@ -53,7 +53,7 @@ def get_sample(params):
particle_layout.addParticle(sphere) particle_layout.addParticle(sphere)
interference = ba.InterferenceFunction2DLattice( interference = ba.InterferenceFunction2DLattice(
ba.HexagonalLattice2D(lattice_length)) ba.HexagonalLattice2D(lattice_length, 0))
pdf = ba.FTDecayFunction2DCauchy(10*nm, 10*nm, 0) pdf = ba.FTDecayFunction2DCauchy(10*nm, 10*nm, 0)
interference.setDecayFunction(pdf) interference.setDecayFunction(pdf)
......
...@@ -27,7 +27,7 @@ def get_sample(params): ...@@ -27,7 +27,7 @@ def get_sample(params):
particle_layout.addParticle(sphere) particle_layout.addParticle(sphere)
interference = ba.InterferenceFunction2DLattice( interference = ba.InterferenceFunction2DLattice(
ba.HexagonalLattice2D(lattice_length)) ba.HexagonalLattice2D(lattice_length, 0))
pdf = ba.FTDecayFunction2DCauchy(10*nm, 10*nm, 0) pdf = ba.FTDecayFunction2DCauchy(10*nm, 10*nm, 0)
interference.setDecayFunction(pdf) interference.setDecayFunction(pdf)
......
...@@ -6,6 +6,7 @@ Fit progress is plotted using lmfit iteration calbback function. ...@@ -6,6 +6,7 @@ Fit progress is plotted using lmfit iteration calbback function.
import numpy as np import numpy as np
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
import bornagain as ba import bornagain as ba
import ba_fitmonitor
from bornagain import deg, angstrom, nm from bornagain import deg, angstrom, nm
import lmfit import lmfit
......
...@@ -14,6 +14,8 @@ and use genetic algorithm as the minimizer. ...@@ -14,6 +14,8 @@ and use genetic algorithm as the minimizer.
import numpy as np import numpy as np
import bornagain as ba import bornagain as ba
import ba_fitmonitor as bafim
import ba_plot
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
from os import path from os import path
...@@ -121,7 +123,7 @@ def run_fitting(): ...@@ -121,7 +123,7 @@ def run_fitting():
fit_objective.addSimulationAndData(get_simulation, real_data, fit_objective.addSimulationAndData(get_simulation, real_data,
uncertainties) uncertainties)
plot_observer = ba_fitmonitor.PlotterSpecular(units=ba.Axes.RQ4) plot_observer = bafim.PlotterSpecular(units=ba.Axes.RQ4)
fit_objective.initPrint(10) fit_objective.initPrint(10)
fit_objective.initPlot(10, plot_observer) fit_objective.initPlot(10, plot_observer)
fit_objective.setObjectiveMetric("Chi2", "L1") fit_objective.setObjectiveMetric("Chi2", "L1")
......
...@@ -93,7 +93,7 @@ def get_simulation(q_axis, parameters, polarization, analyzer): ...@@ -93,7 +93,7 @@ def get_simulation(q_axis, parameters, polarization, analyzer):
scan.setAbsoluteQResolution(distr, parameters["q_res"]) scan.setAbsoluteQResolution(distr, parameters["q_res"])
simulation.beam().setPolarization(polarization) simulation.beam().setPolarization(polarization)
simulation.setAnalyzerProperties(analyzer, 1, 0.5) simulation.detector().setAnalyzerProperties(analyzer, 1, 0.5)
simulation.setScan(scan) simulation.setScan(scan)
return simulation return simulation
......
...@@ -34,6 +34,7 @@ from matplotlib import pyplot as plt ...@@ -34,6 +34,7 @@ from matplotlib import pyplot as plt
import numpy as np import numpy as np
from os import path from os import path
import bornagain as ba import bornagain as ba
import ba_plot
from scipy.optimize import differential_evolution from scipy.optimize import differential_evolution
...@@ -151,7 +152,7 @@ def chi_2(real_data, sim_data, weights): ...@@ -151,7 +152,7 @@ def chi_2(real_data, sim_data, weights):
Computes chi_2 metrics and returns its value Computes chi_2 metrics and returns its value
""" """
sim_data_upsc = np.multiply(weights, sim_data) sim_data_upsc = np.multiply(weights, sim_data)
sim_data_upsc[sim_data_upsc is 0] = 1e-30 sim_data_upsc[sim_data_upsc==0] = 1e-30
real_data_upsc = np.multiply(weights, real_data) real_data_upsc = np.multiply(weights, real_data)
diff = real_data_upsc - sim_data_upsc diff = real_data_upsc - sim_data_upsc
return np.sum(np.divide(np.multiply(diff, diff), sim_data_upsc)) return np.sum(np.divide(np.multiply(diff, diff), sim_data_upsc))
...@@ -270,7 +271,7 @@ def plot_result(sim_result, ref_result, bin_start=0, bin_end=-1): ...@@ -270,7 +271,7 @@ def plot_result(sim_result, ref_result, bin_start=0, bin_end=-1):
get_real_data_values(bin_start, bin_end), sim_result.axis(), get_real_data_values(bin_start, bin_end), sim_result.axis(),
sim_data, ref_result.axis(), ref_data) sim_data, ref_result.axis(), ref_data)
xlabel = ba.get_axes_labels(sim_result, ba.Axes.DEFAULT)[0] xlabel = ba_plot.get_axes_labels(sim_result, ba.Axes.DEFAULT)[0]
ylabel = "Intensity" ylabel = "Intensity"
plt.xlabel(xlabel, fontsize=16) plt.xlabel(xlabel, fontsize=16)
plt.ylabel(ylabel, fontsize=16) plt.ylabel(ylabel, fontsize=16)
......
...@@ -4,8 +4,10 @@ Fitting experimental data: spherical nanoparticles with size distribution ...@@ -4,8 +4,10 @@ Fitting experimental data: spherical nanoparticles with size distribution
in 3 layers system (experiment at GALAXI). in 3 layers system (experiment at GALAXI).
""" """
import bornagain as ba import bornagain as ba
from bornagain import nm as nm from bornagain import nm
import ba_fitmonitor
from sample_builder import SampleBuilder from sample_builder import SampleBuilder
from matplotlib import pyplot as plt
wavelength = 1.34*ba.angstrom wavelength = 1.34*ba.angstrom
alpha_i = 0.463*ba.deg alpha_i = 0.463*ba.deg
...@@ -63,7 +65,8 @@ def run_fitting(): ...@@ -63,7 +65,8 @@ def run_fitting():
fit_objective = ba.FitObjective() fit_objective = ba.FitObjective()
fit_objective.addSimulationAndData(create_simulation, real_data, 1) fit_objective.addSimulationAndData(create_simulation, real_data, 1)
fit_objective.initPrint(10) fit_objective.initPrint(10)
fit_objective.initPlot(10) observer = ba_fitmonitor.PlotterGISAS()
fit_objective.initPlot(10, observer)
params = ba.Parameters() params = ba.Parameters()
params.add("radius", 5.*nm, min=4, max=6, step=0.1*nm) params.add("radius", 5.*nm, min=4, max=6, step=0.1*nm)
...@@ -77,3 +80,4 @@ def run_fitting(): ...@@ -77,3 +80,4 @@ def run_fitting():
if __name__ == '__main__': if __name__ == '__main__':
run_fitting() run_fitting()
plt.show()
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
Vacuum layer is populated with spheres with size distribution. Vacuum layer is populated with spheres with size distribution.
""" """
import bornagain as ba import bornagain as ba
from bornagain import nm
class SampleBuilder: class SampleBuilder:
......
###############################################################################
# Run unmodified examples
###############################################################################
set(test_script ${TOOL_DIR}/code/batch-plot.py)
set(output_dir ${TEST_OUTPUT_DIR_PY_EXAMPLES}) set(output_dir ${TEST_OUTPUT_DIR_PY_EXAMPLES})
file(MAKE_DIRECTORY ${output_dir}) file(MAKE_DIRECTORY ${output_dir})
####################################################################################################
# Run examples that don't plot
####################################################################################################
function(run_noplot example)
get_filename_component(name ${example} NAME_WE)
set(test_name Example.exec.${name})
add_test(${test_name}
env PYTHONPATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
${Python3_EXECUTABLE} ${example} ${output_dir})
endfunction()
file(GLOB ex_noplot
${EXAMPLES_DIR}/fit/algo/*.py
)
foreach(example ${ex_noplot})
run_noplot(${example})
endforeach()
####################################################################################################
# Run unmodified examples, with plots under batch control
####################################################################################################
set(test_script ${TOOL_DIR}/code/batch-plot.py)
# Run one Python example. # Run one Python example.
# Check whether the example passes. # Check whether the example passes.
# Don't check results. # Don't check results.
...@@ -46,9 +65,9 @@ file(GLOB examples ...@@ -46,9 +65,9 @@ file(GLOB examples
${EXAMPLES_DIR}/fit55_Specular/FitSpecularBasics.py) ${EXAMPLES_DIR}/fit55_Specular/FitSpecularBasics.py)
run_examples("${examples}" "") run_examples("${examples}" "")
############################################################################ ####################################################################################################
# Check results of modified examples # Persistence tests: Run modified examples, and check results against references
############################################################################ ####################################################################################################
set(OUTPUT_DIR ${TEST_OUTPUT_DIR_PY_PERSIST}) set(OUTPUT_DIR ${TEST_OUTPUT_DIR_PY_PERSIST})
file(MAKE_DIRECTORY ${OUTPUT_DIR}) file(MAKE_DIRECTORY ${OUTPUT_DIR})
......
...@@ -45,6 +45,9 @@ class Plotter: ...@@ -45,6 +45,9 @@ class Plotter:
self._units = units self._units = units
self._aspect = aspect self._aspect = aspect
def __call__(self, fit_objective):
self.plot(fit_objective)
def reset(self): def reset(self):
self._fig.clf() self._fig.clf()
...@@ -147,9 +150,6 @@ class PlotterSpecular(Plotter): ...@@ -147,9 +150,6 @@ class PlotterSpecular(Plotter):
self.gs = gridspec.GridSpec(1, 2, width_ratios=[2.5, 1], wspace=0) self.gs = gridspec.GridSpec(1, 2, width_ratios=[2.5, 1], wspace=0)
self.units = units self.units = units
def __call__(self, fit_objective):
self.plot(fit_objective)
@staticmethod @staticmethod
def as_si(val, ndp): def as_si(val, ndp):
""" """
...@@ -248,7 +248,7 @@ class PlotterSpecular(Plotter): ...@@ -248,7 +248,7 @@ class PlotterSpecular(Plotter):
alpha=0.6) alpha=0.6)
plt.ylim((0.5*np.min(real_values), 5*np.max(real_values))) plt.ylim((0.5*np.min(real_values), 5*np.max(real_values)))
xlabel = ba_plot.get_axes_labels(real_data, self.units)[0] xlabel = bp.get_axes_labels(real_data, self.units)[0]
legend = ['BornAgain', 'Data'] legend = ['BornAgain', 'Data']
if unc_values is not None: if unc_values is not None:
legend = ['BornAgain', 'Data', r'Data $\pm \sigma$'] legend = ['BornAgain', 'Data', r'Data $\pm \sigma$']
......
...@@ -242,15 +242,7 @@ class ObserverCallbackWrapper(PyObserverCallback): ...@@ -242,15 +242,7 @@ class ObserverCallbackWrapper(PyObserverCallback):
def finalize(self, minimizer_result): def finalize(self, minimizer_result):
return self.finalize_cpp(self.convert_result(minimizer_result)) return self.finalize_cpp(self.convert_result(minimizer_result))
def create_default_plotter(self): def initPlot(self, every_nth, callback):
import ba_fitmonitor as bafim
self.m_plotter = bafim.PlotterGISAS()
return self.m_plotter.plot
def initPlot(self, every_nth, callback = None):
if not callback:
callback = self.create_default_plotter()
self.wrp_plot_observer = ObserverCallbackWrapper(callback) self.wrp_plot_observer = ObserverCallbackWrapper(callback)
return self.initPlot_cpp(every_nth, self.wrp_plot_observer) return self.initPlot_cpp(every_nth, self.wrp_plot_observer)
......
...@@ -3045,15 +3045,7 @@ class FitObjective(object): ...@@ -3045,15 +3045,7 @@ class FitObjective(object):
def finalize(self, minimizer_result): def finalize(self, minimizer_result):
return self.finalize_cpp(self.convert_result(minimizer_result)) return self.finalize_cpp(self.convert_result(minimizer_result))
def create_default_plotter(self): def initPlot(self, every_nth, callback):
import ba_fitmonitor as bafim
self.m_plotter = bafim.PlotterGISAS()
return self.m_plotter.plot
def initPlot(self, every_nth, callback = None):
if not callback:
callback = self.create_default_plotter()
self.wrp_plot_observer = ObserverCallbackWrapper(callback) self.wrp_plot_observer = ObserverCallbackWrapper(callback)
return self.initPlot_cpp(every_nth, self.wrp_plot_observer) return self.initPlot_cpp(every_nth, self.wrp_plot_observer)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment