diff --git a/Sample/Particle/IFormFactor.h b/Sample/Particle/IFormFactor.h
index a20446cd3d4d58fba4297abd8028fcc87f8e7f12..acc1e991ab81ff33c717ea84f66728d6ae07ac06 100644
--- a/Sample/Particle/IFormFactor.h
+++ b/Sample/Particle/IFormFactor.h
@@ -66,6 +66,8 @@ public:
     //! multiplies with the unit matrix.
     virtual SpinMatrix formfactor_pol(C3 q) const;
 
+    virtual std::string validate() const { return ""; }
+
 protected:
     //! IShape3D object, used to retrieve vertices (which may be approximate in the case
     //! of round shapes). For soft particles, this will be a hard mean shape.
diff --git a/Sample/Particle/Particle.cpp b/Sample/Particle/Particle.cpp
index 5aade9ccbeb5fecece40863af9f817ff0164b927..df65d46d7538ba44cd20f3b4d052ec6f6ad999de 100644
--- a/Sample/Particle/Particle.cpp
+++ b/Sample/Particle/Particle.cpp
@@ -47,3 +47,8 @@ std::vector<const INode*> Particle::nodeChildren() const
 {
     return std::vector<const INode*>() << IParticle::nodeChildren() << m_formfactor;
 }
+
+std::string Particle::validate() const
+{
+    return m_formfactor->validate();
+}
diff --git a/Sample/Particle/Particle.h b/Sample/Particle/Particle.h
index 401e9b144f8964eeae04f60ea928cd458556f88e..fa0d6e0606498edc78a86161cb7d7323da2e6b46 100644
--- a/Sample/Particle/Particle.h
+++ b/Sample/Particle/Particle.h
@@ -36,7 +36,7 @@ public:
 
     const IFormFactor* formfactor_at_bottom() const { return m_formfactor.get(); }
 
-    std::string validate() const final { return ""; }
+    std::string validate() const final;
 
 private:
     const Material m_material;
diff --git a/auto/Wrap/doxygenSample.i b/auto/Wrap/doxygenSample.i
index ce29cc75a2eb00fc8e3b5e834f08c03f4ffa1aca..5721b26fba99e7a6fbc0255dd7f7b5b01125343a 100644
--- a/auto/Wrap/doxygenSample.i
+++ b/auto/Wrap/doxygenSample.i
@@ -1144,6 +1144,9 @@ IFormFactor::formfactor_pol
 Returns scattering amplitude for complex scattering wavevector q=k_i-k_f in case of matrix interactions. Default implementation calls formfactor_at_bottom(q) and multiplies with the unit matrix. 
 ";
 
+%feature("docstring")  IFormFactor::validate "virtual std::string IFormFactor::validate() const
+IFormFactor::validate";
+
 
 // File: classIFormFactorPolyhedron.xml
 %feature("docstring") IFormFactorPolyhedron "
@@ -5613,6 +5616,8 @@ magnetization (in A/m)
 
 
 // File: Particle_8cpp.xml
+%feature("docstring")  validate "std::string validate() const
+";
 
 
 // File: Particle_8h.xml
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index 57d6e336f8938e54301fad4ff1db4ba4e4968e39..2480456c8d8041a5158863a628ff75b4b28a6207 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -2771,6 +2771,14 @@ class IFormFactor(ISampleNode):
 
         """
         return _libBornAgainSample.IFormFactor_formfactor_pol(self, q)
+
+    def validate(self):
+        r"""
+        validate(IFormFactor self) -> std::string
+        virtual std::string IFormFactor::validate() const
+        IFormFactor::validate
+        """
+        return _libBornAgainSample.IFormFactor_validate(self)
     def __disown__(self):
         self.this.disown()
         _libBornAgainSample.disown_IFormFactor(self)
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index 667203b40d87db0c98bc53a11a2c7925c0ef37b2..7a10a383a0ed0e45c7686e6aae39ef67df6130f9 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -7894,6 +7894,38 @@ SpinMatrix SwigDirector_IFormFactor::formfactor_pol(C3 q) const {
 }
 
 
+std::string SwigDirector_IFormFactor::validate() const {
+  std::string c_result;
+  if (!swig_get_self()) {
+    Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call IFormFactor.__init__.");
+  }
+#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
+  const size_t swig_method_index = 16;
+  const char *const swig_method_name = "validate";
+  PyObject *method = swig_get_method(swig_method_index, swig_method_name);
+  swig::SwigVar_PyObject args = PyTuple_New(0);
+  swig::SwigVar_PyObject result = PyObject_Call(method, (PyObject *) args, NULL);
+#else
+  swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar("validate");
+  swig::SwigVar_PyObject result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);
+#endif
+  if (!result) {
+    PyObject *error = PyErr_Occurred();
+    if (error) {
+      Swig::DirectorMethodException::raise("Error detected when calling 'IFormFactor.validate'");
+    }
+  }
+  std::string *swig_optr = 0;
+  int swig_ores = SWIG_AsPtr_std_string(result, &swig_optr);
+  if (!SWIG_IsOK(swig_ores) || !swig_optr) {
+    Swig::DirectorTypeMismatchException::raise(SWIG_ErrorType(SWIG_ArgError((swig_optr ? swig_ores : SWIG_TypeError))), "in output value of type '""std::string""'");
+  }
+  c_result = *swig_optr;
+  if (SWIG_IsNewObj(swig_ores)) delete swig_optr;
+  return (std::string) c_result;
+}
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -33385,6 +33417,41 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IFormFactor_validate(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IFormFactor *arg1 = (IFormFactor *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  Swig::Director *director = 0;
+  bool upcall = false;
+  std::string result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IFormFactor, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IFormFactor_validate" "', argument " "1"" of type '" "IFormFactor const *""'"); 
+  }
+  arg1 = reinterpret_cast< IFormFactor * >(argp1);
+  director = SWIG_DIRECTOR_CAST(arg1);
+  upcall = (director && (director->swig_get_self()==swig_obj[0]));
+  try {
+    if (upcall) {
+      result = ((IFormFactor const *)arg1)->IFormFactor::validate();
+    } else {
+      result = ((IFormFactor const *)arg1)->validate();
+    }
+  } catch (Swig::DirectorException&) {
+    SWIG_fail;
+  }
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_disown_IFormFactor(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IFormFactor *arg1 = (IFormFactor *) 0 ;
@@ -61274,6 +61341,11 @@ static PyMethodDef SwigMethods[] = {
 		"Returns scattering amplitude for complex scattering wavevector q=k_i-k_f in case of matrix interactions. Default implementation calls formfactor_at_bottom(q) and multiplies with the unit matrix. \n"
 		"\n"
 		""},
+	 { "IFormFactor_validate", _wrap_IFormFactor_validate, METH_O, "\n"
+		"IFormFactor_validate(IFormFactor self) -> std::string\n"
+		"virtual std::string IFormFactor::validate() const\n"
+		"IFormFactor::validate\n"
+		""},
 	 { "disown_IFormFactor", _wrap_disown_IFormFactor, METH_O, NULL},
 	 { "IFormFactor_swigregister", IFormFactor_swigregister, METH_O, NULL},
 	 { "IFormFactor_swiginit", IFormFactor_swiginit, METH_VARARGS, NULL},
diff --git a/auto/Wrap/libBornAgainSample_wrap.h b/auto/Wrap/libBornAgainSample_wrap.h
index d0cb8f32afe3bacb1a91475b8a600207cb91c579..8c448a6da254095da8f7a86bcae1784a5482a9be 100644
--- a/auto/Wrap/libBornAgainSample_wrap.h
+++ b/auto/Wrap/libBornAgainSample_wrap.h
@@ -85,6 +85,7 @@ public:
     virtual std::string pythonConstructor() const;
     virtual bool canSliceAnalytically(IRotation const *rot) const;
     virtual SpinMatrix formfactor_pol(C3 q) const;
+    virtual std::string validate() const;
 
 /* Internal director utilities */
 public:
@@ -115,7 +116,7 @@ private:
       return method;
     }
 private:
-    mutable swig::SwigVar_PyObject vtable[16];
+    mutable swig::SwigVar_PyObject vtable[17];
 #endif
 
 };