#!/usr/bin/env python3
"""
External minimize: using lmfit minimizers for BornAgain fits.
Fit progress is plotted using lmfit iteration callback function.
"""
import bornagain as ba
from bornagain import ba_fitmonitor, nm
import lmfit
import model2_hexlattice as model


class LMFITPlotter:
    """
    Adapts standard plotter for lmfit minimizer.
    """

    def __init__(self, fit_objective, every_nth=10):
        self.fit_objective = fit_objective
        self.plotter_gisas = ba_fitmonitor.PlotterGISAS()
        self.every_nth = every_nth

    def __call__(self, P, i, resid):
        if i % self.every_nth == 0:
            self.plotter_gisas.plot(self.fit_objective)


if __name__ == '__main__':
    data = model.fake_data()

    fit_objective = ba.FitObjective()
    fit_objective.addFitPair(model.get_simulation, data, 1)
    fit_objective.initPrint(10)

    P = lmfit.Parameters()
    P.add('radius', value=7*nm, min=5*nm, max=8*nm)
    P.add('length', value=10*nm, min=8*nm, max=14*nm)
    plotter = LMFITPlotter(fit_objective)
    result = lmfit.minimize(fit_objective.evaluate_residuals, P, iter_cb=plotter)
    result.params.pretty_print()
    print(lmfit.fit_report(result))
    ba.showSample3D(model.get_sample(result.params), sample_size=300*nm, seed=0)
