Medical Imaging Interaction Toolkit  2018.4.99-a3d2e8fb
Medical Imaging Interaction Toolkit
MRPerfusionMiniApp.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 // std includes
14 #include <string>
15 
16 // itk includes
17 #include "itksys/SystemTools.hxx"
18 
19 // CTK includes
20 #include "mitkCommandLineParser.h"
21 
22 // MITK includes
23 #include <mitkIOUtil.h>
25 
26 #include <mitkImageTimeSelector.h>
27 #include <mitkImageCast.h>
28 
31 #include <mitkModelFitInfo.h>
33 
37 #include <mitkExtractTimeGrid.h>
51 #include <mitkModelFactoryBase.h>
52 
53 std::string inFilename;
54 std::string outFileName;
55 std::string maskFileName;
56 std::string aifMaskFileName;
57 std::string aifImageFileName;
58 
63 
64 bool useConstraints(false);
65 bool verbose(false);
66 bool roibased(false);
67 bool preview(false);
68 
69 std::string modelName;
70 
71 float aifHematocritLevel(0);
72 float brixInjectionTime(0);
73 
74 const std::string MODEL_NAME_2SL = "2SL";
75 const std::string MODEL_NAME_3SL = "3SL";
76 const std::string MODEL_NAME_descriptive = "descriptive";
77 const std::string MODEL_NAME_tofts = "tofts";
78 const std::string MODEL_NAME_2CX = "2CX";
79 
80 void onFitEvent(::itk::Object* caller, const itk::EventObject & event, void* /*data*/)
81 {
82  itk::ProgressEvent progressEvent;
83 
84  if (progressEvent.CheckEvent(&event))
85  {
86  mitk::ParameterFitImageGeneratorBase* castedReporter = dynamic_cast<mitk::ParameterFitImageGeneratorBase*>(caller);
87  std::cout <<castedReporter->GetProgress()*100 << "% ";
88  }
89 }
90 
91 
93 {
94  // set general information about your MiniApp
95  parser.setCategory("Dynamic Data Analysis Tools");
96  parser.setTitle("MR Perfusion");
97  parser.setDescription("MiniApp that allows to fit MRI perfusion models and generates the according parameter maps. IMPORTANT!!!: The app assumes that the input images (signal and AIF) are concentration images. If your images do not hold this assumption, convert the image date before using this app (e.g. by using the signal-to-concentration-converter mini app.");
98  parser.setContributor("DKFZ MIC");
100 
102  // how should arguments be prefixed
103  parser.setArgumentPrefix("--", "-");
104  // add each argument, unless specified otherwise each argument is optional
105  // see mitkCommandLineParser::addArgument for more information
106  parser.beginGroup("Model parameters");
107  parser.addArgument(
108  "model", "l", mitkCommandLineParser::String, "Model function", "Model that should be used to fit the concentration signal. Options are: \""+MODEL_NAME_descriptive+"\" (descriptive pharmacokinetic Brix model),\""+MODEL_NAME_3SL+"\" (three step linear model), \""+MODEL_NAME_tofts+"\" (extended tofts model) or \""+MODEL_NAME_2CX+"\" (two compartment exchange model).", us::Any(std::string(MODEL_NAME_tofts)));
109  parser.addArgument(
110  "injectiontime", "j", mitkCommandLineParser::Float, "Injection time [min]", "Injection time of the bolus. This information is needed for the descriptive pharmacokinetic Brix model.", us::Any());
111  parser.endGroup();
112  parser.beginGroup("Required I/O parameters");
113  parser.addArgument(
114  "input", "i", mitkCommandLineParser::File, "Input file", "input 3D+t image file", us::Any(), false, false, false, mitkCommandLineParser::Input);
115  parser.addArgument("output",
116  "o",
118  "Output file template",
119  "where to save the output parameter images. The specified path will be used as template to determine the format (via extension) and the name \"root\". For each parameter a suffix will be added to the name.",
120  us::Any(),
121  false, false, false, mitkCommandLineParser::Output);
122  parser.endGroup();
123 
124  parser.beginGroup("AIF parameters");
125  parser.addArgument(
126  "aifmask", "n", mitkCommandLineParser::File, "AIF mask file", "Mask that defines the spatial image region that should be used as AIF for models that need one. Must have the same geometry as the AIF input image!", us::Any(), true, false, false, mitkCommandLineParser::Input);
127  parser.addArgument(
128  "aifimage", "a", mitkCommandLineParser::File, "AIF image file", "3D+t image that defines the image that containes the AIF signal. If this flag is not set and the model needs a AIF, the CLI will assume that the AIF is encoded in the normal image. Must have the same geometry as the AIF mask!", us::Any(), true, false, false, mitkCommandLineParser::Input);
129  parser.addArgument(
130  "hematocrit", "h", mitkCommandLineParser::Float, "Hematocrit Level", "Value needed for correct AIF computation. Only needed if model needs an AIF. Default value is 0.45.", us::Any(0.45));
131  parser.endGroup();
132 
133  parser.beginGroup("Optional parameters");
134  parser.addArgument(
135  "mask", "m", mitkCommandLineParser::File, "Mask file", "Mask that defines the spatial image region that should be fitted. Must have the same geometry as the input image!", us::Any(), true, false, false, mitkCommandLineParser::Input);
136  parser.addArgument(
137  "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output");
138  parser.addArgument(
139  "roibased", "r", mitkCommandLineParser::Bool, "Roi based fitting", "Will compute a mean intesity signal over the ROI before fitting it. If this mode is used a mask must be specified.");
140  parser.addArgument(
141  "constraints", "c", mitkCommandLineParser::Bool, "Constraints", "Indicates if constraints should be used for the fitting (if flag is set the default contraints will be used.).", us::Any(false));
142  parser.addArgument(
143  "preview", "p", mitkCommandLineParser::Bool, "Preview outputs", "The application previews the outputs (filename, type) it would produce with the current settings.");
144  parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text");
145  parser.endGroup();
147 }
148 
149 bool configureApplicationSettings(std::map<std::string, us::Any> parsedArgs)
150 {
151  if (parsedArgs.size() == 0)
152  return false;
153 
154  // parse, cast and set required arguments
156  if (parsedArgs.count("model"))
157  {
158  modelName = us::any_cast<std::string>(parsedArgs["model"]);
159  }
160 
161  inFilename = us::any_cast<std::string>(parsedArgs["input"]);
162  outFileName = us::any_cast<std::string>(parsedArgs["output"]);
163 
164  if (parsedArgs.count("mask"))
165  {
166  maskFileName = us::any_cast<std::string>(parsedArgs["mask"]);
167  }
168 
169  if (parsedArgs.count("aifimage"))
170  {
171  aifImageFileName = us::any_cast<std::string>(parsedArgs["aifimage"]);
172  }
173 
174  if (parsedArgs.count("aifmask"))
175  {
176  aifMaskFileName = us::any_cast<std::string>(parsedArgs["aifmask"]);
177  }
178 
179  verbose = false;
180  if (parsedArgs.count("verbose"))
181  {
182  verbose = us::any_cast<bool>(parsedArgs["verbose"]);
183  }
184 
185  preview = false;
186  if (parsedArgs.count("preview"))
187  {
188  preview = us::any_cast<bool>(parsedArgs["preview"]);
189  }
190 
191  roibased = false;
192  if (parsedArgs.count("roibased"))
193  {
194  roibased = us::any_cast<bool>(parsedArgs["roibased"]);
195  }
196 
197  useConstraints = false;
198  if (parsedArgs.count("constraints"))
199  {
200  useConstraints = us::any_cast<bool>(parsedArgs["constraints"]);
201  }
202 
203  aifHematocritLevel = 0.45;
204  if (parsedArgs.count("hematocrit"))
205  {
206  aifHematocritLevel = us::any_cast<float>(parsedArgs["hematocrit"]);
207  }
208 
209  brixInjectionTime = 0.0;
210  if (parsedArgs.count("injectiontime"))
211  {
212  brixInjectionTime = us::any_cast<float>(parsedArgs["injectiontime"]);
213  }
214  return true;
215 }
216 
218  const mitk::ModelParameterizerBase* parameterizer, const mitk::ModelFactoryBase* modelFactory)
219 {
222 
225  fitFunctor->RegisterEvaluationParameter("Chi^2", chi2);
226 
227  if (useConstraints)
228  {
229  fitFunctor->SetConstraintChecker(modelFactory->CreateDefaultConstraints().GetPointer());
230  }
231 
232  mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel();
233 
234  ::itk::LevenbergMarquardtOptimizer::ScalesType scales;
235  scales.SetSize(refModel->GetNumberOfParameters());
236  scales.Fill(1.0);
237  fitFunctor->SetScales(scales);
238 
239  fitFunctor->SetDebugParameterMaps(true);
240 
241  return fitFunctor.GetPointer();
242 }
243 
247 {
248  mitk::Image::Pointer result;
249 
250  if (mask.IsNotNull())
251  {
252  result = mask;
253 
254  //mask settings
255  if (mask->GetTimeSteps() > 1)
256  {
257  MITK_INFO << "Selected mask has multiple timesteps. Only use first timestep to mask model fit.";
259  maskedImageTimeSelector->SetInput(mask);
260  maskedImageTimeSelector->SetTimeNr(0);
261  maskedImageTimeSelector->UpdateLargestPossibleRegion();
262  result = maskedImageTimeSelector->GetOutput();
263  }
264  }
265 
266  return result;
267 }
268 
269 
272 {
273  if (aifMask.IsNotNull())
274  {
275  aif.clear();
276  aifTimeGrid.clear();
277 
278  mitk::AterialInputFunctionGenerator::Pointer aifGenerator =
280 
281  //Hematocrit level
282  aifGenerator->SetHCL(aifHematocritLevel);
283  std::cout << "AIF hematocrit level: " << aifHematocritLevel << std::endl;
284 
285  mitk::Image::Pointer selectedAIFMask = aifMask;
286 
287  //mask settings
288  if (aifMask->GetTimeSteps() > 1)
289  {
290  MITK_INFO << "Selected AIF mask has multiple timesteps. Only use first timestep to mask model fit.";
292  maskedImageTimeSelector->SetInput(aifMask);
293  maskedImageTimeSelector->SetTimeNr(0);
294  maskedImageTimeSelector->UpdateLargestPossibleRegion();
295  aifMask = maskedImageTimeSelector->GetOutput();
296  }
297 
298  aifGenerator->SetMask(aifMask);
299 
300  mitk::Image::Pointer selectedAIFImage = image;
301  //image settings
302  if (aifImage.IsNotNull())
303  {
304  selectedAIFImage = aifImage;
305  }
306 
307  aifGenerator->SetDynamicImage(selectedAIFImage);
308 
309  aif = aifGenerator->GetAterialInputFunction();
310  aifTimeGrid = aifGenerator->GetAterialInputFunctionTimeGrid();
311  }
312  else
313  {
314  mitkThrow() << "Cannot generate AIF. AIF mask was not specified or correctly loaded.";
315  }
316 }
317 
318 
319 void generateDescriptiveBrixModel_PixelBased(mitk::modelFit::ModelFitInfo::Pointer&
320  modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
321 {
322  mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator =
324 
327 
328  mitk::Image::Pointer mask3D = getMask3D();
329 
330  //Model configuration (static parameters) can be done now
331  modelParameterizer->SetTau(brixInjectionTime);
332  std::cout << "Injection time [min]: " << brixInjectionTime << std::endl;
333 
335  imageTimeSelector->SetInput(image);
336  imageTimeSelector->SetTimeNr(0);
337  imageTimeSelector->UpdateLargestPossibleRegion();
338 
339  mitk::DescriptivePharmacokineticBrixModelParameterizer::BaseImageType::Pointer baseImage;
340  mitk::CastToItkImage(imageTimeSelector->GetOutput(), baseImage);
341 
342  modelParameterizer->SetBaseImage(baseImage);
343 
344  //Specify fitting strategy and criterion parameters
345  mitk::ModelFactoryBase::Pointer factory = mitk::DescriptivePharmacokineticBrixModelFactory::New().GetPointer();
346  mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory);
347 
348  //Parametrize fit generator
349  fitGenerator->SetModelParameterizer(modelParameterizer);
350  std::string roiUID = "";
351 
352  if (mask3D.IsNotNull())
353  {
354  fitGenerator->SetMask(mask3D);
355  roiUID = mitk::EnsureModelFitUID(mask);
356  }
357 
358  fitGenerator->SetDynamicImage(image);
359  fitGenerator->SetFitFunctor(fitFunctor);
360 
361  generator = fitGenerator.GetPointer();
362 
363  //Create model info
364  modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer,
366 }
367 
368 void generateDescriptiveBrixModel_ROIBased(mitk::modelFit::ModelFitInfo::Pointer&
369  modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
370 {
371  mitk::Image::Pointer mask3D = getMask3D();
372 
373  if (mask3D.IsNull())
374  {
375  return;
376  }
377 
378  mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator =
380 
383 
384  //Compute ROI signal
385  mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator =
387  signalGenerator->SetMask(mask3D);
388  signalGenerator->SetDynamicImage(image);
389  signalGenerator->Generate();
390 
391  mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean();
392 
393  //Model configuration (static parameters) can be done now
394  modelParameterizer->SetTau(brixInjectionTime);
395  std::cout << "Injection time [min]: " << brixInjectionTime << std::endl;
396  modelParameterizer->SetBaseValue(roiSignal[0]);
397 
398  //Specify fitting strategy and criterion parameters
399  mitk::ModelFactoryBase::Pointer factory = mitk::DescriptivePharmacokineticBrixModelFactory::New().GetPointer();
400  mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory);
401 
402  //Parametrize fit generator
403  fitGenerator->SetModelParameterizer(modelParameterizer);
404  fitGenerator->SetMask(mask3D);
405  fitGenerator->SetFitFunctor(fitFunctor);
406  fitGenerator->SetSignal(roiSignal);
407  fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image));
408 
409  generator = fitGenerator.GetPointer();
410 
411  std::string roiUID = mitk::EnsureModelFitUID(mask);
412 
413  //Create model info
414  modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer,
417 
418  for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos =
419  roiSignal.begin(); pos != roiSignal.end(); ++pos)
420  {
421  infoSignal.push_back(*pos);
422  }
423 
424  modelFitInfo->inputData.SetTableValue("ROI", infoSignal);
425 }
426 
427 template <typename TParameterizer, typename TFactory>
428 void GenerateLinearModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer&
429  modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
430 {
431  mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator =
433 
434  typename TParameterizer::Pointer modelParameterizer = TParameterizer::New();
435 
436  mitk::Image::Pointer mask3D = getMask3D();
437 
438  //Specify fitting strategy and criterion parameters
439  mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer();
440  mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory);
441 
442  //Parametrize fit generator
443  fitGenerator->SetModelParameterizer(modelParameterizer);
444  std::string roiUID = "";
445 
446  if (mask3D.IsNotNull())
447  {
448  fitGenerator->SetMask(mask3D);
449  roiUID = mitk::EnsureModelFitUID(mask);
450  }
451 
452  fitGenerator->SetDynamicImage(image);
453  fitGenerator->SetFitFunctor(fitFunctor);
454 
455  generator = fitGenerator.GetPointer();
456 
457  //Create model info
458  modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer,
460 }
461 
462 template <typename TParameterizer, typename TFactory>
463 void GenerateLinearModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer&
464  modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
465 {
466  mitk::Image::Pointer mask3D = getMask3D();
467 
468  if (mask3D.IsNull())
469  {
470  return;
471  }
472 
473  mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator =
475 
476  typename TParameterizer::Pointer modelParameterizer = TParameterizer::New();
477 
478  //Compute ROI signal
479  mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator =
481  signalGenerator->SetMask(mask3D);
482  signalGenerator->SetDynamicImage(image);
483  signalGenerator->Generate();
484 
485  mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean();
486 
487  //Specify fitting strategy and criterion parameters
488  mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer();
489  mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory);
490 
491 
492  //Parametrize fit generator
493  fitGenerator->SetModelParameterizer(modelParameterizer);
494  fitGenerator->SetMask(mask3D);
495  fitGenerator->SetFitFunctor(fitFunctor);
496  fitGenerator->SetSignal(roiSignal);
497  fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image));
498 
499  generator = fitGenerator.GetPointer();
500 
501  std::string roiUID = mitk::EnsureModelFitUID(mask);
502 
503  //Create model info
504  modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer,
507 
508  for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos =
509  roiSignal.begin(); pos != roiSignal.end(); ++pos)
510  {
511  infoSignal.push_back(*pos);
512  }
513 
514  modelFitInfo->inputData.SetTableValue("ROI", infoSignal);
515 }
516 
517 template <typename TParameterizer, typename TFactory>
518 void generateAIFbasedModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer&
519  modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
520 {
521  mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator =
523 
524  typename TParameterizer::Pointer modelParameterizer =
525  TParameterizer::New();
526 
529  getAIF(aif, aifTimeGrid);
530 
531  modelParameterizer->SetAIF(aif);
532  modelParameterizer->SetAIFTimeGrid(aifTimeGrid);
533 
534  mitk::Image::Pointer mask3D = getMask3D();
535 
536  //Specify fitting strategy and criterion parameters
537  mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer();
538  mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory);
539 
540  //Parametrize fit generator
541  fitGenerator->SetModelParameterizer(modelParameterizer);
542  std::string roiUID = "";
543 
544  if (mask3D.IsNotNull())
545  {
546  fitGenerator->SetMask(mask3D);
547  roiUID = mitk::EnsureModelFitUID(mask);
548  }
549 
550  fitGenerator->SetDynamicImage(image);
551  fitGenerator->SetFitFunctor(fitFunctor);
552 
553  generator = fitGenerator.GetPointer();
554 
555  //Create model info
556  modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer,
558  roiUID);
559 
561 
562  for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos =
563  aif.begin(); pos != aif.end(); ++pos)
564  {
565  infoSignal.push_back(*pos);
566  }
567 
568  modelFitInfo->inputData.SetTableValue("AIF", infoSignal);
569 }
570 
571 template <typename TParameterizer, typename TFactory>
573  mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo,
574  mitk::ParameterFitImageGeneratorBase::Pointer& generator)
575 {
576  mitk::Image::Pointer mask3D = getMask3D();
577 
578  if (mask3D.IsNull())
579  {
580  return;
581  }
582 
583  mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator =
585 
586  typename TParameterizer::Pointer modelParameterizer =
587  TParameterizer::New();
588 
591  getAIF(aif, aifTimeGrid);
592 
593  modelParameterizer->SetAIF(aif);
594  modelParameterizer->SetAIFTimeGrid(aifTimeGrid);
595 
596  //Compute ROI signal
597  mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator =
599  signalGenerator->SetMask(mask3D);
600  signalGenerator->SetDynamicImage(image);
601  signalGenerator->Generate();
602 
603  mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean();
604 
605  //Specify fitting strategy and criterion parameters
606  mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer();
607  mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory);
608 
609  //Parametrize fit generator
610  fitGenerator->SetModelParameterizer(modelParameterizer);
611  fitGenerator->SetMask(mask3D);
612  fitGenerator->SetFitFunctor(fitFunctor);
613  fitGenerator->SetSignal(roiSignal);
614  fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image));
615 
616  generator = fitGenerator.GetPointer();
617 
618  std::string roiUID = mitk::EnsureModelFitUID(mask);
619 
620  //Create model info
621  modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer,
623  roiUID);
624 
626 
627  for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos =
628  roiSignal.begin(); pos != roiSignal.end(); ++pos)
629  {
630  infoSignal.push_back(*pos);
631  }
632 
633  modelFitInfo->inputData.SetTableValue("ROI", infoSignal);
634 
635  infoSignal.clear();
636 
637  for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos =
638  aif.begin(); pos != aif.end(); ++pos)
639  {
640  infoSignal.push_back(*pos);
641  }
642 
643  modelFitInfo->inputData.SetTableValue("AIF", infoSignal);
644 }
645 
646 
647 void storeResultImage(const std::string& name, mitk::Image* image, mitk::modelFit::Parameter::Type nodeType, const mitk::modelFit::ModelFitInfo* modelFitInfo)
648 {
649  mitk::modelFit::SetModelFitDataProperties(image, name, nodeType, modelFitInfo);
650 
651  std::string ext = ::itksys::SystemTools::GetFilenameLastExtension(outFileName);
652 
653  std::string dir = itksys::SystemTools::GetFilenamePath(outFileName);
654  dir = itksys::SystemTools::ConvertToOutputPath(dir);
655 
656  std::string rootName = itksys::SystemTools::GetFilenameWithoutLastExtension(outFileName);
657 
658  std::string fileName = rootName + "_" + name + ext;
659 
660  std::vector<std::string> pathElements;
661  pathElements.push_back(dir);
662  pathElements.push_back(fileName);
663 
664  std::string fullOutPath = itksys::SystemTools::ConvertToOutputPath(dir + "/" + fileName);
665 
666  mitk::IOUtil::Save(image, fullOutPath);
667 
668  std::cout << "Store result (parameter: "<<name<<"): " << fullOutPath << std::endl;
669 }
670 
671 
672 void createFitGenerator(mitk::modelFit::ModelFitInfo::Pointer& fitSession, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
673 {
674  bool isDescBrixFactory = modelName == MODEL_NAME_descriptive;
675  bool isToftsFactory = modelName == MODEL_NAME_tofts;
676  bool is2CXMFactory = modelName == MODEL_NAME_2CX;
677  bool is3SLFactory = modelName == MODEL_NAME_3SL;
678  bool is2SLFactory = modelName == MODEL_NAME_2SL;
679 
680  if (isDescBrixFactory)
681  {
682  std::cout << "Model: descriptive pharmacokinetic brix model" << std::endl;
683  if (!roibased)
684  {
685  generateDescriptiveBrixModel_PixelBased(fitSession, generator);
686  }
687  else
688  {
689  generateDescriptiveBrixModel_ROIBased(fitSession, generator);
690  }
691  }
692  else if (is3SLFactory)
693  {
694  std::cout << "Model: three step linear model" << std::endl;
695  if (!roibased)
696  {
697  GenerateLinearModelFit_PixelBased<mitk::ThreeStepLinearModelParameterizer, mitk::ThreeStepLinearModelFactory>(fitSession, generator);
698  }
699  else
700  {
701  GenerateLinearModelFit_ROIBased<mitk::ThreeStepLinearModelParameterizer, mitk::ThreeStepLinearModelFactory>(fitSession, generator);
702  }
703  }
704  else if (is2SLFactory)
705  {
706  std::cout << "Model: two step linear model" << std::endl;
707  if (!roibased)
708  {
709  GenerateLinearModelFit_PixelBased<mitk::TwoStepLinearModelParameterizer, mitk::TwoStepLinearModelFactory>(fitSession, generator);
710  }
711  else
712  {
713  GenerateLinearModelFit_ROIBased<mitk::TwoStepLinearModelParameterizer, mitk::TwoStepLinearModelFactory>(fitSession, generator);
714  }
715  }
716  else if (isToftsFactory)
717  {
718  std::cout << "Model: extended tofts model" << std::endl;
719  if (!roibased)
720  {
721  generateAIFbasedModelFit_PixelBased<mitk::ExtendedToftsModelParameterizer, mitk::ExtendedToftsModelFactory>(fitSession, generator);
722  }
723  else
724  {
725  generateAIFbasedModelFit_ROIBased<mitk::ExtendedToftsModelParameterizer, mitk::ExtendedToftsModelFactory>(fitSession, generator);
726  }
727  }
728  else if (is2CXMFactory)
729  {
730  std::cout << "Model: two compartment exchange model" << std::endl;
731  if (!roibased)
732  {
733  generateAIFbasedModelFit_PixelBased<mitk::TwoCompartmentExchangeModelParameterizer, mitk::TwoCompartmentExchangeModelFactory>(fitSession, generator);
734  }
735  else
736  {
737  generateAIFbasedModelFit_ROIBased<mitk::TwoCompartmentExchangeModelParameterizer, mitk::TwoCompartmentExchangeModelFactory>(fitSession, generator);
738  }
739  }
740  else
741  {
742  std::cerr << "ERROR. Model flag is unknown. Given flag: " << modelName << std::endl;
743  }
744 }
745 
746 void doFitting()
747 {
748  mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr;
749  mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr;
750 
751  ::itk::CStyleCommand::Pointer command = ::itk::CStyleCommand::New();
752  command->SetCallback(onFitEvent);
753 
754  createFitGenerator(fitSession, generator);
755 
756  if (generator.IsNotNull() )
757  {
758  std::cout << "Started fitting process..." << std::endl;
759  generator->AddObserver(::itk::AnyEvent(), command);
760  generator->Generate();
761  std::cout << std::endl << "Finished fitting process" << std::endl;
762 
763  mitk::storeModelFitGeneratorResults(outFileName, generator, fitSession);
764  }
765  else
766  {
767  mitkThrow() << "Fitting error! Could not initialize fitting job.";
768  }
769 }
770 
771 void doPreview()
772 {
773  mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr;
774  mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr;
775 
776  createFitGenerator(fitSession, generator);
777 
778  if (generator.IsNotNull())
779  {
781  }
782  else
783  {
784  mitkThrow() << "Fitting error! Could not initialize fitting job.";
785  }
786 }
787 
788 int main(int argc, char* argv[])
789 {
790  mitkCommandLineParser parser;
791  setupParser(parser);
792  const std::map<std::string, us::Any>& parsedArgs = parser.parseArguments(argc, argv);
793 
794  mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" });
795 
796  if (!configureApplicationSettings(parsedArgs))
797  {
798  return EXIT_FAILURE;
799  };
800 
801  // Show a help message
802  if (parsedArgs.count("help") || parsedArgs.count("h"))
803  {
804  std::cout << parser.helpText();
805  return EXIT_SUCCESS;
806  }
807 
809  try
810  {
811  image = mitk::IOUtil::Load<mitk::Image>(inFilename, &readerFilterFunctor);
812  std::cout << "Input: " << inFilename << std::endl;
813 
814  if (!maskFileName.empty())
815  {
816  mask = mitk::IOUtil::Load<mitk::Image>(maskFileName, &readerFilterFunctor);
817  std::cout << "Mask: " << maskFileName << std::endl;
818  }
819  else
820  {
821  std::cout << "Mask: none" << std::endl;
822  }
823 
825  {
826  if (!aifMaskFileName.empty())
827  {
828  aifMask = mitk::IOUtil::Load<mitk::Image>(aifMaskFileName, &readerFilterFunctor);
829  std::cout << "AIF mask: " << aifMaskFileName << std::endl;
830  }
831  else
832  {
833  mitkThrow() << "Error. Cannot fit. Choosen model needs an AIF. Please specify AIF mask (--aifmask).";
834  }
835  if (!aifImageFileName.empty())
836  {
837  aifImage = mitk::IOUtil::Load<mitk::Image>(aifImageFileName, &readerFilterFunctor);
838  std::cout << "AIF image: " << aifImageFileName << std::endl;
839  }
840  else
841  {
842  std::cout << "AIF image: none (using signal image)" << std::endl;
843  }
844  }
845 
846  if (roibased && mask.IsNull())
847  {
848  mitkThrow() << "Error. Cannot fit. Please specify mask if you select roi based fitting.";
849  }
850 
851  std::cout << "Style: ";
852  if (roibased)
853  {
854  std::cout << "ROI based";
855  }
856  else
857  {
858  std::cout << "pixel based";
859  }
860  std::cout << std::endl;
861 
862  if (preview)
863  {
864  doPreview();
865  }
866  else
867  {
868  doFitting();
869  }
870 
871  std::cout << "Processing finished." << std::endl;
872 
873  return EXIT_SUCCESS;
874  }
875  catch (const itk::ExceptionObject& e)
876  {
877  MITK_ERROR << e.what();
878  return EXIT_FAILURE;
879  }
880  catch (const std::exception& e)
881  {
882  MITK_ERROR << e.what();
883  return EXIT_FAILURE;
884  }
885  catch (...)
886  {
887  MITK_ERROR << "Unexpected error encountered.";
888  return EXIT_FAILURE;
889  }
890 }
const std::string MODEL_NAME_3SL
Option callback functor with a preference list/ black list option selection strategy.
int main(int argc, char *argv[])
const std::string MODEL_NAME_tofts
#define MITK_INFO
Definition: mitkLogMacros.h:18
#define MITK_ERROR
Definition: mitkLogMacros.h:20
void setupParser(mitkCommandLineParser &parser)
mitk::Image::Pointer image
void setContributor(std::string contributor)
std::string modelName
ValueType * any_cast(Any *operand)
Definition: usAny.h:377
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, mitkCommandLineParser::Channel channel=mitkCommandLineParser::Channel::None)
MITKMODELFIT_EXPORT void previewModelFitGeneratorResults(const std::string &outputPathTemplate, mitk::ParameterFitImageGeneratorBase *generator)
std::map< std::string, us::Any > parseArguments(const StringContainerType &arguments, bool *ok=nullptr)
virtual ModelBasePointer GenerateParameterizedModel(const IndexType &currentPosition) const =0
void onFitEvent(::itk::Object *caller, const itk::EventObject &event, void *)
mitk::Image::Pointer aifMask
bool configureApplicationSettings(std::map< std::string, us::Any > parsedArgs)
void generateAIFbasedModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer &modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer &generator)
MITKMODELFIT_EXPORT ModelFitInfo::Pointer CreateFitInfoFromModelParameterizer(const ModelParameterizerBase *usedParameterizer, mitk::BaseData *inputImage, const std::string &fitType, const std::string &fitName="", const NodeUIDType roiUID="")
void generateDescriptiveBrixModel_PixelBased(mitk::modelFit::ModelFitInfo::Pointer &modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer &generator)
void GenerateLinearModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer &modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer &generator)
virtual double GetProgress() const =0
void generateAIFbasedModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer &modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer &generator)
MITKMODELFIT_EXPORT ModelBase::TimeGridType ExtractTimeGrid(const Image *image)
static const std::string FIT_TYPE_VALUE_ROIBASED()
const std::string MODEL_NAME_descriptive
MITKMODELFIT_EXPORT void SetModelFitDataProperties(mitk::BaseData *data, const ModelBase::ParameterNameType &name, modelFit::Parameter::Type dataType, const modelFit::ModelFitInfo *fitInfo)
#define mitkThrow()
const std::string MODEL_NAME_2CX
Image class for storing images.
Definition: mitkImage.h:72
std::string aifImageFileName
Definition: usAny.h:163
NodeUIDType MITKMODELFIT_EXPORT EnsureModelFitUID(mitk::BaseData *data)
void generateDescriptiveBrixModel_ROIBased(mitk::modelFit::ModelFitInfo::Pointer &modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer &generator)
std::string inFilename
bool roibased(false)
std::string helpText() const
float brixInjectionTime(0)
itk::Array< double > AterialInputFunctionType
void setCategory(std::string category)
mitk::Image::Pointer aifImage
mitk::ModelFitFunctorBase::Pointer createDefaultFitFunctor(const mitk::ModelParameterizerBase *parameterizer, const mitk::ModelFactoryBase *modelFactory)
Data class that stores all information about a modelfit that is relevant to the visualization and sto...
void setArgumentPrefix(const std::string &longPrefix, const std::string &shortPrefix)
float aifHematocritLevel(0)
virtual ConstraintCheckerBase::Pointer CreateDefaultConstraints() const =0
bool useConstraints(false)
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
static void Save(const mitk::BaseData *data, const std::string &path, bool setPathProperty=false)
Save a mitk::BaseData instance.
Definition: mitkIOUtil.cpp:774
static const std::string FIT_TYPE_VALUE_PIXELBASED()
void createFitGenerator(mitk::modelFit::ModelFitInfo::Pointer &fitSession, mitk::ParameterFitImageGeneratorBase::Pointer &generator)
void getAIF(mitk::AIFBasedModelBase::AterialInputFunctionType &aif, mitk::AIFBasedModelBase::AterialInputFunctionType &aifTimeGrid)
std::string maskFileName
MITKMODELFIT_EXPORT void storeModelFitGeneratorResults(const std::string &outputPathTemplate, mitk::ParameterFitImageGeneratorBase *generator, const mitk::modelFit::ModelFitInfo *fitSession)
void GenerateLinearModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer &modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer &generator)
void doPreview()
const std::string MODEL_NAME_2SL
std::string aifMaskFileName
void doFitting()
bool preview(false)
void setTitle(std::string title)
mitk::Image::Pointer getMask3D()
void setDescription(std::string description)
mitk::Image::Pointer mask
std::string outFileName
void beginGroup(const std::string &description)
void storeResultImage(const std::string &name, mitk::Image *image, mitk::modelFit::Parameter::Type nodeType, const mitk::modelFit::ModelFitInfo *modelFitInfo)
static Pointer New()
bool verbose(false)