The BornAgain fitting API allows users to define a custom objective function to for the minimization engine.
In this example we are going to construct a vector of residuals calculated between the
experimental and simulated intensity values after applying an additional $sqrt$ function to the amplitudes.
The length of vector n corresponds to the total number of non-masked detector channels.
This is done by defining a custom residual function my_residuals.
It calls fit_objective.evaluate(P) to run the simulation and
store the intensity arrays, then retrieves them via
fit_objective.flatSimData() and fit_objective.flatExpData()
and applies sqrt before differencing.
The custom function is then passed directly to lmfit.minimize.
#!/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.
"""importbornagainasbafrombornagainimportnmimportnumpyasnpimportlmfitimportmodel2_hexlatticeasmodelif__name__=='__main__':data=model.fake_data()fit_objective=ba.FitObjective()fit_objective.addFitPair(model.get_simulation,data,1)fit_objective.initPrint(10)defmy_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()))returnsim-expP=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))