#!/usr/bin/env python3
"""
Using custom objective function to fit GISAS data.

In this example objective function returns vector of residuals computed from
the data and simulation after applying sqrt() to intensity values.
"""
import bornagain as ba
from bornagain import nm
import numpy as np
import lmfit
import model2_hexlattice as model


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

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

    def my_residuals(P):
        """Custom residuals: apply sqrt to intensities before differencing."""
        fit_objective.evaluate(P)
        sim = np.sqrt(np.asarray(fit_objective.flatSimData()))
        exp = np.sqrt(np.asarray(fit_objective.flatExpData()))
        return sim - exp

    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)

    result = lmfit.minimize(my_residuals, P)
    print(lmfit.fit_report(result))
    ba.showSample3D(model.get_sample(result.params), sample_size=300*nm, seed=0)
