From d39df137f19ee2fc605e0b2ada43d19a82511124 Mon Sep 17 00:00:00 2001
From: Ludovic Hussonnois <ludovic.hussonnois@c-s.fr>
Date: Fri, 14 Apr 2017 15:43:30 +0100
Subject: [PATCH] REFAC: Inherit ContingencyTable from itk::Object

---
 .../app/otbComputeConfusionMatrix.cxx         | 11 ++--
 .../app/otbTrainVectorClassifier.cxx          | 15 +++--
 .../include/otbContingencyTable.h             | 65 ++++++++++++++-----
 .../include/otbContingencyTableCalculator.h   |  5 +-
 .../include/otbContingencyTableCalculator.txx |  7 +-
 .../otbContingencyTableCalculatorTest.cxx     | 11 ++--
 6 files changed, 75 insertions(+), 39 deletions(-)

diff --git a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx
index de72549233..bfc3098307 100644
--- a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx
+++ b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx
@@ -80,6 +80,7 @@ public:
   typedef ConfusionMatrixMeasurementsType::MeasurementType                      MeasurementType;
 
   typedef ContingencyTable<ClassLabelType>  ContingencyTableType;
+  typedef ContingencyTableType::Pointer     ContingencyTablePointerType;
 
 
 private:
@@ -207,16 +208,16 @@ private:
       }    
   }
 
-  void LogContingencyTable(const ContingencyTableType& contingencyTable)
+  void LogContingencyTable(const ContingencyTablePointerType& contingencyTable)
   {
-    otbAppLogINFO("Contingency table: reference labels (rows) vs. produced labels (cols)\n" << contingencyTable);
+    otbAppLogINFO("Contingency table: reference labels (rows) vs. produced labels (cols)\n" << (*contingencyTable.GetPointer()));
   }
 
-  void m_WriteContingencyTable(const ContingencyTableType& contingencyTable)
+  void m_WriteContingencyTable(const ContingencyTablePointerType& contingencyTable)
   {
     std::ofstream outFile;
     outFile.open( this->GetParameterString( "out" ).c_str() );
-    outFile << contingencyTable.to_csv();
+    outFile << contingencyTable->to_csv();
     outFile.close();
   }
 
@@ -397,7 +398,7 @@ private:
       calculator->Compute( itRef, itInput,sid.refhasnodata,sid.refnodata,sid.prodhasnodata,sid.prodnodata);
       }
 
-    ContingencyTableType contingencyTable = calculator->BuildContingencyTable();
+    ContingencyTablePointerType contingencyTable = calculator->BuildContingencyTable();
     LogContingencyTable(contingencyTable);
     m_WriteContingencyTable(contingencyTable);
   }
diff --git a/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx b/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx
index 52952b22f4..db1226b04e 100644
--- a/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx
+++ b/Modules/Applications/AppClassification/app/otbTrainVectorClassifier.cxx
@@ -49,6 +49,9 @@ public:
   typedef ConfusionMatrixCalculatorType::ConfusionMatrixType ConfusionMatrixType;
   typedef ConfusionMatrixCalculatorType::MapOfIndicesType MapOfIndicesType;
   typedef ConfusionMatrixCalculatorType::ClassLabelType ClassLabelType;
+  
+  typedef ContingencyTable<ClassLabelType> ContingencyTableType;
+  typedef ContingencyTableType::Pointer    ContingencyTablePointerType;
 
 protected:
   void DoInit()
@@ -80,14 +83,14 @@ protected:
       }
     else
       {
-      ContingencyTable<ClassLabelType> table = ComputeContingencyTable( m_PredictedList,
-                                                                        m_ClassificationSamplesWithLabel.labeledListSample );
+      ContingencyTablePointerType table = ComputeContingencyTable( m_PredictedList,
+                                                                   m_ClassificationSamplesWithLabel.labeledListSample );
       WriteContingencyTable( table );
       }
   }
 
-  ContingencyTable<ClassLabelType> ComputeContingencyTable(const TargetListSampleType::Pointer &predictedListSample,
-                                                           const TargetListSampleType::Pointer &performanceLabeledListSample)
+  ContingencyTablePointerType ComputeContingencyTable(const TargetListSampleType::Pointer &predictedListSample,
+                                                      const TargetListSampleType::Pointer &performanceLabeledListSample)
   {
     typedef ContingencyTableCalculator<ClassLabelType> ContigencyTableCalcutaltorType;
 
@@ -103,14 +106,14 @@ protected:
   }
 
 
-  void WriteContingencyTable(const ContingencyTable<ClassLabelType> & table)
+  void WriteContingencyTable(const ContingencyTablePointerType& table)
   {
     if(IsParameterEnabled("io.confmatout"))
       {
       // Write contingency table
       std::ofstream outFile;
       outFile.open( this->GetParameterString( "io.confmatout" ).c_str() );
-      outFile << table.to_csv();
+      outFile << table->to_csv();
       }
   }
 
diff --git a/Modules/Learning/Unsupervised/include/otbContingencyTable.h b/Modules/Learning/Unsupervised/include/otbContingencyTable.h
index d1996e66a3..04d515d6d0 100644
--- a/Modules/Learning/Unsupervised/include/otbContingencyTable.h
+++ b/Modules/Learning/Unsupervised/include/otbContingencyTable.h
@@ -24,24 +24,39 @@
 #include <vector>
 #include <iostream>
 #include <iomanip>
+#include <itkObject.h>
+#include <itkObjectFactory.h>
 #include <itkVariableSizeMatrix.h>
 
 namespace otb
 {
 template<class TClassLabel>
-class ContingencyTable
+class ContingencyTable : public itk::Object
 {
 public:
+  /** Standard class typedefs */
+  typedef ContingencyTable              Self;
+  typedef itk::Object                   Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(ContingencyTableCalculator, itk::Object);
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
   typedef itk::VariableSizeMatrix<unsigned long> MatrixType;
-  typedef std::vector<TClassLabel> LabelList;
+  typedef std::vector<TClassLabel>               LabelList;
 
   MatrixType matrix;
 
-  ContingencyTable(LabelList referenceLabels, LabelList producedLabels) : refLabels( referenceLabels ),
-                                                                          prodLabels( producedLabels )
+  void SetLabels(LabelList referenceLabels, LabelList producedLabels)
   {
-    unsigned int rows = static_cast<unsigned int>(refLabels.size());
-    unsigned int cols = static_cast<unsigned int>(prodLabels.size());
+    m_RefLabels = referenceLabels;
+    m_ProdLabels = producedLabels;
+    unsigned int rows = static_cast<unsigned int>(m_RefLabels.size());
+    unsigned int cols = static_cast<unsigned int>(m_ProdLabels.size());
     matrix.SetSize( rows, cols );
     matrix.Fill( 0 );
   }
@@ -51,19 +66,19 @@ public:
 
     // Retrieve the maximal width from the matrix and the labels
     size_t maxWidth = 6;
-    for( size_t i = 0; i << contingencyTable.prodLabels.size(); ++i )
+    for( size_t i = 0; i << contingencyTable.m_ProdLabels.size(); ++i )
       {
       std::ostringstream oss;
-      oss << contingencyTable.prodLabels[i];
+      oss << contingencyTable.m_ProdLabels[i];
       size_t length = oss.str().length();
       if( length > maxWidth )
         maxWidth = length;
       }
 
-    for( size_t i = 0; i << contingencyTable.refLabels.size(); ++i )
+    for( size_t i = 0; i << contingencyTable.m_RefLabels.size(); ++i )
       {
       std::ostringstream oss;
-      oss << contingencyTable.refLabels[i];
+      oss << contingencyTable.m_RefLabels[i];
       size_t length = oss.str().length();
       if( length > maxWidth )
         maxWidth = length;
@@ -85,16 +100,16 @@ public:
 
     // Write the first line of the matrix (produced labels)
     o << std::setfill(' ') << std::setw( width ) << "labels";
-    for( size_t i = 0; i < contingencyTable.prodLabels.size(); ++i )
+    for( size_t i = 0; i < contingencyTable.m_ProdLabels.size(); ++i )
       {
-      o << std::setfill(' ') << std::setw( width ) << contingencyTable.prodLabels[i];
+      o << std::setfill(' ') << std::setw( width ) << contingencyTable.m_ProdLabels[i];
       }
     o << std::endl;
 
     // For each line write the reference label, then the count value
     for( unsigned int i = 0; i < contingencyTable.matrix.Rows(); ++i )
       {
-      o << std::setfill(' ') << std::setw( width ) << contingencyTable.refLabels[i];
+      o << std::setfill(' ') << std::setw( width ) << contingencyTable.m_RefLabels[i];
       for( unsigned int j = 0; j < contingencyTable.matrix.Cols(); ++j )
         {
         o << std::setfill(' ') << std::setw( width ) << contingencyTable.matrix( i, j );
@@ -111,16 +126,16 @@ public:
 
     std::ostringstream oss;
     oss << "labels";
-    for( size_t i = 0; i < prodLabels.size(); ++i )
+    for( size_t i = 0; i < m_ProdLabels.size(); ++i )
       {
-      oss << separator << prodLabels[i];
+      oss << separator << m_ProdLabels[i];
       }
     oss << std::endl;
 
     // For each line write the reference label, then the count value
     for( unsigned int i = 0; i < matrix.Rows(); ++i )
       {
-      oss << refLabels[i];
+      oss << m_RefLabels[i];
       for( unsigned int j = 0; j < matrix.Cols(); ++j )
         {
         oss << separator << matrix( i, j );
@@ -132,9 +147,23 @@ public:
     return oss.str();
   }
 
+protected:
+  ContingencyTable()
+  {
+    SetLabels(LabelList{}, LabelList{});
+  }
+  ~ContingencyTable() ITK_OVERRIDE {}
+  void PrintSelf(std::ostream& os, itk::Indent itkNotUsed(indent)) const ITK_OVERRIDE
+  {
+    os << *this;
+  }
+
 private:
-  LabelList refLabels;
-  LabelList prodLabels;
+  ContingencyTable(const Self &); //purposely not implemented
+  void operator=(const Self &); //purposely not implemented
+
+  LabelList m_RefLabels;
+  LabelList m_ProdLabels;
 
 
 };
diff --git a/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.h b/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.h
index 7f06bf7d18..ae30bf8441 100644
--- a/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.h
+++ b/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.h
@@ -53,7 +53,8 @@ public:
   /** Method for creation through the object factory. */
   itkNewMacro(Self);
 
-  typedef ContingencyTable<TClassLabel> ContingencyTableType;
+  typedef ContingencyTable<TClassLabel>          ContingencyTableType;
+  typedef typename ContingencyTableType::Pointer ContingencyTablePointerType;
 
   typedef typename std::map<TClassLabel, unsigned long> CountMapType;
   typedef typename std::map<TClassLabel, CountMapType > MapOfClassesType;
@@ -72,7 +73,7 @@ public:
   itkGetConstMacro(NumberOfSamples, unsigned long);
 
   void Clear();
-  ContingencyTableType BuildContingencyTable();
+  ContingencyTablePointerType BuildContingencyTable();
 
 protected:
   ContingencyTableCalculator();
diff --git a/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.txx b/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.txx
index 8f11d6207f..369ee1a3a0 100644
--- a/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.txx
+++ b/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.txx
@@ -83,7 +83,7 @@ ContingencyTableCalculator<TClassLabel>
 
 
 template<class TClassLabel>
-typename ContingencyTableCalculator<TClassLabel>::ContingencyTableType
+typename ContingencyTableCalculator<TClassLabel>::ContingencyTablePointerType
 ContingencyTableCalculator<TClassLabel>
 ::BuildContingencyTable()
 {
@@ -113,11 +113,12 @@ ContingencyTableCalculator<TClassLabel>
   std::copy(refLabels.begin(), refLabels.end(), std::back_inserter(referenceLabels));
   std::copy(prodLabels.begin(), prodLabels.end(), std::back_inserter(producedLabels));
 
-  ContingencyTableType contingencyTable(referenceLabels, producedLabels);
+  ContingencyTablePointerType contingencyTable = ContingencyTableType::New();
+  contingencyTable->SetLabels(referenceLabels, producedLabels);
 
   for( unsigned int i = 0; i < rows; ++i )
     for( unsigned int j = 0; j < cols; ++j )
-      contingencyTable.matrix(i,j) = m_LabelCount[referenceLabels[i]][producedLabels[j]];
+      contingencyTable->matrix(i,j) = m_LabelCount[referenceLabels[i]][producedLabels[j]];
 
 
   return contingencyTable;
diff --git a/Modules/Learning/Unsupervised/test/otbContingencyTableCalculatorTest.cxx b/Modules/Learning/Unsupervised/test/otbContingencyTableCalculatorTest.cxx
index b5ccae6bd7..dc0bdc8033 100644
--- a/Modules/Learning/Unsupervised/test/otbContingencyTableCalculatorTest.cxx
+++ b/Modules/Learning/Unsupervised/test/otbContingencyTableCalculatorTest.cxx
@@ -93,7 +93,8 @@ int otbContingencyTableCalculatorCompute(int argc, char* argv[])
   typedef itk::FixedArray<ClassLabelType, 1>              RLabelType;
   typedef itk::Statistics::ListSample<RLabelType>         RListLabelType;
   typedef otb::ContingencyTableCalculator<ClassLabelType> CalculatorType;
-  typedef CalculatorType::ContingencyTableType          ContingencyTableType;
+  typedef CalculatorType::ContingencyTableType            ContingencyTableType;
+  typedef ContingencyTableType::Pointer                   ContingencyTablePointerType;
 
   CalculatorType::Pointer calculator = CalculatorType::New();
 
@@ -126,7 +127,7 @@ int otbContingencyTableCalculatorCompute(int argc, char* argv[])
     }
 
   calculator->Compute( refLabels->Begin(), refLabels->End(), prodLabels->Begin(), prodLabels->End() );
-  ContingencyTableType confmat = calculator->BuildContingencyTable();
+  ContingencyTablePointerType contingencyTable = calculator->BuildContingencyTable();
 
 
   if( static_cast<int>(calculator->GetNumberOfRefClasses()) != nbRefClasses )
@@ -148,7 +149,7 @@ int otbContingencyTableCalculatorCompute(int argc, char* argv[])
     }
 
 
-  std::cout << "contingency table" << std::endl  << confmat << std::endl;
+  std::cout << "contingency table" << std::endl  << (*contingencyTable.GetPointer()) << std::endl;
 
   return EXIT_SUCCESS;
 }
@@ -216,10 +217,10 @@ int otbContingencyTableCalculatorComputeWithBaseline(int itkNotUsed(argc), char*
     }
 
   calculator->Compute( refLabels->Begin(), refLabels->End(), prodLabels->Begin(), prodLabels->End() );
-  CalculatorType::ContingencyTableType confmat = calculator->BuildContingencyTable();
+  CalculatorType::ContingencyTablePointerType contingencyTable = calculator->BuildContingencyTable();
 
   std::cout << std::endl;
-  std::cout << "contingency Table" << std::endl << confmat << std::endl;
+  std::cout << "contingency Table" << std::endl << (*contingencyTable.GetPointer()) << std::endl;
   unsigned int nbRefClasses = 5;
   unsigned int nbProdClasses = 7;
 
-- 
GitLab