From ad08b84f164660aef0d485b3e32b2ac0bae3ca43 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Traizet?= <traizetc@cesbio.cnes.fr>
Date: Mon, 3 Jul 2017 14:37:02 +0200
Subject: [PATCH] BUG : Serialization of SOM models works again

---
 app/cbDimensionalityReductionVector.cxx | 56 +++++++++++++++++--------
 include/SOMModel.h                      |  1 +
 include/SOMModel.txx                    | 28 +++++--------
 include/cbLearningApplicationBaseDR.h   |  8 ++--
 include/cbTrainSOM.txx                  |  1 +
 5 files changed, 56 insertions(+), 38 deletions(-)

diff --git a/app/cbDimensionalityReductionVector.cxx b/app/cbDimensionalityReductionVector.cxx
index dbfd87d39a..ce4e1fa1ca 100644
--- a/app/cbDimensionalityReductionVector.cxx
+++ b/app/cbDimensionalityReductionVector.cxx
@@ -237,7 +237,6 @@ class CbDimensionalityReductionVector : public Application
 			{
 				int dimension = GetParameterInt("pcadim");
 				m_Model->SetDimension(dimension );
-				std::cout << "yo"  << std::endl;
 			}
 
 			
@@ -270,26 +269,41 @@ class CbDimensionalityReductionVector : public Application
 				if (GetParameterString("mode")=="overwrite")
 				{
 					output = ogr::DataSource::New(GetParameterString("out"), ogr::DataSource::Modes::Overwrite);
+					otb::ogr::Layer newLayer = output->CreateLayer(GetParameterString("out"),
+					 const_cast<OGRSpatialReference*>(layer.GetSpatialRef()),
+					 layer.GetGeomType());
+					// Copy existing fields
+					OGRFeatureDefn &inLayerDefn = layer.GetLayerDefn();
+					for (int k=0 ; k<inLayerDefn.GetFieldCount()-nbBands ; k++) // we don't copy the original bands 
+					{
+					OGRFieldDefn fieldDefn(inLayerDefn.GetFieldDefn(k));
+					newLayer.CreateField(fieldDefn);
+					}
 				}
 				else if (GetParameterString("mode")=="update")
 				{
-					output = ogr::DataSource::New(GetParameterString("out"), ogr::DataSource::Modes::Update_LayerCreateOnly );
+					//output = ogr::DataSource::New(GetParameterString("out"), ogr::DataSource::Modes::Update_LayerCreateOnly);
+					// Update mode
+					otb::ogr::DataSource::Pointer source_output = otb::ogr::DataSource::New(GetParameterString("out"), otb::ogr::DataSource::Modes::Read);
+					layer = source_output->GetLayer(0);
+					updateMode = true;
+					otbAppLogINFO("Update input vector data.");
+					
+					// fill temporary buffer for the transfer
+					otb::ogr::Layer inputLayer = layer;
+					layer = buffer->CopyLayer(inputLayer, std::string("Buffer"));
+					// close input data source 
+					source_output->Clear();
+					// Re-open input data source in update mode
+					output = otb::ogr::DataSource::New(GetParameterString("out"), otb::ogr::DataSource::Modes::Update_LayerUpdate);
+				
 				}
 				else
 				{
-					otbAppLogFATAL(<< "Error when creating the output file" << GetParameterString("mode") << " : unsupported writting mode type [update/overwrite]");
+					otbAppLogFATAL(<< "Error when creating the output file" << GetParameterString("mode") << " : unsupported writting mode type");
 				}
 				
-				otb::ogr::Layer newLayer = output->CreateLayer(GetParameterString("out"),
-				 const_cast<OGRSpatialReference*>(layer.GetSpatialRef()),
-				 layer.GetGeomType());
-				// Copy existing fields
-				OGRFeatureDefn &inLayerDefn = layer.GetLayerDefn();
-				for (int k=0 ; k<inLayerDefn.GetFieldCount()-nbBands ; k++) // we don't copy the original bands 
-				{
-				OGRFieldDefn fieldDefn(inLayerDefn.GetFieldDefn(k));
-				newLayer.CreateField(fieldDefn);
-				}
+			
 			}
 			
 			/*
@@ -309,6 +323,7 @@ class CbDimensionalityReductionVector : public Application
 		
 			
 			otb::ogr::Layer outLayer = output->GetLayer(0);
+			
 			OGRErr errStart = outLayer.ogr().StartTransaction();
 			
 			if (errStart != OGRERR_NONE)
@@ -337,10 +352,11 @@ class CbDimensionalityReductionVector : public Application
 			}
 			
 			// Add an ID field. (The ID already contained in the layer refers to the polygon)
+			/*
 			OGRFieldDefn IDField("ID_point", OFTInteger);
 			ogr::FieldDefn IDFieldDef(IDField);
 			outLayer.CreateField(IDFieldDef);
-			
+			*/
 			// Fill output layer
 			
 			unsigned int count=0;
@@ -351,12 +367,18 @@ class CbDimensionalityReductionVector : public Application
 			for( ; it!=itEnd ; ++it, ++count)
 			{
 				ogr::Feature dstFeature(outLayer.GetLayerDefn());
-				dstFeature.SetFrom( *it , TRUE);
-				dstFeature.SetFID(it->GetFID());
+				/*
+				if (GetParameterString("mode")=="overwrite")
+				{*/
+					dstFeature.SetFrom( *it , TRUE);
+					dstFeature.SetFID(it->GetFID());
+				//}
+				
+				
 				for (std::size_t i=0; i<classfieldname.size(); ++i){
 					dstFeature[classfieldname[i]].SetValue<ValueType>(target->GetMeasurementVector(count)[i]);
 				}
-				dstFeature["ID_point"].SetValue<int>(id);
+				//dstFeature["ID_point"].SetValue<int>(id);
 				if (updateMode)
 				{
 					outLayer.SetFeature(dstFeature);
diff --git a/include/SOMModel.h b/include/SOMModel.h
index 88209ed24e..a5752ac5c9 100644
--- a/include/SOMModel.h
+++ b/include/SOMModel.h
@@ -46,6 +46,7 @@ public:
 	typedef SOMMap<itk::VariableLengthVector<TInputValue>,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, MapDimension> MapType;
 	typedef typename MapType::SizeType       				SizeType;
 	typedef typename MapType::SpacingType       			SpacingType;
+	//typedef otb::SOM<InputListSampleType, MapType> 			EstimatorType;
 	typedef otb::SOM<InputListSampleType, MapType> 			EstimatorType;
 
 	typedef Functor::CzihoSOMLearningBehaviorFunctor    	SOMLearningBehaviorFunctorType;
diff --git a/include/SOMModel.txx b/include/SOMModel.txx
index 7afbd6f501..b0b2229ac7 100644
--- a/include/SOMModel.txx
+++ b/include/SOMModel.txx
@@ -22,7 +22,7 @@ namespace otb
 template <class TInputValue, unsigned int MapDimension>
 SOMModel<TInputValue,  MapDimension>::SOMModel()
 {
-	//m_Dimension = typename MapType::ImageDimension;
+	this->m_Dimension = MapType::ImageDimension;
 }
 
 
@@ -46,12 +46,9 @@ void SOMModel<TInputValue,  MapDimension>::Train()
     estimator->SetBetaEnd(m_BetaEnd);
     estimator->SetMaxWeight(m_MaxWeight);
     //AddProcess(estimator,"Learning");
-    
     estimator->Update();
-	
     m_SOMMap = estimator->GetOutput();
-    std::cout << "dr of the first sample : " << m_SOMMap->GetWinner(m_ListSample->GetMeasurementVector(0)) << std::endl;
-}
+   }
 
 
 
@@ -100,7 +97,7 @@ void SOMModel<TInputValue, MapDimension>::Save(const std::string & filename, con
 	inputIterator.GoToBegin();
 	std::ofstream ofs(filename, std::ios::binary);
 	binary_write_string(ofs,"som"); 
-	binary_write(ofs,static_cast<int>(MapDimension));
+	binary_write(ofs,static_cast<unsigned int>(MapDimension));
 	SizeType size = m_SOMMap->GetLargestPossibleRegion().GetSize() ;
 	for (size_t i=0;i<MapDimension;i++){
 		binary_write(ofs,size[i]);
@@ -129,12 +126,10 @@ void SOMModel<TInputValue, MapDimension>::Load(const std::string & filename, con
 		binary_read(ifs,s[i]);
 	}
 	std::string modelType(s);
-	
 	/** Read the dimension of the map (should be equal to MapDimension) */
 	
-	int dimension;
+	unsigned int dimension;
 	binary_read(ifs,dimension);
-	
 	if (modelType != "som" || dimension != MapDimension){
 		itkExceptionMacro(<< "Error opening " << filename.c_str() );
     }
@@ -146,10 +141,8 @@ void SOMModel<TInputValue, MapDimension>::Load(const std::string & filename, con
 		binary_read(ifs,size[i]);
 		index[i]=0;
 	}
-	
 	unsigned int numberOfElements;
 	binary_read(ifs,numberOfElements);
-	
 	m_SOMMap = MapType::New();
 	typename MapType::RegionType region;
 	region.SetSize( size );
@@ -165,13 +158,15 @@ void SOMModel<TInputValue, MapDimension>::Load(const std::string & filename, con
 		InputSampleType  vect(numberOfElements);
 		for (int i=0 ; i<numberOfElements; i++)
 		{
-			binary_read(ifs,vect[i]);
+			float v;    // InputValue type is not the same during training anddimredvector.
+			binary_read(ifs,v);
+			vect[i] = static_cast<double>(v);
 		}
 		outputIterator.Set(vect);
 		++outputIterator;
 	}
-
 	ifs.close();
+	
 	this->m_Dimension = MapType::ImageDimension;
 }
 
@@ -180,15 +175,14 @@ template <class TInputValue, unsigned int MapDimension>
 typename SOMModel<TInputValue, MapDimension>::TargetSampleType
 SOMModel<TInputValue, MapDimension>::DoPredict(const InputSampleType & value, ConfidenceValueType * quality) const
 { 
-	unsigned int dimension =MapType::ImageDimension;
     TargetSampleType target;
-    target.SetSize(dimension);
+    target.SetSize(this->m_Dimension);
 	
     auto winner =m_SOMMap->GetWinner(value);
-    for (int i=0; i< dimension ;i++) {
+    for (int i=0; i< this->m_Dimension ;i++) {
 		target[i] = winner.GetElement(i); 
 	}
-	
+
 	return target;
 }
 
diff --git a/include/cbLearningApplicationBaseDR.h b/include/cbLearningApplicationBaseDR.h
index 94c62d1b43..3d90432fa9 100644
--- a/include/cbLearningApplicationBaseDR.h
+++ b/include/cbLearningApplicationBaseDR.h
@@ -87,16 +87,16 @@ public:
 	  
 	// Dimensionality reduction models
 
-	typedef SOMMap<TInputValue,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 2> Map2DType;
+	//typedef SOMMap<TInputValue,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 2> Map2DType;
 	typedef otb::SOMModel<InputValueType, 2> SOM2DModelType;
 	
-	typedef SOMMap<TInputValue,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 3> Map3DType;
+	//typedef SOMMap<TInputValue,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 3> Map3DType;
 	typedef otb::SOMModel<InputValueType, 3> SOM3DModelType;
 	
-	typedef SOMMap<TInputValue,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 4> Map4DType;
+	//typedef SOMMap<TInputValue,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 4> Map4DType;
 	typedef otb::SOMModel<InputValueType, 4> SOM4DModelType;
 	
-	typedef SOMMap<TInputValue,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 5> Map5DType;
+	//typedef SOMMap<TInputValue,itk::Statistics::EuclideanDistanceMetric<itk::VariableLengthVector<TInputValue>>, 5> Map5DType;
 	typedef otb::SOMModel<InputValueType, 5> SOM5DModelType;
 	
 
diff --git a/include/cbTrainSOM.txx b/include/cbTrainSOM.txx
index 9ac28dd906..538ccea03c 100644
--- a/include/cbTrainSOM.txx
+++ b/include/cbTrainSOM.txx
@@ -117,6 +117,7 @@ void cbLearningApplicationBaseDR<TInputValue,TOutputValue>
 		using TemplateEstimatorType = typename somchoice::EstimatorType;
 		typename somchoice::Pointer dimredTrainer = somchoice::New();
 		unsigned int dim = dimredTrainer->GetDimension();
+		std::cout << dim << std::endl;
 		dimredTrainer->SetNumberOfIterations(GetParameterInt("model.som.ni"));
 		dimredTrainer->SetBetaInit(GetParameterFloat("model.som.bi"));
 		dimredTrainer->SetBetaEnd(GetParameterFloat("model.som.bf"));
-- 
GitLab