From fd458417e653a4ca0449b5bb12095b735c7828e2 Mon Sep 17 00:00:00 2001
From: Tiago Freitas Pereira <tiagofrepereira@gmail.com>
Date: Thu, 12 Mar 2015 18:16:22 +0100
Subject: [PATCH] Fixed bugs with lists as input. Added tests for the
 exceptions

---
 bob/learn/em/isv_trainer.cpp              | 11 +++++++-
 bob/learn/em/ivector_trainer.cpp          |  2 ++
 bob/learn/em/jfa_trainer.cpp              | 27 ++++++++++++++++++-
 bob/learn/em/plda_trainer.cpp             |  8 ++++++
 bob/learn/em/test/test_ivector_trainer.py |  6 +++++
 bob/learn/em/test/test_jfa_trainer.py     | 32 ++++++++++++++++++++++-
 bob/learn/em/test/test_plda_trainer.py    |  7 +++++
 7 files changed, 90 insertions(+), 3 deletions(-)

diff --git a/bob/learn/em/isv_trainer.cpp b/bob/learn/em/isv_trainer.cpp
index ea98e2e..d557999 100644
--- a/bob/learn/em/isv_trainer.cpp
+++ b/bob/learn/em/isv_trainer.cpp
@@ -35,7 +35,10 @@ static int extract_GMMStats_2d(PyObject *list,
   for (int i=0; i<PyList_GET_SIZE(list); i++)
   {
     PyObject* another_list;
-    PyArg_Parse(PyList_GetItem(list, i), "O!", &PyList_Type, &another_list);
+    if(!PyArg_Parse(PyList_GetItem(list, i), "O!", &PyList_Type, &another_list)){
+      PyErr_Format(PyExc_RuntimeError, "Expected a list of lists of GMMStats objects [[GMMStats,GMMStats],[GMMStats,GMMStats].....[GMMStats,GMMStats]]");
+      return -1;
+    }
 
     std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > another_training_data;
     for (int j=0; j<PyList_GET_SIZE(another_list); j++){
@@ -432,6 +435,8 @@ static PyObject* PyBobLearnEMISVTrainer_initialize(PyBobLearnEMISVTrainerObject*
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->initialize(*isv_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the initialize method", 0)
 
@@ -464,6 +469,8 @@ static PyObject* PyBobLearnEMISVTrainer_e_step(PyBobLearnEMISVTrainerObject* sel
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->eStep(*isv_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the e_step method", 0)
 
@@ -530,6 +537,8 @@ static PyObject* PyBobLearnEMISVTrainer_enroll(PyBobLearnEMISVTrainerObject* sel
   std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > training_data;
   if(extract_GMMStats_1d(stats ,training_data)==0)
     self->cxx->enroll(*isv_machine->cxx, training_data, n_iter);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the enroll method", 0)
 
diff --git a/bob/learn/em/ivector_trainer.cpp b/bob/learn/em/ivector_trainer.cpp
index 72c2e40..61a427d 100644
--- a/bob/learn/em/ivector_trainer.cpp
+++ b/bob/learn/em/ivector_trainer.cpp
@@ -368,6 +368,8 @@ static PyObject* PyBobLearnEMIVectorTrainer_e_step(PyBobLearnEMIVectorTrainerObj
   std::vector<bob::learn::em::GMMStats> training_data;
   if(extract_GMMStats_1d(stats ,training_data)==0)
     self->cxx->eStep(*ivector_machine->cxx, training_data);
+  else
+    return 0;
 
   Py_RETURN_NONE;
   BOB_CATCH_MEMBER("cannot perform the e_step method", 0)
diff --git a/bob/learn/em/jfa_trainer.cpp b/bob/learn/em/jfa_trainer.cpp
index 38a82a8..6ee7792 100644
--- a/bob/learn/em/jfa_trainer.cpp
+++ b/bob/learn/em/jfa_trainer.cpp
@@ -35,7 +35,10 @@ static int extract_GMMStats_2d(PyObject *list,
   for (int i=0; i<PyList_GET_SIZE(list); i++)
   {
     PyObject* another_list;
-    PyArg_Parse(PyList_GetItem(list, i), "O!", &PyList_Type, &another_list);
+    if(!PyArg_Parse(PyList_GetItem(list, i), "O!", &PyList_Type, &another_list)){
+      PyErr_Format(PyExc_RuntimeError, "Expected a list of lists of GMMStats objects [[GMMStats,GMMStats],[GMMStats,GMMStats].....[GMMStats,GMMStats]]");
+      return -1;
+    }
 
     std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > another_training_data;
     for (int j=0; j<PyList_GET_SIZE(another_list); j++){
@@ -643,6 +646,8 @@ static PyObject* PyBobLearnEMJFATrainer_initialize(PyBobLearnEMJFATrainerObject*
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->initialize(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the initialize method", 0)
 
@@ -675,6 +680,8 @@ static PyObject* PyBobLearnEMJFATrainer_e_step_v(PyBobLearnEMJFATrainerObject* s
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->eStep1(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
 
   BOB_CATCH_MEMBER("cannot perform the e_step_v method", 0)
@@ -708,6 +715,8 @@ static PyObject* PyBobLearnEMJFATrainer_m_step_v(PyBobLearnEMJFATrainerObject* s
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->mStep1(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the m_step_v method", 0)
 
@@ -740,6 +749,8 @@ static PyObject* PyBobLearnEMJFATrainer_finalize_v(PyBobLearnEMJFATrainerObject*
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->finalize1(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the finalize_v method", 0)
 
@@ -772,6 +783,8 @@ static PyObject* PyBobLearnEMJFATrainer_e_step_u(PyBobLearnEMJFATrainerObject* s
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->eStep2(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the e_step_u method", 0)
 
@@ -804,6 +817,8 @@ static PyObject* PyBobLearnEMJFATrainer_m_step_u(PyBobLearnEMJFATrainerObject* s
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->mStep2(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the m_step_u method", 0)
 
@@ -836,6 +851,8 @@ static PyObject* PyBobLearnEMJFATrainer_finalize_u(PyBobLearnEMJFATrainerObject*
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->finalize2(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the finalize_u method", 0)
 
@@ -868,6 +885,8 @@ static PyObject* PyBobLearnEMJFATrainer_e_step_d(PyBobLearnEMJFATrainerObject* s
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->eStep3(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the e_step_d method", 0)
 
@@ -900,6 +919,8 @@ static PyObject* PyBobLearnEMJFATrainer_m_step_d(PyBobLearnEMJFATrainerObject* s
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->mStep3(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the m_step_d method", 0)
 
@@ -932,6 +953,8 @@ static PyObject* PyBobLearnEMJFATrainer_finalize_d(PyBobLearnEMJFATrainerObject*
   std::vector<std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > > training_data;
   if(extract_GMMStats_2d(stats ,training_data)==0)
     self->cxx->finalize3(*jfa_base->cxx, training_data);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the finalize_d method", 0)
 
@@ -967,6 +990,8 @@ static PyObject* PyBobLearnEMJFATrainer_enroll(PyBobLearnEMJFATrainerObject* sel
   std::vector<boost::shared_ptr<bob::learn::em::GMMStats> > training_data;
   if(extract_GMMStats_1d(stats ,training_data)==0)
     self->cxx->enroll(*jfa_machine->cxx, training_data, n_iter);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the enroll method", 0)
 
diff --git a/bob/learn/em/plda_trainer.cpp b/bob/learn/em/plda_trainer.cpp
index f396454..e6d03d5 100644
--- a/bob/learn/em/plda_trainer.cpp
+++ b/bob/learn/em/plda_trainer.cpp
@@ -451,6 +451,8 @@ static PyObject* PyBobLearnEMPLDATrainer_initialize(PyBobLearnEMPLDATrainerObjec
 
     self->cxx->initialize(*plda_base->cxx, data_vector);
   }
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the initialize method", 0)
 
@@ -483,6 +485,8 @@ static PyObject* PyBobLearnEMPLDATrainer_e_step(PyBobLearnEMPLDATrainerObject* s
   std::vector<blitz::Array<double,2> > data_vector;
   if(list_as_vector(data ,data_vector)==0)
     self->cxx->eStep(*plda_base->cxx, data_vector);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the e_step method", 0)
 
@@ -515,6 +519,8 @@ static PyObject* PyBobLearnEMPLDATrainer_m_step(PyBobLearnEMPLDATrainerObject* s
   std::vector<blitz::Array<double,2> > data_vector;
   if(list_as_vector(data ,data_vector)==0)
     self->cxx->mStep(*plda_base->cxx, data_vector);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the m_step method", 0)
 
@@ -547,6 +553,8 @@ static PyObject* PyBobLearnEMPLDATrainer_finalize(PyBobLearnEMPLDATrainerObject*
   std::vector<blitz::Array<double,2> > data_vector;
   if(list_as_vector(data ,data_vector)==0)
     self->cxx->finalize(*plda_base->cxx, data_vector);
+  else
+    return 0;
 
   BOB_CATCH_MEMBER("cannot perform the finalize method", 0)
 
diff --git a/bob/learn/em/test/test_ivector_trainer.py b/bob/learn/em/test/test_ivector_trainer.py
index 4456119..7539253 100644
--- a/bob/learn/em/test/test_ivector_trainer.py
+++ b/bob/learn/em/test/test_ivector_trainer.py
@@ -10,6 +10,7 @@
 import numpy
 import numpy.linalg
 import numpy.random
+import nose.tools
 
 from bob.learn.em import GMMMachine, GMMStats, IVectorMachine, IVectorTrainer
 
@@ -243,6 +244,11 @@ def test_trainer_nosigma():
     # M-Step
     trainer.m_step(m)
     assert numpy.allclose(t_ref[it], m.t, 1e-5)
+    
+
+  #testing exceptions
+  nose.tools.assert_raises(RuntimeError, trainer.e_step, m, [1,2,2])
+    
 
 def test_trainer_update_sigma():
   # Ubm
diff --git a/bob/learn/em/test/test_jfa_trainer.py b/bob/learn/em/test/test_jfa_trainer.py
index 33e6531..457fcfb 100644
--- a/bob/learn/em/test/test_jfa_trainer.py
+++ b/bob/learn/em/test/test_jfa_trainer.py
@@ -12,6 +12,7 @@ import numpy
 import numpy.linalg
 
 import bob.core.random
+import nose.tools
 
 from bob.learn.em import GMMStats, GMMMachine, JFABase, JFAMachine, ISVBase, ISVMachine, JFATrainer, ISVTrainer
 
@@ -210,6 +211,27 @@ def test_JFATrainAndEnrol():
   z_ref = numpy.array([8.2228e-20, 3.15216909492e-13, -1.48616735364395e-10, 1.0625905e-17, 3.7150503117895e-11, 1.71104e-19], 'float64')
   assert numpy.allclose(m.y, y_ref, eps)
   assert numpy.allclose(m.z, z_ref, eps)
+  
+  #Testing exceptions
+  nose.tools.assert_raises(RuntimeError, t.initialize, mb, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.initialize, mb, [[1,2,2]])
+  nose.tools.assert_raises(RuntimeError, t.e_step_u, mb, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.e_step_u, mb, [[1,2,2]])
+  nose.tools.assert_raises(RuntimeError, t.m_step_u, mb, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.m_step_u, mb, [[1,2,2]])
+  
+  nose.tools.assert_raises(RuntimeError, t.e_step_v, mb, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.e_step_v, mb, [[1,2,2]])  
+  nose.tools.assert_raises(RuntimeError, t.m_step_v, mb, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.m_step_v, mb, [[1,2,2]])  
+    
+  nose.tools.assert_raises(RuntimeError, t.e_step_d, mb, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.e_step_d, mb, [[1,2,2]])
+  nose.tools.assert_raises(RuntimeError, t.m_step_d, mb, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.m_step_d, mb, [[1,2,2]])
+  
+  nose.tools.assert_raises(RuntimeError, t.enroll, m, [[1,2,2]],5)
+  
 
 
 def test_ISVTrainAndEnrol():
@@ -226,7 +248,6 @@ def test_ISVTrainAndEnrol():
   ubm.variance_supervector = UBM_VAR
   mb = ISVBase(ubm,2)
   t = ISVTrainer(4.)
-  #t.train(mb, TRAINING_STATS)
   t.initialize(mb, TRAINING_STATS)
   mb.u = M_u
   for i in range(10):
@@ -251,6 +272,14 @@ def test_ISVTrainAndEnrol():
   gse = [gse1, gse2]
   t.enroll(m, gse, 5)
   assert numpy.allclose(m.z, z_ref, eps)
+  
+  #Testing exceptions
+  nose.tools.assert_raises(RuntimeError, t.initialize, mb, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.initialize, mb, [[1,2,2]])
+  nose.tools.assert_raises(RuntimeError, t.e_step, mb, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.e_step, mb, [[1,2,2]])
+  nose.tools.assert_raises(RuntimeError, t.enroll, m, [[1,2,2]],5)
+  
 
 
 def test_JFATrainInitialize():
@@ -284,6 +313,7 @@ def test_JFATrainInitialize():
   assert numpy.allclose(u1, u2, eps)
   assert numpy.allclose(v1, v2, eps)
   assert numpy.allclose(d1, d2, eps)
+    
 
 def test_ISVTrainInitialize():
 
diff --git a/bob/learn/em/test/test_plda_trainer.py b/bob/learn/em/test/test_plda_trainer.py
index 4e8abfd..96e89cb 100644
--- a/bob/learn/em/test/test_plda_trainer.py
+++ b/bob/learn/em/test/test_plda_trainer.py
@@ -14,6 +14,7 @@ import numpy.linalg
 
 from bob.learn.em import PLDATrainer, PLDABase, PLDAMachine
 import bob.learn.em
+import nose.tools
 
 class PythonPLDATrainer():
   """A simplified (and slower) version of the PLDATrainer"""
@@ -638,6 +639,12 @@ def test_plda_EM_vs_Prince():
   assert numpy.allclose(m.f, m_py.f, 1e-10)
   assert numpy.allclose(m.g, m_py.g, 1e-10)
   assert numpy.allclose(m.sigma, m_py.sigma, 1e-10)
+  
+  #testing exceptions
+  nose.tools.assert_raises(RuntimeError, t.initialize, m, [1,2,2])  
+  nose.tools.assert_raises(RuntimeError, t.e_step, m, [1,2,2])
+  nose.tools.assert_raises(RuntimeError, t.m_step, m, [1,2,2])  
+  
 
 
 def test_plda_enrollment():
-- 
GitLab