Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkVigraRandomForestTest.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include <mitkTestingMacros.h>
14 #include <mitkTestFixture.h>
15 #include "mitkIOUtil.h"
16 #include "itkArray2D.h"
17 
18 #include <itkCSVArray2DFileReader.h>
19 #include <itkCSVArray2DDataObject.h>
21 #include <itkLabelSampler.h>
22 #include <itkAddImageFilter.h>
23 #include <mitkImageCast.h>
25 
26 class mitkVigraRandomForestTestSuite : public mitk::TestFixture
27 {
28  CPPUNIT_TEST_SUITE(mitkVigraRandomForestTestSuite );
29  // MITK_TEST(Load_RandomForestBaseDataUsingIOUtil_shouldReturnTrue);
30  // MITK_TEST(Save_RandomForestBaseDataUsingIOUtil_shouldReturnTrue);
31 
32  // MITK_TEST(LoadWithMitkOptions_RandomForestBaseDataUsingIOUtil_shouldReturnTrue);
33  // MITK_TEST(SaveWithMitkOptions_RandomForestBaseDataUsingIOUtil_shouldReturnTrue);
34 
35  MITK_TEST(TrainThreadedDecisionForest_MatlabDataSet_shouldReturnTrue);
36  MITK_TEST(PredictWeightedDecisionForest_SetWeightsToZero_shouldReturnTrue);
37  MITK_TEST(TrainThreadedDecisionForest_BreastCancerDataSet_shouldReturnTrue);
38  CPPUNIT_TEST_SUITE_END();
39 
40 private:
41 
42  typedef Eigen::Matrix<double ,Eigen::Dynamic,Eigen::Dynamic> MatrixDoubleType;
43  typedef Eigen::Matrix<int, Eigen::Dynamic,Eigen::Dynamic> MatrixIntType;
44 
45  std::pair<MatrixDoubleType, MatrixDoubleType> FeatureData_Cancer;
46  std::pair<MatrixIntType, MatrixIntType> LabelData_Cancer;
47 
48  std::pair<MatrixDoubleType, MatrixDoubleType> FeatureData_Matlab;
49  std::pair<MatrixIntType, MatrixIntType> LabelData_Matlab;
50 
52 
53 public:
54 
55  // ------------------------------------------------------------------------------------------------------
56  // ------------------------------------------------------------------------------------------------------
57 
58 
59  void setUp() override
60  {
61  FeatureData_Cancer = convertCSVToMatrix<double>(GetTestDataFilePath("Classification/FeaturematrixBreastcancer.csv"),';',0.5,true);
62  LabelData_Cancer = convertCSVToMatrix<int>(GetTestDataFilePath("Classification/LabelmatrixBreastcancer.csv"),';',0.5,false);
63  FeatureData_Matlab = convertCSVToMatrix<double>(GetTestDataFilePath("Classification/FeaturematrixMatlab.csv"),';',0.5,true);
64  LabelData_Matlab = convertCSVToMatrix<int>(GetTestDataFilePath("Classification/LabelmatrixMatlab.csv"),';',0.5,false);
66  }
67 
68  void tearDown() override
69  {
70  classifier = nullptr;
71  }
72 
73  // ------------------------------------------------------------------------------------------------------
74  // ------------------------------------------------------------------------------------------------------
75  /*
76  Train the classifier with an exampledataset of mattlab.
77  Note: The included data are gauan normaldistributed.
78  */
79  void TrainThreadedDecisionForest_MatlabDataSet_shouldReturnTrue()
80  {
81 
82  auto & Features_Training = FeatureData_Matlab.first;
83  auto & Labels_Training = LabelData_Matlab.first;
84 
85  auto & Features_Testing = FeatureData_Matlab.second;
86  auto & Labels_Testing = LabelData_Matlab.second;
87 
88  /* Train the classifier, by giving trainingdataset for the labels and features.
89  The result in an colunmvector of the labels.*/
90  classifier->Train(Features_Training,Labels_Training);
91  Eigen::MatrixXi classes = classifier->Predict(Features_Testing);
92 
93  /* Testing the matching between the calculated colunmvector and the result of the RandomForest */
94  unsigned int testmatrix_rows = classes.rows();
95 
96  unsigned int correctly_classified_rows = 0;
97  for(unsigned int i= 0; i < testmatrix_rows; i++){
98  if(classes(i,0) == Labels_Testing(i,0)){
99  correctly_classified_rows++;
100  }
101  }
102 
103  MITK_TEST_CONDITION(correctly_classified_rows == testmatrix_rows, "Matlab Data correctly classified");
104  }
105 
106  // ------------------------------------------------------------------------------------------------------
107  // ------------------------------------------------------------------------------------------------------
108  /*
109  Train the classifier with the dataset of breastcancer patients from the
110  LibSVM Libary
111  */
112  void TrainThreadedDecisionForest_BreastCancerDataSet_shouldReturnTrue()
113  {
114 
115  auto & Features_Training = FeatureData_Cancer.first;
116  auto & Features_Testing = FeatureData_Cancer.second;
117  auto & Labels_Training = LabelData_Cancer.first;
118  auto & Labels_Testing = LabelData_Cancer.second;
119 
120 
121  /* Train the classifier, by giving trainingdataset for the labels and features.
122  The result in an colunmvector of the labels.*/
123  classifier->Train(Features_Training,Labels_Training);
124  Eigen::MatrixXi classes = classifier->Predict(Features_Testing);
125 
126  /* Testing the matching between the calculated colunmvector and the result of the RandomForest */
127  unsigned int maxrows = classes.rows();
128 
129  int count = 0;
130 
131  for(unsigned int i= 0; i < maxrows; i++){
132  if(classes(i,0) == Labels_Testing(i,0)){
133  count++;
134  }
135  }
136  MITK_TEST_CONDITION(isIntervall<int>(Labels_Testing,classes,98,99),"Testvalue of cancer data set is in range.");
137  }
138 
139  // ------------------------------------------------------------------------------------------------------
140  // ------------------------------------------------------------------------------------------------------
141 
142  void PredictWeightedDecisionForest_SetWeightsToZero_shouldReturnTrue()
143  {
144 
145  auto & Features_Training = FeatureData_Matlab.first;
146  auto & Features_Testing = FeatureData_Matlab.second;
147  auto & Labels_Training = LabelData_Matlab.first;
148 // auto & Labels_Testing = LabelData_Matlab.second;
149 
150  classifier->Train(Features_Training,Labels_Training);
151 
152  // get weights type resize it and set all weights to zero
153  auto weights = classifier->GetTreeWeights();
154  weights.resize(classifier->GetRandomForest().tree_count(),1);
155  weights.fill(0);
156 
157  classifier->SetTreeWeights(weights);
158 
159  // if all wieghts zero the missclassification rate mus be high
160  Eigen::MatrixXi classes = classifier->PredictWeighted(Features_Testing);
161 
162  /* Testing the matching between the calculated colunmvector and the result of the RandomForest */
163  unsigned int maxrows = classes.rows();
164  unsigned int count = 0;
165 
166  // check if all predictions are of class 1
167  for(unsigned int i= 0; i < maxrows; i++)
168  if(classes(i,0) == 1)
169  count++;
170 
171  MITK_TEST_CONDITION( (count == maxrows) ,"Weighted prediction - weights applied (all weights = 0).");
172  }
173 
174 
175  // ------------------------------------------------------------------------------------------------------
176  // ------------------------------------------------------------------------------------------------------
177  /*Reading an file, which includes the trainingdataset and the testdataset, and convert the
178  content of the file into an 2dim matrixpair.
179  There are an delimiter, which separates the matrix into an trainingmatrix and testmatrix */
180  template<typename T>
181  std::pair<Eigen::Matrix<T ,Eigen::Dynamic,Eigen::Dynamic>,Eigen::Matrix<T ,Eigen::Dynamic,Eigen::Dynamic> >convertCSVToMatrix(const std::string &path, char delimiter,double range, bool isXMatrix)
182  {
183  typename itk::CSVArray2DFileReader<T>::Pointer fr = itk::CSVArray2DFileReader<T>::New();
184  fr->SetFileName(path);
185  fr->SetFieldDelimiterCharacter(delimiter);
186  fr->HasColumnHeadersOff();
187  fr->HasRowHeadersOff();
188  fr->Parse();
189  try{
190  fr->Update();
191  }catch ( const itk::ExceptionObject& ex ){
192  cout << "Exception caught!" << std::endl;
193  cout << ex.GetDescription() << std::endl;
194  }
195 
196  typename itk::CSVArray2DDataObject<T>::Pointer p = fr->GetOutput();
197  unsigned int maxrowrange = p->GetMatrix().rows();
198  unsigned int c = p->GetMatrix().cols();
199  unsigned int percentRange = (unsigned int)(maxrowrange*range);
200 
201  if(isXMatrix == true){
202  Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> trainMatrixX(percentRange,c);
203  Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> testMatrixXPredict(maxrowrange-percentRange,c);
204 
205  for(unsigned int row = 0; row < percentRange; row++){
206  for(unsigned int col = 0; col < c; col++){
207  trainMatrixX(row,col) = p->GetData(row,col);
208  }
209  }
210 
211  for(unsigned int row = percentRange; row < maxrowrange; row++){
212  for(unsigned int col = 0; col < c; col++){
213  testMatrixXPredict(row-percentRange,col) = p->GetData(row,col);
214  }
215  }
216 
217  return std::make_pair(trainMatrixX,testMatrixXPredict);
218  }
219  else{
220  Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> trainLabelMatrixY(percentRange,c);
221  Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> testMatrixYPredict(maxrowrange-percentRange,c);
222 
223  for(unsigned int row = 0; row < percentRange; row++){
224  for(unsigned int col = 0; col < c; col++){
225  trainLabelMatrixY(row,col) = p->GetData(row,col);
226  }
227  }
228 
229  for(unsigned int row = percentRange; row < maxrowrange; row++){
230  for(unsigned int col = 0; col < c; col++){
231  testMatrixYPredict(row-percentRange,col) = p->GetData(row,col);
232  }
233  }
234  return std::make_pair(trainLabelMatrixY,testMatrixYPredict);
235  }
236 
237  }
238 
239  /*
240  Reading an csv-data and transfer the included datas into an matrix.
241  */
242  template<typename T>
243  Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> readCsvData(const std::string &path, char delimiter)
244  {
245  typename itk::CSVArray2DFileReader<T>::Pointer fr = itk::CSVArray2DFileReader<T>::New();
246  fr->SetFileName(path);
247  fr->SetFieldDelimiterCharacter(delimiter);
248  fr->HasColumnHeadersOff();
249  fr->HasRowHeadersOff();
250  fr->Parse();
251  try{
252  fr->Update();
253  }catch ( const itk::ExceptionObject& ex ){
254  cout << "Exception caught!" << std::endl;
255  cout << ex.GetDescription() << std::endl;
256  }
257 
258  typename itk::CSVArray2DDataObject<T>::Pointer p = fr->GetOutput();
259  unsigned int maxrowrange = p->GetMatrix().rows();
260  unsigned int maxcols = p->GetMatrix().cols();
261  Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> matrix(maxrowrange,maxcols);
262 
263  for(unsigned int rows = 0; rows < maxrowrange; rows++){
264  for(unsigned int cols = 0; cols < maxcols; cols++ ){
265  matrix(rows,cols) = p->GetData(rows,cols);
266  }
267  }
268 
269  return matrix;
270  }
271 
272  /*
273  Write the content of the array into an own csv-data in the following sequence:
274  root.csv: 1 2 3 0 0 4
275  writen.csv: 1 1:2 2:3 3:0 4:0 5:4
276  */
277  template<typename T>
278  void writeMatrixToCsv(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> paramMatrix,const std::string &path)
279  {
280  std::ofstream outputstream (path,std::ofstream::out); // 682
281 
282  if(outputstream.is_open()){
283  for(int i = 0; i < paramMatrix.rows(); i++){
284  outputstream << paramMatrix(i,0);
285  for(int j = 1; j < 11; j++){
286  outputstream << " " << j << ":" << paramMatrix(i,j);
287  }
288  outputstream << endl;
289  }
290  outputstream.close();
291  }
292  else{
293  cout << "Unable to write into CSV" << endl;
294  }
295  }
296 
297  // Method for intervalltesting
298  template<typename T>
299  bool isIntervall(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> expected, Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> actual, double lowrange, double toprange)
300  {
301  bool isInIntervall = false;
302  int count = 0;
303  unsigned int rowRange = expected.rows();
304  unsigned int colRange = expected.cols();
305  for(unsigned int i = 0; i < rowRange; i++){
306  for(unsigned int j = 0; j < colRange; j++){
307  if(expected(i,j) == actual(i,j)){
308  count++;
309  }
310  }
311 
312  double valueOfMatch = 100*count/(double)(rowRange);
313  if((lowrange <= valueOfMatch) && (toprange >= valueOfMatch)){
314  isInIntervall = true;
315  }
316  }
317  return isInIntervall;
318  }
319 
320 
321 };
322 
323 MITK_TEST_SUITE_REGISTRATION(mitkVigraRandomForest)
MITK_TEST_SUITE_REGISTRATION(mitkImageToItk)
#define MITK_TEST(TESTMETHOD)
Adds a test to the current test suite.
static std::string GetTestDataFilePath(const std::string &testData)
Get the absolute path for test data.
#define MITK_TEST_CONDITION(COND, MSG)
Test fixture for parameterized tests.