Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
TumorResponseEvaluationTool.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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 // MITK - DataCollection
18 #include <mitkCollectionReader.h>
19 #include <mitkCollectionWriter.h>
20 #include <mitkDataCollection.h>
21 #include <mitkImageCast.h>
22 
26 // CTK
27 #include "mitkCommandLineParser.h"
28 // ITK
29 #include <itkImageRegionIterator.h>
30 
31 using namespace std;
32 
33 int main(int argc, char *argv[])
34 {
35  // Setup CLI Module parsable interface
36  mitkCommandLineParser parser;
37  parser.setTitle("Tumor Invasion Analysis");
38  parser.setCategory("Tumor Analysis");
39  parser.setDescription("Learns and predicts Invasion behavior");
40  parser.setContributor("MBI");
41 
42  parser.setArgumentPrefix("--", "-");
43  // Add command line argument names
44  parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Show options");
45  parser.addArgument("loadFile", "l", mitkCommandLineParser::InputFile, "DataCollection File");
46  parser.addArgument(
47  "colIds", "c", mitkCommandLineParser::String, "Patient Identifiers from DataCollection used for training");
48  parser.addArgument(
49  "testId", "t", mitkCommandLineParser::String, "Patient Identifier from DataCollection used for testing");
50  parser.addArgument("features", "b", mitkCommandLineParser::String, "Features");
51  parser.addArgument("stats", "s", mitkCommandLineParser::String, "Output file for stats");
52  parser.addArgument("ratio", "q", mitkCommandLineParser::Float, "ratio of tumor to healthy");
53  parser.addArgument("treeDepth", "d", mitkCommandLineParser::Int, "limits tree depth");
54  parser.addArgument("forestSize", "f", mitkCommandLineParser::Int, "number of trees");
55  parser.addArgument("configName", "n", mitkCommandLineParser::String, "human readable name for configuration");
56  parser.addArgument("output", "o", mitkCommandLineParser::OutputDirectory, "output folder for results");
57  parser.addArgument("forest", "t", mitkCommandLineParser::OutputFile, "store trained forest to file");
58 
59  map<string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
60  // Show a help message
61  if (parsedArgs.size() == 0)
62  return EXIT_SUCCESS;
63  if (parsedArgs.count("help") || parsedArgs.count("h"))
64  {
65  std::cout << parser.helpText();
66  return EXIT_SUCCESS;
67  }
68 
69  // Default values
70  float ratio = 1.0;
71  bool useStatsFile = false;
72  unsigned int forestSize = 250;
73  unsigned int treeDepth = 0;
74  std::string configName = "";
75  std::string outputFolder = "";
76  std::string forestFile = "";
77 
78  std::vector<std::string> features;
79  std::vector<std::string> trainingIds;
80  std::vector<std::string> testingIds;
81  std::vector<std::string> loadIds; // features + masks needed for training and evaluation
82  std::string outputFile;
83  std::string xmlFile;
84  std::ofstream experimentFS;
85 
86  // Parse input parameters
87  {
88  if (parsedArgs.count("colIds") || parsedArgs.count("c"))
89  {
90  std::istringstream ss(us::any_cast<string>(parsedArgs["colIds"]));
91  std::string token;
92 
93  while (std::getline(ss, token, ','))
94  trainingIds.push_back(token);
95  }
96 
97  if (parsedArgs.count("output") || parsedArgs.count("o"))
98  {
99  outputFolder = us::any_cast<string>(parsedArgs["output"]);
100  }
101 
102  if (parsedArgs.count("configName") || parsedArgs.count("n"))
103  {
104  configName = us::any_cast<string>(parsedArgs["configName"]);
105  }
106 
107  if (parsedArgs.count("features") || parsedArgs.count("b"))
108  {
109  std::istringstream ss(us::any_cast<string>(parsedArgs["features"]));
110  std::string token;
111 
112  while (std::getline(ss, token, ','))
113  features.push_back(token);
114  }
115 
116  if (parsedArgs.count("treeDepth") || parsedArgs.count("d"))
117  {
118  treeDepth = us::any_cast<int>(parsedArgs["treeDepth"]);
119  }
120 
121  if (parsedArgs.count("ratio") || parsedArgs.count("q"))
122  {
123  ratio = us::any_cast<float>(parsedArgs["ratio"]);
124  }
125 
126  if (parsedArgs.count("forestSize") || parsedArgs.count("f"))
127  {
128  forestSize = us::any_cast<int>(parsedArgs["forestSize"]);
129  }
130 
131  if (parsedArgs.count("stats") || parsedArgs.count("s"))
132  {
133  useStatsFile = true;
134  experimentFS.open(us::any_cast<string>(parsedArgs["stats"]).c_str(), std::ios_base::app);
135  }
136 
137  if (parsedArgs.count("forest") || parsedArgs.count("t"))
138  {
139  forestFile = us::any_cast<string>(parsedArgs["stats"]);
140  }
141 
142  if (parsedArgs.count("testId") || parsedArgs.count("t"))
143  {
144  std::istringstream ss(us::any_cast<string>(parsedArgs["testId"]));
145  std::string token;
146 
147  while (std::getline(ss, token, ','))
148  testingIds.push_back(token);
149  }
150 
151  for (unsigned int i = 0; i < features.size(); i++)
152  {
153  loadIds.push_back(features.at(i));
154  }
155  loadIds.push_back("GTV");
156  loadIds.push_back("BRAINMASK");
157  loadIds.push_back("TARGET");
158 
159  if (parsedArgs.count("stats") || parsedArgs.count("s"))
160  {
161  outputFile = us::any_cast<string>(parsedArgs["stats"]);
162  }
163 
164  if (parsedArgs.count("loadFile") || parsedArgs.count("l"))
165  {
166  xmlFile = us::any_cast<string>(parsedArgs["loadFile"]);
167  }
168  else
169  {
170  MITK_ERROR << parser.helpText();
171  return EXIT_FAILURE;
172  }
173  }
174 
175  mitk::DataCollection::Pointer trainCollection;
176  mitk::DataCollection::Pointer testCollection;
177  {
178  mitk::CollectionReader colReader;
179  // Load only relevant images
180  colReader.SetDataItemNames(loadIds);
181  colReader.AddSubColIds(testingIds);
182  testCollection = colReader.LoadCollection(xmlFile);
183  colReader.ClearDataElementIds();
184  colReader.ClearSubColIds();
185  colReader.SetDataItemNames(loadIds);
186  colReader.AddSubColIds(trainingIds);
187  trainCollection = colReader.LoadCollection(xmlFile);
188  }
189 
190  std::cout << "Setup Training" << std::endl;
192 
193  classifier.SetClassRatio(ratio);
194  classifier.SamplesWeightingActivated(true);
195  classifier.PrepareResponseSamples(trainCollection);
196  // Learning stage
197  std::cout << "Start Training" << std::endl;
198  classifier.LearnProgressionFeatures(trainCollection, features, forestSize, treeDepth);
199 
200  if (forestFile != "")
201  classifier.SaveRandomForest(forestFile);
202 
203  std::cout << "Start Predict" << std::endl;
204  classifier.PredictInvasion(testCollection, features);
205 
206  if (outputFolder != "")
207  {
208  std::cout << "Saving files to " << outputFolder << std::endl;
209  mitk::CollectionWriter::ExportCollectionToFolder(trainCollection, "/tmp/dumple");
210  }
211 
212  /* prepare target values to match training values:
213  * 0 - excluded (e.g. out of brainmask)
214  * 1 - no involvement (healthy all the time)
215  * 2 - formerly healthy, now tumor (rezivid)
216  * 3 - formerly tumor, now necroses (responsive)
217  */
218 
219  {
220  mitk::DataCollectionImageIterator<unsigned char, 3> gtvIter(testCollection, "GTV");
221  mitk::DataCollectionImageIterator<unsigned char, 3> targetIt(testCollection, "TARGET");
222 
223  while (!gtvIter.IsAtEnd())
224  {
225  if (targetIt.GetVoxel() == 0 && gtvIter.GetVoxel() == 0)
226  targetIt.SetVoxel(1);
227 
228  if (targetIt.GetVoxel() == 0 && gtvIter.GetVoxel() == 1)
229  targetIt.SetVoxel(3);
230 
231  if (targetIt.GetVoxel() == 1 && gtvIter.GetVoxel() == 0)
232  targetIt.SetVoxel(2);
233 
234  targetIt++;
235  gtvIter++;
236  }
237  }
238 
240  mitk::ProgressionValueToIndexMapper progressionValueToIndexMapper;
241  mitk::BinaryValueToIndexMapper binaryValueToIndexMapper;
242 
243  stats.SetCollection(testCollection);
244  stats.SetClassCount(4);
245  stats.SetGoldName("TARGET");
246  stats.SetTestName("RESULT");
247  stats.SetMaskName("BRAINMASK");
248  stats.SetGroundTruthValueToIndexMapper(&binaryValueToIndexMapper);
249  stats.SetTestValueToIndexMapper(&binaryValueToIndexMapper);
250 
251  stats.Update();
252  std::ostringstream outStr;
253  stats.Print(outStr, std::cout, true);
254  std::cout << std::endl << std::endl << outStr.str() << std::endl;
255 
256  if (useStatsFile)
257  std::cout << "dummy" << std::endl;
258 
259  if (outputFolder != "")
260  {
261  std::cout << "Saving files to " << outputFolder << std::endl;
262  mitk::CollectionWriter::ExportCollectionToFolder(testCollection, outputFolder);
263  }
264 
265  return EXIT_SUCCESS;
266 }
void SamplesWeightingActivated(bool isActive)
SamplesWeightingActivated If activated a weighted mask for the samples is calculated, weighting samples according to their location and ratio.
DataCollection::Pointer LoadCollection(const std::string &xmlFileName)
Build up a mitk::DataCollection from a XML resource.
int main(int argc, char *argv[])
void SetDataItemNames(std::vector< std::string > itemNames)
void Print(std::ostream &out, std::ostream &sout=std::cout, bool withHeader=false, std::string label="None")
void SaveRandomForest(std::string filename)
SaveRandomForest - Saves a trained random forest.
void SetTestName(std::string name)
#define MITK_ERROR
Definition: mitkLogMacros.h:24
void setContributor(std::string contributor)
void SetTestValueToIndexMapper(const ValueToIndexMapper *mapper)
STL namespace.
ValueType * any_cast(Any *operand)
Definition: usAny.h:377
void SetGroundTruthValueToIndexMapper(const ValueToIndexMapper *mapper)
std::map< std::string, us::Any > parseArguments(const StringContainerType &arguments, bool *ok=nullptr)
void PrepareResponseSamples(DataCollection *collection)
PrepareResponseSamples.
void SetMaskName(std::string name)
void SetGoldName(std::string name)
void addArgument(const std::string &longarg, const std::string &shortarg, Type type, const std::string &argLabel, const std::string &argHelp=std::string(), const us::Any &defaultValue=us::Any(), bool optional=true, bool ignoreRest=false, bool deprecated=false)
void PredictInvasion(DataCollection *collection, std::vector< std::string > modalitiesList)
PredictGrowth - Classify voxels into remaining healthy / turning into tumor.
void SetCollection(DataCollection::Pointer collection)
void SetClassCount(vcl_size_t count)
void setCategory(std::string category)
static bool ExportCollectionToFolder(DataCollection *dataCollection, std::string xmlFile, std::vector< std::string > filter)
ExportCollectionToFolder.
The TumorInvasionAnalysis class - Classifies Tumor progression using RF and predicts on new cases...
void setArgumentPrefix(const std::string &longPrefix, const std::string &shortPrefix)
void LearnProgressionFeatures(DataCollection *collection, std::vector< std::string > modalitiesList, vcl_size_t forestSize=300, vcl_size_t treeDepth=10)
LearnProgressionFeatures.
void SetClassRatio(ScalarType ratio)
SetClassRatio - set ratio of tumor voxels to healthy voxels that is to be used for training...
void AddSubColIds(std::vector< std::string > subColIds)
const char features[]
std::string helpText() const
void setTitle(std::string title)
void setDescription(std::string description)