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