diff --git a/Tests/Functional/Python/PyFit/CMakeLists.txt b/Tests/Functional/Python/PyFit/CMakeLists.txt index 2e947e15d75374d9f7b3e23dd030ba89b377a735..bb2e0553167170d2230b52ca08d00dd6a20be134 100644 --- a/Tests/Functional/Python/PyFit/CMakeLists.txt +++ b/Tests/Functional/Python/PyFit/CMakeLists.txt @@ -16,6 +16,7 @@ set(tests "fitsuite_api.py" "minimizer_api.py" "standalone_fits.py" + "fitobjective_api.py" # "testfit_GSLLMA.py" # "testfit_GSLMultiMin.py" # "testfit_GSLSimAn.py" diff --git a/Tests/Functional/Python/PyFit/fitobjective_api.py b/Tests/Functional/Python/PyFit/fitobjective_api.py new file mode 100644 index 0000000000000000000000000000000000000000..1251297c342f6266938857f7d378838d66958937 --- /dev/null +++ b/Tests/Functional/Python/PyFit/fitobjective_api.py @@ -0,0 +1,75 @@ +""" +Testing python specific API for FitObjective related classes. +""" +import sys +import os +import unittest +import numpy as np + +sys.path.append("@CMAKE_LIBRARY_OUTPUT_DIRECTORY@") +import bornagain as ba + + +class SimulationBuilder: + def __init__(self): + self.m_ncalls = 0 + self.m_pars = None + self.m_nrow = 3 + self.m_ncol = 4 + + def size(self): + return self.m_nrow*self.m_ncol + + def build_simulation(self, pars): + self.m_ncalls += 1 + self.m_pars = pars + + ml = ba.MultiLayer() + material = ba.HomogeneousMaterial("Shell", 0.0, 0.0) + ml.addLayer(ba.Layer(material)) + ml.addLayer(ba.Layer(material)) + + simulation = ba.GISASSimulation(ml) + simulation.setDetectorParameters(self.m_ncol, 0.0, 1.0, self.m_nrow, 0.0, 1.0) + return simulation + + def create_data(self): + return np.full((self.m_nrow, self.m_ncol), 1, dtype=np.float64) + + + +class FitObjectiveAPITest(unittest.TestCase): + + def test_SimulationBuilderCallback(self): + """ + Testing simulation construction using Python callback + """ + pars = ba.Parameters() + pars.add(ba.Parameter("par0", 0.0)) + pars.add(ba.Parameter("par1", 1.0)) + + builder = SimulationBuilder() + data = builder.create_data() + + # adding simulation callback and experimental data + objective = ba.FitObjective() + objective.addSimulationAndData(builder.build_simulation, data, 1.0) + self.assertEqual(builder.m_ncalls, 0) + self.assertEqual(objective.numberOfFitElements(), 0) + + # running objective function + objective.evaluate(pars) + self.assertEqual(builder.m_ncalls, 1) + self.assertEqual(objective.numberOfFitElements(), builder.size()) + self.assertEqual(list(builder.m_pars.values()), [0.0, 1.0]) + + # checking arrays of experimental and simulated data + expected_sim = np.full((builder.size()), 0, dtype=np.float64).tolist() + expected_data = np.full((builder.size()), 1, dtype=np.float64).tolist() + self.assertEqual(expected_sim, list(objective.simulation_array())) + self.assertEqual(expected_data, list(objective.experimental_array())) + + + +if __name__ == '__main__': + unittest.main() diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py index 4e17db8e7aa8a057c12d6102ef75589cc918dc01..b5e22e21359c7ef1769d07ed4f5213ab8b6976be 100644 --- a/auto/Wrap/libBornAgainCore.py +++ b/auto/Wrap/libBornAgainCore.py @@ -7578,8 +7578,8 @@ class FitObjective(_object): def addSimulationAndData_cpp(self, callback, data, weight=1.0): """ - addSimulationAndData_cpp(FitObjective self, PyBuilderCallback callback, IntensityData data, double weight=1.0) - addSimulationAndData_cpp(FitObjective self, PyBuilderCallback callback, IntensityData data) + addSimulationAndData_cpp(FitObjective self, PyBuilderCallback callback, vdouble2d_t data, double weight=1.0) + addSimulationAndData_cpp(FitObjective self, PyBuilderCallback callback, vdouble2d_t data) """ return _libBornAgainCore.FitObjective_addSimulationAndData_cpp(self, callback, data, weight) @@ -7610,8 +7610,8 @@ class FitObjective(_object): def addSimulationAndData(self, callback, data, weight): - wrp = SimulationBuilderWrapper(callback) - return self.addSimulationAndData_cpp(wrp, data, weight) + self.wrp = SimulationBuilderWrapper(callback) + return self.addSimulationAndData_cpp(self.wrp, data, weight) FitObjective_swigregister = _libBornAgainCore.FitObjective_swigregister FitObjective_swigregister(FitObjective) diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp index ecf6dea597d67cbb2cef10f9e0edd86e5b91b9b6..1a457bfe32d88be1cc36f3ace141a7c5a23cd19e 100644 --- a/auto/Wrap/libBornAgainCore_wrap.cpp +++ b/auto/Wrap/libBornAgainCore_wrap.cpp @@ -50637,14 +50637,13 @@ SWIGINTERN PyObject *_wrap_FitObjective_addSimulationAndData_cpp__SWIG_0(PyObjec PyObject *resultobj = 0; FitObjective *arg1 = (FitObjective *) 0 ; PyBuilderCallback *arg2 = 0 ; - OutputData< double > *arg3 = 0 ; + std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > *arg3 = 0 ; double arg4 ; void *argp1 = 0 ; int res1 = 0 ; void *argp2 = 0 ; int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; + int res3 = SWIG_OLDOBJ ; double val4 ; int ecode4 = 0 ; PyObject * obj0 = 0 ; @@ -50666,23 +50665,28 @@ SWIGINTERN PyObject *_wrap_FitObjective_addSimulationAndData_cpp__SWIG_0(PyObjec SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "2"" of type '" "PyBuilderCallback &""'"); } arg2 = reinterpret_cast< PyBuilderCallback * >(argp2); - res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_OutputDataT_double_t, 0 | 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "3"" of type '" "OutputData< double > const &""'"); - } - if (!argp3) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "3"" of type '" "OutputData< double > const &""'"); + { + std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > *ptr = (std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > *)0; + res3 = swig::asptr(obj2, &ptr); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "3"" of type '" "std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > const &""'"); + } + if (!ptr) { + SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "3"" of type '" "std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > const &""'"); + } + arg3 = ptr; } - arg3 = reinterpret_cast< OutputData< double > * >(argp3); ecode4 = SWIG_AsVal_double(obj3, &val4); if (!SWIG_IsOK(ecode4)) { SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "4"" of type '" "double""'"); } arg4 = static_cast< double >(val4); - (arg1)->addSimulationAndData(*arg2,(OutputData< double > const &)*arg3,arg4); + (arg1)->addSimulationAndData(*arg2,(std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > const &)*arg3,arg4); resultobj = SWIG_Py_Void(); + if (SWIG_IsNewObj(res3)) delete arg3; return resultobj; fail: + if (SWIG_IsNewObj(res3)) delete arg3; return NULL; } @@ -50691,13 +50695,12 @@ SWIGINTERN PyObject *_wrap_FitObjective_addSimulationAndData_cpp__SWIG_1(PyObjec PyObject *resultobj = 0; FitObjective *arg1 = (FitObjective *) 0 ; PyBuilderCallback *arg2 = 0 ; - OutputData< double > *arg3 = 0 ; + std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > *arg3 = 0 ; void *argp1 = 0 ; int res1 = 0 ; void *argp2 = 0 ; int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; + int res3 = SWIG_OLDOBJ ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; @@ -50716,18 +50719,23 @@ SWIGINTERN PyObject *_wrap_FitObjective_addSimulationAndData_cpp__SWIG_1(PyObjec SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "2"" of type '" "PyBuilderCallback &""'"); } arg2 = reinterpret_cast< PyBuilderCallback * >(argp2); - res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_OutputDataT_double_t, 0 | 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "3"" of type '" "OutputData< double > const &""'"); - } - if (!argp3) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "3"" of type '" "OutputData< double > const &""'"); + { + std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > *ptr = (std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > *)0; + res3 = swig::asptr(obj2, &ptr); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "3"" of type '" "std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > const &""'"); + } + if (!ptr) { + SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "FitObjective_addSimulationAndData_cpp" "', argument " "3"" of type '" "std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > const &""'"); + } + arg3 = ptr; } - arg3 = reinterpret_cast< OutputData< double > * >(argp3); - (arg1)->addSimulationAndData(*arg2,(OutputData< double > const &)*arg3); + (arg1)->addSimulationAndData(*arg2,(std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > const &)*arg3); resultobj = SWIG_Py_Void(); + if (SWIG_IsNewObj(res3)) delete arg3; return resultobj; fail: + if (SWIG_IsNewObj(res3)) delete arg3; return NULL; } @@ -50754,7 +50762,7 @@ SWIGINTERN PyObject *_wrap_FitObjective_addSimulationAndData_cpp(PyObject *self, int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_PyBuilderCallback, 0); _v = SWIG_CheckState(res); if (_v) { - int res = SWIG_ConvertPtr(argv[2], 0, SWIGTYPE_p_OutputDataT_double_t, 0); + int res = swig::asptr(argv[2], (std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > >**)(0)); _v = SWIG_CheckState(res); if (_v) { return _wrap_FitObjective_addSimulationAndData_cpp__SWIG_1(self, args); @@ -50772,7 +50780,7 @@ SWIGINTERN PyObject *_wrap_FitObjective_addSimulationAndData_cpp(PyObject *self, int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_PyBuilderCallback, 0); _v = SWIG_CheckState(res); if (_v) { - int res = SWIG_ConvertPtr(argv[2], 0, SWIGTYPE_p_OutputDataT_double_t, 0); + int res = swig::asptr(argv[2], (std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > >**)(0)); _v = SWIG_CheckState(res); if (_v) { { @@ -50790,8 +50798,8 @@ SWIGINTERN PyObject *_wrap_FitObjective_addSimulationAndData_cpp(PyObject *self, fail: SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'FitObjective_addSimulationAndData_cpp'.\n" " Possible C/C++ prototypes are:\n" - " FitObjective::addSimulationAndData(PyBuilderCallback &,OutputData< double > const &,double)\n" - " FitObjective::addSimulationAndData(PyBuilderCallback &,OutputData< double > const &)\n"); + " FitObjective::addSimulationAndData(PyBuilderCallback &,std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > const &,double)\n" + " FitObjective::addSimulationAndData(PyBuilderCallback &,std::vector< std::vector< double,std::allocator< double > >,std::allocator< std::vector< double,std::allocator< double > > > > const &)\n"); return 0; } @@ -122951,8 +122959,8 @@ static PyMethodDef SwigMethods[] = { { (char *)"new_FitObjective", _wrap_new_FitObjective, METH_VARARGS, (char *)"new_FitObjective() -> FitObjective"}, { (char *)"delete_FitObjective", _wrap_delete_FitObjective, METH_VARARGS, (char *)"delete_FitObjective(FitObjective self)"}, { (char *)"FitObjective_addSimulationAndData_cpp", _wrap_FitObjective_addSimulationAndData_cpp, METH_VARARGS, (char *)"\n" - "addSimulationAndData_cpp(PyBuilderCallback callback, IntensityData data, double weight=1.0)\n" - "FitObjective_addSimulationAndData_cpp(FitObjective self, PyBuilderCallback callback, IntensityData data)\n" + "addSimulationAndData_cpp(PyBuilderCallback callback, vdouble2d_t data, double weight=1.0)\n" + "FitObjective_addSimulationAndData_cpp(FitObjective self, PyBuilderCallback callback, vdouble2d_t data)\n" ""}, { (char *)"FitObjective_evaluate", _wrap_FitObjective_evaluate, METH_VARARGS, (char *)"FitObjective_evaluate(FitObjective self, Fit::Parameters const & params) -> double"}, { (char *)"FitObjective_evaluate_residuals", _wrap_FitObjective_evaluate_residuals, METH_VARARGS, (char *)"FitObjective_evaluate_residuals(FitObjective self, Fit::Parameters const & params) -> vdouble1d_t"},