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"},