17 #include "itksys/SystemTools.hxx" 77 void onFitEvent(::itk::Object* caller,
const itk::EventObject & event,
void* )
79 itk::ProgressEvent progressEvent;
81 if (progressEvent.CheckEvent(&event))
84 std::cout <<castedReporter->
GetProgress()*100 <<
"% ";
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.");
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());
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.",
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);
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));
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.");
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));
140 "preview",
"p",
mitkCommandLineParser::Bool,
"Preview outputs",
"The application previews the outputs (filename, type) it would produce with the current settings.");
148 if (parsedArgs.size() == 0)
153 if (parsedArgs.count(
"model"))
161 if (parsedArgs.count(
"mask"))
166 if (parsedArgs.count(
"aifimage"))
171 if (parsedArgs.count(
"aifmask"))
177 if (parsedArgs.count(
"verbose"))
183 if (parsedArgs.count(
"preview"))
189 if (parsedArgs.count(
"roibased"))
195 if (parsedArgs.count(
"constraints"))
197 useConstraints =
us::any_cast<
bool>(parsedArgs[
"constraints"]);
201 if (parsedArgs.count(
"hematocrit"))
203 aifHematocritLevel =
us::any_cast<
float>(parsedArgs[
"hematocrit"]);
207 if (parsedArgs.count(
"injectiontime"))
209 brixInjectionTime =
us::any_cast<
float>(parsedArgs[
"injectiontime"]);
222 fitFunctor->RegisterEvaluationParameter(
"Chi^2", chi2);
231 ::itk::LevenbergMarquardtOptimizer::ScalesType scales;
232 scales.SetSize(refModel->GetNumberOfParameters());
234 fitFunctor->SetScales(scales);
236 fitFunctor->SetDebugParameterMaps(
true);
238 return fitFunctor.GetPointer();
247 if (mask.IsNotNull())
252 if (mask->GetTimeSteps() > 1)
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();
270 if (aifMask.IsNotNull())
275 mitk::AterialInputFunctionGenerator::Pointer aifGenerator =
285 if (aifMask->GetTimeSteps() > 1)
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();
295 aifGenerator->SetMask(aifMask);
299 if (aifImage.IsNotNull())
304 aifGenerator->SetDynamicImage(selectedAIFImage);
306 aif = aifGenerator->GetAterialInputFunction();
307 aifTimeGrid = aifGenerator->GetAterialInputFunctionTimeGrid();
311 mitkThrow() <<
"Cannot generate AIF. AIF mask was not specified or correctly loaded.";
317 modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
319 mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator =
332 imageTimeSelector->SetInput(image);
333 imageTimeSelector->SetTimeNr(0);
334 imageTimeSelector->UpdateLargestPossibleRegion();
336 mitk::DescriptivePharmacokineticBrixModelParameterizer::BaseImageType::Pointer baseImage;
339 modelParameterizer->SetBaseImage(baseImage);
346 fitGenerator->SetModelParameterizer(modelParameterizer);
347 std::string roiUID =
"";
349 if (mask3D.IsNotNull())
351 fitGenerator->SetMask(mask3D);
355 fitGenerator->SetDynamicImage(image);
356 fitGenerator->SetFitFunctor(fitFunctor);
358 generator = fitGenerator.GetPointer();
366 modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
375 mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator =
382 mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator =
384 signalGenerator->SetMask(mask3D);
385 signalGenerator->SetDynamicImage(image);
386 signalGenerator->Generate();
393 modelParameterizer->SetBaseValue(roiSignal[0]);
400 fitGenerator->SetModelParameterizer(modelParameterizer);
401 fitGenerator->SetMask(mask3D);
402 fitGenerator->SetFitFunctor(fitFunctor);
403 fitGenerator->SetSignal(roiSignal);
406 generator = fitGenerator.GetPointer();
415 for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos =
416 roiSignal.begin(); pos != roiSignal.end(); ++pos)
418 infoSignal.push_back(*pos);
421 modelFitInfo->inputData.SetTableValue(
"ROI", infoSignal);
426 modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
428 mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator =
441 fitGenerator->SetModelParameterizer(modelParameterizer);
442 std::string roiUID =
"";
444 if (mask3D.IsNotNull())
446 fitGenerator->SetMask(mask3D);
450 fitGenerator->SetDynamicImage(image);
451 fitGenerator->SetFitFunctor(fitFunctor);
453 generator = fitGenerator.GetPointer();
461 modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
470 mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator =
477 mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator =
479 signalGenerator->SetMask(mask3D);
480 signalGenerator->SetDynamicImage(image);
481 signalGenerator->Generate();
490 fitGenerator->SetModelParameterizer(modelParameterizer);
491 fitGenerator->SetMask(mask3D);
492 fitGenerator->SetFitFunctor(fitFunctor);
493 fitGenerator->SetSignal(roiSignal);
496 generator = fitGenerator.GetPointer();
505 for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos =
506 roiSignal.begin(); pos != roiSignal.end(); ++pos)
508 infoSignal.push_back(*pos);
511 modelFitInfo->inputData.SetTableValue(
"ROI", infoSignal);
514 template <
typename TParameterizer,
typename TFactory>
516 modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
518 mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator =
521 typename TParameterizer::Pointer modelParameterizer =
522 TParameterizer::New();
528 modelParameterizer->SetAIF(aif);
529 modelParameterizer->SetAIFTimeGrid(aifTimeGrid);
534 mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer();
538 fitGenerator->SetModelParameterizer(modelParameterizer);
539 std::string roiUID =
"";
541 if (mask3D.IsNotNull())
543 fitGenerator->SetMask(mask3D);
547 fitGenerator->SetDynamicImage(image);
548 fitGenerator->SetFitFunctor(fitFunctor);
550 generator = fitGenerator.GetPointer();
559 for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos =
560 aif.begin(); pos != aif.end(); ++pos)
562 infoSignal.push_back(*pos);
565 modelFitInfo->inputData.SetTableValue(
"AIF", infoSignal);
568 template <
typename TParameterizer,
typename TFactory>
570 mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo,
571 mitk::ParameterFitImageGeneratorBase::Pointer& generator)
580 mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator =
583 typename TParameterizer::Pointer modelParameterizer =
584 TParameterizer::New();
590 modelParameterizer->SetAIF(aif);
591 modelParameterizer->SetAIFTimeGrid(aifTimeGrid);
594 mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator =
596 signalGenerator->SetMask(mask3D);
597 signalGenerator->SetDynamicImage(image);
598 signalGenerator->Generate();
603 mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer();
607 fitGenerator->SetModelParameterizer(modelParameterizer);
608 fitGenerator->SetMask(mask3D);
609 fitGenerator->SetFitFunctor(fitFunctor);
610 fitGenerator->SetSignal(roiSignal);
613 generator = fitGenerator.GetPointer();
624 for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos =
625 roiSignal.begin(); pos != roiSignal.end(); ++pos)
627 infoSignal.push_back(*pos);
630 modelFitInfo->inputData.SetTableValue(
"ROI", infoSignal);
634 for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos =
635 aif.begin(); pos != aif.end(); ++pos)
637 infoSignal.push_back(*pos);
640 modelFitInfo->inputData.SetTableValue(
"AIF", infoSignal);
648 std::string ext = ::itksys::SystemTools::GetFilenameLastExtension(
outFileName);
650 std::string dir = itksys::SystemTools::GetFilenamePath(
outFileName);
651 dir = itksys::SystemTools::ConvertToOutputPath(dir);
653 std::string rootName = itksys::SystemTools::GetFilenameWithoutLastExtension(
outFileName);
655 std::string fileName = rootName +
"_" + name + ext;
657 std::vector<std::string> pathElements;
658 pathElements.push_back(dir);
659 pathElements.push_back(fileName);
661 std::string fullOutPath = itksys::SystemTools::ConvertToOutputPath(dir +
"/" + fileName);
665 std::cout <<
"Store result (parameter: "<<name<<
"): " << fullOutPath << std::endl;
669 void createFitGenerator(mitk::modelFit::ModelFitInfo::Pointer& fitSession, mitk::ParameterFitImageGeneratorBase::Pointer& generator)
676 if (isDescBrixFactory)
678 std::cout <<
"Model: descriptive pharmacokinetic brix model" << std::endl;
688 else if (is3SLFactory)
690 std::cout <<
"Model: three step linear model" << std::endl;
700 else if (isToftsFactory)
702 std::cout <<
"Model: extended tofts model" << std::endl;
705 generateAIFbasedModelFit_PixelBased<mitk::ExtendedToftsModelParameterizer, mitk::ExtendedToftsModelFactory>(fitSession, generator);
709 generateAIFbasedModelFit_ROIBased<mitk::ExtendedToftsModelParameterizer, mitk::ExtendedToftsModelFactory>(fitSession, generator);
712 else if (is2CXMFactory)
714 std::cout <<
"Model: two compartment exchange model" << std::endl;
717 generateAIFbasedModelFit_PixelBased<mitk::TwoCompartmentExchangeModelParameterizer, mitk::TwoCompartmentExchangeModelFactory>(fitSession, generator);
721 generateAIFbasedModelFit_ROIBased<mitk::TwoCompartmentExchangeModelParameterizer, mitk::TwoCompartmentExchangeModelFactory>(fitSession, generator);
726 std::cerr <<
"ERROR. Model flag is unknown. Given flag: " <<
modelName << std::endl;
732 mitk::ParameterFitImageGeneratorBase::Pointer generator =
nullptr;
733 mitk::modelFit::ModelFitInfo::Pointer fitSession =
nullptr;
735 ::itk::CStyleCommand::Pointer command = ::itk::CStyleCommand::New();
740 if (generator.IsNotNull() )
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;
751 mitkThrow() <<
"Fitting error! Could not initialize fitting job.";
757 mitk::ParameterFitImageGeneratorBase::Pointer generator =
nullptr;
758 mitk::modelFit::ModelFitInfo::Pointer fitSession =
nullptr;
762 if (generator.IsNotNull())
768 mitkThrow() <<
"Fitting error! Could not initialize fitting job.";
772 int main(
int argc,
char* argv[])
776 const std::map<std::string, us::Any>& parsedArgs = parser.
parseArguments(argc, argv);
786 if (parsedArgs.count(
"help") || parsedArgs.count(
"h"))
795 image = mitk::IOUtil::Load<mitk::Image>(
inFilename, &readerFilterFunctor);
796 std::cout <<
"Input: " << inFilename << std::endl;
800 mask = mitk::IOUtil::Load<mitk::Image>(
maskFileName, &readerFilterFunctor);
801 std::cout <<
"Mask: " << maskFileName << std::endl;
805 std::cout <<
"Mask: none" << std::endl;
812 aifMask = mitk::IOUtil::Load<mitk::Image>(
aifMaskFileName, &readerFilterFunctor);
813 std::cout <<
"AIF mask: " << aifMaskFileName << std::endl;
817 mitkThrow() <<
"Error. Cannot fit. Choosen model needs an AIF. Please specify AIF mask (--aifmask).";
821 aifImage = mitk::IOUtil::Load<mitk::Image>(
aifImageFileName, &readerFilterFunctor);
822 std::cout <<
"AIF image: " << aifImageFileName << std::endl;
826 std::cout <<
"AIF image: none (using signal image)" << std::endl;
832 mitkThrow() <<
"Error. Cannot fit. Please specify mask if you select roi based fitting.";
835 std::cout <<
"Style: ";
838 std::cout <<
"ROI based";
842 std::cout <<
"pixel based";
844 std::cout << std::endl;
855 std::cout <<
"Processing finished." << std::endl;
859 catch (
const itk::ExceptionObject& e)
864 catch (
const std::exception& e)
871 MITK_ERROR <<
"Unexpected error encountered.";
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
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)
ValueType * any_cast(Any *operand)
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 ¤tPosition) 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
std::vector< double > ValueType
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)
const std::string MODEL_NAME_2CX
Image class for storing images.
std::string aifImageFileName
NodeUIDType MITKMODELFIT_EXPORT EnsureModelFitUID(mitk::BaseData *data)
void generateDescriptiveBrixModel_ROIBased(mitk::modelFit::ModelFitInfo::Pointer &modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer &generator)
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.
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)
MITKMODELFIT_EXPORT void storeModelFitGeneratorResults(const std::string &outputPathTemplate, mitk::ParameterFitImageGeneratorBase *generator, const mitk::modelFit::ModelFitInfo *fitSession)
std::string aifMaskFileName
void setTitle(std::string title)
mitk::Image::Pointer getMask3D()
itk::Array< double > ResultType
void setDescription(std::string description)
mitk::Image::Pointer mask
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)