diff --git a/Modules/ModelFit/CMakeLists.txt b/Modules/ModelFit/CMakeLists.txt new file mode 100644 index 0000000000..6ddd33235a --- /dev/null +++ b/Modules/ModelFit/CMakeLists.txt @@ -0,0 +1,19 @@ +MITK_CREATE_MODULE(ModelFit + INCLUDE_DIRS + PUBLIC ${MITK_BINARY_DIR} + PRIVATE src/Common src/Functors src/Models src/TestingHelper + DEPENDS + PUBLIC MitkCore MitkSceneSerializationBase + PRIVATE MitkMultilabel + PACKAGE_DEPENDS + PUBLIC ITK|ITKOptimizers + PRIVATE Boost +) + +if(BUILD_TESTING) + ADD_SUBDIRECTORY(test) +endif(BUILD_TESTING) + +ADD_SUBDIRECTORY(autoload/IO) +ADD_SUBDIRECTORY(autoload/Models) +ADD_SUBDIRECTORY(cmdapps) diff --git a/Modules/ModelFit/autoload/IO/CMakeLists.txt b/Modules/ModelFit/autoload/IO/CMakeLists.txt new file mode 100644 index 0000000000..64fbc9b5f1 --- /dev/null +++ b/Modules/ModelFit/autoload/IO/CMakeLists.txt @@ -0,0 +1,6 @@ +MITK_CREATE_MODULE(ModelFitIOServices + DEPENDS + PUBLIC MitkModelFit + PRIVATE MitkCore + AUTOLOAD_WITH MitkCore +) diff --git a/Modules/ModelFit/autoload/IO/files.cmake b/Modules/ModelFit/autoload/IO/files.cmake new file mode 100644 index 0000000000..8452a05661 --- /dev/null +++ b/Modules/ModelFit/autoload/IO/files.cmake @@ -0,0 +1,12 @@ +set(CPP_FILES + mitkModelFitIOActivator.cpp +) + +set(H_FILES +) + +set(TPP_FILES +) + +set(MOC_H_FILES +) diff --git a/Modules/ModelFit/autoload/IO/mitkModelFitIOActivator.cpp b/Modules/ModelFit/autoload/IO/mitkModelFitIOActivator.cpp new file mode 100644 index 0000000000..404470f04d --- /dev/null +++ b/Modules/ModelFit/autoload/IO/mitkModelFitIOActivator.cpp @@ -0,0 +1,99 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include +#include + +#include +#include +#include +#include +#include + +namespace mitk +{ + +/* + * This is the module activator for the IO aspects of the "ModelFit" module. + */ +class ModelFitIOActivator : public us::ModuleActivator +{ +public: + void registerProperty(const std::string& name, const std::string& key, const std::string& description) + { + mitk::CoreServices::GetPropertyDescriptions()->AddDescription(name, description); + + mitk::PropertyPersistenceInfo::Pointer ppi = mitk::PropertyPersistenceInfo::New(); + ppi->SetNameAndKey(name, key); + + mitk::CoreServices::GetPropertyPersistence()->AddInfo(ppi, true); + } + + void registerProperty(const std::string& name, const std::string& key, const std::string& description, const PropertyPersistenceInfo::DeserializationFunctionType &deFnc, const PropertyPersistenceInfo::SerializationFunctionType &serFnc) + { + mitk::CoreServices::GetPropertyDescriptions()->AddDescription(name, description); + + mitk::PropertyPersistenceInfo::Pointer ppi = mitk::PropertyPersistenceInfo::New(); + ppi->SetNameAndKey(name, key); + ppi->SetDeserializationFunction(deFnc); + ppi->SetSerializationFunction(serFnc); + + mitk::CoreServices::GetPropertyPersistence()->AddInfo(ppi, true); + } + + void Load(us::ModuleContext* /*context*/) + { + //register relevant properties + registerProperty(mitk::ModelFitConstants::UID_PROPERTY_NAME(), "data_uid", "UID used to identify data in an MITK session."); + + registerProperty(mitk::ModelFitConstants::INPUT_VARIABLES_PROPERTY_NAME(), "modelfit_input_variables", "Array of input variables used in/for a model fit.", PropertyPersistenceDeserialization::deserializeXMLToScalarListLookupTableProperty, PropertyPersistenceSerialization::serializeScalarListLookupTablePropertyToXML); + + registerProperty(mitk::ModelFitConstants::PARAMETER_NAME_PROPERTY_NAME(), "modelfit_parameter_name", "Name of the parameter, that is represented by the data and how it is used in the function string (modelfit.model.function)."); + registerProperty(mitk::ModelFitConstants::PARAMETER_UNIT_PROPERTY_NAME(), "modelfit_parameter_unit", "Unit string of the Parameter. Is only used for display. Default value: \"\" (no unit)"); + registerProperty(mitk::ModelFitConstants::PARAMETER_SCALE_PROPERTY_NAME(), "modelfit_parameter_scale", "Scaling of the parameter. Default value: 1."); + registerProperty(mitk::ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME(), "modelfit_parameter_type", "Type of the parameters. Default value: parameter. Other options: derived, criterion, evaluation."); + + registerProperty(mitk::ModelFitConstants::MODEL_TYPE_PROPERTY_NAME(), "modelfit_model_type", "Value specifies the type of model (helpfull for classification; e.g. MR perfusion)"); + registerProperty(mitk::ModelFitConstants::MODEL_NAME_PROPERTY_NAME(), "modelfit_model_name", "Name of the specific fit. Only used for display."); + registerProperty(mitk::ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME(), "modelfit_model_function", "Functions string, that specifies the model and will be parsed, to plot the curves based on the parameter. Optional parameter that must not be set."); + registerProperty(mitk::ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME(), "modelfit_model_functionClass", "ID of the model class implementation."); + registerProperty(mitk::ModelFitConstants::MODEL_X_PROPERTY_NAME(), "modelfit_model_x", "Value identifies the model type."); + + registerProperty(mitk::ModelFitConstants::XAXIS_NAME_PROPERTY_NAME(), "modelfit_xaxis_name", "Value identifies the model type."); + registerProperty(mitk::ModelFitConstants::XAXIS_UNIT_PROPERTY_NAME(), "modelfit_xaxis_unit", "Value identifies the model type."); + + registerProperty(mitk::ModelFitConstants::YAXIS_NAME_PROPERTY_NAME(), "modelfit_yaxis_name", "Value identifies the model type."); + registerProperty(mitk::ModelFitConstants::YAXIS_UNIT_PROPERTY_NAME(), "modelfit_yaxis_unit", "Value identifies the model type."); + + registerProperty(mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME(), "modelfit_fit_uid", "Value identifies the model type."); + registerProperty(mitk::ModelFitConstants::FIT_TYPE_PROPERTY_NAME(), "modelfit_fit_type", "Value identifies the model type."); + registerProperty(mitk::ModelFitConstants::FIT_INPUT_IMAGEUID_PROPERTY_NAME(), "modelfit_fit_input_imageUID", "Value identifies the model type."); + registerProperty(mitk::ModelFitConstants::FIT_INPUT_ROIUID_PROPERTY_NAME(), "modelfit_fit_input_roiUID", "Value identifies the model type."); + registerProperty(mitk::ModelFitConstants::FIT_INPUT_DATA_PROPERTY_NAME(), "modelfit_fit_input_data", "Value identifies the model type."); + registerProperty(mitk::ModelFitConstants::FIT_STATIC_PARAMETERS_PROPERTY_NAME(), "modelfit_fit_staticParameters", "Value identifies the model type.", PropertyPersistenceDeserialization::deserializeXMLToScalarListLookupTableProperty, PropertyPersistenceSerialization::serializeScalarListLookupTablePropertyToXML); + } + + void Unload(us::ModuleContext* ) + { + } + +private: + +}; +} + +US_EXPORT_MODULE_ACTIVATOR(mitk::ModelFitIOActivator) diff --git a/Modules/ModelFit/autoload/Models/CMakeLists.txt b/Modules/ModelFit/autoload/Models/CMakeLists.txt new file mode 100644 index 0000000000..1f15532ba7 --- /dev/null +++ b/Modules/ModelFit/autoload/Models/CMakeLists.txt @@ -0,0 +1,6 @@ +MITK_CREATE_MODULE(ModelFitModelsServices + DEPENDS + PUBLIC MitkModelFit + PRIVATE MitkCore + AUTOLOAD_WITH MitkModelFit +) diff --git a/Modules/ModelFit/autoload/Models/files.cmake b/Modules/ModelFit/autoload/Models/files.cmake new file mode 100644 index 0000000000..911de0a41f --- /dev/null +++ b/Modules/ModelFit/autoload/Models/files.cmake @@ -0,0 +1,12 @@ +set(CPP_FILES + mitkModelFitModelsActivator.cpp +) + +set(H_FILES +) + +set(TPP_FILES +) + +set(MOC_H_FILES +) diff --git a/Modules/ModelFit/autoload/Models/mitkModelFitModelsActivator.cpp b/Modules/ModelFit/autoload/Models/mitkModelFitModelsActivator.cpp new file mode 100644 index 0000000000..6d7895d695 --- /dev/null +++ b/Modules/ModelFit/autoload/Models/mitkModelFitModelsActivator.cpp @@ -0,0 +1,64 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include +#include + +#include + +//general models +#include "mitkGenericParamModelFactory.h" +#include "mitkLinearModelFactory.h" +#include "mitkT2DecayModelFactory.h" + +namespace mitk +{ + +/* + * This is the module activator for the IO aspects of the "ModelFit" module. + */ +class ModelFitModelsActivator : public us::ModuleActivator +{ +public: + + template void RegisterProvider(us::ModuleContext* context) + { + auto provider = new TProvider(); + provider->RegisterService(context); + + m_RegisteredProviders.push_back(std::unique_ptr(provider)); + } + + virtual void Load(us::ModuleContext* context) override + { + m_RegisteredProviders.clear(); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + } + + virtual void Unload(us::ModuleContext* ) override + { + } + +private: + std::vector > m_RegisteredProviders; +}; + +} + +US_EXPORT_MODULE_ACTIVATOR(mitk::ModelFitModelsActivator) diff --git a/Modules/ModelFit/cmdapps/CMakeLists.txt b/Modules/ModelFit/cmdapps/CMakeLists.txt new file mode 100644 index 0000000000..f78ad56dda --- /dev/null +++ b/Modules/ModelFit/cmdapps/CMakeLists.txt @@ -0,0 +1,34 @@ +option(BUILD_ModelFitMiniApps "Build commandline tools for the ModelFit module" OFF) + +if(BUILD_ModelFitMiniApps OR MITK_BUILD_ALL_APPS) + + # needed include directories + include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ) + # list of miniapps + # if an app requires additional dependencies + # they are added after a "^^" and separated by "_" + set( miniapps + GenericFittingMiniApp^^ + PixelDumpMiniApp^^ + ) + + foreach(miniapp ${miniapps}) + # extract mini app name and dependencies + string(REPLACE "^^" "\\;" miniapp_info ${miniapp}) + set(miniapp_info_list ${miniapp_info}) + list(GET miniapp_info_list 0 appname) + list(GET miniapp_info_list 1 raw_dependencies) + string(REPLACE "_" "\\;" dependencies "${raw_dependencies}") + set(dependencies_list ${dependencies}) + + mitkFunctionCreateCommandLineApp( + NAME ${appname} + DEPENDS MitkCore MitkModelFit ${dependencies_list} + PACKAGE_DEPENDS ITK + ) + endforeach() + +endif(BUILD_ModelFitMiniApps OR MITK_BUILD_ALL_APPS) diff --git a/Modules/ModelFit/cmdapps/GenericFittingMiniApp.cpp b/Modules/ModelFit/cmdapps/GenericFittingMiniApp.cpp new file mode 100644 index 0000000000..108e770c63 --- /dev/null +++ b/Modules/ModelFit/cmdapps/GenericFittingMiniApp.cpp @@ -0,0 +1,364 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// std includes +#include + +// itk includes +#include "itksys/SystemTools.hxx" + +// CTK includes +#include "mitkCommandLineParser.h" + +// MITK includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +std::string inFilename; +std::string outFileName; +std::string maskFileName; +bool verbose(false); +bool roibased(false); +std::string functionName; +std::string formular; +mitk::Image::Pointer image; +mitk::Image::Pointer mask; + + +void onFitEvent(::itk::Object* caller, const itk::EventObject & event, void* /*data*/) +{ + itk::ProgressEvent progressEvent; + + if (progressEvent.CheckEvent(&event)) + { + mitk::ParameterFitImageGeneratorBase* castedReporter = dynamic_cast(caller); + std::cout <GetProgress()*100 << "% "; + } +} + + +void setupParser(mitkCommandLineParser& parser) +{ + // set general information about your MiniApp + parser.setCategory("Dynamic Data Analysis Tools"); + parser.setTitle("Generic Fitting"); + parser.setDescription("MiniApp that allows to make a pixel based fitting on the intensity signal over time for a given model function."); + parser.setContributor("DKFZ MIC"); + //! [create parser] + + //! [add arguments] + // how should arguments be prefixed + parser.setArgumentPrefix("--", "-"); + // add each argument, unless specified otherwise each argument is optional + // see mitkCommandLineParser::addArgument for more information + parser.beginGroup("Model parameters"); + parser.addArgument( + "function", "f", mitkCommandLineParser::String, "Model function", "Function that should be used to fit the intensity signals. Options are: \"Linear\" or \"\" (for generic formulas).", us::Any(std::string("Linear"))); + parser.addArgument( + "formular", "y", mitkCommandLineParser::String, "Generic model function formular", "Formular of a generic model (if selected) that will be parsed and fitted.", us::Any()); + parser.endGroup(); + parser.beginGroup("Required I/O parameters"); + parser.addArgument( + "input", "i", mitkCommandLineParser::InputFile, "Input file", "input 3D+t image file", us::Any(), false); + parser.addArgument("output", + "o", + mitkCommandLineParser::OutputFile, + "Output file template", + "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.", + us::Any(), + false); + parser.endGroup(); + + parser.beginGroup("Optional parameters"); + parser.addArgument( + "mask", "m", mitkCommandLineParser::InputFile, "Mask file", "Mask that defines the spatial image region that should be fitted. Must have the same geometry as the input image!", us::Any()); + parser.addArgument( + "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output"); + parser.addArgument( + "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."); + parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); + parser.endGroup(); + //! [add arguments] +} + +bool configureApplicationSettings(std::map parsedArgs) +{ + if (parsedArgs.size() == 0) + return false; + + // parse, cast and set required arguments + functionName = "Linear"; + if (parsedArgs.count("function")) + { + functionName = us::any_cast(parsedArgs["function"]); + } + if (parsedArgs.count("formular")) + { + formular = us::any_cast(parsedArgs["formular"]); + } + inFilename = us::any_cast(parsedArgs["input"]); + outFileName = us::any_cast(parsedArgs["output"]); + + + verbose = false; + if (parsedArgs.count("verbose")) + { + verbose = us::any_cast(parsedArgs["verbose"]); + } + + roibased = false; + if (parsedArgs.count("roibased")) + { + roibased = us::any_cast(parsedArgs["roibased"]); + } + + if (parsedArgs.count("mask")) + { + maskFileName = us::any_cast(parsedArgs["mask"]); + } + + return true; +} + +void configureInitialParametersOfParameterizer(mitk::ModelParameterizerBase* + parameterizer) +{ + mitk::GenericParamModelParameterizer* genericParameterizer = + dynamic_cast(parameterizer); + + if (genericParameterizer) + { + genericParameterizer->SetFunctionString(formular); + } +} + +mitk::ModelFitFunctorBase::Pointer createDefaultFitFunctor( + const mitk::ModelParameterizerBase* parameterizer) +{ + mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor = + mitk::LevenbergMarquardtModelFitFunctor::New(); + + mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::Pointer chi2 = + mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::New(); + fitFunctor->RegisterEvaluationParameter("Chi^2", chi2); + + mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel(); + + ::itk::LevenbergMarquardtOptimizer::ScalesType scales; + scales.SetSize(refModel->GetNumberOfParameters()); + scales.Fill(1.0); + fitFunctor->SetScales(scales); + + fitFunctor->SetDebugParameterMaps(true); + + return fitFunctor.GetPointer(); +} + +template +void generateModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& + /*modelFitInfo*/, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + configureInitialParametersOfParameterizer(modelParameterizer); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + + fitGenerator->SetMask(mask); + + fitGenerator->SetDynamicImage(image); + fitGenerator->SetFitFunctor(fitFunctor); + + generator = fitGenerator.GetPointer(); +} + +template +void generateModelFit_ROIBased( + mitk::modelFit::ModelFitInfo::Pointer& /*modelFitInfo*/, + mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::ROIBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + configureInitialParametersOfParameterizer(modelParameterizer); + + //Compute ROI signal + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = + mitk::MaskedDynamicImageStatisticsGenerator::New(); + signalGenerator->SetMask(mask); + signalGenerator->SetDynamicImage(image); + signalGenerator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + fitGenerator->SetMask(mask); + fitGenerator->SetFitFunctor(fitFunctor); + fitGenerator->SetSignal(roiSignal); + fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image)); + + generator = fitGenerator.GetPointer(); +} + +void doFitting() +{ + mitk::ParameterFitImageGeneratorBase::Pointer generator = NULL; + mitk::modelFit::ModelFitInfo::Pointer fitSession = NULL; + + ::itk::CStyleCommand::Pointer command = ::itk::CStyleCommand::New(); + command->SetCallback(onFitEvent); + + bool isLinearFactory = functionName == "Linear"; + + if (isLinearFactory) + { + std::cout << "Model: linear" << std::endl; + if (!roibased) + { + generateModelFit_PixelBased(fitSession, generator); + } + else + { + generateModelFit_ROIBased(fitSession, generator); + } + } + else + { + std::cout << "Model: generic (2 parameter)" << std::endl; + if (!roibased) + { + generateModelFit_PixelBased(fitSession, generator); + } + else + { + generateModelFit_ROIBased(fitSession, generator); + } + } + + if (generator.IsNotNull() ) + { + std::cout << "Started fitting process..." << std::endl; + generator->AddObserver(::itk::AnyEvent(), command); + generator->Generate(); + std::cout << std::endl << "Finished fitting process" << std::endl; + + mitk::storeModelFitGeneratorResults(outFileName, generator, fitSession); + } + else + { + mitkThrow() << "Fitting error! Could not initalize fitting job."; + } +} + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + setupParser(parser); + + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + + const std::map& parsedArgs = parser.parseArguments(argc, argv); + if (!configureApplicationSettings(parsedArgs)) + { + return EXIT_FAILURE; + }; + + // Show a help message + if (parsedArgs.count("help") || parsedArgs.count("h")) + { + std::cout << parser.helpText(); + return EXIT_SUCCESS; + } + + //! [do processing] + try + { + image = mitk::IOUtil::Load(inFilename, &readerFilterFunctor); + std::cout << "Input: " << inFilename << std::endl; + + if (!maskFileName.empty()) + { + mask = mitk::IOUtil::Load(maskFileName, &readerFilterFunctor); + std::cout << "Mask: " << maskFileName << std::endl; + } + else + { + std::cout << "Mask: none" << std::endl; + } + + if (roibased && mask.IsNull()) + { + mitkThrow() << "Error. Cannot fit. Please specify mask if you select roi based fitting."; + } + + std::cout << "Style: "; + if (roibased) + { + std::cout << "ROI based"; + } + else + { + std::cout << "pixel based"; + } + std::cout << std::endl; + + doFitting(); + + std::cout << "Processing finished." << std::endl; + + return EXIT_SUCCESS; + } + catch (itk::ExceptionObject e) + { + MITK_ERROR << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + MITK_ERROR << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + MITK_ERROR << "Unexpected error encountered."; + return EXIT_FAILURE; + } +} diff --git a/Modules/ModelFit/cmdapps/PixelDumpMiniApp.cpp b/Modules/ModelFit/cmdapps/PixelDumpMiniApp.cpp new file mode 100644 index 0000000000..0a0a212176 --- /dev/null +++ b/Modules/ModelFit/cmdapps/PixelDumpMiniApp.cpp @@ -0,0 +1,451 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// std includes +#include + +// itk includes +#include "itksys/SystemTools.hxx" +#include "itkImageRegionConstIteratorWithIndex.h" +#include "itkCastImageFilter.h" +#include "itkExtractImageFilter.h" + +// CTK includes +#include "mitkCommandLineParser.h" + +// MITK includes +#include +#include + +#include +#include "mitkImageAccessByItk.h" +#include "mitkImageCast.h" + +mitkCommandLineParser::StringContainerType inFilenames; +std::string outFileName; +std::string maskFileName; +mitkCommandLineParser::StringContainerType captions; + +using ImageVectorType = std::vector; +ImageVectorType images; + +mitk::Image::Pointer mask; + +bool verbose(false); + +typedef itk::Image InternalImageType; +typedef std::map InternalImageMapType; +InternalImageMapType internalImages; + +itk::ImageRegion<3> relevantRegion; +InternalImageType::PointType relevantOrigin; +InternalImageType::SpacingType relevantSpacing; +InternalImageType::DirectionType relevantDirection; + +typedef itk::Index<3> DumpIndexType; +typedef std::vector DumpedValuesType; + +struct DumpIndexCompare +{ + bool operator() (const DumpIndexType& lhs, const DumpIndexType& rhs) + { + if (lhs[0] < rhs[0]) + { + return true; + } + else if (lhs[0] > rhs[0]) + { + return false; + } + + if (lhs[1] < rhs[1]) + { + return true; + } + else if (lhs[1] > rhs[1]) + { + return false; + } + + return lhs[2] < rhs[2]; + } +}; + +typedef std::map DumpPixelMapType; +DumpPixelMapType dumpedPixels; + +void setupParser(mitkCommandLineParser& parser) +{ + // set general information about your MiniApp + parser.setCategory("Generic Analysis Tools"); + parser.setTitle("Pixel Dumper"); + parser.setDescription("MiniApp that allows to dump the pixel values of all passed files into a csv. The region of dumping can defined by a mask. All images (and mask) must have the same geometrie."); + parser.setContributor("DKFZ MIC"); + //! [create parser] + + //! [add arguments] + // how should arguments be prefixed + parser.setArgumentPrefix("--", "-"); + // add each argument, unless specified otherwise each argument is optional + // see mitkCommandLineParser::addArgument for more information + parser.beginGroup("Required I/O parameters"); + parser.addArgument( + "inputs", "i", mitkCommandLineParser::StringList, "Input files", "list of the images that should be dumped.", us::Any(), false); + parser.addArgument("output", + "o", + mitkCommandLineParser::OutputFile, + "Output file", + "where to save the csv.", + us::Any(), + false); + parser.endGroup(); + + parser.beginGroup("Optional parameters"); + parser.addArgument( + "mask", "m", mitkCommandLineParser::InputFile, "Mask file", "Mask that defines the spatial image region that should be dumped. Must have the same geometry as the input images!", us::Any()); + parser.addArgument( + "captions", "c", mitkCommandLineParser::StringList, "Captions of image columns", "If provided the pixel columns of the csv will be named according to the passed values instead of using the image pathes. Number of images and names must be equal.", us::Any(), false); + parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); + parser.endGroup(); + //! [add arguments] +} + +bool configureApplicationSettings(std::map parsedArgs) +{ + if (parsedArgs.size() == 0) + return false; + + // parse, cast and set required arguments + + inFilenames = us::any_cast(parsedArgs["inputs"]); + outFileName = us::any_cast(parsedArgs["output"]); + + if (parsedArgs.count("mask")) + { + maskFileName = us::any_cast(parsedArgs["mask"]); + } + + captions = inFilenames; + + if (parsedArgs.count("captions")) + { + captions = us::any_cast(parsedArgs["captions"]); + } + + return true; +} + +template < typename TPixel, unsigned int VImageDimension > +void ExtractRelevantInformation( + const itk::Image< TPixel, VImageDimension > *image) +{ + relevantRegion = image->GetLargestPossibleRegion(); + relevantOrigin = image->GetOrigin(); + relevantSpacing = image->GetSpacing(); + relevantDirection = image->GetDirection(); +} + +template < typename TPixel, unsigned int VImageDimension > +void DoInternalImageConversion( + const itk::Image< TPixel, VImageDimension > *image, + InternalImageType::Pointer& internalImage) +{ + typedef itk::Image< TPixel, VImageDimension > ImageType; + + //check if image fit to geometry + + // Make sure that spacing are the same + typename ImageType::SpacingType imageSpacing = image->GetSpacing(); + typename ImageType::PointType zeroPoint; zeroPoint.Fill(0.0); + if ((zeroPoint + imageSpacing).SquaredEuclideanDistanceTo((zeroPoint + relevantSpacing)) > + 1e-6) // for the dumper we are not as strict as mitk normally would be (mitk::eps) + { + mitkThrow() << "Images need to have same spacing! (Image spacing: " << imageSpacing + << "; relevant spacing: " << relevantSpacing << ")"; + } + + // Make sure that orientation of mask and image are the same + typename ImageType::DirectionType imageDirection = image->GetDirection(); + for (unsigned int i = 0; i < imageDirection.RowDimensions; ++i) + { + for (unsigned int j = 0; j < imageDirection.ColumnDimensions; ++j) + { + double differenceDirection = imageDirection[i][j] - relevantDirection[i][j]; + if (fabs(differenceDirection) > 1e-6) // SD: 1e6 wird hier zum zweiten mal als Magic Number benutzt -> Konstante + { + // for the dumper we are not as strict as mitk normally would be (mitk::eps) + mitkThrow() << "Images need to have same direction! (Image direction: " + << imageDirection << "; relevant direction: " << relevantDirection << ")"; + } + } + } + + // Make sure that origin of mask and image are the same + typename ImageType::PointType imageOrigin = image->GetOrigin(); + if (imageOrigin.SquaredEuclideanDistanceTo(relevantOrigin) > 1e-6) + { + // for the dumper we are not as strict as mitk normally would be (mitk::eps) + mitkThrow() << "Image need to have same spacing! (Image spacing: " + << imageSpacing << "; relevant spacing: " << relevantOrigin << ")"; + } + + typename ImageType::RegionType imageRegion = image->GetLargestPossibleRegion(); + + if (!imageRegion.IsInside(relevantRegion) && imageRegion != relevantRegion) + { + mitkThrow() << "Images need to have same region! (Image region: " + << imageRegion << "; relevant region: " << relevantRegion << ")"; + } + + //convert to internal image + typedef itk::ExtractImageFilter ExtractFilterType; + typename ExtractFilterType::Pointer extractFilter = ExtractFilterType::New(); + typedef itk::CastImageFilter CastFilterType; + typename CastFilterType::Pointer castFilter = CastFilterType::New(); + + extractFilter->SetInput(image); + extractFilter->SetExtractionRegion(relevantRegion); + castFilter->SetInput(extractFilter->GetOutput()); + castFilter->Update(); + internalImage = castFilter->GetOutput(); +} + +template < typename TPixel, unsigned int VImageDimension > +void DoMaskedCollecting( + const itk::Image< TPixel, VImageDimension > *image) +{ + typedef itk::Image< TPixel, VImageDimension > ImageType; + + itk::ImageRegionConstIteratorWithIndex it(image, relevantRegion); + + it.GoToBegin(); + + while (!it.IsAtEnd()) + { + if (mask.IsNull() || it.Get() > 0) + { + DumpedValuesType values; + + const auto index = it.GetIndex(); + + for (auto& imagePos : internalImages) + { + double value = imagePos.second->GetPixel(index); + values.push_back(value); + } + + dumpedPixels.insert(std::make_pair(index, values)); + } + ++it; + } +} + +InternalImageMapType ConvertImageTimeSteps(mitk::Image* image) +{ + InternalImageMapType map; + + InternalImageType::Pointer internalImage; + + for (unsigned int i = 0; i < image->GetTimeSteps(); ++i) + { + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(image); + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer imageTimePoint = imageTimeSelector->GetOutput(); + + AccessFixedDimensionByItk_1(imageTimePoint, + DoInternalImageConversion, + 3, + internalImage); + + std::stringstream stream; + stream << "[" << i << "]"; + map.insert(std::make_pair(stream.str(), internalImage)); + } + + return map; +} + +void doDumping() +{ + if (mask.IsNotNull() && mask->GetTimeSteps() > 1) + { + std::cout << + "Pixel Dumper: Selected mask has multiple timesteps. Only use first timestep to mask the pixel dumping." << std::endl; + + mitk::ImageTimeSelector::Pointer maskTimeSelector = mitk::ImageTimeSelector::New(); + maskTimeSelector->SetInput(mask); + maskTimeSelector->SetTimeNr(0); + maskTimeSelector->UpdateLargestPossibleRegion(); + mask = maskTimeSelector->GetOutput(); + } + + try + { + if (mask.IsNotNull()) + { // if mask exist, we use the mask because it could be a sub region. + AccessFixedDimensionByItk(mask, ExtractRelevantInformation, 3); + } + else + { + AccessFixedDimensionByItk(images.front(), ExtractRelevantInformation, 3); + } + } + catch (const std::exception& e) + { + std::cerr << "Error extracting image geometry. Error text: " << e.what(); + throw; + } + + + for (unsigned int index = 0; index < images.size(); ++index) + { + try + { + InternalImageMapType conversionMap = ConvertImageTimeSteps(images[index]); + + if (conversionMap.size() == 1) + { + internalImages.insert(std::make_pair(captions[index], conversionMap.begin()->second)); + } + else if (conversionMap.size() > 1) + { + for (auto& pos : conversionMap) + { + std::stringstream namestream; + namestream << captions[index] << " " << pos.first; + internalImages.insert(std::make_pair(namestream.str(), pos.second)); + } + } + } + catch (const std::exception& e) + { + std::stringstream errorStr; + errorStr << "Inconsistent image \"" << captions[index] << "\" will be excluded from the collection. Error: " << e.what(); + std::cerr << errorStr.str() << std::endl; + } + + } + + if (mask.IsNotNull()) + { // if mask exist, we use the mask because it could be a sub region. + AccessFixedDimensionByItk(mask, DoMaskedCollecting, 3); + } + else + { + AccessFixedDimensionByItk(images.front(), DoMaskedCollecting, 3); + } + +} + +void storeCSV() +{ + std::ofstream resultfile; + resultfile.open(outFileName.c_str()); + resultfile << "x,y,z"; + for (auto aImage : internalImages) + { + resultfile << "," << aImage.first; + } + + resultfile << std::endl; + + for (auto dumpPos : dumpedPixels) + { + resultfile << dumpPos.first[0] << "," << dumpPos.first[1] << "," << dumpPos.first[2]; + + for(auto d : dumpPos.second) + { + resultfile << "," << d; + } + + resultfile << std::endl; + } +} + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + setupParser(parser); + const std::map& parsedArgs = parser.parseArguments(argc, argv); + + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + + if (!configureApplicationSettings(parsedArgs)) + { + return EXIT_FAILURE; + }; + + // Show a help message + if (parsedArgs.count("help") || parsedArgs.count("h")) + { + std::cout << parser.helpText(); + return EXIT_SUCCESS; + } + + if (!captions.empty() && inFilenames.size() != captions.size()) + { + std::cerr << "Cannot dump images. Number of given captions does not equal number of given images."; + return EXIT_FAILURE; + }; + + //! [do processing] + try + { + std::cout << "Load images:" << std::endl; + for (auto path : inFilenames) + { + std::cout << "Input: " << path << std::endl; + auto image = mitk::IOUtil::Load(path, &readerFilterFunctor); + images.push_back(image); + + } + + if (!maskFileName.empty()) + { + mask = mitk::IOUtil::Load(maskFileName, &readerFilterFunctor); + std::cout << "Mask: " << maskFileName << std::endl; + } + else + { + std::cout << "Mask: none" << std::endl; + } + + doDumping(); + storeCSV(); + + std::cout << "Processing finished." << std::endl; + + return EXIT_SUCCESS; + } + catch (itk::ExceptionObject e) + { + MITK_ERROR << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + MITK_ERROR << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + MITK_ERROR << "Unexpected error encountered."; + return EXIT_FAILURE; + } +} diff --git a/Modules/ModelFit/files.cmake b/Modules/ModelFit/files.cmake new file mode 100644 index 0000000000..4db6c02121 --- /dev/null +++ b/Modules/ModelFit/files.cmake @@ -0,0 +1,75 @@ +file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") + +set(CPP_FILES + Common/mitkExtractTimeGrid.cpp + Common/mitkTimeGridHelper.cpp + Common/mitkMaskedDynamicImageStatisticsGenerator.cpp + Common/mitkModelFitConstants.cpp + Common/mitkModelFitParameter.cpp + Common/mitkModelFitCmdAppsHelper.cpp + Common/mitkParameterFitImageGeneratorBase.cpp + Common/mitkPixelBasedParameterFitImageGenerator.cpp + Common/mitkROIBasedParameterFitImageGenerator.cpp + Common/mitkModelFitInfo.cpp + Common/mitkModelFitStaticParameterMap.cpp + Common/mitkModelGenerator.cpp + Common/mitkModelFitUIDHelper.cpp + Common/mitkModelFitResultHelper.cpp + Common/mitkScalarListLookupTable.cpp + Common/mitkScalarListLookupTableProperty.cpp + Common/mitkScalarListLookupTablePropertySerializer.cpp + Common/mitkIModelFitProvider.cpp + Common/mitkModelFitParameterValueExtraction.cpp + Common/mitkBinaryImageToLabelSetImageFilter.cpp + Common/mitkFormulaParser.cpp + Common/mitkFresnel.cpp + Functors/mitkSimpleFunctorBase.cpp + Functors/mitkSimpleFunctorPolicy.cpp + Functors/mitkChiSquareFitCostFunction.cpp + Functors/mitkReducedChiSquareFitCostFunction.cpp + Functors/mitkConstraintCheckerBase.cpp + Functors/mitkSimpleBarrierConstraintChecker.cpp + Functors/mitkSquaredDifferencesFitCostFunction.cpp + Functors/mitkSumOfSquaredDifferencesFitCostFunction.cpp + Functors/mitkMVConstrainedCostFunctionDecorator.cpp + Functors/mitkMVModelFitCostFunction.cpp + Functors/mitkNormalizedSumOfSquaredDifferencesFitCostFunction.cpp + Functors/mitkSVModelFitCostFunction.cpp + Functors/mitkModelFitFunctorBase.cpp + Functors/mitkLevenbergMarquardtModelFitFunctor.cpp + Functors/mitkDummyModelFitFunctor.cpp + Functors/mitkModelFitInfoSignalGenerationFunctor.cpp + Functors/mitkIndexedValueFunctorPolicy.cpp + Functors/mitkModelDataGenerationFunctor.cpp + Models/mitkModelBase.cpp + Models/mitkModelFactoryBase.cpp + Models/mitkModelParameterizerBase.cpp + Models/mitkLinearModel.cpp + Models/mitkLinearModelFactory.cpp + Models/mitkInitialParameterizationDelegateBase.cpp + Models/mitkImageBasedParameterizationDelegate.cpp + Models/mitkGenericParamModel.cpp + Models/mitkGenericParamModelFactory.cpp + Models/mitkGenericParamModelParameterizer.cpp + Models/mitkValueBasedParameterizationDelegate.cpp + Models/mitkT2DecayModel.cpp + Models/mitkT2DecayModelFactory.cpp + Models/mitkT2DecayModelParameterizer.cpp + TestingHelper/mitkTestArtifactGenerator.cpp + TestingHelper/mitkTestModel.cpp + TestingHelper/mitkTestModelFactory.cpp +) + +set(TPP_FILES + include/itkMultiOutputNaryFunctorImageFilter.tpp + include/itkMaskedStatisticsImageFilter.hxx + include/itkMaskedNaryStatisticsImageFilter.hxx + include/mitkModelFitProviderBase.tpp +) + +set(HXX_FILES +) + + +set(MOC_H_FILES +) diff --git a/Modules/ModelFit/include/itkMaskedNaryStatisticsImageFilter.h b/Modules/ModelFit/include/itkMaskedNaryStatisticsImageFilter.h new file mode 100644 index 0000000000..48ac3874bd --- /dev/null +++ b/Modules/ModelFit/include/itkMaskedNaryStatisticsImageFilter.h @@ -0,0 +1,114 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __itkMaskedNaryStatisticsImageFilter_h +#define __itkMaskedNaryStatisticsImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkImageIterator.h" +#include "itkArray.h" + +namespace itk +{ +/** \class MaskedNaryStatisticsImageFilter + * \brief Computes a masked statistic on N images and produces vectors of those statistic results. + * + * All the input images must be of the same type. + * + * \ingroup IntensityImageFilters + * \ingroup ITKImageIntensity + */ + +template< class TInputImage, class TMaskImage = ::itk::Image > +class ITK_EXPORT MaskedNaryStatisticsImageFilter: + public ImageToImageFilter< TInputImage, TInputImage > + +{ +public: + /** Standard class typedefs. */ + typedef MaskedNaryStatisticsImageFilter Self; + typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(MaskedNaryStatisticsImageFilter, ImageToImageFilter); + + /** Some typedefs. */ + typedef TInputImage InputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename NumericTraits< InputImagePixelType >::RealType RealType; + + typedef std::vector PixelVectorType; + typedef std::vector RealVectorType; + + typedef TMaskImage MaskImageType; + typedef typename MaskImageType::Pointer MaskImagePointer; + typedef typename MaskImageType::ConstPointer MaskImageConstPointer; + typedef typename MaskImageType::RegionType MaskImageRegionType; + + itkSetConstObjectMacro(Mask, MaskImageType); + itkGetConstObjectMacro(Mask, MaskImageType); + + itkGetConstReferenceMacro(Mean,RealVectorType); + itkGetConstReferenceMacro(Sigma,RealVectorType); + itkGetConstReferenceMacro(Variance,RealVectorType); + itkGetConstReferenceMacro(Sum,RealVectorType); + itkGetConstReferenceMacro(Minimum,PixelVectorType); + itkGetConstReferenceMacro(Maximum,PixelVectorType); + + /** ImageDimension constants */ + itkStaticConstMacro( + InputImageDimension, unsigned int, TInputImage::ImageDimension); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro( SameDimensionCheck, + ( Concept::SameDimension< InputImageDimension, InputImageDimension > ) ); + itkConceptMacro( OutputHasZeroCheck, + ( Concept::HasZero< InputImagePixelType > ) ); + /** End concept checking */ +#endif +protected: + MaskedNaryStatisticsImageFilter(); + virtual ~MaskedNaryStatisticsImageFilter() {} + + void GenerateData(); + +private: + MaskedNaryStatisticsImageFilter(const Self &); //purposely not implemented + void operator=(const Self &); //purposely not implemented + + RealVectorType m_Mean; + RealVectorType m_Sigma; + RealVectorType m_Variance; + RealVectorType m_Sum; + PixelVectorType m_Minimum; + PixelVectorType m_Maximum; + + MaskImageConstPointer m_Mask; +}; +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkMaskedNaryStatisticsImageFilter.hxx" +#endif + +#endif diff --git a/Modules/ModelFit/include/itkMaskedNaryStatisticsImageFilter.hxx b/Modules/ModelFit/include/itkMaskedNaryStatisticsImageFilter.hxx new file mode 100644 index 0000000000..eb7612a93e --- /dev/null +++ b/Modules/ModelFit/include/itkMaskedNaryStatisticsImageFilter.hxx @@ -0,0 +1,86 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __itkMaskedNaryStatisticsImageFilter_hxx +#define __itkMaskedNaryStatisticsImageFilter_hxx + +#include "itkMaskedNaryStatisticsImageFilter.h" +#include "itkProgressReporter.h" +#include "itkMaskedStatisticsImageFilter.h" + +namespace itk +{ + /** + * Constructor + */ + template< class TInputImage, class TMaskImage > + MaskedNaryStatisticsImageFilter< TInputImage, TMaskImage > + ::MaskedNaryStatisticsImageFilter() + { + // This number will be incremented each time an image + // is added over the two minimum required + this->SetNumberOfRequiredInputs(1); + } + + template< class TInputImage, class TMaskImage > + void + MaskedNaryStatisticsImageFilter< TInputImage, TMaskImage > + ::GenerateData() + { + const unsigned int numberOfInputImages = + static_cast< unsigned int >( this->GetNumberOfIndexedInputs() ); + + ProgressReporter progress( this, 0, numberOfInputImages ); + + m_Maximum.clear(); + m_Minimum.clear(); + m_Sum.clear(); + m_Mean.clear(); + m_Sigma.clear(); + m_Variance.clear(); + + // go through the inputs and add iterators for non-null inputs + for ( unsigned int i = 0; i < numberOfInputImages; ++i ) + { + InputImagePointer inputPtr = + dynamic_cast< TInputImage * >( ProcessObject::GetInput(i) ); + + if ( !inputPtr ) + { + itkExceptionMacro(<< "Cannot compute statistics. At least one of the input images has a wrong type. Wrong image index: "<< i); + } + + typedef itk::MaskedStatisticsImageFilter FilterType; + typename FilterType::Pointer statFilter = FilterType::New(); + + statFilter->SetInput(inputPtr); + statFilter->SetMask(m_Mask); + statFilter->Update(); + + m_Maximum.push_back(statFilter->GetMaximum()); + m_Minimum.push_back(statFilter->GetMinimum()); + m_Sum.push_back(statFilter->GetSum()); + m_Mean.push_back(statFilter->GetMean()); + m_Sigma.push_back(statFilter->GetSigma()); + m_Variance.push_back(statFilter->GetVariance()); + + progress.CompletedPixel(); + } + } + +} // end namespace itk + +#endif diff --git a/Modules/ModelFit/include/itkMaskedStatisticsImageFilter.h b/Modules/ModelFit/include/itkMaskedStatisticsImageFilter.h new file mode 100644 index 0000000000..734e584c58 --- /dev/null +++ b/Modules/ModelFit/include/itkMaskedStatisticsImageFilter.h @@ -0,0 +1,195 @@ +/*========================================================================= +* +* Copyright Insight Software Consortium +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0.txt +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*=========================================================================*/ +#ifndef __itkMaskedStatisticsImageFilter_h +#define __itkMaskedStatisticsImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkNumericTraits.h" +#include "itkArray.h" +#include "itkSimpleDataObjectDecorator.h" + +namespace itk +{ + /** \class MaskedStatisticsImageFilter + * \brief Compute min. max, variance and mean of an (masked) Image. + * + * MaskedStatisticsImageFilter computes the minimum, maximum, sum, mean, variance + * sigma of an image. The filter needs all of its input image. It + * behaves as a filter with an input and output. Thus it can be inserted + * in a pipeline with other filters and the statistics will only be + * recomputed if a downstream filter changes. + * + * The filter passes its input through unmodified. The filter is + * threaded. It computes statistics in each thread then combines them in + * its AfterThreadedGenerate method. + * \remark This filter differs from itk::StatisticsImageFilter by the fact that you can + * specify an mask image. If set, only pixels within the mask (mask value > 0) are taken + * into account for the statistics. + * + * \ingroup MathematicalStatisticsImageFilters + * \ingroup ITKImageStatistics + * + */ + template< typename TInputImage , typename TMaskImage = ::itk::Image > + class MaskedStatisticsImageFilter: + public ImageToImageFilter< TInputImage, TInputImage > + { + public: + /** Standard Self typedef */ + typedef MaskedStatisticsImageFilter Self; + typedef ImageToImageFilter< TInputImage, TInputImage > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(MaskedStatisticsImageFilter, ImageToImageFilter); + + /** Image related typedefs. */ + typedef typename Superclass::InputImageType InputImageType; + typedef typename Superclass::InputImagePointer InputImagePointer; + + typedef typename TInputImage::RegionType RegionType; + typedef typename TInputImage::SizeType SizeType; + typedef typename TInputImage::IndexType IndexType; + typedef typename TInputImage::PixelType PixelType; + + /** Image related typedefs. */ + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + /** Type to use for computations. */ + typedef typename NumericTraits< PixelType >::RealType RealType; + + /** Smart Pointer type to a DataObject. */ + typedef typename DataObject::Pointer DataObjectPointer; + + /** Type of DataObjects used for scalar outputs */ + typedef SimpleDataObjectDecorator< RealType > RealObjectType; + typedef SimpleDataObjectDecorator< PixelType > PixelObjectType; + + typedef TMaskImage MaskImageType; + typedef typename MaskImageType::ConstPointer MaskImageConstPointer; + typedef typename MaskImageType::RegionType MaskImageRegionType; + + /** Return the computed Minimum. */ + PixelType GetMinimum() const + { return this->GetMinimumOutput()->Get(); } + PixelObjectType * GetMinimumOutput(); + + const PixelObjectType * GetMinimumOutput() const; + + /** Return the computed Maximum. */ + PixelType GetMaximum() const + { return this->GetMaximumOutput()->Get(); } + PixelObjectType * GetMaximumOutput(); + + const PixelObjectType * GetMaximumOutput() const; + + /** Return the computed Mean. */ + RealType GetMean() const + { return this->GetMeanOutput()->Get(); } + RealObjectType * GetMeanOutput(); + + const RealObjectType * GetMeanOutput() const; + + /** Return the computed Standard Deviation. */ + RealType GetSigma() const + { return this->GetSigmaOutput()->Get(); } + RealObjectType * GetSigmaOutput(); + + const RealObjectType * GetSigmaOutput() const; + + /** Return the computed Variance. */ + RealType GetVariance() const + { return this->GetVarianceOutput()->Get(); } + RealObjectType * GetVarianceOutput(); + + const RealObjectType * GetVarianceOutput() const; + + /** Return the compute Sum. */ + RealType GetSum() const + { return this->GetSumOutput()->Get(); } + RealObjectType * GetSumOutput(); + + const RealObjectType * GetSumOutput() const; + + /** Make a DataObject of the correct type to be used as the specified + * output. */ + typedef ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType; + using Superclass::MakeOutput; + virtual DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx); + + itkSetConstObjectMacro(Mask, MaskImageType); + itkGetConstObjectMacro(Mask, MaskImageType); + +#ifdef ITK_USE_CONCEPT_CHECKING + // Begin concept checking + itkConceptMacro( InputHasNumericTraitsCheck, + ( Concept::HasNumericTraits< PixelType > ) ); + // End concept checking +#endif + + protected: + MaskedStatisticsImageFilter(); + ~MaskedStatisticsImageFilter(){} + void PrintSelf(std::ostream & os, Indent indent) const; + + /** Pass the input through unmodified. Do this by Grafting in the + * AllocateOutputs method. + */ + void AllocateOutputs(); + + /** Initialize some accumulators before the threads run. */ + void BeforeThreadedGenerateData(); + + /** Do final mean and variance computation from data accumulated in threads. + */ + void AfterThreadedGenerateData(); + + /** Multi-thread version GenerateData. */ + void ThreadedGenerateData(const RegionType & + outputRegionForThread, + ThreadIdType threadId); + + // Override since the filter needs all the data for the algorithm + void GenerateInputRequestedRegion(); + + // Override since the filter produces all of its output + void EnlargeOutputRequestedRegion(DataObject *data); + + private: + MaskedStatisticsImageFilter(const Self &); //purposely not implemented + void operator=(const Self &); //purposely not implemented + + Array< RealType > m_ThreadSum; + Array< RealType > m_SumOfSquares; + Array< SizeValueType > m_Count; + Array< PixelType > m_ThreadMin; + Array< PixelType > m_ThreadMax; + MaskImageConstPointer m_Mask; + }; // end of class +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkMaskedStatisticsImageFilter.hxx" +#endif + +#endif diff --git a/Modules/ModelFit/include/itkMaskedStatisticsImageFilter.hxx b/Modules/ModelFit/include/itkMaskedStatisticsImageFilter.hxx new file mode 100644 index 0000000000..e6dea73005 --- /dev/null +++ b/Modules/ModelFit/include/itkMaskedStatisticsImageFilter.hxx @@ -0,0 +1,393 @@ +/*========================================================================= +* +* Copyright Insight Software Consortium +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0.txt +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*=========================================================================*/ +#ifndef __itkMaskedStatisticsImageFilter_hxx +#define __itkMaskedStatisticsImageFilter_hxx +#include "itkMaskedStatisticsImageFilter.h" + + +#include "itkImageScanlineIterator.h" +#include "itkProgressReporter.h" + +namespace itk +{ + template< typename TInputImage, typename TMaskImage > + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::MaskedStatisticsImageFilter():m_ThreadSum(1), m_SumOfSquares(1), m_Count(1), m_ThreadMin(1), m_ThreadMax(1) + { + // first output is a copy of the image, DataObject created by + // superclass + // + // allocate the data objects for the outputs which are + // just decorators around pixel types + for ( int i = 1; i < 3; ++i ) + { + typename PixelObjectType::Pointer output = + static_cast< PixelObjectType * >( this->MakeOutput(i).GetPointer() ); + this->ProcessObject::SetNthOutput( i, output.GetPointer() ); + } + // allocate the data objects for the outputs which are + // just decorators around real types + for ( int i = 3; i < 7; ++i ) + { + typename RealObjectType::Pointer output = + static_cast< RealObjectType * >( this->MakeOutput(i).GetPointer() ); + this->ProcessObject::SetNthOutput( i, output.GetPointer() ); + } + + this->GetMinimumOutput()->Set( NumericTraits< PixelType >::max() ); + this->GetMaximumOutput()->Set( NumericTraits< PixelType >::NonpositiveMin() ); + this->GetMeanOutput()->Set( NumericTraits< RealType >::max() ); + this->GetSigmaOutput()->Set( NumericTraits< RealType >::max() ); + this->GetVarianceOutput()->Set( NumericTraits< RealType >::max() ); + this->GetSumOutput()->Set(NumericTraits< RealType >::Zero); + } + + template< typename TInputImage, typename TMaskImage > + DataObject::Pointer + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::MakeOutput(DataObjectPointerArraySizeType output) + { + switch ( output ) + { + case 0: + return TInputImage::New().GetPointer(); + break; + case 1: + return PixelObjectType::New().GetPointer(); + break; + case 2: + return PixelObjectType::New().GetPointer(); + break; + case 3: + case 4: + case 5: + case 6: + return RealObjectType::New().GetPointer(); + break; + default: + // might as well make an image + return TInputImage::New().GetPointer(); + break; + } + } + + template< typename TInputImage, typename TMaskImage > + typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::PixelObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetMinimumOutput() + { + return static_cast< PixelObjectType * >( this->ProcessObject::GetOutput(1) ); + } + + template< typename TInputImage, typename TMaskImage > + const typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::PixelObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetMinimumOutput() const + { + return static_cast< const PixelObjectType * >( this->ProcessObject::GetOutput(1) ); + } + + template< typename TInputImage, typename TMaskImage > + typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::PixelObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetMaximumOutput() + { + return static_cast< PixelObjectType * >( this->ProcessObject::GetOutput(2) ); + } + + template< typename TInputImage, typename TMaskImage > + const typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::PixelObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetMaximumOutput() const + { + return static_cast< const PixelObjectType * >( this->ProcessObject::GetOutput(2) ); + } + + template< typename TInputImage, typename TMaskImage > + typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::RealObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetMeanOutput() + { + return static_cast< RealObjectType * >( this->ProcessObject::GetOutput(3) ); + } + + template< typename TInputImage, typename TMaskImage > + const typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::RealObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetMeanOutput() const + { + return static_cast< const RealObjectType * >( this->ProcessObject::GetOutput(3) ); + } + + template< typename TInputImage, typename TMaskImage > + typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::RealObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetSigmaOutput() + { + return static_cast< RealObjectType * >( this->ProcessObject::GetOutput(4) ); + } + + template< typename TInputImage, typename TMaskImage > + const typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::RealObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetSigmaOutput() const + { + return static_cast< const RealObjectType * >( this->ProcessObject::GetOutput(4) ); + } + + template< typename TInputImage, typename TMaskImage > + typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::RealObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetVarianceOutput() + { + return static_cast< RealObjectType * >( this->ProcessObject::GetOutput(5) ); + } + + template< typename TInputImage, typename TMaskImage > + const typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::RealObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetVarianceOutput() const + { + return static_cast< const RealObjectType * >( this->ProcessObject::GetOutput(5) ); + } + + template< typename TInputImage, typename TMaskImage > + typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::RealObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetSumOutput() + { + return static_cast< RealObjectType * >( this->ProcessObject::GetOutput(6) ); + } + + template< typename TInputImage, typename TMaskImage > + const typename MaskedStatisticsImageFilter< TInputImage, TMaskImage >::RealObjectType * + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GetSumOutput() const + { + return static_cast< const RealObjectType * >( this->ProcessObject::GetOutput(6) ); + } + + template< typename TInputImage, typename TMaskImage > + void + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::GenerateInputRequestedRegion() + { + Superclass::GenerateInputRequestedRegion(); + if ( this->GetInput() ) + { + InputImagePointer image = + const_cast< typename Superclass::InputImageType * >( this->GetInput() ); + image->SetRequestedRegionToLargestPossibleRegion(); + } + } + + template< typename TInputImage, typename TMaskImage > + void + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::EnlargeOutputRequestedRegion(DataObject *data) + { + Superclass::EnlargeOutputRequestedRegion(data); + data->SetRequestedRegionToLargestPossibleRegion(); + } + + template< typename TInputImage, typename TMaskImage > + void + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::AllocateOutputs() + { + // Pass the input through as the output + InputImagePointer image = + const_cast< TInputImage * >( this->GetInput() ); + + this->GraftOutput(image); + + // Nothing that needs to be allocated for the remaining outputs + } + + template< typename TInputImage, typename TMaskImage > + void + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::BeforeThreadedGenerateData() + { + ThreadIdType numberOfThreads = this->GetNumberOfThreads(); + + // Resize the thread temporaries + m_Count.SetSize(numberOfThreads); + m_SumOfSquares.SetSize(numberOfThreads); + m_ThreadSum.SetSize(numberOfThreads); + m_ThreadMin.SetSize(numberOfThreads); + m_ThreadMax.SetSize(numberOfThreads); + + // Initialize the temporaries + m_Count.Fill(NumericTraits< SizeValueType >::Zero); + m_ThreadSum.Fill(NumericTraits< RealType >::Zero); + m_SumOfSquares.Fill(NumericTraits< RealType >::Zero); + m_ThreadMin.Fill( NumericTraits< PixelType >::max() ); + m_ThreadMax.Fill( NumericTraits< PixelType >::NonpositiveMin() ); + } + + template< typename TInputImage, typename TMaskImage > + void + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::AfterThreadedGenerateData() + { + ThreadIdType i; + SizeValueType count; + RealType sumOfSquares; + + ThreadIdType numberOfThreads = this->GetNumberOfThreads(); + + PixelType minimum; + PixelType maximum; + RealType mean; + RealType sigma; + RealType variance; + RealType sum; + + sum = sumOfSquares = NumericTraits< RealType >::Zero; + count = 0; + + // Find the min/max over all threads and accumulate count, sum and + // sum of squares + minimum = NumericTraits< PixelType >::max(); + maximum = NumericTraits< PixelType >::NonpositiveMin(); + for ( i = 0; i < numberOfThreads; i++ ) + { + count += m_Count[i]; + sum += m_ThreadSum[i]; + sumOfSquares += m_SumOfSquares[i]; + + if ( m_ThreadMin[i] < minimum ) + { + minimum = m_ThreadMin[i]; + } + if ( m_ThreadMax[i] > maximum ) + { + maximum = m_ThreadMax[i]; + } + } + // compute statistics + mean = sum / static_cast< RealType >( count ); + + // unbiased estimate + variance = ( sumOfSquares - ( sum * sum / static_cast< RealType >( count ) ) ) + / ( static_cast< RealType >( count ) - 1 ); + sigma = std::sqrt(variance); + + // Set the outputs + this->GetMinimumOutput()->Set(minimum); + this->GetMaximumOutput()->Set(maximum); + this->GetMeanOutput()->Set(mean); + this->GetSigmaOutput()->Set(sigma); + this->GetVarianceOutput()->Set(variance); + this->GetSumOutput()->Set(sum); + } + + template< typename TInputImage, typename TMaskImage > + void + MaskedStatisticsImageFilter< TInputImage, TMaskImage > + ::ThreadedGenerateData(const RegionType & outputRegionForThread, + ThreadIdType threadId) + { + const SizeValueType size0 = outputRegionForThread.GetSize(0); + if( size0 == 0) + { + return; + } + RealType realValue; + PixelType value; + + RealType sum = NumericTraits< RealType >::Zero; + RealType sumOfSquares = NumericTraits< RealType >::Zero; + SizeValueType count = NumericTraits< SizeValueType >::Zero; + PixelType min = NumericTraits< PixelType >::max(); + PixelType max = NumericTraits< PixelType >::NonpositiveMin(); + + ImageScanlineConstIterator< TInputImage > it (this->GetInput(), outputRegionForThread); + + // support progress methods/callbacks + const size_t numberOfLinesToProcess = outputRegionForThread.GetNumberOfPixels() / size0; + ProgressReporter progress( this, threadId, numberOfLinesToProcess ); + + // do the work + while ( !it.IsAtEnd() ) + { + while ( !it.IsAtEndOfLine() ) + { + bool isValid = true; + + if(m_Mask.IsNotNull()) + { + typename InputImageType::IndexType index = it.GetIndex(); + typename InputImageType::PointType point; + this->GetInput()->TransformIndexToPhysicalPoint(index, point); + if (this->m_Mask->TransformPhysicalPointToIndex(point, index)) + { + isValid = this->m_Mask->GetPixel(index) > 0.0; + }; + } + + if (isValid) + { + value = it.Get(); + realValue = static_cast< RealType >( value ); + if ( value < min ) + { + min = value; + } + if ( value > max ) + { + max = value; + } + + sum += realValue; + sumOfSquares += ( realValue * realValue ); + ++count; + } + + ++it; + } + it.NextLine(); + progress.CompletedPixel(); + } + + m_ThreadSum[threadId] = sum; + m_SumOfSquares[threadId] = sumOfSquares; + m_Count[threadId] = count; + m_ThreadMin[threadId] = min; + m_ThreadMax[threadId] = max; + } + + template< typename TImage, typename TMaskImage > + void + MaskedStatisticsImageFilter< TImage, TMaskImage > + ::PrintSelf(std::ostream & os, Indent indent) const + { + Superclass::PrintSelf(os, indent); + + os << indent << "Minimum: " + << static_cast< typename NumericTraits< PixelType >::PrintType >( this->GetMinimum() ) << std::endl; + os << indent << "Maximum: " + << static_cast< typename NumericTraits< PixelType >::PrintType >( this->GetMaximum() ) << std::endl; + os << indent << "Sum: " << this->GetSum() << std::endl; + os << indent << "Mean: " << this->GetMean() << std::endl; + os << indent << "Sigma: " << this->GetSigma() << std::endl; + os << indent << "Variance: " << this->GetVariance() << std::endl; + } +} // end namespace itk +#endif diff --git a/Modules/ModelFit/include/itkMultiOutputNaryFunctorImageFilter.h b/Modules/ModelFit/include/itkMultiOutputNaryFunctorImageFilter.h new file mode 100644 index 0000000000..512089d89b --- /dev/null +++ b/Modules/ModelFit/include/itkMultiOutputNaryFunctorImageFilter.h @@ -0,0 +1,150 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __itkMultiOutputNaryFunctorImageFilter_h +#define __itkMultiOutputNaryFunctorImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkImageIterator.h" +#include "itkArray.h" + +namespace itk +{ +/** \class MultiOutputNaryFunctorImageFilter + * \brief Perform a generic pixel-wise operation on N images and produces m output images. + * + * This is an extension of the itk::NaryFunctorImageFilter. It assumes that the functor + * returns not only one result pixel value but a vector of m values an therefore generates + * m output images. In addition (and difference to itk::NaryFunctorImageFilter) it also + * passes the index of the current value vector to the functor (for space correlated + * evaluations).\n + * Class is templated over the types of the input images + * and the type of the output images. It is also templated by the + * operation to be applied. A Functor style is used to represent the + * function.\n + * + * All the input images must be of the same type. + * + * \ingroup IntensityImageFilters MultiThreaded + * \ingroup ITKImageIntensity + */ + +template< class TInputImage, class TOutputImage, class TFunction, class TMaskImage = ::itk::Image > +class ITK_EXPORT MultiOutputNaryFunctorImageFilter: + public ImageToImageFilter< TInputImage, TOutputImage > + +{ +public: + /** Standard class typedefs. */ + typedef MultiOutputNaryFunctorImageFilter Self; + typedef ImageToImageFilter< TInputImage, TOutputImage > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(MultiOutputNaryFunctorImageFilter, ImageToImageFilter); + + /** Some typedefs. */ + typedef TFunction FunctorType; + typedef TInputImage InputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + typedef typename FunctorType::InputPixelArrayType NaryInputArrayType; + typedef typename FunctorType::OutputPixelArrayType NaryOutputArrayType; + typedef TMaskImage MaskImageType; + typedef typename MaskImageType::Pointer MaskImagePointer; + typedef typename MaskImageType::RegionType MaskImageRegionType; + + /** Get the functor object. The functor is returned by reference. + * (Functors do not have to derive from itk::LightObject, so they do + * not necessarily have a reference count. So we cannot return a + * SmartPointer). */ + FunctorType & GetFunctor() { return m_Functor; } + + /** Set the functor object. This replaces the current Functor with a + * copy of the specified Functor. This allows the user to specify a + * functor that has ivars set differently than the default functor. + * This method requires an operator!=() be defined on the functor + * (or the compiler's default implementation of operator!=() being + * appropriate). */ + void SetFunctor(FunctorType & functor) + { + if ( m_Functor != functor ) + { + m_Functor = functor; + this->ActualizeOutputs(); + this->Modified(); + } + } + + itkSetObjectMacro(Mask, MaskImageType); + itkGetConstObjectMacro(Mask, MaskImageType); + + /** ImageDimension constants */ + itkStaticConstMacro( + InputImageDimension, unsigned int, TInputImage::ImageDimension); + itkStaticConstMacro( + OutputImageDimension, unsigned int, TOutputImage::ImageDimension); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro( SameDimensionCheck, + ( Concept::SameDimension< InputImageDimension, OutputImageDimension > ) ); + itkConceptMacro( OutputHasZeroCheck, + ( Concept::HasZero< OutputImagePixelType > ) ); + /** End concept checking */ +#endif +protected: + MultiOutputNaryFunctorImageFilter(); + virtual ~MultiOutputNaryFunctorImageFilter() {} + + /** MultiOutputNaryFunctorImageFilter can be implemented as a multi threaded filter. + * Therefore, this implementation provides a ThreadedGenerateData() routine + * which is called for each processing thread. The output image data is + * allocated automatically by the superclass prior to calling + * ThreadedGenerateData(). ThreadedGenerateData can only write to the + * portion of the output image specified by the parameter + * "outputRegionForThread" + * + * \sa ImageToImageFilter::ThreadedGenerateData(), + * ImageToImageFilter::GenerateData() */ + void ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, + ThreadIdType threadId); + + /** Methods actualize the output settings of the filter according to the current functor*/ + void ActualizeOutputs(); + +private: + MultiOutputNaryFunctorImageFilter(const Self &); //purposely not implemented + void operator=(const Self &); //purposely not implemented + + FunctorType m_Functor; + MaskImagePointer m_Mask; +}; +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkMultiOutputNaryFunctorImageFilter.tpp" +#endif + +#endif diff --git a/Modules/ModelFit/include/itkMultiOutputNaryFunctorImageFilter.tpp b/Modules/ModelFit/include/itkMultiOutputNaryFunctorImageFilter.tpp new file mode 100644 index 0000000000..deb5513da0 --- /dev/null +++ b/Modules/ModelFit/include/itkMultiOutputNaryFunctorImageFilter.tpp @@ -0,0 +1,235 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __itkMultiOutputNaryFunctorImageFilter_hxx +#define __itkMultiOutputNaryFunctorImageFilter_hxx + +#include "itkMultiOutputNaryFunctorImageFilter.h" +#include "itkImageRegionIterator.h" +#include "itkProgressReporter.h" + +namespace itk +{ + /** + * Constructor + */ + template< class TInputImage, class TOutputImage, class TFunction, class TMaskImage > + MultiOutputNaryFunctorImageFilter< TInputImage, TOutputImage, TFunction, TMaskImage > + ::MultiOutputNaryFunctorImageFilter() + { + // This number will be incremented each time an image + // is added over the two minimum required + this->SetNumberOfRequiredInputs(1); + + this->ActualizeOutputs(); + } + + template< class TInputImage, class TOutputImage, class TFunction, class TMaskImage > + void + MultiOutputNaryFunctorImageFilter< TInputImage, TOutputImage, TFunction, TMaskImage > + ::ActualizeOutputs() + { + this->SetNumberOfRequiredOutputs(m_Functor.GetNumberOfOutputs()); + + for (typename Superclass::DataObjectPointerArraySizeType i = this->GetNumberOfIndexedOutputs(); i< m_Functor.GetNumberOfOutputs(); ++i) + { + this->SetNthOutput( i, this->MakeOutput(i) ); + } + + while(this->GetNumberOfIndexedOutputs() > m_Functor.GetNumberOfOutputs()) + { + this->RemoveOutput(this->GetNumberOfIndexedOutputs()-1); + } + }; + + /** + * ThreadedGenerateData Performs the pixel-wise addition + */ + template< class TInputImage, class TOutputImage, class TFunction, class TMaskImage > + void + MultiOutputNaryFunctorImageFilter< TInputImage, TOutputImage, TFunction, TMaskImage > + ::ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, + ThreadIdType threadId) + { + ProgressReporter progress( this, threadId, + outputRegionForThread.GetNumberOfPixels() ); + + const unsigned int numberOfInputImages = + static_cast< unsigned int >( this->GetNumberOfIndexedInputs() ); + + const unsigned int numberOfOutputImages = + static_cast< unsigned int >( this->GetNumberOfIndexedOutputs() ); + + typedef ImageRegionConstIterator< TInputImage > ImageRegionConstIteratorType; + std::vector< ImageRegionConstIteratorType * > inputItrVector; + inputItrVector.reserve(numberOfInputImages); + + typedef ImageRegionIterator< TOutputImage > OutputImageRegionIteratorType; + std::vector< OutputImageRegionIteratorType * > outputItrVector; + outputItrVector.reserve(numberOfOutputImages); + + //check if mask image is set and generate iterator if mask is valid + typedef ImageRegionConstIterator< TMaskImage > MaskImageRegionIteratorType; + MaskImageRegionIteratorType* pMaskIterator = NULL; + + if (m_Mask.IsNotNull()) + { + if (!m_Mask->GetLargestPossibleRegion().IsInside(outputRegionForThread)) + { + itkExceptionMacro("Mask of filter is set but does not cover region of thread. Mask region: "<< m_Mask->GetLargestPossibleRegion() <<"Thread region: "<( ProcessObject::GetInput(i) ); + + if ( inputPtr ) + { + inputItrVector.push_back( new ImageRegionConstIteratorType(inputPtr, outputRegionForThread) ); + } + + } + + // go through the outputs and add iterators for non-null outputs + for ( unsigned int i = 0; i < numberOfOutputImages; ++i ) + { + OutputImagePointer outputPtr = + dynamic_cast< TOutputImage * >( ProcessObject::GetOutput(i) ); + + if ( outputPtr ) + { + outputItrVector.push_back( new OutputImageRegionIteratorType(outputPtr, outputRegionForThread) ); + } + } + + typename std::vector< ImageRegionConstIteratorType * >::iterator regionInputIterators; + const typename std::vector< ImageRegionConstIteratorType * >::const_iterator regionInputItEnd = + inputItrVector.end(); + + typename std::vector< OutputImageRegionIteratorType * >::iterator regionOutputIterators; + const typename std::vector< OutputImageRegionIteratorType * >::const_iterator regionOutputItEnd = + outputItrVector.end(); + + const unsigned int numberOfValidInputImages = inputItrVector.size(); + const unsigned int numberOfValidOutputImages = outputItrVector.size(); + + if ( (numberOfValidInputImages != 0) && ( numberOfValidOutputImages != 0)) + { + try + { + + while ( !(outputItrVector.front()->IsAtEnd()) ) + { + typename NaryInputArrayType::iterator arrayInIt; + typename NaryOutputArrayType::iterator arrayOutIt; + NaryInputArrayType naryInputArray(numberOfValidInputImages); + NaryOutputArrayType naryOutputArray(numberOfValidOutputImages); + + bool isValid = true; + + if (pMaskIterator) + { + isValid = pMaskIterator->Get() > 0; + ++(*pMaskIterator); + } + + arrayInIt = naryInputArray.begin(); + regionInputIterators = inputItrVector.begin(); + + typename ImageRegionConstIteratorType::IndexType currentIndex; + if(regionInputIterators != regionInputItEnd) + { + currentIndex = ( *regionInputIterators )->GetIndex(); + } + + while ( regionInputIterators != regionInputItEnd ) + { + *arrayInIt++ = ( *regionInputIterators )->Get(); + ++( *( *regionInputIterators ) ); + ++regionInputIterators; + } + + if (isValid) + { + naryOutputArray = m_Functor(naryInputArray, currentIndex); + + if (numberOfValidOutputImages != naryOutputArray.size()) + { + itkExceptionMacro("Error. Number of valid output images do not equal number of outputs required by functor. Number of valid outputs: "<< numberOfValidOutputImages << "; needed output number:" << this->m_Functor.GetNumberOfOutputs()); + } + } + else + { + for (typename NaryOutputArrayType::iterator pos = naryOutputArray.begin(); pos!= naryOutputArray.end(); ++pos) + { + *pos = 0.0; + } + } + + arrayOutIt = naryOutputArray.begin(); + regionOutputIterators = outputItrVector.begin(); + while ( regionOutputIterators != regionOutputItEnd ) + { + ( *regionOutputIterators )->Set(*arrayOutIt++); + ++( *( *regionOutputIterators ) ); + ++regionOutputIterators; + } + + progress.CompletedPixel(); + } + } + catch(...) + { + // Free memory in case of exceptions + regionInputIterators = inputItrVector.begin(); + while ( regionInputIterators != regionInputItEnd ) + { + delete ( *regionInputIterators++ ); + } + + regionOutputIterators = outputItrVector.begin(); + while ( regionOutputIterators != regionOutputItEnd ) + { + delete ( *regionOutputIterators++ ); + } + + delete pMaskIterator; + throw; + } + } + + // Free memory regulary + regionInputIterators = inputItrVector.begin(); + while ( regionInputIterators != regionInputItEnd ) + { + delete ( *regionInputIterators++ ); + } + + regionOutputIterators = outputItrVector.begin(); + while ( regionOutputIterators != regionOutputItEnd ) + { + delete ( *regionOutputIterators++ ); + } + + delete pMaskIterator; + } +} // end namespace itk + +#endif diff --git a/Modules/ModelFit/include/mitkBinaryImageToLabelSetImageFilter.h b/Modules/ModelFit/include/mitkBinaryImageToLabelSetImageFilter.h new file mode 100644 index 0000000000..c11a782db6 --- /dev/null +++ b/Modules/ModelFit/include/mitkBinaryImageToLabelSetImageFilter.h @@ -0,0 +1,67 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkBinaryImageToLabelSetImageFilter_h +#define mitkBinaryImageToLabelSetImageFilter_h + +#include + +#include "mitkCommon.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /** \brief Converts an binary image to a LabelSetImage. The amount of labels equals the connected components. + */ + class MITKMODELFIT_EXPORT BinaryImageToLabelSetImageFilter : public ImageToImageFilter + { + public: + mitkClassMacro(BinaryImageToLabelSetImageFilter, ImageToImageFilter); + itkFactorylessNewMacro(Self) itkCloneMacro(Self) + + void SetInput(const InputImageType* image) override; + void SetInput(unsigned int index, const InputImageType* image) override; + + itkSetMacro(FullyConnected, bool); + itkGetConstMacro(FullyConnected, bool); + + itkSetMacro(ForegroundValue, unsigned int); + itkGetConstMacro(ForegroundValue, unsigned int); + + itkSetMacro(OutputIsLabelSetImage, bool); + itkGetConstMacro(OutputIsLabelSetImage, bool); + + private: + using Superclass::SetInput; + + BinaryImageToLabelSetImageFilter() = default; + ~BinaryImageToLabelSetImageFilter() override = default; + + template + void ApplyBinaryImageToLabelMapFilter(const itk::Image* inputImage); + + void GenerateData() override; + void VerifyInputInformation() override; + void VerifyInputImage(const mitk::Image* inputImage); + + bool m_FullyConnected = true; + unsigned int m_ForegroundValue = 1; + bool m_OutputIsLabelSetImage = false; + }; +} + +#endif diff --git a/Modules/ModelFit/include/mitkChiSquareFitCostFunction.h b/Modules/ModelFit/include/mitkChiSquareFitCostFunction.h new file mode 100644 index 0000000000..cb96da86bb --- /dev/null +++ b/Modules/ModelFit/include/mitkChiSquareFitCostFunction.h @@ -0,0 +1,39 @@ +#ifndef CHI_SQUARE_FITCOSTFUNCTION_H +#define CHI_SQUARE_FITCOSTFUNCTION_H + +#include + +#include "MitkModelFitExports.h" + + +namespace mitk +{ +/** Multi valued model fit cost function that computes the Chi square. NOTE: This is only for Data from Radioactive Decays (e.g. PET, SPECT) +*/ +class MITKMODELFIT_EXPORT ChiSquareFitCostFunction : public mitk::SVModelFitCostFunction +{ +public: + + typedef ChiSquareFitCostFunction Self; + typedef mitk::SVModelFitCostFunction Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + itkNewMacro(Self); + + typedef Superclass::SignalType SignalType; + +protected: + + virtual MeasureType CalcMeasure(const ParametersType ¶meters, const SignalType& signal) const; + + ChiSquareFitCostFunction() + { + + } + + ~ChiSquareFitCostFunction(){} + +}; +} + +#endif // CHISQUAREFITCOSTFUNCTION_H diff --git a/Modules/ModelFit/include/mitkConcreteModelFactoryBase.h b/Modules/ModelFit/include/mitkConcreteModelFactoryBase.h new file mode 100644 index 0000000000..9cc6238bd2 --- /dev/null +++ b/Modules/ModelFit/include/mitkConcreteModelFactoryBase.h @@ -0,0 +1,176 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __CONCRETE_MODEL_FACTORY_BASE_H +#define __CONCRETE_MODEL_FACTORY_BASE_H + +#include "mitkModelFactoryBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + template + class ConcreteModelFactoryBase : public ModelFactoryBase + { + public: +/* typedef ConcreteModelFactoryBase Self; + typedef ModelFactoryBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; +*/ + mitkClassMacro(ConcreteModelFactoryBase, ModelFactoryBase); + + typedef ModelFactoryBase::ModelBaseType ModelBaseType; + typedef ModelFactoryBase::ModelBasePointer ModelBasePointer; + + typedef TModel ModelType; + typedef typename ModelType::Pointer ModelPointer; + + typedef ModelFactoryBase::ParameterNameType ParameterNameType; + typedef ModelFactoryBase::ParameterNamesType ParameterNamesType; + typedef ModelFactoryBase::ParametersSizeType ParametersSizeType; + typedef ModelFactoryBase::ParamterScaleMapType ParamterScaleMapType; + typedef ModelFactoryBase::ParamterUnitMapType ParamterUnitMapType; + typedef ModelFactoryBase::DerivedParameterNamesType DerivedParameterNamesType; + typedef ModelFactoryBase::DerivedParametersSizeType DerivedParametersSizeType; + typedef ModelFactoryBase::DerivedParamterScaleMapType DerivedParamterScaleMapType; + typedef ModelFactoryBase::DerivedParamterUnitMapType DerivedParamterUnitMapType; + typedef ModelFactoryBase::FunctionStringType FunctionStringType; + typedef ModelFactoryBase::ModellClassIDType ModellClassIDType; + + static ModelPointer CreateConcreteModel() + { + return ModelType::New(); + } + + virtual ModelBasePointer CreateModel() const override + { + return CreateConcreteModel().GetPointer(); + }; + + ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override + { + ConstraintCheckerBase::Pointer noConstraints; + return noConstraints; + }; + + virtual ParameterNamesType GetParameterNames() const override + { + return m_Reference->GetParameterNames(); + }; + + virtual ParametersSizeType GetNumberOfParameters() const override + { + return m_Reference->GetNumberOfParameters(); + }; + + virtual ParamterScaleMapType GetParameterScales() const override + { + return m_Reference->GetParameterScales(); + }; + + virtual ParamterUnitMapType GetParameterUnits() const override + { + return m_Reference->GetParameterUnits(); + }; + + virtual ParameterNamesType GetDerivedParameterNames() const override + { + return m_Reference->GetDerivedParameterNames(); + }; + + virtual ParametersSizeType GetNumberOfDerivedParameters() const override + { + return m_Reference->GetNumberOfDerivedParameters(); + }; + + virtual DerivedParamterScaleMapType GetDerivedParameterScales() const override + { + return m_Reference->GetDerivedParameterScales(); + }; + + virtual DerivedParamterUnitMapType GetDerivedParameterUnits() const override + { + return m_Reference->GetDerivedParameterUnits(); + }; + + virtual std::string GetModelDisplayName() const override + { + return m_Reference->GetModelDisplayName(); + }; + + virtual std::string GetModelType() const override + { + return m_Reference->GetModelType(); + }; + + virtual FunctionStringType GetFunctionString() const override + { + return m_Reference->GetFunctionString(); + }; + + virtual ModellClassIDType GetClassID() const override + { + return m_Reference->GetClassID(); + }; + + virtual std::string GetXName() const override + { + return m_Reference->GetXName(); + }; + + virtual std::string GetXAxisName() const override + { + return m_Reference->GetXAxisName(); + }; + + virtual std::string GetXAxisUnit() const override + { + return m_Reference->GetXAxisUnit(); + }; + + virtual std::string GetYAxisName() const override + { + return m_Reference->GetYAxisName(); + }; + + virtual std::string GetYAxisUnit() const override + { + return m_Reference->GetYAxisUnit(); + } + + protected: + ConcreteModelFactoryBase() + { + m_Reference = ModelType::New(); + }; + + virtual ~ConcreteModelFactoryBase() + { + }; + + ModelPointer m_Reference; + + private: + + //No copy constructor allowed + ConcreteModelFactoryBase(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // __CONCRETE_MODEL_FACTORY_BASE_H diff --git a/Modules/ModelFit/include/mitkConcreteModelParameterizerBase.h b/Modules/ModelFit/include/mitkConcreteModelParameterizerBase.h new file mode 100644 index 0000000000..4a52050f61 --- /dev/null +++ b/Modules/ModelFit/include/mitkConcreteModelParameterizerBase.h @@ -0,0 +1,209 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __CONCRETE_MODEL_PARAMETERIZER_BASE_H +#define __CONCRETE_MODEL_PARAMETERIZER_BASE_H + +#include "mitkModelParameterizerBase.h" + +namespace mitk +{ + template + class ConcreteModelParameterizerBase : public ModelParameterizerBase + { + public: + typedef ConcreteModelParameterizerBase Self; + typedef ModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ConcreteModelParameterizerBase, ModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef typename Superclass::ModelBaseType ModelBaseType; + typedef typename Superclass::ModelBasePointer ModelBasePointer; + + typedef TModel ModelType; + typedef typename ModelType::Pointer ModelPointer; + + typedef typename Superclass::StaticParameterValueType StaticParameterValueType; + typedef typename Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef typename Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /* Returns the global static parameters for the model. + * @remark this default implementation assumes no global static parameters exist. + * Thus an empty map is returned.*/ + virtual StaticParameterMapType GetGlobalStaticParameters() const + { + StaticParameterMapType result; + return result; + }; + + /* Returns the local static parameters for the model at the given index. + * @remark this default implementation assumes no local static parameters exist. + * Thus an empty map is returned.*/ + virtual StaticParameterMapType GetLocalStaticParameters(const IndexType& /*currentPosition*/) const + { + StaticParameterMapType result; + return result; + }; + + /* Returns an newly generated instance of the concrete model. + * It is parameterized by the static parameters (returns of GetGlobalParameter() and + * GetLocalParameter()). + */ + virtual ModelBasePointer GenerateParameterizedModel(const IndexType& currentPosition) const override + { + ModelPointer newModel = ModelType::New(); + StaticParameterMapType params = this->GetGlobalStaticParameters(); + StaticParameterMapType locals = this->GetLocalStaticParameters(currentPosition); + + params.insert(locals.begin(), locals.end()); + newModel->SetTimeGrid(m_DefaultTimeGrid); + newModel->SetStaticParameters(params); + + return newModel.GetPointer(); + }; + + virtual ModelBasePointer GenerateParameterizedModel() const override + { + ModelPointer newModel = ModelType::New(); + StaticParameterMapType params = this->GetGlobalStaticParameters(); + + newModel->SetTimeGrid(m_DefaultTimeGrid); + newModel->SetStaticParameters(params, false); + + return newModel.GetPointer(); + }; + + /* Returns a parameterization filled with zeros. + * @remark this default implementation assumes no special initial parameterization is suggested. + * Thus an zero filled vector is returned.*/ + virtual ParametersType GetDefaultInitialParameterization() const + { + ModelPointer newModel = ModelType::New(); + ParametersType params; + params.SetSize(newModel->GetNumberOfParameters()); + params.Fill(0.0); + + return params; + }; + + virtual ParameterNamesType GetParameterNames() const override + { + return GenerateParameterizedModel()->GetParameterNames(); + }; + + virtual ParametersSizeType GetNumberOfParameters() const override + { + return GenerateParameterizedModel()->GetNumberOfParameters(); + }; + + virtual ParamterScaleMapType GetParameterScales() const override + { + return GenerateParameterizedModel()->GetParameterScales(); + }; + + virtual ParamterUnitMapType GetParameterUnits() const override + { + return GenerateParameterizedModel()->GetParameterUnits(); + }; + + virtual ParameterNamesType GetDerivedParameterNames() const override + { + return GenerateParameterizedModel()->GetDerivedParameterNames(); + }; + + virtual ParametersSizeType GetNumberOfDerivedParameters() const override + { + return GenerateParameterizedModel()->GetNumberOfDerivedParameters(); + }; + + virtual DerivedParamterScaleMapType GetDerivedParameterScales() const override + { + return GenerateParameterizedModel()->GetDerivedParameterScales(); + }; + + virtual DerivedParamterUnitMapType GetDerivedParameterUnits() const override + { + return GenerateParameterizedModel()->GetDerivedParameterUnits(); + }; + + virtual std::string GetModelDisplayName() const override + { + return GenerateParameterizedModel()->GetModelDisplayName(); + }; + + virtual std::string GetModelType() const override + { + return GenerateParameterizedModel()->GetModelType(); + }; + + virtual FunctionStringType GetFunctionString() const override + { + return GenerateParameterizedModel()->GetFunctionString(); + }; + + virtual ModellClassIDType GetClassID() const override + { + return GenerateParameterizedModel()->GetClassID(); + }; + + virtual std::string GetXName() const override + { + return GenerateParameterizedModel()->GetXName(); + }; + + virtual std::string GetXAxisName() const override + { + return GenerateParameterizedModel()->GetXAxisName(); + }; + + virtual std::string GetXAxisUnit() const override + { + return GenerateParameterizedModel()->GetXAxisUnit(); + }; + + virtual std::string GetYAxisName() const override + { + return GenerateParameterizedModel()->GetYAxisName(); + }; + + virtual std::string GetYAxisUnit() const override + { + return GenerateParameterizedModel()->GetYAxisUnit(); + } + + protected: + ConcreteModelParameterizerBase() + { + }; + + virtual ~ConcreteModelParameterizerBase() + { + }; + + private: + + //No copy constructor allowed + ConcreteModelParameterizerBase(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // __CONCRETE_MODEL_PARAMETERIZER_BASE_H diff --git a/Modules/ModelFit/include/mitkConstraintCheckerBase.h b/Modules/ModelFit/include/mitkConstraintCheckerBase.h new file mode 100644 index 0000000000..674be6d874 --- /dev/null +++ b/Modules/ModelFit/include/mitkConstraintCheckerBase.h @@ -0,0 +1,66 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef CONSTRAINT_CHECKER_BASE_H +#define CONSTRAINT_CHECKER_BASE_H + +#include +#include + +#include "mitkConstraintCheckerInterface.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + +/** \class ConstraintCheckerBase + * \brief This class is the base class for constraint checker. + * @remark All functions of the ConstraintCheckerInterface must be implemented thread save because it will be used in a multi threaded + * environment. + */ +class MITKMODELFIT_EXPORT ConstraintCheckerBase : public itk::Object, public ConstraintCheckerInterface +{ +public: + + typedef ConstraintCheckerBase Self; + typedef ConstraintCheckerInterface Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef Superclass::PenaltyValueType PenaltyValueType; + typedef Superclass::PenaltyArrayType PenaltyArrayType; + typedef Superclass::SignalType SignalType; + typedef Superclass::ParametersType ParametersType; + + virtual PenaltyValueType GetPenaltySum(const ParametersType ¶meters) const; + +protected: + + ConstraintCheckerBase() + { + } + + ~ConstraintCheckerBase(){} + +private: + ConstraintCheckerBase(const ConstraintCheckerBase& source); + void operator=(const ConstraintCheckerBase&); //purposely not implemented +}; + +} + +#endif // ConstraintCheckerBase_H diff --git a/Modules/ModelFit/include/mitkConstraintCheckerInterface.h b/Modules/ModelFit/include/mitkConstraintCheckerInterface.h new file mode 100644 index 0000000000..0ed97e430d --- /dev/null +++ b/Modules/ModelFit/include/mitkConstraintCheckerInterface.h @@ -0,0 +1,73 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef CONSTRAINTCHECKER_INTERFACE_H +#define CONSTRAINTCHECKER_INTERFACE_H + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /** Interface class that is implemented by all constraint checkers that are used in the context of model fitting. + * @remark All functions of the interface must be implemented thread save because it will be used in a multi threaded + * environment. + */ + class MITKMODELFIT_EXPORT ConstraintCheckerInterface + { + public: + + typedef ConstraintCheckerInterface Self; + + typedef double PenaltyValueType; + typedef itk::Array PenaltyArrayType; + typedef itk::Array SignalType; + typedef ModelBase::ParametersType ParametersType; + + /** Returns the penalties for all defined constraints. + * @pre defined constraints must address valid parameters in the passed parameters set. + * @post the result vector has the size given by GetNumberOfConstraints(). + */ + virtual PenaltyArrayType GetPenalties(const ParametersType ¶meters) const = 0; + + /** Returns the sum of all penalties. + * @pre defined constraints must address valid parameters in the passed parameters set. + */ + virtual PenaltyValueType GetPenaltySum(const ParametersType ¶meters) const = 0; + + /** Returns the number of defined constraints, that will be checked. Thus also the size of the penalty vector.*/ + virtual unsigned int GetNumberOfConstraints() const = 0; + + /** Returns the penalty value that indicates at least one failed constrained.*/ + virtual PenaltyValueType GetFailedConstraintValue() const = 0; + + protected: + + ConstraintCheckerInterface() + {} + + virtual ~ConstraintCheckerInterface() + {} + + private: + ConstraintCheckerInterface(const ConstraintCheckerInterface& source); + void operator=(const ConstraintCheckerInterface&); //purposely not implemented + }; + +} + +#endif // MODELFITCOSTFUNCTION_H diff --git a/Modules/ModelFit/include/mitkDummyModelFitFunctor.h b/Modules/ModelFit/include/mitkDummyModelFitFunctor.h new file mode 100644 index 0000000000..ca9c086126 --- /dev/null +++ b/Modules/ModelFit/include/mitkDummyModelFitFunctor.h @@ -0,0 +1,80 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __DUMMYMODELFITFUNCTOR_H +#define __DUMMYMODELFITFUNCTOR_H + +#include + +#include "mitkModelBase.h" +#include "mitkModelFitFunctorBase.h" +#include "mitkMVConstrainedCostFunctionDecorator.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT DummyModelFitFunctor : public ModelFitFunctorBase + { + public: + typedef DummyModelFitFunctor Self; + typedef ModelFitFunctorBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkNewMacro(Self); + itkTypeMacro(DummyModelFitFunctor, ModelFitFunctorBase); + + typedef Superclass::InputPixelArrayType InputPixelArrayType; + typedef Superclass::OutputPixelArrayType OutputPixelArrayType; + + itkSetMacro(DerivativeStepLength, double); + itkGetMacro(DerivativeStepLength, double); + + virtual ParameterNamesType GetCriterionNames() const; + + protected: + + typedef Superclass::ParametersType ParametersType; + typedef Superclass::SignalType SignalType; + + DummyModelFitFunctor(); + + ~DummyModelFitFunctor(); + + virtual ParametersType DoModelFit(const SignalType& value, const ModelBase* model, + const ModelBase::ParametersType& initialParameters, + DebugParameterMapType& debugParameters) const; + + virtual OutputPixelArrayType GetCriteria(const ModelBase* model, const ParametersType& parameters, + const SignalType& sample) const; + + /** Generator function that instantiates and parameterizes the cost function that should be used by the fit functor*/ + virtual MVModelFitCostFunction::Pointer GenerateCostFunction(const SignalType& value, + const ModelBase* model) const; + + virtual ParameterNamesType DefineDebugParameterNames() const; + + private: + double m_DerivativeStepLength; + + }; + +} + + +#endif // __DUMMYMODELFITFUNCTOR_H diff --git a/Modules/ModelFit/include/mitkExtractTimeGrid.h b/Modules/ModelFit/include/mitkExtractTimeGrid.h new file mode 100644 index 0000000000..90cfdb9530 --- /dev/null +++ b/Modules/ModelFit/include/mitkExtractTimeGrid.h @@ -0,0 +1,44 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_EXTRACT_TIME_GRID_H_ +#define __MITK_EXTRACT_TIME_GRID_H_ + +#include + +#include +#include + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /*Extracts the time grid of an image (its time geometry) for usage with models. + * Time grid is empty (size == 0) if image pointer is invalid. + * @remark the model time grid has a resolution in sec and not ms like the time geometry.*/ + MITKMODELFIT_EXPORT ModelBase::TimeGridType ExtractTimeGrid(const Image* image); + + /*Extracts the time grid of a time geometry for usage with models. + * Time grid is empty (size == 0) if geometry pointer is invalid. + * @remark the model time grid has a resolution in sec and not ms like the time geometry.*/ + MITKMODELFIT_EXPORT ModelBase::TimeGridType ExtractTimeGrid(const TimeGeometry* geometry); + +} + +#endif diff --git a/Modules/ModelFit/include/mitkFormulaParser.h b/Modules/ModelFit/include/mitkFormulaParser.h new file mode 100644 index 0000000000..5ad3b291c8 --- /dev/null +++ b/Modules/ModelFit/include/mitkFormulaParser.h @@ -0,0 +1,111 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITKFORMULAPARSER_H__ +#define __MITKFORMULAPARSER_H__ + +#include +#include + +#include "mitkExceptionMacro.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /*! + * @brief Exception class for all exceptions that are generated in the FormulaParser module. + */ + class MITKMODELFIT_EXPORT FormulaParserException : public mitk::Exception + { + public: + mitkExceptionClassMacro(FormulaParserException, mitk::Exception); + }; + + + /*! + * @brief This class offers the functionality to evaluate simple mathematical formula + * strings (e.g. "3.5 + 4 * x * sin(x) - 1 / 2"). + * @details Internally it utilizes the @c boost::spirit framework with the @ref Grammar + * structure to parse the input string into a valid result number. + * Function strings (e.g. @c "sin", @c "tan" or @c "abs") are translated to + * actual function calls and variables (e.g. @c "x", @c "myVariable", "amount_") + * are replaced by their currently assigned value via a look-up table. + * + * The parser is able to recognize: + * @li sums, differences, products and divisions (a + b, + * 4 - 3, 2 * x, 9 / 3) + * @li algebraic signs (@c +5, @c -5) + * @li exponentiation (2 ^ 4) + * @li parentheses (3 * (4 + 2)) + * @li variables (@c x, @c myVar, @c test2_var_) + * @li the following unary functions: @c abs, @c exp, @c sin, @c cos, @c tan, + * @c sind (sine in degrees), @c cosd (cosine in degrees), @c tand (tangent in + * degrees) + * + * In order to use the FormulaParser you just have to initialize it with a map of + * variables (i.e. a look-up table where @c "x" is assigned to @c 5 for example and + * @c "y" is assigned to @c 13 and so on) and then call the + * @ref FormulaParser::parse function with the string that should be evaluated. Be + * sure to update the look-up table everytime a variable's value changes since that + * is not done automatically. + * + * @author Sascha Diatschuk + */ + class MITKMODELFIT_EXPORT FormulaParser + { + public: + using ValueType = double; + using VariableMapType = std::map; + /*! + * @brief Construct the FormulaParser and initialized the variables with + * @b variables. + * @param[in] variables A map of variables with values that will be assigned to the + * corresponding member variable. The map is delivered as a + * pointer so you can still change it from outside this class. + */ + FormulaParser(const VariableMapType* variables); + + /*! + * @brief Evaluates the @b input string and returns the resulting + * value. + * @param[in] input The string to be evaluated. + * @return The number that results from the evaluated string. + * @throw FormulaParserException If + * @li the parser comes across an unexpected character, + * @li a variable in the input string could not be found in the look-up + * table or + * @li the parser cannot apply the grammar to the string at all. + */ + ValueType parse(const std::string& input); + + /*! + * @brief Looks up the associated value of the given string @b var in the + * variables map. + * @param[in] var The name of the variable whose value is to be returned. + * @return The associated value of the given variable name. + * @throw FormulaParserException If the variable map is empty or the given variable name + * cannot be found. + */ + ValueType lookupVariable(const std::string var); + + private: + /*! @brief Map that holds the values that will replace the variables during evaluation. */ + const VariableMapType* m_Variables; + }; +} + +#endif diff --git a/Modules/ModelFit/include/mitkFresnel.h b/Modules/ModelFit/include/mitkFresnel.h new file mode 100644 index 0000000000..328de73873 --- /dev/null +++ b/Modules/ModelFit/include/mitkFresnel.h @@ -0,0 +1,57 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +/**************************************************************************** + * fresnel.h - + * Calculation of Fresnel integrals by expansion to Chebyshev series + * Expansions are taken from the book + * Y.L. Luke. Mathematical functions and their approximations. + * Ìoscow, "Mir", 1980. PP. 145-149 (Russian edition) + **************************************************************************** + */ + +#ifndef MITKFRESNEL_H_ +#define MITKFRESNEL_H_ + +namespace mitk +{ + + /* fresnel_c(x) - Fresnel Cosine Integral + * C(x)=fresnel_c(x)=\dint\limits_{0}^{x}\cos (\frac{\pi}{2}t^{2})dt + */ + double fresnel_c(double x); + + /* fresnel_s(x) - Fresnel Sine Integral + * S(x)=fresnel_s(x)=\dint\limits_{0}^{x}\sin (\frac{\pi}{2}t^{2})dt + */ + double fresnel_s(double x); + + /* Additional functions*/ + /* fresnel_c2(x) + * fresnel_c2(x)=fresnel_c(x*sqrt(2/pi))= + * = \sqrt{\frac{2}{\pi }}\dint\limits_{0}^{x}\cos (t^{2})dt + */ + double fresnel_c2(double x); + + /* fresnel_s2(x) + * fresnel_s2(x)=fresnel_s(x*sqrt(2/pi))= + * = \sqrt{\frac{2}{\pi }}\dint\limits_{0}^{x}\sin (t^{2})dt + */ + double fresnel_s2(double x); +} + +#endif /* FRESNEL_H_ */ + diff --git a/Modules/ModelFit/include/mitkGaussianNoiseFunctor.h b/Modules/ModelFit/include/mitkGaussianNoiseFunctor.h new file mode 100644 index 0000000000..d66ad9fdc5 --- /dev/null +++ b/Modules/ModelFit/include/mitkGaussianNoiseFunctor.h @@ -0,0 +1,86 @@ +#ifndef MITKGAUSSIANNOISEFUNCTOR_H +#define MITKGAUSSIANNOISEFUNCTOR_H + +#include +#include + +namespace mitk +{ + template + class GaussianNoiseFunctor + { + + public: + GaussianNoiseFunctor(): m_Mu(0), m_Sigma(0) {}; + ~GaussianNoiseFunctor() {}; + + void SetMean(double mu) + { + this->m_Mu = mu; + } + void SetSigma(double sigma) + { + this->m_Sigma = sigma; + } + + bool operator!=(const GaussianNoiseFunctor& other) const + { + return !(*this == other); + } + + bool operator==(const GaussianNoiseFunctor& other) const + { + return (this->m_Mu == other.m_Mu) && (this->m_Sigma == other.m_Sigma) ; + } + + inline TOutputPixel operator()(const TInputPixel& value) const + { + double n = noise(this->m_Mu, this->m_Sigma); + + TOutputPixel result = value + n; + + return result; + } + + private: + double m_Mu, m_Sigma; + + + /** @todo #2 Better function? + * This function is meant to generate a random number from a normal distribution with the passed mean and standard deviation. + * I found this code online, under c++11 there is supposed to be a std - libary for that: std::normal_distribution + **/ + inline double noise(double mu, double sigma) const + { + double u1, u2, W, mult; + static double x1, x2; + static int i = 0; + + if (i == 1) + { + i = !i; + return (mu + sigma * (double)x2); + } + + do + { + u1 = -1 + (static_cast (rand()) / static_cast (RAND_MAX)) * 2; + u2 = -1 + (static_cast (rand()) / static_cast (RAND_MAX)) * 2; + W = u1 * u1 + u2 * u2; + } + while (W >= 1 || W == 0); + + mult = sqrt((-2 * log(W)) / W); + x1 = u1 * mult; + x2 = u2 * mult; + + i = !i; + + return (mu + sigma * (double)x1); + + } + }; +} + + +#endif // MITKGAUSSIANNOISEFUNCTOR_H diff --git a/Modules/ModelFit/include/mitkGenericParamModel.h b/Modules/ModelFit/include/mitkGenericParamModel.h new file mode 100644 index 0000000000..7d6fb8a78e --- /dev/null +++ b/Modules/ModelFit/include/mitkGenericParamModel.h @@ -0,0 +1,112 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_GENERIC_PARAM_MODEL_H_ +#define __MITK_GENERIC_PARAM_MODEL_H_ + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /** Model that can parse a user specified function string and uses it as model function + that is represented by the model instance. + The parser used to interpret the string can handle simple mathematical formulas (e.g. "3.5 + a * x * sin(x) - 1 / 2"). + The parser is able to recognize: + - sums, differences, products and divisions (a + b, 4 - 3, 2 * x, 9 / 3) + - algebraic signs ( +5, -5) + - exponentiation ( 2 ^ 4 ) + - parentheses (3 * (4 + 2)) + - following unary functions: abs, exp, sin, cos, tan, sind (sine in degrees), cosd (cosine in degrees), tand (tangent in degrees) + - variables (x, a, b, ... j) + + Remark: The variable "x" is reserved. It is the signal position / timepoint. + Remark: The current version supports up to 10 model parameter. + Don't use it for a model parameter that should be deduced by fitting (these are a..j).*/ + class MITKMODELFIT_EXPORT GenericParamModel : public mitk::ModelBase + { + + public: + typedef GenericParamModel Self; + typedef mitk::ModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef Superclass::ParameterNameType ParameterNameType; + typedef Superclass::ParametersSizeType ParametersSizeType; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(GenericParamModel, ModelBase); + + static const std::string NAME_STATIC_PARAMETER_number; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual FunctionStringType GetFunctionString() const override; + itkSetStringMacro(FunctionString); + + /**@pre The Number of paremeters must be between 1 and 10.*/ + itkSetClampMacro(NumberOfParameters, ParametersSizeType, 1, 10); + + virtual std::string GetXName() const override; + + virtual ParameterNamesType GetParameterNames() const override; + + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParameterNamesType GetStaticParameterNames() const override; + + virtual ParametersSizeType GetNumberOfStaticParameters() const override; + + protected: + GenericParamModel(); + virtual ~GenericParamModel() {}; + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const; + + virtual void SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values); + virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const; + + private: + /**Function string that should be parsed when computing the model function.*/ + FunctionStringType m_FunctionString; + + /**Number of parameters the model should offer / the function string contains.*/ + ParametersSizeType m_NumberOfParameters; + + //No copy constructor allowed + GenericParamModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; +} + +#endif \ No newline at end of file diff --git a/Modules/ModelFit/include/mitkGenericParamModelFactory.h b/Modules/ModelFit/include/mitkGenericParamModelFactory.h new file mode 100644 index 0000000000..c487b37532 --- /dev/null +++ b/Modules/ModelFit/include/mitkGenericParamModelFactory.h @@ -0,0 +1,58 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __GENERIC_PARAM_MODEL_FACTORY_H +#define __GENERIC_PARAM_MODEL_FACTORY_H + +#include + +#include "mitkConcreteModelFactoryBase.h" +#include "mitkGenericParamModel.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT GenericParamModelFactory : public + ConcreteModelFactoryBase + { + public: + mitkClassMacroItkParent(GenericParamModelFactory, ConcreteModelFactoryBase); + itkFactorylessNewMacro(Self); + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const override; + + protected: + virtual ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit) + const override; + + GenericParamModelFactory(); + + virtual ~GenericParamModelFactory(); + + private: + + //No copy constructor allowed + GenericParamModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + + +#endif //__GENERIC_PARAM_MODEL_FACTORY_H diff --git a/Modules/ModelFit/include/mitkGenericParamModelParameterizer.h b/Modules/ModelFit/include/mitkGenericParamModelParameterizer.h new file mode 100644 index 0000000000..e52f90b7cb --- /dev/null +++ b/Modules/ModelFit/include/mitkGenericParamModelParameterizer.h @@ -0,0 +1,83 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef __GENERIC_PARAM_MODEL_PARAMETERIZER_H +#define __GENERIC_PARAM_MODEL_PARAMETERIZER_H + +#include "mitkConcreteModelParameterizerBase.h" +#include "mitkGenericParamModel.h" + +namespace mitk +{ + /** Parameterizer for the GenricParamModel. + */ + class MITKMODELFIT_EXPORT GenericParamModelParameterizer : public ConcreteModelParameterizerBase + + { + public: + typedef GenericParamModelParameterizer Self; + typedef ConcreteModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(GenericParamModelParameterizer, ConcreteModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef typename Superclass::ModelBaseType ModelBaseType; + typedef typename Superclass::ModelBasePointer ModelBasePointer; + + typedef typename Superclass::ModelType ModelType; + typedef typename Superclass::ModelPointer ModelPointer; + + typedef typename Superclass::StaticParameterValueType StaticParameterValueType; + typedef typename Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef typename Superclass::StaticParameterMapType StaticParameterMapType; + + + typedef typename Superclass::IndexType IndexType; + + itkSetMacro(FunctionString, mitk::ModelBase::FunctionStringType); + + /**@pre The Number of paremeters must be between 1 and 10.*/ + itkSetClampMacro(NumberOfParameters, ParametersSizeType, 1, 10); + + virtual mitk::ModelBase::FunctionStringType GetFunctionString() const override; + + using Superclass::GenerateParameterizedModel; + virtual ModelBasePointer GenerateParameterizedModel(const IndexType& currentPosition) const; + + virtual StaticParameterMapType GetGlobalStaticParameters() const override; + + virtual ParametersType GetDefaultInitialParameterization() const override; + + protected: + + GenericParamModelParameterizer(); + virtual ~GenericParamModelParameterizer(); + + mitk::ModelBase::FunctionStringType m_FunctionString; + + /**Number of parameters the model should offer / the function string contains.*/ + ParametersSizeType m_NumberOfParameters; + + private: + + //No copy constructor allowed + GenericParamModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; + +} +#endif // __GENERIC_PARAM_MODEL_PARAMETERIZER_H diff --git a/Modules/ModelFit/include/mitkIModelFitProvider.h b/Modules/ModelFit/include/mitkIModelFitProvider.h new file mode 100644 index 0000000000..9e32e804dc --- /dev/null +++ b/Modules/ModelFit/include/mitkIModelFitProvider.h @@ -0,0 +1,107 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __I_MODEL_FIT_PROVIDER_H +#define __I_MODEL_FIT_PROVIDER_H + +#include +#include + +#include "MitkModelFitExports.h" + +namespace mitk +{ + class ModelFactoryBase; + namespace modelFit + { + class ModelFitInfo; + } +} + +namespace itk +{ + template + class SmartPointer; +} + +namespace mitk +{ + /** + * \ingroup MicroServices_Interfaces + * + * \brief The common interface for all model providers for model fitting. + * + * Implementations of this interface must be registered as a service + * to make themselves available via the service registry. + * + * It is recommended to derive new implementations from ModelFitProviderBase or + * from AbstractFileIO (if both reader and writer is implemented), + * which provide correct service registration semantics. + * + * \sa ModelFitProviderBase + */ + struct MITKMODELFIT_EXPORT IModelFitProvider + { + virtual ~IModelFitProvider(); + + /** + * \brief returns a factory instance for the model represented by the provider. + */ + virtual itk::SmartPointer GenerateFactory() const = 0; + + /** + * @param fitInfo Pointer to a fit info instance for the respective model. + * + * This methods returns the values of the model variable that was used by the fit. + * Normally it is a time grid directly extracted from the input image time geometry. + * But depending on the model and fit it could be generated out of other properties. + * This method is a.o. used when the fit should be plotted correctly. + */ + virtual ModelBase::TimeGridType GetVariableGrid(const modelFit::ModelFitInfo* fitInfo) const = 0; + + /** + * @brief Service property name for a description. + * + * The property value must be of type \c std::string. + * + * @return The property name. + */ + static std::string PROP_DESCRIPTION(); + + /** + * @brief Service property name for the model ID handled by the provider. + * + * The property value must be of type \c std::string. + * + * @return The property name. + */ + static std::string PROP_MODEL_CLASS_ID(); + + /** + * @brief Service property name for the model type of the model handled by the provider. + * + * The property value must be of type \c std::string. + * + * @return The property name. + */ + static std::string PROP_MODEL_TYPE(); + }; + +} // namespace mitk + +MITK_DECLARE_SERVICE_INTERFACE(mitk::IModelFitProvider, "org.mitk.IModelFitProvider") + +#endif /* __I_MODEL_FIT_PROVIDER_H */ diff --git a/Modules/ModelFit/include/mitkIModelProvider.h b/Modules/ModelFit/include/mitkIModelProvider.h new file mode 100644 index 0000000000..5d5ea04aea --- /dev/null +++ b/Modules/ModelFit/include/mitkIModelProvider.h @@ -0,0 +1,117 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __I_MODEL_FIT_PROVIDER_H +#define __I_MODEL_FIT_PROVIDER_H + + +#include + +namespace mitk +{ + class BaseData; +} + +namespace itk +{ + template + class SmartPointer; +} + +namespace mitk +{ + /** + * \ingroup MicroServices_Interfaces + * + * \brief The common interface for all providers of models for fitting in mitk. + * + * Implementations of this interface must be registered as a service + * to make themselve available via the service registry. If the + * implementation is state-full, the service should be registered using + * a PrototypeServiceFactory. + * + * It is recommended to derive new implementations from ModelFitProviderBase, + * which provide correct service registration semantics. + * + * \sa ModelFitProviderBase + */ + struct MITKCORE_EXPORT IFileReader : public IFileIO + { + virtual ~IFileReader(); + + /** + * \brief Set the input location. + * \param location The file name to read from. + */ + virtual void SetInput(const std::string &location) = 0; + + /** + * @brief Set an input stream to read from. + * @param location A custom label for the input stream. + * @param is The input stream. + * + * If \c is is \c NULL, this clears the current input stream and \c location + * is interpreted as a file-system path. Otherwise, \c location is a custom + * label describing the input stream \c is. + */ + virtual void SetInput(const std::string &location, std::istream *is) = 0; + + /** + * @brief Get the current input location. + * @return The input location. + */ + virtual std::string GetInputLocation() const = 0; + + /** + * @brief Get the input stream. + * @return The currently set input stream. + */ + virtual std::istream *GetInputStream() const = 0; + + /** + * \brief Reads the specified file or input stream and returns its contents. + * + * \return A list of created BaseData objects. + * + * If GetInputStream() returns a non-null value, this method must use + * the returned stream object to read the data from. If no input stream + * was set, the data must be read from the path returned by GetInputLocation(). + * + * \throws mitk::Exception + */ + virtual std::vector> Read() = 0; + + /** + * \brief Reads the specified file or input stream, loading its + * contents into the provided DataStorage. + * + * \param ds The DataStorage to which the data is added. + * \return The set of added DataNodes to \c ds. + * + * This method may be overridden by implementations to create or + * reconstructed a hierarchy of mitk::DataNode instances in the + * provided mitk::DataStorage. + * + * \throws mitk::Exception + */ + virtual DataStorage::SetOfObjects::Pointer Read(mitk::DataStorage &ds) = 0; + }; + +} // namespace mitk + +MITK_DECLARE_SERVICE_INTERFACE(mitk::IFileReader, "org.mitk.IFileReader") + +#endif /* IFileReader_H_HEADER_INCLUDED_C1E7E521 */ diff --git a/Modules/ModelFit/include/mitkImageBasedParameterizationDelegate.h b/Modules/ModelFit/include/mitkImageBasedParameterizationDelegate.h new file mode 100644 index 0000000000..0066bc6156 --- /dev/null +++ b/Modules/ModelFit/include/mitkImageBasedParameterizationDelegate.h @@ -0,0 +1,69 @@ +#ifndef MITKIMAGEBASEDPARAMETERIZATIONDELEGATE_H +#define MITKIMAGEBASEDPARAMETERIZATIONDELEGATE_H + +#include "mitkValueBasedParameterizationDelegate.h" +#include +#include + +#include "mitkModelBase.h" +#include "mitkImage.h" +#include "mitkModelTraitsInterface.h" + +#include "MitkModelFitExports.h" + +namespace mitk { + +class MITKMODELFIT_EXPORT ImageBasedParameterizationDelegate : public ValueBasedParameterizationDelegate +{ +public: + + typedef ImageBasedParameterizationDelegate Self; + typedef ValueBasedParameterizationDelegate Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + itkTypeMacro(ImageBasedParameterizationDelegate, InitialParameterizationDelegateBase); + + typedef Superclass::ModelBaseType ModelBaseType; + + typedef Superclass::ParametersType ParametersType; + + typedef Superclass::IndexType IndexType; + + /** Returns the parameterization (e.g. initial parametrization for fitting) that should be used. + If no ParameterizationDelegate is set (see SetInitialParameterizationDelegate()) it will just return + the result of GetInitialParameterization().*/ + virtual ParametersType GetInitialParameterization() const override; + virtual ParametersType GetInitialParameterization(const IndexType& currentPosition) const override; + + /** Adds an image as a source for the initial value of a parameter. + * @param image Pointer to the image that is the value source. + * @param paramIndex Indicates which parameter is defined by the source image. + * It equals the position in the return vector of GetInitialParameterization(). + * @remark setting an image for an index overwrites the value for this index set by + * SetInitialParameterization. + * @pre paramIndex must be in bound of the initial parametrization vector. + * @pre image must be a valid instance*/ + void AddInitialParameterImage(const mitk::Image* image, ParametersType::size_type paramIndex); +protected: + + typedef std::map ImageMapType; + ImageMapType m_ParameterImageMap; + + ImageBasedParameterizationDelegate(); + + virtual ~ImageBasedParameterizationDelegate(); + +private: + + //No copy constructor allowed + ImageBasedParameterizationDelegate(const Self& source); + void operator=(const Self&); //purposely not implemented +}; + +} +#endif // MITKTWOCXINITIALPARAMETERIZATIONDELEGATE_H diff --git a/Modules/ModelFit/include/mitkIndexedValueFunctorBase.h b/Modules/ModelFit/include/mitkIndexedValueFunctorBase.h new file mode 100644 index 0000000000..aabc270e7c --- /dev/null +++ b/Modules/ModelFit/include/mitkIndexedValueFunctorBase.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef IndexedValueFunctorBase_H +#define IndexedValueFunctorBase_H + +#include +#include +#include + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /**Functor base class for functors that use the index and/or input value + to generate the output. + This class is used in conjunction with IndexedValueFunctorPolicy and + the itkMultiOutputNaryFunctorImageFilter. */ + class MITKMODELFIT_EXPORT IndexedValueFunctorBase: public ::itk::Object + { + public: + typedef IndexedValueFunctorBase Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(IndexedValueFunctorBase, itk::Object); + + typedef ScalarType InputImagePixelType; + typedef std::vector InputPixelVectorType; + typedef std::vector OutputPixelVectorType; + + typedef itk::Array GridArrayType; + typedef itk::Index<3> IndexType; + + virtual OutputPixelVectorType Compute(const InputPixelVectorType & value, const IndexType& currentIndex) const = 0; + + virtual unsigned int GetNumberOfOutputs() const = 0; + + protected: + + IndexedValueFunctorBase() + {}; + + ~IndexedValueFunctorBase() + {}; + + }; + +} + + +#endif // IndexedValueFunctorBase_H diff --git a/Modules/ModelFit/include/mitkIndexedValueFunctorPolicy.h b/Modules/ModelFit/include/mitkIndexedValueFunctorPolicy.h new file mode 100644 index 0000000000..0abf293e82 --- /dev/null +++ b/Modules/ModelFit/include/mitkIndexedValueFunctorPolicy.h @@ -0,0 +1,63 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef IndexedValueFunctorPolicy_H +#define IndexedValueFunctorPolicy_H + +#include "itkIndex.h" +#include "mitkIndexedValueFunctorBase.h" +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT IndexedValueFunctorPolicy + { + public: + typedef IndexedValueFunctorBase FunctorType; + typedef IndexedValueFunctorBase::ConstPointer FunctorConstPointer; + + typedef FunctorType::InputPixelVectorType InputPixelVectorType; + typedef FunctorType::OutputPixelVectorType OutputPixelVectorType; + typedef InputPixelVectorType InputPixelArrayType; + + typedef FunctorType::IndexType IndexType; + typedef std::vector OutputPixelArrayType; + + IndexedValueFunctorPolicy(); + + ~IndexedValueFunctorPolicy(); + + unsigned int GetNumberOfOutputs() const; + + void SetFunctor(const FunctorType *functor); + + + bool operator!=(const IndexedValueFunctorPolicy & other) const; + + bool operator==(const IndexedValueFunctorPolicy & other) const; + + OutputPixelVectorType operator()(const InputPixelVectorType & value, const IndexType& currentIndex) const; + + private: + + FunctorConstPointer m_Functor; + }; + +} + + +#endif // IndexedValueFunctorPolicy_H diff --git a/Modules/ModelFit/include/mitkInitialParameterizationDelegateBase.h b/Modules/ModelFit/include/mitkInitialParameterizationDelegateBase.h new file mode 100644 index 0000000000..787c845d14 --- /dev/null +++ b/Modules/ModelFit/include/mitkInitialParameterizationDelegateBase.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __INITIAL_PARAMETERIZATION_DELEGATE_BASE_H +#define __INITIAL_PARAMETERIZATION_DELEGATE_BASE_H + +#include +#include + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /** Base class for all initial parametrization delegates + * These delegates are used to define custom strategies, which are used by model parameterizers + * to determine the initial parametrization of a model (e.g. starting parameter for fitting). + */ + class MITKMODELFIT_EXPORT InitialParameterizationDelegateBase : public itk::Object + { + public: + typedef InitialParameterizationDelegateBase Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(InitialParameterizationDelegateBase, itk::Object); + + typedef ModelBase ModelBaseType; + + typedef ModelBaseType::ParametersType ParametersType; + + typedef ::itk::Index<3> IndexType; + + /** Returns the parameterization (e.g. initial parametrization for fitting) that should be used. + If no ParameterizationDelegate is set (see SetInitialParameterizationDelegate()) it will just return + the result of GetInitialParameterization().*/ + virtual ParametersType GetInitialParameterization() const = 0; + virtual ParametersType GetInitialParameterization(const IndexType& currentPosition) const = 0; + + protected: + + InitialParameterizationDelegateBase(); + + virtual ~InitialParameterizationDelegateBase(); + + private: + + //No copy constructor allowed + InitialParameterizationDelegateBase(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // __MODEL_PARAMETERIZER_BASE_H diff --git a/Modules/ModelFit/include/mitkLevenbergMarquardtModelFitFunctor.h b/Modules/ModelFit/include/mitkLevenbergMarquardtModelFitFunctor.h new file mode 100644 index 0000000000..6b61c6bca5 --- /dev/null +++ b/Modules/ModelFit/include/mitkLevenbergMarquardtModelFitFunctor.h @@ -0,0 +1,108 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef LEVENBERGMARQUARDTMODELFITFUNCTOR_H +#define LEVENBERGMARQUARDTMODELFITFUNCTOR_H + +#include +#include + +#include "mitkModelBase.h" +#include "mitkModelFitFunctorBase.h" +#include "mitkMVConstrainedCostFunctionDecorator.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT LevenbergMarquardtModelFitFunctor : public ModelFitFunctorBase + { + public: + typedef LevenbergMarquardtModelFitFunctor Self; + typedef ModelFitFunctorBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkNewMacro(Self); + itkTypeMacro(LevenbergMarquardtModelFitFunctor, ModelFitFunctorBase); + + typedef Superclass::InputPixelArrayType InputPixelArrayType; + typedef Superclass::OutputPixelArrayType OutputPixelArrayType; + + itkSetMacro(Epsilon, double); + itkSetMacro(GradientTolerance, double); + itkSetMacro(ValueTolerance, double); + itkSetMacro(DerivativeStepLength, double); + itkSetMacro(Iterations, unsigned int); + itkSetMacro(Scales, ::itk::LevenbergMarquardtOptimizer::ScalesType); + + itkGetMacro(Epsilon, double); + itkGetMacro(GradientTolerance, double); + itkGetMacro(ValueTolerance, double); + itkGetMacro(DerivativeStepLength, double); + itkGetMacro(Iterations, unsigned int); + itkGetMacro(Scales, ::itk::LevenbergMarquardtOptimizer::ScalesType); + + itkSetConstObjectMacro(ConstraintChecker, ConstraintCheckerBase); + itkGetConstObjectMacro(ConstraintChecker, ConstraintCheckerBase); + itkSetMacro(ActivateFailureThreshold, bool); + itkGetConstMacro(ActivateFailureThreshold, bool); + + virtual ParameterNamesType GetCriterionNames() const; + + protected: + + typedef Superclass::ParametersType ParametersType; + typedef Superclass::SignalType SignalType; + + LevenbergMarquardtModelFitFunctor(); + + ~LevenbergMarquardtModelFitFunctor(); + + virtual ParametersType DoModelFit(const SignalType& value, const ModelBase* model, + const ModelBase::ParametersType& initialParameters, + DebugParameterMapType& debugParameters) const; + + virtual OutputPixelArrayType GetCriteria(const ModelBase* model, const ParametersType& parameters, + const SignalType& sample) const; + + /** Generator function that instantiates and parameterizes the cost function that should be used by the fit functor*/ + virtual MVModelFitCostFunction::Pointer GenerateCostFunction(const SignalType& value, + const ModelBase* model) const; + + virtual ParameterNamesType DefineDebugParameterNames() const; + + private: + double m_Epsilon; + double m_GradientTolerance; + double m_ValueTolerance; + unsigned int m_Iterations; + double m_DerivativeStepLength; + ::itk::LevenbergMarquardtOptimizer::ScalesType m_Scales; + + /**Constraint checker. If set it will be used by the optimization strategies to add additional constraints to the + given cost function. */ + ConstraintCheckerBase::ConstPointer m_ConstraintChecker; + /**If set to true and an constraint checker is set. The cost function will allways fail if the penalty of the + checker reaches the threshold. In this case no function evaluation will be done-*/ + bool m_ActivateFailureThreshold; + }; + +} + + +#endif // MODEL_FIT_FUNCTOR_BASE_H diff --git a/Modules/ModelFit/include/mitkLinearModel.h b/Modules/ModelFit/include/mitkLinearModel.h new file mode 100644 index 0000000000..488f4fee79 --- /dev/null +++ b/Modules/ModelFit/include/mitkLinearModel.h @@ -0,0 +1,93 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_LINEAR_MODEL_H_ +#define __MITK_LINEAR_MODEL_H_ + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT LinearModel : public mitk::ModelBase + { + + public: + typedef LinearModel Self; + typedef mitk::ModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef Superclass::ParameterNameType ParameterNameType; + typedef Superclass::ParametersSizeType ParametersSizeType; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(LinearModel, ModelBase); + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual FunctionStringType GetFunctionString() const override; + + virtual std::string GetXName() const override; + + virtual ParameterNamesType GetParameterNames() const override; + + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParameterNamesType GetStaticParameterNames() const override; + + virtual ParametersSizeType GetNumberOfStaticParameters() const override; + + virtual ParameterNamesType GetDerivedParameterNames() const override; + + virtual ParametersSizeType GetNumberOfDerivedParameters() const override; + + protected: + LinearModel() {}; + virtual ~LinearModel() {}; + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const; + virtual DerivedParameterMapType ComputeDerivedParameters(const mitk::ModelBase::ParametersType& + parameters) const; + + virtual void SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values); + virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const; + + private: + + //No copy constructor allowed + LinearModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; +} + +#endif diff --git a/Modules/ModelFit/include/mitkLinearModelFactory.h b/Modules/ModelFit/include/mitkLinearModelFactory.h new file mode 100644 index 0000000000..6b686a24bb --- /dev/null +++ b/Modules/ModelFit/include/mitkLinearModelFactory.h @@ -0,0 +1,57 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __LINEAR_TEST_MODEL_FACTORY_H +#define __LINEAR_TEST_MODEL_FACTORY_H + +#include + +#include "mitkConcreteModelFactoryBase.h" +#include "mitkLinearModel.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT LinearModelFactory : public ConcreteModelFactoryBase + { + public: + mitkClassMacroItkParent(LinearModelFactory, ConcreteModelFactoryBase); + itkFactorylessNewMacro(Self); + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + virtual ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit) + const; + + LinearModelFactory(); + + virtual ~LinearModelFactory(); + + private: + + //No copy constructor allowed + LinearModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + + +#endif //__LINEAR_TEST_MODEL_FACTORY_H diff --git a/Modules/ModelFit/include/mitkLinearModelParameterizer.h b/Modules/ModelFit/include/mitkLinearModelParameterizer.h new file mode 100644 index 0000000000..cec8632d24 --- /dev/null +++ b/Modules/ModelFit/include/mitkLinearModelParameterizer.h @@ -0,0 +1,29 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __LINEAR_MODEL_PARAMETERIZER_H +#define __LINEAR_MODEL_PARAMETERIZER_H + +#include "mitkConcreteModelParameterizerBase.h" +#include "mitkLinearModel.h" + +namespace mitk +{ + + typedef ConcreteModelParameterizerBase LinearModelParameterizer; +} + +#endif // __LINEAR_MODEL_PARAMETERIZER_H diff --git a/Modules/ModelFit/include/mitkMVConstrainedCostFunctionDecorator.h b/Modules/ModelFit/include/mitkMVConstrainedCostFunctionDecorator.h new file mode 100644 index 0000000000..71749c771a --- /dev/null +++ b/Modules/ModelFit/include/mitkMVConstrainedCostFunctionDecorator.h @@ -0,0 +1,104 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MV_CONSTRAINED_COST_FUNCTION_DECORATOR_H +#define MV_CONSTRAINED_COST_FUNCTION_DECORATOR_H + +#include +#include + +#include "MitkModelFitExports.h" + +namespace mitk +{ + +/** \class MVConstrainedCostFunctionDecorator + * \brief This class is used to add constraints to any multi valued model fit cost function. + * + * MVConstrainedCostFunctionDecorator is used to extend a given cost function + * with the functionality to regard given constraints for the measure. + * To add this functionality to a cost function, instantiate the decorator, set + * the wrapped cost function (that will be extended) and set a constraint checker + * that defines the type of constraints.\n + * The decorator has a failure threshold. An evaluation + * can always be accounted as a failure if the sum of penalties given by the checker + * is greater or equal to the threshold. If the evaluation is a failure the wrapped cost function + * will not be evaluated. Otherwise the penalty will be added to every measure of the cost function. + */ +class MITKMODELFIT_EXPORT MVConstrainedCostFunctionDecorator : public mitk::MVModelFitCostFunction +{ +public: + + typedef MVConstrainedCostFunctionDecorator Self; + typedef mitk::MVModelFitCostFunction Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkNewMacro(Self); + + typedef Superclass::SignalType SignalType; + typedef ConstraintCheckerBase::PenaltyValueType PenaltyValueType; + + itkSetConstObjectMacro(WrappedCostFunction, MVModelFitCostFunction); + itkGetConstObjectMacro(WrappedCostFunction, MVModelFitCostFunction); + + itkSetConstObjectMacro(ConstraintChecker, ConstraintCheckerBase); + itkGetConstObjectMacro(ConstraintChecker, ConstraintCheckerBase); + + itkSetMacro(FailureThreshold, PenaltyValueType); + itkGetConstMacro(FailureThreshold, PenaltyValueType); + itkSetMacro(ActivateFailureThreshold, bool); + itkGetConstMacro(ActivateFailureThreshold, bool); + + /**Returns the number of evaluations done by the cost function instance + since creation.*/ + itkGetConstMacro(EvaluationCount, unsigned int); + + /**Returns the ration between evaluations that were penaltized and all evaluation since + creation of the instance. 0.0 means no evaluation was penalized; 1.0 all evaluations were. + (evaluations that hit the failure threshold count as penalized too.)*/ + double GetPenaltyRatio() const; + /**Returns the ration between evaluations that where beyond the failure thershold and all evaluation since + creation of the instance. 0.0 means no evaluation was a failure (but some may be penalized); + 1.0 all evaluations were failures.*/ + double GetFailureRatio() const; + + /**Returns the index of the first (in terms of index position) failed parameter in the last failed evaluation.*/ + ParametersType::size_type GetFailedParameter() const; +protected: + + virtual MeasureType CalcMeasure(const ParametersType ¶meters, const SignalType& signal) const; + + MVConstrainedCostFunctionDecorator() : m_FailureThreshold(1e6), m_ActivateFailureThreshold(true), + m_EvaluationCount(0), m_PenaltyCount(0), m_FailureCount(0), m_LastFailedParameter(-1) + { + } + + ~MVConstrainedCostFunctionDecorator(){} + + ConstraintCheckerBase::ConstPointer m_ConstraintChecker; + MVModelFitCostFunction::ConstPointer m_WrappedCostFunction; + PenaltyValueType m_FailureThreshold; + bool m_ActivateFailureThreshold; + mutable unsigned int m_EvaluationCount; + mutable unsigned int m_PenaltyCount; + mutable unsigned int m_FailureCount; + mutable ParametersType::size_type m_LastFailedParameter; +}; + +} + +#endif diff --git a/Modules/ModelFit/include/mitkMVModelFitCostFunction.h b/Modules/ModelFit/include/mitkMVModelFitCostFunction.h new file mode 100644 index 0000000000..dc3a02a8e4 --- /dev/null +++ b/Modules/ModelFit/include/mitkMVModelFitCostFunction.h @@ -0,0 +1,82 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MV_MODELFITCOSTFUNCTION_H +#define MV_MODELFITCOSTFUNCTION_H + +#include +#include + +#include "mitkModelFitCostFunctionInterface.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + +/** Base class for all model fit cost function that return a multiple cost value + * It offers also a default implementation for the numerical computation of the + * derivatives. Normaly you just have to (re)implement CalcMeasure(). +*/ +class MITKMODELFIT_EXPORT MVModelFitCostFunction : public itk::MultipleValuedCostFunction, public ModelFitCostFunctionInterface +{ +public: + + typedef MVModelFitCostFunction Self; + typedef itk::MultipleValuedCostFunction Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef ModelFitCostFunctionInterface::SignalType SignalType; + typedef Superclass::MeasureType MeasureType; + typedef Superclass::DerivativeType DerivativeType; + + void SetSample(const SignalType &sampleSet); + + MeasureType GetValue(const ParametersType& parameter) const; + void GetDerivative (const ParametersType ¶meters, DerivativeType &derivative) const; + + unsigned int GetNumberOfValues (void) const; + unsigned int GetNumberOfParameters (void) const; + + itkSetConstObjectMacro(Model, ModelBase); + itkGetConstObjectMacro(Model, ModelBase); + + itkSetMacro(DerivativeStepLength, double); + itkGetConstMacro(DerivativeStepLength, double); + +protected: + + virtual MeasureType CalcMeasure(const ParametersType ¶meters, const SignalType& signal) const = 0; + + MVModelFitCostFunction() : m_DerivativeStepLength(1e-5) + { + } + + ~MVModelFitCostFunction(){} + + SignalType m_Sample; + +private: + ModelBase::ConstPointer m_Model; + + /**value (delta of parameters) used to compute the derivatives numerically*/ + double m_DerivativeStepLength; +}; + +} + +#endif // MVModelFitCostFunction_H diff --git a/Modules/ModelFit/include/mitkMaskedDynamicImageStatisticsGenerator.h b/Modules/ModelFit/include/mitkMaskedDynamicImageStatisticsGenerator.h new file mode 100644 index 0000000000..4e02e9648e --- /dev/null +++ b/Modules/ModelFit/include/mitkMaskedDynamicImageStatisticsGenerator.h @@ -0,0 +1,88 @@ +/*=================================================================== + + The Medical Imaging Interaction Toolkit (MITK) + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. + + See LICENSE.txt or http://www.mitk.org for details. + + ===================================================================*/ + +#ifndef __MITK_MASKED_DYMAMIC_IMAGE_STATISTICS_GENERATOR_H +#define __MITK_MASKED_DYMAMIC_IMAGE_STATISTICS_GENERATOR_H + +#include + +#include "MitkModelFitExports.h" + +namespace mitk +{ +/** Simple mitk based wrapper for the itk::MaskedNaryStatisticsImageFilter. + * takes an input image and a mask image (both mitk::Images) and calculates the statistic + * of the input image within the given mask (every pixel != 0).\n + * The class assumes that the mask image is 3D (only one time step), if this is not the case + * *only* the first time step will be used as mask.\n + * If the input image has multiple time steps, the statistics will be calculated for each time + * step. This the result arrays will always have as many values as the input image + * has time steps.*/ +class MITKMODELFIT_EXPORT MaskedDynamicImageStatisticsGenerator : public itk::Object +{ +public: + mitkClassMacroItkParent(MaskedDynamicImageStatisticsGenerator, itk::Object); + + itkNewMacro(Self); + + typedef itk::Array ResultType; + + itkSetConstObjectMacro(DynamicImage,Image); + itkGetConstObjectMacro(DynamicImage,Image); + + itkSetConstObjectMacro(Mask, Image); + itkGetConstObjectMacro(Mask, Image); + + const ResultType& GetMaximum(); + const ResultType& GetMinimum(); + const ResultType& GetMean(); + const ResultType& GetSigma(); + const ResultType& GetVariance(); + const ResultType& GetSum(); + + void Generate(); + +protected: + MaskedDynamicImageStatisticsGenerator(); + ~MaskedDynamicImageStatisticsGenerator(); + + template + void DoCalculateStatistics(const itk::Image* image); + + virtual void CheckValidInputs() const; + + bool HasOutdatedResults() const; + + itk::TimeStamp m_GenerationTimeStamp; + +private: + Image::ConstPointer m_DynamicImage; + Image::ConstPointer m_Mask; + + typedef itk::Image InternalMaskType; + InternalMaskType::ConstPointer m_InternalMask; + + ResultType m_Maximum; + ResultType m_Minimum; + ResultType m_Mean; + ResultType m_Sigma; + ResultType m_Variance; + ResultType m_Sum; +}; + +} + +#endif // ATERIALINPUTFUNCTIONGENERATOR_H diff --git a/Modules/ModelFit/include/mitkModelBase.h b/Modules/ModelFit/include/mitkModelBase.h new file mode 100644 index 0000000000..939801627b --- /dev/null +++ b/Modules/ModelFit/include/mitkModelBase.h @@ -0,0 +1,217 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MODELBASE_H +#define MODELBASE_H + +#include + +#include +#include +#include + +#include "MitkModelFitExports.h" +#include "mitkModelTraitsInterface.h" + +namespace mitk +{ + /**@class ModelBase + * @brief Base class for (dynamic) models. + * A model can be used to calculate its signal given the discrete time grid of the signal + * and the parameters of the model.\n + * A model has 3 types of parameters:\n + * - parameters + * - static parameters + * - derived parameters + * . + * "Parameters" and "static parameters" are used to compute the signal of the model. + * "Parameters" are the ones that will be changed for/by model fitting. + * "Static parameters" are used to configure the model for fitting but are itself not + * part of the fitting scope (compare itk::Transform parameters and static parameters). + * "Derived parameters" are model specific parameters computed from "Parameters" e.g. (DerivedParam1 = Param1/Param2). + * It may be implemented if e.g. for practical usage not the fitted parameters are needed but + * derivation of them. + * @remark: If you implement your own model calls regard const correctness and do not change + * or undermine the constness of this base class. It is important because in case of fitting + * models are used in a multi threaded environment and must be thread safe. Thus the getter and + * computation functions are implemented as const and thread safe methods.*/ + class MITKMODELFIT_EXPORT ModelBase : public itk::Object, public ModelTraitsInterface + { + public: + typedef ModelBase Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ModelBase, itk::Object); + + typedef ModelTraitsInterface::ModelResultType ModelResultType; + typedef ModelTraitsInterface::ParameterValueType ParameterValueType; + typedef ModelTraitsInterface::ParametersType ParametersType; + /** Type defining the time grid used be models. + * @remark the model time grid has a resolution in sec and not like the time geometry which uses ms.*/ + typedef itk::Array TimeGridType; + typedef ModelTraitsInterface::ParameterNameType ParameterNameType; + typedef ModelTraitsInterface::ParameterNamesType ParameterNamesType; + typedef ModelTraitsInterface::ParametersSizeType ParametersSizeType; + + typedef ModelTraitsInterface::DerivedParameterNamesType DerivedParameterNamesType; + typedef ModelTraitsInterface::DerivedParametersSizeType DerivedParametersSizeType; + + typedef double StaticParameterValueType; + typedef std::vector StaticParameterValuesType; + typedef std::map StaticParameterMapType; + + typedef double DerivedParameterValueType; + typedef std::map DerivedParameterMapType; + + /**Default implementation returns a scale of 1.0 for every defined parameter.*/ + virtual ParamterScaleMapType GetParameterScales() const; + + /**Default implementation returns no unit string ("") for every defined parameter.*/ + virtual ParamterUnitMapType GetParameterUnits() const; + + /**Default implementation returns a scale of 1.0 for every defined derived parameter.*/ + virtual DerivedParamterScaleMapType GetDerivedParameterScales() const; + + /**Default implementation returns no unit string ("") for every defined derived parameter.*/ + virtual DerivedParamterUnitMapType GetDerivedParameterUnits() const; + + /**Default implementation returns GetClassID as display name.*/ + virtual std::string GetModelDisplayName() const; + + /**Default implementation returns "Unkown" as model type.*/ + virtual std::string GetModelType() const; + + /**Default implementation returns an empty functions string.*/ + virtual FunctionStringType GetFunctionString() const; + + /**Default implementation the class name of the concrete instance as ID.*/ + virtual ModellClassIDType GetClassID() const; + + /**Default implementation returns an empty string.*/ + virtual std::string GetXName() const; + + /**Default implementation returns an empty string.*/ + virtual std::string GetXAxisName() const; + + /**Default implementation returns an empty string.*/ + virtual std::string GetXAxisUnit() const; + + /**Default implementation returns an empty string.*/ + virtual std::string GetYAxisName() const; + + /**Default implementation returns an empty string.*/ + virtual std::string GetYAxisUnit() const; + + /** Returns the names of static parameters that will be used when using + * the model to compute the signal (but are not defined via GetSignal()).*/ + virtual ParameterNamesType GetStaticParameterNames() const = 0; + /** Returns the number of static parameters that will be used when using + * the model to compute the signal (but are not defined via GetSignal()).*/ + virtual ParametersSizeType GetNumberOfStaticParameters() const = 0; + + /**Default implementation returns no unit string ("") for every defined parameter.*/ + virtual ParamterUnitMapType GetStaticParameterUnits() const; + + + /** Returns the names of derived parameters that can/will be computed by the model + * given specific model parameters. + * @remark Default implementation has no derived parameters*/ + virtual DerivedParameterNamesType GetDerivedParameterNames() const; + /** Returns the number of derived parameters that can/will be computed by the model + * given specific model parameters. + * @remark Default implementation has no derived parameters*/ + virtual DerivedParametersSizeType GetNumberOfDerivedParameters() const; + + /** Generic interface method that can be used to set the static parameters of the model + * before it is used. + * It checks the validity of the passed map and uses SetStaticParameter to set the values. + * @param parameters The map with the static parameters and their values. + * @param allParameters If true an exception will be thrown if the keys of passed parameters do + * not equal the return of GetStaticParameterNames. Thus if true, one must set all static + * parameters of the model. + * @pre Parameters must only contain keys that exist in GetStaticParameterNames() + * @pre If allParameters == true, parameters must define all keys of GetStaticParameterNames()*/ + void SetStaticParameters(const StaticParameterMapType& parameters, bool allParameters = true); + + /** Generic interface method that can be used to retrieve the static parameters of the model; + * e.g. in order to serialize the model settings. + * It calls GetStaticParameter for every name defined in GetStaticParameterNames().*/ + StaticParameterMapType GetStaticParameters() const; + + /** Generic interface method that computes all derived parameters implemented for the given models. + * To changed the derived parameter computation. ComputeDerivedParameters must be (re)implemented. + * @pre parameters must have the right size. + * @param parameters The parameters of the model for which the derived parameters should be computed. + * It calls GetStaticParameter for every name defined in GetStaticParameterNames(). + * @remark Default implementation has no derived parameters*/ + DerivedParameterMapType GetDerivedParameters(const ParametersType& parameters) const; + + /** Sets the time grid of the model. It indicates the time points correlated with the signal the modell should + produce. + @remark The resolution of the time grid is in seconds. (Not in ms like the mitk::TimeGeometry)*/ + virtual void SetTimeGrid(const TimeGridType& grid); + /** Gets the time grid of the model. It indicates the time points correlated with the signal the modell should + produce. + @remark The resolution of the time grid is in seconds. (Not in ms like the mitk::TimeGeometry)*/ + itkGetConstReferenceMacro(TimeGrid, TimeGridType); + + ModelResultType GetSignal(const ParametersType& parameters) const; + + protected: + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const = 0; + + /** Member is called by GetSignal() before ComputeModelfunction(). It indicates if model is in a valid state and + * ready to compute the signal. The default implementation checks nothing and always returns true. + * Reimplement to realize special behavior for derived classes. + * @param [out] error Set internally to indicate the error reason if method returns false. Is used by GetSignal() for the + * exception comment. + * @return Returns true if the model is valid and can compute a signal. Otherwise it returns false.*/ + virtual bool ValidateModel(std::string& error) const; + + /** Helper function called by GetDerivedParameters(). Implement in derived classes to realize + * the concrete computation of derived parameters. + * @remark Default implementation has no derived parameters*/ + virtual DerivedParameterMapType ComputeDerivedParameters(const ParametersType& parameters) const; + + /** Helper function called by SetStaticParameters(). Implement in derived classes to realize + * the concrete setting of static parameters.*/ + virtual void SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values) = 0; + /** Helper function called by GetStaticParameters(). Implement in derived classes to realize + * the concrete retrieval of static parameters.*/ + virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const = 0; + + ModelBase(); + virtual ~ModelBase(); + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const; + + //timeGrid in seconds + + TimeGridType m_TimeGrid; + + private: + + //No copy constructor allowed + ModelBase(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // MODELBASE_H diff --git a/Modules/ModelFit/include/mitkModelBasedValueFunctorBase.h b/Modules/ModelFit/include/mitkModelBasedValueFunctorBase.h new file mode 100644 index 0000000000..93be534fe5 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelBasedValueFunctorBase.h @@ -0,0 +1,62 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef ModelBasedValueFunctorBase_H +#define ModelBasedValueFunctorBase_H + +#include "mitkIndexedValueFunctorBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /**Functor base class for functors that are some how based on an model. + This abstract class adds the possibility to query the signal grid + of the model.*/ + class MITKMODELFIT_EXPORT ModelBasedValueFunctorBase: public IndexedValueFunctorBase + { + public: + typedef ModelBasedValueFunctorBase Self; + typedef IndexedValueFunctorBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ModelBasedValueFunctorBase, IndexedValueFunctorBase); + + typedef Superclass::InputImagePixelType InputImagePixelType; + typedef Superclass::InputPixelVectorType InputPixelVectorType; + typedef Superclass::OutputPixelVectorType OutputPixelVectorType; + typedef Superclass::IndexType IndexType; + + typedef itk::Array GridArrayType; + + virtual GridArrayType GetGrid() const = 0; + + protected: + + ModelBasedValueFunctorBase() + {}; + + ~ModelBasedValueFunctorBase() + {}; + + }; + +} + + +#endif // ModelBasedValueFunctorBase_H diff --git a/Modules/ModelFit/include/mitkModelDataGenerationFunctor.h b/Modules/ModelFit/include/mitkModelDataGenerationFunctor.h new file mode 100644 index 0000000000..53706e577b --- /dev/null +++ b/Modules/ModelFit/include/mitkModelDataGenerationFunctor.h @@ -0,0 +1,70 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKMODELDATAGENERATIONFUNCTOR_H +#define MITKMODELDATAGENERATIONFUNCTOR_H + +#include "mitkSimpleFunctorBase.h" +#include "mitkModelBase.h" +#include "mitkModelParameterizerBase.h" + +#include + +namespace mitk +{ + + /** Functor class that can be used to generate a model signal for each index. + This class assumes that value parameter passed in the Compute() call, + is the parameter vector that should be used to generate the model signal. + The time grid and the parameterized model are provided by the model + parameterizer. This this functor will generate a signal for each index position + and return the signal as output.*/ + class MITKMODELFIT_EXPORT ModelDataGenerationFunctor : public SimpleFunctorBase + { + public: + + typedef ModelDataGenerationFunctor Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkFactorylessNewMacro(Self); + itkTypeMacro(ModelDataGenerationFunctor, SimpleFunctorBase); + + typedef std::vector ParameterNamesType; + typedef ModelBase::ModelResultType SignalType; + typedef itk::Array ModelParametersType; + + itkSetConstObjectMacro(ModelParameterizer, ModelParameterizerBase); + itkGetConstObjectMacro(ModelParameterizer, ModelParameterizerBase); + + virtual SimpleFunctorBase::OutputPixelVectorType Compute(const InputPixelVectorType & value) const override; + + virtual unsigned int GetNumberOfOutputs() const override; + + virtual GridArrayType GetGrid() const override; + + protected: + ModelDataGenerationFunctor(); + virtual ~ModelDataGenerationFunctor(); + + private: + ModelParameterizerBase::ConstPointer m_ModelParameterizer; + + }; +} + +#endif // MITKMODELDATAGENERATIONFUNCTOR_H diff --git a/Modules/ModelFit/include/mitkModelFactoryBase.h b/Modules/ModelFit/include/mitkModelFactoryBase.h new file mode 100644 index 0000000000..8151746dfc --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFactoryBase.h @@ -0,0 +1,94 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MODEL_FACTORY_BASE_H +#define __MODEL_FACTORY_BASE_H + +#include + +#include "mitkModelBase.h" +#include "mitkModelTraitsInterface.h" +#include "mitkModelParameterizerBase.h" +#include "mitkModelFitInfo.h" +#include "mitkConstraintCheckerBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /**Base class for model factories. + * Default implementation just passes the model properties through from an instance created with add model. + * To use the the base class, derive and at least implement the abstract member functions. + */ + class MITKMODELFIT_EXPORT ModelFactoryBase : public itk::Object, public ModelTraitsInterface + { + public: + /*typedef ModelFactoryBase Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; +*/ + mitkClassMacroItkParent(ModelFactoryBase, itk::Object); + + typedef ModelBase ModelBaseType; + typedef ModelBaseType::Pointer ModelBasePointer; + + typedef ModelTraitsInterface::ParameterNameType ParameterNameType; + typedef ModelTraitsInterface::ParameterNamesType ParameterNamesType; + typedef ModelTraitsInterface::ParametersSizeType ParametersSizeType; + + typedef ModelTraitsInterface::ParamterScaleMapType ParamterScaleMapType; + typedef ModelTraitsInterface::ParamterUnitMapType ParamterUnitMapType; + typedef ModelTraitsInterface::FunctionStringType FunctionStringType; + typedef ModelTraitsInterface::ModellClassIDType ModellClassIDType; + + typedef ModelTraitsInterface::DerivedParameterNamesType DerivedParameterNamesType; + typedef ModelTraitsInterface::DerivedParametersSizeType DerivedParametersSizeType; + typedef ModelTraitsInterface::DerivedParamterScaleMapType DerivedParamterScaleMapType; + typedef ModelTraitsInterface::DerivedParamterUnitMapType DerivedParamterUnitMapType; + + virtual ModelBasePointer CreateModel() const = 0; + + /** Created a model parameterizer set up according to the passed model fit info. + @pre fit must point to a valid instance.*/ + ModelParameterizerBase::Pointer CreateParameterizer(const modelFit::ModelFitInfo* fit) const; + + /** Create the default constraints that should/can be used for fitting if nothing else + * is specified by the user. + * @return Pointer to the constraint checker for default constraints. May return a NULL pointer + * to indicated that the Model has no constraints by default. */ + virtual ConstraintCheckerBase::Pointer CreateDefaultConstraints() const = 0; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const = 0; + + protected: + virtual ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit) + const = 0; + + ModelFactoryBase(); + virtual ~ModelFactoryBase(); + + private: + + //No copy constructor allowed + ModelFactoryBase(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // __MODEL_FACTORY_BASE_H diff --git a/Modules/ModelFit/include/mitkModelFitCmdAppsHelper.h b/Modules/ModelFit/include/mitkModelFitCmdAppsHelper.h new file mode 100644 index 0000000000..948efb124a --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitCmdAppsHelper.h @@ -0,0 +1,60 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef _MITK_MODEL_FIT_CMD_APPS_HELPER_H_ +#define _MITK_MODEL_FIT_CMD_APPS_HELPER_H_ + +// std includes +#include + +// itk includes +#include "itksys/SystemTools.hxx" + +// MITK includes +#include +#include +#include +#include + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /** Helper function that generates the file path that would be used to store an result image. + The output path will be determined given the outputPathTemplate (which determines the directory, + the basic file name and the file formate). The output file name is: _.*/ + MITKMODELFIT_EXPORT std::string generateModelFitResultImagePath(const std::string& outputPathTemplate, const std::string& parameterName); + + /** Helper function that takes the given image and stores it based on a template path. + The real output path will be determined given the outputPathTemplate (which determines the directory, + the basic file name and the file formate). The output file name is: _.*/ + MITKMODELFIT_EXPORT void storeParameterResultImage(const std::string& outputPathTemplate, const std::string& parameterName, mitk::Image* image, mitk::modelFit::Parameter::Type parameterType = mitk::modelFit::Parameter::ParameterType); + + /** Helper function that takes the given image, sets its properties according to the fit session and stores it. + The output path will be determined given the outputPathTemplate (which determines the directory, + the basic file name and the file formate). The output file name is: _.*/ + MITKMODELFIT_EXPORT void storeModelFitResultImage(const std::string& outputPathTemplate, const std::string& parameterName, mitk::Image* image, mitk::modelFit::Parameter::Type nodeType, const mitk::modelFit::ModelFitInfo* modelFitInfo); + + /** Helper function that stores all results of the passed generator according to the passed outputPathTemplate. + For further information regarding the output file path, please see storeModelFitResultImage().*/ + MITKMODELFIT_EXPORT void storeModelFitGeneratorResults(const std::string& outputPathTemplate, mitk::ParameterFitImageGeneratorBase* generator, const mitk::modelFit::ModelFitInfo* fitSession); + + /** Helper function that outputs on the std::cout the result images the generator would produces.*/ + MITKMODELFIT_EXPORT void previewModelFitGeneratorResults(const std::string& outputPathTemplate, mitk::ParameterFitImageGeneratorBase* generator); + +} +#endif diff --git a/Modules/ModelFit/include/mitkModelFitConstants.h b/Modules/ModelFit/include/mitkModelFitConstants.h new file mode 100644 index 0000000000..ccc300e864 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitConstants.h @@ -0,0 +1,204 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef _MITK_MODEL_FIT_CONSTANTS_H_ +#define _MITK_MODEL_FIT_CONSTANTS_H_ + +#include + +#include "MitkModelFitExports.h" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +namespace mitk +{ + struct MITKMODELFIT_EXPORT ModelFitConstants + { + /** + * Name of the "root" property for all information concerning model fitting. + */ + static const std::string MODEL_FIT_PROPERTY_NAME(); + + /** + * Name of the "uid" property for all data objects concerning model fitting. + */ + static const std::string UID_PROPERTY_NAME(); + + /** + * modelfit.input.variables ist eine Map der Variablennamen, die einem Eingabebild zu eigen sind und + * unabhängig von einem Fit sind. + * Deren Wert ist ein Array, welches die Variablenwerte für die einzelnen Zeitschritte enthält. + * Die Länge eines solchen Arrays muss entweder der Anzahl der Zeitschritte dieses Bildes entsprechen + * oder genau 1 sein, wenn der Wert für alle Zeitschritte dieses Bildes gleich ist. + * Beispiele: + * ["x1":[580], "x2":[3060], "x3":[41]] (1 Zeitschritt, 3 Variablen) + * ["TE":[2.47, 5.85, 9.23, 12.61], "TI":[10.3]] (4 Zeitschritte, 2 Variablen) + */ + static const std::string INPUT_VARIABLES_PROPERTY_NAME(); + + /** + * modelfit.parameter.name ist der Bezeichner des Parameters, wie es im Funktions-String (modelfit.model.function) vorkommt. + */ + static const std::string PARAMETER_NAME_PROPERTY_NAME(); + + /** + * modelfit.parameter.unit ist die Einheit des Parameters und dient nur der formatierten Ausgabe. Standardwert: "" + */ + static const std::string PARAMETER_UNIT_PROPERTY_NAME(); + + /** + * modelfit.parameter.scale ist die Skalierung des Parameters. Standardwert: 1 + */ + static const std::string PARAMETER_SCALE_PROPERTY_NAME(); + + /** + * modelfit.parameter.type ist der type des parameters. Standardwert: PARAMETER_TYPE_VALUE_PARAMETER + */ + static const std::string PARAMETER_TYPE_PROPERTY_NAME(); + + /** + * modelfit.parameter.type Wert für normale Parameters. + */ + static const std::string PARAMETER_TYPE_VALUE_PARAMETER(); + + /** + * modelfit.parameter.type Wert für derived Parameters. + */ + static const std::string PARAMETER_TYPE_VALUE_DERIVED_PARAMETER(); + + /** + * modelfit.parameter.type Wert für Crtierion-Parameters. + */ + static const std::string PARAMETER_TYPE_VALUE_CRITERION(); + + /** + * modelfit.parameter.type Wert für Evaluation-Parameters. + */ + static const std::string PARAMETER_TYPE_VALUE_EVALUATION_PARAMETER(); + + /** + * modelfit.model.type ist der Bezeichner des Modelltyps und dient nur der formatierten Ausgabe + */ + static const std::string MODEL_TYPE_PROPERTY_NAME(); + + /** + * modelfit.model.name ist der Bezeichner des Fits und dient nur der formatierten Ausgabe. + */ + static const std::string MODEL_NAME_PROPERTY_NAME(); + + /** + * modelfit.model.function ist der Funktions-String, der geparsed wird, um die Kurve zu plotten. + */ + static const std::string MODEL_FUNCTION_PROPERTY_NAME(); + + /** + * modelfit.model.functionClass ist die ID der Modellklasse. + */ + static const std::string MODEL_FUNCTION_CLASS_PROPERTY_NAME(); + + /** + * modelfit.model.x ist der Name der Variable, die die x-Werte stellt, wie sie im Funktions-String vorkommt. Wird nur gebraucht wenn modelfit.model.function definiert ist. + */ + static const std::string MODEL_X_PROPERTY_NAME(); + + /** + * Default value for MODEL_X_PROPERTY_NAME. + */ + static const std::string MODEL_X_VALUE_DEFAULT(); + + /** + * modelfit.xaxis.name ist der Bezeichner der x-Achse und dient nur der formatierten Ausgabe. Standardwert: "Time" + */ + static const std::string XAXIS_NAME_PROPERTY_NAME(); + + /** + * Default value for XAXIS_NAME_PROPERTY_NAME. + */ + static const std::string XAXIS_NAME_VALUE_DEFAULT(); + + /** + * modelfit.xaxis.unit ist die Einheit der x-Achse und dient nur der formatierten Ausgabe. Standardwert: "ms" + */ + static const std::string XAXIS_UNIT_PROPERTY_NAME(); + + /** + * modelfit.xaxis.name ist der Bezeichner der x-Achse und dient nur der formatierten Ausgabe. Standardwert: "Intensity" + */ + static const std::string YAXIS_NAME_PROPERTY_NAME(); + + /** + * Default value for YAXIS_NAME_PROPERTY_NAME. + */ + static const std::string YAXIS_NAME_VALUE_DEFAULT(); + + /** + * modelfit.xaxis.unit ist die Einheit der x-Achse und dient nur der formatierten Ausgabe. Standardwert: "" + */ + static const std::string YAXIS_UNIT_PROPERTY_NAME(); + + /** + * modelfit.fit.uid ist eine einzigartige ID (unabhängig von Ausführungsrechner, Session oder Applikationsinstanz), + * die einem Fit vergeben wird um alle zugehörigen Bilder eindeutig zu kennzeichnen. + */ + static const std::string FIT_UID_PROPERTY_NAME(); + + /** + * modelfit.fit.type defines the type of model fitting; e.g. pixel based or ROI based. Thus it determines the meaning of other fit specific informations. + */ + static const std::string FIT_TYPE_PROPERTY_NAME(); + + static const std::string FIT_TYPE_VALUE_PIXELBASED(); + + static const std::string FIT_TYPE_VALUE_ROIBASED(); + + /** + * modelfit.fit.input.imageUID defines the UID of the image that is used directly or indirectly (then it is source for input.data) to make the fit. + */ + static const std::string FIT_INPUT_IMAGEUID_PROPERTY_NAME(); + + /** + * modelfit.fit.input.roiUID defines the UID of the ROI that is used to make the fit. If not set no Mask was used or specified. + */ + static const std::string FIT_INPUT_ROIUID_PROPERTY_NAME(); + + /** + * modelfit.fit.input.data defines the data signal that is used to make the fit and was extracted from the input image (e.g. in ROIbased fit). + */ + static const std::string FIT_INPUT_DATA_PROPERTY_NAME(); + + /** + * modelfit.fit.staticParameters ist eine Map der Variablennamen, die im Funktions-String vorkommen und + * nicht mit modelfit.input.variables abgedeckt sind. Dies können z.B. Konstanten sein oder Variablen, + * die sich (abhängig vom Fit) über den Zeitverlauf ändern, wie z.B. der Mittelwert einer Maske über einen Arterienquerschnitt. + * (Entspricht den StaticParameters in mitk::ModelBase) + * Der Wert der Variablen ist ein Array, welches die Variablenwerte enthält. + * Beispiel: + * ["AIF":[2, 8, 8, 4, 5], "tau":[0.42]] (insgesamt 5 Zeitschritte, 2 Variablen) + */ + static const std::string FIT_STATIC_PARAMETERS_PROPERTY_NAME(); + + + }; +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/Modules/ModelFit/include/mitkModelFitCostFunctionInterface.h b/Modules/ModelFit/include/mitkModelFitCostFunctionInterface.h new file mode 100644 index 0000000000..6ec81f39f0 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitCostFunctionInterface.h @@ -0,0 +1,59 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MODELFITCOSTFUNCTION_INTERFACE_H +#define MODELFITCOSTFUNCTION_INTERFACE_H + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ +/** Interface class that is implemented by all cost functions that are used in the context of model fitting. +*/ +class MITKMODELFIT_EXPORT ModelFitCostFunctionInterface +{ +public: + + typedef ModelFitCostFunctionInterface Self; + + typedef itk::Array SignalType; + + virtual void SetSample(const SignalType &sampleSet) = 0; + + virtual void SetModel(const ModelBase* model) = 0; + virtual const ModelBase* GetModel() const = 0; + +protected: + + ModelFitCostFunctionInterface() + { + } + + virtual ~ModelFitCostFunctionInterface() + {} + +private: + + ModelFitCostFunctionInterface(const ModelFitCostFunctionInterface& source); + void operator=(const ModelFitCostFunctionInterface&); //purposely not implemented + +}; + +} + +#endif // MODELFITCOSTFUNCTION_H diff --git a/Modules/ModelFit/include/mitkModelFitException.h b/Modules/ModelFit/include/mitkModelFitException.h new file mode 100644 index 0000000000..3b398cdcf0 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitException.h @@ -0,0 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkModelFitException_h +#define mitkModelFitException_h + +#include "mitkExceptionMacro.h" + +namespace mitk +{ + namespace modelFit + { + /** + * @brief Class-specific exception for modelfits. + */ + class MITKMODELFIT_EXPORT ModelFitException : public Exception + { + public: + mitkExceptionClassMacro(ModelFitException, Exception); + }; + } +} + +#endif // mitkModelFitException_h diff --git a/Modules/ModelFit/include/mitkModelFitFunctorBase.h b/Modules/ModelFit/include/mitkModelFitFunctorBase.h new file mode 100644 index 0000000000..6269111e28 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitFunctorBase.h @@ -0,0 +1,141 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MODEL_FIT_FUNCTOR_BASE_H +#define MODEL_FIT_FUNCTOR_BASE_H + +#include + +#include + +#include "mitkModelBase.h" +#include "mitkSVModelFitCostFunction.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT ModelFitFunctorBase: public ::itk::Object + { + public: + typedef ModelFitFunctorBase Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ModelFitFunctorBase, itk::Object); + + typedef ScalarType ParameterImagePixelType; + typedef std::vector InputPixelArrayType; + typedef std::vector OutputPixelArrayType; + + /** Returns the values determined by fitting the passed model. The values in the returned vector are ordered in the + * following sequence: + * - model parameters (see also GetParameterNames()) + * - derived model parameters (see also GetDerivedParameterNames()) + * - criterion(s) (see also GetCriterionNames()) + * - evaluation parameters (see also GetEvaluationParameterNames()) + * @param value Signal the model should be fitted onto + * @param model Pointer to the preconfigured/ready to use model instance for the fitting against the signal curve + * @param initialParameters parameters of the model that should be used as starting point of the fitting process. + * @pre model must point to a valid instance. + * @pre Size of initialParameters must be equal to model->GetNumberOfParameters(). + */ + OutputPixelArrayType Compute(const InputPixelArrayType& value, const ModelBase* model, + const ModelBase::ParametersType& initialParameters) const; + + /** Returns the number of outputs the fit functor will return if compute is called. + * The number depends in parts on the passed model. + * @exception Exception will be thrown if no valid model is passed.*/ + unsigned int GetNumberOfOutputs(const ModelBase* model) const; + + typedef ModelBase::ParameterNamesType ParameterNamesType; + + /** Returns names of all evaluation parameters defined by the user*/ + ParameterNamesType GetEvaluationParameterNames() const; + void ResetEvaluationParameters(); + void RegisterEvaluationParameter(const std::string& parameterName, + SVModelFitCostFunction* evaluationCostFunction); + const SVModelFitCostFunction* GetEvaluationParameterCostFunction(const std::string& parameterName) + const; + + /** Returns names of the criterion used to fit the model. */ + virtual ParameterNamesType GetCriterionNames() const = 0 ; + + /** Returns names of the depug parameters generated by the functor. + Is empty, if debug is deactivated. */ + ParameterNamesType GetDebugParameterNames() const; + + itkBooleanMacro(DebugParameterMaps); + itkSetMacro(DebugParameterMaps, bool); + itkGetConstMacro(DebugParameterMaps, bool); + + protected: + + typedef ModelBase::ParametersType ParametersType; + typedef ModelFitCostFunctionInterface::SignalType SignalType; + + ModelFitFunctorBase(); + + ~ModelFitFunctorBase(); + + /**Internal Method called by Compute to get the final criterion values thar dove the fit. + must be implemented be concrete functor classes.*/ + virtual OutputPixelArrayType GetCriteria(const ModelBase* model, const ParametersType& parameters, + const SignalType& sample) const = 0; + + /** Internal Method called by Compute(). + Gets all derived parameters of the models with the final found parameters of the fit.*/ + OutputPixelArrayType GetDerivedParameters(const ModelBase* model, + const ParametersType& parameters) const; + + /** Internal Method called by Compute(). + Gets the evaluation parameters for all cost functions enlisted by the user, based on + the model with the final found parameters of the fit and the input signal.*/ + OutputPixelArrayType GetEvaluationParameters(const ModelBase* model, + const ParametersType& parameters, const SignalType& sample) const; + + typedef std::map DebugParameterMapType; + + /** Internal Method called by Compute(). It does the real fit and returns the found parameters. + Additionally it must return its debug parameter via debugParameters. + @post If m_DebugParameterMaps is true, it must return all debug parameters defined by + GetDebugParameterNames() via debugParameters. + @param value Signal the Model should be fitted against + @param model Pointer to the model that should be fitted + @param initialParameters Initial modal parameters for the fit + @param [out] debugParameters Map containing all debug parameters for the done fit (must only valid if m_DebugParameterMap is true)*/ + virtual ParametersType DoModelFit(const SignalType& value, const ModelBase* model, + const ModelBase::ParametersType& initialParameters, + DebugParameterMapType& debugParameters) const = 0; + + /** Returns names of the depug parameters generated by the functor. Will be called by GetDebugParameterNames, + if debug is activated. */ + virtual ParameterNamesType DefineDebugParameterNames()const = 0; + + private: + + typedef std::map CostFunctionMapType; + CostFunctionMapType m_CostFunctionMap; + bool m_DebugParameterMaps; + ::itk::SimpleFastMutexLock m_Mutex; + }; + +} + + +#endif // MODEL_FIT_FUNCTOR_BASE_H diff --git a/Modules/ModelFit/include/mitkModelFitFunctorPolicy.h b/Modules/ModelFit/include/mitkModelFitFunctorPolicy.h new file mode 100644 index 0000000000..8e57777686 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitFunctorPolicy.h @@ -0,0 +1,121 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MODELFITFUNCTOR_POLICY_H +#define MODELFITFUNCTOR_POLICY_H + +#include "itkIndex.h" +#include "mitkModelFitFunctorBase.h" +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT ModelFitFunctorPolicy + { + public: + typedef ModelFitFunctorBase::InputPixelArrayType InputPixelArrayType; + typedef ModelFitFunctorBase::InputPixelArrayType OutputPixelArrayType; + + typedef mitk::ModelParameterizerBase ParameterizerType; + typedef ParameterizerType::ConstPointer ParameterizerConstPointer; + + typedef ModelFitFunctorBase FunctorType; + typedef ModelFitFunctorBase::ConstPointer FunctorConstPointer; + + typedef itk::Index<3> IndexType; + + ModelFitFunctorPolicy() + {}; + + ~ModelFitFunctorPolicy() {}; + + unsigned int GetNumberOfOutputs() const + { + unsigned int result = 0; + + if (m_Functor.IsNotNull() && m_ModelParameterizer.IsNotNull()) + { + ParameterizerType::ModelBasePointer tempModel = m_ModelParameterizer->GenerateParameterizedModel(); + result = m_Functor->GetNumberOfOutputs(tempModel); + } + + return result; + } + + void SetModelFitFunctor(const mitk::ModelFitFunctorBase* functor) + { + if (!functor) + { + itkGenericExceptionMacro( << "Error. Functor is Null."); + } + + m_Functor = functor; + } + + void SetModelParameterizer(const ParameterizerType* parameterizer) + { + if (!parameterizer) + { + itkGenericExceptionMacro( << "Error. Parameterizer is Null."); + } + + m_ModelParameterizer = parameterizer; + } + + bool operator!=(const ModelFitFunctorPolicy& other) const + { + return !(*this == other); + } + + bool operator==(const ModelFitFunctorPolicy& other) const + { + return (this->m_Functor == other.m_Functor) && + (this->m_ModelParameterizer == other.m_ModelParameterizer); + } + + inline OutputPixelArrayType operator()(const InputPixelArrayType& value, + const IndexType& currentIndex) const + { + if (!m_Functor) + { + itkGenericExceptionMacro( << "Error. Cannot process operator(). Functor is Null."); + } + + if (!m_ModelParameterizer) + { + itkGenericExceptionMacro( << "Error. Cannot process operator(). Parameterizer is Null."); + } + + ParameterizerType::ModelBasePointer parameterizedModel = + m_ModelParameterizer->GenerateParameterizedModel(currentIndex); + ParameterizerType::ParametersType initialParams = m_ModelParameterizer->GetInitialParameterization( + currentIndex); + OutputPixelArrayType result = m_Functor->Compute(value, parameterizedModel, initialParams); + + return result; + } + + private: + + FunctorConstPointer m_Functor; + ParameterizerConstPointer m_ModelParameterizer; + }; + +} + + +#endif // LEVENBERGMARQUARDTMODELFITFUNCTOR_H diff --git a/Modules/ModelFit/include/mitkModelFitInfo.h b/Modules/ModelFit/include/mitkModelFitInfo.h new file mode 100644 index 0000000000..ccf8b3bf39 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitInfo.h @@ -0,0 +1,200 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkModelFitInfo_h +#define mitkModelFitInfo_h + +#include +#include + +#include + +#include "mitkModelFitConstants.h" +#include "mitkModelFitParameter.h" +#include "mitkModelFitStaticParameterMap.h" +#include "mitkScalarListLookupTable.h" +#include "mitkModelFitUIDHelper.h" +#include "mitkModelParameterizerBase.h" +#include "mitkModelTraitsInterface.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + namespace modelFit + { + /** + * @brief Data class that stores all information about a modelfit that is relevant to the + * visualization and stored as properties in the result nodes. + */ + class MITKMODELFIT_EXPORT ModelFitInfo : public itk::LightObject + { + public: + typedef mitk::NodeUIDType UIDType; + typedef std::vector ParamListType; + typedef ParamListType::const_iterator ConstIterType; + + mitkClassMacroItkParent(ModelFitInfo, itk::LightObject) + itkSimpleNewMacro(ModelFitInfo) + + ModelFitInfo() : + x(mitk::ModelFitConstants::MODEL_X_VALUE_DEFAULT()), + xAxisName(mitk::ModelFitConstants::XAXIS_NAME_VALUE_DEFAULT()), + yAxisName(mitk::ModelFitConstants::YAXIS_NAME_VALUE_DEFAULT()) + { + } + + /** + * @brief Adds the given parameter to this fit's parameter list if it doesn't + * exist already. + * @param p The param that should be added to this fit's parameter list. + */ + void AddParameter(Parameter::Pointer p); + + /** + * @brief Searches for the parameter with the given name and type in the fit's + * parameter list and returns it. + * @param name The name of the desired parameter. + * @param type The type of the desired parameter. + * @return The parameter with the given name on success or NULL otherwise. + */ + Parameter::ConstPointer GetParameter(const std::string& name, const Parameter::Type& type) + const; + + /** + * @brief Searches for the parameter with the given name and type in the fit's + * parameter list and deletes it if it exists. + * @param name The name of the desired parameter. + * @param type The type of the desired parameter. + */ + void DeleteParameter(const std::string& name, const Parameter::Type& type); + + /**Return const reference to the parameter list.*/ + const ParamListType& GetParameters() const; + + /** ModelFitConstants::MODEL_NAME_PROPERTY_NAME */ + std::string modelName; + /** ModelFitConstants::MODEL_TYPE_PROPERTY_NAME */ + std::string modelType; + /** ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME */ + std::string function; + /** ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME */ + std::string functionClassID; + /** ModelFitConstants::MODEL_X_PROPERTY_NAME */ + std::string x; + + /** ModelFitConstants::XAXIS_NAME_PROPERTY_NAME */ + std::string xAxisName; + /** ModelFitConstants::XAXIS_UNIT_PROPERTY_NAME */ + std::string xAxisUnit; + + /** ModelFitConstants::YAXIS_NAME_PROPERTY_NAME */ + std::string yAxisName; + /** ModelFitConstants::YAXIS_UNIT_PROPERTY_NAME */ + std::string yAxisUnit; + + /** ModelFitConstants::FIT_UID_PROPERTY_NAME */ + UIDType uid; + /** ModelFitConstants::FIT_TYPE_PROPERTY_NAME */ + std::string fitType; + /** ModelFitConstants::FIT_STATIC_PARAMETERS_PROPERTY_NAME */ + StaticParameterMap staticParamMap; + /** ModelFitConstants::FIT_INPUT_ROIUID_PROPERTY_NAME */ + UIDType roiUID; + /** ModelFitConstants::FIT_INPUT_IMAGEUID_PROPERTY_NAME */ + UIDType inputUID; + /** ModelFitConstants::FIT_INPUT_DATA_PROPERTY_NAME */ + ScalarListLookupTable inputData; + mitk::Image::Pointer inputImage; + + private: + typedef ParamListType::iterator IterType; + typedef itk::MutexLockHolder LockType; + + ParamListType parameterList; + itk::SimpleFastMutexLock mutex; + }; + + /** + * @brief Reads the string property with the given name from the data of the given node + * and returns its value. Throws a ModelFitException if the property doesn't exist. + * @param node The node whose property value should be returned. + * @param prop The name of the property that should be read. + * @return The value of the found property. + * @throw ModelFitException If the property doesn't exist or returns an empty string. + */ + MITKMODELFIT_EXPORT const std::string GetMandatoryProperty(const mitk::DataNode* node, + const std::string& prop); + + /** + * @brief Reads the string property with the given name from the given base data and + * returns its value. Throws a ModelFitException if the property doesn't exist. + * @param data The data whose property value should be returned. + * @param prop The name of the property that should be read. + * @return The value of the found property. + * @throw ModelFitException If the property doesn't exist or returns an empty string. + */ + MITKMODELFIT_EXPORT const std::string GetMandatoryProperty(const mitk::BaseData* data, + const std::string& prop); + + /** + * @brief Creates a new ModelFitInfo instance from the nodes in the passed storage. + * The fit will be identified by the passed UID. Returns the instance on + * success. + * @param uid The uid of the fit that should get its ModelFitInfo created and which identifies the nodes in the storage. + * @param storage Pointer to the data storage containing any potential relevantThe nodes. + * @return The newly created modelfit on success or NULL otherwise. + */ + MITKMODELFIT_EXPORT ModelFitInfo::Pointer CreateFitInfoFromNode(const ModelFitInfo::UIDType& uid, + const mitk::DataStorage* storage); + + /** creates a new ModelFitInfo instance from a passed modal instance and his traits instance* + * @param usedModel Pointer to a model which was used for a fit, which should get a fit info created. + * @param modelTraits Pointer to traits interface for the model that was used for the fit. + * @param inputImage Pointer to the input image. If it has no UID yet, a property will be added to the node. + * @return The newly created modelfit on success or NULL otherwise.*/ + MITKMODELFIT_EXPORT ModelFitInfo::Pointer CreateFitInfoFromModelParameterizer( + const ModelParameterizerBase* usedParameterizer, mitk::BaseData* inputImage, + const std::string& fitType, const NodeUIDType roiUID = ""); + /** @overload + Overloaded version that allows additional definition of optional input data for the fit.*/ + MITKMODELFIT_EXPORT ModelFitInfo::Pointer CreateFitInfoFromModelParameterizer( + const ModelParameterizerBase* usedParameterizer, mitk::BaseData* inputImage, + const std::string& fitType, const ScalarListLookupTable& inputData, const NodeUIDType roiUID = ""); + + /** Returns all nodes that belong to the fit indicated by the passed UID. + * @param fitUID The uid of the fit that is relevant for the query. + * @param storage Pointer to the data storage containing any potential relevant nodes. + * @return The set of found nodes or null if storage is not valid. + */ + MITKMODELFIT_EXPORT DataStorage::SetOfObjects::ConstPointer GetNodesOfFit( + const ModelFitInfo::UIDType& fitUID, + const mitk::DataStorage* storage); + + typedef std::set NodeUIDSetType; + /** Returns the UIDs of all fits that are derived (directly or indirectly from the passed node). + * @param node The node which defines the parent node. It will be searched in his derived nodes for fits. + * @param storage Pointer to the data storage containing any potential relevant nodes. + * @return The set of found uid will be returned. + */ + MITKMODELFIT_EXPORT NodeUIDSetType GetFitUIDsOfNode(const mitk::DataNode* node, + const mitk::DataStorage* storage); + + } +} + +#endif // mitkModelFit_h diff --git a/Modules/ModelFit/include/mitkModelFitInfoSignalGenerationFunctor.h b/Modules/ModelFit/include/mitkModelFitInfoSignalGenerationFunctor.h new file mode 100644 index 0000000000..6cb6aec733 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitInfoSignalGenerationFunctor.h @@ -0,0 +1,85 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKModelFitInfoSignalGenerationFunctor_H +#define MITKModelFitInfoSignalGenerationFunctor_H + +#include "mitkModelBasedValueFunctorBase.h" +#include "mitkModelParameterizerBase.h" +#include "mitkModelFitInfo.h" + +#include "mitkModelFitParameterValueExtraction.h" + +#include + +namespace mitk +{ + + /** Functor class that can be used to generate a model signal for each index. + This class is similar to ModelDataGenerationFunctor. But instead of using + the passed input value as model parameters in the compute function, the model + fit info is used to deduce the parameters based on the index. + The time grid and the parameterized model are provided by the model + parameterizer. This this functor will generate a signal for each index position + and return the signal as output.*/ + class MITKMODELFIT_EXPORT ModelFitInfoSignalGenerationFunctor : public ModelBasedValueFunctorBase + { + public: + + typedef ModelFitInfoSignalGenerationFunctor Self; + typedef ModelBasedValueFunctorBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkFactorylessNewMacro(Self); + itkTypeMacro(ModelFitInfoSignalGenerationFunctor, ModelBasedValueFunctorBase); + + typedef std::vector ParameterNamesType; + typedef ModelBase::ModelResultType SignalType; + typedef itk::Array ModelParametersType; + + itkSetConstObjectMacro(ModelParameterizer, ModelParameterizerBase); + itkGetConstObjectMacro(ModelParameterizer, ModelParameterizerBase); + + itkSetConstObjectMacro(FitInfo, mitk::modelFit::ModelFitInfo); + itkGetConstObjectMacro(FitInfo, mitk::modelFit::ModelFitInfo); + + virtual IndexedValueFunctorBase::OutputPixelVectorType Compute(const InputPixelVectorType & value, const IndexType& currentIndex) const override; + /** Convinient overload because this functor does not need the value */ + virtual IndexedValueFunctorBase::OutputPixelVectorType Compute(const IndexType& currentIndex) const; + + virtual unsigned int GetNumberOfOutputs() const override; + + virtual GridArrayType GetGrid() const override; + + protected: + /**Method is called by Compute() to specify the parameters used to generate the model signal for the current index. + The default implementation just extracts the parameters out of the model fit info and maps it into the result vector. + Reimplement the method to change this behavior.*/ + virtual ModelBase::ParametersType CompileModelParameters(const IndexType& currentIndex, const ModelBase * model) const; + + ModelFitInfoSignalGenerationFunctor(); + + virtual ~ModelFitInfoSignalGenerationFunctor(); + + private: + ModelParameterizerBase::ConstPointer m_ModelParameterizer; + modelFit::ModelFitInfo::ConstPointer m_FitInfo; + + }; +} + +#endif // MITKModelFitInfoSignalGenerationFunctor_H diff --git a/Modules/ModelFit/include/mitkModelFitParameter.h b/Modules/ModelFit/include/mitkModelFitParameter.h new file mode 100644 index 0000000000..2563978942 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitParameter.h @@ -0,0 +1,70 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkModelFitParameter_h +#define mitkModelFitParameter_h + +#include +#include "mitkModelFitUIDHelper.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + namespace modelFit + { + /** + * @brief Data class that stores all information about a modelfit parameter. + * Such a parameter is going to be fitted for the according model. + */ + class MITKMODELFIT_EXPORT Parameter : public itk::LightObject + { + public: + mitkClassMacroItkParent(Parameter, itk::LightObject) + itkSimpleNewMacro(Parameter) + + enum Type + { + ParameterType, + DerivedType, + CriterionType, + EvaluationType + }; + + Parameter(); + + /** ModelFitConstants::PARAMETER_NAME_PROPERTY_NAME */ + std::string name; + /** ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME */ + Type type; + /** ModelFitConstants::PARAMETER_UNIT_PROPERTY_NAME */ + std::string unit; + /** ModelFitConstants::PARAMETER_SCALE_PROPERTY_NAME */ + float scale; + /** Corresponding image */ + mitk::Image::ConstPointer image; + }; + + /** Extracts the parameter information stored in the data instance and returns it as parameter instance. + * If the data does not encode an parameter/fit result a Null pointer will be returned. + * @param data The data instance that contains parameter information that should be extracted. + * @return The newly created parameter instance on success or NULL otherwise. + */ + MITKMODELFIT_EXPORT Parameter::Pointer ExtractParameterFromData(const mitk::BaseData* data); + } +} + +#endif // mitkModelFitParameter_h \ No newline at end of file diff --git a/Modules/ModelFit/include/mitkModelFitParameterValueExtraction.h b/Modules/ModelFit/include/mitkModelFitParameterValueExtraction.h new file mode 100644 index 0000000000..57028082a2 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitParameterValueExtraction.h @@ -0,0 +1,63 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkModelFitParameterValueExtraction_h +#define mitkModelFitParameterValueExtraction_h + +#include + +#include "mitkModelFitInfo.h" +#include "mitkModelTraitsInterface.h" + +#include "MitkModelFitExports.h" + + +namespace mitk +{ + + /** Helper function that gets the voxel value (as double) of an image (given an 3D position and a time step). + Function is used in different contexts of model fit view. + @param noThrow If set to false, function will throw exceptions. If set to true, exceptions will be blocked, an MITK_ERROR will be notified and the return is 0.0.*/ + MITKMODELFIT_EXPORT ModelTraitsInterface::ParameterValueType ReadVoxel(const mitk::Image* image, + const mitk::Point3D& position, unsigned int timestep = 0, bool noThrow = true); + + /** Helper function that gets the voxel value (as double) of an image (given an image index and a time step). + Function is used in different contexts of model fit view. + @param noThrow If set to false, function will throw exceptions.If set to true, exceptions will be blocked, an MITK_ERROR will be notified and the return is 0.0. */ + MITKMODELFIT_EXPORT ModelTraitsInterface::ParameterValueType ReadVoxel(const mitk::Image* image, + const ::itk::Index<3>& index, unsigned int timestep = 0, bool noThrow = true); + + using ParameterValueMapType = std::map; + + /** Helper function that extracts a map (keys are the parameter names, values are the associated parameter values) + of parameter values for the specified 3D point given a model fit info instance. + @pre fit must point to a valid instance. + */ + MITKMODELFIT_EXPORT ParameterValueMapType ExtractParameterValueMapFromModelFit(const mitk::modelFit::ModelFitInfo* fitInfo, + const mitk::Point3D& position); + MITKMODELFIT_EXPORT ParameterValueMapType ExtractParameterValueMapFromModelFit(const mitk::modelFit::ModelFitInfo* fitInfo, + const ::itk::Index<3>& index); + + /** Helper function that converts a parameter value map (like returned by ExtractParameterValueMapFromModelFit() into the ParametersType. + the ordering will be deduced with the help of the passed trait interface. + @pre pTraitInterface must point to a valid instance. + @pre valueMap must contain all parameter names of pTraitsInterface*/ + MITKMODELFIT_EXPORT ModelTraitsInterface::ParametersType + ConvertParameterMapToParameterVector(const ParameterValueMapType &valueMap, const ModelTraitsInterface * pTraitInterface); + +} + +#endif diff --git a/Modules/ModelFit/include/mitkModelFitProviderBase.h b/Modules/ModelFit/include/mitkModelFitProviderBase.h new file mode 100644 index 0000000000..bfd963eebf --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitProviderBase.h @@ -0,0 +1,88 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MODEL_FIT_PROVIDER_BASE_H +#define __MODEL_FIT_PROVIDER_BASE_H + +#include + +// MITK +#include + +// Microservices +#include +#include +#include + +namespace mitk +{ + /** + * @brief Base class for model fit provider. + */ + template + class ModelFitProviderBase : public mitk::IModelFitProvider + { + public: + /** Returns an instance of the model factory that is represented by the provider.*/ + virtual itk::SmartPointer GenerateFactory() const override; + + /** Returns the grid of the model variable extracted from the fit info. The default implementation + returns a time grid extracted from the time geometry of the fitInfo->inputImage. Reimplement for + other models/fits to generate other variable grids. + @pre fitInfo is a valid instance for the model fit. + */ + virtual ModelBase::TimeGridType GetVariableGrid(const modelFit::ModelFitInfo* fitInfo) const override; + + us::ServiceRegistration RegisterService(us::ModuleContext *context = us::GetModuleContext()); + void UnregisterService(); + + ModelFitProviderBase(); + virtual ~ModelFitProviderBase(); + + protected: + + ModelFitProviderBase(const ModelFitProviderBase &other); + + virtual us::ServiceProperties GetServiceProperties() const; + + /** + * \brief Set the service ranking for this file reader. + * + * Default is zero and should only be chosen differently for a reason. + * The ranking is used to determine which reader to use if several + * equivalent readers have been found. + * It may be used to replace a default reader from MITK in your own project. + * E.g. if you want to use your own reader for nrrd files instead of the default, + * implement it and give it a higher ranking than zero. + */ + void SetRanking(int ranking); + int GetRanking() const; + + private: + ModelFitProviderBase &operator=(const ModelFitProviderBase &other); + + class Impl; + std::unique_ptr< Impl > d; + }; + +} // namespace mitk + + +#ifndef ITK_MANUAL_INSTANTIATION +#include "mitkModelFitProviderBase.tpp" +#endif + +#endif /* __MODEL_FIT_PROVIDER_BASE_H */ diff --git a/Modules/ModelFit/include/mitkModelFitProviderBase.tpp b/Modules/ModelFit/include/mitkModelFitProviderBase.tpp new file mode 100644 index 0000000000..7554a4c4e7 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitProviderBase.tpp @@ -0,0 +1,148 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +#include +#include + +#include +#include +#include + +namespace mitk +{ + template + class ModelFitProviderBase::Impl + { + public: + Impl() : m_ReferenceFactory(TModelFactory::New()) + { + }; + + Impl(const Impl &other) = default; + + void SetRanking(int ranking) + { + m_Ranking = ranking; + }; + + int GetRanking() const + { + return m_Ranking; + }; + + us::ServiceRegistration m_Reg; + int m_Ranking; + using ModelFactoryType = TModelFactory; + + typename ModelFactoryType::Pointer m_ReferenceFactory; + }; + + template + ModelFitProviderBase::ModelFitProviderBase() : d() + { + } + + template + ModelFitProviderBase::~ModelFitProviderBase() + { + UnregisterService(); + } + + template + ModelFitProviderBase::ModelFitProviderBase(const ModelFitProviderBase &other) : IModelFitProvider(), d(new Impl(*other.d.get())) + { + } + + template + itk::SmartPointer + ModelFitProviderBase::GenerateFactory() const + { + return TModelFactory::New().GetPointer(); + }; + + template + ModelBase::TimeGridType + ModelFitProviderBase::GetVariableGrid(const modelFit::ModelFitInfo* fitInfo) const + { + if (!fitInfo) + { + mitkThrow() << "Error. Cannot get variable grid for model. Passed model fit info is null."; + } + + if (!fitInfo->inputImage.IsNotNull()) + { + mitkThrow() << "Error. Cannot get variable grid for model. Passed model fit info has no input image."; + } + return mitk::ExtractTimeGrid(fitInfo->inputImage); + }; + + + template + us::ServiceRegistration + ModelFitProviderBase::RegisterService(us::ModuleContext *context) + { + if (d) + return d->m_Reg; + + if (context == nullptr) + { + context = us::GetModuleContext(); + } + + d.reset(new Impl()); + + us::ServiceProperties props = this->GetServiceProperties(); + d->m_Reg = context->RegisterService(this, props); + return d->m_Reg; + } + + template + void + ModelFitProviderBase::UnregisterService() + { + try + { + d->m_Reg.Unregister(); + } + catch (const std::exception &) + { + } + } + + template + us::ServiceProperties + ModelFitProviderBase::GetServiceProperties() const + { + us::ServiceProperties result; + + result[IModelFitProvider::PROP_MODEL_CLASS_ID()] = this->d->m_ReferenceFactory->GetClassID(); + result[IModelFitProvider::PROP_MODEL_TYPE()] = this->d->m_ReferenceFactory->GetModelType(); + result[us::ServiceConstants::SERVICE_RANKING()] = this->GetRanking(); + return result; + } + + template + void + ModelFitProviderBase::SetRanking(int ranking) { d->SetRanking(ranking); } + + template + int + ModelFitProviderBase::GetRanking() const { return d->GetRanking(); } + +} diff --git a/Modules/ModelFit/include/mitkModelFitResultHelper.h b/Modules/ModelFit/include/mitkModelFitResultHelper.h new file mode 100644 index 0000000000..f73d9792fb --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitResultHelper.h @@ -0,0 +1,65 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_MODEL_FIT_RESULT_HELPER_H_ +#define __MITK_MODEL_FIT_RESULT_HELPER_H_ + +#include +#include + +#include "mitkScalarListLookupTableProperty.h" +#include "mitkModelBase.h" +#include "mitkModelFitParameter.h" +#include "mitkModelFitStaticParameterMap.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + class DataStorage; + class ModelTraitsInterface; + class ModelBase; + + namespace modelFit + { + class ModelFitInfo; + + typedef std::map ModelFitResultImageMapType; + typedef std::vector ModelFitResultNodeVectorType; + + /**Helper function that sets the properties of the passed base data according to the given model fit info instance and parameter specification. + @param data Instance that properties should be configured. + @param name Name of the parameter this data instance represents. + @param dataType Type of the parameter this data instance represents. + @param fitInfo Instance to the fit info that containes the information of the fit that derived the parameter. + @pre Data must point to a valid instance. + @pre fitInfo must point to an valid instance. + */ + MITKMODELFIT_EXPORT void SetModelFitDataProperties(mitk::BaseData* data, const ModelBase::ParameterNameType& name, modelFit::Parameter::Type dataType, const modelFit::ModelFitInfo* fitInfo); + + MITKMODELFIT_EXPORT mitk::ScalarListLookupTableProperty::Pointer ConvertStaticParametersToProperty(const mitk::modelFit::StaticParameterMap& params); + + MITKMODELFIT_EXPORT DataNode::Pointer CreateResultNode(const ModelBase::ParameterNameType& name, modelFit::Parameter::Type nodeType, Image* parameterImage, const ModelFitInfo* modelFitInfo, const std::string& sessionName = ""); + + MITKMODELFIT_EXPORT ModelFitResultNodeVectorType CreateResultNodeMap(const ModelFitResultImageMapType& results, const ModelFitResultImageMapType& derivedResults, const ModelFitResultImageMapType& criterionResults, const ModelFitResultImageMapType& evaluationResults, const ModelFitInfo* fitInfo, const std::string& sessionName = ""); + + MITKMODELFIT_EXPORT void StoreResultsInDataStorage(DataStorage* storage, const ModelFitResultNodeVectorType& resultNodes, DataNode* parentNode = NULL); + + } + +} + +#endif diff --git a/Modules/ModelFit/include/mitkModelFitStaticParameterMap.h b/Modules/ModelFit/include/mitkModelFitStaticParameterMap.h new file mode 100644 index 0000000000..a6a4f4a9fc --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitStaticParameterMap.h @@ -0,0 +1,159 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkModelFitStaticParameterMap_h +#define mitkModelFitStaticParameterMap_h + +#include +#include +#include + +#include "MitkModelFitExports.h" +#include "mitkModelBase.h" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +namespace mitk +{ + namespace modelFit + { + /** Data structure that is used to store information about the static parameters of a model fit*/ + class MITKMODELFIT_EXPORT StaticParameterMap + { + private: + /** @brief Type of the map key */ + typedef ModelBase::ParameterNameType KeyType; + + public: + /** @brief Type of the map value */ + typedef ModelBase::StaticParameterValuesType ValueType; + /** @brief Type of a variable, consisting of name and value list */ + typedef std::pair StaticParameterType; + + private: + /** @brief Type of the map */ + typedef ModelBase::StaticParameterMapType MapType; + + /* @brief Stores the variables with their value lists */ + MapType m_map; + + /** + * @brief Stores the number of values that each list (which contains more than one + * value) contains. + */ + unsigned int m_numValues; + + public: + /** @brief Needed for 'foreach' support */ + typedef MapType::const_iterator const_iterator; + + StaticParameterMap() : m_numValues(1) {} + + /** + * @brief Adds the given value list under the given variable name if the name + * doesn't exist already. If it does exist, nothing is added. + * @pre The given list must contain either 1 or n values, where n is the + * amount of values that lists contain which are already part of the + * map (and contain more than one value). That means if the map is + * empty or contains only lists that have only one value each, this + * rule doesn't apply. An exception is thrown otherwise. + * @param name The name of the variable to which the values should be added. + * @param newList The value list that should be added. + * @throw ModelFitException If the given list contains an amount of values that is + * greater than 1 and doesn't match the amount of values + * of the lists that are already part of the map (see + * pre-condition). + */ + void Add(const std::string& name, const ValueType& newList); + + /** + * @brief Returns the values of the given variable name. + * @param name The name of the variables whose values should be returned. + * @return The values of the given variable name. + * @throw std::range_error If the variable name doesn't exist. + */ + const ValueType& Get(const std::string& name) const; + + MapType::size_type Size() const + { + return m_map.size(); + } + + const_iterator begin() const + { + return m_map.begin(); + } + + const_iterator end() const + { + return m_map.end(); + } + + /** + * @brief Sorts the values of the given variable name in ascending order. The + * values of all other variables will also be switched in that specific + * order. If name is empty or the variable could not be found, the map is + * ordered by the first variable that contains more than one value (also in + * ascending order). + * @details Example: + *
  • Before sorting: + * "A": [3, 2, 5, 1, 4] + * "B": [0] + * "C": [3, 4, 1, 5, 2] + *
  • Sort(): + * "A": [1, 2, 3, 4, 5] + * "B": [0] + * "C": [5, 4, 3, 2, 1] + *
  • Sort("B"): + * "A": [5, 4, 3, 2, 1] + * "B": [0] + * "C": [1, 2, 3, 4, 5] + *
  • Sort("X"): + * "A": [1, 2, 3, 4, 5] + * "B": [0] + * "C": [5, 4, 3, 2, 1] + * @param name The name of the variable the map should be sorted by. + */ + void Sort(const std::string& name = ""); + + /** + * @brief Resets the map, so it's empty. + */ + void Clear(); + }; + + /** + * @brief Compares two var lists and returns true if the first list's first item is + * lower than the second one's. + * @param a The first list to compare the other one to. + * @param b The other list to compare the first one to. + * @return True if the first list's first item is smaller than the second one's. + */ + inline bool operator<(const StaticParameterMap::ValueType& a, const StaticParameterMap::ValueType& b) + { + return (a.front() < b.front()); + } + } +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // mitkModelFitStaticParameterMap_h diff --git a/Modules/ModelFit/include/mitkModelFitUIDHelper.h b/Modules/ModelFit/include/mitkModelFitUIDHelper.h new file mode 100644 index 0000000000..df88559d70 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelFitUIDHelper.h @@ -0,0 +1,59 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef mitkModelFitUIDHelper_h +#define mitkModelFitUIDHelper_h + +#include + +//MITK +#include + +#include "MitkModelFitExports.h" + +namespace mitk +{ + class BaseData; + class DataStorage; + + typedef std::string NodeUIDType; + + /** Helper that searches for the node in the storage that has a data object with the given uid. Returns NULL if no node was found.*/ + DataNode::Pointer MITKMODELFIT_EXPORT GetNodeByModelFitUID(const mitk::DataStorage* storage, const NodeUIDType& uid); + + /** Gets the UID of the passed data. The UID is stored in the property "data.uid". If this property does not exist the method will + check the existance of a property for the DICOM tag series instance UID (0x0020, 0x000e) and return the value as UID. If this does also + not exist, a UID will generated, the property "data.uid" will be added with a new UID and the new UID will be returned. + @pre Passed data is a valid pointer.*/ + NodeUIDType MITKMODELFIT_EXPORT EnsureModelFitUID(mitk::BaseData* data); + /** Convinience function that calls the overloaded EnsureModelFitUID() with the data of the passed node. + @pre Passed node is a valid pointer.*/ + NodeUIDType MITKMODELFIT_EXPORT EnsureModelFitUID(mitk::DataNode* node); + + /** Helper that checks if the data has the passed UID. Following strategy will be used for the check. + 1. Checks existance of property "data.uid" and if its content equals the passed uid. + 2. If 1 fails, it checks the existance of a property for the DICOM tag series instance UID (0x0020, 0x000e) and the equality of its value. + 3. If 2 also fails, return will be false.*/ + bool MITKMODELFIT_EXPORT CheckModelFitUID(const mitk::BaseData* data, const NodeUIDType& uid); + /** Convinience helper function that calls the overloaded CheckModelFitUID() with the data of the passed node.*/ + bool MITKMODELFIT_EXPORT CheckModelFitUID(const mitk::DataNode* node, const NodeUIDType& uid); + + +} + +#endif + diff --git a/Modules/ModelFit/include/mitkModelGenerator.h b/Modules/ModelFit/include/mitkModelGenerator.h new file mode 100644 index 0000000000..fb6ef84c42 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelGenerator.h @@ -0,0 +1,63 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MODEL_GENERATOR_H +#define MODEL_GENERATOR_H + +#include "mitkModelBase.h" +#include "mitkModelFactoryBase.h" +#include "mitkModelParameterizerBase.h" + +#include "mitkModelFitInfo.h" + +#include "mitkIModelFitProvider.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT ModelGenerator + { + public: + typedef ModelFactoryBase::ModellClassIDType ModelClassIDType; + + /** Returns the pointer to a factory instance that is responsible for the + given model class id. + If no fitting factory can be found, a null pointer is returned. + */ + static ModelFactoryBase::Pointer GetModelFactory(const ModelClassIDType& id); + + /** Takes a fit instances and generates the corresponding ModelParameterizer. + If no fitting factory can be found or no class id is specified in the fit, a null pointer is returned. + */ + static ModelParameterizerBase::Pointer GenerateModelParameterizer(const modelFit::ModelFitInfo& + fit); + + static IModelFitProvider* GetProviderService(const ModelClassIDType& id); + + protected: + ModelGenerator(); + virtual ~ModelGenerator(); + + private: + //No copy constructor allowed + ModelGenerator(const ModelGenerator& source); + void operator=(const ModelGenerator&); //purposely not implemented + }; +} + +#endif // MODEL_GENERATOR_H diff --git a/Modules/ModelFit/include/mitkModelParameterizerBase.h b/Modules/ModelFit/include/mitkModelParameterizerBase.h new file mode 100644 index 0000000000..ddbeeca636 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelParameterizerBase.h @@ -0,0 +1,104 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MODEL_PARAMETERIZER_BASE_H +#define __MODEL_PARAMETERIZER_BASE_H + +#include +#include + +#include "mitkModelBase.h" +#include "mitkInitialParameterizationDelegateBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /** Base class for all model parameterizers + * Model parameterizers are used to offer a generic api to generate/bind + * models with specific global static and local static parameters in order to + * utilize the model correctly.\n + * - Global static parameter: parameters that are the same for a model independent + * of the spatial position (in image space) that should be modeled (e.g. parameter "Tau" + * for the DescriptivePharmacokineticBrixModel) + * - Local static parameter: parameters that are specific for the spatial position (in image space) + * that should be modeled (e.g. parameter "S0" for the DescriptivePharmacokineticBrixModel) + */ + class MITKMODELFIT_EXPORT ModelParameterizerBase : public itk::Object, public ModelTraitsInterface + { + public: + typedef ModelParameterizerBase Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ModelParameterizerBase, itk::Object); + + typedef ModelBase ModelBaseType; + typedef ModelBaseType::Pointer ModelBasePointer; + + typedef ModelBaseType::ParametersType ParametersType; + typedef ModelBaseType::StaticParameterValueType StaticParameterValueType; + typedef ModelBaseType::StaticParameterValuesType StaticParameterValuesType; + typedef ModelBaseType::StaticParameterMapType StaticParameterMapType; + typedef ModelBaseType::TimeGridType TimeGridType; + + typedef ::itk::Index<3> IndexType; + + virtual StaticParameterMapType GetGlobalStaticParameters() const = 0; + virtual StaticParameterMapType GetLocalStaticParameters(const IndexType& currentPosition) const = 0; + + /** Returns the parameterization (e.g. initial parametrization for fitting) that should be used. + If no ParameterizationDelegate is set (see SetInitialParameterizationDelegate()) it will just return + the result of GetInitialParameterization().*/ + ParametersType GetInitialParameterization() const; + ParametersType GetInitialParameterization(const IndexType& currentPosition) const; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const = 0; + + /** Possibility to set a custom strategy for defining the initial parameterization via a delegate.*/ + void SetInitialParameterizationDelegate(const InitialParameterizationDelegateBase* delegate); + + virtual ModelBasePointer GenerateParameterizedModel(const IndexType& currentPosition) const = 0; + /** Generate model instance, only with global static parametrization. + * Any local static parameter stay default.*/ + virtual ModelBasePointer GenerateParameterizedModel() const = 0; + + itkSetMacro(DefaultTimeGrid, TimeGridType); + itkGetConstReferenceMacro(DefaultTimeGrid, TimeGridType); + + protected: + + + ModelParameterizerBase(); + + virtual ~ModelParameterizerBase(); + + InitialParameterizationDelegateBase::ConstPointer m_InitialDelegate; + + /** The default time grid that should be set to generated models.*/ + TimeGridType m_DefaultTimeGrid; + private: + + //No copy constructor allowed + ModelParameterizerBase(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // __MODEL_PARAMETERIZER_BASE_H diff --git a/Modules/ModelFit/include/mitkModelTraitsInterface.h b/Modules/ModelFit/include/mitkModelTraitsInterface.h new file mode 100644 index 0000000000..f039246372 --- /dev/null +++ b/Modules/ModelFit/include/mitkModelTraitsInterface.h @@ -0,0 +1,99 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MODEL_TRAITS_INTERFACE_H +#define __MODEL_TRAITS_INTERFACE_H + +#include "MitkModelFitExports.h" + +#include +#include +#include + +namespace mitk +{ + class MITKMODELFIT_EXPORT ModelTraitsInterface + { + public: + + + typedef itk::Array ModelResultType; + using ParameterValueType = double; + typedef itk::Array ParametersType; + + typedef std::string ParameterNameType; + typedef std::vector ParameterNamesType; + typedef ParametersType::SizeValueType ParametersSizeType; + typedef ParameterNamesType DerivedParameterNamesType; + typedef ParametersSizeType DerivedParametersSizeType; + + typedef std::map ParamterScaleMapType; + typedef std::map ParamterUnitMapType; + typedef std::map DerivedParamterScaleMapType; + typedef std::map DerivedParamterUnitMapType; + + typedef std::string FunctionStringType; + typedef std::string ModellClassIDType; + + /** Returns the names of parameters that must be defined when using + * the model to compute the signal (GetSignal()).*/ + virtual ParameterNamesType GetParameterNames() const = 0; + /** Returns the number of parameters that must be defined when using + * the model to compute the signal (GetSignal()).*/ + virtual ParametersSizeType GetNumberOfParameters() const = 0; + + virtual ParamterScaleMapType GetParameterScales() const = 0; + virtual ParamterUnitMapType GetParameterUnits() const = 0; + + /** Returns the names of derived parameters that must be defined when using + * the model to compute them (GetDerivedParameters()).*/ + virtual DerivedParameterNamesType GetDerivedParameterNames() const = 0; + /** Returns the number of derived parameters that must be defined when using + * the model to compute them (GetDerivedParameters()).*/ + virtual DerivedParametersSizeType GetNumberOfDerivedParameters() const = 0; + + virtual DerivedParamterScaleMapType GetDerivedParameterScales() const = 0; + virtual DerivedParamterUnitMapType GetDerivedParameterUnits() const = 0; + + virtual std::string GetModelDisplayName() const = 0; + + virtual std::string GetModelType() const = 0; + + virtual FunctionStringType GetFunctionString() const = 0; + + virtual ModellClassIDType GetClassID() const = 0; + + virtual std::string GetXName() const = 0; + + virtual std::string GetXAxisName() const = 0; + virtual std::string GetXAxisUnit() const = 0; + + virtual std::string GetYAxisName() const = 0; + virtual std::string GetYAxisUnit() const = 0; + + protected: + ModelTraitsInterface() {}; + virtual ~ModelTraitsInterface() {}; + + private: + + //No copy constructor allowed + ModelTraitsInterface(const ModelTraitsInterface& source); + void operator=(const ModelTraitsInterface&); //purposely not implemented + }; +} + +#endif // __MODEL_TRAITS_INTERFACE_H diff --git a/Modules/ModelFit/include/mitkNormalizedSumOfSquaredDifferencesFitCostFunction.h b/Modules/ModelFit/include/mitkNormalizedSumOfSquaredDifferencesFitCostFunction.h new file mode 100644 index 0000000000..ab65dc8720 --- /dev/null +++ b/Modules/ModelFit/include/mitkNormalizedSumOfSquaredDifferencesFitCostFunction.h @@ -0,0 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKNORMALIZEDSUMOFSQUAREDDIFFERENCESFITCOSTFUNCTION_H +#define MITKNORMALIZEDSUMOFSQUAREDDIFFERENCESFITCOSTFUNCTION_H + +#include + +#include "MitkModelFitExports.h" + +namespace mitk +{ + +/** Multi valued model fit cost function that computes the squared differences between the model output and the + * signal. +*/ +class MITKMODELFIT_EXPORT NormalizedSumOfSquaredDifferencesFitCostFunction : public mitk::SVModelFitCostFunction +{ +public: + + typedef NormalizedSumOfSquaredDifferencesFitCostFunction Self; + typedef mitk::SVModelFitCostFunction Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkNewMacro(Self); + + typedef Superclass::SignalType SignalType; + +protected: + + virtual MeasureType CalcMeasure(const ParametersType ¶meters, const SignalType& signal) const; + + NormalizedSumOfSquaredDifferencesFitCostFunction() + { + } + + ~NormalizedSumOfSquaredDifferencesFitCostFunction(){} +}; + +} + +#endif // MITKNORMALIZEDSUMOFSQUAREDDIFFERENCESFITCOSTFUNCTION_H diff --git a/Modules/ModelFit/include/mitkParameterFitImageGeneratorBase.h b/Modules/ModelFit/include/mitkParameterFitImageGeneratorBase.h new file mode 100644 index 0000000000..4046ed1822 --- /dev/null +++ b/Modules/ModelFit/include/mitkParameterFitImageGeneratorBase.h @@ -0,0 +1,108 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_PARAMETER_FIT_IMAGE_GENERATOR_BASE_H_ +#define __MITK_PARAMETER_FIT_IMAGE_GENERATOR_BASE_H_ + +#include + +#include + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /** Base class for generators for parameter fits of a given model. + * The generators creates 4 types of images: + * - parameter images: The images that encode the results of each fitted parameter + * - derived parameter images: Images that encode the results of derived parameters defined by the model + * - criterion images: Images that encode the criterion value of the fitting strategy for the fitted parameters + * - evaluation parameter images: Images that encode measures of additional evaluation cost functions defined by the user. (These were not part of the fitting strategy) + * . + */ + class MITKMODELFIT_EXPORT ParameterFitImageGeneratorBase: public ::itk::Object + { + public: + mitkClassMacroItkParent(ParameterFitImageGeneratorBase, ::itk::Object); + + using ParameterImagePixelType = ScalarType; + + using ModelBaseType = ModelBase; + using ParameterNameType = ModelBaseType::ParameterNameType; + using ParameterNamesType = ModelBaseType::ParameterNamesType; + + using ParameterImageMapType = std::map; + + /** Returns the progress of the current fit. e.g. 0 : none; 0.5 = 50%; 1: complete*/ + virtual double GetProgress() const = 0; + + /** Commences the model fit over the dynamic image data. Stores the fitted parameter in + * parameter images. After this method call is finished the parameter images can be retrieved via + * GetParameterImages. + * @pre Model must be set + * @pre DynamicImage must be set + * @post Parameter image map contains an image for every parameter of the model referenced by the parameter name.*/ + void Generate(); + + /** Returns the fitted/generated parameter images. Triggers Generate() if result is outdated.*/ + ParameterImageMapType GetParameterImages(); + + /** Returns the generated derived parameter images. Triggers Generate() if result is outdated.*/ + ParameterImageMapType GetDerivedParameterImages(); + + /** Returns the generated criterion images. Triggers Generate() if result is outdated.*/ + ParameterImageMapType GetCriterionImages(); + + /** Returns the generated evaluation parameter images. Triggers Generate() if result is outdated.*/ + ParameterImageMapType GetEvaluationParameterImages(); + + /** Returns the names of the fitted/generated parameters, that will be generated. These are also the keys of the related image map.*/ + virtual ParameterNamesType GetParameterNames() const = 0; + + /** Returns the names of the derived parameters, that will be generated. These are also the keys of the related image map.*/ + virtual ParameterNamesType GetDerivedParameterNames() const = 0; + + /** Returns the names of the criteria, that will be generated. These are also the keys of the related image map.*/ + virtual ParameterNamesType GetCriterionNames() const = 0; + + /** Returns the names of the evaluation parameters, that will be generated. These are also the keys of the related image map.*/ + virtual ParameterNamesType GetEvaluationParameterNames() const = 0; + + protected: + ParameterFitImageGeneratorBase() {}; + virtual ~ParameterFitImageGeneratorBase() {}; + + virtual bool HasOutdatedResult() const; + /** Check if the fit can be generated and all needed inputs are valid. + * Throw an exception for a non valid or missing input.*/ + virtual void CheckValidInputs() const; + virtual void DoFitAndGetResults(ParameterImageMapType& parameterImages, ParameterImageMapType& derivedParameterImages, ParameterImageMapType& criterionImages, ParameterImageMapType& evaluationParameterImages) = 0; + + itk::TimeStamp m_GenerationTimeStamp; + + private: + + ParameterImageMapType m_ParameterImageMap; + ParameterImageMapType m_DerivedParameterImageMap; + ParameterImageMapType m_CriterionImageMap; + ParameterImageMapType m_EvaluationParameterImageMap; + }; + +} + +#endif // __MITK_PARAMETER_FIT_IMAGE_GENERATOR_H_ diff --git a/Modules/ModelFit/include/mitkPixelBasedParameterFitImageGenerator.h b/Modules/ModelFit/include/mitkPixelBasedParameterFitImageGenerator.h new file mode 100644 index 0000000000..9f9e58aa65 --- /dev/null +++ b/Modules/ModelFit/include/mitkPixelBasedParameterFitImageGenerator.h @@ -0,0 +1,134 @@ +/*=================================================================== + + The Medical Imaging Interaction Toolkit (MITK) + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. + + See LICENSE.txt or http://www.mitk.org for details. + + ===================================================================*/ + +#ifndef __MITK_PIXEL_BASED_PARAMETER_FIT_IMAGE_GENERATOR_H_ +#define __MITK_PIXEL_BASED_PARAMETER_FIT_IMAGE_GENERATOR_H_ + +#include + +#include + +#include "mitkModelParameterizerBase.h" +#include "mitkModelFitFunctorBase.h" +#include "mitkParameterFitImageGeneratorBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /** Class for generators for pixel based parameter fits of a given model based on a given 4D mitk image. + * The class uses a model fit functor (based on ModelFitFunctorBase) given by the use. + * @remark This generator fits every pixel on its own. If you want to fit the mean value of the given mask use + * ROIBasedParameterFitImageGenerator. + * The generator creates 4 types of images: + * - parameter images: The images that encode the results of each fitted parameter + * - derived parameter images: Images that encode the results of derived parameters defined by the model + * - criterion images: Images that encode the criterion value of the fitting strategy for the fitted parameters + * - evaluation parameter images: Images that encode measures of additional evaluation cost functions defined by the user. (These were not part of the fitting strategy) + * . + */ +class MITKMODELFIT_EXPORT PixelBasedParameterFitImageGenerator: public ParameterFitImageGeneratorBase +{ +public: + mitkClassMacro(PixelBasedParameterFitImageGenerator, ParameterFitImageGeneratorBase); + + itkNewMacro(Self); + + typedef ScalarType ParameterImagePixelType; + typedef std::vector FunctorValueArrayType; + + typedef ModelFitFunctorBase FitFunctorType; + + typedef ModelParameterizerBase ParameterizerType; + + typedef ParameterFitImageGeneratorBase::ModelBaseType ModelBaseType; + typedef ParameterFitImageGeneratorBase::ParameterNameType ParameterNameType; + typedef ParameterFitImageGeneratorBase::ParameterImageMapType ParameterImageMapType; + + itkSetObjectMacro(DynamicImage, Image); + itkGetConstObjectMacro(DynamicImage, Image); + + itkSetObjectMacro(Mask, Image); + itkGetConstObjectMacro(Mask, Image); + + itkSetObjectMacro(FitFunctor, FitFunctorType); + itkGetObjectMacro(FitFunctor, FitFunctorType); + + itkSetObjectMacro(ModelParameterizer, ParameterizerType); + itkGetObjectMacro(ModelParameterizer, ParameterizerType); + + itkSetMacro(TimeGridByParameterizer, bool); + itkGetMacro(TimeGridByParameterizer, bool); + itkBooleanMacro(TimeGridByParameterizer); + + virtual double GetProgress() const override; + + virtual ParameterNamesType GetParameterNames() const override; + + virtual ParameterNamesType GetDerivedParameterNames() const override; + + virtual ParameterNamesType GetCriterionNames() const override; + + virtual ParameterNamesType GetEvaluationParameterNames() const override; + +protected: + PixelBasedParameterFitImageGenerator() : m_Progress(0), m_TimeGridByParameterizer(false) + { + m_InternalMask = nullptr; + m_Mask = nullptr; + m_DynamicImage = nullptr; + }; + + ~PixelBasedParameterFitImageGenerator() = default; + + template + void DoParameterFit(itk::Image* image); + + template + void DoPrepareMask(itk::Image* image); + + void onFitProgressEvent(::itk::Object* caller, const ::itk::EventObject& eventObject); + + virtual bool HasOutdatedResult() const; + virtual void CheckValidInputs() const; + virtual void DoFitAndGetResults(ParameterImageMapType& parameterImages, ParameterImageMapType& derivedParameterImages, ParameterImageMapType& criterionImages, ParameterImageMapType& evaluationParameterImages); + +private: + Image::Pointer m_DynamicImage; + Image::Pointer m_Mask; + + typedef itk::Image InternalMaskType; + InternalMaskType::Pointer m_InternalMask; + + FitFunctorType::Pointer m_FitFunctor; + + ParameterizerType::Pointer m_ModelParameterizer; + + ParameterImageMapType m_TempResultMap; + ParameterImageMapType m_TempDerivedResultMap; + ParameterImageMapType m_TempEvaluationResultMap; + ParameterImageMapType m_TempCriterionResultMap; + + double m_Progress; + /**Indicates if the time grid defined in the parameterizer should be used (True) + or if the filter should extract the time grid from the input image (False).*/ + bool m_TimeGridByParameterizer; +}; + +} + +#endif // __MITK_PARAMETER_FIT_IMAGE_GENERATOR_H_ diff --git a/Modules/ModelFit/include/mitkROIBasedParameterFitImageGenerator.h b/Modules/ModelFit/include/mitkROIBasedParameterFitImageGenerator.h new file mode 100644 index 0000000000..783b8573c1 --- /dev/null +++ b/Modules/ModelFit/include/mitkROIBasedParameterFitImageGenerator.h @@ -0,0 +1,124 @@ +/*=================================================================== + + The Medical Imaging Interaction Toolkit (MITK) + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. + + See LICENSE.txt or http://www.mitk.org for details. + + ===================================================================*/ + +#ifndef __MITK_ROI_BASED_PARAMETER_FIT_IMAGE_GENERATOR_H_ +#define __MITK_ROI_BASED_PARAMETER_FIT_IMAGE_GENERATOR_H_ + +#include + +#include + +#include "mitkModelParameterizerBase.h" +#include "mitkModelFitFunctorBase.h" +#include "mitkParameterFitImageGeneratorBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /** Class for generators for parameter fits of a given model based on one given signal and its time grid. + * The class uses a model fit functor (based on ModelFitFunctorBase) given by the user. It will fit the model to the passed signal. + * To produce the output/parameter images, the passed mask will be used as template. The geometry of the mask specifies the geometry + * of the result images. Every pixel inside the mask (mask value > 0) will be filled with the fitting results. Every pixel outside the mask + * (mask value == 0) will be set to 0.\n + * The generators creates 4 types of images: + * - parameter images: The images that encode the results of each fitted parameter + * - derived parameter images: Images that encode the results of derived parameters defined by the model + * - criterion images: Images that encode the criterion value of the fitting strategy for the fitted parameters + * - evaluation parameter images: Images that encode measures of additional evaluation cost functions defined by the user. (These were not part of the fitting strategy) + * . + */ +class MITKMODELFIT_EXPORT ROIBasedParameterFitImageGenerator: public ParameterFitImageGeneratorBase +{ +public: + mitkClassMacro(ROIBasedParameterFitImageGenerator, ParameterFitImageGeneratorBase); + + itkNewMacro(Self); + + using ParameterImagePixelType = ScalarType; + using FunctorValueArrayType = std::vector; + + using FitFunctorType = ModelFitFunctorBase; + + using ParameterizerType = ModelParameterizerBase; + + using ModelBaseType = ParameterFitImageGeneratorBase::ModelBaseType; + using ParameterNameType = ParameterFitImageGeneratorBase::ParameterNameType; + using ParameterImageMapType = ParameterFitImageGeneratorBase::ParameterImageMapType; + + using TimeGridType = ModelBaseType::TimeGridType; + using SignalType = ModelBaseType::ModelResultType; + + itkSetObjectMacro(Mask, Image); + itkGetConstObjectMacro(Mask, Image); + + itkGetConstReferenceMacro(Signal, SignalType); + itkSetMacro(Signal, SignalType); + + itkGetConstReferenceMacro(TimeGrid, TimeGridType); + itkSetMacro(TimeGrid, TimeGridType); + + itkSetObjectMacro(FitFunctor, FitFunctorType); + itkGetObjectMacro(FitFunctor, FitFunctorType); + + itkSetObjectMacro(ModelParameterizer, ParameterizerType); + itkGetObjectMacro(ModelParameterizer, ParameterizerType); + + virtual double GetProgress() const override; + + virtual ParameterNamesType GetParameterNames() const override; + + virtual ParameterNamesType GetDerivedParameterNames() const override; + + virtual ParameterNamesType GetCriterionNames() const override; + + virtual ParameterNamesType GetEvaluationParameterNames() const override; + +protected: + ROIBasedParameterFitImageGenerator() : m_Progress(0) + { + m_Mask = nullptr; + }; + + virtual ~ROIBasedParameterFitImageGenerator() override = default; + + template + void DoImageGeneration(itk::Image* image, double value); + + void onFitProgressEvent(::itk::Object* caller, const ::itk::EventObject& eventObject); + + virtual bool HasOutdatedResult() const override; + virtual void CheckValidInputs() const override; + virtual void DoFitAndGetResults(ParameterImageMapType& parameterImages, ParameterImageMapType& derivedParameterImages, ParameterImageMapType& criterionImages, ParameterImageMapType& evaluationParameterImages) override; + +private: + Image::Pointer m_Mask; + SignalType m_Signal; + TimeGridType m_TimeGrid; + + FitFunctorType::Pointer m_FitFunctor; + + Image::Pointer m_TempResultImage; + + ParameterizerType::Pointer m_ModelParameterizer; + + double m_Progress; +}; + +} + +#endif // __MITK_PARAMETER_FIT_IMAGE_GENERATOR_H_ diff --git a/Modules/ModelFit/include/mitkReducedChiSquareFitCostFunction.h b/Modules/ModelFit/include/mitkReducedChiSquareFitCostFunction.h new file mode 100644 index 0000000000..5195c71eb8 --- /dev/null +++ b/Modules/ModelFit/include/mitkReducedChiSquareFitCostFunction.h @@ -0,0 +1,36 @@ +#ifndef REDUCED_CHI_SQUARE_FITCOSTFUNCTION_H +#define REDUCED_CHI_SQUARE_FITCOSTFUNCTION_H + +#include + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT ReducedChiSquareFitCostFunction : public mitk::SVModelFitCostFunction + { + public: + typedef ReducedChiSquareFitCostFunction Self; + typedef mitk::SVModelFitCostFunction Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + itkNewMacro(Self); + + typedef Superclass::SignalType SignalType; + + protected: + + virtual MeasureType CalcMeasure(const ParametersType ¶meters, const SignalType& signal) const; + + ReducedChiSquareFitCostFunction() + { + + } + + ~ReducedChiSquareFitCostFunction(){} + + }; + +} +#endif // REDUCEDCHISQUAREFITCOSTFUNCTION_H diff --git a/Modules/ModelFit/include/mitkSVModelFitCostFunction.h b/Modules/ModelFit/include/mitkSVModelFitCostFunction.h new file mode 100644 index 0000000000..33e5363a70 --- /dev/null +++ b/Modules/ModelFit/include/mitkSVModelFitCostFunction.h @@ -0,0 +1,78 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef SV_MODELFITCOSTFUNCTION_H +#define SV_MODELFITCOSTFUNCTION_H + +#include +#include + +#include "mitkModelFitCostFunctionInterface.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + +/** Base class for all model fit cost function that return a singel cost value*/ +class MITKMODELFIT_EXPORT SVModelFitCostFunction : public itk::SingleValuedCostFunction, public ModelFitCostFunctionInterface +{ +public: + + typedef SVModelFitCostFunction Self; + typedef itk::SingleValuedCostFunction Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef ModelFitCostFunctionInterface::SignalType SignalType; + typedef Superclass::MeasureType MeasureType; + typedef Superclass::DerivativeType DerivativeType; + + void SetSample(const SignalType &sampleSet); + + MeasureType GetValue(const ParametersType& parameter) const; + void GetDerivative (const ParametersType ¶meters, DerivativeType &derivative) const; + + unsigned int GetNumberOfParameters (void) const; + + itkSetConstObjectMacro(Model, ModelBase); + itkGetConstObjectMacro(Model, ModelBase); + + itkSetMacro(DerivativeStepLength, double); + itkGetConstMacro(DerivativeStepLength, double); + +protected: + + virtual MeasureType CalcMeasure(const ParametersType ¶meters, const SignalType& signal) const = 0; + + SVModelFitCostFunction(): m_DerivativeStepLength(1e-5) + { + } + + ~SVModelFitCostFunction(){} + + SignalType m_Sample; + +private: + ModelBase::ConstPointer m_Model; + + /**value (delta of parameters) used to compute the derivatives numerically*/ + double m_DerivativeStepLength; +}; + +} + +#endif // SV_MODELFITCOSTFUNCTION_H diff --git a/Modules/ModelFit/include/mitkScalarListLookupTable.h b/Modules/ModelFit/include/mitkScalarListLookupTable.h new file mode 100644 index 0000000000..d5d419a197 --- /dev/null +++ b/Modules/ModelFit/include/mitkScalarListLookupTable.h @@ -0,0 +1,104 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkScalarListLookupTable_h +#define mitkScalarListLookupTable_h + +#include +#include +#include + +#include "MitkModelFitExports.h" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +namespace mitk +{ + /** + * @brief Data class for modelfit properties that store a map of lists (e.g. static + * parameters). + */ + class MITKMODELFIT_EXPORT ScalarListLookupTable + { + public: + typedef std::string KeyType; + typedef std::vector ValueType; + typedef std::map LookupTableType; + typedef std::pair EntryType; + + ScalarListLookupTable() {} + virtual ~ScalarListLookupTable() {} + + virtual const char* GetNameOfClass() const; + + /** + * @brief Sets the list at the given map key to the given value. + * @param key The name of the list (i.e. map key). + * @param value The list to be added (i.e. map value). + */ + void SetTableValue(const KeyType& key, const ValueType& value); + + /** + * @brief Returns true if the list with the given name exists. + * @param key The name of the desired list (i.e. map key) + * @return true if the list exists or false otherwise. + */ + bool ValueExists(const KeyType& key) const; + + /** + * @brief Returns the list with the given name. + * @param key The name (i.e. map key) of the desired list. + * @return The list with the given name. + * @throw std::range_error If the list doesn't exist. + */ + const ValueType& GetTableValue(const KeyType& key) const; + + /** + * @brief Returns the map of lists. + * @return The map of lists. + */ + const LookupTableType& GetLookupTable() const; + + void SetLookupTable(const LookupTableType& table); + + bool operator==(const ScalarListLookupTable& lookupTable) const; + bool operator!=(const ScalarListLookupTable& lookupTable) const; + + virtual ScalarListLookupTable& operator=(const ScalarListLookupTable& other); + + protected: + LookupTableType m_LookupTable; + }; + + /** + * @brief Adds the string representation of the given ScalarListLookupTable to the + * given stream. + * @param stream The stream to which the map's string representation should be added. + * @param l The map whose string representation should be added to the stream. + * @return The given stream with the added string representation of the map. + */ + MITKMODELFIT_EXPORT std::ostream& operator<<(std::ostream& stream, + const ScalarListLookupTable& l); +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // mitkScalarListLookupTable_h diff --git a/Modules/ModelFit/include/mitkScalarListLookupTableProperty.h b/Modules/ModelFit/include/mitkScalarListLookupTableProperty.h new file mode 100644 index 0000000000..16009c7a98 --- /dev/null +++ b/Modules/ModelFit/include/mitkScalarListLookupTableProperty.h @@ -0,0 +1,31 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkScalarListLookupTableProperty_h +#define mitkScalarListLookupTableProperty_h + +#include "MitkModelFitExports.h" +#include "mitkGenericProperty.h" +#include "mitkScalarListLookupTable.h" + +namespace mitk +{ + mitkDeclareGenericProperty(ScalarListLookupTableProperty, ScalarListLookupTable, + MITKMODELFIT_EXPORT); +} + + +#endif // mitkScalarListLookupTableProperty_h diff --git a/Modules/ModelFit/include/mitkScalarListLookupTablePropertySerializer.h b/Modules/ModelFit/include/mitkScalarListLookupTablePropertySerializer.h new file mode 100644 index 0000000000..8fce7fef5a --- /dev/null +++ b/Modules/ModelFit/include/mitkScalarListLookupTablePropertySerializer.h @@ -0,0 +1,59 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkScalarListLookupTablePropertySerializer_h +#define mitkScalarListLookupTablePropertySerializer_h + +#include "mitkBasePropertySerializer.h" + +#include "mitkBaseProperty.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /** + * @brief Serializer for the ScalarListLookupTableProperty so it can be written and read from + * file. + */ + class ScalarListLookupTablePropertySerializer : public BasePropertySerializer + { + public: + mitkClassMacro(ScalarListLookupTablePropertySerializer, BasePropertySerializer); + itkNewMacro(Self); + + virtual TiXmlElement* Serialize(); + virtual BaseProperty::Pointer Deserialize(TiXmlElement* element); + + protected: + ScalarListLookupTablePropertySerializer() {} + virtual ~ScalarListLookupTablePropertySerializer() {} + }; + + namespace PropertyPersistenceSerialization + { + /** Serialization of a ScalarListLookupTableProperty into a XML string.*/ + MITKMODELFIT_EXPORT ::std::string serializeScalarListLookupTablePropertyToXML(const mitk::BaseProperty *prop); + } + + namespace PropertyPersistenceDeserialization + { + /**Deserialize a passed XML string into a ScalarListLookupTableProperty.*/ + MITKMODELFIT_EXPORT mitk::BaseProperty::Pointer deserializeXMLToScalarListLookupTableProperty(const std::string &value); + } +} + +#endif // mitkScalarListLookupTablePropertySerializer_h diff --git a/Modules/ModelFit/include/mitkSimpleBarrierConstraintChecker.h b/Modules/ModelFit/include/mitkSimpleBarrierConstraintChecker.h new file mode 100644 index 0000000000..93d18f07e8 --- /dev/null +++ b/Modules/ModelFit/include/mitkSimpleBarrierConstraintChecker.h @@ -0,0 +1,130 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef SIMPLE_BARRIER_CONSTRAINT_CHECKER_H +#define SIMPLE_BARRIER_CONSTRAINT_CHECKER_H + +#include "mitkConstraintCheckerBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /** \class SimpleBarrierConstraintChecker + * \brief This class implements constraints as simple barrier functions. + * + * SimpleBarrierConstraintChecker is used to check parameters against inequality + * constraints realized as simple barrier functions.\n + * Inequality constraints will be transformed to an inequality greater + * or equal zero (c(x)>= 0). The BarrierSize indicates the size of the + * region in front of the border of the legal value range. The barrier + * function is modelled by log(c(x)/BarrierSize).\n + * Example:\n + * The given constraint is 500<= param_1. Its barriersize is 50, so + * the barrier region is between 500 and 550.\n + * The constraint will be transformed in 0 <= param_1 - 500. + * The barrier function will 0 for any param_1 > 550 and + * min(-log((param_1 - 500)/50), MaxConstraintPenalty) + * for any other value of param_1.\n + * If you have set a sum barrier, it will be checked against the value sum of the + * specified parameters. + */ + class MITKMODELFIT_EXPORT SimpleBarrierConstraintChecker : public ConstraintCheckerBase + { + public: + typedef SimpleBarrierConstraintChecker Self; + typedef ConstraintCheckerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkFactorylessNewMacro(Self); + + typedef Superclass::PenaltyValueType PenaltyValueType; + typedef Superclass::PenaltyArrayType PenaltyArrayType; + typedef Superclass::SignalType SignalType; + typedef Superclass::ParametersType ParametersType; + + typedef double BarrierValueType; + typedef double BarrierWidthType; + typedef ParametersType::SizeValueType ParameterIndexType; + typedef std::vector ParameterIndexVectorType; + + struct Constraint + { + ParameterIndexVectorType parameters; + BarrierValueType barrier; + BarrierWidthType width; + bool upperBarrier; + Constraint(): barrier(0), width(0), upperBarrier(true) + {}; + }; + + virtual PenaltyArrayType GetPenalties(const ParametersType& parameters) const override; + + virtual unsigned int GetNumberOfConstraints() const override; + + virtual PenaltyValueType GetFailedConstraintValue() const override; + + /** Sets a lower barrier for one parameter*/ + void SetLowerBarrier(ParameterIndexType parameterID, BarrierValueType barrier, + BarrierWidthType width = 0.0); + /** Sets an upper barrier for one parameter*/ + void SetUpperBarrier(ParameterIndexType parameterID, BarrierValueType barrier, + BarrierWidthType width = 0.0); + /** Sets a lower sum barrier for a set of parameter*/ + void SetLowerSumBarrier(const ParameterIndexVectorType& parameterIDs, BarrierValueType barrier, + BarrierWidthType width = 0.0); + /** Sets an upper sum barrier for a set of parameter*/ + void SetUpperSumBarrier(const ParameterIndexVectorType& parameterIDs, BarrierValueType barrier, + BarrierWidthType width = 0.0); + + /*returns the constraint with the given index. + @pre The index must exist.*/ + Constraint& GetConstraint(unsigned int index); + /*returns the constraint with the given index. + @pre The index must exist.*/ + const Constraint& GetConstraint(unsigned int index) const; + + /*removes a constraint. Indicated by the index. If the index does not exist, + nothing will be removed and the state of the checker stays untouched.*/ + void DeleteConstraint(unsigned int index); + + void ResetConstraints(); + + itkSetMacro(MaxConstraintPenalty, PenaltyValueType); + itkGetConstMacro(MaxConstraintPenalty, PenaltyValueType); + + protected: + + typedef std::vector ConstraintVectorType; + ConstraintVectorType m_Constraints; + + PenaltyValueType CalcPenalty(const ParametersType& parameters, const Constraint& constraint) const; + + SimpleBarrierConstraintChecker() : m_MaxConstraintPenalty(1e15) + { + } + + ~SimpleBarrierConstraintChecker() {} + + private: + PenaltyValueType m_MaxConstraintPenalty; + }; + +} + +#endif // SimpleBarrierConstraintChecker_H diff --git a/Modules/ModelFit/include/mitkSimpleFunctorBase.h b/Modules/ModelFit/include/mitkSimpleFunctorBase.h new file mode 100644 index 0000000000..5d12fec810 --- /dev/null +++ b/Modules/ModelFit/include/mitkSimpleFunctorBase.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef SIMPLEFUNCTORBASE_H +#define SIMPLEFUNCTORBASE_H + +#include + +#include + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /**Simple functor base class for the itkMultiOutputNaryFunctorImageFilter. */ + class MITKMODELFIT_EXPORT SimpleFunctorBase: public ::itk::Object + { + public: + typedef SimpleFunctorBase Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(SimpleFunctorBase, itk::Object); + + typedef ScalarType InputImagePixelType; + typedef std::vector InputPixelVectorType; + typedef std::vector OutputPixelVectorType; + + typedef itk::Array GridArrayType; + + virtual GridArrayType GetGrid() const = 0; + + virtual OutputPixelVectorType Compute(const InputPixelVectorType & value) const = 0; + + /** @todo #3 Function needs to be implemented in every derived Functor + * The function is already declared here to ensure that derived models give feedback on how many output parameters they produce + * This is requested by several generators + */ + virtual unsigned int GetNumberOfOutputs() const = 0; + + protected: + + SimpleFunctorBase(); + + virtual ~SimpleFunctorBase(); + + }; + +} + + +#endif // SIMPLEFUNCTORBASE_H diff --git a/Modules/ModelFit/include/mitkSimpleFunctorPolicy.h b/Modules/ModelFit/include/mitkSimpleFunctorPolicy.h new file mode 100644 index 0000000000..27d5827cca --- /dev/null +++ b/Modules/ModelFit/include/mitkSimpleFunctorPolicy.h @@ -0,0 +1,70 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef SIMPLEFUNCTOR_POLICY_H +#define SIMPLEFUNCTOR_POLICY_H + +#include "itkIndex.h" +#include "mitkSimpleFunctorBase.h" +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT SimpleFunctorPolicy + { + public: + typedef std::vector InputPixelArrayType; + typedef std::vector OutputPixelArrayType; + + typedef SimpleFunctorBase FunctorType; + typedef SimpleFunctorBase::ConstPointer FunctorConstPointer; + + typedef itk::Index<3> IndexType; + + SimpleFunctorPolicy(); + + ~SimpleFunctorPolicy(); + + unsigned int GetNumberOfOutputs() const; + + void SetFunctor(const mitk::SimpleFunctorBase *functor); + + bool operator!=(const SimpleFunctorPolicy & other) const; + + bool operator==(const SimpleFunctorPolicy & other) const; + + inline OutputPixelArrayType operator()( const InputPixelArrayType & value, const IndexType& /*currentIndex*/ ) const + { + if (!m_Functor) + { + itkGenericExceptionMacro(<< "Error. Cannot process operator(). Functor is Null."); + } + + OutputPixelArrayType result = m_Functor->Compute(value); + + return result; + } + + private: + + FunctorConstPointer m_Functor; + }; + +} + + +#endif // SIMPLEFUNCTORPOLICY_H diff --git a/Modules/ModelFit/include/mitkSquaredDifferencesFitCostFunction.h b/Modules/ModelFit/include/mitkSquaredDifferencesFitCostFunction.h new file mode 100644 index 0000000000..df9a201591 --- /dev/null +++ b/Modules/ModelFit/include/mitkSquaredDifferencesFitCostFunction.h @@ -0,0 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef SQUARED_DIFFERENCES_FITCOSTFUNCTION_H +#define SQUARED_DIFFERENCES_FITCOSTFUNCTION_H + +#include + +#include "MitkModelFitExports.h" + +namespace mitk +{ + +/** Multi valued model fit cost function that computes the squared differences between the model output and the + * signal. +*/ +class MITKMODELFIT_EXPORT SquaredDifferencesFitCostFunction : public mitk::MVModelFitCostFunction +{ +public: + + typedef SquaredDifferencesFitCostFunction Self; + typedef mitk::MVModelFitCostFunction Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkNewMacro(Self); + + typedef Superclass::SignalType SignalType; + +protected: + + virtual MeasureType CalcMeasure(const ParametersType ¶meters, const SignalType& signal) const; + + SquaredDifferencesFitCostFunction() + { + } + + ~SquaredDifferencesFitCostFunction(){} +}; + +} + +#endif // SquaredDifferencesFitCostFunction_H diff --git a/Modules/ModelFit/include/mitkSumOfSquaredDifferencesFitCostFunction.h b/Modules/ModelFit/include/mitkSumOfSquaredDifferencesFitCostFunction.h new file mode 100644 index 0000000000..e40cb0450e --- /dev/null +++ b/Modules/ModelFit/include/mitkSumOfSquaredDifferencesFitCostFunction.h @@ -0,0 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef SUM_OF_SQUARED_DIFFERENCES_FITCOSTFUNCTION_H +#define SUM_OF_SQUARED_DIFFERENCES_FITCOSTFUNCTION_H + +#include + +#include "MitkModelFitExports.h" + +namespace mitk +{ + +/** Multi valued model fit cost function that computes the squared differences between the model output and the + * signal. +*/ +class MITKMODELFIT_EXPORT SumOfSquaredDifferencesFitCostFunction : public mitk::SVModelFitCostFunction +{ +public: + + typedef SumOfSquaredDifferencesFitCostFunction Self; + typedef mitk::SVModelFitCostFunction Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkNewMacro(Self); + + typedef Superclass::SignalType SignalType; + +protected: + + virtual MeasureType CalcMeasure(const ParametersType ¶meters, const SignalType& signal) const; + + SumOfSquaredDifferencesFitCostFunction() + { + } + + ~SumOfSquaredDifferencesFitCostFunction(){} +}; + +} + +#endif // SumOfSquaredDifferencesFitCostFunction_H diff --git a/Modules/ModelFit/include/mitkT2DecayModel.h b/Modules/ModelFit/include/mitkT2DecayModel.h new file mode 100644 index 0000000000..47faefaf46 --- /dev/null +++ b/Modules/ModelFit/include/mitkT2DecayModel.h @@ -0,0 +1,88 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_T2_DECAY_MODEL_H_ +#define __MITK_T2_DECAY_MODEL_H_ + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /** Simple model of the MR T2 signal decay. */ + class MITKMODELFIT_EXPORT T2DecayModel : public mitk::ModelBase + { + + public: + typedef T2DecayModel Self; + typedef mitk::ModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef Superclass::ParameterNameType ParameterNameType; + typedef Superclass::ParametersSizeType ParametersSizeType; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(T2DecayModel, ModelBase); + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual FunctionStringType GetFunctionString() const override; + + virtual std::string GetXName() const override; + + virtual ParameterNamesType GetParameterNames() const override; + + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParameterNamesType GetStaticParameterNames() const override; + + virtual ParametersSizeType GetNumberOfStaticParameters() const override; + + protected: + T2DecayModel() {}; + virtual ~T2DecayModel() {}; + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const; + + virtual void SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values); + virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const; + + private: + + //No copy constructor allowed + T2DecayModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; +} + +#endif diff --git a/Modules/ModelFit/include/mitkT2DecayModelFactory.h b/Modules/ModelFit/include/mitkT2DecayModelFactory.h new file mode 100644 index 0000000000..b9b815ad55 --- /dev/null +++ b/Modules/ModelFit/include/mitkT2DecayModelFactory.h @@ -0,0 +1,57 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __T2_DECAY_TEST_MODEL_FACTORY_H +#define __T2_DECAY_TEST_MODEL_FACTORY_H + +#include + +#include "mitkConcreteModelFactoryBase.h" +#include "mitkT2DecayModel.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT T2DecayModelFactory : public ConcreteModelFactoryBase + { + public: + mitkClassMacroItkParent(T2DecayModelFactory, ConcreteModelFactoryBase); + itkFactorylessNewMacro(Self); + + virtual ParametersType GetDefaultInitialParameterization() const override; + + ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override; + + protected: + virtual ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit) + const; + + T2DecayModelFactory(); + + virtual ~T2DecayModelFactory(); + + private: + + //No copy constructor allowed + T2DecayModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + + +#endif //__LINEAR_TEST_MODEL_FACTORY_H diff --git a/Modules/ModelFit/include/mitkT2DecayModelParameterizer.h b/Modules/ModelFit/include/mitkT2DecayModelParameterizer.h new file mode 100644 index 0000000000..aeb62bc389 --- /dev/null +++ b/Modules/ModelFit/include/mitkT2DecayModelParameterizer.h @@ -0,0 +1,67 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __T2_DECAY_MODEL_PARAMETERIZER_H +#define __T2_DECAY_MODEL_PARAMETERIZER_H + +#include "mitkConcreteModelParameterizerBase.h" +#include "mitkT2DecayModel.h" +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT T2DecayModelParameterizer : public + mitk::ConcreteModelParameterizerBase + { + public: + typedef T2DecayModelParameterizer Self; + typedef mitk::ConcreteModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(T2DecayModelParameterizer, + mitk::ConcreteModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + virtual ParametersType GetDefaultInitialParameterization() const override; + + protected: + T2DecayModelParameterizer(); + + virtual ~T2DecayModelParameterizer(); + + private: + + //No copy constructor allowed + T2DecayModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // __LINEAR_MODEL_PARAMETERIZER_H diff --git a/Modules/ModelFit/include/mitkTestArtifactGenerator.h b/Modules/ModelFit/include/mitkTestArtifactGenerator.h new file mode 100644 index 0000000000..e5e3334662 --- /dev/null +++ b/Modules/ModelFit/include/mitkTestArtifactGenerator.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __TEST_ARTIFACT_GENERATOR_H +#define __TEST_ARTIFACT_GENERATOR_H + +#include "itkImage.h" +#include "itkImageRegionIterator.h" + +#include "mitkImage.h" +#include "mitkImagePixelReadAccessor.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + typedef itk::Image TestImageType; + typedef itk::Image TestMaskType; + + TestImageType::Pointer MITKMODELFIT_EXPORT GenerateTestImage(int factor = 1); + + TestMaskType::Pointer MITKMODELFIT_EXPORT GenerateTestMask(); + + Image::Pointer MITKMODELFIT_EXPORT GenerateTestFrame(double timePoint); + + Image::Pointer MITKMODELFIT_EXPORT GenerateTestMaskMITK(); + + Image::Pointer MITKMODELFIT_EXPORT GenerateDynamicTestImageMITK(); + +} + +#endif diff --git a/Modules/ModelFit/include/mitkTestModel.h b/Modules/ModelFit/include/mitkTestModel.h new file mode 100644 index 0000000000..ac4abf2048 --- /dev/null +++ b/Modules/ModelFit/include/mitkTestModel.h @@ -0,0 +1,107 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_TEST_MODEL_H_ +#define __MITK_TEST_MODEL_H_ + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + /**Simple (linear) test model that is used to check functionality of default implementations in factories and stuff.*/ + class MITKMODELFIT_EXPORT TestModel : public mitk::ModelBase + { + + public: + typedef TestModel Self; + typedef mitk::ModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef Superclass::ParameterNameType ParameterNameType; + typedef Superclass::ParametersSizeType ParametersSizeType; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(TestModel, ModelBase); + + virtual ParamterScaleMapType GetParameterScales() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual FunctionStringType GetFunctionString() const override; + + virtual std::string GetXName() const override; + + virtual std::string GetXAxisName() const override; + + virtual std::string GetXAxisUnit() const override; + + virtual std::string GetYAxisName() const override; + + virtual std::string GetYAxisUnit() const override; + + virtual ParameterNamesType GetParameterNames() const override; + + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParameterNamesType GetStaticParameterNames() const override; + + virtual ParametersSizeType GetNumberOfStaticParameters() const override; + + virtual ParameterNamesType GetDerivedParameterNames() const override; + + virtual ParametersSizeType GetNumberOfDerivedParameters() const override; + + protected: + TestModel() {}; + virtual ~TestModel() {}; + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + virtual DerivedParameterMapType ComputeDerivedParameters(const mitk::ModelBase::ParametersType& + parameters) const override; + + virtual void SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values); + virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const + override; + + private: + + //No copy constructor allowed + TestModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; +} + +#endif diff --git a/Modules/ModelFit/include/mitkTestModelFactory.h b/Modules/ModelFit/include/mitkTestModelFactory.h new file mode 100644 index 0000000000..162c8d7512 --- /dev/null +++ b/Modules/ModelFit/include/mitkTestModelFactory.h @@ -0,0 +1,55 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __TEST_MODEL_FACTORY_H +#define __TEST_MODEL_FACTORY_H + +#include + +#include "mitkConcreteModelFactoryBase.h" +#include "mitkTestModel.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + + class MITKMODELFIT_EXPORT TestModelFactory : public ConcreteModelFactoryBase + { + public: + mitkClassMacro(TestModelFactory, ConcreteModelFactoryBase); + itkFactorylessNewMacro(Self); + + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + virtual ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit) + const; + + TestModelFactory(); + + virtual ~TestModelFactory(); + + private: + + //No copy constructor allowed + TestModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + + +#endif //__LINEAR_TEST_MODEL_FACTORY_H diff --git a/Modules/ModelFit/include/mitkTimeGridHelper.h b/Modules/ModelFit/include/mitkTimeGridHelper.h new file mode 100644 index 0000000000..2f4e7fdbfd --- /dev/null +++ b/Modules/ModelFit/include/mitkTimeGridHelper.h @@ -0,0 +1,35 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_TIME_GRID_HELPER_H_ +#define __MITK_TIME_GRID_HELPER_H_ + +#include "mitkModelBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /* Checks if the time grid is monotone increasing (timeGrid[n] <= timeGrid[n+1]). + * It is a precondition for the helper interpolate time grid.*/ + MITKMODELFIT_EXPORT bool TimeGridIsMonotonIncreasing(const ModelBase::TimeGridType timeGrid); + + /* Helper function that interpolates a passed signal to a new time grid. + * @pre The time grids must be monotone increasing. Use TimeGridIsMonotonIncreasing() to verify that.*/ + MITKMODELFIT_EXPORT ModelBase::ModelResultType InterpolateSignalToNewTimeGrid(const ModelBase::ModelResultType& inputSignal, const ModelBase::TimeGridType& inputGrid, const ModelBase::TimeGridType& outputGrid); +} + +#endif diff --git a/Modules/ModelFit/include/mitkValueBasedParameterizationDelegate.h b/Modules/ModelFit/include/mitkValueBasedParameterizationDelegate.h new file mode 100644 index 0000000000..bed752876c --- /dev/null +++ b/Modules/ModelFit/include/mitkValueBasedParameterizationDelegate.h @@ -0,0 +1,76 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __VALUE_BASED_PARAMETERIZATION_DELEGATE_H +#define __VALUE_BASED_PARAMETERIZATION_DELEGATE_H + +#include +#include + +#include "mitkInitialParameterizationDelegateBase.h" + +#include "MitkModelFitExports.h" + +namespace mitk +{ + /** Parameterization delegate that always use parameters defined by the users. + */ + class MITKMODELFIT_EXPORT ValueBasedParameterizationDelegate : public + InitialParameterizationDelegateBase + { + public: + typedef ValueBasedParameterizationDelegate Self; + typedef InitialParameterizationDelegateBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + itkTypeMacro(ValueBasedParameterizationDelegate, InitialParameterizationDelegateBase); + + typedef Superclass::ModelBaseType ModelBaseType; + + typedef Superclass::ParametersType ParametersType; + + typedef Superclass::IndexType IndexType; + + void SetInitialParameterization(ParametersType params); + + /** Returns the parameterization (e.g. initial parametrization for fitting) that should be used. + If no ParameterizationDelegate is set (see SetInitialParameterizationDelegate()) it will just return + the result of GetInitialParameterization().*/ + virtual ParametersType GetInitialParameterization() const; + virtual ParametersType GetInitialParameterization(const IndexType& currentPosition) const; + + protected: + + ParametersType m_Parameterization; + + ValueBasedParameterizationDelegate(); + + virtual ~ValueBasedParameterizationDelegate(); + + private: + + //No copy constructor allowed + ValueBasedParameterizationDelegate(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // __MODEL_PARAMETERIZER_BASE_H diff --git a/Modules/ModelFit/src/Common/mitkBinaryImageToLabelSetImageFilter.cpp b/Modules/ModelFit/src/Common/mitkBinaryImageToLabelSetImageFilter.cpp new file mode 100644 index 0000000000..beb24061dd --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkBinaryImageToLabelSetImageFilter.cpp @@ -0,0 +1,100 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkBinaryImageToLabelSetImageFilter.h" + +#include +#include +#include +#include + +//itk +#include +#include + + + template + void mitk::BinaryImageToLabelSetImageFilter::ApplyBinaryImageToLabelMapFilter(const itk::Image* inputImage) + { + using ImageType = itk::Image; + using BinaryImageToLabelMapFilterType = itk::BinaryImageToLabelMapFilter; + typename BinaryImageToLabelMapFilterType::Pointer binaryImageToLabelMapFilter = BinaryImageToLabelMapFilterType::New(); + binaryImageToLabelMapFilter->SetInput(inputImage); + binaryImageToLabelMapFilter->SetInputForegroundValue(m_ForegroundValue); + binaryImageToLabelMapFilter->SetFullyConnected(m_FullyConnected); + + using LabelMap2ImageType = itk::LabelMapToLabelImageFilter< typename BinaryImageToLabelMapFilterType::OutputImageType, ImageType>; + + typename LabelMap2ImageType::Pointer label2image = LabelMap2ImageType::New(); + label2image->SetInput(binaryImageToLabelMapFilter->GetOutput()); + label2image->Update(); + auto labeledImage = mitk::ImportItkImage(label2image->GetOutput()); + + if (m_OutputIsLabelSetImage) { + auto labeledBinaryImage = mitk::LabelSetImage::New(); + labeledBinaryImage->InitializeByLabeledImage(labeledImage); + this->SetOutput(MakeNameFromOutputIndex(0), labeledBinaryImage.GetPointer()); + } + else { + this->SetOutput(MakeNameFromOutputIndex(0), labeledImage.GetPointer()); + } + } + + void mitk::BinaryImageToLabelSetImageFilter::VerifyInputImage(const mitk::Image* inputImage) + { + if (!inputImage->IsInitialized()) + mitkThrow() << "Input image is not initialized."; + + if (!inputImage->IsVolumeSet()) + mitkThrow() << "Input image volume is not set."; + + auto geometry = inputImage->GetGeometry(); + + if (nullptr == geometry || !geometry->IsValid()) + mitkThrow() << "Input image has invalid geometry."; + + if (!geometry->GetImageGeometry()) + mitkThrow() << "Geometry of input image is not an image geometry."; + } + +void mitk::BinaryImageToLabelSetImageFilter::GenerateData() +{ + const auto* inputImage = this->GetInput(); + AccessByItk(inputImage, ApplyBinaryImageToLabelMapFilter); +} + +void mitk::BinaryImageToLabelSetImageFilter::SetInput(const InputImageType* image) +{ + if (this->GetInput() == image) + return; + + Superclass::SetInput(image); +} + +void mitk::BinaryImageToLabelSetImageFilter::SetInput(unsigned int index, const InputImageType* image) +{ + if (0 != index) + mitkThrow() << "Input index " << index << " is invalid."; + + this->SetInput(image); +} + +void mitk::BinaryImageToLabelSetImageFilter::VerifyInputInformation() +{ + Superclass::VerifyInputInformation(); + + VerifyInputImage(this->GetInput()); +} diff --git a/Modules/ModelFit/src/Common/mitkExtractTimeGrid.cpp b/Modules/ModelFit/src/Common/mitkExtractTimeGrid.cpp new file mode 100644 index 0000000000..108bc787bc --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkExtractTimeGrid.cpp @@ -0,0 +1,53 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkExtractTimeGrid.h" + +mitk::ModelBase::TimeGridType mitk::ExtractTimeGrid(const Image* image) +{ + mitk::ModelBase::TimeGridType result; + if (image) + { + result = ExtractTimeGrid(image->GetTimeGeometry()); + } + return result; +}; + +mitk::ModelBase::TimeGridType mitk::ExtractTimeGrid(const TimeGeometry* geometry) +{ + mitk::ModelBase::TimeGridType result; + if (geometry) + { + unsigned int i = 0; + std::vector tempGrid; + while(geometry->IsValidTimeStep(i)) + { + tempGrid.push_back(geometry->TimeStepToTimePoint(i)/1000.0); + ++i; + } + + result.SetSize(tempGrid.size()); + + mitk::ModelBase::TimeGridType::iterator destPost = result.begin(); + + for(std::vector::iterator sourcePos = tempGrid.begin(); sourcePos != tempGrid.end(); ++sourcePos, ++destPost) + { + *destPost = *sourcePos; + } + } + + return result; +}; diff --git a/Modules/ModelFit/src/Common/mitkFormulaParser.cpp b/Modules/ModelFit/src/Common/mitkFormulaParser.cpp new file mode 100644 index 0000000000..fe8d95bbbb --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkFormulaParser.cpp @@ -0,0 +1,294 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include + +#include "mitkFormulaParser.h" +#include "mitkFresnel.h" + +namespace qi = boost::spirit::qi; +namespace ascii = boost::spirit::ascii; +namespace phx = boost::phoenix; + +typedef std::string::const_iterator Iter; +typedef ascii::space_type Skipper; + +namespace qi = boost::spirit::qi; + +namespace mitk +{ + /*! + * @brief Transforms the given number from degrees to radians and returns it. + * @tparam T The scalar type that represents a value (e.g. double). + * @param[in] deg A scalar value in degrees. + * @return The given value in radians. + */ + template + inline T deg2rad(const T deg) + { + return deg * boost::math::constants::pi() / static_cast(180); + } + + /*! + * @brief Returns the cosine of the given degree scalar. + * @tparam T The scalar type that represents a value (e.g. double). + * @param[in] t A scalar value in degrees whose cosine should be returned. + * @return The cosine of the given degree scalar. + */ + template + inline T cosd(const T t) + { + return std::cos(deg2rad(t)); + } + + /*! + * @brief Returns the sine of the given degree scalar. + * @tparam T The scalar type that represents a value (e.g. double). + * @param[in] t A scalar value in degrees whose sine should be returned. + * @return The sine of the given degree scalar. + */ + template + inline T sind(const T t) + { + return std::sin(deg2rad(t)); + } + + /*! + * @brief Returns the tangent of the given degree scalar. + * @tparam T The scalar type that represents a value (e.g. double). + * @param[in] t A scalar value in degrees whose tangent should be returned. + * @return The tangent of the given degree scalar. + */ + template + inline T tand(const T t) + { + return std::tan(deg2rad(t)); + } + + /*! + * @brief Returns the fresnel integral sine at the given x-coordinate. + * @details Code for "fresnel_s()" (fresnel.cpp and fresnel.h) taken as-is from the GNU + * Scientific Library (http://www.gnu.org/software/gsl/), specifically from + * http://www.network-theory.co.uk/download/gslextras/Fresnel/. + * @tparam T The scalar type that represents a value (e.g. double). + * @param[in] t The x-coordinate at which the fresnel integral sine should be returned. + * @return The fresnel integral sine at the given x-coordinate. + */ + template + T fresnelS(const T t) + { + T x = t / boost::math::constants::root_half_pi(); + return static_cast(fresnel_s(x) / boost::math::constants::root_two_div_pi()); + } + + /*! + * @brief Returns the fresnel integral cosine at the given x-coordinate. + * @details Code for "fresnel_c()" (fresnel.cpp and fresnel.h) taken as-is from the GNU + * Scientific Library (http://www.gnu.org/software/gsl/), specifically from + * http://www.network-theory.co.uk/download/gslextras/Fresnel/. + * @tparam T The scalar type that represents a value (e.g. double). + * @param[in] t The x-coordinate at which the fresnel integral cosine should be returned. + * @return The fresnel integral cosine at the given x-coordinate. + */ + template + T fresnelC(const T t) + { + T x = t / boost::math::constants::root_half_pi(); + return static_cast(fresnel_c(x) / boost::math::constants::root_two_div_pi()); + } + + /*! + * @brief The grammar that defines the language (i.e. what is allowed) for the parser. + */ + class Grammar : public qi::grammar + { + /*! + * @brief Helper structure that makes it easier to dynamically call any + * one-parameter-function by overloading the @c () operator. + */ + struct func1_ + { + // Required for Phoenix 3+ + template + struct result; + + /*! + * @brief Helper structure that is needed for compatibility with + * @c boost::phoenix. + * @tparam Functor Type of the functor (this struct). + * @tparam Function Type of the function that should be called. + * @tparam Arg1 Type of the argument the function should be called with. + * + */ + template + struct result + { + /*! @brief The result structure always needs this typedef */ + typedef Arg1 type; + }; + + /*! + * @brief Calls the function @b f with the argument @b a1 and returns the + * result. + * The result always has the same type as the argument. + * @tparam Function Type of the function that should be called. + * @tparam Arg1 Type of the argument the function should be called with. + * @param[in] f The function that should be called. + * @param[in] a1 The argument the function should be called with. + * @return The result of the called function. + */ + template + Arg1 operator()(const Function f, const Arg1 a1) const + { + return f(a1); + } + }; + + /*! + * @brief Helper structure that maps strings to function calls so that parsing e.g. + * @c "cos(0)" actually calls the @c std::cos function with parameter @c 1 so it + * returns @c 0. + */ + class unaryFunction_ : + public qi::symbols::value_type, FormulaParser::ValueType(*)(FormulaParser::ValueType)> + { + public: + /*! + * @brief Constructs the structure, this is where the mapping takes place. + */ + unaryFunction_() + { + this->add + ("abs", static_cast(&std::abs)) + ("exp", static_cast(&std::exp)) // @TODO: exp ignores division by zero + ("sin", static_cast(&std::sin)) + ("cos", static_cast(&std::cos)) + ("tan", static_cast(&std::tan)) + ("sind", &sind) + ("cosd", &cosd) + ("tand", &tand) + ("fresnelS", &fresnelS) + ("fresnelC", &fresnelC); + } + } unaryFunction; + + public: + /*! + * @brief Constructs the grammar with the given formula parser. + * @param[in, out] formulaParser The formula parser this grammar is for - so it can + * access its variable map. + */ + Grammar(FormulaParser& formulaParser) : Grammar::base_type(start) + { + using qi::_val; + using qi::_1; + using qi::_2; + using qi::char_; + using qi::alpha; + using qi::alnum; + using qi::double_; + using qi::as_string; + + phx::function func1; + + start = expression > qi::eoi; + + expression = term[_val = _1] + >> *(('+' >> term[_val += _1]) + | ('-' >> term[_val -= _1])); + + term = factor[_val = _1] + >> *(('*' >> factor[_val *= _1]) + | ('/' >> factor[_val /= _1])); + + factor = primary[_val = _1]; + /*! @TODO: Repair exponentiation */ + //>> *('^' >> factor[phx::bind(std::pow, _val, _1)]); + + variable = as_string[alpha >> *(alnum | char_('_'))] + [_val = phx::bind(&FormulaParser::lookupVariable, &formulaParser, _1)]; + + primary = double_[_val = _1] + | '(' >> expression[_val = _1] >> ')' + | ('-' >> primary[_val = -_1]) + | ('+' >> primary[_val = _1]) + | (unaryFunction >> '(' >> expression >> ')')[_val = func1(_1, _2)] + | variable[_val = _1]; + } + + /*! the rules of the grammar. */ + qi::rule start; + qi::rule expression; + qi::rule term; + qi::rule factor; + qi::rule variable; + qi::rule primary; + }; + + + FormulaParser::FormulaParser(const VariableMapType* variables) : m_Variables(variables) + {} + + FormulaParser::ValueType FormulaParser::parse(const std::string& input) + { + std::string::const_iterator iter = input.begin(); + std::string::const_iterator end = input.end(); + FormulaParser::ValueType result = static_cast(0); + + try + { + if (!qi::phrase_parse(iter, end, Grammar(*this), ascii::space, result)) + { + mitkThrowException(FormulaParserException) << "Could not parse '" << input << + "': Grammar could not be applied to the input " << "at all."; + } + } + catch (qi::expectation_failure& e) + { + std::string parsed = ""; + + for (Iter i = input.begin(); i != e.first; i++) + { + parsed += *i; + } + mitkThrowException(FormulaParserException) << "Error while parsing '" << input << + "': Unexpected character '" << *e.first << "' after '" << parsed << "'"; + } + + return result; + }; + + FormulaParser::ValueType FormulaParser::lookupVariable(const std::string var) + { + if (m_Variables == NULL) + { + mitkThrowException(FormulaParserException) << "Map of variables is empty"; + } + + try + { + return m_Variables->at(var); + } + catch (std::out_of_range&) + { + mitkThrowException(FormulaParserException) << "No variable '" << var << "' defined in lookup"; + } + }; + +} diff --git a/Modules/ModelFit/src/Common/mitkFresnel.cpp b/Modules/ModelFit/src/Common/mitkFresnel.cpp new file mode 100644 index 0000000000..4a533b10f4 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkFresnel.cpp @@ -0,0 +1,287 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +/**************************************************************************** + * fresnel.c - + * Calculation of Fresnel integrals by expansion to Chebyshev series + * Expansions are taken from the book + * Y.L. Luke. Mathematical functions and their approximations. + * Moscow, "Mir", 1980. PP. 145-149 (Russian edition) + **************************************************************************** + */ + +#include + +static const double sqrt_pi_2 = 1.2533141373155002512078826424; /* sqrt(pi/2) */ +static const double sqrt_2_pi = 0.7978845608028653558798921199; /* sqrt(2/pi) */ +static const double _1_sqrt_2pi = 0.3989422804014326779399460599; /* 1/sqrt(2*pi) */ +static const double pi_2 = 1.5707963267948966192313216916; /* pi/2 */ + +static double f_data_a[18] = +{ + 0.76435138664186000189, + -0.43135547547660179313, + 0.43288199979726653054, + -0.26973310338387111029, + 0.08416045320876935378, + -0.01546524484461381958, + 0.00187855423439822018, + -0.00016264977618887547, + 0.00001057397656383260, + -0.00000053609339889243, + 0.00000002181658454933, + -0.00000000072901621186, + 0.00000000002037332546, + -0.00000000000048344033, + 0.00000000000000986533, + -0.00000000000000017502, + 0.00000000000000000272, + -0.00000000000000000004 +}; + +static double f_data_b[17] = +{ + 0.63041404314570539241, + -0.42344511405705333544, + 0.37617172643343656625, + -0.16249489154509567415, + 0.03822255778633008694, + -0.00564563477132190899, + 0.00057454951976897367, + -0.00004287071532102004, + 0.00000245120749923299, + -0.00000011098841840868, + 0.00000000408249731696, + -0.00000000012449830219, + 0.00000000000320048425, + -0.00000000000007032416, + 0.00000000000000133638, + -0.00000000000000002219, + 0.00000000000000000032 +}; + +static double fresnel_cos_0_8(double x) +{ + double x_8 = x / 8.0; + double xx = 2.0*x_8*x_8 - 1.0; + + double t0 = 1.0; + double t1 = xx; + double sumC = f_data_a[0] + f_data_a[1] * t1; + double t2; + int n; + for (n = 2; n < 18; n++) + { + t2 = 2.0*xx*t1 - t0; + sumC += f_data_a[n] * t2; + t0 = t1; t1 = t2; + } + return _1_sqrt_2pi * sqrt(x)*sumC; +} + +static double fresnel_sin_0_8(double x) +{ + double x_8 = x / 8.0; + double xx = 2.0*x_8*x_8 - 1.0; + double t0 = 1.; + double t1 = xx; + double ot1 = x_8; + double ot2 = 2.0*x_8*t1 - ot1; + double sumS = f_data_b[0] * ot1 + f_data_b[1] * ot2; + int n; + double t2; + for (n = 2; n < 17; n++) + { + t2 = 2.0*xx*t1 - t0; + ot1 = ot2; + ot2 = 2.0*x_8*t2 - ot1; + sumS += f_data_b[n] * ot2; + t0 = t1; t1 = t2; + } + return _1_sqrt_2pi * sqrt(x)*sumS; +} + +static double f_data_e[41] = +{ + 0.97462779093296822410, + -0.02424701873969321371, + 0.00103400906842977317, + -0.00008052450246908016, + 0.00000905962481966582, + -0.00000131016996757743, + 0.00000022770820391497, + -0.00000004558623552026, + 0.00000001021567537083, + -0.00000000251114508133, + 0.00000000066704761275, + -0.00000000018931512852, + 0.00000000005689898935, + -0.00000000001798219359, + 0.00000000000594162963, + -0.00000000000204285065, + 0.00000000000072797580, + -0.00000000000026797428, + 0.00000000000010160694, + -0.00000000000003958559, + 0.00000000000001581262, + -0.00000000000000646411, + 0.00000000000000269981, + -0.00000000000000115038, + 0.00000000000000049942, + -0.00000000000000022064, + 0.00000000000000009910, + -0.00000000000000004520, + 0.00000000000000002092, + -0.00000000000000000982, + 0.00000000000000000467, + -0.00000000000000000225, + 0.00000000000000000110, + -0.00000000000000000054, + 0.00000000000000000027, + -0.00000000000000000014, + 0.00000000000000000007, + -0.00000000000000000004, + 0.00000000000000000002, + -0.00000000000000000001, + 0.00000000000000000001 +}; + +static double f_data_f[35] = +{ + 0.99461545179407928910, + -0.00524276766084297210, + 0.00013325864229883909, + -0.00000770856452642713, + 0.00000070848077032045, + -0.00000008812517411602, + 0.00000001359784717148, + -0.00000000246858295747, + 0.00000000050925789921, + -0.00000000011653400634, + 0.00000000002906578309, + -0.00000000000779847361, + 0.00000000000222802542, + -0.00000000000067239338, + 0.00000000000021296411, + -0.00000000000007041482, + 0.00000000000002419805, + -0.00000000000000861080, + 0.00000000000000316287, + -0.00000000000000119596, + 0.00000000000000046444, + -0.00000000000000018485, + 0.00000000000000007527, + -0.00000000000000003131, + 0.00000000000000001328, + -0.00000000000000000574, + 0.00000000000000000252, + -0.00000000000000000113, + 0.00000000000000000051, + -0.00000000000000000024, + 0.00000000000000000011, + -0.00000000000000000005, + 0.00000000000000000002, + -0.00000000000000000001, + 0.00000000000000000001 +}; + +static double fresnel_cos_8_inf(double x) +{ + double xx = 128.0 / (x*x) - 1.0; /* 2.0*(8/x)^2 - 1 */ + double t0 = 1.0; + double t1 = xx; + double sumP = f_data_e[0] + f_data_e[1] * t1; + double sumQ = f_data_f[0] + f_data_f[1] * t1; + double t2; + int n; + for (n = 2; n < 35; n++) + { + t2 = 2.0*xx*t1 - t0; + sumP += f_data_e[n] * t2; /* sumP += f_data_e[n]*ChebyshevT(n,xx) */ + sumQ += f_data_f[n] * t2; /* sumQ += f_data_f[n]*ChebyshevT(n,xx) */ + t0 = t1; t1 = t2; + } + for (n = 35; n < 41; n++) + { + t2 = 2.0*xx*t1 - t0; + sumP += f_data_e[n] * t2; /* sumP += f_data_e[n]*ChebyshevT(n,xx) */ + t0 = t1; t1 = t2; + } + return 0.5 - _1_sqrt_2pi * (0.5*sumP*cos(x) / x - sumQ * sin(x)) / sqrt(x); +} + +static double fresnel_sin_8_inf(double x) +{ + double xx = 128.0 / (x*x) - 1.0; /* 2.0*(8/x)^2 - 1 */ + double t0 = 1.0; + double t1 = xx; + double sumP = f_data_e[0] + f_data_e[1] * t1; + double sumQ = f_data_f[0] + f_data_f[1] * t1; + double t2; + int n; + for (n = 2; n < 35; n++) + { + t2 = 2.0*xx*t1 - t0; + sumP += f_data_e[n] * t2; /* sumP += f_data_e[n]*ChebyshevT(n,xx) */ + sumQ += f_data_f[n] * t2; /* sumQ += f_data_f[n]*ChebyshevT(n,xx) */ + t0 = t1; t1 = t2; + } + for (n = 35; n < 41; n++) + { + t2 = 2.0*xx*t1 - t0; + sumP += f_data_e[n] * t2; /* sumQ += f_data_f[n]*ChebyshevT(n,xx) */ + t0 = t1; t1 = t2; + } + return 0.5 - _1_sqrt_2pi * (0.5*sumP*sin(x) / x + sumQ * cos(x)) / sqrt(x); +} + + +namespace mitk +{ + + double fresnel_c(double x) + { + double xx = x * x*pi_2; + double ret_val; + if (xx <= 8.0) + ret_val = fresnel_cos_0_8(xx); + else + ret_val = fresnel_cos_8_inf(xx); + return (x < 0.0) ? -ret_val : ret_val; + } + + double fresnel_s(double x) + { + double xx = x * x*pi_2; + double ret_val; + if (xx <= 8.0) + ret_val = fresnel_sin_0_8(xx); + else + ret_val = fresnel_sin_8_inf(xx); + return (x < 0.0) ? -ret_val : ret_val; + } + + double fresnel_c2(double x) + { + return fresnel_c(x*sqrt_2_pi); + } + + double fresnel_s2(double x) + { + return fresnel_s(x*sqrt_2_pi); + } + +} diff --git a/Modules/ModelFit/src/Common/mitkIModelFitProvider.cpp b/Modules/ModelFit/src/Common/mitkIModelFitProvider.cpp new file mode 100644 index 0000000000..a4b4e7233d --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkIModelFitProvider.cpp @@ -0,0 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIModelFitProvider.h" + +namespace mitk +{ + IModelFitProvider::~IModelFitProvider() {} + std::string mitk::IModelFitProvider::PROP_DESCRIPTION() + { + static std::string s = "org.mitk.IModelFitProvider.description"; + return s; + } + + std::string mitk::IModelFitProvider::PROP_MODEL_CLASS_ID() + { + static std::string s = "org.mitk.IModelFitProvider.classid"; + return s; + } + + std::string mitk::IModelFitProvider::PROP_MODEL_TYPE() + { + static std::string s = "org.mitk.IModelFitProvider.modeltype"; + return s; + } +} \ No newline at end of file diff --git a/Modules/ModelFit/src/Common/mitkMaskedDynamicImageStatisticsGenerator.cpp b/Modules/ModelFit/src/Common/mitkMaskedDynamicImageStatisticsGenerator.cpp new file mode 100644 index 0000000000..60b95e0177 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkMaskedDynamicImageStatisticsGenerator.cpp @@ -0,0 +1,197 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkMaskedDynamicImageStatisticsGenerator.h" + +#include "mitkImageTimeSelector.h" +#include "mitkImageAccessByItk.h" +#include "mitkImageCast.h" +#include "itkMaskedNaryStatisticsImageFilter.h" + +mitk::MaskedDynamicImageStatisticsGenerator::MaskedDynamicImageStatisticsGenerator() +{ + m_Mask = NULL; + m_DynamicImage = NULL; +}; + +mitk::MaskedDynamicImageStatisticsGenerator::~MaskedDynamicImageStatisticsGenerator(){}; + +const mitk::MaskedDynamicImageStatisticsGenerator::ResultType& mitk::MaskedDynamicImageStatisticsGenerator::GetMaximum() +{ + if(this->HasOutdatedResults()) + { + CheckValidInputs(); + Generate(); + } + return m_Maximum; +}; + +const mitk::MaskedDynamicImageStatisticsGenerator::ResultType& mitk::MaskedDynamicImageStatisticsGenerator::GetMinimum() +{ + if(this->HasOutdatedResults()) + { + CheckValidInputs(); + Generate(); + } + return m_Minimum; +}; + +const mitk::MaskedDynamicImageStatisticsGenerator::ResultType& mitk::MaskedDynamicImageStatisticsGenerator::GetMean() +{ + if(this->HasOutdatedResults()) + { + CheckValidInputs(); + Generate(); + } + return m_Mean; +}; + +const mitk::MaskedDynamicImageStatisticsGenerator::ResultType& mitk::MaskedDynamicImageStatisticsGenerator::GetSigma() +{ + if(this->HasOutdatedResults()) + { + CheckValidInputs(); + Generate(); + } + return m_Sigma; +}; + +const mitk::MaskedDynamicImageStatisticsGenerator::ResultType& mitk::MaskedDynamicImageStatisticsGenerator::GetVariance() +{ + if(this->HasOutdatedResults()) + { + CheckValidInputs(); + Generate(); + } + return m_Variance; +}; + +const mitk::MaskedDynamicImageStatisticsGenerator::ResultType& mitk::MaskedDynamicImageStatisticsGenerator::GetSum() +{ + if(this->HasOutdatedResults()) + { + CheckValidInputs(); + Generate(); + } + return m_Sum; +}; + +template +void mitk::MaskedDynamicImageStatisticsGenerator::DoCalculateStatistics(const itk::Image* /*image*/) +{ + typedef itk::Image InputFrameImageType; + typedef itk::MaskedNaryStatisticsImageFilter FilterType; + + typename FilterType::Pointer statFilter = FilterType::New(); + + //add the time frames to the fit filter + unsigned int timeSteps = this->m_DynamicImage->GetTimeSteps(); + std::vector frameCache; + for (unsigned int i = 0; i < timeSteps; ++i) + { + typename InputFrameImageType::Pointer frameImage; + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(this->m_DynamicImage); + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + Image::Pointer frameMITKImage = imageTimeSelector->GetOutput(); + frameCache.push_back(frameMITKImage); + mitk::CastToItkImage(frameMITKImage, frameImage); + statFilter->SetInput(i,frameImage); + } + + if (this->m_InternalMask.IsNotNull()) + { + statFilter->SetMask(this->m_InternalMask); + } + + statFilter->Update(); + + m_Maximum.SetSize(timeSteps); + m_Minimum.SetSize(timeSteps); + m_Mean.SetSize(timeSteps); + m_Sigma.SetSize(timeSteps); + m_Variance.SetSize(timeSteps); + m_Sum.SetSize(timeSteps); + + for (unsigned int i = 0; i < timeSteps; ++i) + { + m_Maximum.SetElement(i,statFilter->GetMaximum()[i]); + m_Minimum.SetElement(i,statFilter->GetMinimum()[i]); + m_Mean.SetElement(i,statFilter->GetMean()[i]); + m_Sigma.SetElement(i,statFilter->GetSigma()[i]); + m_Variance.SetElement(i,statFilter->GetVariance()[i]); + m_Sum.SetElement(i,statFilter->GetSum()[i]); + } + + this->m_GenerationTimeStamp.Modified(); +} + +void mitk::MaskedDynamicImageStatisticsGenerator::Generate() +{ + if(this->m_Mask.IsNotNull()) + { + InternalMaskType::Pointer castedMask; + CastToItkImage(m_Mask, castedMask); + if (castedMask.IsNull()) + { + mitkThrow() << "Dynamic cast of mask went wrong. Internal Mask is NULL. Image statistics cannot be generated."; + } + + this->m_InternalMask = castedMask; + } + else + { + this->m_InternalMask = NULL; + } + + AccessFixedDimensionByItk(m_DynamicImage, mitk::MaskedDynamicImageStatisticsGenerator::DoCalculateStatistics, 4); +} + +void + mitk::MaskedDynamicImageStatisticsGenerator::CheckValidInputs() const +{ + + if (m_DynamicImage.IsNull()) + { + mitkThrow() << "Cannot generate statistics. Input dynamic image is not set."; + } +} + +bool + mitk::MaskedDynamicImageStatisticsGenerator::HasOutdatedResults() const +{ + bool result = this->GetMTime() > this->m_GenerationTimeStamp; + + if (m_DynamicImage.IsNotNull()) + { + if (m_DynamicImage->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + if (m_Mask.IsNotNull()) + { + if (m_Mask->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + return result; + +}; diff --git a/Modules/ModelFit/src/Common/mitkModelFitCmdAppsHelper.cpp b/Modules/ModelFit/src/Common/mitkModelFitCmdAppsHelper.cpp new file mode 100644 index 0000000000..ed0319d98b --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkModelFitCmdAppsHelper.cpp @@ -0,0 +1,124 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + + +std::string sanitizeString(const std::string& path) +{ + auto result = path; + std::string illegalChars = "\\/:?\"<>|%* "; + for (auto &c : result) + { + bool found = illegalChars.find(c) != std::string::npos; + if (found){ + c = '_'; + } + } + return result; +} + +MITKMODELFIT_EXPORT std::string mitk::generateModelFitResultImagePath(const std::string& outputPathTemplate, const std::string& parameterName) +{ + std::string ext = ::itksys::SystemTools::GetFilenameLastExtension(outputPathTemplate); + + std::string dir = itksys::SystemTools::GetFilenamePath(outputPathTemplate); + dir = itksys::SystemTools::ConvertToOutputPath(dir); + + std::string rootName = itksys::SystemTools::GetFilenameWithoutLastExtension(outputPathTemplate); + + std::string fileName = rootName + "_" + sanitizeString(parameterName) + ext; + + std::string fullOutPath = itksys::SystemTools::ConvertToOutputPath(dir + "/" + fileName); + + return fullOutPath; +} + +std::string convertParameterTypeToStr(mitk::modelFit::Parameter::Type type) +{ + switch (type) + { + case mitk::modelFit::Parameter::ParameterType: return "parameter"; + case mitk::modelFit::Parameter::DerivedType: return "derived"; + case mitk::modelFit::Parameter::CriterionType: return "criterion"; + case mitk::modelFit::Parameter::EvaluationType: return "evaluation"; + default: return "unkown"; + } +} + +MITKMODELFIT_EXPORT void mitk::storeModelFitResultImage(const std::string& outputPathTemplate, const std::string& parameterName, mitk::Image* image, mitk::modelFit::Parameter::Type nodeType, const mitk::modelFit::ModelFitInfo* modelFitInfo) +{ + mitk::modelFit::SetModelFitDataProperties(image, parameterName, nodeType, modelFitInfo); + + storeParameterResultImage(outputPathTemplate, parameterName, image, nodeType); +} + +MITKMODELFIT_EXPORT void mitk::storeParameterResultImage(const std::string& outputPathTemplate, const std::string& parameterName, mitk::Image* image, mitk::modelFit::Parameter::Type parameterType) +{ + std::string fullOutPath = generateModelFitResultImagePath(outputPathTemplate, parameterName); + + mitk::IOUtil::Save(image, fullOutPath); + + std::cout << "Store result " << convertParameterTypeToStr(parameterType) << ": " << parameterName << " -> " << fullOutPath << std::endl; +} + +MITKMODELFIT_EXPORT void mitk::storeModelFitGeneratorResults(const std::string& outputPathTemplate, mitk::ParameterFitImageGeneratorBase* generator, const mitk::modelFit::ModelFitInfo* fitSession) +{ + if (generator) + { + for (auto imageIterator : generator->GetParameterImages()) + { + storeModelFitResultImage(outputPathTemplate, imageIterator.first, imageIterator.second, mitk::modelFit::Parameter::ParameterType, fitSession); + } + for (auto imageIterator : generator->GetDerivedParameterImages()) + { + storeModelFitResultImage(outputPathTemplate, imageIterator.first, imageIterator.second, mitk::modelFit::Parameter::DerivedType, fitSession); + } + for (auto imageIterator : generator->GetCriterionImages()) + { + storeModelFitResultImage(outputPathTemplate, imageIterator.first, imageIterator.second, mitk::modelFit::Parameter::CriterionType, fitSession); + } + for (auto imageIterator : generator->GetEvaluationParameterImages()) + { + storeModelFitResultImage(outputPathTemplate, imageIterator.first, imageIterator.second, mitk::modelFit::Parameter::EvaluationType, fitSession); + } + } +} + + +MITKMODELFIT_EXPORT void mitk::previewModelFitGeneratorResults(const std::string& outputPathTemplate, mitk::ParameterFitImageGeneratorBase* generator) +{ + if (generator) + { + for (auto aName : generator->GetParameterNames()) + { + std::cout << "Store result " << convertParameterTypeToStr(modelFit::Parameter::ParameterType) << ": " << aName << " -> " << generateModelFitResultImagePath(outputPathTemplate, aName) << std::endl; + } + for (auto aName : generator->GetDerivedParameterNames()) + { + std::cout << "Store result " << convertParameterTypeToStr(modelFit::Parameter::DerivedType) << ": " << aName << " -> " << generateModelFitResultImagePath(outputPathTemplate, aName) << std::endl; + } + for (auto aName : generator->GetCriterionNames()) + { + std::cout << "Store result " << convertParameterTypeToStr(modelFit::Parameter::CriterionType) << ": " << aName << " -> " << generateModelFitResultImagePath(outputPathTemplate, aName) << std::endl; + } + for (auto aName : generator->GetEvaluationParameterNames()) + { + std::cout << "Store result " << convertParameterTypeToStr(modelFit::Parameter::EvaluationType) << ": " << aName << " -> " << generateModelFitResultImagePath(outputPathTemplate, aName) << std::endl; + } + std::cout << "Preview done." << std::endl; + } +} diff --git a/Modules/ModelFit/src/Common/mitkModelFitConstants.cpp b/Modules/ModelFit/src/Common/mitkModelFitConstants.cpp new file mode 100644 index 0000000000..7f990249fd --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkModelFitConstants.cpp @@ -0,0 +1,50 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelFitConstants.h" + + +const std::string mitk::ModelFitConstants::MODEL_FIT_PROPERTY_NAME() { return "modelfit";} +const std::string mitk::ModelFitConstants::UID_PROPERTY_NAME() { return "data.uid";} +const std::string mitk::ModelFitConstants::INPUT_VARIABLES_PROPERTY_NAME() { return "modelfit.input.variables";} +const std::string mitk::ModelFitConstants::PARAMETER_NAME_PROPERTY_NAME() { return "modelfit.parameter.name";} +const std::string mitk::ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME() { return "modelfit.parameter.type";} +const std::string mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_PARAMETER() { return "parameter";} +const std::string mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_DERIVED_PARAMETER() { return "derived";} +const std::string mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_CRITERION() { return "criterion";} +const std::string mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_EVALUATION_PARAMETER() { return "evaluation";} +const std::string mitk::ModelFitConstants::PARAMETER_UNIT_PROPERTY_NAME() { return "modelfit.parameter.unit";} +const std::string mitk::ModelFitConstants::PARAMETER_SCALE_PROPERTY_NAME() { return "modelfit.parameter.scale";} +const std::string mitk::ModelFitConstants::MODEL_TYPE_PROPERTY_NAME() { return "modelfit.model.type";} +const std::string mitk::ModelFitConstants::MODEL_NAME_PROPERTY_NAME() { return "modelfit.model.name";} +const std::string mitk::ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME() { return "modelfit.model.function";} +const std::string mitk::ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME() { return "modelfit.model.functionClass";} +const std::string mitk::ModelFitConstants::MODEL_X_PROPERTY_NAME() { return "modelfit.model.x";} +const std::string mitk::ModelFitConstants::MODEL_X_VALUE_DEFAULT() { return "x";} +const std::string mitk::ModelFitConstants::XAXIS_NAME_PROPERTY_NAME() { return "modelfit.xaxis.name";} +const std::string mitk::ModelFitConstants::XAXIS_NAME_VALUE_DEFAULT() { return "Time";} +const std::string mitk::ModelFitConstants::XAXIS_UNIT_PROPERTY_NAME() { return "modelfit.xaxis.unit";} +const std::string mitk::ModelFitConstants::YAXIS_NAME_PROPERTY_NAME() { return "modelfit.yaxis.name";} +const std::string mitk::ModelFitConstants::YAXIS_NAME_VALUE_DEFAULT() { return "Intensity";} +const std::string mitk::ModelFitConstants::YAXIS_UNIT_PROPERTY_NAME() { return "modelfit.yaxis.unit";} +const std::string mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME() { return "modelfit.fit.uid";} +const std::string mitk::ModelFitConstants::FIT_TYPE_PROPERTY_NAME() { return "modelfit.fit.type";} +const std::string mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED() { return "pixelbased";} +const std::string mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED() { return "ROIbased";} +const std::string mitk::ModelFitConstants::FIT_INPUT_IMAGEUID_PROPERTY_NAME() { return "modelfit.fit.input.imageUID";} +const std::string mitk::ModelFitConstants::FIT_INPUT_ROIUID_PROPERTY_NAME() { return "modelfit.fit.input.roiUID";} +const std::string mitk::ModelFitConstants::FIT_INPUT_DATA_PROPERTY_NAME() { return "modelfit.fit.input.data";} +const std::string mitk::ModelFitConstants::FIT_STATIC_PARAMETERS_PROPERTY_NAME() { return "modelfit.fit.staticParameters";} \ No newline at end of file diff --git a/Modules/ModelFit/src/Common/mitkModelFitInfo.cpp b/Modules/ModelFit/src/Common/mitkModelFitInfo.cpp new file mode 100644 index 0000000000..fa7ae9d2a4 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkModelFitInfo.cpp @@ -0,0 +1,431 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include "mitkDataNode.h" +#include "mitkDataStorage.h" +#include "mitkModelFitInfo.h" +#include "mitkScalarListLookupTableProperty.h" +#include "mitkModelFitException.h" + +void mitk::modelFit::ModelFitInfo::AddParameter(Parameter::Pointer p) +{ + if (p.IsNull()) + { + mitkThrow() << "Given parameter must not be NULL"; + } + + if (GetParameter(p->name, p->type).IsNull()) + { + MITK_DEBUG << "Adding parameter '" << p->name << "with type " << p->type + << "' to modelFit '" << uid << "'."; + + LockType lock(mutex); + parameterList.push_back(p); + } + else + { + MITK_DEBUG << "Parameter '" << p->name << "' of modelFit '" << uid + << "' already exists. Aborting."; + } +} + +mitk::modelFit::Parameter::ConstPointer +mitk::modelFit::ModelFitInfo::GetParameter(const std::string& name, + const Parameter::Type& type) const +{ + for (ConstIterType iter = parameterList.begin(); iter != parameterList.end(); ++iter) + { + Parameter::ConstPointer p = static_cast(*iter); + + if (p->name == name && p->type == type) + { + return p; + } + } + + return NULL; +} + + +const mitk::modelFit::ModelFitInfo::ParamListType& mitk::modelFit::ModelFitInfo::GetParameters() +const +{ + return this->parameterList; +}; + +void mitk::modelFit::ModelFitInfo::DeleteParameter(const std::string& name, + const Parameter::Type& type) +{ + for (IterType iter = parameterList.begin(); iter != parameterList.end(); ++iter) + { + Parameter::ConstPointer p = static_cast(*iter); + + if (p->name == name && p->type == type) + { + MITK_DEBUG << "Deleting parameter '" << name << " with type " << type + << "' from modelFit '" << uid << "'."; + + LockType lock(mutex); + parameterList.erase(iter); + return; + } + } +} + + +const std::string mitk::modelFit::GetMandatoryProperty(const mitk::DataNode* node, + const std::string& prop) +{ + std::string result; + + if (!node || !node->GetData() || + !node->GetData()->GetPropertyList()->GetStringProperty(prop.c_str(), result) || result.empty()) + { + mitkThrowException(mitk::modelFit::ModelFitException) << "Node " << node->GetName() + << " is lacking the required " + << "property '" << prop + << "' or contains an empty string."; + } + + return result; +} + +const std::string mitk::modelFit::GetMandatoryProperty(const mitk::BaseData* data, + const std::string& prop) +{ + std::string result; + + if (!data || !data->GetPropertyList()->GetStringProperty(prop.c_str(), result) || result.empty()) + { + mitkThrowException(mitk::modelFit::ModelFitException) << "Data is lacking the required " + << "property '" << prop + << "' or contains an empty string."; + } + + return result; +} + +mitk::modelFit::ModelFitInfo::Pointer +mitk::modelFit::CreateFitInfoFromNode(const ModelFitInfo::UIDType& uid, + const mitk::DataStorage* storage) +{ + if (!storage) + { + return NULL; + } + + mitk::DataStorage::SetOfObjects::ConstPointer nodes = GetNodesOfFit(uid, storage); + + if (nodes.IsNull() || nodes->empty()) + { + return NULL; + } + + mitk::DataNode::ConstPointer node = nodes->GetElement( + 0).GetPointer(); //take one of the nodes as template + + if (!node->GetData()) + { + return NULL; + } + + ModelFitInfo::Pointer fit = ModelFitInfo::New(); + fit->uid = uid; + + // Mandatory properties + try + { + fit->fitType = GetMandatoryProperty(node, mitk::ModelFitConstants::FIT_TYPE_PROPERTY_NAME()); + fit->modelType = GetMandatoryProperty(node, mitk::ModelFitConstants::MODEL_TYPE_PROPERTY_NAME()); + fit->modelName = GetMandatoryProperty(node, mitk::ModelFitConstants::MODEL_NAME_PROPERTY_NAME()); + } + catch (const ModelFitException& e) + { + MITK_ERROR << e.what(); + return NULL; + } + + // Either a function string or a function class must exist + if (!node->GetData()->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME().c_str(), + fit->function)) + { + fit->function = ""; + } + + try + { + fit->functionClassID = + GetMandatoryProperty(node, mitk::ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME()); + } + catch (const ModelFitException&) + { + if (fit->function.empty()) + { + MITK_ERROR << "The properties '" + << mitk::ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME() + << "'and '" << mitk::ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME() + << "' are both empty or missing. One of these is required."; + return NULL; + } + } + + node->GetData()->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::MODEL_X_PROPERTY_NAME().c_str(), fit->x); + node->GetData()->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::XAXIS_NAME_PROPERTY_NAME().c_str(), fit->xAxisName); + node->GetData()->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::XAXIS_UNIT_PROPERTY_NAME().c_str(), fit->xAxisUnit); + node->GetData()->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::YAXIS_NAME_PROPERTY_NAME().c_str(), fit->yAxisName); + node->GetData()->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::YAXIS_UNIT_PROPERTY_NAME().c_str(), fit->yAxisUnit); + + // Parameter + for (DataStorage::SetOfObjects::ConstIterator pos = nodes->Begin(); pos != nodes->End(); ++pos) + { + modelFit::Parameter::Pointer param = ExtractParameterFromData(pos->Value()->GetData()); + + if (param.IsNotNull()) + { + fit->AddParameter(param); + } + } + + // Static parameters + mitk::ScalarListLookupTableProperty::ConstPointer varProp = dynamic_cast(node->GetData()->GetProperty(mitk::ModelFitConstants::FIT_STATIC_PARAMETERS_PROPERTY_NAME().c_str()).GetPointer()); + + if (varProp.IsNotNull()) + { + const mitk::ScalarListLookupTable lut = varProp->GetValue(); + const mitk::ScalarListLookupTable::LookupTableType& varMap = lut.GetLookupTable(); + + for (mitk::ScalarListLookupTable::LookupTableType::const_iterator mapIter = + varMap.begin(); mapIter != varMap.end(); ++mapIter) + { + fit->staticParamMap.Add(mapIter->first, mapIter->second); + } + } + + //fit input and ROI + try + { + fit->inputUID = GetMandatoryProperty(node, + mitk::ModelFitConstants::FIT_INPUT_IMAGEUID_PROPERTY_NAME()); + } + catch (const ModelFitException& e) + { + MITK_ERROR << e.what(); + return NULL; + } + + if (storage) + { + mitk::DataNode::Pointer inputNode = GetNodeByModelFitUID(storage, fit->inputUID); + + if (inputNode.IsNull()) + { + MITK_ERROR << "Cannot create valid model fit info. input node cannot be found."; + return NULL; + } + + mitk::Image::Pointer inputImage = dynamic_cast(inputNode->GetData()); + + if (inputImage.IsNull()) + { + MITK_ERROR << "Cannot create valid model fit info. input node does not contain an image."; + return NULL; + } + + fit->inputImage = inputImage; + } + + node->GetData()->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::FIT_INPUT_ROIUID_PROPERTY_NAME().c_str(), + fit->roiUID); + + mitk::ScalarListLookupTableProperty::ConstPointer inputDataProp = dynamic_cast(node->GetData()->GetProperty(mitk::ModelFitConstants::FIT_INPUT_DATA_PROPERTY_NAME().c_str()).GetPointer()); + if (inputDataProp.IsNotNull()) + { + fit->inputData = inputDataProp->GetValue(); + } + + return fit; +} + +mitk::modelFit::ModelFitInfo::Pointer +mitk::modelFit::CreateFitInfoFromModelParameterizer(const ModelParameterizerBase* usedParameterizer, +mitk::BaseData* inputImage, const std::string& fitType, + const NodeUIDType roiUID) +{ + if (!usedParameterizer) + { + return NULL; + } + + UIDGenerator generator("FitUID_"); + std::string uid = generator.GetUID(); + + ModelFitInfo::Pointer fit = ModelFitInfo::New(); + fit->uid = uid; + fit->fitType = fitType; + fit->inputImage = dynamic_cast(inputImage); + fit->inputUID = EnsureModelFitUID(inputImage); + + if (fit->inputImage.IsNull()) + { + mitkThrow() << "Cannot generate model fit info. Input node does not contain an image."; + } + + fit->modelType = usedParameterizer->GetModelType(); + fit->modelName = usedParameterizer->GetModelDisplayName(); + + fit->function = usedParameterizer->GetFunctionString(); + fit->x = usedParameterizer->GetXName(); + fit->functionClassID = usedParameterizer->GetClassID(); + + fit->xAxisName = usedParameterizer->GetXAxisName(); + fit->xAxisUnit = usedParameterizer->GetXAxisUnit(); + fit->yAxisName = usedParameterizer->GetYAxisName(); + fit->yAxisUnit = usedParameterizer->GetYAxisUnit(); + + // Parameter + ModelTraitsInterface::ParameterNamesType paramNames = usedParameterizer->GetParameterNames(); + ModelTraitsInterface::ParamterScaleMapType paramScales = usedParameterizer->GetParameterScales(); + ModelTraitsInterface::ParamterUnitMapType paramUnits = usedParameterizer->GetParameterUnits(); + + for (ModelTraitsInterface::ParameterNamesType::iterator pos = paramNames.begin(); + pos != paramNames.end(); ++pos) + { + modelFit::Parameter::Pointer param = modelFit::Parameter::New(); + param->name = *pos; + param->type = Parameter::ParameterType; + + if (paramScales.find(*pos) == paramScales.end()) + { + mitkThrow() << + "Cannot generate model fit info. Model traits invalid (scales do not include parameter). Parameter name: " + << *pos; + } + + if (paramUnits.find(*pos) == paramUnits.end()) + { + mitkThrow() << + "Cannot generate model fit info. Model traits invalid (units do not include parameter). Parameter name: " + << *pos; + } + + param->scale = paramScales[*pos]; + param->unit = paramUnits[*pos]; + fit->AddParameter(param); + } + + //derived parameter + ModelTraitsInterface::DerivedParameterNamesType derivedNames = + usedParameterizer->GetDerivedParameterNames(); + ModelTraitsInterface::DerivedParamterScaleMapType derivedScales = + usedParameterizer->GetDerivedParameterScales(); + ModelTraitsInterface::DerivedParamterUnitMapType derivedUnits = + usedParameterizer->GetDerivedParameterUnits(); + + for (ModelTraitsInterface::ParameterNamesType::iterator pos = derivedNames.begin(); + pos != derivedNames.end(); ++pos) + { + modelFit::Parameter::Pointer param = modelFit::Parameter::New(); + param->name = *pos; + param->type = Parameter::DerivedType; + + if (derivedScales.find(*pos) == derivedScales.end()) + { + mitkThrow() << + "Cannot generate model fit info. Model traits invalid (scales do not include parameter). Parameter name: " + << *pos; + } + + if (derivedUnits.find(*pos) == derivedUnits.end()) + { + mitkThrow() << + "Cannot generate model fit info. Model traits invalid (units do not include parameter). Parameter name: " + << *pos; + } + + param->scale = derivedScales[*pos]; + param->unit = derivedUnits[*pos]; + fit->AddParameter(param); + } + + // Static parameters (but transfer only the global ones) + ModelParameterizerBase::StaticParameterMapType staticParamMap = + usedParameterizer->GetGlobalStaticParameters(); + + for (ModelParameterizerBase::StaticParameterMapType::const_iterator pos = staticParamMap.begin(); + pos != staticParamMap.end(); ++pos) + { + fit->staticParamMap.Add(pos->first, pos->second); + } + + + fit->roiUID = roiUID; + + return fit; +} + +mitk::modelFit::ModelFitInfo::Pointer +mitk::modelFit::CreateFitInfoFromModelParameterizer(const ModelParameterizerBase* usedParameterizer, +mitk::BaseData* inputImage, const std::string& fitType, + const ScalarListLookupTable& inputData, const NodeUIDType roiUID) +{ + mitk::modelFit::ModelFitInfo::Pointer info = CreateFitInfoFromModelParameterizer(usedParameterizer, + inputImage, fitType, roiUID); + + info->inputData = inputData; + + return info; +} + +mitk::DataStorage::SetOfObjects::ConstPointer +mitk::modelFit::GetNodesOfFit(const ModelFitInfo::UIDType& fitUID, const mitk::DataStorage* storage) +{ + if (!storage) + { + return NULL; + } + + mitk::NodePredicateDataProperty::Pointer predicate = mitk::NodePredicateDataProperty::New( + mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(), mitk::StringProperty::New(fitUID)); + return storage->GetSubset(predicate); +}; + + +mitk::modelFit::NodeUIDSetType +mitk::modelFit::GetFitUIDsOfNode(const mitk::DataNode* node, const mitk::DataStorage* storage) +{ + mitk::modelFit::NodeUIDSetType result; + + if (node && storage) + { + mitk::NodePredicateDataProperty::Pointer predicate = mitk::NodePredicateDataProperty::New( + mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str()); + mitk::DataStorage::SetOfObjects::ConstPointer nodes = storage->GetDerivations(node, predicate, + false); + + for (mitk::DataStorage::SetOfObjects::ConstIterator pos = nodes->Begin(); pos != nodes->End(); + ++pos) + { + mitk::modelFit::ModelFitInfo::UIDType uid; + pos->Value()->GetData()->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(), uid); + result.insert(uid); + } + + } + + return result; +}; diff --git a/Modules/ModelFit/src/Common/mitkModelFitParameter.cpp b/Modules/ModelFit/src/Common/mitkModelFitParameter.cpp new file mode 100644 index 0000000000..388fa5bafc --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkModelFitParameter.cpp @@ -0,0 +1,74 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkModelFitParameter.h" +#include "mitkModelFitConstants.h" + +mitk::modelFit::Parameter::Parameter() : + name (""), type(Parameter::ParameterType), unit(""), scale(1.0f) +{ +} + +mitk::modelFit::Parameter::Pointer mitk::modelFit::ExtractParameterFromData(const mitk::BaseData* data) +{ + if (!data) + { + return NULL; + } + + mitk::modelFit::Parameter::Pointer param = mitk::modelFit::Parameter::New(); + + if (!data->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::PARAMETER_NAME_PROPERTY_NAME().c_str(), param->name)) + { + return NULL; + }; + + param->image = dynamic_cast(data); + + if(!(param->image)) + { + return NULL; + } + + std::string typeString; + data->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(), typeString); + + if(typeString == mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_DERIVED_PARAMETER()) + { + param->type = Parameter::DerivedType; + } + else if(typeString == mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_CRITERION()) + { + param->type = Parameter::CriterionType; + } + else if(typeString == mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_EVALUATION_PARAMETER()) + { + param->type = Parameter::EvaluationType; + } + else + { + param->type = Parameter::ParameterType; + } + + data->GetPropertyList()->GetStringProperty(mitk::ModelFitConstants::PARAMETER_UNIT_PROPERTY_NAME().c_str(), + param->unit); + data->GetPropertyList()->GetFloatProperty(mitk::ModelFitConstants::PARAMETER_SCALE_PROPERTY_NAME().c_str(), + param->scale); + + return param; +} + diff --git a/Modules/ModelFit/src/Common/mitkModelFitParameterValueExtraction.cpp b/Modules/ModelFit/src/Common/mitkModelFitParameterValueExtraction.cpp new file mode 100644 index 0000000000..6ecec4cd77 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkModelFitParameterValueExtraction.cpp @@ -0,0 +1,200 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelFitParameterValueExtraction.h" +#include "mitkModelFitException.h" + +#include +#include + + +/** +* @brief Reads the intensity with the given pixel type from the given image at the given position and time +* step (at the currently selected voxel) and stores it in the variable 'value'. +* @tparam TPixel The type of the voxel (e.g. float). +* @param image The image whose voxel should be read. +* @param position The position in the image that should be read out. +* @param timestep The time step at which the voxel should be read. +* @param value The variable where the result is stored. +*/ +template +void ReadVoxelInternal(const mitk::PixelType, const mitk::Image *image, + const ::itk::Index<3> index, + unsigned int timestep, mitk::ModelTraitsInterface::ParameterValueType &value) +{ + // Read voxel + if (image->GetDimension() == 2) + { + mitk::ImagePixelReadAccessor readAccess(image, image->GetSliceData(0)); + itk::Index<2> idx; + idx[0] = index[0]; + idx[1] = index[1]; + value = static_cast(readAccess.GetPixelByIndex(idx)); + } + else if (image->GetDimension() == 3) + { + mitk::ImagePixelReadAccessor readAccess(image, image->GetVolumeData(0)); + value = static_cast(readAccess.GetPixelByIndex(index)); + } + else if (image->GetDimension() == 4) + { + mitk::ImagePixelReadAccessor readAccess(image, image->GetVolumeData(timestep)); + value = static_cast(readAccess.GetPixelByIndex(index)); + } + + MITK_DEBUG << "Voxel [" << index[0] << ", " << index[1] << ", " << index[2] << ", " << timestep + << "]: " << value; +} + + +mitk::ModelTraitsInterface::ParameterValueType +mitk::ReadVoxel(const mitk::Image* image, + const mitk::Point3D& position, unsigned int timestep, bool noThrow) +{ + // Calculate index + ::itk::Index<3> index; + mitk::BaseGeometry::Pointer geometry = image->GetTimeGeometry()->GetGeometryForTimeStep(timestep); + + // check for invalid time step + if (geometry.IsNull()) + { + geometry = image->GetTimeGeometry()->GetGeometryForTimeStep(0); + } + + geometry->WorldToIndex(position, index); + + return ReadVoxel(image, index, timestep, noThrow); +} + +mitk::ModelTraitsInterface::ParameterValueType +mitk::ReadVoxel(const mitk::Image* image, +const ::itk::Index<3> &index, unsigned int timestep, bool noThrow) +{ + double result = 0.0; + + // check for invalid time step + if (timestep >= image->GetTimeSteps()) + { + timestep = 0; + } + + try + { + mitkPixelTypeMultiplex4(ReadVoxelInternal, image->GetPixelType(), image, index, timestep, result); + } + catch (const std::exception& e) + { + if (noThrow) + { + MITK_ERROR << "Exception in ReadVoxel (index: " << index << "; timestep: " << timestep << "). Reason: " << e.what(); + } + else throw; + } + catch (...) + { + if (noThrow) + { + MITK_ERROR << "Unknown exception in ReadVoxel (index: " << index << "; timestep: " << timestep << ")."; + } + else throw; + } + + return result; +} + +mitk::ParameterValueMapType +mitk::ExtractParameterValueMapFromModelFit(const mitk::modelFit::ModelFitInfo* fitInfo, + const mitk::Point3D& position) +{ + if (!fitInfo) + { + mitkThrow() << "Cannot extract parameter value map out of model fit instance. Passed model fit instance is a null ptr."; + } + + ParameterValueMapType parameterMap; + + for (mitk::modelFit::ModelFitInfo::ConstIterType paramIter = fitInfo->GetParameters().begin(); + paramIter != fitInfo->GetParameters().end(); + ++paramIter) + { + const mitk::modelFit::Parameter* param = *paramIter; + + if (param->type == mitk::modelFit::Parameter::ParameterType) + { + parameterMap[param->name] = mitk::ReadVoxel(param->image, position); + } + } + + return parameterMap; +}; + +mitk::ParameterValueMapType +mitk::ExtractParameterValueMapFromModelFit(const mitk::modelFit::ModelFitInfo* fitInfo, +const ::itk::Index<3> &index) +{ + if (!fitInfo) + { + mitkThrow() << "Cannot extract parameter value map out of model fit instance. Passed model fit instance is a null ptr."; + } + + ParameterValueMapType parameterMap; + + for (mitk::modelFit::ModelFitInfo::ConstIterType paramIter = fitInfo->GetParameters().begin(); + paramIter != fitInfo->GetParameters().end(); + ++paramIter) + { + const mitk::modelFit::Parameter* param = *paramIter; + + if (param->type == mitk::modelFit::Parameter::ParameterType) + { + parameterMap[param->name] = mitk::ReadVoxel(param->image, index); + } + } + + return parameterMap; +}; + +mitk::ModelTraitsInterface::ParametersType +mitk::ConvertParameterMapToParameterVector(const ParameterValueMapType &valueMap, const ModelTraitsInterface * pTraitInterface) +{ + if (!pTraitInterface) + { + mitkThrow() << "Cannot convert parameter values. Passed traits interface is a null ptr."; + } + + const mitk::ModelTraitsInterface::ParameterNamesType paramNameVector = + pTraitInterface->GetParameterNames(); + + mitk::ModelTraitsInterface::ParametersType paramArray(paramNameVector.size()); + mitk::ModelTraitsInterface::ParametersSizeType paramIndex = 0; + + for (const auto& name : paramNameVector) + { + ParameterValueMapType::const_iterator iter = valueMap.find(name); + + if (iter != valueMap.end()) + { + paramArray[paramIndex] = iter->second; + ++paramIndex; + } + else + { + mitkThrow() << "Cannot convert parameter values. Parameter name ('" << name << "') is missing in value map."; + } + } + + return paramArray; +} diff --git a/Modules/ModelFit/src/Common/mitkModelFitResultHelper.cpp b/Modules/ModelFit/src/Common/mitkModelFitResultHelper.cpp new file mode 100644 index 0000000000..ea751791fd --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkModelFitResultHelper.cpp @@ -0,0 +1,273 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelFitResultHelper.h" + +#include +#include + +#include "mitkModelTraitsInterface.h" +#include "mitkModelFitConstants.h" +#include "mitkModelFitInfo.h" + +namespace mitk +{ + namespace modelFit + { + void AdaptDataPropertyToParameter(mitk::BaseData* data, const ModelBase::ParameterNameType& name, modelFit::Parameter::Type dataType, const modelFit::ModelFitInfo* fitInfo) + { + assert(data); + + if (!data) + { + mitkThrow() << "Cannot add model or fit properties to data instance. Passed data instance is null. parameter name:" << name; + } + + if (!fitInfo) + { + mitkThrow() << "Cannot add model or fit properties to data. Passed fit info instance is null. parameter name:" << name; + } + + data->GetPropertyList()->SetStringProperty(ModelFitConstants::PARAMETER_NAME_PROPERTY_NAME().c_str(),name.c_str()); + + if (dataType == modelFit::Parameter::ParameterType) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(), ModelFitConstants::PARAMETER_TYPE_VALUE_PARAMETER().c_str()); + } + else if (dataType == modelFit::Parameter::DerivedType) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(), ModelFitConstants::PARAMETER_TYPE_VALUE_DERIVED_PARAMETER().c_str()); + } + else if (dataType == modelFit::Parameter::CriterionType) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(), ModelFitConstants::PARAMETER_TYPE_VALUE_CRITERION().c_str()); + } + else if (dataType == modelFit::Parameter::EvaluationType) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(), ModelFitConstants::PARAMETER_TYPE_VALUE_EVALUATION_PARAMETER().c_str()); + } + + + if (dataType == modelFit::Parameter::ParameterType || dataType == modelFit::Parameter::DerivedType) + { + modelFit::Parameter::ConstPointer param = fitInfo->GetParameter(name,dataType); + + if (param.IsNull()) + { + mitkThrow() << "Cannot generate model fit result data. Parameter name is not part of the model fit info. Parameter name: "<unit.empty()) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::PARAMETER_UNIT_PROPERTY_NAME().c_str(), param->unit.c_str()); + } + + if (param->scale != 1.0) + { + data->GetPropertyList()->SetFloatProperty(ModelFitConstants::PARAMETER_SCALE_PROPERTY_NAME().c_str(), param->scale); + } + } + + }; + + void AdaptDataPropertyToModelFit(mitk::BaseData* data, const modelFit::ModelFitInfo* fitInfo) + { + assert(data); + + if (!data) + { + mitkThrow() << "Cannot add model or fit properties to data. Passed data instance is null."; + } + + if (!fitInfo) + { + mitkThrow() << "Cannot add model or fit properties to data. Passed model traits instance is null."; + } + + //model section + data->GetPropertyList()->SetStringProperty(ModelFitConstants::MODEL_TYPE_PROPERTY_NAME().c_str(), fitInfo->modelType.c_str()); + data->GetPropertyList()->SetStringProperty(ModelFitConstants::MODEL_NAME_PROPERTY_NAME().c_str(), fitInfo->modelName.c_str()); + + data->GetPropertyList()->SetStringProperty(ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME().c_str(), fitInfo->functionClassID.c_str()); + if(!(fitInfo->function.empty())) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME().c_str(), fitInfo->function.c_str()); + data->GetPropertyList()->SetStringProperty(ModelFitConstants::MODEL_X_PROPERTY_NAME().c_str(), fitInfo->x.c_str()); + } + + //axis section + if (!fitInfo->xAxisName.empty()) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::XAXIS_NAME_PROPERTY_NAME().c_str(), fitInfo->xAxisName.c_str()); + } + + if (!fitInfo->xAxisUnit.empty()) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::XAXIS_UNIT_PROPERTY_NAME().c_str(), fitInfo->xAxisUnit.c_str()); + } + + if (!fitInfo->yAxisName.empty()) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::YAXIS_NAME_PROPERTY_NAME().c_str(), fitInfo->yAxisName.c_str()); + } + + if (!fitInfo->yAxisUnit.empty()) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::YAXIS_UNIT_PROPERTY_NAME().c_str(), fitInfo->yAxisUnit.c_str()); + } + + //fit section + data->GetPropertyList()->SetStringProperty(ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(), fitInfo->uid.c_str()); + data->GetPropertyList()->SetStringProperty(ModelFitConstants::FIT_TYPE_PROPERTY_NAME().c_str(), fitInfo->fitType.c_str()); + data->GetPropertyList()->SetStringProperty(ModelFitConstants::FIT_INPUT_IMAGEUID_PROPERTY_NAME().c_str(), fitInfo->inputUID.c_str()); + + if (fitInfo->inputData.GetLookupTable().size() > 0) + { + mitk::ScalarListLookupTableProperty::Pointer inputDataProp = mitk::ScalarListLookupTableProperty::New(); + inputDataProp->SetValue(fitInfo->inputData); + + data->SetProperty(ModelFitConstants::FIT_INPUT_DATA_PROPERTY_NAME().c_str(), inputDataProp); + } + + if (!fitInfo->roiUID.empty()) + { + data->GetPropertyList()->SetStringProperty(ModelFitConstants::FIT_INPUT_ROIUID_PROPERTY_NAME().c_str(), fitInfo->roiUID.c_str()); + } + + data->SetProperty(ModelFitConstants::FIT_STATIC_PARAMETERS_PROPERTY_NAME().c_str(), ConvertStaticParametersToProperty(fitInfo->staticParamMap)); + }; + + mitk::DataNode::Pointer CreateNode(const ModelBase::ParameterNameType& name, Image* parameterImage, const ModelFitInfo* fitInfo, const std::string& sessionName) + { + if (!parameterImage) + { + mitkThrow() << "Cannot generate model fit result node. Passed parameterImage is null. parameter name: "<SetData(parameterImage); + + std::string nodeName = name; + + if (!sessionName.empty()) + { + nodeName = sessionName+"_"+nodeName; + } + + result->SetName(nodeName); + + result->SetVisibility(false); + + return result; + }; + } +} + +mitk::ScalarListLookupTableProperty::Pointer mitk::modelFit::ConvertStaticParametersToProperty(const mitk::modelFit::StaticParameterMap& params) +{ + mitk::ScalarListLookupTableProperty::Pointer result = mitk::ScalarListLookupTableProperty::New(); + + ScalarListLookupTable table; + + for(mitk::modelFit::StaticParameterMap::const_iterator pos = params.begin(); pos != params.end(); ++pos) + { + table.SetTableValue(pos->first,pos->second); + } + + result->SetValue(table); + + return result; +}; + +MITKMODELFIT_EXPORT void mitk::modelFit::SetModelFitDataProperties(mitk::BaseData* data, const ModelBase::ParameterNameType& name, modelFit::Parameter::Type dataType, const modelFit::ModelFitInfo* fitInfo) +{ + AdaptDataPropertyToModelFit(data, fitInfo); + AdaptDataPropertyToParameter(data, name, dataType, fitInfo); +}; + +MITKMODELFIT_EXPORT mitk::DataNode::Pointer mitk::modelFit::CreateResultNode( const ModelBase::ParameterNameType& name, modelFit::Parameter::Type nodeType, Image* parameterImage, const ModelFitInfo* modelFitInfo, const std::string& sessionName ) +{ + if (!parameterImage) + { + mitkThrow() << "Cannot generate model fit result node. Passed parameterImage is null. parameter name: "<first, modelFit::Parameter::ParameterType, pos->second, fitInfo, sessionName); + nodes.push_back(newNode); + } + + for (ModelFitResultImageMapType::const_iterator pos = derivedResults.begin(); pos!=derivedResults.end(); ++pos) + { + DataNode::Pointer newNode = CreateResultNode(pos->first, modelFit::Parameter::DerivedType, pos->second, fitInfo, sessionName); + nodes.push_back(newNode); + } + + for (ModelFitResultImageMapType::const_iterator pos = criterionResults.begin(); pos!=criterionResults.end(); ++pos) + { + DataNode::Pointer newNode = CreateResultNode(pos->first, modelFit::Parameter::CriterionType, pos->second, fitInfo, sessionName); + nodes.push_back(newNode); + } + + for (ModelFitResultImageMapType::const_iterator pos = evaluationResults.begin(); pos!=evaluationResults.end(); ++pos) + { + DataNode::Pointer newNode = CreateResultNode(pos->first, modelFit::Parameter::EvaluationType, pos->second, fitInfo, sessionName); + nodes.push_back(newNode); + } + + return nodes; +}; + +MITKMODELFIT_EXPORT void mitk::modelFit::StoreResultsInDataStorage(DataStorage* storage, const ModelFitResultNodeVectorType& resultNodes, DataNode* parentNode) +{ + if (!storage) + { + mitkThrow() << "Cannot store model fit results in data storage. Passed storage is null."; + } + + for (ModelFitResultNodeVectorType::const_iterator pos = resultNodes.begin(); pos!=resultNodes.end(); ++pos) + { + storage->Add(*pos,parentNode); + } +}; + diff --git a/Modules/ModelFit/src/Common/mitkModelFitStaticParameterMap.cpp b/Modules/ModelFit/src/Common/mitkModelFitStaticParameterMap.cpp new file mode 100644 index 0000000000..0485507210 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkModelFitStaticParameterMap.cpp @@ -0,0 +1,185 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include "mitkModelFitStaticParameterMap.h" +#include "mitkModelFitException.h" + +void mitk::modelFit::StaticParameterMap::Add(const std::string& name, const ValueType& newList) +{ + MapType::const_iterator mapIter = m_map.find(name); + + // Only add if the name doesn't exist yet + if (mapIter == m_map.end()) + { + // If the new list contains more than one values, make sure it contains the same number of + // values as other lists that contain more than one value + if (newList.size() > 1) + { + if (m_numValues > 1 && newList.size() != m_numValues) + { + mitkThrowException(ModelFitException) << "Unable to add variable '" << name + << "' to StaticParameterMap: It contains " + << newList.size() << "values (should be " + << m_numValues; + } + else if (m_numValues == 1) + { + m_numValues = newList.size(); + } + } + + m_map.insert(StaticParameterType(name, newList)); + } +} + +const mitk::modelFit::StaticParameterMap::ValueType& +mitk::modelFit::StaticParameterMap::Get(const std::string& name) const +{ + MapType::const_iterator mapIter = m_map.find(name); + + if (mapIter != m_map.end()) + { + return mapIter->second; + } + + throw std::range_error("'" + name + "' does not exist in InputStaticParameterMap"); +} + +void mitk::modelFit::StaticParameterMap::Sort(const std::string& name /* = "" */) +{ + if (m_map.empty() || m_numValues == 1) + { + return; + } + + // Copy the actual map and operate on the copy to fulfill exception guarantees. + MapType localMap = m_map; + + // Copy map contents to a m*n matrix where n is the number of values and m is the number of + // variables + std::vector temp; + + for (size_t i = 0; i < m_numValues; ++i) + { + temp.push_back(ValueType()); + } + + { + MapType::const_iterator foundPair = localMap.find(name); + + if (!name.empty()) + { + if (foundPair != localMap.end()) + { + // An existing variable name has been given, so make sure its values are in the + // first row of the matrix + const ValueType& list = foundPair->second; + + if (list.size() > 1) // only copy lists that have more than one value + { + for (size_t i = 0; i < list.size(); ++i) + { + temp[i].push_back(list[i]); + } + } + } + } + + // Copy the rest of the values to the matrix + for (MapType::const_iterator mapIter = localMap.begin(); mapIter != localMap.end(); + ++mapIter) + { + if (!name.empty() && name == mapIter->first) + { + // Skip this variable since it was already added (in the first row) + continue; + } + + const ValueType& list = mapIter->second; + + if (list.size() > 1) // only copy lists that have more than one value + { + for (size_t i = 0; i < list.size(); ++i) + { + temp[i].push_back(list[i]); + } + } + } + } + + // Sort the matrix + std::sort(temp.begin(), temp.end()); + + // Copy the matrix contents back to the map + { + int i = 0; + MapType::iterator foundPair = localMap.find(name); + + if (foundPair != localMap.end()) + { + // An existing variable name has been given, so make sure the first row of the matrix is + // copied back to that variable + ValueType& list = foundPair->second; + + if (list.size() > 1) // only copy lists that have more than one value + { + list.clear(); + + for (size_t j = 0; j < temp.size(); ++j) + { + list.push_back(temp[j][i]); + } + + ++i; + } + } + + // Copy the rest of the matrix back to the map + for (MapType::iterator mapIter = localMap.begin(); mapIter != localMap.end(); ++mapIter) + { + if (!name.empty() && name == mapIter->first) + { + // Skip this variable since it was already filled (from the first row) + continue; + } + + ValueType& list = mapIter->second; + + if (list.size() > 1) // only copy lists that have more than one value + { + list.clear(); + + for (size_t j = 0; j < temp.size(); ++j) + { + list.push_back(temp[j][i]); + } + + ++i; + } + } + } + + // Write the now sorted copy back to the actual map + m_map = localMap; +} + +void mitk::modelFit::StaticParameterMap::Clear() +{ + m_map.clear(); + m_numValues = 1; +} diff --git a/Modules/ModelFit/src/Common/mitkModelFitUIDHelper.cpp b/Modules/ModelFit/src/Common/mitkModelFitUIDHelper.cpp new file mode 100644 index 0000000000..1972139585 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkModelFitUIDHelper.cpp @@ -0,0 +1,132 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelFitUIDHelper.h" + + +// Mitk +#include +#include +#include +#include +#include +#include +#include + +mitk::DataNode::Pointer mitk::GetNodeByModelFitUID(const mitk::DataStorage* storage, const NodeUIDType& uid) +{ + mitk::DataNode::Pointer result; + + if (storage) + { + auto nodes = storage->GetAll(); + for (auto node : *(nodes.GetPointer())) + { + if (CheckModelFitUID(node, uid)) + { + result = node; + break; + } + } + } + + return result; +} + +mitk::NodeUIDType mitk::EnsureModelFitUID(mitk::DataNode* node) +{ + if (!node) + { + mitkThrow() << "Cannot ensure node UID. Passed node pointer is NULL."; + } + + return EnsureModelFitUID(node->GetData()); +}; + +mitk::NodeUIDType mitk::EnsureModelFitUID(mitk::BaseData* data) +{ + if (!data) + { + mitkThrow() << "Cannot ensure node UID. Passed node pointer is NULL."; + } + + BaseProperty::Pointer uidProp = data->GetProperty(mitk::ModelFitConstants::UID_PROPERTY_NAME().c_str()); + std::string propUID = ""; + + + if (uidProp.IsNotNull()) + { + propUID = uidProp->GetValueAsString(); + } + else + { + //if the "user" defined UID is not found we will check if there is a DICOM series instance UID and use this value if available. + uidProp = data->GetProperty(GeneratePropertyNameForDICOMTag(0x0020, 0x000e).c_str()); + + if (uidProp.IsNotNull()) + { + propUID = uidProp->GetValueAsString(); + } + else + { + mitk::UIDGenerator generator; + propUID = generator.GetUID(); + + data->SetProperty(mitk::ModelFitConstants::UID_PROPERTY_NAME().c_str(), mitk::StringProperty::New(propUID)); + } + } + + return propUID; +}; + +bool mitk::CheckModelFitUID(const mitk::DataNode* node, const NodeUIDType& uid) +{ + if (node) + { + return CheckModelFitUID(node->GetData(), uid); + } + + return false; +}; + +bool mitk::CheckModelFitUID(const mitk::BaseData* data, const NodeUIDType& uid) +{ + bool result = false; + + if (data) + { + BaseProperty::Pointer uidProp = data->GetProperty(mitk::ModelFitConstants::UID_PROPERTY_NAME().c_str()); + + if (uidProp.IsNotNull()) + { + result = uidProp->GetValueAsString() == uid; + } + + if (!result) + { + //if the "user" defined UID does not match, we will check if there is a DICOM series instance UID and use this value for the check. + uidProp = data->GetProperty(GeneratePropertyNameForDICOMTag(0x0020, 0x000e).c_str()); + + if (uidProp.IsNotNull()) + { + result = uidProp->GetValueAsString() == uid; + } + } + } + + return result; +}; + diff --git a/Modules/ModelFit/src/Common/mitkModelGenerator.cpp b/Modules/ModelFit/src/Common/mitkModelGenerator.cpp new file mode 100644 index 0000000000..155143521d --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkModelGenerator.cpp @@ -0,0 +1,76 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelGenerator.h" +#include "mitkIModelFitProvider.h" + +#include "usModuleContext.h" +#include "usGetModuleContext.h" + +mitk::IModelFitProvider* mitk::ModelGenerator::GetProviderService(const ModelClassIDType& id) +{ + mitk::IModelFitProvider* result = nullptr; + std::string filter = "(" + mitk::IModelFitProvider::PROP_MODEL_CLASS_ID() + "=" + id + ")"; + std::vector > providerRegisters = us::GetModuleContext()->GetServiceReferences(filter); + + if (!providerRegisters.empty()) + { + if (providerRegisters.size() > 1) + { + MITK_WARN << "Multiple provider for class id'"<GetService(providerRegisters.front()); + } + + return result; +}; + +mitk::ModelGenerator::ModelGenerator() += default; + +mitk::ModelGenerator::~ModelGenerator() += default; + +mitk::ModelFactoryBase::Pointer mitk::ModelGenerator::GetModelFactory(const ModelClassIDType& id) +{ + mitk::ModelFactoryBase::Pointer factory = nullptr; + + auto service = GetProviderService(id); + + if (service) + { + factory = service->GenerateFactory(); + } + + + return factory; +} + + +mitk::ModelParameterizerBase::Pointer mitk::ModelGenerator::GenerateModelParameterizer( + const modelFit::ModelFitInfo& fit) +{ + mitk::ModelParameterizerBase::Pointer result = nullptr; + + mitk::ModelFactoryBase::Pointer factory = GetModelFactory(fit.functionClassID); + + if (factory.IsNotNull()) + { + result = factory->CreateParameterizer(&fit); + } + + return result; +} diff --git a/Modules/ModelFit/src/Common/mitkParameterFitImageGeneratorBase.cpp b/Modules/ModelFit/src/Common/mitkParameterFitImageGeneratorBase.cpp new file mode 100644 index 0000000000..065f238ac7 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkParameterFitImageGeneratorBase.cpp @@ -0,0 +1,100 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkParameterFitImageGeneratorBase.h" + +bool + mitk::ParameterFitImageGeneratorBase::HasOutdatedResult() const +{ + bool result = this->GetMTime() > this->m_GenerationTimeStamp; + + return result; +}; + +void + mitk::ParameterFitImageGeneratorBase::CheckValidInputs() const +{ +}; + + +void + mitk::ParameterFitImageGeneratorBase::Generate() +{ + CheckValidInputs(); + + if (!this->HasOutdatedResult()) + { //still up to date -> nothing to do + return; + } + + ParameterImageMapType paramImages; + ParameterImageMapType derivedImages; + ParameterImageMapType criterionImages; + ParameterImageMapType evaluationImages; + + DoFitAndGetResults(paramImages, derivedImages, criterionImages, evaluationImages); + + m_ParameterImageMap = paramImages; + m_DerivedParameterImageMap = derivedImages; + m_CriterionImageMap = criterionImages; + m_EvaluationParameterImageMap = evaluationImages; + + this->m_GenerationTimeStamp.Modified(); +}; + +mitk::ParameterFitImageGeneratorBase::ParameterImageMapType + mitk::ParameterFitImageGeneratorBase::GetParameterImages() +{ + if (this->HasOutdatedResult()) + { + Generate(); + } + + return m_ParameterImageMap; +}; + +mitk::ParameterFitImageGeneratorBase::ParameterImageMapType + mitk::ParameterFitImageGeneratorBase::GetDerivedParameterImages() +{ + if (this->HasOutdatedResult()) + { + Generate(); + } + + return m_DerivedParameterImageMap; +}; + +mitk::ParameterFitImageGeneratorBase::ParameterImageMapType + mitk::ParameterFitImageGeneratorBase::GetCriterionImages() +{ + if (this->HasOutdatedResult()) + { + Generate(); + } + + return m_CriterionImageMap; +}; + +mitk::ParameterFitImageGeneratorBase::ParameterImageMapType + mitk::ParameterFitImageGeneratorBase::GetEvaluationParameterImages() +{ + if (this->HasOutdatedResult()) + { + Generate(); + } + + return m_EvaluationParameterImageMap; +}; \ No newline at end of file diff --git a/Modules/ModelFit/src/Common/mitkPixelBasedParameterFitImageGenerator.cpp b/Modules/ModelFit/src/Common/mitkPixelBasedParameterFitImageGenerator.cpp new file mode 100644 index 0000000000..a2046d8e69 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkPixelBasedParameterFitImageGenerator.cpp @@ -0,0 +1,279 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "itkCommand.h" +#include "itkMultiOutputNaryFunctorImageFilter.h" + +#include "mitkPixelBasedParameterFitImageGenerator.h" +#include "mitkImageTimeSelector.h" +#include "mitkImageAccessByItk.h" +#include "mitkImageCast.h" +#include "mitkModelFitFunctorPolicy.h" + +#include "mitkExtractTimeGrid.h" + +void + mitk::PixelBasedParameterFitImageGenerator:: + onFitProgressEvent(::itk::Object* caller, const ::itk::EventObject& /*eventObject*/) +{ + this->InvokeEvent(::itk::ProgressEvent()); + + auto* process = dynamic_cast(caller); + if (process) + { + this->m_Progress = process->GetProgress(); + } +}; + +template +void + mitk::PixelBasedParameterFitImageGenerator::DoPrepareMask(itk::Image* image) +{ + m_InternalMask = dynamic_cast(image); + + if (m_InternalMask.IsNull()) + { + MITK_INFO << "Parameter Fit Generator. Need to cast mask for parameter fit."; + using InputImageType = itk::Image; + using CastFilterType = itk::CastImageFilter< InputImageType, InternalMaskType >; + typename CastFilterType::Pointer spImageCaster = CastFilterType::New(); + + spImageCaster->SetInput(image); + + m_InternalMask = spImageCaster->GetOutput(); + spImageCaster->Update(); + } +} + +template +mitk::PixelBasedParameterFitImageGenerator::ParameterImageMapType StoreResultImages( mitk::ModelFitFunctorBase::ParameterNamesType ¶mNames, itk::ImageSource* source, mitk::ModelFitFunctorBase::ParameterNamesType::size_type startPos, mitk::ModelFitFunctorBase::ParameterNamesType::size_type& endPos ) +{ + mitk::PixelBasedParameterFitImageGenerator::ParameterImageMapType result; + for (mitk::ModelFitFunctorBase::ParameterNamesType::size_type j = 0; j < paramNames.size(); ++j) + { + if (source->GetNumberOfOutputs() < startPos+j) + { + mitkThrow() << "Error while generating fitted parameter images. Number of sources is too low and does not match expected parameter number. Output size: "<< source->GetNumberOfOutputs()<<"; number of param names: "<GetOutput(startPos+j); + mitk::CastToMitkImage(outputImg, paramImage); + + result.insert(std::make_pair(paramNames[j],paramImage)); + } + + endPos = startPos + paramNames.size(); + + return result; +} + +template +void + mitk::PixelBasedParameterFitImageGenerator::DoParameterFit(itk::Image* /*image*/) +{ + using InputFrameImageType = itk::Image; + using ParameterImageType = itk::Image; + + using FitFilterType = itk::MultiOutputNaryFunctorImageFilter; + + typename FitFilterType::Pointer fitFilter = FitFilterType::New(); + + typename ::itk::MemberCommand::Pointer spProgressCommand = ::itk::MemberCommand::New(); + spProgressCommand->SetCallbackFunction(this, &Self::onFitProgressEvent); + fitFilter->AddObserver(::itk::ProgressEvent(), spProgressCommand); + + //add the time frames to the fit filter + std::vector frameCache; + for (unsigned int i = 0; i < this->m_DynamicImage->GetTimeSteps(); ++i) + { + typename InputFrameImageType::Pointer frameImage; + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(this->m_DynamicImage); + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + Image::Pointer frameMITKImage = imageTimeSelector->GetOutput(); + frameCache.push_back(frameMITKImage); + mitk::CastToItkImage(frameMITKImage, frameImage); + fitFilter->SetInput(i,frameImage); + } + + ModelBaseType::TimeGridType timeGrid = ExtractTimeGrid(m_DynamicImage); + if (m_TimeGridByParameterizer) + { + if (timeGrid.GetSize() != m_ModelParameterizer->GetDefaultTimeGrid().GetSize()) + { + mitkThrow() << "Cannot do fitting. Filter is set to use default time grid of the parameterizer, but grid size does not match the number of input image frames. Grid size: " << m_ModelParameterizer->GetDefaultTimeGrid().GetSize() << "; frame count: " << timeGrid.GetSize(); + } + + } + else + { + this->m_ModelParameterizer->SetDefaultTimeGrid(timeGrid); + } + + ModelFitFunctorPolicy functor; + + functor.SetModelFitFunctor(this->m_FitFunctor); + functor.SetModelParameterizer(this->m_ModelParameterizer); + fitFilter->SetFunctor(functor); + if (this->m_InternalMask.IsNotNull()) + { + fitFilter->SetMask(this->m_InternalMask); + } + + //generate the fits + fitFilter->Update(); + + //convert the outputs into mitk images and fill the parameter image map + ModelBaseType::Pointer refModel = this->m_ModelParameterizer->GenerateParameterizedModel(); + ModelFitFunctorBase::ParameterNamesType paramNames = refModel->GetParameterNames(); + ModelFitFunctorBase::ParameterNamesType derivedParamNames = refModel->GetDerivedParameterNames(); + ModelFitFunctorBase::ParameterNamesType criterionNames = this->m_FitFunctor->GetCriterionNames(); + ModelFitFunctorBase::ParameterNamesType evaluationParamNames = this->m_FitFunctor->GetEvaluationParameterNames(); + ModelFitFunctorBase::ParameterNamesType debugParamNames = this->m_FitFunctor->GetDebugParameterNames(); + + if (fitFilter->GetNumberOfOutputs() != (paramNames.size() + derivedParamNames.size() + criterionNames.size() + evaluationParamNames.size() + debugParamNames.size())) + { + mitkThrow() << "Error while generating fitted parameter images. Fit filter output size does not match expected parameter number. Output size: "<< fitFilter->GetNumberOfOutputs(); + } + + ModelFitFunctorBase::ParameterNamesType::size_type resultPos = 0; + this->m_TempResultMap = StoreResultImages(paramNames,fitFilter,resultPos, resultPos); + this->m_TempDerivedResultMap = StoreResultImages(derivedParamNames,fitFilter,resultPos, resultPos); + this->m_TempCriterionResultMap = StoreResultImages(criterionNames,fitFilter,resultPos, resultPos); + this->m_TempEvaluationResultMap = StoreResultImages(evaluationParamNames,fitFilter,resultPos, resultPos); + //also add debug params (if generated) to the evaluation result map + mitk::PixelBasedParameterFitImageGenerator::ParameterImageMapType debugMap = StoreResultImages(debugParamNames, fitFilter, resultPos, resultPos); + this->m_TempEvaluationResultMap.insert(debugMap.begin(), debugMap.end()); +} + +bool + mitk::PixelBasedParameterFitImageGenerator::HasOutdatedResult() const +{ + bool result = Superclass::HasOutdatedResult(); + + if (m_ModelParameterizer.IsNotNull()) + { + if (m_ModelParameterizer->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + if (m_FitFunctor.IsNotNull()) + { + if (m_FitFunctor->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + if (m_DynamicImage.IsNotNull()) + { + if (m_DynamicImage->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + if (m_Mask.IsNotNull()) + { + if (m_Mask->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + return result; + +}; + +void + mitk::PixelBasedParameterFitImageGenerator::CheckValidInputs() const +{ + Superclass::CheckValidInputs(); + + if (m_DynamicImage.IsNull()) + { + mitkThrow() << "Cannot generate fitted parameter images. Input dynamic image is not set."; + } + +}; + +void mitk::PixelBasedParameterFitImageGenerator::DoFitAndGetResults(ParameterImageMapType& parameterImages, ParameterImageMapType& derivedParameterImages, ParameterImageMapType& criterionImages, ParameterImageMapType& evaluationParameterImages) +{ + this->m_Progress = 0; + + if(this->m_Mask.IsNotNull()) + { + AccessFixedDimensionByItk(m_Mask, mitk::PixelBasedParameterFitImageGenerator::DoPrepareMask, 3); + } + else + { + this->m_InternalMask = nullptr; + } + + AccessFixedDimensionByItk(m_DynamicImage, mitk::PixelBasedParameterFitImageGenerator::DoParameterFit, 4); + + parameterImages = this->m_TempResultMap; + derivedParameterImages = this->m_TempDerivedResultMap; + criterionImages = this->m_TempCriterionResultMap; + evaluationParameterImages = this->m_TempEvaluationResultMap; + +}; + +double + mitk::PixelBasedParameterFitImageGenerator::GetProgress() const +{ + return m_Progress; +}; + +mitk::PixelBasedParameterFitImageGenerator::ParameterNamesType +mitk::PixelBasedParameterFitImageGenerator::GetParameterNames() const +{ + ParameterizerType::ModelBasePointer parameterizedModel = + m_ModelParameterizer->GenerateParameterizedModel(); + + return parameterizedModel->GetParameterNames(); +} + +mitk::PixelBasedParameterFitImageGenerator::ParameterNamesType +mitk::PixelBasedParameterFitImageGenerator::GetDerivedParameterNames() const +{ + ParameterizerType::ModelBasePointer parameterizedModel = + m_ModelParameterizer->GenerateParameterizedModel(); + + return parameterizedModel->GetDerivedParameterNames(); +} + +mitk::PixelBasedParameterFitImageGenerator::ParameterNamesType +mitk::PixelBasedParameterFitImageGenerator::GetCriterionNames() const +{ + return this->m_FitFunctor->GetCriterionNames(); +} + +mitk::PixelBasedParameterFitImageGenerator::ParameterNamesType +mitk::PixelBasedParameterFitImageGenerator::GetEvaluationParameterNames() const +{ + auto evals = this->m_FitFunctor->GetEvaluationParameterNames(); + auto debugs = this->m_FitFunctor->GetDebugParameterNames(); + + evals.insert(evals.end(), debugs.begin(), debugs.end()); + + return evals; +} diff --git a/Modules/ModelFit/src/Common/mitkROIBasedParameterFitImageGenerator.cpp b/Modules/ModelFit/src/Common/mitkROIBasedParameterFitImageGenerator.cpp new file mode 100644 index 0000000000..7c440fe808 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkROIBasedParameterFitImageGenerator.cpp @@ -0,0 +1,268 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "itkChangeInformationImageFilter.h" + +#include "mitkROIBasedParameterFitImageGenerator.h" +#include "mitkImageAccessByItk.h" +#include "mitkImageCast.h" + +void +mitk::ROIBasedParameterFitImageGenerator:: +onFitProgressEvent(::itk::Object* caller, const ::itk::EventObject& /*eventObject*/) +{ + this->InvokeEvent(::itk::ProgressEvent()); + + itk::ProcessObject* process = dynamic_cast(caller); + + if (process) + { + this->m_Progress = process->GetProgress(); + } +}; + +template +void +mitk::ROIBasedParameterFitImageGenerator::DoImageGeneration(itk::Image* image, + double value) +{ + typedef itk::Image MaskType; + typedef itk::Image ParameterImageType; + + typedef itk::ChangeInformationImageFilter< ParameterImageType > OutputImageInformationFilterType; + typename OutputImageInformationFilterType::Pointer copyGeoInfoFilter = + OutputImageInformationFilterType::New(); + + typename ParameterImageType::Pointer paramImg = ParameterImageType::New(); + + copyGeoInfoFilter->ChangeDirectionOn(); + copyGeoInfoFilter->SetOutputDirection(image->GetDirection()); + copyGeoInfoFilter->ChangeOriginOn(); + copyGeoInfoFilter->SetOutputOrigin(image->GetOrigin()); + copyGeoInfoFilter->ChangeSpacingOn(); + copyGeoInfoFilter->SetOutputSpacing(image->GetSpacing()); + copyGeoInfoFilter->SetInput(paramImg); + copyGeoInfoFilter->Update(); + + paramImg = copyGeoInfoFilter->GetOutput(); + paramImg->SetRegions(image->GetLargestPossibleRegion()); + paramImg->Allocate(); + paramImg->FillBuffer(0.0); + + typedef itk::ImageRegionConstIterator MaskIteratorType; + typedef itk::ImageRegionIterator ImageIteratorType; + + MaskIteratorType maskItr(image, image->GetLargestPossibleRegion()); + ImageIteratorType imgItr(paramImg, image->GetLargestPossibleRegion()); + maskItr.GoToBegin(); + imgItr.GoToBegin(); + while (!maskItr.IsAtEnd()) + { + if (maskItr.Get() > 0.0) + { + imgItr.Set(value); + } + + ++maskItr; + ++imgItr; + } + + m_TempResultImage = Image::New(); + mitk::CastToMitkImage(paramImg, m_TempResultImage); +} + +bool +mitk::ROIBasedParameterFitImageGenerator::HasOutdatedResult() const +{ + bool result = Superclass::HasOutdatedResult(); + + if (m_ModelParameterizer.IsNotNull()) + { + if (m_ModelParameterizer->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + if (m_Mask.IsNotNull()) + { + if (m_Mask->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + if (m_FitFunctor.IsNotNull()) + { + if (m_FitFunctor->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + return result; +}; + +void +mitk::ROIBasedParameterFitImageGenerator::CheckValidInputs() const +{ + Superclass::CheckValidInputs(); + + if (m_Mask.IsNull()) + { + mitkThrow() << "Cannot generate fitted parameter images. Input mask is not set."; + } + + if (m_Signal.Size() != m_TimeGrid.Size()) + { + mitkThrow() << "Cannot generate fitted parameter images. Signal and TimeGrid do not match."; + } + +}; + +void mitk::ROIBasedParameterFitImageGenerator::DoFitAndGetResults(ParameterImageMapType& + parameterImages, ParameterImageMapType& derivedParameterImages, + ParameterImageMapType& criterionImages, ParameterImageMapType& evaluationParameterImages) +{ + this->m_Progress = 0; + + //fit the signal + ModelParameterizerBase::IndexType index; + index.Fill(0); + this->m_ModelParameterizer->SetDefaultTimeGrid(m_TimeGrid); + ParameterizerType::ModelBasePointer parameterizedModel = + m_ModelParameterizer->GenerateParameterizedModel(index); + ParameterizerType::ParametersType initialParameters = + m_ModelParameterizer->GetInitialParameterization(index); + + ModelFitFunctorBase::InputPixelArrayType inputValues; + + for (SignalType::const_iterator pos = m_Signal.begin(); pos != m_Signal.end(); ++pos) + { + inputValues.push_back(*pos); + } + + ModelFitFunctorBase::OutputPixelArrayType fitResult = m_FitFunctor->Compute(inputValues, + parameterizedModel, initialParameters); + + //generate the results maps + ParameterImageMapType tempResultMap; + ParameterImageMapType tempDerivedResultMap; + ParameterImageMapType tempEvaluationResultMap; + ParameterImageMapType tempCriterionResultMap; + + ModelFitFunctorBase::ParameterNamesType paramNames = parameterizedModel->GetParameterNames(); + ModelFitFunctorBase::ParameterNamesType derivedParamNames = + parameterizedModel->GetDerivedParameterNames(); + ModelFitFunctorBase::ParameterNamesType criterionNames = this->m_FitFunctor->GetCriterionNames(); + ModelFitFunctorBase::ParameterNamesType evaluationParamNames = + this->m_FitFunctor->GetEvaluationParameterNames(); + ModelFitFunctorBase::ParameterNamesType debugParamNames = this->m_FitFunctor->GetDebugParameterNames(); + + if (fitResult.size() != (paramNames.size() + derivedParamNames.size() + criterionNames.size() + + evaluationParamNames.size() + debugParamNames.size())) + { + mitkThrow() << + "Error while generating fitted parameter images. Fit functor output size does not match expected parameter number. Output size: " + << fitResult.size(); + } + + for (ModelFitFunctorBase::ParameterNamesType::size_type j = 0; j < paramNames.size(); ++j) + { + ModelFitFunctorBase::OutputPixelArrayType::value_type value = fitResult[j]; + AccessByItk_n(m_Mask, mitk::ROIBasedParameterFitImageGenerator::DoImageGeneration, (value)); + tempResultMap.insert(std::make_pair(paramNames[j], m_TempResultImage)); + } + + ModelFitFunctorBase::ParameterNamesType::size_type offset = paramNames.size(); + for (ModelFitFunctorBase::ParameterNamesType::size_type j = 0; j < derivedParamNames.size(); ++j) + { + ModelFitFunctorBase::OutputPixelArrayType::value_type value = fitResult[j + offset]; + AccessByItk_n(m_Mask, mitk::ROIBasedParameterFitImageGenerator::DoImageGeneration, (value)); + tempDerivedResultMap.insert(std::make_pair(derivedParamNames[j], m_TempResultImage)); + } + + offset += derivedParamNames.size(); + for (ModelFitFunctorBase::ParameterNamesType::size_type j = 0; j < criterionNames.size(); ++j) + { + ModelFitFunctorBase::OutputPixelArrayType::value_type value = fitResult[j + offset]; + AccessByItk_n(m_Mask, mitk::ROIBasedParameterFitImageGenerator::DoImageGeneration, (value)); + tempCriterionResultMap.insert(std::make_pair(criterionNames[j], m_TempResultImage)); + } + + offset += criterionNames.size(); + for (ModelFitFunctorBase::ParameterNamesType::size_type j = 0; j < evaluationParamNames.size(); ++j) + { + ModelFitFunctorBase::OutputPixelArrayType::value_type value = fitResult[j + offset]; + AccessByItk_n(m_Mask, mitk::ROIBasedParameterFitImageGenerator::DoImageGeneration, (value)); + tempEvaluationResultMap.insert(std::make_pair(evaluationParamNames[j], m_TempResultImage)); + } + + offset += evaluationParamNames.size(); + for (ModelFitFunctorBase::ParameterNamesType::size_type j = 0; j < debugParamNames.size(); ++j) + { //add debug params (if they are generated to the evaluation result map + ModelFitFunctorBase::OutputPixelArrayType::value_type value = fitResult[j + offset]; + AccessByItk_n(m_Mask, mitk::ROIBasedParameterFitImageGenerator::DoImageGeneration, (value)); + tempEvaluationResultMap.insert(std::make_pair(debugParamNames[j], m_TempResultImage)); + } + + parameterImages = tempResultMap; + derivedParameterImages = tempDerivedResultMap; + criterionImages = tempCriterionResultMap; + evaluationParameterImages = tempEvaluationResultMap; + +}; + +double +mitk::ROIBasedParameterFitImageGenerator::GetProgress() const +{ + return m_Progress; +}; + +mitk::ROIBasedParameterFitImageGenerator::ParameterNamesType +mitk::ROIBasedParameterFitImageGenerator::GetParameterNames() const +{ + ParameterizerType::ModelBasePointer parameterizedModel = + m_ModelParameterizer->GenerateParameterizedModel(); + + return parameterizedModel->GetParameterNames(); +} + +mitk::ROIBasedParameterFitImageGenerator::ParameterNamesType +mitk::ROIBasedParameterFitImageGenerator::GetDerivedParameterNames() const +{ + ParameterizerType::ModelBasePointer parameterizedModel = + m_ModelParameterizer->GenerateParameterizedModel(); + + return parameterizedModel->GetDerivedParameterNames(); +} + +mitk::ROIBasedParameterFitImageGenerator::ParameterNamesType +mitk::ROIBasedParameterFitImageGenerator::GetCriterionNames() const +{ + return this->m_FitFunctor->GetCriterionNames(); +} + +mitk::ROIBasedParameterFitImageGenerator::ParameterNamesType +mitk::ROIBasedParameterFitImageGenerator::GetEvaluationParameterNames() const +{ + auto evals = this->m_FitFunctor->GetEvaluationParameterNames(); + auto debugs = this->m_FitFunctor->GetDebugParameterNames(); + + evals.insert(evals.end(), debugs.begin(), debugs.end()); + + return evals; +} diff --git a/Modules/ModelFit/src/Common/mitkScalarListLookupTable.cpp b/Modules/ModelFit/src/Common/mitkScalarListLookupTable.cpp new file mode 100644 index 0000000000..de51ca07f0 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkScalarListLookupTable.cpp @@ -0,0 +1,120 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkScalarListLookupTable.h" +#include +#include +const char* mitk::ScalarListLookupTable::GetNameOfClass() const +{ + return "ScalarListLookupTable"; +} + +void mitk::ScalarListLookupTable::SetTableValue(const KeyType& key, const ValueType& value) +{ + m_LookupTable[key] = value; +} + +bool mitk::ScalarListLookupTable::ValueExists(const KeyType& key) const +{ + LookupTableType::const_iterator it = m_LookupTable.find(key); + return (it != m_LookupTable.end()); +} + +const mitk::ScalarListLookupTable::ValueType& +mitk::ScalarListLookupTable::GetTableValue(const KeyType& key) const +{ + LookupTableType::const_iterator it = m_LookupTable.find(key); + + if (it != m_LookupTable.end()) + { + return it->second; + } + else + { + throw std::range_error("id does not exist in the lookup table"); + } +} + +const mitk::ScalarListLookupTable::LookupTableType& +mitk::ScalarListLookupTable::GetLookupTable() const +{ + return m_LookupTable; +} + +void mitk::ScalarListLookupTable::SetLookupTable(const LookupTableType& table) +{ + m_LookupTable = table; +}; + + +bool mitk::ScalarListLookupTable::operator==(const mitk::ScalarListLookupTable& lookupTable) const +{ + return (m_LookupTable == lookupTable.m_LookupTable); +} +bool mitk::ScalarListLookupTable::operator!=(const mitk::ScalarListLookupTable& lookupTable) const +{ + return !(m_LookupTable == lookupTable.m_LookupTable); +} + +mitk::ScalarListLookupTable& +mitk::ScalarListLookupTable::operator=(const ScalarListLookupTable& other) +{ + if (this == &other) + { + return *this; + } + else + { + m_LookupTable = other.m_LookupTable; + return *this; + } +} + +std::ostream& mitk::operator<<(std::ostream& stream, const ScalarListLookupTable& l) +{ + typedef ScalarListLookupTable::LookupTableType::const_iterator MapIterType; + typedef ScalarListLookupTable::ValueType::const_iterator VectorIterType; + MapIterType mapStart = l.GetLookupTable().begin(); + MapIterType mapEnd = l.GetLookupTable().end(); + stream << "["; + + for (MapIterType i = mapStart; i != mapEnd; ++i) + { + if (i != mapStart) + { + stream << ", "; + } + + stream << i->first << " -> ["; + + VectorIterType vectorStart = i->second.begin(); + VectorIterType vectorEnd = i->second.end(); + + for (VectorIterType j = vectorStart; j != vectorEnd; ++j) + { + if (j != vectorStart) + { + stream << ", "; + } + + stream << *j; + } + + stream << "]"; + } + + return stream << "]"; +}; diff --git a/Modules/ModelFit/src/Common/mitkScalarListLookupTableProperty.cpp b/Modules/ModelFit/src/Common/mitkScalarListLookupTableProperty.cpp new file mode 100644 index 0000000000..f601494c3c --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkScalarListLookupTableProperty.cpp @@ -0,0 +1,20 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkScalarListLookupTableProperty.h" + +mitkDefineGenericProperty(ScalarListLookupTableProperty, ScalarListLookupTable, + ScalarListLookupTable()); diff --git a/Modules/ModelFit/src/Common/mitkScalarListLookupTablePropertySerializer.cpp b/Modules/ModelFit/src/Common/mitkScalarListLookupTablePropertySerializer.cpp new file mode 100644 index 0000000000..f7ffa847b5 --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkScalarListLookupTablePropertySerializer.cpp @@ -0,0 +1,131 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkScalarListLookupTableProperty.h" +#include "mitkScalarListLookupTablePropertySerializer.h" + + +TiXmlElement* mitk::ScalarListLookupTablePropertySerializer::Serialize() +{ + const ScalarListLookupTableProperty* prop = + dynamic_cast(m_Property.GetPointer()); + + if (prop == NULL) + { + MITK_ERROR << "Serialization: Property is NULL"; + return NULL; + } + + ScalarListLookupTable lut = prop->GetValue(); + const ScalarListLookupTable::LookupTableType& map = lut.GetLookupTable(); + + TiXmlElement* mapElement = new TiXmlElement("ScalarListLookupTable"); + + for (ScalarListLookupTable::LookupTableType::const_iterator mapIter = map.begin(); + mapIter != map.end(); ++mapIter) + { + const ScalarListLookupTable::ValueType& list = mapIter->second; + TiXmlElement* listElement = new TiXmlElement("List"); + listElement->SetAttribute("name", mapIter->first); + + for (ScalarListLookupTable::ValueType::const_iterator listIter = list.begin(); + listIter != list.end(); ++listIter) + { + TiXmlElement* valueElement = new TiXmlElement("Element"); + valueElement->SetDoubleAttribute("value", *listIter); + listElement->LinkEndChild(valueElement); + } + + mapElement->LinkEndChild(listElement); + } + + return mapElement; +} + +mitk::BaseProperty::Pointer +mitk::ScalarListLookupTablePropertySerializer::Deserialize(TiXmlElement* element) +{ + if (!element) + { + MITK_ERROR << "Deserialization: Element is NULL"; + return NULL; + } + + ScalarListLookupTable lut; + + for (TiXmlElement* listElement = element->FirstChildElement("List"); + listElement != NULL; listElement = listElement->NextSiblingElement("List")) + { + std::string name; + + if (listElement->Attribute("name") != NULL) + { + name = listElement->Attribute("name"); + } + else + { + MITK_ERROR << "Deserialization: No element with attribute 'name' found"; + return NULL; + } + + ScalarListLookupTable::ValueType list; + + for (TiXmlElement* valueElement = listElement->FirstChildElement("Element"); + valueElement != NULL; + valueElement = valueElement->NextSiblingElement("Element")) + { + double value; + + if (valueElement->QueryDoubleAttribute("value", &value) == TIXML_WRONG_TYPE) + { + MITK_ERROR << "Deserialization: No element with attribute 'value' found"; + return NULL; + } + + list.push_back(value); + } + + lut.SetTableValue(name, list); + } + + return ScalarListLookupTableProperty::New(lut).GetPointer(); +} + +MITK_REGISTER_SERIALIZER(ScalarListLookupTablePropertySerializer); + +::std::string mitk::PropertyPersistenceSerialization::serializeScalarListLookupTablePropertyToXML( + const mitk::BaseProperty *prop) +{ + mitk::ScalarListLookupTablePropertySerializer::Pointer lutSerializer = mitk::ScalarListLookupTablePropertySerializer::New(); + + lutSerializer->SetProperty(prop); + auto xmlLut = lutSerializer->Serialize(); + + TiXmlPrinter printer; + xmlLut->Accept(&printer); + printer.SetStreamPrinting(); + return printer.Str(); +} + +mitk::BaseProperty::Pointer mitk::PropertyPersistenceDeserialization::deserializeXMLToScalarListLookupTableProperty( + const std::string &value) +{ + mitk::ScalarListLookupTablePropertySerializer::Pointer lutSerializer = mitk::ScalarListLookupTablePropertySerializer::New(); + + TiXmlDocument doc; + doc.Parse(value.c_str()); + return lutSerializer->Deserialize(doc.RootElement()); +} diff --git a/Modules/ModelFit/src/Common/mitkTimeGridHelper.cpp b/Modules/ModelFit/src/Common/mitkTimeGridHelper.cpp new file mode 100644 index 0000000000..ddd01d83fe --- /dev/null +++ b/Modules/ModelFit/src/Common/mitkTimeGridHelper.cpp @@ -0,0 +1,71 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTimeGridHelper.h" + +#include "itkExceptionObject.h" + +bool mitk::TimeGridIsMonotonIncreasing(const mitk::ModelBase::TimeGridType timeGrid) +{ + mitk::ModelBase::TimeGridType::ValueType lastTime = itk::NumericTraits::NonpositiveMin(); + + for(mitk::ModelBase::TimeGridType::const_iterator posTime = timeGrid.begin(); posTime != timeGrid.end(); ++posTime) + { + if (lastTime>*posTime) return false; + } + + return true; +}; + +mitk::ModelBase::ModelResultType mitk::InterpolateSignalToNewTimeGrid(const ModelBase::ModelResultType& inputSignal, const ModelBase::TimeGridType& inputGrid, const ModelBase::TimeGridType& outputGrid) +{ + mitk::ModelBase::ModelResultType result(outputGrid.GetSize()); + if (! inputSignal.GetSize()) + { + return result; + } + + if (inputSignal.GetSize() != inputGrid.GetSize()) + { + itkGenericExceptionMacro("Input signal and input time grid have not the same size."); + } + + mitk::ModelBase::ModelResultType::ValueType lastValue = inputSignal[0]; + mitk::ModelBase::TimeGridType::ValueType lastTime = itk::NumericTraits::NonpositiveMin(); + + mitk::ModelBase::TimeGridType::const_iterator posITime = inputGrid.begin(); + mitk::ModelBase::ModelResultType::const_iterator posValue = inputSignal.begin(); + mitk::ModelBase::ModelResultType::iterator posResult = result.begin(); + + for(mitk::ModelBase::TimeGridType::const_iterator posOTime = outputGrid.begin(); posOTime != outputGrid.end(); ++posResult, ++posOTime) + { + while(*posOTime > *posITime && posITime!=inputGrid.end()) + { //forward in the input grid until the current output point + //is between last and the current input point. + lastValue = *posValue; + lastTime = *posITime; + ++posValue; + ++posITime; + } + + double weightLast = 1 - (*posOTime - lastTime)/(*posITime - lastTime); + double weightNext = 1 - (*posITime - *posOTime)/(*posITime - lastTime); + + *posResult = weightLast * lastValue + weightNext * (*posValue); + } + + return result; +}; diff --git a/Modules/ModelFit/src/Functors/mitkChiSquareFitCostFunction.cpp b/Modules/ModelFit/src/Functors/mitkChiSquareFitCostFunction.cpp new file mode 100644 index 0000000000..8eae773a15 --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkChiSquareFitCostFunction.cpp @@ -0,0 +1,29 @@ +#include "mitkChiSquareFitCostFunction.h" + +mitk::ChiSquareFitCostFunction::MeasureType mitk::ChiSquareFitCostFunction::CalcMeasure(const ParametersType & /*parameters*/, const SignalType &signal) const +{ + MeasureType measure = 0.0; + + mitk::ModelBase::TimeGridType grid = Superclass::GetModel()->GetTimeGrid(); + + + double dt = 0.0; + for(SignalType::size_type i=0; i +#include + +mitk::DummyModelFitFunctor:: +DummyModelFitFunctor(): m_DerivativeStepLength(1e-5) +{}; + +mitk::DummyModelFitFunctor:: +~DummyModelFitFunctor() +{}; + +mitk::DummyModelFitFunctor::ParameterNamesType +mitk::DummyModelFitFunctor:: +GetCriterionNames() const +{ + ParameterNamesType names; + names.push_back("sum_diff^2"); + return names; +}; + +mitk::DummyModelFitFunctor::OutputPixelArrayType +mitk::DummyModelFitFunctor:: +GetCriteria(const ModelBase* model, const ParametersType& parameters, + const SignalType& sample) const +{ + ::mitk::SumOfSquaredDifferencesFitCostFunction::Pointer metric + = ::mitk::SumOfSquaredDifferencesFitCostFunction::New(); + metric->SetModel(model); + metric->SetSample(sample); + + mitk::DummyModelFitFunctor::OutputPixelArrayType result(1); + result[0] = metric->GetValue(parameters); + + return result; +}; + +mitk::MVModelFitCostFunction::Pointer mitk::DummyModelFitFunctor::GenerateCostFunction( + const SignalType& value, const ModelBase* model) const +{ + ::mitk::SquaredDifferencesFitCostFunction::Pointer metric + = ::mitk::SquaredDifferencesFitCostFunction::New(); + metric->SetModel(model); + metric->SetSample(value); + metric->SetDerivativeStepLength(m_DerivativeStepLength); + + mitk::MVModelFitCostFunction::Pointer result = metric.GetPointer(); + + return result; +}; + +mitk::DummyModelFitFunctor::ParametersType +mitk::DummyModelFitFunctor:: +DoModelFit(const SignalType& value, const ModelBase* model, + const ModelBase::ParametersType& initialParameters, + DebugParameterMapType& /*debugParameters*/) const +{ + mitk::MVModelFitCostFunction::Pointer metric = this->GenerateCostFunction(value, model); + + MITK_INFO << "DEBUG signal: " << value; + MITK_INFO << "DEBUG time grid: " << model->GetTimeGrid(); + MITK_INFO << "DEBUG model: " << model->GetSignal(initialParameters); + MITK_INFO << "DEBUG parameters: " << initialParameters; + + MITK_INFO << "DEBUG metric values: " << metric->GetValue(initialParameters); + + return initialParameters; +}; + +mitk::DummyModelFitFunctor::ParameterNamesType +mitk::DummyModelFitFunctor::DefineDebugParameterNames() const +{ + return mitk::DummyModelFitFunctor::ParameterNamesType(); +}; diff --git a/Modules/ModelFit/src/Functors/mitkIndexedValueFunctorPolicy.cpp b/Modules/ModelFit/src/Functors/mitkIndexedValueFunctorPolicy.cpp new file mode 100644 index 0000000000..3f3eda0aec --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkIndexedValueFunctorPolicy.cpp @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkIndexedValueFunctorPolicy.h" + +mitk::IndexedValueFunctorPolicy::IndexedValueFunctorPolicy() +{}; + +mitk::IndexedValueFunctorPolicy::~IndexedValueFunctorPolicy() +{}; + +unsigned int mitk::IndexedValueFunctorPolicy::GetNumberOfOutputs() const +{ + unsigned int result = 0; + + if (m_Functor.IsNotNull()) + { + result = m_Functor->GetNumberOfOutputs(); + } + + return result; +} + +void mitk::IndexedValueFunctorPolicy::SetFunctor(const FunctorType *functor) +{ + if (!functor) + { + itkGenericExceptionMacro(<< "Error. Functor is Null."); + } + + m_Functor = functor; +} + + +bool mitk::IndexedValueFunctorPolicy::operator!=(const IndexedValueFunctorPolicy & other) const +{ + return !(*this == other); +} + +bool mitk::IndexedValueFunctorPolicy::operator==(const IndexedValueFunctorPolicy & other) const +{ + return (this->m_Functor == other.m_Functor); +} + +mitk::IndexedValueFunctorPolicy::OutputPixelVectorType mitk::IndexedValueFunctorPolicy::operator()(const InputPixelVectorType & value, const IndexType& currentIndex) const +{ + if (!m_Functor) + { + itkGenericExceptionMacro(<< "Error. Cannot process operator(). Functor is Null."); + } + + OutputPixelVectorType result = m_Functor->Compute(value, currentIndex); + + return result; +} diff --git a/Modules/ModelFit/src/Functors/mitkLevenbergMarquardtModelFitFunctor.cpp b/Modules/ModelFit/src/Functors/mitkLevenbergMarquardtModelFitFunctor.cpp new file mode 100644 index 0000000000..bf918d29ec --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkLevenbergMarquardtModelFitFunctor.cpp @@ -0,0 +1,179 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkLevenbergMarquardtModelFitFunctor.h" + +#include "mitkSquaredDifferencesFitCostFunction.h" +#include "mitkSumOfSquaredDifferencesFitCostFunction.h" +#include +#include + +mitk::LevenbergMarquardtModelFitFunctor:: +LevenbergMarquardtModelFitFunctor(): m_Epsilon(1e-5), m_GradientTolerance(1e-3), + m_ValueTolerance(1e-5), m_Iterations(1000), m_DerivativeStepLength(1e-5), + m_ActivateFailureThreshold(true) +{}; + +mitk::LevenbergMarquardtModelFitFunctor:: +~LevenbergMarquardtModelFitFunctor() +{}; + +mitk::LevenbergMarquardtModelFitFunctor::ParameterNamesType +mitk::LevenbergMarquardtModelFitFunctor:: +GetCriterionNames() const +{ + ParameterNamesType names; + names.push_back("sum_diff^2"); + return names; +}; + +mitk::LevenbergMarquardtModelFitFunctor::OutputPixelArrayType +mitk::LevenbergMarquardtModelFitFunctor:: +GetCriteria(const ModelBase* model, const ParametersType& parameters, + const SignalType& sample) const +{ + ::mitk::SumOfSquaredDifferencesFitCostFunction::Pointer metric + = ::mitk::SumOfSquaredDifferencesFitCostFunction::New(); + metric->SetModel(model); + metric->SetSample(sample); + + mitk::LevenbergMarquardtModelFitFunctor::OutputPixelArrayType result(1); + result[0] = metric->GetValue(parameters); + + return result; +}; + +mitk::MVModelFitCostFunction::Pointer mitk::LevenbergMarquardtModelFitFunctor::GenerateCostFunction( + const SignalType& value, const ModelBase* model) const +{ + ::mitk::SquaredDifferencesFitCostFunction::Pointer metric + = ::mitk::SquaredDifferencesFitCostFunction::New(); + metric->SetModel(model); + metric->SetSample(value); + metric->SetDerivativeStepLength(m_DerivativeStepLength); + + mitk::MVModelFitCostFunction::Pointer result = metric.GetPointer(); + + if (m_ConstraintChecker.IsNotNull()) + { + ::mitk::MVConstrainedCostFunctionDecorator::Pointer decorator + = ::mitk::MVConstrainedCostFunctionDecorator::New(); + decorator->SetConstraintChecker(m_ConstraintChecker); + decorator->SetWrappedCostFunction(metric); + decorator->SetFailureThreshold(m_ConstraintChecker->GetFailedConstraintValue()); + + decorator->SetModel(model); + decorator->SetSample(value); + decorator->SetActivateFailureThreshold(m_ActivateFailureThreshold); + result = decorator; + } + + return result; +}; + +mitk::LevenbergMarquardtModelFitFunctor::ParameterNamesType +mitk::LevenbergMarquardtModelFitFunctor::DefineDebugParameterNames() const +{ + ParameterNamesType result; + result.push_back("optimization_time"); + result.push_back("nr_of_iterations"); + result.push_back("stop_condition"); + if (m_ConstraintChecker.IsNotNull()) + { + result.push_back("constraint_penalty_ratio"); + result.push_back("constraint_failure_ratio"); + result.push_back("constraint_last_failed_parameter"); + } + return result; +}; + +mitk::LevenbergMarquardtModelFitFunctor::ParametersType +mitk::LevenbergMarquardtModelFitFunctor:: +DoModelFit(const SignalType& value, const ModelBase* model, + const ModelBase::ParametersType& initialParameters, + DebugParameterMapType& debugParameters) const +{ + std::chrono::time_point startTime; + startTime = std::chrono::system_clock::now(); + ::itk::LevenbergMarquardtOptimizer::ParametersType internalInitParam = initialParameters; + ::itk::LevenbergMarquardtOptimizer::ScalesType scales = m_Scales; + + if (initialParameters.GetNumberOfElements() != model->GetNumberOfParameters()) + { + MITK_DEBUG << + "Size of initial parameters of fit functor optimizer do not match number of model parameters. Renitialize parameters with 0.0."; + internalInitParam.SetSize(model->GetNumberOfParameters()); + internalInitParam.Fill(0.0); + } + + if (m_Scales.GetNumberOfElements() != model->GetNumberOfParameters()) + { + MITK_DEBUG << + "Size of scales of fit functor optimizer do not match number of model parameters. Reinitialize scales with 1.0."; + scales.SetSize(model->GetNumberOfParameters()); + scales.Fill(1.0); + } + + mitk::MVModelFitCostFunction::Pointer metric = this->GenerateCostFunction(value, model); + + ::itk::LevenbergMarquardtOptimizer::Pointer optimizer = ::itk::LevenbergMarquardtOptimizer::New(); + + optimizer->SetCostFunction(metric); + optimizer->SetEpsilonFunction(m_Epsilon); + optimizer->SetGradientTolerance(m_GradientTolerance); + optimizer->SetNumberOfIterations(m_Iterations); + optimizer->SetScales(scales); + optimizer->SetInitialPosition(internalInitParam); + + optimizer->StartOptimization(); + + itk::Optimizer::ParametersType position = optimizer->GetCurrentPosition(); + + std::chrono::time_point stopTime; + stopTime = std::chrono::system_clock::now(); + debugParameters.clear(); + if (this->GetDebugParameterMaps()) + { + const auto timeDiff = std::chrono::duration_cast(stopTime - startTime).count(); + debugParameters.insert(std::make_pair("optimization_time", timeDiff)); + + ParameterImagePixelType value = optimizer->GetOptimizer()->get_num_iterations(); + debugParameters.insert(std::make_pair("nr_of_iterations", value)); + value = optimizer->GetOptimizer()->get_failure_code(); + debugParameters.insert(std::make_pair("stop_condition", value)); + + + const ::mitk::MVConstrainedCostFunctionDecorator* decorator = dynamic_cast(metric.GetPointer()); + if (decorator) + { + value = decorator->GetPenaltyRatio(); + debugParameters.insert(std::make_pair("constraint_penalty_ratio", value)); + value = decorator->GetFailureRatio(); + debugParameters.insert(std::make_pair("constraint_failure_ratio", value)); + value = decorator->GetFailedParameter(); + debugParameters.insert(std::make_pair("constraint_last_failed_parameter", value)); + } + else + { + if (m_ConstraintChecker.IsNotNull()) + { + mitkThrow() << "Fit functor has invalid state/wrong implementation. Constraint checker is set, but used metric seems to be no MVContstrainedCostFunctionDecorator."; + } + } + } + + return position; +}; diff --git a/Modules/ModelFit/src/Functors/mitkMVConstrainedCostFunctionDecorator.cpp b/Modules/ModelFit/src/Functors/mitkMVConstrainedCostFunctionDecorator.cpp new file mode 100644 index 0000000000..51eec79b0b --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkMVConstrainedCostFunctionDecorator.cpp @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkMVConstrainedCostFunctionDecorator.h" + +#include + +#include + +mitk::MVConstrainedCostFunctionDecorator::MeasureType + mitk::MVConstrainedCostFunctionDecorator::CalcMeasure(const ParametersType ¶meters, const SignalType & /*signal*/) const +{ + if (m_ConstraintChecker.IsNull()) mitkThrow()<<"Error. Cannot calc measure. Constraint checker is not set"; + if (m_WrappedCostFunction.IsNull()) mitkThrow()<<"Error. Cannot calc measure. Wrapped metric is not set"; + + m_EvaluationCount++; + + PenaltyValueType penalty = m_ConstraintChecker->GetPenaltySum(parameters); + + MeasureType measure; + measure.SetSize(m_WrappedCostFunction->GetNumberOfValues()); + measure.Fill(penalty); + + if (penaltyGetValue(parameters); + if (wrappedMeasure.Size() != measure.Size()) mitkThrow()<<"Error. Cannot calc measure. Penalty measure and wrapped measure have different size. Penalty size:"< 0) + { + ++m_PenaltyCount; + } + } + else + { + auto penalties = m_ConstraintChecker->GetPenalties(parameters); + for (ParametersType::size_type pos = 0; pos < penalties.size(); ++pos) + { + if (penalties[pos] >= m_FailureThreshold) + { + m_LastFailedParameter = pos; + break; + } + } + m_FailureCount++; + } + + return measure; +} + +double +mitk::MVConstrainedCostFunctionDecorator:: +GetPenaltyRatio() const +{ + return m_PenaltyCount / (double)m_EvaluationCount; +}; + +double +mitk::MVConstrainedCostFunctionDecorator:: +GetFailureRatio() const +{ + return m_FailureCount / (double)m_EvaluationCount; +}; + +mitk::MVConstrainedCostFunctionDecorator::ParametersType::size_type +mitk::MVConstrainedCostFunctionDecorator:: +GetFailedParameter() const +{ + return m_LastFailedParameter; +}; diff --git a/Modules/ModelFit/src/Functors/mitkMVModelFitCostFunction.cpp b/Modules/ModelFit/src/Functors/mitkMVModelFitCostFunction.cpp new file mode 100644 index 0000000000..413916c314 --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkMVModelFitCostFunction.cpp @@ -0,0 +1,79 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkMVModelFitCostFunction.h" + +#include + + +mitk::MVModelFitCostFunction::MeasureType mitk::MVModelFitCostFunction::GetValue(const ParametersType ¶meter) const +{ + MeasureType measure; + + SignalType signal = m_Model->GetSignal(parameter); + + if(signal.GetSize() != m_Sample.GetSize()) itkExceptionMacro("Signal size does not matche sample size!"); + if(signal.GetSize() == 0) itkExceptionMacro("Signal is empty!"); + + measure = CalcMeasure(parameter, signal); + + return measure; +} + +void mitk::MVModelFitCostFunction::GetDerivative (const ParametersType ¶meters, DerivativeType &derivative) const +{ + ParametersType::SizeValueType paramCount = parameters.Size(); + MeasureType::SizeValueType measureCount = GetNumberOfValues(); + + derivative.SetSize(paramCount,m_Sample.Size()); + + for ( ParametersType::SizeValueType i = 0; i < paramCount; i++ ) + { + ParametersType newParameters = parameters; + newParameters[i] -= m_DerivativeStepLength; + + MeasureType e0 = GetValue(newParameters); + + newParameters = parameters; + newParameters[i] += m_DerivativeStepLength; + + MeasureType e1 = GetValue(newParameters); + + for(MeasureType::SizeValueType j = 0; jGetNumberOfParameters(); +} + +unsigned int mitk::MVModelFitCostFunction::GetNumberOfValues() const{ + return m_Sample.GetSize(); +} + +void mitk::MVModelFitCostFunction::SetSample(const SignalType &sampleSet) +{ + itkDebugMacro("setting Sample to " << sampleSet); + this->m_Sample = sampleSet; + this->Modified(); +} + diff --git a/Modules/ModelFit/src/Functors/mitkModelDataGenerationFunctor.cpp b/Modules/ModelFit/src/Functors/mitkModelDataGenerationFunctor.cpp new file mode 100644 index 0000000000..b5ca05706d --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkModelDataGenerationFunctor.cpp @@ -0,0 +1,64 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelDataGenerationFunctor.h" + +mitk::SimpleFunctorBase::OutputPixelVectorType +mitk::ModelDataGenerationFunctor::Compute(const InputPixelVectorType &value) const { + if (this->m_ModelParameterizer->GetDefaultTimeGrid().GetSize() == 0) { + itkExceptionMacro("Error. Cannot compute SignalCurve. No time grid is set " + "in parameterizer!"); + } + + ModelParametersType parameters(value.size()); + + for (ModelParametersType::SizeValueType i = 0; i < parameters.Size(); ++i) { + parameters[i] = value[i]; + } + + ModelBase::Pointer model = + this->m_ModelParameterizer->GenerateParameterizedModel(); + SignalType signal = model->GetSignal(parameters); + + OutputPixelVectorType result; + + for (SignalType::const_iterator pos = signal.begin(); pos != signal.end(); + ++pos) { + result.push_back(*pos); + } + + return result; +}; + +unsigned int mitk::ModelDataGenerationFunctor::GetNumberOfOutputs() const { + if (m_ModelParameterizer.IsNotNull()) { + return m_ModelParameterizer->GetDefaultTimeGrid().GetSize(); + } + + return 0; +}; + +mitk::ModelDataGenerationFunctor::GridArrayType +mitk::ModelDataGenerationFunctor::GetGrid() const { + if (m_ModelParameterizer.IsNotNull()) { + return m_ModelParameterizer->GetDefaultTimeGrid(); + } + + return GridArrayType(); +}; + +mitk::ModelDataGenerationFunctor::ModelDataGenerationFunctor() = default; +mitk::ModelDataGenerationFunctor::~ModelDataGenerationFunctor() = default; diff --git a/Modules/ModelFit/src/Functors/mitkModelFitFunctorBase.cpp b/Modules/ModelFit/src/Functors/mitkModelFitFunctorBase.cpp new file mode 100644 index 0000000000..2af5a1dccc --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkModelFitFunctorBase.cpp @@ -0,0 +1,245 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelFitFunctorBase.h" + +mitk::ModelFitFunctorBase::OutputPixelArrayType +mitk::ModelFitFunctorBase:: +Compute(const InputPixelArrayType& value, const ModelBase* model, + const ModelBase::ParametersType& initialParameters) const +{ + if (!model) + { + itkExceptionMacro("Cannot compute fit. Passed model is not defined."); + } + + if (model->GetNumberOfParameters() != initialParameters.Size()) + { + itkExceptionMacro("Cannot compute fit. Parameter count of passed model and passed initial parameters differ. Model parameter count: " + << model->GetNumberOfParameters() << "; Initial parameters: " << initialParameters); + } + + SignalType sample(value.size()); + + for (SignalType::SizeValueType i = 0; i < sample.Size(); ++i) + { + sample[i] = value [i]; + } + + DebugParameterMapType debugParams; + ParameterNamesType debugNames; + if (this->m_DebugParameterMaps) + { + debugNames = this->GetDebugParameterNames(); + } + + ParametersType fittedParameters = DoModelFit(sample, model, initialParameters, debugParams); + + OutputPixelArrayType derivedParameters = this->GetDerivedParameters(model, fittedParameters); + + OutputPixelArrayType criteria = this->GetCriteria(model, fittedParameters, sample); + + OutputPixelArrayType evaluationParameters = this->GetEvaluationParameters(model, fittedParameters, + sample); + + if (criteria.size() != this->GetCriterionNames().size()) + { + itkExceptionMacro("ModelFitInfo implementation seems to be inconsitent. Number of criterion values is not equal to number of criterion names."); + } + + OutputPixelArrayType result(fittedParameters.Size() + derivedParameters.size() + criteria.size() + + evaluationParameters.size() + debugNames.size()); + + for (ParametersType::SizeValueType i = 0; i < fittedParameters.Size(); ++i) + { + result[i] = fittedParameters[i]; + } + + OutputPixelArrayType::size_type offset = fittedParameters.Size(); + + for (OutputPixelArrayType::size_type j = 0; j < derivedParameters.size(); ++j) + { + result[offset + j] = derivedParameters[j]; + } + + offset += derivedParameters.size(); + for (OutputPixelArrayType::size_type j = 0; j < criteria.size(); ++j) + { + result[offset + j] = criteria[j]; + } + + offset += criteria.size(); + for (OutputPixelArrayType::size_type j = 0; j < evaluationParameters.size(); ++j) + { + result[offset + j] = evaluationParameters[j]; + } + + offset += evaluationParameters.size(); + for (OutputPixelArrayType::size_type j = 0; j < debugNames.size(); ++j) + { + DebugParameterMapType::const_iterator pos = debugParams.find(debugNames[j]); + if (pos == debugParams.end()) + { + itkExceptionMacro("ModelFitInfo implementation seems to be inconsitent. Debug parameter defined by functor is not in its returned debug map. Invalid debug parameter name: "<second; + } + } + + return result; +}; + +unsigned int +mitk::ModelFitFunctorBase::GetNumberOfOutputs(const ModelBase* model) const +{ + if (!model) + { + itkExceptionMacro("Cannot get number of outputs. Model is not defined."); + } + + return model->GetNumberOfParameters() + model->GetNumberOfDerivedParameters() + + this->GetCriterionNames().size() + m_CostFunctionMap.size()+ this->GetDebugParameterNames().size(); +}; + +void +mitk::ModelFitFunctorBase::ResetEvaluationParameters() +{ + m_Mutex.Lock(); + + m_CostFunctionMap.clear(); + + m_Mutex.Unlock(); +}; + +void +mitk::ModelFitFunctorBase::RegisterEvaluationParameter(const std::string& parameterName, + SVModelFitCostFunction* evaluationCostFunction) +{ + m_Mutex.Lock(); + + SVModelFitCostFunction::Pointer costFunctPtr = evaluationCostFunction; + + m_CostFunctionMap.insert(std::make_pair(parameterName, costFunctPtr)); + + m_Mutex.Unlock(); +}; + +mitk::ModelFitFunctorBase::ParameterNamesType +mitk::ModelFitFunctorBase::GetEvaluationParameterNames() const +{ + m_Mutex.Lock(); + + ParameterNamesType result; + + for (CostFunctionMapType::const_iterator pos = m_CostFunctionMap.begin(); + pos != m_CostFunctionMap.end(); ++pos) + { + result.push_back(pos->first); + } + + m_Mutex.Unlock(); + + return result; +}; + +const mitk::SVModelFitCostFunction* +mitk::ModelFitFunctorBase::GetEvaluationParameterCostFunction(const std::string& parameterName) +const +{ + const SVModelFitCostFunction* result = NULL; + + m_Mutex.Lock(); + + CostFunctionMapType::const_iterator pos = m_CostFunctionMap.find(parameterName); + + if (pos != m_CostFunctionMap.end()) + { + result = (pos->second).GetPointer(); + } + + m_Mutex.Unlock(); + + return result; +}; + +mitk::ModelFitFunctorBase::ParameterNamesType +mitk::ModelFitFunctorBase::GetDebugParameterNames() const +{ + ParameterNamesType result; + + if (this->m_DebugParameterMaps) + { + result = this->DefineDebugParameterNames(); + } + + return result; +}; + +mitk::ModelFitFunctorBase:: +ModelFitFunctorBase() : m_DebugParameterMaps(false) +{}; + +mitk::ModelFitFunctorBase:: +~ModelFitFunctorBase() {}; + +mitk::ModelFitFunctorBase::OutputPixelArrayType +mitk::ModelFitFunctorBase::GetDerivedParameters(const ModelBase* model, + const ParametersType& parameters) const +{ + ModelBase::DerivedParameterMapType derivedParameterMap = model->GetDerivedParameters(parameters); + OutputPixelArrayType result(derivedParameterMap.size()); + + unsigned int i = 0; + + for (ModelBase::DerivedParameterMapType::const_iterator pos = derivedParameterMap.begin(); + pos != derivedParameterMap.end(); ++pos, ++i) + { + result[i] = pos->second; + } + + return result; +}; + +mitk::ModelFitFunctorBase::OutputPixelArrayType +mitk::ModelFitFunctorBase::GetEvaluationParameters(const ModelBase* model, + const ParametersType& parameters, const SignalType& sample) const +{ + m_Mutex.Lock(); + + OutputPixelArrayType result(m_CostFunctionMap.size()); + + unsigned int i = 0; + + for (CostFunctionMapType::const_iterator pos = m_CostFunctionMap.begin(); + pos != m_CostFunctionMap.end(); ++pos, ++i) + { + //break constness to configure evaluation cost functions. This operatoin is guarded be the mutex + //after costFct->GetValue() the cost function may change its state again and is irrelevant for the + //current call of GetEvaluationParameters + SVModelFitCostFunction* costFct = const_cast(pos->second.GetPointer()); + + costFct->SetModel(model); + costFct->SetSample(sample); + + result[i] = costFct->GetValue(parameters); + } + + m_Mutex.Unlock(); + + return result; +}; diff --git a/Modules/ModelFit/src/Functors/mitkModelFitInfoSignalGenerationFunctor.cpp b/Modules/ModelFit/src/Functors/mitkModelFitInfoSignalGenerationFunctor.cpp new file mode 100644 index 0000000000..606c24cabe --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkModelFitInfoSignalGenerationFunctor.cpp @@ -0,0 +1,82 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelFitInfoSignalGenerationFunctor.h" + + +mitk::IndexedValueFunctorBase::OutputPixelVectorType +mitk::ModelFitInfoSignalGenerationFunctor::Compute(const InputPixelVectorType &, const IndexType& currentIndex) const +{ + return this->Compute(currentIndex); +}; + +mitk::IndexedValueFunctorBase::OutputPixelVectorType +mitk::ModelFitInfoSignalGenerationFunctor::Compute(const IndexType& currentIndex) const + { + if (this->m_ModelParameterizer->GetDefaultTimeGrid().GetSize() == 0) + { + itkExceptionMacro("Error. Cannot compute SignalCurve. No time grid is set in parameterizer!"); + } + + ModelBase::Pointer model = this->m_ModelParameterizer->GenerateParameterizedModel(currentIndex); + + auto params = this->CompileModelParameters(currentIndex, model); + + SignalType signal = model->GetSignal(params); + + OutputPixelVectorType result; + + for (SignalType::const_iterator pos = signal.begin(); pos!= signal.end(); ++pos) + { + result.push_back(*pos); + } + + return result; + }; + +mitk::ModelBase::ParametersType +mitk::ModelFitInfoSignalGenerationFunctor::CompileModelParameters(const IndexType& currentIndex, const ModelBase * model) const +{ + auto paramMap = mitk::ExtractParameterValueMapFromModelFit(m_FitInfo, currentIndex); + return mitk::ConvertParameterMapToParameterVector(paramMap, model); +}; + +unsigned int +mitk::ModelFitInfoSignalGenerationFunctor::GetNumberOfOutputs() const + { + if (m_ModelParameterizer.IsNotNull()) + { + return m_ModelParameterizer->GetDefaultTimeGrid().GetSize(); + } + + return 0; + }; + +mitk::IndexedValueFunctorBase::GridArrayType +mitk::ModelFitInfoSignalGenerationFunctor::GetGrid() const + { + if (m_ModelParameterizer.IsNotNull()) + { + return m_ModelParameterizer->GetDefaultTimeGrid(); + } + + return GridArrayType(); + }; + +mitk::ModelFitInfoSignalGenerationFunctor::ModelFitInfoSignalGenerationFunctor() +{}; +mitk::ModelFitInfoSignalGenerationFunctor::~ModelFitInfoSignalGenerationFunctor() +{}; diff --git a/Modules/ModelFit/src/Functors/mitkNormalizedSumOfSquaredDifferencesFitCostFunction.cpp b/Modules/ModelFit/src/Functors/mitkNormalizedSumOfSquaredDifferencesFitCostFunction.cpp new file mode 100644 index 0000000000..b9d7655c0b --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkNormalizedSumOfSquaredDifferencesFitCostFunction.cpp @@ -0,0 +1,30 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#include "mitkNormalizedSumOfSquaredDifferencesFitCostFunction.h" + +mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::MeasureType mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::CalcMeasure(const ParametersType &/*parameters*/, const SignalType &signal) const +{ + MeasureType measure = 0.0; + unsigned int signalSize = signal.GetSize(); + + for(SignalType::size_type i=0; iGetTimeGrid(); + + mitk::ModelBase::ParametersSizeType numberOfParameters = Superclass::GetModel()->GetNumberOfParameters(); + + mitk::ModelBase::ParametersSizeType numberOfTimeSteps = (Superclass::GetModel()->GetTimeGrid()).GetSize(); + + + double dt = 0.0; + for(SignalType::size_type i=0; i + + +mitk::SVModelFitCostFunction::MeasureType mitk::SVModelFitCostFunction::GetValue(const ParametersType ¶meter) const +{ + MeasureType measure; + + SignalType signal = m_Model->GetSignal(parameter); + + if(signal.GetSize() != m_Sample.GetSize()) itkExceptionMacro("Signal size does not matche sample size!"); + if(signal.GetSize() == 0) itkExceptionMacro("Signal is empty!"); + + measure = CalcMeasure(parameter, signal); + + return measure; +} + +void mitk::SVModelFitCostFunction::GetDerivative (const ParametersType ¶meters, DerivativeType &derivative) const +{ + ParametersType::SizeValueType paramCount = parameters.Size(); + + derivative.SetSize(paramCount); + + for ( ParametersType::SizeValueType i = 0; i < paramCount; i++ ) + { + ParametersType newParameters = parameters; + newParameters[i] -= m_DerivativeStepLength; + + MeasureType e0 = GetValue(newParameters); + + newParameters = parameters; + newParameters[i] += m_DerivativeStepLength; + + MeasureType e1 = GetValue(newParameters); + + derivative[i] = (e1 - e0) / ( 2 * m_DerivativeStepLength ); + } +}; + +unsigned int mitk::SVModelFitCostFunction::GetNumberOfParameters() const +{ + return m_Model->GetNumberOfParameters(); +} + +void mitk::SVModelFitCostFunction::SetSample(const SignalType &sampleSet) +{ + itkDebugMacro("setting Sample to " << sampleSet); + this->m_Sample = sampleSet; + this->Modified(); +} + diff --git a/Modules/ModelFit/src/Functors/mitkSimpleBarrierConstraintChecker.cpp b/Modules/ModelFit/src/Functors/mitkSimpleBarrierConstraintChecker.cpp new file mode 100644 index 0000000000..827f2eb065 --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkSimpleBarrierConstraintChecker.cpp @@ -0,0 +1,202 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkSimpleBarrierConstraintChecker.h" + +#include + +#include "mitkExceptionMacro.h" + +mitk::SimpleBarrierConstraintChecker::PenaltyArrayType +mitk::SimpleBarrierConstraintChecker::GetPenalties(const ParametersType& parameters) const +{ + PenaltyArrayType result(m_Constraints.size()); + + PenaltyArrayType::iterator penaltyPos = result.begin(); + + for (ConstraintVectorType::const_iterator pos = m_Constraints.begin(); pos != m_Constraints.end(); + ++pos, ++penaltyPos) + { + *penaltyPos = CalcPenalty(parameters, *pos); + } + + return result; +}; + +unsigned int mitk::SimpleBarrierConstraintChecker::GetNumberOfConstraints() const +{ + return m_Constraints.size(); +}; + +mitk::SimpleBarrierConstraintChecker::PenaltyValueType +mitk::SimpleBarrierConstraintChecker::GetFailedConstraintValue() const +{ + return m_MaxConstraintPenalty; +}; + +void mitk::SimpleBarrierConstraintChecker::SetLowerBarrier(ParameterIndexType parameterID, + BarrierValueType barrier, BarrierWidthType width) +{ + Constraint c; + ParameterIndexVectorType params; + params.push_back(parameterID); + c.parameters = params; + c.barrier = barrier; + c.width = width; + c.upperBarrier = false; + + m_Constraints.push_back(c); +}; + +void mitk::SimpleBarrierConstraintChecker::SetUpperBarrier(ParameterIndexType parameterID, + BarrierValueType barrier, BarrierWidthType width) +{ + Constraint c; + ParameterIndexVectorType params; + params.push_back(parameterID); + c.parameters = params; + c.barrier = barrier; + c.width = width; + c.upperBarrier = true; + + m_Constraints.push_back(c); +}; + +void mitk::SimpleBarrierConstraintChecker::SetLowerSumBarrier(const ParameterIndexVectorType& + parameterIDs, BarrierValueType barrier, BarrierWidthType width) +{ + Constraint c; + + c.parameters = parameterIDs; + c.barrier = barrier; + c.width = width; + c.upperBarrier = false; + + m_Constraints.push_back(c); +}; + +void mitk::SimpleBarrierConstraintChecker::SetUpperSumBarrier(const ParameterIndexVectorType& + parameterIDs, BarrierValueType barrier, BarrierWidthType width) +{ + Constraint c; + + c.parameters = parameterIDs; + c.barrier = barrier; + c.width = width; + c.upperBarrier = true; + + m_Constraints.push_back(c); +}; + +mitk::SimpleBarrierConstraintChecker::Constraint& +mitk::SimpleBarrierConstraintChecker::GetConstraint(unsigned int index) +{ + if (index >= GetNumberOfConstraints()) + { + mitkThrow() << + "Error. Cannot get constraint. Invalid constraint index passed.Parameter Invalid index:" + << index; + } + + return m_Constraints[index]; +}; + +const mitk::SimpleBarrierConstraintChecker::Constraint& +mitk::SimpleBarrierConstraintChecker::GetConstraint(unsigned int index) const +{ + if (index >= GetNumberOfConstraints()) + { + mitkThrow() << + "Error. Cannot get constraint. Invalid constraint index passed.Parameter Invalid index:" + << index; + } + + return m_Constraints[index]; +}; + +void mitk::SimpleBarrierConstraintChecker::DeleteConstraint(unsigned int index) +{ + if (index >= GetNumberOfConstraints()) + { + return; + } + + m_Constraints.erase(m_Constraints.begin() + index); +}; + + +void mitk::SimpleBarrierConstraintChecker::ResetConstraints() +{ + m_Constraints.clear(); +}; + +mitk::SimpleBarrierConstraintChecker::PenaltyValueType +mitk::SimpleBarrierConstraintChecker::CalcPenalty(const ParametersType& parameters, + const Constraint& constraint) const +{ + double constrainedValue = 0; + + for (ParameterIndexVectorType::const_iterator pos = constraint.parameters.begin(); + pos != constraint.parameters.end(); ++pos) + { + if (*pos >= parameters.size()) + { + mitkThrow() << + "Error. Parameter specified by constraint is no part of the passed parameter values. Invalid parameter ID:" + << *pos; + } + + constrainedValue += parameters[*pos]; + }; + + PenaltyValueType result = 0; + + //transform into an inequality against 0. + //basic form of inequalities are constrainedValue (relation) constraint.barrier + double transformedTermValue = constraint.barrier - constrainedValue; + + if (!constraint.upperBarrier) + { + // need the form 0 <= term, but right now it would be 0 >= term, so *-1 + transformedTermValue *= -1; + } + + double barrierSize = abs((double)(constraint.width)); + + //Check if it would be the maximum penalty anyway. + if (transformedTermValue <= 0) + { + result = this->m_MaxConstraintPenalty; + } + else if (transformedTermValue > barrierSize) + { + //Check if it is outside the barrier region + //the constrained value is outside the barrier region within a legal valid range. + result = 0; + } + else + { + // the constrained value seems to violate the constraint or at least is within the + // barrier region, so compute the penalty + + //calculate the barrier function value + double barrierValue = -1 * log(transformedTermValue / barrierSize); + + result = std::min(barrierValue, this->m_MaxConstraintPenalty); + } + + return result; +}; \ No newline at end of file diff --git a/Modules/ModelFit/src/Functors/mitkSimpleFunctorBase.cpp b/Modules/ModelFit/src/Functors/mitkSimpleFunctorBase.cpp new file mode 100644 index 0000000000..62c45b3728 --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkSimpleFunctorBase.cpp @@ -0,0 +1,20 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkSimpleFunctorBase.h" + +mitk::SimpleFunctorBase::SimpleFunctorBase() = default; +mitk::SimpleFunctorBase::~SimpleFunctorBase() = default; diff --git a/Modules/ModelFit/src/Functors/mitkSimpleFunctorPolicy.cpp b/Modules/ModelFit/src/Functors/mitkSimpleFunctorPolicy.cpp new file mode 100644 index 0000000000..6bd46a9f85 --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkSimpleFunctorPolicy.cpp @@ -0,0 +1,57 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkSimpleFunctorPolicy.h" + +mitk::SimpleFunctorPolicy::SimpleFunctorPolicy() = default; +mitk::SimpleFunctorPolicy::~SimpleFunctorPolicy() = default; + +unsigned int + mitk::SimpleFunctorPolicy::GetNumberOfOutputs() const +{ + unsigned int result = 0; + + if (m_Functor.IsNotNull()) + { + result = m_Functor->GetNumberOfOutputs(); + } + + return result; +} + +void + mitk::SimpleFunctorPolicy::SetFunctor (const mitk::SimpleFunctorBase *functor) +{ + if (!functor) + { + itkGenericExceptionMacro(<< "Error. Functor is Null."); + } + + m_Functor = functor; +} + + +bool + mitk::SimpleFunctorPolicy::operator!=( const SimpleFunctorPolicy & other) const +{ + return !(*this == other); +} + +bool + mitk::SimpleFunctorPolicy::operator==( const SimpleFunctorPolicy & other ) const +{ + return (this->m_Functor == other.m_Functor); +} diff --git a/Modules/ModelFit/src/Functors/mitkSquaredDifferencesFitCostFunction.cpp b/Modules/ModelFit/src/Functors/mitkSquaredDifferencesFitCostFunction.cpp new file mode 100644 index 0000000000..e9802cabe8 --- /dev/null +++ b/Modules/ModelFit/src/Functors/mitkSquaredDifferencesFitCostFunction.cpp @@ -0,0 +1,30 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkSquaredDifferencesFitCostFunction.h" + +mitk::SquaredDifferencesFitCostFunction::MeasureType mitk::SquaredDifferencesFitCostFunction::CalcMeasure(const ParametersType &/*parameters*/, const SignalType &signal) const +{ + MeasureType measure; + measure.SetSize(signal.GetSize()); + + for(SignalType::size_type i=0; i 1) + { + result.push_back("b"); + } + if (m_NumberOfParameters > 2) + { + result.push_back("c"); + } + if (m_NumberOfParameters > 3) + { + result.push_back("d"); + } + if (m_NumberOfParameters > 4) + { + result.push_back("e"); + } + if (m_NumberOfParameters > 5) + { + result.push_back("f"); + } + if (m_NumberOfParameters > 6) + { + result.push_back("g"); + } + if (m_NumberOfParameters > 7) + { + result.push_back("h"); + } + if (m_NumberOfParameters > 8) + { + result.push_back("i"); + } + if (m_NumberOfParameters > 9) + { + result.push_back("j"); + } + + return result; +}; + +mitk::GenericParamModel::ParametersSizeType +mitk::GenericParamModel::GetNumberOfParameters() const +{ + return m_NumberOfParameters; +}; + +mitk::GenericParamModel::ModelResultType +mitk::GenericParamModel::ComputeModelfunction(const ParametersType& parameters) const +{ + unsigned int timeSteps = m_TimeGrid.GetSize(); + ModelResultType signal(timeSteps); + + std::map parameterMap; + parameterMap.insert(std::make_pair(GetXName(), 0.0)); + + auto paramNames = this->GetParameterNames(); + for (ParametersType::size_type i = 0; i < parameters.size(); ++i) + { + parameterMap.insert(std::make_pair(paramNames[i], parameters[i])); + } + + FormulaParser formulaParser(¶meterMap); + + TimeGridType::const_iterator timeGridEnd = m_TimeGrid.end(); + ModelResultType::iterator signalPos = signal.begin(); + + for (TimeGridType::const_iterator gridPos = m_TimeGrid.begin(); gridPos != timeGridEnd; + ++gridPos, ++signalPos) + { + parameterMap[GetXName()] = *gridPos; + *signalPos = formulaParser.parse(m_FunctionString); + } + + return signal; +}; + +mitk::GenericParamModel::ParameterNamesType mitk::GenericParamModel::GetStaticParameterNames() +const +{ + ParameterNamesType result; + result.push_back(NAME_STATIC_PARAMETER_number); + return result; +} + +mitk::GenericParamModel::ParametersSizeType +mitk::GenericParamModel::GetNumberOfStaticParameters() const +{ + return 1; +} + +void mitk::GenericParamModel::SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values) +{ + if (name == NAME_STATIC_PARAMETER_number) + { + SetNumberOfParameters(values[0]); + } +}; + +mitk::GenericParamModel::StaticParameterValuesType +mitk::GenericParamModel::GetStaticParameterValue( + const ParameterNameType& name) const +{ + StaticParameterValuesType result; + + if (name == NAME_STATIC_PARAMETER_number) + { + result.push_back(m_NumberOfParameters); + } + + return result; +}; + +itk::LightObject::Pointer mitk::GenericParamModel::InternalClone() const +{ + GenericParamModel::Pointer newClone = GenericParamModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + newClone->SetNumberOfParameters(this->m_NumberOfParameters); + + return newClone.GetPointer(); +}; \ No newline at end of file diff --git a/Modules/ModelFit/src/Models/mitkGenericParamModelFactory.cpp b/Modules/ModelFit/src/Models/mitkGenericParamModelFactory.cpp new file mode 100644 index 0000000000..53be415d6f --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkGenericParamModelFactory.cpp @@ -0,0 +1,49 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkGenericParamModelFactory.h" +#include "mitkGenericParamModelParameterizer.h" + +mitk::GenericParamModelFactory::GenericParamModelFactory() += default; + +mitk::GenericParamModelFactory::~GenericParamModelFactory() += default; + +mitk::ModelParameterizerBase::ParametersType +mitk::GenericParamModelFactory::GetDefaultInitialParameterization() const +{ + return GenericParamModelParameterizer::New()->GetDefaultInitialParameterization(); +}; + + +mitk::ModelParameterizerBase::Pointer +mitk::GenericParamModelFactory::DoCreateParameterizer( + const mitk::modelFit::ModelFitInfo* fit) const +{ + mitk::ModelParameterizerBase::Pointer result; + + GenericParamModelParameterizer::Pointer modelParameterizer = + GenericParamModelParameterizer::New(); + + auto paramCount = fit->staticParamMap.Get( + GenericParamModel::NAME_STATIC_PARAMETER_number); + modelParameterizer->SetNumberOfParameters(paramCount[0]); + + result = modelParameterizer.GetPointer(); + + return result; +}; diff --git a/Modules/ModelFit/src/Models/mitkGenericParamModelParameterizer.cpp b/Modules/ModelFit/src/Models/mitkGenericParamModelParameterizer.cpp new file mode 100644 index 0000000000..60eb963445 --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkGenericParamModelParameterizer.cpp @@ -0,0 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkGenericParamModelParameterizer.h" + +mitk::ModelBase::FunctionStringType mitk::GenericParamModelParameterizer::GetFunctionString() const +{ + return m_FunctionString; +}; + +mitk::GenericParamModelParameterizer::ModelBasePointer + mitk::GenericParamModelParameterizer::GenerateParameterizedModel(const IndexType& currentPosition) const +{ + ModelPointer newModel = dynamic_cast(Superclass::GenerateParameterizedModel( + currentPosition).GetPointer()); + newModel->SetFunctionString(m_FunctionString); + return newModel.GetPointer(); +}; + +mitk::GenericParamModelParameterizer::StaticParameterMapType + mitk::GenericParamModelParameterizer::GetGlobalStaticParameters() const +{ + StaticParameterMapType result; + StaticParameterValuesType values; + values.push_back(m_NumberOfParameters); + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_number, values)); + return result; +}; + +mitk::GenericParamModelParameterizer::ParametersType + mitk::GenericParamModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(m_NumberOfParameters); + initialParameters.Fill(1.0); + return initialParameters; +}; + +mitk::GenericParamModelParameterizer::GenericParamModelParameterizer():m_NumberOfParameters(1) +{}; + +mitk::GenericParamModelParameterizer::~GenericParamModelParameterizer() += default; diff --git a/Modules/ModelFit/src/Models/mitkImageBasedParameterizationDelegate.cpp b/Modules/ModelFit/src/Models/mitkImageBasedParameterizationDelegate.cpp new file mode 100644 index 0000000000..2362f72a07 --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkImageBasedParameterizationDelegate.cpp @@ -0,0 +1,51 @@ +#include "mitkImageBasedParameterizationDelegate.h" + +#include "mitkImagePixelReadAccessor.h" +#include "mitkPixelTypeMultiplex.h" + +mitk::ImageBasedParameterizationDelegate::ImageBasedParameterizationDelegate() +{ +} + +mitk::ImageBasedParameterizationDelegate::~ImageBasedParameterizationDelegate() +{ +} + +mitk::ImageBasedParameterizationDelegate::ParametersType mitk::ImageBasedParameterizationDelegate::GetInitialParameterization() const +{ + itk::Index<3> index = {{0, 0, 0}}; + return GetInitialParameterization(index); +} + +template +static void AccessPixel(mitk::PixelType /*ptype*/, mitk::Image::ConstPointer im, const mitk::ImageBasedParameterizationDelegate::IndexType ¤tPosition, mitk::ImageBasedParameterizationDelegate::ParametersType::ValueType &val) +{ + mitk::ImagePixelReadAccessor access(im); + val = access.GetPixelByIndex(currentPosition); +} + +mitk::ImageBasedParameterizationDelegate::ParametersType mitk::ImageBasedParameterizationDelegate::GetInitialParameterization(const IndexType ¤tPosition) const +{ + ParametersType initialParameters = this->m_Parameterization; + + for (const auto& pos : this->m_ParameterImageMap) + { + ParametersType::ValueType value; + mitkPixelTypeMultiplex3(AccessPixel, pos.second->GetChannelDescriptor().GetPixelType(), pos.second, currentPosition, value); + + initialParameters[pos.first] = value; + } + + return initialParameters; +} + +void +mitk::ImageBasedParameterizationDelegate::AddInitialParameterImage(const mitk::Image* image, ParametersType::size_type paramIndex) +{ + if (paramIndex >= this->m_Parameterization.Size()) + { + mitkThrow() << "Initial value image is set for invalid parameter index. Number of parameter: " << this->m_Parameterization.Size() << "; invalid index: " << paramIndex; + } + + m_ParameterImageMap.insert(std::make_pair(paramIndex, image)); +}; diff --git a/Modules/ModelFit/src/Models/mitkInitialParameterizationDelegateBase.cpp b/Modules/ModelFit/src/Models/mitkInitialParameterizationDelegateBase.cpp new file mode 100644 index 0000000000..08b4b8e96d --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkInitialParameterizationDelegateBase.cpp @@ -0,0 +1,26 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkInitialParameterizationDelegateBase.h" + + +mitk::InitialParameterizationDelegateBase::InitialParameterizationDelegateBase() +{ +}; + +mitk::InitialParameterizationDelegateBase::~InitialParameterizationDelegateBase() +{ +}; diff --git a/Modules/ModelFit/src/Models/mitkLinearModel.cpp b/Modules/ModelFit/src/Models/mitkLinearModel.cpp new file mode 100644 index 0000000000..1389eba98a --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkLinearModel.cpp @@ -0,0 +1,129 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkLinearModel.h" + +std::string mitk::LinearModel::GetModelDisplayName() const +{ + return "Linear Model"; +}; + +std::string mitk::LinearModel::GetModelType() const +{ + return "Generic"; +}; + +mitk::LinearModel::FunctionStringType mitk::LinearModel::GetFunctionString() const +{ + return "slope*x+offset"; +}; + +std::string mitk::LinearModel::GetXName() const +{ + return "x"; +}; + +mitk::LinearModel::ParameterNamesType +mitk::LinearModel::GetParameterNames() const +{ + ParameterNamesType result; + result.push_back("slope"); + result.push_back("offset"); + return result; +}; + +mitk::LinearModel::ParametersSizeType +mitk::LinearModel::GetNumberOfParameters() const +{ + return 2; +}; + +mitk::LinearModel::ParameterNamesType +mitk::LinearModel::GetDerivedParameterNames() const +{ + ParameterNamesType result; + result.push_back("x-intercept"); + return result; +}; + +mitk::LinearModel::ParametersSizeType +mitk::LinearModel::GetNumberOfDerivedParameters() const +{ + return 1; +}; + +mitk::LinearModel::ModelResultType +mitk::LinearModel::ComputeModelfunction(const ParametersType& parameters) const +{ + ModelResultType signal(m_TimeGrid.GetSize()); + + TimeGridType::const_iterator timeGridEnd = m_TimeGrid.end(); + ModelResultType::iterator signalPos = signal.begin(); + + for (TimeGridType::const_iterator gridPos = m_TimeGrid.begin(); gridPos != timeGridEnd; + ++gridPos, ++signalPos) + { + *signalPos = parameters[0] * (*gridPos) + parameters[1]; + } + + return signal; +}; + +mitk::LinearModel::ParameterNamesType mitk::LinearModel::GetStaticParameterNames() const +{ + ParameterNamesType result; + + return result; +} + +mitk::LinearModel::ParametersSizeType mitk::LinearModel::GetNumberOfStaticParameters() const +{ + return 0; +} + +void mitk::LinearModel::SetStaticParameter(const ParameterNameType& /*name*/, + const StaticParameterValuesType& /*values*/) +{ + //do nothing +}; + +mitk::LinearModel::StaticParameterValuesType mitk::LinearModel::GetStaticParameterValue( + const ParameterNameType& /*name*/) const +{ + StaticParameterValuesType result; + + //do nothing + + return result; +}; + +mitk::ModelBase::DerivedParameterMapType mitk::LinearModel::ComputeDerivedParameters( + const mitk::ModelBase::ParametersType& parameters) const +{ + DerivedParameterMapType result; + double intercept = -1 * parameters[1] / parameters[0]; + result.insert(std::make_pair("x-intercept", intercept)); + return result; +}; + +itk::LightObject::Pointer mitk::LinearModel::InternalClone() const +{ + LinearModel::Pointer newClone = LinearModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +}; diff --git a/Modules/ModelFit/src/Models/mitkLinearModelFactory.cpp b/Modules/ModelFit/src/Models/mitkLinearModelFactory.cpp new file mode 100644 index 0000000000..5764aeb0cd --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkLinearModelFactory.cpp @@ -0,0 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkLinearModelFactory.h" +#include "mitkConcreteModelParameterizerBase.h" + +mitk::LinearModelFactory::LinearModelFactory() +{ +}; + +mitk::LinearModelFactory::~LinearModelFactory() +{ +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::LinearModelFactory::GetDefaultInitialParameterization() const +{ + return ConcreteModelParameterizerBase::New()->GetDefaultInitialParameterization(); +}; + +mitk::ModelParameterizerBase::Pointer mitk::LinearModelFactory::DoCreateParameterizer( + const modelFit::ModelFitInfo* /*fit*/) const +{ + return ConcreteModelParameterizerBase::New().GetPointer(); +}; diff --git a/Modules/ModelFit/src/Models/mitkModelBase.cpp b/Modules/ModelFit/src/Models/mitkModelBase.cpp new file mode 100644 index 0000000000..f3c6b67400 --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkModelBase.cpp @@ -0,0 +1,270 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelBase.h" +#include "itkMacro.h" + +#include + +mitk::ModelBase::ParamterScaleMapType +mitk::ModelBase::GetParameterScales() const +{ + ParamterScaleMapType result; + ParameterNamesType names = GetParameterNames(); + + for (ParameterNamesType::iterator pos = names.begin(); pos != names.end(); ++pos) + { + result.insert(std::make_pair(*pos, 1.0)); + } + + return result; +}; + +mitk::ModelBase::ParamterUnitMapType +mitk::ModelBase::GetParameterUnits() const +{ + ParamterUnitMapType result; + ParameterNamesType names = GetParameterNames(); + + for (ParameterNamesType::iterator pos = names.begin(); pos != names.end(); ++pos) + { + result.insert(std::make_pair(*pos, "")); + } + + return result; +}; + +mitk::ModelBase::DerivedParamterScaleMapType +mitk::ModelBase::GetDerivedParameterScales() const +{ + DerivedParamterScaleMapType result; + DerivedParameterNamesType names = this->GetDerivedParameterNames(); + + for (DerivedParameterNamesType::iterator pos = names.begin(); pos != names.end(); ++pos) + { + result.insert(std::make_pair(*pos, 1.0)); + } + + return result; +}; + +mitk::ModelBase::DerivedParamterUnitMapType +mitk::ModelBase::GetDerivedParameterUnits() const +{ + DerivedParamterUnitMapType result; + DerivedParameterNamesType names = this->GetDerivedParameterNames(); + + for (DerivedParameterNamesType::iterator pos = names.begin(); pos != names.end(); ++pos) + { + result.insert(std::make_pair(*pos, "")); + } + + return result; +}; + +std::string +mitk::ModelBase::GetModelDisplayName() const +{ + return this->GetClassID(); +}; + +std::string mitk::ModelBase::GetModelType() const +{ + return "Unkown"; +}; + +mitk::ModelBase::FunctionStringType mitk::ModelBase::GetFunctionString() const +{ + return ""; +}; + +mitk::ModelBase::ModellClassIDType mitk::ModelBase::GetClassID() const +{ + return this->GetNameOfClass(); +}; + +std::string mitk::ModelBase::GetXName() const +{ + return ""; +}; + +std::string mitk::ModelBase::GetXAxisName() const +{ + return ""; +}; + +std::string mitk::ModelBase::GetXAxisUnit() const +{ + return ""; +}; + +std::string mitk::ModelBase::GetYAxisName() const +{ + return ""; +}; + +std::string mitk::ModelBase::GetYAxisUnit() const +{ + return ""; +} + +mitk::ModelBase::ModelBase() +{ +} + +mitk::ModelBase::~ModelBase() +{ +} + +mitk::ModelBase::ModelResultType mitk::ModelBase::GetSignal(const ParametersType& parameters) const +{ + if (parameters.size() != this->GetNumberOfParameters()) + { + itkExceptionMacro("Passed parameter set has wrong size for model. Cannot evaluate model. Required size: " + << this->GetNumberOfParameters() << "; passed parameters: " << parameters); + } + + std::string error; + + if (!ValidateModel(error)) + { + itkExceptionMacro("Cannot evaluate model and return signal. Model is in an invalid state. Validation error: " + << error); + } + + ModelResultType signal = ComputeModelfunction(parameters); + + return signal; +} + +bool mitk::ModelBase::ValidateModel(std::string& /*error*/) const +{ + return true; +}; + + +void mitk::ModelBase::SetTimeGrid(const TimeGridType& grid) +{ + itkDebugMacro("setting TimeGrid to " << grid); + + if (grid.GetSize() == 0) + { + itkExceptionMacro("Time Grid Vector is empty! Set valid time grid"); + } + + if (this->m_TimeGrid != grid) + { + this->m_TimeGrid = grid; + this->Modified(); + } +} + +void mitk::ModelBase::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "Time grid: " << m_TimeGrid; +}; + +void mitk::ModelBase::SetStaticParameters(const StaticParameterMapType& parameters, + bool allParameters) +{ + ParameterNamesType names = this->GetStaticParameterNames(); + + if ((parameters.size() != names.size()) && allParameters) + { + itkExceptionMacro("Cannot set static parameter of model. Passed parameters does not define all parameters correctly. Required size:" + << names.size() << "; passed size: " << parameters.size()); + } + + for (StaticParameterMapType::const_iterator pos = parameters.begin(); pos != parameters.end(); + ++pos) + { + ParameterNamesType::iterator finding = std::find(names.begin(), names.end(), pos->first); + + if (finding == names.end()) + { + itkExceptionMacro("Cannot set static parameter of model. Passed parameter name is not in the list of valid names. Passed name: " + << pos->first); + } + } + + //Setting is done in an other loop to ensure that the state of the model only changes if all values are valid. + for (StaticParameterMapType::const_iterator pos = parameters.begin(); pos != parameters.end(); + ++pos) + { + this->SetStaticParameter(pos->first, pos->second); + } + +}; + +mitk::ModelBase::StaticParameterMapType mitk::ModelBase::GetStaticParameters() const +{ + StaticParameterMapType result; + ParameterNamesType names = this->GetStaticParameterNames(); + + for (ParameterNamesType::const_iterator pos = names.begin(); pos != names.end(); ++pos) + { + StaticParameterValuesType values = this->GetStaticParameterValue(*pos); + result.insert(std::make_pair(*pos, values)); + } + + return result; +}; + +mitk::ModelBase::DerivedParameterNamesType mitk::ModelBase::GetDerivedParameterNames() const +{ + ParameterNamesType emptyResult; + return emptyResult; +}; + +mitk::ModelBase::ParamterUnitMapType +mitk::ModelBase::GetStaticParameterUnits() const +{ + ParamterUnitMapType result; + ParameterNamesType names = GetStaticParameterNames(); + + for (ParameterNamesType::iterator pos = names.begin(); pos != names.end(); ++pos) + { + result.insert(std::make_pair(*pos, "")); + } + + return result; +}; + +mitk::ModelBase::DerivedParametersSizeType mitk::ModelBase::GetNumberOfDerivedParameters() const +{ + return 0; +}; + +mitk::ModelBase::DerivedParameterMapType mitk::ModelBase::GetDerivedParameters( + const mitk::ModelBase::ParametersType& parameters) const +{ + if (parameters.size() != this->GetNumberOfParameters()) + { + itkExceptionMacro("Cannot compute derived parametes. Passed parameters does not define all parameters correctly. Required size:" + << this->GetNumberOfParameters() << "; passed size: " << parameters.size()); + } + + return ComputeDerivedParameters(parameters); +}; + +mitk::ModelBase::DerivedParameterMapType mitk::ModelBase::ComputeDerivedParameters( + const mitk::ModelBase::ParametersType& /*parameters*/) const +{ + DerivedParameterMapType emptyResult; + return emptyResult; +}; diff --git a/Modules/ModelFit/src/Models/mitkModelFactoryBase.cpp b/Modules/ModelFit/src/Models/mitkModelFactoryBase.cpp new file mode 100644 index 0000000000..c62751f9a5 --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkModelFactoryBase.cpp @@ -0,0 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelFactoryBase.h" + +mitk::ModelParameterizerBase::Pointer mitk::ModelFactoryBase::CreateParameterizer( + const mitk::modelFit::ModelFitInfo* fit) const +{ + if (!fit) + { + mitkThrow() << "Cannot generate parameterizer. Passed model fit is Null."; + } + + return DoCreateParameterizer(fit); +}; + +mitk::ModelFactoryBase::ModelFactoryBase() +{ +}; + +mitk::ModelFactoryBase::~ModelFactoryBase() +{ +}; \ No newline at end of file diff --git a/Modules/ModelFit/src/Models/mitkModelParameterizerBase.cpp b/Modules/ModelFit/src/Models/mitkModelParameterizerBase.cpp new file mode 100644 index 0000000000..801a4b2c1a --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkModelParameterizerBase.cpp @@ -0,0 +1,57 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkModelParameterizerBase.h" + + +mitk::ModelParameterizerBase::ModelParameterizerBase() +{ + m_DefaultTimeGrid.SetSize(1); + m_DefaultTimeGrid[0] = 0.0; +}; + +mitk::ModelParameterizerBase::~ModelParameterizerBase() +{ +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::ModelParameterizerBase::GetInitialParameterization() const +{ + if (m_InitialDelegate.IsNotNull()) + { + return m_InitialDelegate->GetInitialParameterization(); + } + + return this->GetDefaultInitialParameterization(); +} + +mitk::ModelParameterizerBase::ParametersType +mitk::ModelParameterizerBase::GetInitialParameterization(const IndexType& currentPosition) const +{ + if (m_InitialDelegate.IsNotNull()) + { + return m_InitialDelegate->GetInitialParameterization(currentPosition); + } + + return this->GetDefaultInitialParameterization(); +} + +void +mitk::ModelParameterizerBase:: +SetInitialParameterizationDelegate(const InitialParameterizationDelegateBase* delegate) +{ + this->m_InitialDelegate = delegate; +}; \ No newline at end of file diff --git a/Modules/ModelFit/src/Models/mitkT2DecayModel.cpp b/Modules/ModelFit/src/Models/mitkT2DecayModel.cpp new file mode 100644 index 0000000000..8de5c3fa85 --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkT2DecayModel.cpp @@ -0,0 +1,104 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkT2DecayModel.h" + +std::string mitk::T2DecayModel::GetModelDisplayName() const +{ + return "T2 Decay Model"; +}; + +std::string mitk::T2DecayModel::GetModelType() const +{ + return "MRSignal"; +}; + +mitk::T2DecayModel::FunctionStringType mitk::T2DecayModel::GetFunctionString() const +{ + return "M0 * exp(-t/T2)"; +}; + +std::string mitk::T2DecayModel::GetXName() const +{ + return "t"; +}; + +mitk::T2DecayModel::ParameterNamesType +mitk::T2DecayModel::GetParameterNames() const +{ + ParameterNamesType result; + result.push_back("M0"); + result.push_back("T2"); + return result; +}; + +mitk::T2DecayModel::ParametersSizeType +mitk::T2DecayModel::GetNumberOfParameters() const +{ + return 2; +}; + +mitk::T2DecayModel::ModelResultType +mitk::T2DecayModel::ComputeModelfunction(const ParametersType& parameters) const +{ + ModelResultType signal(m_TimeGrid.GetSize()); + + ModelResultType::iterator signalPos = signal.begin(); + + for (const auto& gridPos : m_TimeGrid) + { + *signalPos = parameters[0] * exp(-1.0 * gridPos/ parameters[1]); + } + + return signal; +}; + +mitk::T2DecayModel::ParameterNamesType mitk::T2DecayModel::GetStaticParameterNames() const +{ + ParameterNamesType result; + + return result; +} + +mitk::T2DecayModel::ParametersSizeType mitk::T2DecayModel::GetNumberOfStaticParameters() const +{ + return 0; +} + +void mitk::T2DecayModel::SetStaticParameter(const ParameterNameType& /*name*/, + const StaticParameterValuesType& /*values*/) +{ + //do nothing +}; + +mitk::T2DecayModel::StaticParameterValuesType mitk::T2DecayModel::GetStaticParameterValue( + const ParameterNameType& /*name*/) const +{ + StaticParameterValuesType result; + + //do nothing + + return result; +}; + +itk::LightObject::Pointer mitk::T2DecayModel::InternalClone() const +{ + T2DecayModel::Pointer newClone = T2DecayModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +}; diff --git a/Modules/ModelFit/src/Models/mitkT2DecayModelFactory.cpp b/Modules/ModelFit/src/Models/mitkT2DecayModelFactory.cpp new file mode 100644 index 0000000000..6d3f8c039a --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkT2DecayModelFactory.cpp @@ -0,0 +1,49 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkT2DecayModelFactory.h" +#include "mitkT2DecayModelParameterizer.h" +#include "mitkSimpleBarrierConstraintChecker.h" + +mitk::T2DecayModelFactory::T2DecayModelFactory() +{ +}; + +mitk::T2DecayModelFactory::~T2DecayModelFactory() +{ +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::T2DecayModelFactory::GetDefaultInitialParameterization() const +{ + return T2DecayModelParameterizer::New()->GetDefaultInitialParameterization(); +}; + +mitk::ConstraintCheckerBase::Pointer mitk::T2DecayModelFactory::CreateDefaultConstraints() const +{ + mitk::SimpleBarrierConstraintChecker::Pointer constraints = SimpleBarrierConstraintChecker::New(); + + constraints->SetLowerBarrier(0, 0, 0); + constraints->SetLowerBarrier(1, 0, 0); + + return constraints.GetPointer(); +}; + +mitk::ModelParameterizerBase::Pointer mitk::T2DecayModelFactory::DoCreateParameterizer( + const modelFit::ModelFitInfo* /*fit*/) const +{ + return T2DecayModelParameterizer::New().GetPointer(); +}; diff --git a/Modules/ModelFit/src/Models/mitkT2DecayModelParameterizer.cpp b/Modules/ModelFit/src/Models/mitkT2DecayModelParameterizer.cpp new file mode 100644 index 0000000000..c46c43d19d --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkT2DecayModelParameterizer.cpp @@ -0,0 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkT2DecayModelParameterizer.h" + +mitk::T2DecayModelParameterizer::ParametersType +mitk::T2DecayModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(2); + initialParameters[0] = 10; //M0 + initialParameters[1] = 1000; //T2 + + return initialParameters; +}; + +mitk::T2DecayModelParameterizer::T2DecayModelParameterizer() +{ +}; + +mitk::T2DecayModelParameterizer::~T2DecayModelParameterizer() +{ +}; diff --git a/Modules/ModelFit/src/Models/mitkValueBasedParameterizationDelegate.cpp b/Modules/ModelFit/src/Models/mitkValueBasedParameterizationDelegate.cpp new file mode 100644 index 0000000000..ccda4d5b92 --- /dev/null +++ b/Modules/ModelFit/src/Models/mitkValueBasedParameterizationDelegate.cpp @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkValueBasedParameterizationDelegate.h" + + +mitk::ValueBasedParameterizationDelegate::ValueBasedParameterizationDelegate() +{ +}; + +mitk::ValueBasedParameterizationDelegate::~ValueBasedParameterizationDelegate() +{ +}; + +void +mitk::ValueBasedParameterizationDelegate::SetInitialParameterization(ParametersType params) +{ + this->m_Parameterization = params; +}; + +mitk::ValueBasedParameterizationDelegate::ParametersType +mitk::ValueBasedParameterizationDelegate::GetInitialParameterization() const +{ + return this->m_Parameterization; +}; + +mitk::ValueBasedParameterizationDelegate::ParametersType +mitk::ValueBasedParameterizationDelegate::GetInitialParameterization(const IndexType& + /*currentPosition*/) const +{ + return this->m_Parameterization; +}; diff --git a/Modules/ModelFit/src/TestingHelper/mitkTestArtifactGenerator.cpp b/Modules/ModelFit/src/TestingHelper/mitkTestArtifactGenerator.cpp new file mode 100644 index 0000000000..76a29d73b6 --- /dev/null +++ b/Modules/ModelFit/src/TestingHelper/mitkTestArtifactGenerator.cpp @@ -0,0 +1,257 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestArtifactGenerator.h" +#include "mitkArbitraryTimeGeometry.h" +#include "mitkImageCast.h" + +namespace mitk +{ + typedef itk::Image FrameITKImageType; + typedef itk::Image DynamicITKImageType; + typedef itk::Image MaskITKImageType; + + TestImageType::Pointer GenerateTestImage(int factor) + { + TestImageType::Pointer image = TestImageType::New(); + + TestImageType::IndexType start; + start[0] = 0; // first index on X + start[1] = 0; // first index on Y + + TestImageType::SizeType size; + size[0] = 3; // size along X + size[1] = 3; // size along Y + + TestImageType::RegionType region; + region.SetSize(size); + region.SetIndex(start); + + image->SetRegions(region); + image->Allocate(); + + itk::ImageRegionIterator it = itk::ImageRegionIterator(image, + image->GetLargestPossibleRegion()); + + int count = 1; + + while (!it.IsAtEnd()) + { + it.Set(count * factor); + ++it; + ++count; + } + + return image; + } + + TestMaskType::Pointer GenerateTestMask() + { + TestMaskType::Pointer image = TestMaskType::New(); + + TestMaskType::IndexType start; + start[0] = 0; // first index on X + start[1] = 0; // first index on Y + + TestMaskType::SizeType size; + size[0] = 3; // size along X + size[1] = 3; // size along Y + + TestMaskType::RegionType region; + region.SetSize(size); + region.SetIndex(start); + + image->SetRegions(region); + image->Allocate(); + + itk::ImageRegionIterator it = itk::ImageRegionIterator(image, + image->GetLargestPossibleRegion()); + + int count = 1; + + while (!it.IsAtEnd()) + { + if (count > 1 && count < 5) + { + it.Set(1); + } + else + { + it.Set(0); + } + + ++it; + ++count; + } + + return image; + } + + Image::Pointer GenerateTestFrame(double timePoint) + { + FrameITKImageType::Pointer image = FrameITKImageType::New(); + + FrameITKImageType::IndexType start; + start[0] = 0; // first index on X + start[1] = 0; // first index on Y + start[2] = 0; // first index on Z + + FrameITKImageType::SizeType size; + size[0] = 3; // size along X + size[1] = 3; // size along Y + size[2] = 3; // size along Z + + FrameITKImageType::RegionType region; + region.SetSize(size); + region.SetIndex(start); + + image->SetRegions(region); + image->Allocate(); + + itk::ImageRegionIterator it = itk::ImageRegionIterator(image, + image->GetLargestPossibleRegion()); + + int count = 0; + + while (!it.IsAtEnd()) + { + double slope = count % (size[0] * size[1]); + double offset = itk::Math::Floor(count / (size[0] * size[1])) * 10; + + it.Set(slope * timePoint + offset); + ++it; + ++count; + } + + mitk::Image::Pointer mitkImage = mitk::Image::New(); + mitkImage->InitializeByItk(image.GetPointer()); + mitkImage->SetVolume(image->GetBufferPointer()); + + return mitkImage; + } + + Image::Pointer GenerateTestMaskMITK() + { + MaskITKImageType::Pointer image = MaskITKImageType::New(); + + MaskITKImageType::IndexType start; + start[0] = 0; // first index on X + start[1] = 0; // first index on Y + start[2] = 0; // first index on Z + + MaskITKImageType::SizeType size; + size[0] = 3; // size along X + size[1] = 3; // size along Y + size[2] = 3; // size along Z + + MaskITKImageType::RegionType region; + region.SetSize(size); + region.SetIndex(start); + + image->SetRegions(region); + image->Allocate(); + + itk::ImageRegionIterator it = itk::ImageRegionIterator(image, + image->GetLargestPossibleRegion()); + + int count = 0; + + while (!it.IsAtEnd()) + { + if (count < 14) + { + it.Set(1); + } + else + { + it.Set(0); + } + + ++it; + ++count; + } + + mitk::Image::Pointer mitkImage = mitk::Image::New(); + mitkImage->InitializeByItk(image.GetPointer()); + mitkImage->SetVolume(image->GetBufferPointer()); + + return mitkImage; + } + + + Image::Pointer GenerateDynamicTestImageMITK() + { + + mitk::Image::Pointer tempImage = GenerateTestFrame(1); + mitk::Image::Pointer dynamicImage = mitk::Image::New(); + + DynamicITKImageType::Pointer dynamicITKImage = DynamicITKImageType::New(); + DynamicITKImageType::RegionType dynamicITKRegion; + DynamicITKImageType::PointType dynamicITKOrigin; + DynamicITKImageType::IndexType dynamicITKIndex; + DynamicITKImageType::SpacingType dynamicITKSpacing; + + dynamicITKSpacing[0] = tempImage->GetGeometry()->GetSpacing()[0]; + dynamicITKSpacing[1] = tempImage->GetGeometry()->GetSpacing()[1]; + dynamicITKSpacing[2] = tempImage->GetGeometry()->GetSpacing()[2]; + dynamicITKSpacing[3] = 5.0; + + dynamicITKIndex[0] = 0; // The first pixel of the REGION + dynamicITKIndex[1] = 0; + dynamicITKIndex[2] = 0; + dynamicITKIndex[3] = 0; + + dynamicITKRegion.SetSize(0, tempImage->GetDimension(0)); + dynamicITKRegion.SetSize(1, tempImage->GetDimension(1)); + dynamicITKRegion.SetSize(2, tempImage->GetDimension(2)); + dynamicITKRegion.SetSize(3, 10); + + dynamicITKRegion.SetIndex(dynamicITKIndex); + + dynamicITKOrigin[0] = tempImage->GetGeometry()->GetOrigin()[0]; + dynamicITKOrigin[1] = tempImage->GetGeometry()->GetOrigin()[1]; + dynamicITKOrigin[2] = tempImage->GetGeometry()->GetOrigin()[2]; + + dynamicITKImage->SetOrigin(dynamicITKOrigin); + dynamicITKImage->SetSpacing(dynamicITKSpacing); + dynamicITKImage->SetRegions(dynamicITKRegion); + dynamicITKImage->Allocate(); + dynamicITKImage->FillBuffer(0); //not sure if this is necessary + + // Convert + mitk::CastToMitkImage(dynamicITKImage, dynamicImage); + + ArbitraryTimeGeometry::Pointer timeGeometry = ArbitraryTimeGeometry::New(); + timeGeometry->ClearAllGeometries(); + + + for (int i = 0; i < 10; ++i) + { + mitk::Image::Pointer frameImage = GenerateTestFrame(1 + (dynamicITKSpacing[3] * i)); + mitk::ImageReadAccessor accessor(frameImage); + dynamicImage->SetVolume(accessor.GetData(), i); + + timeGeometry->AppendNewTimeStepClone(frameImage->GetGeometry(), 1 + (dynamicITKSpacing[3] * i), + 1 + (dynamicITKSpacing[3]*(i+1))); + } + + dynamicImage->SetTimeGeometry(timeGeometry); + + return dynamicImage; + } + +} + diff --git a/Modules/ModelFit/src/TestingHelper/mitkTestModel.cpp b/Modules/ModelFit/src/TestingHelper/mitkTestModel.cpp new file mode 100644 index 0000000000..46d3953b46 --- /dev/null +++ b/Modules/ModelFit/src/TestingHelper/mitkTestModel.cpp @@ -0,0 +1,177 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestModel.h" + +mitk::TestModel::ParamterScaleMapType +mitk::TestModel::GetParameterScales() const +{ + ParamterScaleMapType result; + ParameterNamesType names = GetParameterNames(); + + for (ParameterNamesType::iterator pos = names.begin(); pos != names.end(); ++pos) + { + result.insert(std::make_pair(*pos, 2.0)); + } + + return result; +}; + +mitk::TestModel::ParamterUnitMapType +mitk::TestModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + ParameterNamesType names = GetParameterNames(); + + for (ParameterNamesType::iterator pos = names.begin(); pos != names.end(); ++pos) + { + result.insert(std::make_pair(*pos, "ParamUnit")); + } + + return result; +}; + +std::string mitk::TestModel::GetModelDisplayName() const +{ + return "Test Model 1"; +}; + +std::string mitk::TestModel::GetModelType() const +{ + return "TestModels"; +}; + +mitk::TestModel::FunctionStringType mitk::TestModel::GetFunctionString() const +{ + return "slope*X+offset"; +}; + +std::string mitk::TestModel::GetXName() const +{ + return "X"; +}; + +std::string mitk::TestModel::GetXAxisName() const +{ + return "xAxis"; +}; + +std::string mitk::TestModel::GetXAxisUnit() const +{ + return "mm"; +}; + +std::string mitk::TestModel::GetYAxisName() const +{ + return "yAxis"; +}; + +std::string mitk::TestModel::GetYAxisUnit() const +{ + return "s"; +} + +mitk::TestModel::ParameterNamesType +mitk::TestModel::GetParameterNames() const +{ + ParameterNamesType result; + result.push_back("slope"); + result.push_back("offset"); + return result; +}; + +mitk::TestModel::ParametersSizeType +mitk::TestModel::GetNumberOfParameters() const +{ + return 2; +}; + +mitk::TestModel::ParameterNamesType +mitk::TestModel::GetDerivedParameterNames() const +{ + ParameterNamesType result; + result.push_back("x-intercept"); + return result; +}; + +mitk::TestModel::ParametersSizeType +mitk::TestModel::GetNumberOfDerivedParameters() const +{ + return 1; +}; + +mitk::TestModel::ModelResultType +mitk::TestModel::ComputeModelfunction(const ParametersType& parameters) const +{ + ModelResultType signal(m_TimeGrid.GetSize()); + + TimeGridType::const_iterator timeGridEnd = m_TimeGrid.end(); + ModelResultType::iterator signalPos = signal.begin(); + + for (TimeGridType::const_iterator gridPos = m_TimeGrid.begin(); gridPos != timeGridEnd; + ++gridPos, ++signalPos) + { + *signalPos = parameters[0] * (*gridPos) + parameters[1]; + } + + return signal; +}; + +mitk::TestModel::ParameterNamesType mitk::TestModel::GetStaticParameterNames() const +{ + ParameterNamesType result; + + return result; +} + +mitk::TestModel::ParametersSizeType mitk::TestModel::GetNumberOfStaticParameters() const +{ + return 0; +} + +void mitk::TestModel::SetStaticParameter(const ParameterNameType& /*name*/, + const StaticParameterValuesType& /*values*/) +{ + //do nothing +}; + +mitk::TestModel::StaticParameterValuesType mitk::TestModel::GetStaticParameterValue( + const ParameterNameType& /*name*/) const +{ + StaticParameterValuesType result; + + //do nothing + + return result; +}; + +mitk::ModelBase::DerivedParameterMapType mitk::TestModel::ComputeDerivedParameters( + const mitk::ModelBase::ParametersType& parameters) const +{ + DerivedParameterMapType result; + double intercept = -1 * parameters[1] / parameters[0]; + result.insert(std::make_pair("x-intercept", intercept)); + return result; +}; + +itk::LightObject::Pointer mitk::TestModel::InternalClone() const +{ + TestModel::Pointer newClone = TestModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +}; diff --git a/Modules/ModelFit/src/TestingHelper/mitkTestModelFactory.cpp b/Modules/ModelFit/src/TestingHelper/mitkTestModelFactory.cpp new file mode 100644 index 0000000000..0c8a24448d --- /dev/null +++ b/Modules/ModelFit/src/TestingHelper/mitkTestModelFactory.cpp @@ -0,0 +1,40 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestModelFactory.h" +#include "mitkConcreteModelParameterizerBase.h" + +mitk::TestModelFactory::TestModelFactory() +{ +}; + +mitk::TestModelFactory::~TestModelFactory() +{ +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::TestModelFactory::GetDefaultInitialParameterization() const +{ + ParametersType dummy; + return dummy; +}; + +mitk::ModelParameterizerBase::Pointer mitk::TestModelFactory::DoCreateParameterizer( + const modelFit::ModelFitInfo* /*fit*/) const +{ + mitk::ModelParameterizerBase::Pointer dummy; + return dummy; +}; diff --git a/Modules/ModelFit/test/CMakeLists.txt b/Modules/ModelFit/test/CMakeLists.txt new file mode 100644 index 0000000000..d45daf111d --- /dev/null +++ b/Modules/ModelFit/test/CMakeLists.txt @@ -0,0 +1 @@ +MITK_CREATE_MODULE_TESTS() \ No newline at end of file diff --git a/Modules/ModelFit/test/files.cmake b/Modules/ModelFit/test/files.cmake new file mode 100644 index 0000000000..8e408bd49c --- /dev/null +++ b/Modules/ModelFit/test/files.cmake @@ -0,0 +1,16 @@ +SET(MODULE_TESTS + itkMultiOutputNaryFunctorImageFilterTest.cpp + itkMaskedStatisticsImageFilterTest.cpp + itkMaskedNaryStatisticsImageFilterTest.cpp + mitkLevenbergMarquardtModelFitFunctorTest.cpp + mitkPixelBasedParameterFitImageGeneratorTest.cpp + mitkROIBasedParameterFitImageGeneratorTest.cpp + mitkMaskedDynamicImageStatisticsGeneratorTest.cpp + mitkModelFitInfoTest.cpp + mitkModelFitUIDHelperTest.cpp + mitkModelFitStaticParameterMapTest.cpp + mitkSimpleBarrierConstraintCheckerTest.cpp + mitkMVConstrainedCostFunctionDecoratorTest.cpp + mitkConcreteModelFactoryBaseTest.cpp + mitkFormulaParserTest.cpp +) diff --git a/Modules/ModelFit/test/itkMaskedNaryStatisticsImageFilterTest.cpp b/Modules/ModelFit/test/itkMaskedNaryStatisticsImageFilterTest.cpp new file mode 100644 index 0000000000..8df2f6f947 --- /dev/null +++ b/Modules/ModelFit/test/itkMaskedNaryStatisticsImageFilterTest.cpp @@ -0,0 +1,109 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "itkImage.h" +#include "itkImageRegionIterator.h" + +#include "itkMaskedNaryStatisticsImageFilter.h" + +#include "mitkTestingMacros.h" +#include "mitkVector.h" + +#include "mitkTestArtifactGenerator.h" + +int itkMaskedNaryStatisticsImageFilterTest(int /*argc*/ , char*[] /*argv[]*/) +{ + // always start with this! + MITK_TEST_BEGIN("itkMaskedNaryStatisticsImageFilterTest") + + //Prepare test artifacts and helper + + mitk::TestImageType::Pointer img1 = mitk::GenerateTestImage(); + mitk::TestImageType::Pointer img2 = mitk::GenerateTestImage(10); + + typedef itk::MaskedNaryStatisticsImageFilter FilterType; + FilterType::Pointer testFilter = FilterType::New(); + + testFilter->SetInput(0,img1); + testFilter->SetInput(1,img2); + + testFilter->Update(); + + FilterType::PixelVectorType max = testFilter->GetMaximum(); + FilterType::PixelVectorType min = testFilter->GetMinimum(); + FilterType::RealVectorType mean = testFilter->GetMean(); + FilterType::RealVectorType sig = testFilter->GetSigma(); + FilterType::RealVectorType variance = testFilter->GetVariance(); + FilterType::RealVectorType sum = testFilter->GetSum(); + + MITK_TEST_CONDITION(2 == max.size(),"Check size of maximum"); + MITK_TEST_CONDITION(2 == min.size(),"Check size of minimum"); + MITK_TEST_CONDITION(2 == mean.size(),"Check size of mean"); + MITK_TEST_CONDITION(2 == sig.size(),"Check size of sigma"); + MITK_TEST_CONDITION(2 == variance.size(),"Check size of variance"); + MITK_TEST_CONDITION(2 == sum.size(),"Check size of sum"); + + CPPUNIT_ASSERT_MESSAGE("Check computed maximum[0]",9 == max[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed minimum[0]",1 == min[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed mean[0]",5 == mean[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed sigma[0]",sqrt(7.5) == sig[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed variance[0]",7.5 == variance[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed sum[0]",45 == sum[0]); + + CPPUNIT_ASSERT_MESSAGE("Check computed maximum[1]",90 == max[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed minimum[1]",10 == min[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed mean[1]",50 == mean[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed sigma[1]",sqrt(750.0) == sig[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed variance[1]",750 == variance[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed sum[1]",450 == sum[1]); + + + //Test with mask set + mitk::TestMaskType::Pointer mask = mitk::GenerateTestMask(); + testFilter->SetMask(mask); + + testFilter->Update(); + + max = testFilter->GetMaximum(); + min = testFilter->GetMinimum(); + mean = testFilter->GetMean(); + sig = testFilter->GetSigma(); + variance = testFilter->GetVariance(); + sum = testFilter->GetSum(); + + MITK_TEST_CONDITION(2 == max.size(),"Check size of maximum"); + MITK_TEST_CONDITION(2 == min.size(),"Check size of minimum"); + MITK_TEST_CONDITION(2 == mean.size(),"Check size of mean"); + MITK_TEST_CONDITION(2 == sig.size(),"Check size of sigma"); + MITK_TEST_CONDITION(2 == variance.size(),"Check size of variance"); + MITK_TEST_CONDITION(2 == sum.size(),"Check size of sum"); + + CPPUNIT_ASSERT_MESSAGE("Check computed maximum[0]",4 == max[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed minimum[0]",2 == min[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed mean[0]",3 == mean[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed sigma[0]",1 == sig[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed variance[0]",1 == variance[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed sum[0]",9 == sum[0]); + + CPPUNIT_ASSERT_MESSAGE("Check computed maximum[1]",40 == max[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed minimum[1]",20 == min[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed mean[1]",30 == mean[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed sigma[1]",10 == sig[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed variance[1]",100 == variance[1]); + CPPUNIT_ASSERT_MESSAGE("Check computed sum[1]",90 == sum[1]); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/itkMaskedStatisticsImageFilterTest.cpp b/Modules/ModelFit/test/itkMaskedStatisticsImageFilterTest.cpp new file mode 100644 index 0000000000..d72b56a6a9 --- /dev/null +++ b/Modules/ModelFit/test/itkMaskedStatisticsImageFilterTest.cpp @@ -0,0 +1,80 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "itkImage.h" +#include "itkImageRegionIterator.h" + +#include "itkMaskedStatisticsImageFilter.h" + +#include "mitkTestingMacros.h" +#include "mitkVector.h" + +#include "mitkTestArtifactGenerator.h" + +int itkMaskedStatisticsImageFilterTest(int /*argc*/, char*[] /*argv[]*/) +{ + // always start with this! + MITK_TEST_BEGIN("itkMaskedStatisticsImageFilterTest") + + //Prepare test artifacts and helper + + mitk::TestImageType::Pointer img1 = mitk::GenerateTestImage(); + + typedef itk::MaskedStatisticsImageFilter FilterType; + FilterType::Pointer testFilter = FilterType::New(); + + testFilter->SetInput(img1); + + testFilter->SetNumberOfThreads(2); + + testFilter->Update(); + + FilterType::PixelType max = testFilter->GetMaximum(); + FilterType::PixelType min = testFilter->GetMinimum(); + FilterType::RealType mean = testFilter->GetMean(); + FilterType::RealType sig = testFilter->GetSigma(); + FilterType::RealType variance = testFilter->GetVariance(); + FilterType::RealType sum = testFilter->GetSum(); + + CPPUNIT_ASSERT_MESSAGE("Check computed maximum",9 == max); + CPPUNIT_ASSERT_MESSAGE("Check computed minimum",1 == min); + CPPUNIT_ASSERT_MESSAGE("Check computed mean",5 == mean); + CPPUNIT_ASSERT_MESSAGE("Check computed sigma",sqrt(7.5) == sig); + CPPUNIT_ASSERT_MESSAGE("Check computed variance",7.5 == variance); + CPPUNIT_ASSERT_MESSAGE("Check computed sum",45 == sum); + + //Test with mask set + mitk::TestMaskType::Pointer mask = mitk::GenerateTestMask(); + testFilter->SetMask(mask); + + testFilter->Update(); + + max = testFilter->GetMaximum(); + min = testFilter->GetMinimum(); + mean = testFilter->GetMean(); + sig = testFilter->GetSigma(); + variance = testFilter->GetVariance(); + sum = testFilter->GetSum(); + + CPPUNIT_ASSERT_MESSAGE("Check computed maximum",4 == max); + CPPUNIT_ASSERT_MESSAGE("Check computed minimum",2 == min); + CPPUNIT_ASSERT_MESSAGE("Check computed mean",3 == mean); + CPPUNIT_ASSERT_MESSAGE("Check computed sigma",1 == sig); + CPPUNIT_ASSERT_MESSAGE("Check computed variance",1 == variance); + CPPUNIT_ASSERT_MESSAGE("Check computed sum",9 == sum); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/itkMultiOutputNaryFunctorImageFilterTest.cpp b/Modules/ModelFit/test/itkMultiOutputNaryFunctorImageFilterTest.cpp new file mode 100644 index 0000000000..ff957e12a0 --- /dev/null +++ b/Modules/ModelFit/test/itkMultiOutputNaryFunctorImageFilterTest.cpp @@ -0,0 +1,222 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "itkImage.h" +#include "itkImageRegionIterator.h" + +#include "itkMultiOutputNaryFunctorImageFilter.h" + +#include "mitkTestingMacros.h" +#include "mitkVector.h" + +#include "mitkTestArtifactGenerator.h" + +class TestFunctor +{ +public: + typedef std::vector InputPixelArrayType; + typedef std::vector OutputPixelArrayType; + typedef itk::Index<2> IndexType; + + TestFunctor() + { + secondOutputSelection = 0; + }; + + ~TestFunctor() {}; + + int secondOutputSelection; + + unsigned int GetNumberOfOutputs() const + { + return 4; + } + + bool operator!=( const TestFunctor & other) const + { + return !(*this == other); + } + + bool operator==( const TestFunctor & other ) const + { + return secondOutputSelection == other.secondOutputSelection; + } + + inline OutputPixelArrayType operator()( const InputPixelArrayType & value, const IndexType& currentIndex ) const + { + OutputPixelArrayType result; + + int sum = 0; + for (InputPixelArrayType::const_iterator pos = value.begin(); pos != value.end(); ++pos) + { + sum += *pos; + } + + result.push_back(sum); + result.push_back(value[secondOutputSelection]); + result.push_back(currentIndex[0]); + result.push_back(currentIndex[1]); + + return result; + } +}; + +int itkMultiOutputNaryFunctorImageFilterTest(int /*argc*/, char*[] /*argv[]*/) +{ + // always start with this! + MITK_TEST_BEGIN("itkMultiOutputNaryFunctorImageFilter") + + //Prepare test artifacts and helper + + mitk::TestImageType::Pointer img1 = mitk::GenerateTestImage(); + mitk::TestImageType::Pointer img2 = mitk::GenerateTestImage(10); + mitk::TestImageType::Pointer img3 = mitk::GenerateTestImage(100); + + mitk::TestImageType::IndexType testIndex1; + testIndex1[0] = 0; + testIndex1[1] = 0; + + mitk::TestImageType::IndexType testIndex2; + testIndex2[0] = 2; + testIndex2[1] = 0; + + mitk::TestImageType::IndexType testIndex3; + testIndex3[0] = 0; + testIndex3[1] = 1; + + mitk::TestImageType::IndexType testIndex4; + testIndex4[0] = 1; + testIndex4[1] = 1; + + mitk::TestImageType::IndexType testIndex5; + testIndex5[0] = 2; + testIndex5[1] = 2; + + //Test default usage of filter + typedef itk::MultiOutputNaryFunctorImageFilter FilterType; + FilterType::Pointer testFilter = FilterType::New(); + + testFilter->SetInput(0,img1); + testFilter->SetInput(1,img2); + testFilter->SetInput(2,img3); + + testFilter->SetNumberOfThreads(2); + + testFilter->Update(); + + mitk::TestImageType::Pointer out1 = testFilter->GetOutput(0); + mitk::TestImageType::Pointer out2 = testFilter->GetOutput(1); + mitk::TestImageType::Pointer out3 = testFilter->GetOutput(2); + mitk::TestImageType::Pointer out4 = testFilter->GetOutput(3); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #1 (functor #1)",111 == out1->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #2 (functor #1)",333 == out1->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #3 (functor #1)",444 == out1->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #4 (functor #1)",555 == out1->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #5 (functor #1)",999 == out1->GetPixel(testIndex5)); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #1 (functor #1)",1 == out2->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #2 (functor #1)",3 == out2->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #3 (functor #1)",4 == out2->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #4 (functor #1)",5 == out2->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #5 (functor #1)",9 == out2->GetPixel(testIndex5)); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #1 (functor #1)",0 == out3->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #2 (functor #1)",2 == out3->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #3 (functor #1)",0 == out3->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #4 (functor #1)",1 == out3->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #5 (functor #1)",2 == out3->GetPixel(testIndex5)); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #1 (functor #1)",0 == out4->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #2 (functor #1)",0 == out4->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #3 (functor #1)",1 == out4->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #4 (functor #1)",1 == out4->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #5 (functor #1)",2 == out4->GetPixel(testIndex5)); + + //Test with functor set by user + TestFunctor funct2; + funct2.secondOutputSelection = 1; + + testFilter->SetFunctor(funct2); + + testFilter->Update(); + + out1 = testFilter->GetOutput(0); + out2 = testFilter->GetOutput(1); + out3 = testFilter->GetOutput(2); + out4 = testFilter->GetOutput(3); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #1 (functor #2)",111 == out1->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #2 (functor #2)",333 == out1->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #3 (functor #2)",444 == out1->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #4 (functor #2)",555 == out1->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #1 index #5 (functor #2)",999 == out1->GetPixel(testIndex5)); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #1 (functor #2)",10 == out2->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #2 (functor #2)",30 == out2->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #3 (functor #2)",40 == out2->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #4 (functor #2)",50 == out2->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #2 index #5 (functor #2)",90 == out2->GetPixel(testIndex5)); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #1 (functor #2)",0 == out3->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #2 (functor #2)",2 == out3->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #3 (functor #2)",0 == out3->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #4 (functor #2)",1 == out3->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #3 index #5 (functor #2)",2 == out3->GetPixel(testIndex5)); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #1 (functor #2)",0 == out4->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #2 (functor #2)",0 == out4->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #3 (functor #2)",1 == out4->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #4 (functor #2)",1 == out4->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of output #4 index #5 (functor #2)",2 == out4->GetPixel(testIndex5)); + + //Test with mask set + mitk::TestMaskType::Pointer mask = mitk::GenerateTestMask(); + testFilter->SetMask(mask); + + testFilter->Update(); + + out1 = testFilter->GetOutput(0); + out2 = testFilter->GetOutput(1); + out3 = testFilter->GetOutput(2); + out4 = testFilter->GetOutput(3); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #1 index #1 (functor #2)",0 == out1->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #1 index #2 (functor #2)",333 == out1->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #1 index #3 (functor #2)",444 == out1->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #1 index #4 (functor #2)",0 == out1->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #1 index #5 (functor #2)",0 == out1->GetPixel(testIndex5)); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #2 index #1 (functor #2)",0 == out2->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #2 index #2 (functor #2)",30 == out2->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #2 index #3 (functor #2)",40 == out2->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #2 index #4 (functor #2)",0 == out2->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #2 index #5 (functor #2)",0 == out2->GetPixel(testIndex5)); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #3 index #1 (functor #2)",0 == out3->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #3 index #2 (functor #2)",2 == out3->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #3 index #3 (functor #2)",0 == out3->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #3 index #4 (functor #2)",0 == out3->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #3 index #5 (functor #2)",0 == out3->GetPixel(testIndex5)); + + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #4 index #1 (functor #2)",0 == out4->GetPixel(testIndex1)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #4 index #2 (functor #2)",0 == out4->GetPixel(testIndex2)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #4 index #3 (functor #2)",1 == out4->GetPixel(testIndex3)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #4 index #4 (functor #2)",0 == out4->GetPixel(testIndex4)); + CPPUNIT_ASSERT_MESSAGE("Check pixel of masked output #4 index #5 (functor #2)",0 == out4->GetPixel(testIndex5)); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkConcreteModelFactoryBaseTest.cpp b/Modules/ModelFit/test/mitkConcreteModelFactoryBaseTest.cpp new file mode 100644 index 0000000000..01590c0b8d --- /dev/null +++ b/Modules/ModelFit/test/mitkConcreteModelFactoryBaseTest.cpp @@ -0,0 +1,74 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkTestingMacros.h" + +#include "mitkTestModel.h" +#include "mitkTestModelFactory.h" +#include "mitkModelFitException.h" + + +int mitkConcreteModelFactoryBaseTest(int /*argc*/, char*[] /*argv[]*/) +{ + MITK_TEST_BEGIN("mitkConcreteModelFactoryBaseTest") + + mitk::TestModelFactory::Pointer factory = mitk::TestModelFactory::New(); + mitk::TestModel::Pointer refModel = mitk::TestModel::New(); + + //check pass through of model properties. + + MITK_TEST_CONDITION_REQUIRED(factory->GetParameterNames() == refModel->GetParameterNames(), + "Testing if GetParameterNames is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetNumberOfParameters() == refModel->GetNumberOfParameters(), + "Testing if GetNumberOfParameters is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetParameterScales() == refModel->GetParameterScales(), + "Testing if GetParameterScales is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetParameterUnits() == refModel->GetParameterUnits(), + "Testing if GetParameterUnits is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetDerivedParameterNames() == + refModel->GetDerivedParameterNames(), + "Testing if GetDerivedParameterNames is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetNumberOfDerivedParameters() == + refModel->GetNumberOfDerivedParameters(), + "Testing if GetNumberOfDerivedParameters is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetDerivedParameterScales() == + refModel->GetDerivedParameterScales(), + "Testing if GetDerivedParameterScales is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetDerivedParameterUnits() == + refModel->GetDerivedParameterUnits(), + "Testing if GetDerivedParameterUnits is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetModelDisplayName() == refModel->GetModelDisplayName(), + "Testing if GetModelDisplayName is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetModelType() == refModel->GetModelType(), + "Testing if GetModelType is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetFunctionString() == refModel->GetFunctionString(), + "Testing if GetFunctionString is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetClassID() == refModel->GetClassID(), + "Testing if GetClassID is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetXName() == refModel->GetXName(), + "Testing if GetXName is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetXAxisName() == refModel->GetXAxisName(), + "Testing if GetXAxisName is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetXAxisUnit() == refModel->GetXAxisUnit(), + "Testing if GetXAxisUnit is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetYAxisName() == refModel->GetYAxisName(), + "Testing if GetYAxisName is successfully passed through."); + MITK_TEST_CONDITION_REQUIRED(factory->GetYAxisUnit() == refModel->GetYAxisUnit(), + "Testing if GetYAxisUnit is successfully passed through."); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkFormulaParserTest.cpp b/Modules/ModelFit/test/mitkFormulaParserTest.cpp new file mode 100644 index 0000000000..395524b354 --- /dev/null +++ b/Modules/ModelFit/test/mitkFormulaParserTest.cpp @@ -0,0 +1,229 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestingMacros.h" +#include "mitkFormulaParser.h" + +using namespace mitk; + +#define TEST_NOTHROW(expression, MSG) \ + do \ + { \ + MITK_TEST_OUTPUT_NO_ENDL(<< MSG) \ + bool test_caught = false; \ + try \ + { \ + expression; \ + } \ + catch(...) \ + { \ + test_caught = true; \ + MITK_TEST_FAILED_MSG(<< "An unwanted exception was thrown"); \ + } \ + if(!test_caught) \ + { \ + MITK_TEST_OUTPUT(<< " [PASSED]") \ + mitk::TestManager::GetInstance()->TestPassed(); \ + } \ + } while(0) + +/*! + * @author Sascha Diatschuk + */ +class FormulaParserTests +{ +public: + static void TestConstructor() + { + std::map varMap; + FormulaParser *nullParser = NULL, *parser = NULL; + + TEST_NOTHROW(nullParser = new FormulaParser(NULL), + "Testing constructor with NULL argument"); + TEST_NOTHROW(parser = new FormulaParser(&varMap), + "Testing constructor with valid argument"); + + delete nullParser; + delete parser; + } + + static void TestLookupVariable() + { + // variable map is NULL + FormulaParser *nullParser = new FormulaParser(NULL); + MITK_TEST_FOR_EXCEPTION(FormulaParserException, nullParser->lookupVariable("test")); + delete nullParser; + + // variable map is empty + std::map varMap; + FormulaParser *parser = new FormulaParser(&varMap); + MITK_TEST_FOR_EXCEPTION(FormulaParserException, parser->lookupVariable("test")); + + // lookup should succeed + double var; + varMap["test"] = 17; + TEST_NOTHROW(var = parser->lookupVariable("test"), + "Testing if lookupVariable throws unwanted exceptions"); + MITK_TEST_CONDITION_REQUIRED(var == 17, + "Testing if lookupVariable returns the correct value"); + + delete parser; + } + + static void TestParse() + { + std::map varMap; + varMap["test"] = 17; + FormulaParser *parser = new FormulaParser(&varMap); + + // empty string + MITK_TEST_FOR_EXCEPTION(FormulaParserException, parser->parse("")); + + // grammar can't process string + MITK_TEST_FOR_EXCEPTION(FormulaParserException, parser->parse("_")); + + // unexpected character + MITK_TEST_FOR_EXCEPTION(FormulaParserException, parser->parse("5=")); + + // unknown variable + MITK_TEST_FOR_EXCEPTION(FormulaParserException, parser->parse("a")); + + double d; + + // addition + TEST_NOTHROW(d = parser->parse("1+2"), + "Testing if addition throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(d == 3, + "Testing if addition produces the correct result"); + + // subtraction + TEST_NOTHROW(d = parser->parse("5-1"), + "Testing if subtraction throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(d == 4, + "Testing if subtraction produces the correct result"); + + // multiplication + TEST_NOTHROW(d = parser->parse("3*4"), + "Testing if multiplication throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(d == 12, + "Testing if multiplication produces the correct result"); + + // division + TEST_NOTHROW(d = parser->parse("28/4"), + "Testing if division throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(d == 7, + "Testing if division produces the correct result"); + + /*! @TODO: Reactivate as soon as exponentiation works again */ + // exponentiation + //TEST_NOTHROW(d = parser->parse("2^3"), + // "Testing if exponentiation throws an unwanted exception"); + //MITK_TEST_CONDITION_REQUIRED(d == 8, + // "Testing if exponentiation produces the correct result"); + + // algebraic signs + TEST_NOTHROW(d = parser->parse("-7 + +1 - -1"), + "Testing if algebraic signs throw an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(d == -5, + "Testing if algebraic signs produce the correct result"); + + // parentheses + TEST_NOTHROW(d = parser->parse("(1+2)*(4-2)"), + "Testing if parentheses throw an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(d == 6, + "Testing if parentheses produce the correct result"); + + // variables + TEST_NOTHROW(d = parser->parse("2*test-test"), + "Testing if variables throw an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(d == 17, + "Testing if variables produce the correct result"); + + // abs + TEST_NOTHROW(d = parser->parse("abs(-5)"), + "Testing if abs throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(d == 5, + "Testing if abs produces the correct result"); + + const double eps = 0.0001; + + // exp + TEST_NOTHROW(d = parser->parse("exp(1)"), + "Testing if exp throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(abs(d - 2.71828182846) < eps, + "Testing if exp produces the correct result"); + + // sin + TEST_NOTHROW(d = parser->parse("sin(1.57079632679)"), + "Testing if sin throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(abs(d - 1) < eps, + "Testing if sin produces the correct result"); + + // cos + TEST_NOTHROW(d = parser->parse("cos(3.14159265359)"), + "Testing if cos throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(abs(d + 1) < eps, + "Testing if cos produces the correct result"); + + // tan + TEST_NOTHROW(d = parser->parse("tan(0.46364760899)"), + "Testing if tan throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(abs(d - 0.5) < eps, + "Testing if tan produces the correct result"); + + // sind + TEST_NOTHROW(d = parser->parse("sind(145)"), + "Testing if sind throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(abs(d - 0.57357643635) < eps, + "Testing if sind produces the correct result"); + + // cosd + TEST_NOTHROW(d = parser->parse("cosd(90)"), + "Testing if cosd throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(d < eps, + "Testing if cosd produces the correct result"); + + // tand + TEST_NOTHROW(d = parser->parse("tand(15)"), + "Testing if tand throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(abs(d - 0.26794919243) < eps, + "Testing if tand produces the correct result"); + + // fresnelS + TEST_NOTHROW(d = parser->parse("fresnelS(1)"), + "Testing if fresnelS throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(abs(d - 0.310268) < eps, + "Testing if fresnelS produces the correct result"); + + TEST_NOTHROW(d = parser->parse("fresnelC(1)"), + "Testing if fresnelC throws an unwanted exception"); + MITK_TEST_CONDITION_REQUIRED(abs(d - 0.904524) < eps, + "Testing if fresnelC produces the correct result"); + + delete parser; + } +}; + +int mitkFormulaParserTest(int, char *[]) +{ + MITK_TEST_BEGIN("FormulaParser Test"); + + FormulaParserTests::TestConstructor(); + FormulaParserTests::TestLookupVariable(); + FormulaParserTests::TestParse(); + + MITK_TEST_END(); +} diff --git a/Modules/ModelFit/test/mitkLevenbergMarquardtModelFitFunctorTest.cpp b/Modules/ModelFit/test/mitkLevenbergMarquardtModelFitFunctorTest.cpp new file mode 100644 index 0000000000..d1ec7a5eaf --- /dev/null +++ b/Modules/ModelFit/test/mitkLevenbergMarquardtModelFitFunctorTest.cpp @@ -0,0 +1,89 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkTestingMacros.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" + +#include "mitkLevenbergMarquardtModelFitFunctor.h" + +#include "mitkLinearModel.h" + +int mitkLevenbergMarquardtModelFitFunctorTest(int /*argc*/, char*[] /*argv[]*/) +{ + // always start with this! + MITK_TEST_BEGIN("LevenbergMarquardtModelFitFunctor") + + //Prepare test artifacts and helper + + mitk::ModelBase::TimeGridType grid(10); + + typedef std::vector ValueArrayType; + + ValueArrayType sample1(10); + ValueArrayType sample2(10); + + for (int i = 0; i < 10; ++i) + { + grid[i] = i; + sample1[i] = 5 * i; + sample2[i] = 2 * i + 10; + } + + mitk::LinearModel::Pointer model = mitk::LinearModel::New(); + model->SetTimeGrid(grid); + + mitk::LinearModel::ParametersType initParams; + initParams.SetSize(2); + initParams.Fill(0.0); + + + mitk::LevenbergMarquardtModelFitFunctor::Pointer testFunctor = + mitk::LevenbergMarquardtModelFitFunctor::New(); + + //Test functor for sample1 + + MITK_TEST_FOR_EXCEPTION(::itk::ExceptionObject, testFunctor->GetNumberOfOutputs(NULL)); + + CPPUNIT_ASSERT_MESSAGE("Check number of outputs with model set.", 4 == testFunctor->GetNumberOfOutputs(model)); + + ValueArrayType output = testFunctor->Compute(sample1, model, initParams); + + CPPUNIT_ASSERT_MESSAGE("Check number of values in functor output.", 4 == output.size()); + + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(5, output[0], 1e-6, true) == true, + "Check fitted parameter 1 (slope) for sample 1."); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0, output[1], 1e-6, true) == true, + "Check fitted parameter 2 (offset) for sample 1."); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0, output[2], 1e-6, true) == true, + "Check derived parameter 1 (x-intercept) for sample 1."); + + //Test functor for sample2 + output = testFunctor->Compute(sample2, model, initParams); + + CPPUNIT_ASSERT_MESSAGE("Check number of values in functor output.", 4 == output.size()); + + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(2, output[0], 1e-6, true) == true, + "Check fitted parameter 1 (slope) for sample 2."); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(10, output[1], 1e-6, true) == true, + "Check fitted parameter 2 (offset) for sample 2.") + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(-5, output[2], 1e-6, true) == true, + "Check derived parameter 1 (x-intercept) for sample 2."); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkMVConstrainedCostFunctionDecoratorTest.cpp b/Modules/ModelFit/test/mitkMVConstrainedCostFunctionDecoratorTest.cpp new file mode 100644 index 0000000000..ff4c43076c --- /dev/null +++ b/Modules/ModelFit/test/mitkMVConstrainedCostFunctionDecoratorTest.cpp @@ -0,0 +1,155 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkTestingMacros.h" + +#include "mitkSimpleBarrierConstraintChecker.h" +#include "mitkMVConstrainedCostFunctionDecorator.h" +#include "mitkLinearModel.h" + +class TestCostFunction : public mitk::MVModelFitCostFunction +{ +public: + + typedef TestCostFunction Self; + typedef mitk::MVModelFitCostFunction Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkNewMacro(Self); + + typedef Superclass::SignalType SignalType; + + mutable unsigned int m_calls; + +protected: + + virtual MeasureType CalcMeasure(const ParametersType ¶meters, const SignalType& signal) const + { + MeasureType result = signal; + result[0] = parameters[0]; + result[1] = parameters[1]; + ++m_calls; + return result; + }; + + TestCostFunction() + { + m_calls = 0; + } + + ~TestCostFunction(){} +}; + +int mitkMVConstrainedCostFunctionDecoratorTest(int /*argc*/, char*[] /*argv[]*/) +{ + MITK_TEST_BEGIN("mitkMVConstrainedCostFunctionDecoratorTest") + + mitk::SimpleBarrierConstraintChecker::Pointer checker = mitk::SimpleBarrierConstraintChecker::New(); + mitk::MVConstrainedCostFunctionDecorator::Pointer decorator = mitk::MVConstrainedCostFunctionDecorator::New(); + TestCostFunction::Pointer innerCF = TestCostFunction::New(); + mitk::LinearModel::Pointer model = mitk::LinearModel::New(); + decorator->SetModel(model); + innerCF->SetModel(model); + + mitk::MVModelFitCostFunction::SignalType signal(5); + signal.Fill(0.0); + decorator->SetSample(signal); + innerCF->SetSample(signal); + + mitk::LinearModel::TimeGridType grid(5); + grid[0] = 0; + grid[1] = 1; + grid[2] = 2; + grid[3] = 3; + grid[4] = 4; + + model->SetTimeGrid(grid); + + mitk::SimpleBarrierConstraintChecker::ParametersType p1(2); + p1[0] = 0; + p1[1] = 50; + mitk::SimpleBarrierConstraintChecker::ParametersType p2(2); + p2[0] = 10; + p2[1] = 50; + mitk::SimpleBarrierConstraintChecker::ParametersType p3(2); + p3[0] = 100; + p3[1] = 50; + mitk::SimpleBarrierConstraintChecker::ParametersType p4(2); + p4[0] = 2; + p4[1] = 50; + + checker->SetLowerBarrier(0,1,4); + checker->SetUpperBarrier(0,100); + + /////////////////////// + //Tests + + //check freshly created checker; + MITK_TEST_CONDITION_REQUIRED(decorator->GetWrappedCostFunction() == NULL, + "Testing GetWrappedCostFunction for new decorator."); + MITK_TEST_CONDITION_REQUIRED(decorator->GetConstraintChecker() == NULL, + "Testing GetWrappedCostFunction for new decorator."); + MITK_TEST_CONDITION_REQUIRED(decorator->GetFailureThreshold() == 1e6, + "Testing GetWrappedCostFunction for new decorator."); + + MITK_TEST_FOR_EXCEPTION(mitk::Exception, decorator->GetValue(p1)); + decorator->SetWrappedCostFunction(innerCF); + MITK_TEST_FOR_EXCEPTION(mitk::Exception, decorator->GetValue(p1)); + decorator->SetWrappedCostFunction(NULL); + decorator->SetConstraintChecker(checker); + MITK_TEST_FOR_EXCEPTION(mitk::Exception, decorator->GetValue(p1)); + decorator->SetWrappedCostFunction(innerCF); + + + mitk::MVModelFitCostFunction::MeasureType measure = decorator->GetValue(p1); + MITK_TEST_CONDITION_REQUIRED(measure[0] == 1e6, "Testing measure 1 with parameters p1."); + MITK_TEST_CONDITION_REQUIRED(measure[1] == 1e6, "Testing measure 2 with parameters p1."); + MITK_TEST_CONDITION_REQUIRED(measure[2] == 1e6, "Testing measure 3 with parameters p1."); + MITK_TEST_CONDITION_REQUIRED(measure[3] == 1e6, "Testing measure 3 with parameters p1."); + MITK_TEST_CONDITION_REQUIRED(measure[4] == 1e6, "Testing measure 3 with parameters p1."); + MITK_TEST_CONDITION_REQUIRED(innerCF->m_calls == 0, "Checking calls with parameters p1."); + + measure = decorator->GetValue(p2); + MITK_TEST_CONDITION_REQUIRED(measure[0] == 10, "Testing measure 1 with parameters p2."); + MITK_TEST_CONDITION_REQUIRED(measure[1] == 50, "Testing measure 2 with parameters p2."); + MITK_TEST_CONDITION_REQUIRED(measure[2] == 70, "Testing measure 3 with parameters p2."); + MITK_TEST_CONDITION_REQUIRED(innerCF->m_calls == 1, "Checking calls with parameters p2."); + + measure = decorator->GetValue(p3); + MITK_TEST_CONDITION_REQUIRED(measure[0] == 1e6, "Testing measure 1 with parameters p3."); + MITK_TEST_CONDITION_REQUIRED(measure[1] == 1e6, "Testing measure 2 with parameters p3."); + MITK_TEST_CONDITION_REQUIRED(measure[2] == 1e6, "Testing measure 3 with parameters p3."); + MITK_TEST_CONDITION_REQUIRED(innerCF->m_calls == 1, "Checking calls with parameters p3."); + + decorator->SetActivateFailureThreshold(false); + measure = decorator->GetValue(p3); + MITK_TEST_CONDITION_REQUIRED(measure[0] == 100+1e6, "Testing measure 1 with parameters p3 (deactiveated threshold)."); + MITK_TEST_CONDITION_REQUIRED(measure[1] == 50+1e6, "Testing measure 2 with parameters p3 (deactiveated threshold)."); + MITK_TEST_CONDITION_REQUIRED(measure[2] == 250+1e6, "Testing measure 3 with parameters p3 (deactiveated threshold)."); + MITK_TEST_CONDITION_REQUIRED(innerCF->m_calls ==2, "Checking calls with parameters p3 (deactiveated threshold)."); + decorator->SetActivateFailureThreshold(true); + + measure = decorator->GetValue(p4); + MITK_TEST_CONDITION_REQUIRED(measure[0] == 2+(-1*log(1/4.)), "Testing measure 1 with parameters p4."); + MITK_TEST_CONDITION_REQUIRED(measure[1] == 50+(-1*log(1/4.)), "Testing measure 2 with parameters p4."); + MITK_TEST_CONDITION_REQUIRED(measure[2] == 54+(-1*log(1/4.)), "Testing measure 3 with parameters p4."); + MITK_TEST_CONDITION_REQUIRED(innerCF->m_calls == 3, "Checking calls with parameters p4."); + + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkMaskedDynamicImageStatisticsGeneratorTest.cpp b/Modules/ModelFit/test/mitkMaskedDynamicImageStatisticsGeneratorTest.cpp new file mode 100644 index 0000000000..c3634f5bac --- /dev/null +++ b/Modules/ModelFit/test/mitkMaskedDynamicImageStatisticsGeneratorTest.cpp @@ -0,0 +1,79 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include "mitkTestingMacros.h" +#include "mitkImage.h" +#include "mitkImagePixelReadAccessor.h" + +#include "mitkMaskedDynamicImageStatisticsGenerator.h" + +#include "mitkTestArtifactGenerator.h" + +int mitkMaskedDynamicImageStatisticsGeneratorTest(int /*argc*/, char*[] /*argv[]*/) +{ + // always start with this! + MITK_TEST_BEGIN("mitkParameterFitImageGenerator") + + mitk::Image::Pointer dynamicImage = mitk::GenerateDynamicTestImageMITK(); + + //Test default usage of filter + mitk::MaskedDynamicImageStatisticsGenerator::Pointer generator = mitk::MaskedDynamicImageStatisticsGenerator::New(); + generator->SetDynamicImage(dynamicImage); + generator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType max = generator->GetMaximum(); + mitk::MaskedDynamicImageStatisticsGenerator::ResultType min = generator->GetMinimum(); + mitk::MaskedDynamicImageStatisticsGenerator::ResultType mean = generator->GetMean(); + mitk::MaskedDynamicImageStatisticsGenerator::ResultType sig = generator->GetSigma(); + mitk::MaskedDynamicImageStatisticsGenerator::ResultType variance = generator->GetVariance(); + mitk::MaskedDynamicImageStatisticsGenerator::ResultType sum = generator->GetSum(); + + MITK_TEST_CONDITION(10 == max.size(),"Check size of maximum"); + MITK_TEST_CONDITION(10 == min.size(),"Check size of minimum"); + MITK_TEST_CONDITION(10 == mean.size(),"Check size of mean"); + MITK_TEST_CONDITION(10 == sig.size(),"Check size of sigma"); + MITK_TEST_CONDITION(10 == variance.size(),"Check size of variance"); + MITK_TEST_CONDITION(10 == sum.size(),"Check size of sum"); + + CPPUNIT_ASSERT_MESSAGE("Check computed maximum[0]", 28 == max[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed minimum[0]", 0 == min[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed mean[0]", 14 == mean[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed sigma[0]", 8.7266171082410953 == sig[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed variance[0]", 76.153846153846160 == variance[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed sum[0]", 378 == sum[0]); + + mitk::Image::Pointer maskImage = mitk::GenerateTestMaskMITK(); + generator->SetMask(maskImage); + generator->Generate(); + + max = generator->GetMaximum(); + min = generator->GetMinimum(); + mean = generator->GetMean(); + sig = generator->GetSigma(); + variance = generator->GetVariance(); + sum = generator->GetSum(); + + CPPUNIT_ASSERT_MESSAGE("Check computed maximum[0]", 14 == max[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed minimum[0]", 0 == min[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed mean[0]",6.8571428571428568 == mean[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed sigma[0]",4.6053003386088953 == sig[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed variance[0]",21.208791208791204 == variance[0]); + CPPUNIT_ASSERT_MESSAGE("Check computed sum[0]",96.000000000000000 == sum[0]); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkModelFitInfoTest.cpp b/Modules/ModelFit/test/mitkModelFitInfoTest.cpp new file mode 100644 index 0000000000..f1ccbe3d6b --- /dev/null +++ b/Modules/ModelFit/test/mitkModelFitInfoTest.cpp @@ -0,0 +1,262 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkTestingMacros.h" +#include "mitkProperties.h" +#include "mitkStandaloneDataStorage.h" + +#include "mitkModelFitInfo.h" +#include "mitkModelFitConstants.h" +#include "mitkModelFitException.h" + +mitk::DataNode::Pointer generateModelFitTestNode() +{ + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetName("Param1"); + node->SetStringProperty("modelfit.testEmpty", ""); + node->SetStringProperty("modelfit.testValid", "test"); + + mitk::EnsureModelFitUID(node); + node->SetStringProperty(mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(),"Fit1"); + node->SetStringProperty(mitk::ModelFitConstants::FIT_TYPE_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED().c_str()); + node->SetStringProperty(mitk::ModelFitConstants::FIT_INPUT_IMAGEUID_PROPERTY_NAME().c_str(),"input UID"); + + node->SetStringProperty(mitk::ModelFitConstants::MODEL_TYPE_PROPERTY_NAME().c_str(),"TestModels"); + node->SetStringProperty(mitk::ModelFitConstants::MODEL_NAME_PROPERTY_NAME().c_str(),"TestModel_1"); + node->SetStringProperty(mitk::ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME().c_str(),""); + node->SetStringProperty(mitk::ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME().c_str(),"ModelClass"); + node->SetStringProperty(mitk::ModelFitConstants::MODEL_X_PROPERTY_NAME().c_str(),"myX"); + + node->SetStringProperty(mitk::ModelFitConstants::XAXIS_NAME_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::XAXIS_NAME_VALUE_DEFAULT().c_str()); + node->SetStringProperty(mitk::ModelFitConstants::XAXIS_UNIT_PROPERTY_NAME().c_str(),"h"); + node->SetStringProperty(mitk::ModelFitConstants::YAXIS_NAME_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::YAXIS_NAME_VALUE_DEFAULT().c_str()); + node->SetStringProperty(mitk::ModelFitConstants::YAXIS_UNIT_PROPERTY_NAME().c_str(),"kg"); + + return node; +} + +mitk::StandaloneDataStorage::Pointer generateModelFitTestStorage() +{ + mitk::StandaloneDataStorage::Pointer storage = mitk::StandaloneDataStorage::New(); + + //create input node + mitk::DataNode::Pointer inputNode = mitk::DataNode::New(); + inputNode->SetName("Input"); + mitk::Image::Pointer image = mitk::Image::New(); + inputNode->SetData(image); + mitk::NodeUIDType inputUID = mitk::EnsureModelFitUID(inputNode); + + storage->Add(inputNode); + + mitk::DataStorage::SetOfObjects::Pointer parents = mitk::DataStorage::SetOfObjects::New(); + parents->push_back(inputNode); + + //create first result for Fit1 + mitk::DataNode::Pointer node1 = mitk::DataNode::New(); + mitk::Image::Pointer paramImage = mitk::Image::New(); + node1->SetData(paramImage); + node1->SetName("Param1"); + mitk::EnsureModelFitUID(node1); + node1->SetStringProperty(mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(),"Fit1"); + node1->SetStringProperty(mitk::ModelFitConstants::FIT_TYPE_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED().c_str()); + node1->SetStringProperty(mitk::ModelFitConstants::FIT_INPUT_IMAGEUID_PROPERTY_NAME().c_str(),inputUID.c_str()); + + node1->SetStringProperty(mitk::ModelFitConstants::MODEL_TYPE_PROPERTY_NAME().c_str(),"TestModels"); + node1->SetStringProperty(mitk::ModelFitConstants::MODEL_NAME_PROPERTY_NAME().c_str(),"TestModel_1"); + node1->SetStringProperty(mitk::ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME().c_str(),""); + node1->SetStringProperty(mitk::ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME().c_str(),"ModelClass"); + node1->SetStringProperty(mitk::ModelFitConstants::MODEL_X_PROPERTY_NAME().c_str(),"myX"); + + node1->SetStringProperty(mitk::ModelFitConstants::XAXIS_NAME_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::XAXIS_NAME_VALUE_DEFAULT().c_str()); + node1->SetStringProperty(mitk::ModelFitConstants::XAXIS_UNIT_PROPERTY_NAME().c_str(),"h"); + node1->SetStringProperty(mitk::ModelFitConstants::YAXIS_NAME_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::YAXIS_NAME_VALUE_DEFAULT().c_str()); + node1->SetStringProperty(mitk::ModelFitConstants::YAXIS_UNIT_PROPERTY_NAME().c_str(),"kg"); + + node1->SetStringProperty(mitk::ModelFitConstants::PARAMETER_NAME_PROPERTY_NAME().c_str(),"Param1"); + node1->SetStringProperty(mitk::ModelFitConstants::PARAMETER_UNIT_PROPERTY_NAME().c_str(),"b"); + node1->SetStringProperty(mitk::ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_PARAMETER().c_str()); + + storage->Add(node1,parents); + + //create second result for Fit1 + mitk::DataNode::Pointer node2 = mitk::DataNode::New(); + node2->SetName("Param2"); + mitk::Image::Pointer paramImage2 = mitk::Image::New(); + node2->SetData(paramImage2); + mitk::EnsureModelFitUID(node2); + node2->SetStringProperty(mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(),"Fit1"); + node2->SetStringProperty(mitk::ModelFitConstants::FIT_TYPE_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED().c_str()); + node2->SetStringProperty(mitk::ModelFitConstants::FIT_INPUT_IMAGEUID_PROPERTY_NAME().c_str(),inputUID.c_str()); + + node2->SetStringProperty(mitk::ModelFitConstants::MODEL_TYPE_PROPERTY_NAME().c_str(),"TestModels"); + node2->SetStringProperty(mitk::ModelFitConstants::MODEL_NAME_PROPERTY_NAME().c_str(),"TestModel_1"); + node2->SetStringProperty(mitk::ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME().c_str(),""); + node2->SetStringProperty(mitk::ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME().c_str(),"ModelClass"); + node2->SetStringProperty(mitk::ModelFitConstants::MODEL_X_PROPERTY_NAME().c_str(),"myX"); + + node2->SetStringProperty(mitk::ModelFitConstants::XAXIS_NAME_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::XAXIS_NAME_VALUE_DEFAULT().c_str()); + node2->SetStringProperty(mitk::ModelFitConstants::XAXIS_UNIT_PROPERTY_NAME().c_str(),"h"); + node2->SetStringProperty(mitk::ModelFitConstants::YAXIS_NAME_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::YAXIS_NAME_VALUE_DEFAULT().c_str()); + node2->SetStringProperty(mitk::ModelFitConstants::YAXIS_UNIT_PROPERTY_NAME().c_str(),"kg"); + + node2->SetStringProperty(mitk::ModelFitConstants::PARAMETER_NAME_PROPERTY_NAME().c_str(),"Param2"); + node2->SetStringProperty(mitk::ModelFitConstants::PARAMETER_UNIT_PROPERTY_NAME().c_str(),"a"); + node2->SetStringProperty(mitk::ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_DERIVED_PARAMETER().c_str()); + + storage->Add(node2, parents); + + //create result for Fit 2 + mitk::DataNode::Pointer node3 = mitk::DataNode::New(); + node3->SetName("Param_Other"); + mitk::EnsureModelFitUID(node3); + node3->SetStringProperty(mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(),"Fit2"); + node3->SetStringProperty(mitk::ModelFitConstants::FIT_TYPE_PROPERTY_NAME().c_str(),mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED().c_str()); + node3->SetStringProperty(mitk::ModelFitConstants::FIT_INPUT_IMAGEUID_PROPERTY_NAME().c_str(),inputUID.c_str()); + + node3->SetStringProperty(mitk::ModelFitConstants::MODEL_TYPE_PROPERTY_NAME().c_str(),"TestModels"); + node3->SetStringProperty(mitk::ModelFitConstants::MODEL_NAME_PROPERTY_NAME().c_str(),"TestModel_2"); + node3->SetStringProperty(mitk::ModelFitConstants::MODEL_FUNCTION_PROPERTY_NAME().c_str(),""); + node3->SetStringProperty(mitk::ModelFitConstants::MODEL_FUNCTION_CLASS_PROPERTY_NAME().c_str(),"ModelClass_B"); + + node3->SetStringProperty(mitk::ModelFitConstants::PARAMETER_NAME_PROPERTY_NAME().c_str(),"Param_Other"); + node3->SetStringProperty(mitk::ModelFitConstants::PARAMETER_UNIT_PROPERTY_NAME().c_str(),"a"); + + storage->Add(node3, parents); + + return storage; +} + +int mitkModelFitInfoTest(int /*argc*/, char*[] /*argv[]*/) +{ + MITK_TEST_BEGIN("mitkModelFitTest") + + mitk::modelFit::Parameter::Pointer p = mitk::modelFit::Parameter::New(); + p->name = "p"; + mitk::modelFit::ModelFitInfo::Pointer fit = mitk::modelFit::ModelFitInfo::New(); + fit->AddParameter(p); + MITK_TEST_CONDITION_REQUIRED(fit->GetParameters().size() == 1, + "Testing if AddParameter successfully adds a parameter."); + + mitk::modelFit::Parameter::ConstPointer resultParam = fit->GetParameter("test", + mitk::modelFit::Parameter::ParameterType); + MITK_TEST_CONDITION_REQUIRED(resultParam.IsNull(), + "Testing if GetParameter returns NULL for wrong parameter."); + + resultParam = fit->GetParameter("p", mitk::modelFit::Parameter::ParameterType); + MITK_TEST_CONDITION_REQUIRED(resultParam == p, + "Testing if GetParameter returns the correct parameter."); + + p->type = mitk::modelFit::Parameter::CriterionType; + resultParam = fit->GetParameter("p", mitk::modelFit::Parameter::CriterionType); + MITK_TEST_CONDITION_REQUIRED(resultParam == p, + "Testing if GetParameter returns the correct parameter with a " << + "non-default type."); + + fit->DeleteParameter("test", mitk::modelFit::Parameter::CriterionType); + MITK_TEST_CONDITION_REQUIRED(fit->GetParameters().size() == 1, + "Testing if DeleteParameter fails for wrong parameter."); + + fit->DeleteParameter("p", mitk::modelFit::Parameter::CriterionType); + MITK_TEST_CONDITION_REQUIRED(fit->GetParameters().size() == 0, + "Testing if DeleteParameter successfully removes a parameter."); + + mitk::DataNode::Pointer node = generateModelFitTestNode(); + mitk::DataNode::Pointer invalideNode = mitk::DataNode::New(); + + MITK_TEST_FOR_EXCEPTION(mitk::modelFit::ModelFitException, + mitk::modelFit::GetMandatoryProperty(node.GetPointer(), "modelfit.testInvalid")); + MITK_TEST_FOR_EXCEPTION(mitk::modelFit::ModelFitException, + mitk::modelFit::GetMandatoryProperty(node.GetPointer(), "modelfit.testEmpty")); + + MITK_TEST_CONDITION_REQUIRED(mitk::modelFit::GetMandatoryProperty(node.GetPointer(), "modelfit.testValid") + == "test", + "Testing if GetMandatoryProperty returns the correct value."); + + mitk::StandaloneDataStorage::Pointer storage = generateModelFitTestStorage(); + + MITK_TEST_CONDITION_REQUIRED(mitk::modelFit::CreateFitInfoFromNode("Fit1",NULL).IsNull(), + "Testing if CreateFitInfoFromNode returns NULL for invalid node."); + + MITK_TEST_CONDITION_REQUIRED(mitk::modelFit::CreateFitInfoFromNode("invalide_UID",storage).IsNull(), + "Testing if CreateFitInfoFromNode returns NULL for node with " << + "missing properties."); + + mitk::DataNode::Pointer testNode = storage->GetNamedNode("Param1"); + mitk::modelFit::ModelFitInfo::Pointer resultFit = mitk::modelFit::CreateFitInfoFromNode("Fit1", storage); + MITK_TEST_CONDITION_REQUIRED(resultFit.IsNotNull(), + "Testing if CreateFitInfoFromNode returns a valid model fit info."); + MITK_TEST_CONDITION_REQUIRED(resultFit->fitType == mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED() && + resultFit->uid == "Fit1" && + resultFit->modelType == "TestModels" && + resultFit->modelName == "TestModel_1" && + resultFit->function == ""&& + resultFit->functionClassID == "ModelClass" && + resultFit->x == "myX" && + resultFit->xAxisName == mitk::ModelFitConstants::XAXIS_NAME_VALUE_DEFAULT() && + resultFit->xAxisUnit == "h" && + resultFit->yAxisName == mitk::ModelFitConstants::YAXIS_NAME_VALUE_DEFAULT() && + resultFit->yAxisUnit == "kg" && + resultFit->GetParameters().size() == 2, + "Testing if CreateFitInfoFromNode creates a fit with correct attributes."); + + mitk::modelFit::Parameter::ConstPointer param = resultFit->GetParameter("Param1",mitk::modelFit::Parameter::ParameterType); + MITK_TEST_CONDITION_REQUIRED(param.IsNotNull(), + "Testing if param 1 exists."); + + MITK_TEST_CONDITION_REQUIRED(param->name == "Param1" && param->unit == "b" && param->image == testNode->GetData(), + "Testing if param 1 is configured correctly."); + + mitk::modelFit::Parameter::ConstPointer param2 = resultFit->GetParameter("Param2",mitk::modelFit::Parameter::DerivedType); + MITK_TEST_CONDITION_REQUIRED(param2.IsNotNull(), + "Testing if param 2 exists."); + + testNode = storage->GetNamedNode("Param2"); + MITK_TEST_CONDITION_REQUIRED(param2->name == "Param2" && param2->unit == "a" && param2->image == testNode->GetData(), + "Testing if param 2 is configured correctly."); + + MITK_TEST_CONDITION_REQUIRED(mitk::modelFit::GetNodesOfFit(resultFit->uid,storage)->Size() == 2, + "Testing if GetNodesOfFit works correctly for Fit1"); + + MITK_TEST_CONDITION_REQUIRED(mitk::modelFit::GetNodesOfFit("Fit2",storage)->Size() == 1, + "Testing if GetNodesOfFit works correctly for Fit1"); + + MITK_TEST_CONDITION_REQUIRED(mitk::modelFit::GetNodesOfFit("unkown_fit",storage)->Size() == 0, + "Testing if GetNodesOfFit works correctly for unkown fits."); + + MITK_TEST_CONDITION_REQUIRED(mitk::modelFit::GetNodesOfFit("unkown_fit",NULL).IsNull(), + "Testing if GetNodesOfFit works correctly for illegal calls."); + + testNode = storage->GetNamedNode("Input"); + mitk::modelFit::NodeUIDSetType uidSet = mitk::modelFit::GetFitUIDsOfNode(testNode,storage); + + MITK_TEST_CONDITION_REQUIRED(uidSet.size() == 2 && + uidSet.find("Fit1")!=uidSet.end() && + uidSet.find("Fit2")!=uidSet.end(), + "Testing if GetFitUIDsOfNode works correctly."); + + uidSet = mitk::modelFit::GetFitUIDsOfNode(NULL,storage); + + MITK_TEST_CONDITION_REQUIRED(uidSet.size() == 0, + "Testing if GetFitUIDsOfNode works correctly with invalid node."); + + uidSet = mitk::modelFit::GetFitUIDsOfNode(testNode,NULL); + + MITK_TEST_CONDITION_REQUIRED(uidSet.size() == 0, + "Testing if GetFitUIDsOfNode works correctly with invalid storage."); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkModelFitStaticParameterMapTest.cpp b/Modules/ModelFit/test/mitkModelFitStaticParameterMapTest.cpp new file mode 100644 index 0000000000..11c69f4490 --- /dev/null +++ b/Modules/ModelFit/test/mitkModelFitStaticParameterMapTest.cpp @@ -0,0 +1,121 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkTestingMacros.h" + +#include "mitkModelFitStaticParameterMap.h" +#include "mitkModelFitException.h" + +int mitkModelFitStaticParameterMapTest(int /*argc*/, char*[] /*argv[]*/) +{ + MITK_TEST_BEGIN("mitkModelFitStaticParameterMapTest") + + mitk::modelFit::StaticParameterMap map; + mitk::modelFit::StaticParameterMap::ValueType list; + list.push_back(0); + map.Add("test", list); + MITK_TEST_CONDITION_REQUIRED(map.Get("test").size() == 1 && + map.Get("test").front() == 0, + "Testing if Add successfully adds a new list."); + + map.Add("test", list); + MITK_TEST_CONDITION_REQUIRED(map.Get("test").size() == 1 && + map.Get("test")[0] == 0, + "Testing if Add doesn't add to an existing list."); + + MITK_TEST_FOR_EXCEPTION(std::range_error, map.Get("")); + + mitk::modelFit::StaticParameterMap::ValueType list2; + list2.push_back(3); + map.Add("abc", list2); + MITK_TEST_CONDITION_REQUIRED(map.Get("test").size() == 1 && + map.Get("test").front() == 0 && + map.Get("abc").size() == 1 && + map.Get("abc").front() == 3, + "Testing if Get returns the correct list."); + + list.push_back(1); + map.Add("def", list); + list.push_back(2); + // Adding a list with 3 values when there's already a list with two values + MITK_TEST_FOR_EXCEPTION(mitk::modelFit::ModelFitException, map.Add("ghi", list)); + + map.Clear(); + MITK_TEST_FOR_EXCEPTION(std::range_error, map.Get("test")); + + list2.push_back(5); + list2.push_back(2); + list2.push_back(4); + list2.push_back(1); + mitk::modelFit::StaticParameterMap::ValueType list3; + list3.push_back(3); + list3.push_back(1); + list3.push_back(4); + list3.push_back(2); + list3.push_back(5); + map.Add("abc", list2); + map.Add("def", list3); + map.Sort(); + MITK_TEST_CONDITION_REQUIRED(map.Get("abc")[0] == 1 && + map.Get("abc")[1] == 2 && + map.Get("abc")[2] == 3 && + map.Get("abc")[3] == 4 && + map.Get("abc")[4] == 5 && + map.Get("def")[0] == 5 && + map.Get("def")[1] == 4 && + map.Get("def")[2] == 3 && + map.Get("def")[3] == 2 && + map.Get("def")[4] == 1, + "Testing if Sort successfully sorts by the first key"); + + map.Sort("def"); + MITK_TEST_CONDITION_REQUIRED(map.Get("abc")[0] == 5 && + map.Get("abc")[1] == 4 && + map.Get("abc")[2] == 3 && + map.Get("abc")[3] == 2 && + map.Get("abc")[4] == 1 && + map.Get("def")[0] == 1 && + map.Get("def")[1] == 2 && + map.Get("def")[2] == 3 && + map.Get("def")[3] == 4 && + map.Get("def")[4] == 5, + "Testing if Sort successfully sorts by the given key"); + + mitk::modelFit::StaticParameterMap::ValueType list4; + list4.push_back(0); + map.Clear(); + map.Add("ghi", list4); + map.Add("abc", list2); + map.Add("def", list3); + + map.Sort(); + MITK_TEST_CONDITION_REQUIRED(map.Get("ghi")[0] == 0 && + map.Get("abc")[0] == 1 && + map.Get("abc")[1] == 2 && + map.Get("abc")[2] == 3 && + map.Get("abc")[3] == 4 && + map.Get("abc")[4] == 5 && + map.Get("def")[0] == 5 && + map.Get("def")[1] == 4 && + map.Get("def")[2] == 3 && + map.Get("def")[3] == 2 && + map.Get("def")[4] == 1, + "Testing if Sort successfully sorts if the map includes " << + "one-value-lists"); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkModelFitUIDHelperTest.cpp b/Modules/ModelFit/test/mitkModelFitUIDHelperTest.cpp new file mode 100644 index 0000000000..9e3366f9e3 --- /dev/null +++ b/Modules/ModelFit/test/mitkModelFitUIDHelperTest.cpp @@ -0,0 +1,72 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkTestingMacros.h" +#include "mitkDataNode.h" +#include "mitkStandaloneDataStorage.h" + +#include "mitkModelFitUIDHelper.h" + +int mitkModelFitUIDHelperTest(int /*argc*/, char*[] /*argv[]*/) +{ + MITK_TEST_BEGIN("mitkModelFitUIDHelperTest") + + mitk::DataNode::Pointer node1 = mitk::DataNode::New(); + mitk::DataNode::Pointer node2 = mitk::DataNode::New(); + + mitk::DataNode* nullNode = nullptr; + mitk::BaseData* nullData = nullptr; + + MITK_TEST_FOR_EXCEPTION(mitk::Exception, mitk::EnsureModelFitUID(nullNode)); + MITK_TEST_CONDITION_REQUIRED(mitk::CheckModelFitUID(nullNode,"testUID") == false, + "Testing if CheckModelFitUID fails of null pointer is passed."); + MITK_TEST_FOR_EXCEPTION(mitk::Exception, mitk::EnsureModelFitUID(nullData)); + MITK_TEST_CONDITION_REQUIRED(mitk::CheckModelFitUID(nullData, "testUID") == false, + "Testing if CheckModelFitUID fails of null pointer is passed."); + + mitk::NodeUIDType uid = mitk::EnsureModelFitUID(node1); + + MITK_TEST_CONDITION_REQUIRED(mitk::CheckModelFitUID(node1,"testUID") == false, + "Testing if CheckModelFitUID fails of wrong UID is passed."); + MITK_TEST_CONDITION_REQUIRED(mitk::CheckModelFitUID(node1, uid) == true, + "Testing if CheckModelFitUID succeeds if correct UID is passed."); + + mitk::NodeUIDType uid2ndCall = mitk::EnsureModelFitUID(node1); + + MITK_TEST_CONDITION_REQUIRED(uid == uid2ndCall, + "Testing if EnsureModelFitUID does not create new UIDs on multiple calls."); + + mitk::NodeUIDType uid2 = mitk::EnsureModelFitUID(node2); + + MITK_TEST_CONDITION_REQUIRED(uid != uid2, + "Testing if EnsureModelFitUID does create different UIDs for different nodes."); + + mitk::StandaloneDataStorage::Pointer storage = mitk::StandaloneDataStorage::New(); + storage->Add(node1); + storage->Add(node2); + + MITK_TEST_CONDITION_REQUIRED(node1 == GetNodeByModelFitUID(storage,uid), + "Testing if GetNodeByModelFitUID finds node 1."); + + MITK_TEST_CONDITION_REQUIRED(node2 == GetNodeByModelFitUID(storage,uid2), + "Testing if GetNodeByModelFitUID finds node 2."); + + MITK_TEST_CONDITION_REQUIRED(GetNodeByModelFitUID(storage,"unkown_uid").IsNull(), + "Testing if GetNodeByModelFitUID returns NULL for unkown UID."); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkPixelBasedParameterFitImageGeneratorTest.cpp b/Modules/ModelFit/test/mitkPixelBasedParameterFitImageGeneratorTest.cpp new file mode 100644 index 0000000000..0307dfc745 --- /dev/null +++ b/Modules/ModelFit/test/mitkPixelBasedParameterFitImageGeneratorTest.cpp @@ -0,0 +1,159 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include "itkImageRegionIterator.h" + +#include "mitkTestingMacros.h" +#include "mitkImage.h" +#include "mitkImagePixelReadAccessor.h" + +#include "mitkPixelBasedParameterFitImageGenerator.h" +#include "mitkLinearModelParameterizer.h" + +#include "mitkLevenbergMarquardtModelFitFunctor.h" + +#include "mitkTestArtifactGenerator.h" + +int mitkPixelBasedParameterFitImageGeneratorTest(int /*argc*/, char*[] /*argv[]*/) +{ + // always start with this! + MITK_TEST_BEGIN("mitkPixelBasedParameterFitImageGenerator") + + //Prepare test artifacts and helper + + itk::Index<3> testIndex1; + testIndex1[0] = 0; + testIndex1[1] = 0; + testIndex1[2] = 0; + + itk::Index<3> testIndex2; + testIndex2[0] = 2; + testIndex2[1] = 0; + testIndex2[2] = 1; + + itk::Index<3> testIndex3; + testIndex3[0] = 1; + testIndex3[1] = 1; + testIndex3[2] = 2; + + itk::Index<3> testIndex4; + testIndex4[0] = 2; + testIndex4[1] = 2; + testIndex4[2] = 0; + + itk::Index<3> testIndex5; + testIndex5[0] = 1; + testIndex5[1] = 1; + testIndex5[2] = 1; + + itk::Index<3> testIndex6; + testIndex6[0] = 2; + testIndex6[1] = 1; + testIndex6[2] = 1; + + + mitk::Image::Pointer dynamicImage = mitk::GenerateDynamicTestImageMITK(); + + mitk::LinearModel::Pointer model = mitk::LinearModel::New(); + mitk::LevenbergMarquardtModelFitFunctor::Pointer testFunctor = mitk::LevenbergMarquardtModelFitFunctor::New(); + + //Test default usage of filter + mitk::PixelBasedParameterFitImageGenerator::Pointer generator = mitk::PixelBasedParameterFitImageGenerator::New(); + mitk::LinearModelParameterizer::Pointer parameterizer = mitk::LinearModelParameterizer::New(); + generator->SetDynamicImage(dynamicImage); + generator->SetModelParameterizer(parameterizer); + generator->SetFitFunctor(testFunctor); + + generator->Generate(); + + mitk::PixelBasedParameterFitImageGenerator::ParameterImageMapType resultImages = generator->GetParameterImages(); + mitk::PixelBasedParameterFitImageGenerator::ParameterImageMapType derivedResultImages = generator->GetDerivedParameterImages(); + + CPPUNIT_ASSERT_MESSAGE("Check number of parameter images", 2 == resultImages.size()); + MITK_TEST_CONDITION(resultImages.find("slope") != resultImages.end(),"Check if \"slope\" parameter image exists."); + MITK_TEST_CONDITION(resultImages.find("offset") != resultImages.end(),"Check if \"offset\" parameter image exists."); + CPPUNIT_ASSERT_MESSAGE("Check number of derived parameter images", 1 == derivedResultImages.size()); + MITK_TEST_CONDITION(derivedResultImages.find("x-intercept") != derivedResultImages.end(),"Check if \"x-intercept\" derived parameter image exists."); + + mitk::ImagePixelReadAccessor slopeAccessor(resultImages["slope"]); + mitk::ImagePixelReadAccessor offsetAccessor(resultImages["offset"]); + + double testValue = slopeAccessor.GetPixelByIndex(testIndex1); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #1 (slope) at index #1"); + testValue = slopeAccessor.GetPixelByIndex(testIndex2); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(2000,testValue, 1e-4, true)==true, "Check param #1 (slope) at index #2"); + testValue = slopeAccessor.GetPixelByIndex(testIndex3); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(4000,testValue, 1e-4, true)==true, "Check param #1 (slope) at index #3"); + testValue = slopeAccessor.GetPixelByIndex(testIndex4); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(8000,testValue, 1e-4, true)==true, "Check param #1 (slope) at index #4"); + + testValue = offsetAccessor.GetPixelByIndex(testIndex1); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #1"); + testValue = offsetAccessor.GetPixelByIndex(testIndex2); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(10,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #2"); + testValue = offsetAccessor.GetPixelByIndex(testIndex3); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(20,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #3"); + testValue = offsetAccessor.GetPixelByIndex(testIndex4); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #4"); + + //Test with mask set + mitk::Image::Pointer maskImage = mitk::GenerateTestMaskMITK(); + generator->SetMask(maskImage); + + generator->Generate(); + + resultImages = generator->GetParameterImages(); + derivedResultImages = generator->GetDerivedParameterImages(); + + CPPUNIT_ASSERT_MESSAGE("Check number of parameter images", 2 == resultImages.size()); + MITK_TEST_CONDITION(resultImages.find("slope") != resultImages.end(),"Check if \"slope\" parameter image exists."); + MITK_TEST_CONDITION(resultImages.find("offset") != resultImages.end(),"Check if \"offset\" parameter image exists."); + CPPUNIT_ASSERT_MESSAGE("Check number of derived parameter images", 1 == derivedResultImages.size()); + MITK_TEST_CONDITION(derivedResultImages.find("x-intercept") != derivedResultImages.end(),"Check if \"x-intercept\" derived parameter image exists."); + + mitk::ImagePixelReadAccessor slopeAccessor2(resultImages["slope"]); + mitk::ImagePixelReadAccessor offsetAccessor2(resultImages["offset"]); + + testValue = slopeAccessor2.GetPixelByIndex(testIndex1); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #1 (slope) at index #1"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex2); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(2000,testValue, 1e-4, true)==true, "Check param #1 (slope) at index #2"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex3); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #1 (slope) at index #3"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex4); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(8000,testValue, 1e-4, true)==true, "Check param #1 (slope) at index #4"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex5); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(4000,testValue, 1e-4, true)==true, "Check param #1 (slope) at index #5"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex6); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #1 (slope) at index #6"); + + testValue = offsetAccessor2.GetPixelByIndex(testIndex1); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #1"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex2); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(10,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #2"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex3); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #3"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex4); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #4"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex5); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(10,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #5"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex6); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #6"); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkROIBasedParameterFitImageGeneratorTest.cpp b/Modules/ModelFit/test/mitkROIBasedParameterFitImageGeneratorTest.cpp new file mode 100644 index 0000000000..4df176529a --- /dev/null +++ b/Modules/ModelFit/test/mitkROIBasedParameterFitImageGeneratorTest.cpp @@ -0,0 +1,142 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include "itkImageRegionIterator.h" + +#include "mitkTestingMacros.h" +#include "mitkImage.h" +#include "mitkImagePixelReadAccessor.h" + +#include "mitkROIBasedParameterFitImageGenerator.h" +#include "mitkLinearModelParameterizer.h" + +#include "mitkLevenbergMarquardtModelFitFunctor.h" + +#include "mitkTestArtifactGenerator.h" + +int mitkROIBasedParameterFitImageGeneratorTest(int /*argc*/, char*[] /*argv[]*/) +{ + // always start with this! + MITK_TEST_BEGIN("mitkROIBasedParameterFitImageGenerator") + + //Prepare test artifacts and helper + + itk::Index<3> testIndex1; + testIndex1[0] = 0; + testIndex1[1] = 0; + testIndex1[2] = 0; + + itk::Index<3> testIndex2; + testIndex2[0] = 2; + testIndex2[1] = 0; + testIndex2[2] = 1; + + itk::Index<3> testIndex3; + testIndex3[0] = 1; + testIndex3[1] = 1; + testIndex3[2] = 2; + + itk::Index<3> testIndex4; + testIndex4[0] = 2; + testIndex4[1] = 2; + testIndex4[2] = 0; + + itk::Index<3> testIndex5; + testIndex5[0] = 1; + testIndex5[1] = 1; + testIndex5[2] = 1; + + itk::Index<3> testIndex6; + testIndex6[0] = 2; + testIndex6[1] = 1; + testIndex6[2] = 1; + + + mitk::Image::Pointer maskImage = mitk::GenerateTestMaskMITK(); + + mitk::ROIBasedParameterFitImageGenerator::TimeGridType timeGrid; + timeGrid.SetSize(5); + timeGrid[0] = 0; + timeGrid[1] = 1; + timeGrid[2] = 2; + timeGrid[3] = 3; + timeGrid[4] = 4; + + mitk::ROIBasedParameterFitImageGenerator::SignalType signal; + signal.SetSize(5); + signal[0] = 3; + signal[1] = 5; + signal[2] = 7; + signal[3] = 9; + signal[4] = 11; + + mitk::LinearModel::Pointer model = mitk::LinearModel::New(); + mitk::LevenbergMarquardtModelFitFunctor::Pointer testFunctor = mitk::LevenbergMarquardtModelFitFunctor::New(); + + //Test default usage of filter + mitk::ROIBasedParameterFitImageGenerator::Pointer generator = mitk::ROIBasedParameterFitImageGenerator::New(); + mitk::LinearModelParameterizer::Pointer parameterizer = mitk::LinearModelParameterizer::New(); + + generator->SetModelParameterizer(parameterizer); + generator->SetFitFunctor(testFunctor); + generator->SetMask(maskImage); + generator->SetSignal(signal); + generator->SetTimeGrid(timeGrid); + + generator->Generate(); + + mitk::ROIBasedParameterFitImageGenerator::ParameterImageMapType resultImages = generator->GetParameterImages(); + mitk::ROIBasedParameterFitImageGenerator::ParameterImageMapType derivedResultImages = generator->GetDerivedParameterImages(); + + CPPUNIT_ASSERT_MESSAGE("Check number of parameter images", 2 == resultImages.size()); + MITK_TEST_CONDITION(resultImages.find("slope") != resultImages.end(),"Check if \"slope\" parameter image exists."); + MITK_TEST_CONDITION(resultImages.find("offset") != resultImages.end(),"Check if \"offset\" parameter image exists."); + CPPUNIT_ASSERT_MESSAGE("Check number of derived parameter images", 1 == derivedResultImages.size()); + MITK_TEST_CONDITION(derivedResultImages.find("x-intercept") != derivedResultImages.end(),"Check if \"x-intercept\" derived parameter image exists."); + + mitk::ImagePixelReadAccessor slopeAccessor2(resultImages["slope"]); + mitk::ImagePixelReadAccessor offsetAccessor2(resultImages["offset"]); + + double testValue = slopeAccessor2.GetPixelByIndex(testIndex1); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(2,testValue, 1e-5, true)==true, "Check param #1 (slope) at index #1"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex2); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(2,testValue, 1e-4, true)==true, "Check param #1 (slope) at index #2"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex3); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #1 (slope) at index #3"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex4); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(2,testValue, 1e-4, true)==true, "Check param #1 (slope) at index #4"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex5); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(2,testValue, 1e-4, true)==true, "Check param #1 (slope) at index #5"); + testValue = slopeAccessor2.GetPixelByIndex(testIndex6); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #1 (slope) at index #6"); + + testValue = offsetAccessor2.GetPixelByIndex(testIndex1); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(3,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #1"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex2); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(3,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #2"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex3); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #3"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex4); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(3,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #4"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex5); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(3,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #5"); + testValue = offsetAccessor2.GetPixelByIndex(testIndex6); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0,testValue, 1e-5, true)==true, "Check param #2 (offset) at index #6"); + + MITK_TEST_END() +} diff --git a/Modules/ModelFit/test/mitkSimpleBarrierConstraintCheckerTest.cpp b/Modules/ModelFit/test/mitkSimpleBarrierConstraintCheckerTest.cpp new file mode 100644 index 0000000000..2268455407 --- /dev/null +++ b/Modules/ModelFit/test/mitkSimpleBarrierConstraintCheckerTest.cpp @@ -0,0 +1,171 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkTestingMacros.h" + +#include "mitkSimpleBarrierConstraintChecker.h" +#include "mitkModelFitConstants.h" +#include "mitkModelFitException.h" + +mitk::SimpleBarrierConstraintChecker::ParametersType GenerateParameters(double p1, double p2, double p3) +{ + mitk::SimpleBarrierConstraintChecker::ParametersType result(3); + result[0] = p1; + result[1] = p2; + result[2] = p3; + return result; +} + +int mitkSimpleBarrierConstraintCheckerTest(int /*argc*/, char*[] /*argv[]*/) +{ + MITK_TEST_BEGIN("mitkSimpleBarrierConstraintCheckerTest") + + mitk::SimpleBarrierConstraintChecker::Pointer checker = mitk::SimpleBarrierConstraintChecker::New(); + + //check freshly created checker; + MITK_TEST_CONDITION_REQUIRED(checker->GetNumberOfConstraints() == 0, + "Testing GetNumberOfConstraints for new checker."); + MITK_TEST_CONDITION_REQUIRED(checker->GetFailedConstraintValue() == 1e6, + "Testing GetNumberOfConstraints for new checker."); + MITK_TEST_CONDITION_REQUIRED(checker->GetMaxConstraintPenalty() == 1e6, + "Testing GetNumberOfConstraints for new checker."); + + //configure checker (test setter) + checker->SetLowerBarrier(0,5); + checker->SetLowerBarrier(1,10,3); + checker->SetUpperBarrier(1,100,10); + checker->SetUpperBarrier(2,50); + + typedef mitk::SimpleBarrierConstraintChecker::ParametersType ParametersType; + typedef mitk::SimpleBarrierConstraintChecker::PenaltyArrayType PenaltiesType; + + ParametersType p1 = GenerateParameters(10,30,40); + ParametersType p2 = GenerateParameters(5.0001,30,40); + ParametersType p3 = GenerateParameters(5,30,40); + ParametersType p4 = GenerateParameters(4.5,12,40); + ParametersType p5 = GenerateParameters(10,10,40); + ParametersType p6 = GenerateParameters(10,91,40); + ParametersType p7 = GenerateParameters(10,100,40); + ParametersType p8 = GenerateParameters(1000,30,50); + ParametersType p9 = GenerateParameters(10,30,49.999); + + PenaltiesType penalties = checker->GetPenalties(p1); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(checker->GetPenaltySum(p1) == penalties[0] + penalties[1] + penalties[2] + penalties[3], "Testing penalty sum of test parameters p1."); + + penalties = checker->GetPenalties(p2); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p2."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p2."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p2."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p2."); + MITK_TEST_CONDITION_REQUIRED(checker->GetPenaltySum(p2) == penalties[0] + penalties[1] + penalties[2] + penalties[3], "Testing penalty sum of test parameters p2."); + + penalties = checker->GetPenalties(p3); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 1e6, "Testing penalty 1 of test parameters p3."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p3."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p3."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p3."); + MITK_TEST_CONDITION_REQUIRED(checker->GetPenaltySum(p3) == penalties[0] + penalties[1] + penalties[2] + penalties[3], "Testing penalty sum of test parameters p3."); + + penalties = checker->GetPenalties(p4); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 1e6, "Testing penalty 1 of test parameters p4."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == -1*log(2/3.), "Testing penalty 2 of test parameters p4."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p4."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p4."); + MITK_TEST_CONDITION_REQUIRED(checker->GetPenaltySum(p4) == penalties[0] + penalties[1] + penalties[2] + penalties[3], "Testing penalty sum of test parameters p4."); + + penalties = checker->GetPenalties(p5); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p5."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 1e6, "Testing penalty 2 of test parameters p5."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p5."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p5."); + MITK_TEST_CONDITION_REQUIRED(checker->GetPenaltySum(p5) == penalties[0] + penalties[1] + penalties[2] + penalties[3], "Testing penalty sum of test parameters p5."); + + penalties = checker->GetPenalties(p6); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p6."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p6."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == -1*log(9/10.), "Testing penalty 3 of test parameters p6."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(checker->GetPenaltySum(p6) == penalties[0] + penalties[1] + penalties[2] + penalties[3], "Testing penalty sum of test parameters p6."); + + penalties = checker->GetPenalties(p7); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p7."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p7."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 1e6, "Testing penalty 3 of test parameters p7."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p7."); + MITK_TEST_CONDITION_REQUIRED(checker->GetPenaltySum(p7) == penalties[0] + penalties[1] + penalties[2] + penalties[3], "Testing penalty sum of test parameters p7."); + + penalties = checker->GetPenalties(p8); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p8."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p8."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p8."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 1e6, "Testing penalty 4 of test parameters p8."); + MITK_TEST_CONDITION_REQUIRED(checker->GetPenaltySum(p8) == penalties[0] + penalties[1] + penalties[2] + penalties[3], "Testing penalty sum of test parameters p8."); + + penalties = checker->GetPenalties(p9); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p9."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p9."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p9."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p9."); + MITK_TEST_CONDITION_REQUIRED(checker->GetPenaltySum(p9) == penalties[0] + penalties[1] + penalties[2] + penalties[3], "Testing penalty sum of test parameters p9."); + + checker->SetMaxConstraintPenalty(2222); + penalties = checker->GetPenalties(p8); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 2222, "Testing penalty 3 of test parameters p8 with changed max penalty."); + + mitk::SimpleBarrierConstraintChecker::ParameterIndexVectorType index; + index.push_back(0); + index.push_back(1); + checker->SetLowerSumBarrier(index,37); + + index[0]=1; + index[1]=2; + checker->SetUpperSumBarrier(index,75); + + penalties = checker->GetPenalties(p1); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(penalties[4] == 0.0, "Testing penalty 5 of test parameters p1."); + MITK_TEST_CONDITION_REQUIRED(penalties[5] == 0.0, "Testing penalty 6 of test parameters p1."); + + penalties = checker->GetPenalties(p2); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p2."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p2."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p2."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p2."); + MITK_TEST_CONDITION_REQUIRED(penalties[4] == 2222, "Testing penalty 5 of test parameters p2."); + MITK_TEST_CONDITION_REQUIRED(penalties[5] == 0.0, "Testing penalty 6 of test parameters p2."); + + penalties = checker->GetPenalties(p9); + MITK_TEST_CONDITION_REQUIRED(penalties[0] == 0.0, "Testing penalty 1 of test parameters p9."); + MITK_TEST_CONDITION_REQUIRED(penalties[1] == 0.0, "Testing penalty 2 of test parameters p9."); + MITK_TEST_CONDITION_REQUIRED(penalties[2] == 0.0, "Testing penalty 3 of test parameters p9."); + MITK_TEST_CONDITION_REQUIRED(penalties[3] == 0.0, "Testing penalty 4 of test parameters p9."); + MITK_TEST_CONDITION_REQUIRED(penalties[4] == 0.0, "Testing penalty 5 of test parameters p9."); + MITK_TEST_CONDITION_REQUIRED(penalties[5] == 2222, "Testing penalty 6 of test parameters p9."); + + ParametersType invalidP; + + MITK_TEST_FOR_EXCEPTION(mitk::Exception, checker->GetPenalties(invalidP)); + + MITK_TEST_END() +} diff --git a/Modules/ModelFitUI/CMakeLists.txt b/Modules/ModelFitUI/CMakeLists.txt new file mode 100644 index 0000000000..9eb1272a99 --- /dev/null +++ b/Modules/ModelFitUI/CMakeLists.txt @@ -0,0 +1,6 @@ +MITK_CREATE_MODULE(ModelFitUI + INCLUDE_DIRS Common Qmitk + DEPENDS MitkModelFit MitkQtWidgets MitkQtWidgetsExt + PACKAGE_DEPENDS Qt5|Core CTK|CTKWidgets Boost +WARNINGS_NO_ERRORS +) diff --git a/Modules/ModelFitUI/Qmitk/QmitkInitialValuesDelegate.cpp b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesDelegate.cpp new file mode 100644 index 0000000000..a14673aca4 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesDelegate.cpp @@ -0,0 +1,117 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkInitialValuesDelegate.h" + +#include +#include + +#include +#include +#include +#include +#include + +QmitkInitialValuesDelegate::QmitkInitialValuesDelegate(QObject* /*parent*/) : m_Storage(nullptr), m_Predicate(nullptr) +{ +} + +QWidget* QmitkInitialValuesDelegate::createEditor(QWidget* parent, + const QStyleOptionViewItem& option + , const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.isValid()) + { + if (valueType(index)==0) + { + return QStyledItemDelegate::createEditor(parent, option, index); + } + else + { + QmitkDataStorageComboBox* box = new QmitkDataStorageComboBox(m_Storage, m_Predicate, parent); + + return box; + } + + } + else + { + return new QLabel(data.toString(), parent); + } +} + +int +QmitkInitialValuesDelegate:: +valueType(const QModelIndex& index) const +{ + QVariant data = index.data(Qt::UserRole); + + return data.toInt(); +} + +void QmitkInitialValuesDelegate::setEditorData(QWidget* editor, + const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.isValid()) + { + if (valueType(index) == 0) + { + return QStyledItemDelegate::setEditorData(editor, index); + } + else + { + QmitkDataStorageComboBox* box = qobject_cast(editor); + + mitk::DataNode *node = static_cast(data.value()); + + auto index = box->Find(node); + box->setCurrentIndex(index); + } + } +} + +void QmitkInitialValuesDelegate::setModelData(QWidget* editor, QAbstractItemModel* model + , const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.isValid() && valueType(index) == 1) + { + QmitkDataStorageComboBox* box = qobject_cast(editor); + QVariant newNode = qVariantFromValue(static_cast(box->GetSelectedNode().GetPointer())); + model->setData(index, newNode); + } + else + { + QStyledItemDelegate::setModelData(editor, model, index); + } +} + +void QmitkInitialValuesDelegate:: +setDataStorage(mitk::DataStorage* storage) +{ + this->m_Storage = storage; +}; + +void QmitkInitialValuesDelegate:: +setNodePredicate(mitk::NodePredicateBase* predicate) +{ + this->m_Predicate = predicate; +}; diff --git a/Modules/ModelFitUI/Qmitk/QmitkInitialValuesDelegate.h b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesDelegate.h new file mode 100644 index 0000000000..0016eacecc --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesDelegate.h @@ -0,0 +1,64 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkInitialValuesDelegate_h +#define QmitkInitialValuesDelegate_h + + +/// Toolkit includes. +#include +#include + +#include + +#include "MitkModelFitUIExports.h" + + +/** \class QmitkInitialValuesDelegate +\brief An item delegate for rendering and editing the initial value (source) for a parameter. +The delegate assumes the following: 1) the data requested with the +edit role, will be an double if it is an simple scalar type. If the type is image, +it will be a pointer to the currently selected data node. If nothing is selected now it will be +a nullptr.*/ +class MITKMODELFITUI_EXPORT QmitkInitialValuesDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + + QmitkInitialValuesDelegate(QObject* parent = 0); + + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option + , const QModelIndex& index) const; + + void setEditorData(QWidget* editor, const QModelIndex& index) const; + + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; + + void setDataStorage(mitk::DataStorage* storage); + void setNodePredicate(mitk::NodePredicateBase* predicate); + +protected: + int valueType(const QModelIndex& index) const; + + /**Storage is used as source for potantial initial value images.*/ + mitk::DataStorage::Pointer m_Storage; + /**Predicates that is used to filter for potential/allowed images in the data storage*/ + mitk::NodePredicateBase::Pointer m_Predicate; + +}; + +#endif diff --git a/Modules/ModelFitUI/Qmitk/QmitkInitialValuesManagerWidget.cpp b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesManagerWidget.cpp new file mode 100644 index 0000000000..f0e2407796 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesManagerWidget.cpp @@ -0,0 +1,115 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include +#include +#include +#include +#include + +#include "QmitkInitialValuesManagerWidget.h" +#include "QmitkInitialValuesModel.h" +#include "QmitkInitialValuesTypeDelegate.h" +#include "QmitkInitialValuesDelegate.h" + +QmitkInitialValuesManagerWidget::QmitkInitialValuesManagerWidget(QWidget*) +{ + this->m_Controls.setupUi(this); + + m_InternalModel = new QmitkInitialValuesModel(this); + m_TypeDelegate = new QmitkInitialValuesTypeDelegate(this); + m_ValuesDelegate = new QmitkInitialValuesDelegate(this); + + this->m_Controls.initialsView->setModel(m_InternalModel); + + this->m_Controls.initialsView->setItemDelegateForColumn(1, m_TypeDelegate); + this->m_Controls.initialsView->setItemDelegateForColumn(2, m_ValuesDelegate); + + connect(m_InternalModel, SIGNAL(modelReset()), this, SLOT(OnModelReset())); + + this->update(); +} + +void +QmitkInitialValuesManagerWidget::OnModelReset() +{ + emit initialValuesChanged(); +}; + +QmitkInitialValuesManagerWidget::~QmitkInitialValuesManagerWidget() +{ + delete m_InternalModel; +} + +void QmitkInitialValuesManagerWidget::setInitialValues(const + mitk::ModelTraitsInterface::ParameterNamesType& names, + const mitk::ModelTraitsInterface::ParametersType values) +{ + this->m_InternalModel->setInitialValues(names, values); +} + +void QmitkInitialValuesManagerWidget::setInitialValues(const + mitk::ModelTraitsInterface::ParameterNamesType& names) +{ + this->m_InternalModel->setInitialValues(names); +} + +void QmitkInitialValuesManagerWidget::setDataStorage(mitk::DataStorage* storage) +{ + m_ValuesDelegate->setDataStorage(storage); + this->m_InternalModel->resetInitialParameterImage(); +} + +void QmitkInitialValuesManagerWidget::setReferenceImageGeometry(mitk::BaseGeometry* refgeo) +{ + mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); + mitk::NodePredicateDimension::Pointer is3D = mitk::NodePredicateDimension::New(3); + + if (refgeo) + { + mitk::NodePredicateGeometry::Pointer hasGeo = mitk::NodePredicateGeometry::New(refgeo); + mitk::NodePredicateAnd::Pointer isValidInitialImage = mitk::NodePredicateAnd::New(isImage, hasGeo, is3D); + m_ValuesDelegate->setNodePredicate(isValidInitialImage); + } + else + { + mitk::NodePredicateAnd::Pointer isValidInitialImage = mitk::NodePredicateAnd::New(isImage, is3D); + m_ValuesDelegate->setNodePredicate(isImage); + } + + this->m_InternalModel->resetInitialParameterImage(); +} + +mitk::ModelTraitsInterface::ParametersType +QmitkInitialValuesManagerWidget::getInitialValues() const +{ + return this->m_InternalModel->getInitialValues(); +}; + + +mitk::InitialParameterizationDelegateBase::Pointer +QmitkInitialValuesManagerWidget::getInitialParametrizationDelegate() const +{ + return this->m_InternalModel->getInitialParametrizationDelegate(); +}; + +bool QmitkInitialValuesManagerWidget::hasValidInitialValues() const +{ + return this->m_InternalModel->hasValidInitialValues(); +}; + diff --git a/Modules/ModelFitUI/Qmitk/QmitkInitialValuesManagerWidget.h b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesManagerWidget.h new file mode 100644 index 0000000000..fc2c2c813d --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesManagerWidget.h @@ -0,0 +1,88 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef QMITK_INITIAL_VALUES_MANAGER_WIDGET_H +#define QMITK_INITIAL_VALUES_MANAGER_WIDGET_H + +#include "MitkModelFitUIExports.h" + +#include "ui_QmitkInitialValuesManagerWidget.h" +#include + +#include "mitkModelTraitsInterface.h" +#include "mitkInitialParameterizationDelegateBase.h" + +/*forward declarations*/ +class QmitkInitialValuesModel; +class QmitkInitialValuesTypeDelegate; +class QmitkInitialValuesDelegate; + +namespace mitk +{ + class DataStorage; + class BaseGeometry; +} + +/** +* \class QmitkInitialValuesManagerWidget +* \brief Widget that allows to edit the initial values of an model. +*/ +class MITKMODELFITUI_EXPORT QmitkInitialValuesManagerWidget : public QWidget +{ + Q_OBJECT + +public: + QmitkInitialValuesManagerWidget(QWidget* parent = 0); + ~QmitkInitialValuesManagerWidget(); + + /** Returns the current set initial values of the model.*/ + mitk::ModelTraitsInterface::ParametersType getInitialValues() const; + mitk::InitialParameterizationDelegateBase::Pointer getInitialParametrizationDelegate() const; + + bool hasValidInitialValues() const; + +signals: + void initialValuesChanged(); + +public Q_SLOTS: + /** Sets the names and the values of the initial parameter set for the model. + @param names List of all possible parameter names. It is assumed that the + index of the list equals the parameter index in the respective fitting model and its parameter values. + @values Default values to start with.*/ + void setInitialValues(const mitk::ModelTraitsInterface::ParameterNamesType& names, + const mitk::ModelTraitsInterface::ParametersType values); + void setInitialValues(const mitk::ModelTraitsInterface::ParameterNamesType& names); + + void setDataStorage(mitk::DataStorage* storage); + + void setReferenceImageGeometry(mitk::BaseGeometry* refgeo); + +protected: + + QmitkInitialValuesModel* m_InternalModel; + + QmitkInitialValuesTypeDelegate* m_TypeDelegate; + QmitkInitialValuesDelegate* m_ValuesDelegate; + + Ui::QmitkInitialValuesManagerWidget m_Controls; + +protected Q_SLOTS: + void OnModelReset(); + +}; + +#endif // QmitkInitialValuesManagerWidget_H diff --git a/Modules/ModelFitUI/Qmitk/QmitkInitialValuesManagerWidget.ui b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesManagerWidget.ui new file mode 100644 index 0000000000..c61828ed5f --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesManagerWidget.ui @@ -0,0 +1,50 @@ + + + QmitkInitialValuesManagerWidget + + + + 0 + 0 + 319 + 460 + + + + Form + + + + 3 + + + 5 + + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + + + + + 3 + + + + + + + + diff --git a/Modules/ModelFitUI/Qmitk/QmitkInitialValuesModel.cpp b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesModel.cpp new file mode 100644 index 0000000000..816e41b2b8 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesModel.cpp @@ -0,0 +1,352 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +#include "mitkExceptionMacro.h" +#include "mitkImage.h" +#include "mitkImageBasedParameterizationDelegate.h" + +#include "QmitkInitialValuesModel.h" + + +QmitkInitialValuesModel:: +QmitkInitialValuesModel(QObject* parent) : + QAbstractTableModel(parent), m_modified(false) +{ +} + +void +QmitkInitialValuesModel:: +setInitialValues(const mitk::ModelTraitsInterface::ParameterNamesType& names, + const mitk::ModelTraitsInterface::ParametersType values) +{ + if (names.size() != values.size()) + { + mitkThrow() << + "Error. Cannot set initial value model. Passed parameter names vector and default values vector have different size."; + } + + emit beginResetModel(); + + this->m_ParameterNames = names; + this->m_Values = values; + + this->m_modified = false; + + emit endResetModel(); +}; + +void +QmitkInitialValuesModel:: +setInitialValues(const mitk::ModelTraitsInterface::ParameterNamesType& names) +{ + mitk::ModelTraitsInterface::ParametersType values; + values.set_size(names.size()); + values.fill(0.0); + + setInitialValues(names, values); +}; + +void +QmitkInitialValuesModel:: +addInitialParameterImage(const mitk::DataNode* node, mitk::ModelTraitsInterface::ParametersType::size_type paramIndex) +{ + if (!node) mitkThrow() << "Try to set a null ptr as initial value source image."; + + if (!dynamic_cast(node->GetData())) mitkThrow() << "Error. Passed node does not contain an image."; + + emit beginResetModel(); + + this->m_ParameterImageMap[paramIndex] = node; + + emit endResetModel(); +}; + +void QmitkInitialValuesModel::resetInitialParameterImage() +{ + emit beginResetModel(); + + this->m_ParameterImageMap.clear(); + + emit endResetModel(); +}; + +mitk::ModelTraitsInterface::ParametersType +QmitkInitialValuesModel:: +getInitialValues() const +{ + return this->m_Values; +}; + +mitk::InitialParameterizationDelegateBase::Pointer +QmitkInitialValuesModel:: +getInitialParametrizationDelegate() const +{ + mitk::ImageBasedParameterizationDelegate::Pointer initDelegate = mitk::ImageBasedParameterizationDelegate::New(); + initDelegate->SetInitialParameterization(m_Values); + + for (const auto& pos : this->m_ParameterImageMap) + { + initDelegate->AddInitialParameterImage(dynamic_cast(pos.second->GetData()), pos.first); + } + + return initDelegate.GetPointer(); +}; + +bool +QmitkInitialValuesModel:: +hasValidInitialValues() const +{ + for (const auto& pos : this->m_ParameterImageMap) + { + if (pos.second.IsNull()) return false; + } + return true; +}; + +int +QmitkInitialValuesModel:: +rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) + { + return 0; + } + + return m_Values.size(); +} + +int +QmitkInitialValuesModel:: +columnCount(const QModelIndex& parent) const +{ + if (parent.isValid()) + { + return 0; + } + + return 3; +} + +int +QmitkInitialValuesModel:: +valueType(const QModelIndex& index) const +{ + if (m_ParameterImageMap.find(index.row()) != m_ParameterImageMap.end()) + { //image type + return 1; + } + else + { //simple scalar + return 0; + } +} + +QVariant +QmitkInitialValuesModel:: +data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + { + return QVariant(); + } + + QVariant result; + + if (index.row() < m_Values.size()) + { + switch (index.column()) + { + case 0: + if (role == Qt::DisplayRole || role == Qt::EditRole) + { + result = QVariant(QString::fromStdString(m_ParameterNames[index.row()])); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Name of the parameter."); + } + + break; + + case 1: + if (role == Qt::DisplayRole) + { + if (valueType(index) == 1) + { //image type + result = QVariant("image"); + } + else + { //simple scalar + result = QVariant("scalar"); + } + } + else if (role == Qt::EditRole) + { + result = QVariant(valueType(index)); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("type of the inital value."); + } + break; + + case 2: + if (role == Qt::DisplayRole || role == Qt::EditRole) + { + const auto& finding = m_ParameterImageMap.find(index.row()); + if (finding != m_ParameterImageMap.end()) + { //image type -> return the name + if (finding->second.IsNotNull()) + { + result = QVariant(finding->second->GetName().c_str()); + } + else + { + result = QVariant("Invalid. Select image."); + } + } + else + { //simple scalar + result = QVariant(m_Values(index.row())); + } + } + else if (role == Qt::UserRole) + { + result = QVariant(valueType(index)); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Initial values for the parameter."); + } + + break; + } + } + + return result; +} + +Qt::ItemFlags +QmitkInitialValuesModel:: +flags(const QModelIndex& index) const +{ + Qt::ItemFlags flags = QAbstractItemModel::flags(index); + + if (index.row() < m_Values.size()) + { + if (index.column() > 0) + { + flags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + } + else + { + flags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } + } + + return flags; +} + +QVariant +QmitkInitialValuesModel:: +headerData(int section, Qt::Orientation orientation, int role) const +{ + if ((Qt::DisplayRole == role) && + (Qt::Horizontal == orientation)) + { + if (section == 0) + { + return QVariant("Parameters"); + } + else if (section == 1) + { + return QVariant("Type"); + } + else if (section == 2) + { + return QVariant("Value"); + } + } + + return QVariant(); +} + +bool +QmitkInitialValuesModel:: +setData(const QModelIndex& index, const QVariant& value, int role) +{ + if (!index.isValid() || index.row() >= m_Values.size() || (index.column() == 0)) + { + return false; + } + + if (Qt::EditRole == role) + { + emit dataChanged(index, index); + + emit beginResetModel(); + + bool result = false; + if (index.column() == 1) + { + if (value.toInt() == 0) + { + this->m_ParameterImageMap.erase(index.row()); + m_modified = true; + result = true; + } + else + { + this->m_ParameterImageMap[index.row()] = nullptr; + m_modified = true; + result = true; + } + } + else + { + if (valueType(index) == 0) + { + m_Values[index.row()] = value.toDouble(); + m_modified = true; + result = true; + } + else + { + mitk::DataNode *node = static_cast(value.value()); + if (node && dynamic_cast(node->GetData())) + { + this->m_ParameterImageMap[index.row()] = node; + m_modified = true; + result = true; + } + } + } + + emit endResetModel(); + + return result; + } + + return false; +}; + +bool QmitkInitialValuesModel::isModified() +{ + return m_modified; +} diff --git a/Modules/ModelFitUI/Qmitk/QmitkInitialValuesModel.h b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesModel.h new file mode 100644 index 0000000000..a7f2440c74 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesModel.h @@ -0,0 +1,98 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkInitialValuesModel_h +#define QmitkInitialValuesModel_h + +#include + +#include "mitkSimpleBarrierConstraintChecker.h" +#include "mitkModelTraitsInterface.h" +#include "mitkDataNode.h" +#include "mitkInitialParameterizationDelegateBase.h" + +#include "MitkModelFitUIExports.h" + + +/*! +\class QmitkInitialValuesModel +Model that handles the definition of inital model values. +*/ +class MITKMODELFITUI_EXPORT QmitkInitialValuesModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + QmitkInitialValuesModel(QObject* parent = NULL); + virtual ~QmitkInitialValuesModel() {}; + + /** Sets the names and the values of the initial parameter set for the model. + @param names List of all possible parameter names. It is assumed that the + index of the list equals the parameter index in the respective fitting model and its parameter values. + @values Default values to start with.*/ + void setInitialValues(const mitk::ModelTraitsInterface::ParameterNamesType& names, + const mitk::ModelTraitsInterface::ParametersType values); + /**@overload + Convinience method that sets the default initial values always to zero.*/ + void setInitialValues(const mitk::ModelTraitsInterface::ParameterNamesType& names); + + /** Adds an image as a source for the initial value of a parameter. + * @param node Pointer to the image that is the value source. + * @param paramIndex Indicates which parameter is defined by the source image. + * It equals the position of the vector defined by setInitialValues(). + * @remark setting an image for an index overwrites the value for this index set by + * SetInitialParameterization. + * @pre paramIndex must be in bound of the initial parametrization vector. + * @pre node must be a valid image instance*/ + void addInitialParameterImage(const mitk::DataNode* node, mitk::ModelTraitsInterface::ParametersType::size_type paramIndex); + + bool hasValidInitialValues() const; + + void resetInitialParameterImage(); + + /** Returns a pointer to a delegate instance that represents the parameterization of the model.*/ + mitk::InitialParameterizationDelegateBase::Pointer getInitialParametrizationDelegate() const; + /** Returns the current set initial values of the model. + * @Remark: this are only the simpel scalar initial values. If an source image was set, this is missed here. + * Use getInitialParametrizationDelegate() to get everything at once.*/ + mitk::ModelTraitsInterface::ParametersType getInitialValues() const; + + virtual Qt::ItemFlags flags(const QModelIndex& index) const; + virtual QVariant data(const QModelIndex& index, int role) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + + /**Indicates if the content of the model was modified since the data was set via setInitialValues()*/ + bool isModified(); + +private: + int valueType(const QModelIndex& index) const; + + mitk::ModelTraitsInterface::ParametersType m_Values; + mitk::ModelTraitsInterface::ParameterNamesType m_ParameterNames; + + typedef std::map ImageMapType; + ImageMapType m_ParameterImageMap; + + /** Indicates if the data of the model was modified, since the model was set. */ + bool m_modified; + +}; + +#endif // QmitkInitialValuesModel_h + diff --git a/Modules/ModelFitUI/Qmitk/QmitkInitialValuesTypeDelegate.cpp b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesTypeDelegate.cpp new file mode 100644 index 0000000000..c1592e67fc --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesTypeDelegate.cpp @@ -0,0 +1,90 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkInitialValuesTypeDelegate.h" + +#include +#include +#include +#include + +QmitkInitialValuesTypeDelegate::QmitkInitialValuesTypeDelegate(QObject* /*parent*/) +{ +} + +QWidget* QmitkInitialValuesTypeDelegate::createEditor(QWidget* parent, + const QStyleOptionViewItem& option + , const QModelIndex& index) const +{ + QVariant displayData = index.data(Qt::DisplayRole); + QVariant data = index.data(Qt::EditRole); + + if (data.isValid()) + { + QComboBox* cmbBox = new QComboBox(parent); + cmbBox->addItem(QString("scalar")); + cmbBox->addItem(QString("image")); + cmbBox->setCurrentIndex(0); + + cmbBox->installEventFilter(const_cast(this)); + + return cmbBox; + } + else + { + return new QLabel(displayData.toString(), parent); + } + +} + +void QmitkInitialValuesTypeDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.isValid()) + { + + QComboBox* cmbBox = qobject_cast(editor); + + if (cmbBox) + { + cmbBox->setCurrentIndex(data.toInt()); + } + else + { + QStyledItemDelegate::setEditorData(editor, index); + } + } +} + +void QmitkInitialValuesTypeDelegate::setModelData(QWidget* editor, QAbstractItemModel* model + , const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.isValid()) + { + QComboBox* cmbBox = qobject_cast(editor); + int selection = cmbBox->currentIndex(); + + QVariant selectionVariant(selection); + model->setData(index, selectionVariant); + } + else + { + QStyledItemDelegate::setModelData(editor, model, index); + } +} diff --git a/Modules/ModelFitUI/Qmitk/QmitkInitialValuesTypeDelegate.h b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesTypeDelegate.h new file mode 100644 index 0000000000..29850b7bb8 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkInitialValuesTypeDelegate.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkInitialValuesTypeDelegate_h +#define QmitkInitialValuesTypeDelegate_h + + +#include + +#include "MitkModelFitUIExports.h" + + +/** \class QmitkInitialValuesTypeDelegate +\brief An item delegate for rendering and editing the type of a initial value. +It assumes that the type is encoded as int. 0: simple scalar, 1: image.*/ +class MITKMODELFITUI_EXPORT QmitkInitialValuesTypeDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + + QmitkInitialValuesTypeDelegate(QObject* parent = 0); + + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option + , const QModelIndex& index) const; + + void setEditorData(QWidget* editor, const QModelIndex& index) const; + + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; +}; + +#endif diff --git a/Modules/ModelFitUI/Qmitk/QmitkParameterFitBackgroundJob.cpp b/Modules/ModelFitUI/Qmitk/QmitkParameterFitBackgroundJob.cpp new file mode 100644 index 0000000000..560c5245ca --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkParameterFitBackgroundJob.cpp @@ -0,0 +1,110 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Software Development for +Integrated Diagnostic and Therapy. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#include "QmitkParameterFitBackgroundJob.h" +#include "mitkModelFitInfo.h" + +void ParameterFitBackgroundJob::OnFitEvent(::itk::Object* caller, const itk::EventObject & event) +{ + itk::ProgressEvent progressEvent; + itk::InitializeEvent initEvent; + itk::StartEvent startEvent; + itk::EndEvent endEvent; + + if (progressEvent.CheckEvent(&event)) + { + mitk::ParameterFitImageGeneratorBase* castedReporter = dynamic_cast(caller); + emit JobProgress(castedReporter->GetProgress()); + } + else if (initEvent.CheckEvent(&event)) + { + emit JobStatusChanged(QString("Initializing parameter fit generator")); + } + else if (startEvent.CheckEvent(&event)) + { + emit JobStatusChanged(QString("Started fitting process.")); + } + else if (endEvent.CheckEvent(&event)) + { + emit JobStatusChanged(QString("Finished fitting process.")); + } +} + +ParameterFitBackgroundJob:: +ParameterFitBackgroundJob(mitk::ParameterFitImageGeneratorBase* generator, const mitk::modelFit::ModelFitInfo* fitInfo, const std::string& fitName, mitk::DataNode* parentNode) +{ + if (!generator) + { + mitkThrow() << "Cannot create parameter fit background job. Passed fit generator is NULL."; + } + + if (!fitInfo) + { + mitkThrow() << "Cannot create parameter fit background job. Passed model traits interface is NULL."; + } + + m_Generator = generator; + m_ModelFitInfo = fitInfo; + m_FitName = fitName; + m_ParentNode = parentNode; + + m_spCommand = ::itk::MemberCommand::New(); + m_spCommand->SetCallbackFunction(this, &ParameterFitBackgroundJob::OnFitEvent); + m_ObserverID = m_Generator->AddObserver(::itk::AnyEvent(), m_spCommand); +}; + +mitk::DataNode* + ParameterFitBackgroundJob:: +GetParentNode() const +{ + return m_ParentNode; +}; + +ParameterFitBackgroundJob:: +~ParameterFitBackgroundJob() +{ + m_Generator->RemoveObserver(m_ObserverID); +}; + +void +ParameterFitBackgroundJob:: +run() +{ + try + { + emit JobStatusChanged(QString("Started fit session.Generate UID: ")+QString::fromStdString(m_ModelFitInfo->uid)); + + m_Generator->Generate(); + + emit JobStatusChanged(QString("Generate result nodes.")); + + m_Results = mitk::modelFit::CreateResultNodeMap(m_Generator->GetParameterImages(), m_Generator->GetDerivedParameterImages(), m_Generator->GetCriterionImages(), m_Generator->GetEvaluationParameterImages(), m_ModelFitInfo, m_FitName); + + emit ResultsAreAvailable(m_Results, this); + } + catch (::std::exception& e) + { + emit Error(QString("Error while fitting data. Details: ")+QString::fromLatin1(e.what())); + } + catch (...) + { + emit Error(QString("Unkown error when fitting the data.")); + } + + emit Finished(); +}; diff --git a/Modules/ModelFitUI/Qmitk/QmitkParameterFitBackgroundJob.h b/Modules/ModelFitUI/Qmitk/QmitkParameterFitBackgroundJob.h new file mode 100644 index 0000000000..5a320840e8 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkParameterFitBackgroundJob.h @@ -0,0 +1,81 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Software Development for +Integrated Diagnostic and Therapy. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef __QMITK_PARAMETER_FIT_BACKGROUND_JOB_H +#define __QMITK_PARAMETER_FIT_BACKGROUND_JOB_H + + +//QT +#include +#include + +//MITK +#include + +#include +#include +#include + +// ITK +#include + +#include "MitkModelFitUIExports.h" + +class MITKMODELFITUI_EXPORT ParameterFitBackgroundJob : public QObject, public QRunnable +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + +public: + ParameterFitBackgroundJob(mitk::ParameterFitImageGeneratorBase* generator, const mitk::modelFit::ModelFitInfo* fitInfo, const std::string& fitName ="", mitk::DataNode* parentNode = NULL); + ~ParameterFitBackgroundJob(); + + void run(); + + /**Returns the node (if defined), that is the parent object for the results of the job. + May be null.*/ + mitk::DataNode* GetParentNode() const; + +signals: + void Finished(); + void Error(QString err); + void ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType resultMap, const ParameterFitBackgroundJob* pJob); + void JobProgress(double progress); + void JobStatusChanged(QString info); + +protected: + //Inputs + mitk::ParameterFitImageGeneratorBase::Pointer m_Generator; + mitk::modelFit::ModelFitInfo::ConstPointer m_ModelFitInfo; + mitk::DataNode::Pointer m_ParentNode; + + //job settings + std::string m_FitName; + + // Results + mitk::modelFit::ModelFitResultNodeVectorType m_Results; + + ::itk::MemberCommand::Pointer m_spCommand; + unsigned long m_ObserverID; + + void OnFitEvent(::itk::Object *, const itk::EventObject &event); +}; + +#endif + diff --git a/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierManagerWidget.cpp b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierManagerWidget.cpp new file mode 100644 index 0000000000..66d0192ea2 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierManagerWidget.cpp @@ -0,0 +1,105 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include "QmitkSimpleBarrierManagerWidget.h" +#include "QmitkSimpleBarrierModel.h" +#include "QmitkSimpleBarrierParametersDelegate.h" +#include "QmitkSimpleBarrierTypeDelegate.h" + +QmitkSimpleBarrierManagerWidget::QmitkSimpleBarrierManagerWidget(QWidget*): m_InternalUpdate(false) +{ + this->m_Controls.setupUi(this); + + m_InternalModel = new QmitkSimpleBarrierModel(this); + m_TypeDelegate = new QmitkSimpleBarrierTypeDelegate(this); + m_ParametersDelegate = new QmitkSimpleBarrierParametersDelegate(this); + + this->m_Controls.constraintsView->setModel(m_InternalModel); + this->m_Controls.constraintsView->setItemDelegateForColumn(0, m_ParametersDelegate); + this->m_Controls.constraintsView->setItemDelegateForColumn(1, m_TypeDelegate); + this->m_Controls.constraintsView->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(this->m_Controls.btnAdd, SIGNAL(clicked(bool)), this, SLOT(OnAddConstraint(bool))); + connect(this->m_Controls.btnDel, SIGNAL(clicked(bool)), this, SLOT(OnDelConstraint(bool))); + connect(m_Controls.constraintsView, SIGNAL(customContextMenuRequested(const QPoint&)), this, + SLOT(OnShowContextMenuIsoSet(const QPoint&))); + + this->update(); +} + +QmitkSimpleBarrierManagerWidget::~QmitkSimpleBarrierManagerWidget() +{ + delete m_InternalModel; + delete m_TypeDelegate; + delete m_ParametersDelegate; +} + +void QmitkSimpleBarrierManagerWidget::setChecker(mitk::SimpleBarrierConstraintChecker* pChecker, + const mitk::ModelTraitsInterface::ParameterNamesType& names) +{ + this->m_Checker = pChecker; + this->m_ParameterNames = names; + this->m_InternalModel->setChecker(m_Checker, names); + update(); +} + +void QmitkSimpleBarrierManagerWidget::OnShowContextMenuIsoSet(const QPoint& pos) +{ + QPoint globalPos = m_Controls.constraintsView->viewport()->mapToGlobal(pos); + + QModelIndex selectedIndex = m_Controls.constraintsView->currentIndex(); + + QMenu viewMenu; + QAction* addLevelAct = viewMenu.addAction("Add new constraint"); + QAction* delLevelAct = viewMenu.addAction("Delete selected constraint"); + delLevelAct->setEnabled(selectedIndex.isValid()); + + QAction* selectedItem = viewMenu.exec(globalPos); + + if (selectedItem == addLevelAct) + { + this->m_InternalModel->addConstraint(); + } + else if (selectedItem == delLevelAct) + { + this->m_InternalModel->deleteConstraint(selectedIndex); + } +} + +void QmitkSimpleBarrierManagerWidget::OnAddConstraint(bool checked) +{ + this->m_InternalModel->addConstraint(); +} + +void QmitkSimpleBarrierManagerWidget::OnDelConstraint(bool checked) +{ + QModelIndex selectedIndex = m_Controls.constraintsView->currentIndex(); + + if (!selectedIndex.isValid()) + { + selectedIndex = m_Controls.constraintsView->indexAt(QPoint(1, 1)); + } + + this->m_InternalModel->deleteConstraint(selectedIndex); +} + +void QmitkSimpleBarrierManagerWidget:: +update() +{ + +}; diff --git a/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierManagerWidget.h b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierManagerWidget.h new file mode 100644 index 0000000000..4f079d7a28 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierManagerWidget.h @@ -0,0 +1,81 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef QMITK_SIMPLE_BARRIER_MANAGER_WIDGET_H +#define QMITK_SIMPLE_BARRIER_MANAGER_WIDGET_H + +#include "MitkModelFitUIExports.h" + +#include "ui_QmitkSimpleBarrierManagerWidget.h" +#include + +#include "mitkSimpleBarrierConstraintChecker.h" + +/*forward declarations*/ +class QmitkSimpleBarrierParametersDelegate; +class QmitkSimpleBarrierTypeDelegate; +class QmitkSimpleBarrierModel; + +/** +* \class QmitkSimpleBarrierManagerWidget +* \brief Widget that allows to edit the constraints of SimpleBarrierConstraintChecker. +*/ +class MITKMODELFITUI_EXPORT QmitkSimpleBarrierManagerWidget : public QWidget +{ + Q_OBJECT + +public: + QmitkSimpleBarrierManagerWidget(QWidget* parent = 0); + ~QmitkSimpleBarrierManagerWidget(); + +signals: + void ConstraintChanged(mitk::SimpleBarrierConstraintChecker::Constraint constraint); + +public Q_SLOTS: + /** Sets the data handled by the model and resets the modified flag + @param pChecker Pointer to the checker instance that should be managed. + @param names List of all possible parameter names. It is assumed that the + index of the list equals the parameter index in the respective fitting model.*/ + void setChecker(mitk::SimpleBarrierConstraintChecker* pChecker, + const mitk::ModelTraitsInterface::ParameterNamesType& names); + +protected Q_SLOTS: + void OnShowContextMenuIsoSet(const QPoint& pos); + void OnAddConstraint(bool checked); + void OnDelConstraint(bool checked); + +protected: + + /** + * \brief Updates the widget according to its current settings. + */ + void update(); + + mitk::SimpleBarrierConstraintChecker::Pointer m_Checker; + mitk::ModelTraitsInterface::ParameterNamesType m_ParameterNames; + + QmitkSimpleBarrierModel* m_InternalModel; + QmitkSimpleBarrierTypeDelegate* m_TypeDelegate; + QmitkSimpleBarrierParametersDelegate* m_ParametersDelegate; + + bool m_InternalUpdate; + + Ui::QmitkSimpleBarrierManagerWidget m_Controls; + +}; + +#endif // QmitkSimpleBarrierManagerWidget_H diff --git a/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierManagerWidget.ui b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierManagerWidget.ui new file mode 100644 index 0000000000..e40229be44 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierManagerWidget.ui @@ -0,0 +1,64 @@ + + + QmitkSimpleBarrierManagerWidget + + + + 0 + 0 + 200 + 300 + + + + Form + + + + 3 + + + 5 + + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + + + + + 3 + + + + + + + + + + + + + - + + + + + + + + + + diff --git a/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierModel.cpp b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierModel.cpp new file mode 100644 index 0000000000..70d7f0b351 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierModel.cpp @@ -0,0 +1,328 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +#include "QmitkSimpleBarrierModel.h" + +const int NUMBER_OF_CONSTRAINT_ASPECTS = 4; +const int INDEX_CONSTRAINT_PARAMS = 0; +const int INDEX_CONSTRAINT_TYPE = 1; +const int INDEX_CONSTRAINT_THRESHOLD = 2; +const int INDEX_CONSTRAINT_WIDTH = 3; + +QmitkSimpleBarrierModel:: +QmitkSimpleBarrierModel(QObject* parent) : + QAbstractTableModel(parent), m_modified(false) +{ + m_Checker = mitk::SimpleBarrierConstraintChecker::New(); +} + +void +QmitkSimpleBarrierModel:: +setChecker(mitk::SimpleBarrierConstraintChecker* pChecker, + const mitk::ModelTraitsInterface::ParameterNamesType& names) +{ + if (pChecker != m_Checker) + { + emit beginResetModel(); + + if (pChecker) + { + m_Checker = pChecker; + } + else + { + m_Checker = mitk::SimpleBarrierConstraintChecker::New(); + } + + m_ParameterNames = names; + m_modified = false; + + emit endResetModel(); + } +}; + +int +QmitkSimpleBarrierModel:: +rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) + { + return 0; + } + + return m_Checker->GetNumberOfConstraints(); +} + +int +QmitkSimpleBarrierModel:: +columnCount(const QModelIndex& parent) const +{ + if (parent.isValid()) + { + return 0; + } + + return NUMBER_OF_CONSTRAINT_ASPECTS; +} + +QVariant +QmitkSimpleBarrierModel:: +data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + { + return QVariant(); + } + + QVariant result; + + if (index.row() < m_Checker->GetNumberOfConstraints()) + { + const mitk::SimpleBarrierConstraintChecker::Constraint constraint = m_Checker->GetConstraint( + static_cast(index.row())); + + switch (index.column()) + { + case INDEX_CONSTRAINT_PARAMS: + if (role == Qt::DisplayRole) + { + QStringList names; + + for (mitk::SimpleBarrierConstraintChecker::ParameterIndexVectorType::const_iterator pos = + constraint.parameters.begin(); pos != constraint.parameters.end(); ++pos) + { + names.append(QString::fromStdString(this->m_ParameterNames[*pos])); + } + + result = QVariant(names); + } + else if (role == Qt::EditRole) + { + QStringList names; + + for (mitk::ModelTraitsInterface::ParameterNamesType::const_iterator pos = + this->m_ParameterNames.begin(); pos != this->m_ParameterNames.end(); ++pos) + { + names.append(QString::fromStdString(*pos)); + } + + result = QVariant(names); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Parameters that are relevant for this constraint. If more then one parameter is specified, it is the sum of all parameters."); + } + + break; + + case INDEX_CONSTRAINT_TYPE: + if (role == Qt::DisplayRole) + { + if (constraint.upperBarrier) + { + result = QVariant(QString("upper")); + } + else + { + result = QVariant(QString("lower")); + } + } + else if (role == Qt::EditRole) + { + if (constraint.upperBarrier) + { + result = QVariant(1); + } + else + { + result = QVariant(0); + } + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Type of boundary constraint."); + } + + break; + + case INDEX_CONSTRAINT_THRESHOLD: + if (role == Qt::DisplayRole || role == Qt::EditRole) + { + result = QVariant(constraint.barrier); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Barrier value for the constraint."); + } + + break; + + case INDEX_CONSTRAINT_WIDTH: + if (role == Qt::DisplayRole || role == Qt::EditRole) + { + result = QVariant(constraint.width); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Width of the penalty zone before the barrier value. Must be >=0.0."); + } + + break; + } + } + + return result; +} + +Qt::ItemFlags +QmitkSimpleBarrierModel:: +flags(const QModelIndex& index) const +{ + Qt::ItemFlags flags = QAbstractItemModel::flags(index); + + if (index.row() < m_Checker->GetNumberOfConstraints()) + { + if (index.column() < NUMBER_OF_CONSTRAINT_ASPECTS && index.column() >= 0) + { + flags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + } + } + + return flags; +} + +QVariant +QmitkSimpleBarrierModel:: +headerData(int section, Qt::Orientation orientation, int role) const +{ + if ((Qt::DisplayRole == role) && + (Qt::Horizontal == orientation)) + { + if (section == INDEX_CONSTRAINT_PARAMS) + { + return QVariant("Parameters"); + } + else if (section == INDEX_CONSTRAINT_TYPE) + { + return QVariant("Type"); + } + else if (section == INDEX_CONSTRAINT_THRESHOLD) + { + return QVariant("Value"); + } + else if (section == INDEX_CONSTRAINT_WIDTH) + { + return QVariant("Width"); + } + } + + return QVariant(); +} + +bool +QmitkSimpleBarrierModel:: +setData(const QModelIndex& index, const QVariant& value, int role) +{ + if (!index.isValid() || (m_Checker->GetNumberOfConstraints() <= index.row()) + || (index.column() >= NUMBER_OF_CONSTRAINT_ASPECTS)) + { + return false; + } + + if (Qt::EditRole == role) + { + mitk::SimpleBarrierConstraintChecker::Constraint constraint = m_Checker->GetConstraint( + static_cast(index.row())); + + switch (index.column()) + { + case 0: + { + QStringList selectedNames = value.toStringList(); + constraint.parameters.clear(); + + for (mitk::SimpleBarrierConstraintChecker::ParameterIndexVectorType::size_type pos = 0; + pos < this->m_ParameterNames.size(); ++pos) + { + if (selectedNames.contains(QString::fromStdString(this->m_ParameterNames[pos]))) + { + constraint.parameters.push_back(pos); + } + } + + emit dataChanged(index, index); + break; + } + + case 1: + constraint.upperBarrier = value.toInt() == 1; + emit dataChanged(index, index); + break; + + case 2: + constraint.barrier = value.toDouble(); + emit dataChanged(index, index); + break; + + case 3: + constraint.width = value.toDouble(); + emit dataChanged(index, index); + break; + } + + emit beginResetModel(); + + m_Checker->GetConstraint(static_cast(index.row())) = constraint; + + m_modified = true; + + emit endResetModel(); + + return true; + } + + return false; +}; + +void QmitkSimpleBarrierModel::addConstraint() +{ + emit beginResetModel(); + m_Checker->SetLowerBarrier(0, 0.0); + m_modified = true; + emit endResetModel(); +} + +void QmitkSimpleBarrierModel::deleteConstraint(const QModelIndex& index) +{ + if (!index.isValid() || (m_Checker->GetNumberOfConstraints() <= index.row()) + || (index.column() >= NUMBER_OF_CONSTRAINT_ASPECTS)) + { + return; + } + + emit beginResetModel(); + m_Checker->DeleteConstraint(static_cast(index.row())); + m_modified = true; + emit endResetModel(); +} + +bool QmitkSimpleBarrierModel::isModified() +{ + return m_modified; +} diff --git a/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierModel.h b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierModel.h new file mode 100644 index 0000000000..8ba77c9dff --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierModel.h @@ -0,0 +1,72 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkSimpleBarrierModel_h +#define QmitkSimpleBarrierModel_h + +#include + +#include "mitkSimpleBarrierConstraintChecker.h" +#include "mitkModelTraitsInterface.h" + +#include "MitkModelFitUIExports.h" + + +/*! +\class QmitkSimpleBarrierModel +Model that handles a SimpleBarrierConstraintChecker and his defined constraints. +It allows to couple a SimpleBarrierConstraintChecker with a Qt table view in +Order to view and edit its contents. E.g. used in the QmitkSimpleBarrierManagerWidget. +*/ +class MITKMODELFITUI_EXPORT QmitkSimpleBarrierModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + QmitkSimpleBarrierModel(QObject* parent = NULL); + virtual ~QmitkSimpleBarrierModel() {}; + + /** Sets the data handled by the model and resets the modified flag + @param pChecker Pointer to the checker instance that should be managed. + @param names List of all possible parameter names. It is assumed that the + index of the list equals the parameter index in the respective fitting model.*/ + void setChecker(mitk::SimpleBarrierConstraintChecker* pChecker, + const mitk::ModelTraitsInterface::ParameterNamesType& names); + + virtual Qt::ItemFlags flags(const QModelIndex& index) const; + virtual QVariant data(const QModelIndex& index, int role) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + + void addConstraint(); + void deleteConstraint(const QModelIndex& index); + + /**Indicates if the content of the model was modified since the data was set via setChecker()*/ + bool isModified(); + +private: + mitk::SimpleBarrierConstraintChecker::Pointer m_Checker; + mitk::ModelTraitsInterface::ParameterNamesType m_ParameterNames; + + /** Indicates if the data of the model was modified, since the model was set. */ + bool m_modified; + +}; + +#endif // QmitkSimpleBarrierModel_h + diff --git a/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierParametersDelegate.cpp b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierParametersDelegate.cpp new file mode 100644 index 0000000000..187fa34b47 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierParametersDelegate.cpp @@ -0,0 +1,152 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkSimpleBarrierParametersDelegate.h" + +#include +#include +#include +#include +#include + +QmitkSimpleBarrierParametersDelegate::QmitkSimpleBarrierParametersDelegate(QObject* /*parent*/) +{ +} + +void QmitkSimpleBarrierParametersDelegate::paint(QPainter* painter, + const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + QVariant data = index.data(Qt::DisplayRole); + QStyleOptionViewItemV4 opt = option; + initStyleOption(&opt, index); + QStyle* style = QApplication::style(); + + QString text = "Invalid data"; + + if (data.isValid()) + { + QStringList names = data.toStringList(); + text.clear(); + + for (QStringList::const_iterator pos = names.begin(); pos != names.end(); ++pos) + { + if (pos != names.begin()) + { + text.append(", "); + } + + text.append(*pos); + } + } + + style->drawItemText(painter, opt.rect.adjusted(0, 0, -5, 0), Qt::AlignRight | Qt::AlignVCenter, + opt.palette, true, text); +} + +QWidget* QmitkSimpleBarrierParametersDelegate::createEditor(QWidget* parent, + const QStyleOptionViewItem& option + , const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + QVariant displayData = index.data(Qt::DisplayRole); + + if (data.isValid()) + { + QListWidget* list = new QListWidget(parent); + list->setFixedSize(100, 100); + + list->installEventFilter(const_cast(this)); + + return list; + + } + else + { + return new QLabel(displayData.toString(), parent); + } +} + +void QmitkSimpleBarrierParametersDelegate::setEditorData(QWidget* editor, + const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + QVariant displayData = index.data(Qt::DisplayRole); + + if (data.isValid() && displayData.isValid()) + { + + QListWidget* list = qobject_cast(editor); + + if (list) + { + list->clear(); + + QStringList names = data.toStringList(); + QStringList checkedNames = displayData.toStringList(); + + for (QStringList::const_iterator pos = names.begin(); pos != names.end(); ++pos) + { + QListWidgetItem* item = new QListWidgetItem(*pos, list); + item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + + if (checkedNames.contains(*pos)) + { + item->setCheckState(Qt::Checked); + } + else + { + item->setCheckState(Qt::Unchecked); + } + } + } + else + { + QStyledItemDelegate::setEditorData(editor, index); + } + } +} + +void QmitkSimpleBarrierParametersDelegate::setModelData(QWidget* editor, QAbstractItemModel* model + , const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.isValid()) + { + QListWidget* list = qobject_cast(editor); + QStringList selectedItems; + + if (list) + { + for (int row = 0; row < list->count(); ++row) + { + QListWidgetItem* item = list->item(row); + + if (item->checkState() == Qt::Checked) + { + selectedItems.append(item->text()); + } + } + } + + QVariant selectedVariant(selectedItems); + model->setData(index, selectedVariant); + } + else + { + QStyledItemDelegate::setModelData(editor, model, index); + } +} \ No newline at end of file diff --git a/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierParametersDelegate.h b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierParametersDelegate.h new file mode 100644 index 0000000000..8489fbd412 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierParametersDelegate.h @@ -0,0 +1,53 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkSimpleBarrierParametersDelegate_h +#define QmitkSimpleBarrierParametersDelegate_h + + +/// Toolkit includes. +#include + +#include "MitkModelFitUIExports.h" + + +/** \class QmitkSimpleBarrierParametersDelegate +\brief An item delegate for rendering and editing the parameters relevant for +a barrier constraint. The delegate assumes the following: 1) if the data is requested with the +edit role, it gets a string list of all possible options. 2) if the data is requested with the +display role it gets only a list of all currently selected options. +If the data is transfered back to the model it contains all selected parameter names in a string list.*/ +class MITKMODELFITUI_EXPORT QmitkSimpleBarrierParametersDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + + QmitkSimpleBarrierParametersDelegate(QObject* parent = 0); + + void paint(QPainter* painter, const QStyleOptionViewItem& option + , const QModelIndex& index) const; + + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option + , const QModelIndex& index) const; + + void setEditorData(QWidget* editor, const QModelIndex& index) const; + + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; + +}; + +#endif diff --git a/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierTypeDelegate.cpp b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierTypeDelegate.cpp new file mode 100644 index 0000000000..065c6c4674 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierTypeDelegate.cpp @@ -0,0 +1,90 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkSimpleBarrierTypeDelegate.h" + +#include +#include +#include +#include + +QmitkSimpleBarrierTypeDelegate::QmitkSimpleBarrierTypeDelegate(QObject* /*parent*/) +{ +} + +QWidget* QmitkSimpleBarrierTypeDelegate::createEditor(QWidget* parent, + const QStyleOptionViewItem& option + , const QModelIndex& index) const +{ + QVariant displayData = index.data(Qt::DisplayRole); + QVariant data = index.data(Qt::EditRole); + + if (data.isValid()) + { + QComboBox* cmbBox = new QComboBox(parent); + cmbBox->addItem(QString("lower")); + cmbBox->addItem(QString("upper")); + cmbBox->setCurrentIndex(0); + + cmbBox->installEventFilter(const_cast(this)); + + return cmbBox; + } + else + { + return new QLabel(displayData.toString(), parent); + } + +} + +void QmitkSimpleBarrierTypeDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.isValid()) + { + + QComboBox* cmbBox = qobject_cast(editor); + + if (cmbBox) + { + cmbBox->setCurrentIndex(data.toInt()); + } + else + { + QStyledItemDelegate::setEditorData(editor, index); + } + } +} + +void QmitkSimpleBarrierTypeDelegate::setModelData(QWidget* editor, QAbstractItemModel* model + , const QModelIndex& index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.isValid()) + { + QComboBox* cmbBox = qobject_cast(editor); + int selection = cmbBox->currentIndex(); + + QVariant selectionVariant(selection); + model->setData(index, selectionVariant); + } + else + { + QStyledItemDelegate::setModelData(editor, model, index); + } +} diff --git a/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierTypeDelegate.h b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierTypeDelegate.h new file mode 100644 index 0000000000..8bab74cee0 --- /dev/null +++ b/Modules/ModelFitUI/Qmitk/QmitkSimpleBarrierTypeDelegate.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkSimpleBarrierTypeDelegate_h +#define QmitkSimpleBarrierTypeDelegate_h + + +#include + +#include "MitkModelFitUIExports.h" + + +/** \class QmitkSimpleBarrierTypeDelegate +\brief An item delegate for rendering and editing the type of a simple barrier constraint. +It assumes that the type is encoded as int. 0: lower border, 1: upper border.*/ +class MITKMODELFITUI_EXPORT QmitkSimpleBarrierTypeDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + + QmitkSimpleBarrierTypeDelegate(QObject* parent = 0); + + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option + , const QModelIndex& index) const; + + void setEditorData(QWidget* editor, const QModelIndex& index) const; + + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; +}; + +#endif diff --git a/Modules/ModelFitUI/files.cmake b/Modules/ModelFitUI/files.cmake new file mode 100644 index 0000000000..7b0311aa62 --- /dev/null +++ b/Modules/ModelFitUI/files.cmake @@ -0,0 +1,34 @@ +set(CPP_FILES + Qmitk/QmitkParameterFitBackgroundJob.cpp + Qmitk/QmitkSimpleBarrierParametersDelegate.cpp + Qmitk/QmitkSimpleBarrierTypeDelegate.cpp + Qmitk/QmitkSimpleBarrierModel.cpp + Qmitk/QmitkSimpleBarrierManagerWidget.cpp + Qmitk/QmitkInitialValuesModel.cpp + Qmitk/QmitkInitialValuesManagerWidget.cpp + Qmitk/QmitkInitialValuesDelegate.cpp + Qmitk/QmitkInitialValuesTypeDelegate.cpp +) + +set(H_FILES +) + +set(TPP_FILES +) + +set(UI_FILES + Qmitk/QmitkSimpleBarrierManagerWidget.ui + Qmitk/QmitkInitialValuesManagerWidget.ui +) + +set(MOC_H_FILES + Qmitk/QmitkSimpleBarrierModel.h + Qmitk/QmitkParameterFitBackgroundJob.h + Qmitk/QmitkSimpleBarrierParametersDelegate.h + Qmitk/QmitkSimpleBarrierTypeDelegate.h + Qmitk/QmitkSimpleBarrierManagerWidget.h + Qmitk/QmitkInitialValuesModel.h + Qmitk/QmitkInitialValuesManagerWidget.h + Qmitk/QmitkInitialValuesDelegate.h + Qmitk/QmitkInitialValuesTypeDelegate.h +) diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index 89c06dd6e0..00e894d947 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,78 +1,82 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(MITK_MODULES Core CommandLine AppUtil RDF LegacyIO DataTypesExt Annotation LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMReaderServices DICOMTesting SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction SceneSerialization Gizmo GraphAlgorithms Multilabel ImageStatistics ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation QtWidgets QtWidgetsExt Chart SegmentationUI MatchPointRegistration MatchPointRegistrationUI Classification GPGPU OpenIGTLink IGTBase IGT CameraCalibration OpenCL OpenCVVideoSupport QtOverlays ToFHardware ToFProcessing ToFUI PhotoacousticsHardware PhotoacousticsAlgorithms PhotoacousticsLib US USUI DicomUI Remeshing Python QtPython Persistence OpenIGTLinkUI IGTUI DicomRT RTUI IOExt XNAT TubeGraph BiophotonicsHardware DiffusionImaging TumorInvasionAnalysis BoundingShape RenderWindowManager RenderWindowManagerUI CEST BasicImageProcessing + ModelFit + ModelFitUI + Pharmacokinetics + PharmacokineticsUI ) if(MITK_ENABLE_PIC_READER) list(APPEND MITK_MODULES IpPicSupportIO) endif() diff --git a/Modules/Pharmacokinetics/CMakeLists.txt b/Modules/Pharmacokinetics/CMakeLists.txt new file mode 100644 index 0000000000..9c725c7550 --- /dev/null +++ b/Modules/Pharmacokinetics/CMakeLists.txt @@ -0,0 +1,19 @@ +MITK_CREATE_MODULE(Pharmacokinetics + INCLUDE_DIRS + PUBLIC ${MITK_BINARY_DIR} + PRIVATE src/Common src/Functors src/Models src/DescriptionParameters src/SimulationFramework + DEPENDS + PUBLIC MitkCore MitkModelFit + PRIVATE MitkMultilabel + PACKAGE_DEPENDS + PUBLIC ITK|ITKOptimizers + PRIVATE Boost + WARNINGS_NO_ERRORS +) + +if(BUILD_TESTING) + ADD_SUBDIRECTORY(test) +endif(BUILD_TESTING) + +ADD_SUBDIRECTORY(autoload/Models) +ADD_SUBDIRECTORY(cmdapps) \ No newline at end of file diff --git a/Modules/Pharmacokinetics/autoload/Models/CMakeLists.txt b/Modules/Pharmacokinetics/autoload/Models/CMakeLists.txt new file mode 100644 index 0000000000..415877143b --- /dev/null +++ b/Modules/Pharmacokinetics/autoload/Models/CMakeLists.txt @@ -0,0 +1,6 @@ +MITK_CREATE_MODULE(PharmacokineticModelsServices + DEPENDS + PUBLIC MitkPharmacokinetics + PRIVATE MitkCore + AUTOLOAD_WITH MitkPharmacokinetics +) diff --git a/Modules/Pharmacokinetics/autoload/Models/files.cmake b/Modules/Pharmacokinetics/autoload/Models/files.cmake new file mode 100644 index 0000000000..363c531b12 --- /dev/null +++ b/Modules/Pharmacokinetics/autoload/Models/files.cmake @@ -0,0 +1,12 @@ +set(CPP_FILES + mitkPharmacokineticModelsActivator.cpp +) + +set(H_FILES +) + +set(TPP_FILES +) + +set(MOC_H_FILES +) diff --git a/Modules/Pharmacokinetics/autoload/Models/mitkPharmacokineticModelsActivator.cpp b/Modules/Pharmacokinetics/autoload/Models/mitkPharmacokineticModelsActivator.cpp new file mode 100644 index 0000000000..ef717069a5 --- /dev/null +++ b/Modules/Pharmacokinetics/autoload/Models/mitkPharmacokineticModelsActivator.cpp @@ -0,0 +1,90 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include +#include + +#include + +//MR perfusion models +#include "mitkDescriptivePharmacokineticBrixModelFactory.h" +#include "mitkExtendedToftsModelFactory.h" +#include "mitkStandardToftsModelFactory.h" +#include "mitkTwoCompartmentExchangeModelFactory.h" +#include "mitkNumericTwoCompartmentExchangeModelFactory.h" + +//PET perfusion models +#include "mitkOneTissueCompartmentModelFactory.h" +#include "mitkExtendedOneTissueCompartmentModelFactory.h" +#include "mitkTwoTissueCompartmentModelFactory.h" +#include "mitkTwoTissueCompartmentFDGModelFactory.h" +#include "mitkNumericTwoTissueCompartmentModelFactory.h" + +//general models +#include "mitkGenericParamModelFactory.h" +#include "mitkLinearModelFactory.h" +#include "mitkT2DecayModelFactory.h" +#include "mitkThreeStepLinearModelFactory.h" + +namespace mitk +{ + +/* + * This is the module activator for the IO aspects of the "pharmacokinetics" module. + */ +class PharmacokineticModelsActivator : public us::ModuleActivator +{ +public: + + template void RegisterProvider(us::ModuleContext* context) + { + auto provider = new TProvider(); + provider->RegisterService(context); + + m_RegisteredProviders.push_back(std::unique_ptr(provider)); + } + + virtual void Load(us::ModuleContext* context) override + { + m_RegisteredProviders.clear(); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + RegisterProvider >(context); + } + + virtual void Unload(us::ModuleContext* ) override + { + } + +private: + std::vector > m_RegisteredProviders; +}; + +} + +US_EXPORT_MODULE_ACTIVATOR(mitk::PharmacokineticModelsActivator) diff --git a/Modules/Pharmacokinetics/cmdapps/CMakeLists.txt b/Modules/Pharmacokinetics/cmdapps/CMakeLists.txt new file mode 100644 index 0000000000..bbb4b7341c --- /dev/null +++ b/Modules/Pharmacokinetics/cmdapps/CMakeLists.txt @@ -0,0 +1,77 @@ +option(BUILD_PerfusionMiniApps "Build commandline tools for the perfusion module" OFF) + +if(BUILD_PerfusionMiniApps) + + # needed include directories + include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ) + # list of miniapps + # if an app requires additional dependencies + # they are added after a "^^" and separated by "_" + set( miniapps + CurveDescriptorMiniApp^^ + MRPerfusionMiniApp^^ + MRSignal2ConcentrationMiniApp^^ + ) + + foreach(miniapp ${miniapps}) + # extract mini app name and dependencies + string(REPLACE "^^" "\\;" miniapp_info ${miniapp}) + set(miniapp_info_list ${miniapp_info}) + list(GET miniapp_info_list 0 appname) + list(GET miniapp_info_list 1 raw_dependencies) + string(REPLACE "_" "\\;" dependencies "${raw_dependencies}") + set(dependencies_list ${dependencies}) + + mitk_create_executable(${appname} + DEPENDS MitkModelFit MitkPharmacokinetics MitkCommandLine ${dependencies_list} + PACKAGE_DEPENDS ITK + CPP_FILES ${appname}.cpp + ) + + if(EXECUTABLE_IS_ENABLED) + # On Linux, create a shell script to start a relocatable application + if(UNIX AND NOT APPLE) + install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh) + endif() + + get_target_property(_is_bundle ${EXECUTABLE_TARGET} MACOSX_BUNDLE) + + if(APPLE) + if(_is_bundle) + set(_target_locations ${EXECUTABLE_TARGET}.app) + set(${_target_locations}_qt_plugins_install_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) + set(_bundle_dest_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) + set(_qt_plugins_for_current_bundle ${EXECUTABLE_TARGET}.app/Contents/MacOS) + set(_qt_conf_install_dirs ${EXECUTABLE_TARGET}.app/Contents/Resources) + install(TARGETS ${EXECUTABLE_TARGET} BUNDLE DESTINATION . ) + else() + if(NOT MACOSX_BUNDLE_NAMES) + set(_qt_conf_install_dirs bin) + set(_target_locations bin/${EXECUTABLE_TARGET}) + set(${_target_locations}_qt_plugins_install_dir bin) + install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) + else() + foreach(bundle_name ${MACOSX_BUNDLE_NAMES}) + list(APPEND _qt_conf_install_dirs ${bundle_name}.app/Contents/Resources) + set(_current_target_location ${bundle_name}.app/Contents/MacOS/${EXECUTABLE_TARGET}) + list(APPEND _target_locations ${_current_target_location}) + set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) + message( " set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) ") + + install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION ${bundle_name}.app/Contents/MacOS/) + endforeach() + endif() + endif() + else() + set(_target_locations bin/${EXECUTABLE_TARGET}${CMAKE_EXECUTABLE_SUFFIX}) + set(${_target_locations}_qt_plugins_install_dir bin) + set(_qt_conf_install_dirs bin) + install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) + endif() + endif() + endforeach() + +endif() diff --git a/Modules/Pharmacokinetics/cmdapps/CurveDescriptorMiniApp.cpp b/Modules/Pharmacokinetics/cmdapps/CurveDescriptorMiniApp.cpp new file mode 100644 index 0000000000..7692c86499 --- /dev/null +++ b/Modules/Pharmacokinetics/cmdapps/CurveDescriptorMiniApp.cpp @@ -0,0 +1,246 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// std includes +#include + +// itk includes +#include "itksys/SystemTools.hxx" + +// CTK includes +#include "mitkCommandLineParser.h" + +// MITK includes +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +std::string inFilename; +std::string outFileName; +std::string maskFileName; +bool verbose(false); +bool preview(false); +mitk::Image::Pointer image; +mitk::Image::Pointer mask; + + +void onFitEvent(::itk::Object* caller, const itk::EventObject & event, void* /*data*/) +{ + itk::ProgressEvent progressEvent; + + if (progressEvent.CheckEvent(&event)) + { + mitk::PixelBasedDescriptionParameterImageGenerator* castedReporter = dynamic_cast(caller); + std::cout <GetProgress()*100 << "% "; + } +} + + +void setupParser(mitkCommandLineParser& parser) +{ + // set general information about your MiniApp + parser.setCategory("Dynamic Data Analysis Tools"); + parser.setTitle("Curve Descriptor"); + parser.setDescription("MiniApp that allows to generate curve descriptor maps for dynamic image."); + parser.setContributor("DKFZ MIC"); + //! [create parser] + + //! [add arguments] + // how should arguments be prefixed + parser.setArgumentPrefix("--", "-"); + // add each argument, unless specified otherwise each argument is optional + // see mitkCommandLineParser::addArgument for more information + parser.beginGroup("Required I/O parameters"); + parser.addArgument( + "input", "i", mitkCommandLineParser::InputFile, "Input file", "input 3D+t image file", us::Any(), false); + parser.addArgument("output", + "o", + mitkCommandLineParser::OutputFile, + "Output file template", + "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.", + us::Any(), + false); + parser.endGroup(); + + parser.beginGroup("Optional parameters"); + parser.addArgument( + "mask", "m", mitkCommandLineParser::InputFile, "Mask file", "Mask that defines the spatial image region that should be fitted. Must have the same geometry as the input image!", us::Any()); + parser.addArgument( + "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output"); + parser.addArgument( + "preview", "p", mitkCommandLineParser::Bool, "Preview outputs", "The application previews the outputs (filename, type) it would produce with the current settings."); + parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); + parser.endGroup(); + //! [add arguments] +} + +bool configureApplicationSettings(std::map parsedArgs) +{ + if (parsedArgs.size() == 0) + return false; + + verbose = false; + if (parsedArgs.count("verbose")) + { + verbose = us::any_cast(parsedArgs["verbose"]); + } + + if (parsedArgs.count("mask")) + { + maskFileName = us::any_cast(parsedArgs["mask"]); + } + + preview = false; + if (parsedArgs.count("preview")) + { + preview = us::any_cast(parsedArgs["preview"]); + } + + inFilename = us::any_cast(parsedArgs["input"]); + outFileName = us::any_cast(parsedArgs["output"]); + + return true; +} + +void ConfigureFunctor(mitk::CurveParameterFunctor* functor) +{ + mitk::CurveDescriptionParameterBase::Pointer parameterFunction = mitk::AreaUnderTheCurveDescriptionParameter::New().GetPointer(); + functor->RegisterDescriptionParameter("AUC", parameterFunction); + + parameterFunction = mitk::AreaUnderFirstMomentDescriptionParameter::New().GetPointer(); + functor->RegisterDescriptionParameter("AUMC", parameterFunction); + + parameterFunction = mitk::MeanResidenceTimeDescriptionParameter::New().GetPointer(); + functor->RegisterDescriptionParameter("MRT", parameterFunction); + + parameterFunction = mitk::TimeToPeakCurveDescriptionParameter::New().GetPointer(); + functor->RegisterDescriptionParameter("TimeToPeak", parameterFunction); +}; + +void doDescription() +{ + mitk::PixelBasedDescriptionParameterImageGenerator::Pointer generator = + mitk::PixelBasedDescriptionParameterImageGenerator::New(); + mitk::CurveParameterFunctor::Pointer functor = mitk::CurveParameterFunctor::New(); + ConfigureFunctor(functor); + functor->SetGrid(mitk::ExtractTimeGrid(image)); + + generator->SetFunctor(functor); + generator->SetDynamicImage(image); + generator->SetMask(mask); + + ::itk::CStyleCommand::Pointer command = ::itk::CStyleCommand::New(); + command->SetCallback(onFitEvent); + + std::cout << "Started curve descriptor computation process..." << std::endl; + generator->AddObserver(::itk::AnyEvent(), command); + generator->Generate(); + std::cout << std::endl << "Finished computation process" << std::endl; + + for (auto imageIterator : generator->GetParameterImages()) + { + mitk::storeParameterResultImage(outFileName, imageIterator.first, imageIterator.second); + } +} + +void doPreview() +{ + mitk::CurveParameterFunctor::Pointer functor = mitk::CurveParameterFunctor::New(); + ConfigureFunctor(functor); + + auto pNames = functor->GetDescriptionParameterNames(); + + for (auto aName : pNames) + { + auto fullPath = mitk::generateModelFitResultImagePath(outFileName, aName); + std::cout << "Store result parameter: " << aName << " -> " << fullPath << std::endl; + } +} + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + setupParser(parser); + + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + + const std::map& parsedArgs = parser.parseArguments(argc, argv); + if (!configureApplicationSettings(parsedArgs)) + { + return EXIT_FAILURE; + }; + + // Show a help message + if (parsedArgs.count("help") || parsedArgs.count("h")) + { + std::cout << parser.helpText(); + return EXIT_SUCCESS; + } + + //! [do processing] + try + { + if (preview) + { + doPreview(); + } + else + { + image = mitk::IOUtil::Load(inFilename, &readerFilterFunctor); + std::cout << "Input: " << inFilename << std::endl; + + if (!maskFileName.empty()) + { + mask = mitk::IOUtil::Load(maskFileName, &readerFilterFunctor); + std::cout << "Mask: " << maskFileName << std::endl; + } + else + { + std::cout << "Mask: none" << std::endl; + } + + doDescription(); + } + + std::cout << "Processing finished." << std::endl; + + return EXIT_SUCCESS; + } + catch (itk::ExceptionObject e) + { + MITK_ERROR << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + MITK_ERROR << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + MITK_ERROR << "Unexpected error encountered."; + return EXIT_FAILURE; + } +} diff --git a/Modules/Pharmacokinetics/cmdapps/MRPerfusionMiniApp.cpp b/Modules/Pharmacokinetics/cmdapps/MRPerfusionMiniApp.cpp new file mode 100644 index 0000000000..6faf139dff --- /dev/null +++ b/Modules/Pharmacokinetics/cmdapps/MRPerfusionMiniApp.cpp @@ -0,0 +1,878 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// std includes +#include + +// itk includes +#include "itksys/SystemTools.hxx" + +// CTK includes +#include "mitkCommandLineParser.h" + +// MITK includes +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +std::string inFilename; +std::string outFileName; +std::string maskFileName; +std::string aifMaskFileName; +std::string aifImageFileName; + +mitk::Image::Pointer image; +mitk::Image::Pointer mask; +mitk::Image::Pointer aifImage; +mitk::Image::Pointer aifMask; + +bool useConstraints(false); +bool verbose(false); +bool roibased(false); +bool preview(false); + +std::string modelName; + +float aifHematocritLevel(0); +float brixInjectionTime(0); + +const std::string MODEL_NAME_3SL = "3SL"; +const std::string MODEL_NAME_descriptive = "descriptive"; +const std::string MODEL_NAME_tofts = "tofts"; +const std::string MODEL_NAME_2CX = "2CX"; + +void onFitEvent(::itk::Object* caller, const itk::EventObject & event, void* /*data*/) +{ + itk::ProgressEvent progressEvent; + + if (progressEvent.CheckEvent(&event)) + { + mitk::ParameterFitImageGeneratorBase* castedReporter = dynamic_cast(caller); + std::cout <GetProgress()*100 << "% "; + } +} + + +void setupParser(mitkCommandLineParser& parser) +{ + // set general information about your MiniApp + parser.setCategory("Dynamic Data Analysis Tools"); + parser.setTitle("MR Perfusion"); + 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."); + parser.setContributor("DKFZ MIC"); + //! [create parser] + + //! [add arguments] + // how should arguments be prefixed + parser.setArgumentPrefix("--", "-"); + // add each argument, unless specified otherwise each argument is optional + // see mitkCommandLineParser::addArgument for more information + parser.beginGroup("Model parameters"); + parser.addArgument( + "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))); + parser.addArgument( + "injectiontime", "j", mitkCommandLineParser::Float, "Injection time [min]", "Injection time of the bolus. This information is needed for the descriptive pharmacokinetic Brix model.", us::Any()); + parser.endGroup(); + parser.beginGroup("Required I/O parameters"); + parser.addArgument( + "input", "i", mitkCommandLineParser::InputFile, "Input file", "input 3D+t image file", us::Any(), false); + parser.addArgument("output", + "o", + mitkCommandLineParser::OutputFile, + "Output file template", + "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.", + us::Any(), + false); + parser.endGroup(); + + parser.beginGroup("AIF parameters"); + parser.addArgument( + "aifmask", "n", mitkCommandLineParser::InputFile, "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()); + parser.addArgument( + "aifimage", "a", mitkCommandLineParser::InputFile, "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()); + parser.addArgument( + "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)); + parser.endGroup(); + + parser.beginGroup("Optional parameters"); + parser.addArgument( + "mask", "m", mitkCommandLineParser::InputFile, "Mask file", "Mask that defines the spatial image region that should be fitted. Must have the same geometry as the input image!", us::Any()); + parser.addArgument( + "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output"); + parser.addArgument( + "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."); + parser.addArgument( + "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)); + parser.addArgument( + "preview", "p", mitkCommandLineParser::Bool, "Preview outputs", "The application previews the outputs (filename, type) it would produce with the current settings."); + parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); + parser.endGroup(); + //! [add arguments] +} + +bool configureApplicationSettings(std::map parsedArgs) +{ + if (parsedArgs.size() == 0) + return false; + + // parse, cast and set required arguments + modelName = MODEL_NAME_tofts; + if (parsedArgs.count("model")) + { + modelName = us::any_cast(parsedArgs["model"]); + } + + inFilename = us::any_cast(parsedArgs["input"]); + outFileName = us::any_cast(parsedArgs["output"]); + + if (parsedArgs.count("mask")) + { + maskFileName = us::any_cast(parsedArgs["mask"]); + } + + if (parsedArgs.count("aifimage")) + { + aifImageFileName = us::any_cast(parsedArgs["aifimage"]); + } + + if (parsedArgs.count("aifmask")) + { + aifMaskFileName = us::any_cast(parsedArgs["aifmask"]); + } + + verbose = false; + if (parsedArgs.count("verbose")) + { + verbose = us::any_cast(parsedArgs["verbose"]); + } + + preview = false; + if (parsedArgs.count("preview")) + { + preview = us::any_cast(parsedArgs["preview"]); + } + + roibased = false; + if (parsedArgs.count("roibased")) + { + roibased = us::any_cast(parsedArgs["roibased"]); + } + + useConstraints = false; + if (parsedArgs.count("constraints")) + { + useConstraints = us::any_cast(parsedArgs["constraints"]); + } + + aifHematocritLevel = 0.45; + if (parsedArgs.count("hematocrit")) + { + aifHematocritLevel = us::any_cast(parsedArgs["hematocrit"]); + } + + brixInjectionTime = 0.0; + if (parsedArgs.count("injectiontime")) + { + brixInjectionTime = us::any_cast(parsedArgs["injectiontime"]); + } + return true; +} + +mitk::ModelFitFunctorBase::Pointer createDefaultFitFunctor( + const mitk::ModelParameterizerBase* parameterizer, const mitk::ModelFactoryBase* modelFactory) +{ + mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor = + mitk::LevenbergMarquardtModelFitFunctor::New(); + + mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::Pointer chi2 = + mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::New(); + fitFunctor->RegisterEvaluationParameter("Chi^2", chi2); + + if (useConstraints) + { + fitFunctor->SetConstraintChecker(modelFactory->CreateDefaultConstraints().GetPointer()); + } + + mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel(); + + ::itk::LevenbergMarquardtOptimizer::ScalesType scales; + scales.SetSize(refModel->GetNumberOfParameters()); + scales.Fill(1.0); + fitFunctor->SetScales(scales); + + fitFunctor->SetDebugParameterMaps(true); + + return fitFunctor.GetPointer(); +} + +/**Helper that ensures that the mask (if it exists) is always 3D image. If the mask is originally an 4D image, the first +time step will be used.*/ +mitk::Image::Pointer getMask3D() +{ + mitk::Image::Pointer result; + + if (mask.IsNotNull()) + { + result = mask; + + //mask settings + if (mask->GetTimeSteps() > 1) + { + MITK_INFO << "Selected mask has multiple timesteps. Only use first timestep to mask model fit."; + mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); + maskedImageTimeSelector->SetInput(mask); + maskedImageTimeSelector->SetTimeNr(0); + maskedImageTimeSelector->UpdateLargestPossibleRegion(); + result = maskedImageTimeSelector->GetOutput(); + } + } + + return result; +} + + +void getAIF(mitk::AIFBasedModelBase::AterialInputFunctionType& aif, + mitk::AIFBasedModelBase::AterialInputFunctionType& aifTimeGrid) +{ + if (aifMask.IsNotNull()) + { + aif.clear(); + aifTimeGrid.clear(); + + mitk::AterialInputFunctionGenerator::Pointer aifGenerator = + mitk::AterialInputFunctionGenerator::New(); + + //Hematocrit level + aifGenerator->SetHCL(aifHematocritLevel); + std::cout << "AIF hematocrit level: " << aifHematocritLevel << std::endl; + + mitk::Image::Pointer selectedAIFMask = aifMask; + + //mask settings + if (aifMask->GetTimeSteps() > 1) + { + MITK_INFO << "Selected AIF mask has multiple timesteps. Only use first timestep to mask model fit."; + mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); + maskedImageTimeSelector->SetInput(aifMask); + maskedImageTimeSelector->SetTimeNr(0); + maskedImageTimeSelector->UpdateLargestPossibleRegion(); + aifMask = maskedImageTimeSelector->GetOutput(); + } + + aifGenerator->SetMask(aifMask); + + mitk::Image::Pointer selectedAIFImage = image; + //image settings + if (aifImage.IsNotNull()) + { + selectedAIFImage = aifImage; + } + + aifGenerator->SetDynamicImage(selectedAIFImage); + + aif = aifGenerator->GetAterialInputFunction(); + aifTimeGrid = aifGenerator->GetAterialInputFunctionTimeGrid(); + } + else + { + mitkThrow() << "Cannot generate AIF. AIF mask was not specified or correctly loaded."; + } +} + + +void generateDescriptiveBrixModel_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + mitk::DescriptivePharmacokineticBrixModelParameterizer::Pointer modelParameterizer = + mitk::DescriptivePharmacokineticBrixModelParameterizer::New(); + + mitk::Image::Pointer mask3D = getMask3D(); + + //Model configuration (static parameters) can be done now + modelParameterizer->SetTau(brixInjectionTime); + std::cout << "Injection time [min]: " << brixInjectionTime << std::endl; + + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(image); + imageTimeSelector->SetTimeNr(0); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::DescriptivePharmacokineticBrixModelParameterizer::BaseImageType::Pointer baseImage; + mitk::CastToItkImage(imageTimeSelector->GetOutput(), baseImage); + + modelParameterizer->SetBaseImage(baseImage); + + //Specify fitting strategy and criterion parameters + mitk::ModelFactoryBase::Pointer factory = mitk::DescriptivePharmacokineticBrixModelFactory::New().GetPointer(); + mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + std::string roiUID = ""; + + if (mask3D.IsNotNull()) + { + fitGenerator->SetMask(mask3D); + roiUID = mitk::EnsureModelFitUID(mask); + } + + fitGenerator->SetDynamicImage(image); + fitGenerator->SetFitFunctor(fitFunctor); + + generator = fitGenerator.GetPointer(); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + image, mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), roiUID); +} + +void generateDescriptiveBrixModel_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::Image::Pointer mask3D = getMask3D(); + + if (mask3D.IsNull()) + { + return; + } + + mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::ROIBasedParameterFitImageGenerator::New(); + + mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::Pointer modelParameterizer = + mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::New(); + + //Compute ROI signal + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = + mitk::MaskedDynamicImageStatisticsGenerator::New(); + signalGenerator->SetMask(mask3D); + signalGenerator->SetDynamicImage(image); + signalGenerator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); + + //Model configuration (static parameters) can be done now + modelParameterizer->SetTau(brixInjectionTime); + std::cout << "Injection time [min]: " << brixInjectionTime << std::endl; + modelParameterizer->SetBaseValue(roiSignal[0]); + + //Specify fitting strategy and criterion parameters + mitk::ModelFactoryBase::Pointer factory = mitk::DescriptivePharmacokineticBrixModelFactory::New().GetPointer(); + mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + fitGenerator->SetMask(mask3D); + fitGenerator->SetFitFunctor(fitFunctor); + fitGenerator->SetSignal(roiSignal); + fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image)); + + generator = fitGenerator.GetPointer(); + + std::string roiUID = mitk::EnsureModelFitUID(mask); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + image, mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), roiUID); + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = + roiSignal.begin(); pos != roiSignal.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("ROI", infoSignal); +} + + +void Generate3StepLinearModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + mitk::ThreeStepLinearModelParameterizer::Pointer modelParameterizer = + mitk::ThreeStepLinearModelParameterizer::New(); + + mitk::Image::Pointer mask3D = getMask3D(); + + //Specify fitting strategy and criterion parameters + mitk::ModelFactoryBase::Pointer factory = mitk::ThreeStepLinearModelFactory::New().GetPointer(); + mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + std::string roiUID = ""; + + if (mask3D.IsNotNull()) + { + fitGenerator->SetMask(mask3D); + roiUID = mitk::EnsureModelFitUID(mask); + } + + fitGenerator->SetDynamicImage(image); + fitGenerator->SetFitFunctor(fitFunctor); + + generator = fitGenerator.GetPointer(); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + image, mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), roiUID); +} + +void Generate3StepLinearModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::Image::Pointer mask3D = getMask3D(); + + if (mask3D.IsNull()) + { + return; + } + + mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::ROIBasedParameterFitImageGenerator::New(); + + mitk::ThreeStepLinearModelParameterizer::Pointer modelParameterizer = + mitk::ThreeStepLinearModelParameterizer::New(); + + //Compute ROI signal + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = + mitk::MaskedDynamicImageStatisticsGenerator::New(); + signalGenerator->SetMask(mask3D); + signalGenerator->SetDynamicImage(image); + signalGenerator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); + + //Specify fitting strategy and criterion parameters + mitk::ModelFactoryBase::Pointer factory = mitk::ThreeStepLinearModelFactory::New().GetPointer(); + mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + fitGenerator->SetMask(mask3D); + fitGenerator->SetFitFunctor(fitFunctor); + fitGenerator->SetSignal(roiSignal); + fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image)); + + generator = fitGenerator.GetPointer(); + + std::string roiUID = mitk::EnsureModelFitUID(mask); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + image, mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), roiUID); + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = + roiSignal.begin(); pos != roiSignal.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("ROI", infoSignal); +} + +template +void generateAIFbasedModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + mitk::AIFBasedModelBase::AterialInputFunctionType aif; + mitk::AIFBasedModelBase::AterialInputFunctionType aifTimeGrid; + getAIF(aif, aifTimeGrid); + + modelParameterizer->SetAIF(aif); + modelParameterizer->SetAIFTimeGrid(aifTimeGrid); + + mitk::Image::Pointer mask3D = getMask3D(); + + //Specify fitting strategy and criterion parameters + mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer(); + mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + std::string roiUID = ""; + + if (mask3D.IsNotNull()) + { + fitGenerator->SetMask(mask3D); + roiUID = mitk::EnsureModelFitUID(mask); + } + + fitGenerator->SetDynamicImage(image); + fitGenerator->SetFitFunctor(fitFunctor); + + generator = fitGenerator.GetPointer(); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + image, mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), + roiUID); + + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = + aif.begin(); pos != aif.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("AIF", infoSignal); +} + +template +void generateAIFbasedModelFit_ROIBased( + mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::Image::Pointer mask3D = getMask3D(); + + if (mask3D.IsNull()) + { + return; + } + + mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::ROIBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + mitk::AIFBasedModelBase::AterialInputFunctionType aif; + mitk::AIFBasedModelBase::AterialInputFunctionType aifTimeGrid; + getAIF(aif, aifTimeGrid); + + modelParameterizer->SetAIF(aif); + modelParameterizer->SetAIFTimeGrid(aifTimeGrid); + + //Compute ROI signal + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = + mitk::MaskedDynamicImageStatisticsGenerator::New(); + signalGenerator->SetMask(mask3D); + signalGenerator->SetDynamicImage(image); + signalGenerator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); + + //Specify fitting strategy and criterion parameters + mitk::ModelFactoryBase::Pointer factory = TFactory::New().GetPointer(); + mitk::ModelFitFunctorBase::Pointer fitFunctor = createDefaultFitFunctor(modelParameterizer, factory); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + fitGenerator->SetMask(mask3D); + fitGenerator->SetFitFunctor(fitFunctor); + fitGenerator->SetSignal(roiSignal); + fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(image)); + + generator = fitGenerator.GetPointer(); + + std::string roiUID = mitk::EnsureModelFitUID(mask); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + image, mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), + roiUID); + + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = + roiSignal.begin(); pos != roiSignal.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("ROI", infoSignal); + + infoSignal.clear(); + + for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = + aif.begin(); pos != aif.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("AIF", infoSignal); +} + + +void storeResultImage(const std::string& name, mitk::Image* image, mitk::modelFit::Parameter::Type nodeType, const mitk::modelFit::ModelFitInfo* modelFitInfo) +{ + mitk::modelFit::SetModelFitDataProperties(image, name, nodeType, modelFitInfo); + + std::string ext = ::itksys::SystemTools::GetFilenameLastExtension(outFileName); + + std::string dir = itksys::SystemTools::GetFilenamePath(outFileName); + dir = itksys::SystemTools::ConvertToOutputPath(dir); + + std::string rootName = itksys::SystemTools::GetFilenameWithoutLastExtension(outFileName); + + std::string fileName = rootName + "_" + name + ext; + + std::vector pathElements; + pathElements.push_back(dir); + pathElements.push_back(fileName); + + std::string fullOutPath = itksys::SystemTools::ConvertToOutputPath(dir + "/" + fileName); + + mitk::IOUtil::Save(image, fullOutPath); + + std::cout << "Store result (parameter: "<(fitSession, generator); + } + else + { + generateAIFbasedModelFit_ROIBased(fitSession, generator); + } + } + else if (is2CXMFactory) + { + std::cout << "Model: two compartment exchange model" << std::endl; + if (!roibased) + { + generateAIFbasedModelFit_PixelBased(fitSession, generator); + } + else + { + generateAIFbasedModelFit_ROIBased(fitSession, generator); + } + } + else + { + std::cerr << "ERROR. Model flag is unknown. Given flag: " << modelName << std::endl; + } +} + +void doFitting() +{ + mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr; + mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr; + + ::itk::CStyleCommand::Pointer command = ::itk::CStyleCommand::New(); + command->SetCallback(onFitEvent); + + createFitGenerator(fitSession, generator); + + if (generator.IsNotNull() ) + { + std::cout << "Started fitting process..." << std::endl; + generator->AddObserver(::itk::AnyEvent(), command); + generator->Generate(); + std::cout << std::endl << "Finished fitting process" << std::endl; + + mitk::storeModelFitGeneratorResults(outFileName, generator, fitSession); + } + else + { + mitkThrow() << "Fitting error! Could not initialize fitting job."; + } +} + +void doPreview() +{ + mitk::ParameterFitImageGeneratorBase::Pointer generator = nullptr; + mitk::modelFit::ModelFitInfo::Pointer fitSession = nullptr; + + createFitGenerator(fitSession, generator); + + if (generator.IsNotNull()) + { + mitk::previewModelFitGeneratorResults(outFileName, generator); + } + else + { + mitkThrow() << "Fitting error! Could not initialize fitting job."; + } +} + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + setupParser(parser); + const std::map& parsedArgs = parser.parseArguments(argc, argv); + + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + + if (!configureApplicationSettings(parsedArgs)) + { + return EXIT_FAILURE; + }; + + // Show a help message + if (parsedArgs.count("help") || parsedArgs.count("h")) + { + std::cout << parser.helpText(); + return EXIT_SUCCESS; + } + + //! [do processing] + try + { + image = mitk::IOUtil::Load(inFilename, &readerFilterFunctor); + std::cout << "Input: " << inFilename << std::endl; + + if (!maskFileName.empty()) + { + mask = mitk::IOUtil::Load(maskFileName, &readerFilterFunctor); + std::cout << "Mask: " << maskFileName << std::endl; + } + else + { + std::cout << "Mask: none" << std::endl; + } + + if (modelName != MODEL_NAME_descriptive && modelName != MODEL_NAME_3SL) + { + if (!aifMaskFileName.empty()) + { + aifMask = mitk::IOUtil::Load(aifMaskFileName, &readerFilterFunctor); + std::cout << "AIF mask: " << aifMaskFileName << std::endl; + } + else + { + mitkThrow() << "Error. Cannot fit. Choosen model needs an AIF. Please specify AIF mask (--aifmask)."; + } + if (!aifImageFileName.empty()) + { + aifImage = mitk::IOUtil::Load(aifImageFileName, &readerFilterFunctor); + std::cout << "AIF image: " << aifImageFileName << std::endl; + } + else + { + std::cout << "AIF image: none (using signal image)" << std::endl; + } + } + + if (roibased && mask.IsNull()) + { + mitkThrow() << "Error. Cannot fit. Please specify mask if you select roi based fitting."; + } + + std::cout << "Style: "; + if (roibased) + { + std::cout << "ROI based"; + } + else + { + std::cout << "pixel based"; + } + std::cout << std::endl; + + if (preview) + { + doPreview(); + } + else + { + doFitting(); + } + + std::cout << "Processing finished." << std::endl; + + return EXIT_SUCCESS; + } + catch (itk::ExceptionObject e) + { + MITK_ERROR << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + MITK_ERROR << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + MITK_ERROR << "Unexpected error encountered."; + return EXIT_FAILURE; + } +} diff --git a/Modules/Pharmacokinetics/cmdapps/MRSignal2ConcentrationMiniApp.cpp b/Modules/Pharmacokinetics/cmdapps/MRSignal2ConcentrationMiniApp.cpp new file mode 100644 index 0000000000..a7baa2871b --- /dev/null +++ b/Modules/Pharmacokinetics/cmdapps/MRSignal2ConcentrationMiniApp.cpp @@ -0,0 +1,293 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// std includes +#include + +// itk includes +#include "itksys/SystemTools.hxx" + +// CTK includes +#include "mitkCommandLineParser.h" + +// MITK includes +#include +#include +#include +#include +#include + +#include + +std::string inFilename; +std::string outFileName; + +mitk::Image::Pointer image; + +bool verbose(false); + +bool t1_absolute(false); +bool t1_relative(false); +bool t1_flash(false); +bool t2(false); + +float k(1.0); +float te(0); +float rec_time(0); +float relaxivity(0); +float rel_time(0); + +void setupParser(mitkCommandLineParser& parser) +{ + // set general information about your MiniApp + parser.setCategory("Dynamic Data Analysis Tools"); + parser.setTitle("MR Signal to Concentration Converter"); + parser.setDescription("MiniApp that allows to convert a T1 or T2 signal image into a concentration image for perfusion analysis."); + parser.setContributor("DKFZ MIC"); + //! [create parser] + + //! [add arguments] + // how should arguments be prefixed + parser.setArgumentPrefix("--", "-"); + // add each argument, unless specified otherwise each argument is optional + // see mitkCommandLineParser::addArgument for more information + parser.beginGroup("Required I/O parameters"); + parser.addArgument( + "input", "i", mitkCommandLineParser::InputFile, "Input file", "input 3D+t image file", us::Any(), false); + parser.addArgument("output", + "o", + mitkCommandLineParser::OutputFile, + "Output file", + "where to save the output concentration image.", + us::Any(), + false); + parser.endGroup(); + + parser.beginGroup("Conversion parameters"); + parser.addArgument( + "t1-absolute", "", mitkCommandLineParser::Bool, "T1 absolute signal enhancement", "Activate conversion for T1 absolute signal enhancement."); + parser.addArgument( + "t1-relative", "", mitkCommandLineParser::Bool, "T1 relative signal enhancement", "Activate conversion for T1 relative signal enhancement."); + parser.addArgument( + "t1-flash", "", mitkCommandLineParser::Bool, "T1 turbo flash", "Activate specific conversion for T1 turbo flash sequences."); + parser.addArgument( + "t2", "", mitkCommandLineParser::Bool, "T2 signal conversion", "Activate conversion for T2 signal enhancement to concentration."); + + parser.addArgument( + "k", "k", mitkCommandLineParser::Float, "Conversion factor k", "Needed for the following conversion modes: T1-absolute, T1-relative, T2. Default value is 1.", us::Any(1)); + parser.addArgument( + "recovery-time", "", mitkCommandLineParser::Float, "Recovery time", "Needed for the following conversion modes: T1-flash."); + parser.addArgument( + "relaxivity", "", mitkCommandLineParser::Float, "Relaxivity", "Needed for the following conversion modes: T1-flash."); + parser.addArgument( + "relaxation-time", "", mitkCommandLineParser::Float, "Relaxation time", "Needed for the following conversion modes: T1-flash."); + parser.addArgument( + "te", "", mitkCommandLineParser::Float, "Echo time TE", "Needed for the following conversion modes: T2.", us::Any(1)); + + parser.beginGroup("Optional parameters"); + parser.addArgument( + "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose output"); + parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); + parser.endGroup(); + //! [add arguments] +} + +bool configureApplicationSettings(std::map parsedArgs) +{ + if (parsedArgs.size() == 0) + return false; + + inFilename = us::any_cast(parsedArgs["input"]); + outFileName = us::any_cast(parsedArgs["output"]); + + verbose = false; + if (parsedArgs.count("verbose")) + { + verbose = us::any_cast(parsedArgs["verbose"]); + } + + t1_absolute = false; + if (parsedArgs.count("t1-absolute")) + { + t1_absolute = us::any_cast(parsedArgs["t1-absolute"]); + } + + t1_relative = false; + if (parsedArgs.count("t1-relative")) + { + t1_relative = us::any_cast(parsedArgs["t1-relative"]); + } + + t1_flash = false; + if (parsedArgs.count("t1-flash")) + { + t1_flash = us::any_cast(parsedArgs["t1-flash"]); + } + + t2 = false; + if (parsedArgs.count("t2")) + { + t2 = us::any_cast(parsedArgs["t2"]); + } + + k = 0.0; + if (parsedArgs.count("k")) + { + k = us::any_cast(parsedArgs["k"]); + } + + relaxivity = 0.0; + if (parsedArgs.count("relaxivity")) + { + relaxivity = us::any_cast(parsedArgs["relaxivity"]); + } + + rec_time = 0.0; + if (parsedArgs.count("recovery-time")) + { + rec_time = us::any_cast(parsedArgs["recovery-time"]); + } + + rel_time = 0.0; + if (parsedArgs.count("relaxation-time")) + { + rel_time = us::any_cast(parsedArgs["relaxation-time"]); + } + + te = 0.0; + if (parsedArgs.count("te")) + { + te = us::any_cast(parsedArgs["te"]); + } + + //consistency checks + int modeCount = 0; + if (t1_absolute) ++modeCount; + if (t1_flash) ++modeCount; + if (t1_relative) ++modeCount; + if (t2) ++modeCount; + + if (modeCount==0) + { + mitkThrow() << "Invalid program call. Please select the type of conversion."; + } + + if (modeCount >1) + { + mitkThrow() << "Invalid program call. Please select only ONE type of conversion."; + } + + if (!k && (t2 || t1_absolute || t1_relative)) + { + mitkThrow() << "Invalid program call. Please set 'k', if you use t1-absolute, t1-relative or t2."; + } + + if (!te && t2) + { + mitkThrow() << "Invalid program call. Please set 'te', if you use t2 mode."; + } + + if ((!rec_time||!rel_time||!relaxivity) && t1_flash) + { + mitkThrow() << "Invalid program call. Please set 'recovery-time', 'relaxation-time' and 'relaxivity', if you use t1-flash mode."; + } + + return true; +} + +void doConversion() +{ + mitk::ConcentrationCurveGenerator::Pointer concentrationGen = + mitk::ConcentrationCurveGenerator::New(); + concentrationGen->SetDynamicImage(image); + + concentrationGen->SetisTurboFlashSequence(t1_flash); + concentrationGen->SetAbsoluteSignalEnhancement(t1_absolute); + concentrationGen->SetRelativeSignalEnhancement(t1_relative); + + concentrationGen->SetisT2weightedImage(t2); + + if (t1_flash) + { + concentrationGen->SetRecoveryTime(rec_time); + concentrationGen->SetRelaxationTime(rel_time); + concentrationGen->SetRelaxivity(relaxivity); + } + else if (t2) + { + concentrationGen->SetT2Factor(k); + concentrationGen->SetT2EchoTime(te); + } + else + { + concentrationGen->SetFactor(k); + } + + mitk::Image::Pointer concentrationImage = concentrationGen->GetConvertedImage(); + + mitk::EnsureModelFitUID(concentrationImage); + mitk::IOUtil::Save(concentrationImage, outFileName); + + std::cout << "Store result: " << outFileName << std::endl; +} + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + setupParser(parser); + const std::map& parsedArgs = parser.parseArguments(argc, argv); + if (!configureApplicationSettings(parsedArgs)) + { + return EXIT_FAILURE; + }; + + mitk::PreferenceListReaderOptionsFunctor readerFilterFunctor = mitk::PreferenceListReaderOptionsFunctor({ "MITK DICOM Reader v2 (classic config)" }, { "MITK DICOM Reader" }); + + // Show a help message + if (parsedArgs.count("help") || parsedArgs.count("h")) + { + std::cout << parser.helpText(); + return EXIT_SUCCESS; + } + + //! [do processing] + try + { + image = mitk::IOUtil::Load(inFilename, &readerFilterFunctor); + std::cout << "Input: " << inFilename << std::endl; + + doConversion(); + + std::cout << "Processing finished." << std::endl; + + return EXIT_SUCCESS; + } + catch (itk::ExceptionObject e) + { + MITK_ERROR << e; + return EXIT_FAILURE; + } + catch (std::exception e) + { + MITK_ERROR << e.what(); + return EXIT_FAILURE; + } + catch (...) + { + MITK_ERROR << "Unexpected error encountered."; + return EXIT_FAILURE; + } +} diff --git a/Modules/Pharmacokinetics/files.cmake b/Modules/Pharmacokinetics/files.cmake new file mode 100644 index 0000000000..b31eb1585c --- /dev/null +++ b/Modules/Pharmacokinetics/files.cmake @@ -0,0 +1,60 @@ +file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") + +set(CPP_FILES + Common/mitkAterialInputFunctionGenerator.cpp + Common/mitkAIFParametrizerHelper.cpp + Common/mitkConcentrationCurveGenerator.cpp + Common/mitkDescriptionParameterImageGeneratorBase.cpp + Common/mitkPixelBasedDescriptionParameterImageGenerator.cpp + DescriptionParameters/mitkCurveDescriptionParameterBase.cpp + DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp + DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp + DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp + DescriptionParameters/mitkTimeToPeakCurveDescriptionParameter.cpp + DescriptionParameters/mitkMaximumCurveDescriptionParameter.cpp + Functors/mitkCurveParameterFunctor.cpp + Models/mitkAIFBasedModelBase.cpp + Models/mitkDescriptivePharmacokineticBrixModel.cpp + Models/mitkDescriptivePharmacokineticBrixModelFactory.cpp + Models/mitkDescriptivePharmacokineticBrixModelValueBasedParameterizer.cpp + Models/mitkDescriptivePharmacokineticBrixModelParameterizer.cpp + Models/mitkThreeStepLinearModel.cpp + Models/mitkThreeStepLinearModelFactory.cpp + Models/mitkThreeStepLinearModelParameterizer.cpp + Models/mitkTwoCompartmentExchangeModel.cpp + Models/mitkTwoCompartmentExchangeModelFactory.cpp + Models/mitkTwoCompartmentExchangeModelParameterizer.cpp + Models/mitkNumericTwoCompartmentExchangeModel.cpp + Models/mitkNumericTwoCompartmentExchangeModelFactory.cpp + Models/mitkNumericTwoCompartmentExchangeModelParameterizer.cpp + Models/mitkExtendedToftsModel.cpp + Models/mitkExtendedToftsModelFactory.cpp + Models/mitkExtendedToftsModelParameterizer.cpp + Models/mitkStandardToftsModel.cpp + Models/mitkStandardToftsModelFactory.cpp + Models/mitkStandardToftsModelParameterizer.cpp + Models/mitkOneTissueCompartmentModel.cpp + Models/mitkOneTissueCompartmentModelFactory.cpp + Models/mitkOneTissueCompartmentModelParameterizer.cpp + Models/mitkExtendedOneTissueCompartmentModel.cpp + Models/mitkExtendedOneTissueCompartmentModelFactory.cpp + Models/mitkExtendedOneTissueCompartmentModelParameterizer.cpp + Models/mitkTwoTissueCompartmentModel.cpp + Models/mitkTwoTissueCompartmentModelFactory.cpp + Models/mitkTwoTissueCompartmentModelParameterizer.cpp + Models/mitkTwoTissueCompartmentFDGModel.cpp + Models/mitkTwoTissueCompartmentFDGModelFactory.cpp + Models/mitkTwoTissueCompartmentFDGModelParameterizer.cpp + Models/mitkNumericTwoTissueCompartmentModel.cpp + Models/mitkNumericTwoTissueCompartmentModelFactory.cpp + Models/mitkNumericTwoTissueCompartmentModelParameterizer.cpp + SimulationFramework/mitkPerfusionDataGenerator.cpp + SimulationFramework/mitkImageGenerationHelper.cpp +) + +set(HXX_FILES +) + + +set(MOC_H_FILES +) diff --git a/Modules/Pharmacokinetics/include/mitkAIFBasedModelBase.h b/Modules/Pharmacokinetics/include/mitkAIFBasedModelBase.h new file mode 100644 index 0000000000..1f9119f189 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkAIFBasedModelBase.h @@ -0,0 +1,118 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef AIFBASEDMODELBASE_H +#define AIFBASEDMODELBASE_H + + +#include "MitkPharmacokineticsExports.h" +#include "mitkModelBase.h" +#include "itkArray2D.h" + +namespace mitk +{ + + /** \class AIFBasedModelBase + * \brief Base Class for all physiological perfusion models using an Aterial Input Function + * All AIF based models come with an array of AIF values and the corresponding TimeGrid ( AIF(t)) + * This class provides functions for setting the AIF Values and optionally a specific AIF TimeGrid. + * It also provides a method for interpolation of the AIF source array to a specified Timegrid that differs from + * AIFTimeGrid. The AIF must be set with an itk::Array. If no AIFTimeGrid is specified with the Setter, it is assumed + * that the AIFTimeGrid is the same as the ModelTimegrid (e.g. AIF is derived from data set to be fitted). In this + * case, AIFvalues must have the same length as ModelTimeGrid, otherwise an exception is generated*/ + class MITKPHARMACOKINETICS_EXPORT AIFBasedModelBase : public mitk::ModelBase + { + public: + + typedef AIFBasedModelBase Self; + typedef ModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + + /** Run-time type information (and related methods). */ + itkTypeMacro(PhysiologciModelBase, AIFBasedModelBase); + + + static const std::string NAME_STATIC_PARAMETER_AIF; + static const std::string NAME_STATIC_PARAMETER_AIFTimeGrid; + + static const std::string UNIT_STATIC_PARAMETER_AIF; + static const std::string UNIT_STATIC_PARAMETER_AIFTimeGrid; + + /** Typedef for Aterial InputFunction AIF(t)*/ + typedef itk::Array AterialInputFunctionType; + + itkGetConstReferenceMacro(AterialInputFunctionValues, AterialInputFunctionType); + itkGetConstReferenceMacro(AterialInputFunctionTimeGrid, TimeGridType); + + itkSetMacro(AterialInputFunctionValues, AterialInputFunctionType); + itkSetMacro(AterialInputFunctionTimeGrid, TimeGridType); + + virtual std::string GetXAxisName() const override; + + virtual std::string GetXAxisUnit() const override; + + virtual std::string GetYAxisName() const override; + + virtual std::string GetYAxisUnit() const override; + + /** Returns the TimeGrid used for the AIF. Either the externally set AIF time grid + * or the time grid of the model if nothing is set.*/ + const TimeGridType& GetCurrentAterialInputFunctionTimeGrid() const; + + /** Returns the Aterial Input function matching currentTimeGrid + * The original values are interpolated to the passed TimeGrid + * if currentTimeGrid.Size() = 0 , the Original AIF will be returned*/ + const AterialInputFunctionType GetAterialInputFunction(TimeGridType currentTimeGrid) const; + + virtual ParameterNamesType GetStaticParameterNames() const override; + virtual ParametersSizeType GetNumberOfStaticParameters() const override; + virtual ParamterUnitMapType GetStaticParameterUnits() const override; + + + protected: + AIFBasedModelBase(); + virtual ~AIFBasedModelBase(); + + /** Reimplementation that checks if AIF and timegrid settings are valid. + * @param [out] error Set internally to indicate the error reason if method returns false. Is used by GetSignal() for the + * exception comment. + * @return Returns true if the model is valid and can compute a signal. Otherwise it returns false.*/ + virtual bool ValidateModel(std::string& error) const override; + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const; + + virtual void SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values) override; + + virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const + override; + + TimeGridType m_AterialInputFunctionTimeGrid; + AterialInputFunctionType m_AterialInputFunctionValues; + + + private: + + + //No copy constructor allowed + AIFBasedModelBase(const Self& source); + void operator=(const Self&); //purposely not implemented + + + }; +} +#endif // AIFBASEDMODELBASE_H diff --git a/Modules/Pharmacokinetics/include/mitkAIFBasedModelParameterizerBase.h b/Modules/Pharmacokinetics/include/mitkAIFBasedModelParameterizerBase.h new file mode 100644 index 0000000000..c6599b9f7f --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkAIFBasedModelParameterizerBase.h @@ -0,0 +1,96 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef __AIFBASED_MODEL_PARAMETERIZER_BASE_H +#define __AIFBASED_MODEL_PARAMETERIZER_BASE_H + +#include "mitkConcreteModelParameterizerBase.h" +#include "mitkAIFParametrizerHelper.h" +#include "mitkAIFBasedModelBase.h" + +namespace mitk +{ + /** Base class for model parameterizers for Models using an Aterial Input Function + */ + template + class MITKPHARMACOKINETICS_EXPORT AIFBasedModelParameterizerBase : public ConcreteModelParameterizerBase + + { + public: + typedef AIFBasedModelParameterizerBase Self; + typedef ConcreteModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(AIFBasedModelParameterizerBase, ConcreteModelParameterizerBase); + + typedef typename Superclass::ModelBaseType ModelBaseType; + typedef typename Superclass::ModelBasePointer ModelBasePointer; + + typedef typename Superclass::ModelType ModelType; + typedef typename Superclass::ModelPointer ModelPointer; + + typedef typename Superclass::StaticParameterValueType StaticParameterValueType; + typedef typename Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef typename Superclass::StaticParameterMapType StaticParameterMapType; + + + typedef typename Superclass::IndexType IndexType; + + itkSetMacro(AIF, mitk::AIFBasedModelBase::AterialInputFunctionType); + itkGetConstReferenceMacro(AIF, mitk::AIFBasedModelBase::AterialInputFunctionType); + + itkSetMacro(AIFTimeGrid, mitk::ModelBase::TimeGridType); + itkGetConstReferenceMacro(AIFTimeGrid, mitk::ModelBase::TimeGridType); + + + /** Returns the global static parameters for the model. + * @remark this default implementation assumes only AIF and its timegrid as static parameters. + * Reimplement in derived classes to change this behavior.*/ + virtual StaticParameterMapType GetGlobalStaticParameters() const + { + StaticParameterMapType result; + StaticParameterValuesType valuesAIF = mitk::convertArrayToParameter(this->m_AIF); + StaticParameterValuesType valuesAIFGrid = mitk::convertArrayToParameter(this->m_AIFTimeGrid); + + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_AIF, valuesAIF)); + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_AIFTimeGrid, valuesAIFGrid)); + + return result; + }; + + + protected: + + AIFBasedModelParameterizerBase() + {}; + + virtual ~AIFBasedModelParameterizerBase() + {}; + + + mitk::AIFBasedModelBase::AterialInputFunctionType m_AIF; + mitk::ModelBase::TimeGridType m_AIFTimeGrid; + + + private: + + //No copy constructor allowed + AIFBasedModelParameterizerBase(const Self& source); + void operator=(const Self&); //purposely not implemented + }; + +} +#endif // __AIFBASED_MODEL_PARAMETERIZER_BASE_H diff --git a/Modules/Pharmacokinetics/include/mitkAIFParametrizerHelper.h b/Modules/Pharmacokinetics/include/mitkAIFParametrizerHelper.h new file mode 100644 index 0000000000..4106064544 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkAIFParametrizerHelper.h @@ -0,0 +1,35 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_AIF_PARAMETERIZER_HELPER_H_ +#define __MITK_AIF_PARAMETERIZER_HELPER_H_ + +#include "mitkModelBase.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + /* Helper function for conversion of an itk::Array into ModelBase::StaticParameterValuesType(std::vector). + Iterates through array and pushes elements into vector*/ + MITKPHARMACOKINETICS_EXPORT ModelBase::StaticParameterValuesType convertArrayToParameter(itk::Array array); + + /* Helper function for conversion of a ModelBase::StaticParameterValuesType(std::vector) into an itk::Array + * Iterates through vector and sets value as array element.*/ + MITKPHARMACOKINETICS_EXPORT itk::Array convertParameterToArray(ModelBase::StaticParameterValuesType); +} + +#endif diff --git a/Modules/Pharmacokinetics/include/mitkAreaUnderFirstMomentDescriptionParameter.h b/Modules/Pharmacokinetics/include/mitkAreaUnderFirstMomentDescriptionParameter.h new file mode 100644 index 0000000000..e9de05ad23 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkAreaUnderFirstMomentDescriptionParameter.h @@ -0,0 +1,33 @@ +#ifndef MITKAREAUNDERFIRSTMOMENTDESCRIPTIONPARAMETER_H +#define MITKAREAUNDERFIRSTMOMENTDESCRIPTIONPARAMETER_H + +#include "mitkCurveDescriptionParameterBase.h" + +namespace mitk +{ + + /** Description parameter that computes the area under the curve */ + class MITKPHARMACOKINETICS_EXPORT AreaUnderFirstMomentDescriptionParameter : public mitk::CurveDescriptionParameterBase + { + public: + typedef mitk::AreaUnderFirstMomentDescriptionParameter Self; + typedef CurveDescriptionParameterBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + virtual DescriptionParameterNamesType GetDescriptionParameterName() const override; + + protected: + static const std::string PARAMETER_NAME; + + AreaUnderFirstMomentDescriptionParameter(); + virtual ~AreaUnderFirstMomentDescriptionParameter(); + + virtual DescriptionParameterResultsType ComputeCurveDescriptionParameter(const CurveType& curve, const CurveGridType& grid) const override; + + }; +} + +#endif // MITKAREAUNDERFIRSTMOMENTDESCRIPTIONPARAMETER_H diff --git a/Modules/Pharmacokinetics/include/mitkAreaUnderTheCurveDescriptionParameter.h b/Modules/Pharmacokinetics/include/mitkAreaUnderTheCurveDescriptionParameter.h new file mode 100644 index 0000000000..f4e58f4e70 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkAreaUnderTheCurveDescriptionParameter.h @@ -0,0 +1,49 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKAREAUNDERTHECURVEDESCRIPTIONPARAMETER_H +#define MITKAREAUNDERTHECURVEDESCRIPTIONPARAMETER_H + +#include "mitkCurveDescriptionParameterBase.h" + +namespace mitk +{ + + /** Description parameter that computes the area under the curve */ + class MITKPHARMACOKINETICS_EXPORT AreaUnderTheCurveDescriptionParameter : public mitk::CurveDescriptionParameterBase + { + public: + typedef mitk::AreaUnderTheCurveDescriptionParameter Self; + typedef CurveDescriptionParameterBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + virtual DescriptionParameterNamesType GetDescriptionParameterName() const override; + + protected: + static const std::string PARAMETER_NAME; + + AreaUnderTheCurveDescriptionParameter(); + virtual ~AreaUnderTheCurveDescriptionParameter(); + + virtual DescriptionParameterResultsType ComputeCurveDescriptionParameter(const CurveType& curve, const CurveGridType& grid) const override; + + }; +} + +#endif // MITKAREAUNDERTHECURVEDESCRIPTIONPARAMETER_H diff --git a/Modules/Pharmacokinetics/include/mitkAterialInputFunctionGenerator.h b/Modules/Pharmacokinetics/include/mitkAterialInputFunctionGenerator.h new file mode 100644 index 0000000000..ee12ecfcc7 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkAterialInputFunctionGenerator.h @@ -0,0 +1,111 @@ +/*=================================================================== + + The Medical Imaging Interaction Toolkit (MITK) + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. + + See LICENSE.txt or http://www.mitk.org for details. + + ===================================================================*/ + +#ifndef ATERIALINPUTFUNCTIONGENERATOR_H +#define ATERIALINPUTFUNCTIONGENERATOR_H + +#include +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + + +namespace mitk +{ + /** \class AterialInputFunctionGenerator + * \brief Compute the Aterial Input Function from a given dynamic image and a mask defining the tumour supplying artery + * + * The AterialInputFunctionGenerator takes a given 4D dynamic image and a corresponding mask and returns an array of the averaged values and + * an array of the corresponding TimeGrid + * within the mask over time. No conversion is performed, so conversion from signal to concentration has to be performed in advanced + * and the resulting image is fed into the Generator. + * The generator checks wether both image and mask are set and passes them to the itkMaskedNaryStatisticsImageFilter and the mitkExtractTimeGrid, to + * calculate the mean of every time slice within the ROI and extract the corresponding time grid from the date set. + */ + class MITKPHARMACOKINETICS_EXPORT AterialInputFunctionGenerator : public itk::Object + { + public: + + mitkClassMacroItkParent(AterialInputFunctionGenerator, itk::Object); + itkNewMacro(Self); + + /** @brief Setter and Getter for Input Image for calculation of AIF, already converted to concentrations + * Getter calls CheckValidInputs() and CalculateAIFAndGetResult() if HasOutdatedResults() is true */ + itkSetConstObjectMacro(DynamicImage, Image); + itkGetConstObjectMacro(DynamicImage, Image); + + /** @brief Setter and Getter for mask defining the tumour feeding atery + * Getter calls CheckValidInputs() and CalculateAIFAndGetResult() if HasOutdatedResults() is true */ + itkSetConstObjectMacro(Mask, Image); + itkGetConstObjectMacro(Mask, Image); + + /** @brief Setter and Getter for the hematocritlevel, important for conversion to plasma curve*/ + itkSetMacro(HCL, double); + itkGetConstReferenceMacro(HCL, double); + + //Common Value for Hematocrit level is 0.45 + static const double DEFAULT_HEMATOCRIT_LEVEL; + + void SetDefaultHematocritLevel() + { + this->m_HCL = DEFAULT_HEMATOCRIT_LEVEL; + }; + double GetDefaultHematocritLevel() + { + return DEFAULT_HEMATOCRIT_LEVEL; + } + + AIFBasedModelBase::AterialInputFunctionType GetAterialInputFunction(); + ModelBase::TimeGridType GetAterialInputFunctionTimeGrid(); + + protected: + AterialInputFunctionGenerator() + { + m_Mask = NULL; + m_DynamicImage = NULL; + this->SetDefaultHematocritLevel(); + }; + + ~AterialInputFunctionGenerator() {}; + + //template + //void DoCalculateAIF(itk::Image* image); + + /** @brief Passes m_DynamicImage and m_Mask to the itkMaskedNaryStatisticsImageFilter and mitkExtractTimeGrid + * and inserts the result into m_AIFValues and m_AIFTimeGrid and modiefies the Timestamp*/ + virtual void CalculateAIFAndGetResult(); + + /** @brief Makes sure that m_DynamicImage and m_Mask are set */ + virtual void CheckValidInputs() const; + + bool HasOutdatedResults(); + + + itk::TimeStamp m_GenerationTimeStamp; + + private: + Image::ConstPointer m_DynamicImage; + Image::ConstPointer m_Mask; + + + AIFBasedModelBase::AterialInputFunctionType m_AIFValues; + ModelBase::TimeGridType m_AIFTimeGrid; + + double m_HCL; + }; + +} + +#endif // ATERIALINPUTFUNCTIONGENERATOR_H diff --git a/Modules/Pharmacokinetics/include/mitkConcentrationCurveGenerator.h b/Modules/Pharmacokinetics/include/mitkConcentrationCurveGenerator.h new file mode 100644 index 0000000000..2f44a4b1a3 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkConcentrationCurveGenerator.h @@ -0,0 +1,146 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef CONCENTRATIONCURVEGENERATOR_H +#define CONCENTRATIONCURVEGENERATOR_H + +#include +#include +#include "mitkConvertToConcentrationAbsoluteFunctor.h" +#include "mitkConvertToConcentrationRelativeFunctor.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk { + +/** \class ConcentrationCurveGenerator +* \brief Converts a given 4D mitk::Image with MR signal values into a 4D mitk::Image with corresponding contrast agent concentration values +* +* From a given 4D image, the Generator takes the 3D image of the first time point as baseline image. It then loops over all time steps, casts +* the current 3D image to itk and passes it to the ConvertToconcentrationFunctor. The returned 3D image has now values of concentration type and is stored at its timepoint +* in the return image. +*/ +class MITKPHARMACOKINETICS_EXPORT ConcentrationCurveGenerator : public itk::Object +{ +public: + + mitkClassMacroItkParent(ConcentrationCurveGenerator, itk::Object); + itkNewMacro(Self); + + //typedef itk::Image ImageType; + typedef itk::Image ConvertedImageType; + + + /** Getter and Setter for 4D mitk::Image*/ + itkSetObjectMacro(DynamicImage,Image); + itkGetConstObjectMacro(DynamicImage,Image); + + /** Parameters Relevant for conversion Calculation; Have to be Set externally (Sequence Dependend)*/ + itkSetMacro(RelaxationTime, double); + itkGetConstReferenceMacro(RelaxationTime, double); + + itkSetMacro(Relaxivity, double); + itkGetConstReferenceMacro(Relaxivity, double); + + itkSetMacro(RecoveryTime, double); + itkGetConstReferenceMacro(RecoveryTime, double); + + itkSetMacro(FlipAngle, double); + itkGetConstReferenceMacro(FlipAngle, double); + + itkSetMacro(Factor, double); + itkGetConstReferenceMacro(Factor, double); + + /** Getter and Setter for T10 Map image*/ + itkSetObjectMacro(T10Image,Image); + itkGetConstObjectMacro(T10Image,Image); + + itkSetMacro(T2Factor, double); + itkGetConstReferenceMacro(T2Factor, double); + + itkSetMacro(T2EchoTime, double); + itkGetConstReferenceMacro(T2EchoTime, double); + + /** @brief Calls Convert and returns the 4D mitk::image in Concentration units*/ + + itkSetMacro(isTurboFlashSequence,bool); + itkGetConstReferenceMacro(isTurboFlashSequence,bool); + + itkSetMacro(AbsoluteSignalEnhancement,bool); + itkGetConstReferenceMacro(AbsoluteSignalEnhancement,bool); + + itkSetMacro(RelativeSignalEnhancement,bool); + itkGetConstReferenceMacro(RelativeSignalEnhancement,bool); + + itkSetMacro(UsingT1Map,bool); + itkGetConstReferenceMacro(UsingT1Map,bool); + + + itkSetMacro(isT2weightedImage,bool); + itkGetConstReferenceMacro(isT2weightedImage,bool); + + Image::Pointer GetConvertedImage(); + +protected: + + ConcentrationCurveGenerator(); + ~ConcentrationCurveGenerator(); + + template + mitk::Image::Pointer convertToConcentration(mitk::Image::Pointer inputImage,mitk::Image::Pointer baselineImage); + + + /** Calls ConvertToconcentrationFunctor for passed 3D itk::image*/ +mitk::Image::Pointer ConvertSignalToConcentrationCurve(mitk::Image::Pointer inputImage, mitk::Image::Pointer baselineImage); + + + + /** @brief Takes the 3D image of the first timepoint to set as baseline image*/ + void PrepareBaselineImage(); + + /** @brief loops over all timepoints, casts the current timepoint 3D mitk::image to itk and passes it to ConvertSignalToConcentrationCurve */ + virtual void Convert(); + + +private: + Image::Pointer m_DynamicImage; + Image::Pointer m_BaselineImage; + Image::Pointer m_T10Image; + + Image::Pointer m_ConvertedImage; + + bool m_isT2weightedImage; + + bool m_isTurboFlashSequence; + bool m_AbsoluteSignalEnhancement; + bool m_RelativeSignalEnhancement; + bool m_UsingT1Map; + + double m_Factor; + //=Repetition Time TR + double m_RecoveryTime; + //= pre-CA T1 time + double m_RelaxationTime; + //= contrast agent relaxivity + double m_Relaxivity; + + double m_FlipAngle; + + double m_T2Factor; + double m_T2EchoTime; +}; + +} +#endif // CONCENTRATIONCURVEGENERATOR_H diff --git a/Modules/Pharmacokinetics/include/mitkConcreteAIFBasedModelFactory.h b/Modules/Pharmacokinetics/include/mitkConcreteAIFBasedModelFactory.h new file mode 100644 index 0000000000..1a4c87d2d4 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkConcreteAIFBasedModelFactory.h @@ -0,0 +1,76 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef MITK_CONCRETE_AIF_BASED_MODEL_FACTORY_H +#define MITK_CONCRETE_AIF_BASED_MODEL_FACTORY_H + +#include "mitkConcreteModelFactoryBase.h" +#include "mitkAIFParametrizerHelper.h" + +namespace mitk +{ + + template + class ConcreteAIFBasedModelFactory : public + mitk::ConcreteModelFactoryBase + { + public: + mitkClassMacro(ConcreteAIFBasedModelFactory, + ConcreteModelFactoryBase); + + typedef typename Superclass::ModelType ModelType; + typedef TModelParameterizer ModelParameterizerType; + + protected: + virtual ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit) + const + { + mitk::ModelParameterizerBase::Pointer result; + + typename ModelParameterizerType::Pointer modelParameterizer = + ModelParameterizerType::New(); + + modelFit::StaticParameterMap::ValueType aif = fit->staticParamMap.Get( + ModelType::NAME_STATIC_PARAMETER_AIF); + + modelParameterizer->SetAIF(mitk::convertParameterToArray(aif)); + + modelFit::StaticParameterMap::ValueType aifGrid = fit->staticParamMap.Get( + ModelType::NAME_STATIC_PARAMETER_AIFTimeGrid); + modelParameterizer->SetAIFTimeGrid(mitk::convertParameterToArray(aifGrid)); + + result = modelParameterizer.GetPointer(); + + return result; + }; + + ConcreteAIFBasedModelFactory() + { + }; + + virtual ~ConcreteAIFBasedModelFactory() + { + }; + + private: + + //No copy constructor allowed + ConcreteAIFBasedModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} +#endif // MITKTWOCOMPARTMENTEXCHANGEMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkConvertT2ConcentrationFunctor.h b/Modules/Pharmacokinetics/include/mitkConvertT2ConcentrationFunctor.h new file mode 100644 index 0000000000..71034c09a6 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkConvertT2ConcentrationFunctor.h @@ -0,0 +1,50 @@ +#ifndef MITKCONVERTT2CONCENTRATIONFUNCTOR +#define MITKCONVERTT2CONCENTRATIONFUNCTOR + +#include "MitkPharmacokineticsExports.h" + +namespace mitk { + + template + class MITKPHARMACOKINETICS_EXPORT ConvertT2ConcentrationFunctor + { + + public: + ConvertT2ConcentrationFunctor(): m_k(0.0), m_TE(0.0) {} ; + ~ConvertT2ConcentrationFunctor() {}; + + void initialize(double factor, double TE) + { + + this->m_k = factor; + this->m_TE = TE; + } + + bool operator!=( const ConvertT2ConcentrationFunctor & other)const + { + return !(*this == other); + } + bool operator==( const ConvertT2ConcentrationFunctor & other) const + { + return (this->m_k == other.m_k && this->m_TE == other.m_TE); + } + + inline TOutputpixel operator()( const TInputPixel1 & value, const TInputPixel2 & baseline) + { + TOutputpixel concentration(0); + if(value !=0 && baseline != 0) + { + concentration = this->m_k / this->m_TE * log((double)(value- baseline)) ; + } + return concentration; + } + + private: + double m_k; + double m_TE; + + }; + +} +#endif // MITKCONVERTT2CONCENTRATIONFUNCTOR + diff --git a/Modules/Pharmacokinetics/include/mitkConvertToConcentrationAbsoluteFunctor.h b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationAbsoluteFunctor.h new file mode 100644 index 0000000000..45913358c0 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationAbsoluteFunctor.h @@ -0,0 +1,46 @@ +#ifndef mitkConvertToConcentrationAbsoluteFunctor_h +#define mitkConvertToConcentrationAbsoluteFunctor_h + +#include "MitkPharmacokineticsExports.h" + +namespace mitk { + + template + class MITKPHARMACOKINETICS_EXPORT ConvertToConcentrationAbsoluteFunctor + { + + public: + ConvertToConcentrationAbsoluteFunctor(): m_k(0.0) {} ; + ~ConvertToConcentrationAbsoluteFunctor() {}; + + void initialize(double factor) + { + + m_k = factor; + } + + bool operator!=( const ConvertToConcentrationAbsoluteFunctor & other)const + { + return !(*this == other); + } + bool operator==( const ConvertToConcentrationAbsoluteFunctor & other) const + { + return (this->m_k == other.m_k); + } + + inline TOutputpixel operator()( const TInputPixel1 & value, const TInputPixel2 & baseline) + { + TOutputpixel concentration(0); + + concentration = this->m_k * (double)(value- baseline) ; + + return concentration; + } + + private: + double m_k; + + }; + +} +#endif // mitkConvertToConcentrationAbsoluteFunctor_h diff --git a/Modules/Pharmacokinetics/include/mitkConvertToConcentrationRelativeFunctor.h b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationRelativeFunctor.h new file mode 100644 index 0000000000..0958364b64 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationRelativeFunctor.h @@ -0,0 +1,49 @@ +#ifndef mitkConvertToConcentrationRelativeFunctor_h +#define mitkConvertToConcentrationRelativeFunctor_h + +#include "MitkPharmacokineticsExports.h" + +namespace mitk { + + template + class MITKPHARMACOKINETICS_EXPORT ConvertToConcentrationRelativeFunctor + { + + public: + ConvertToConcentrationRelativeFunctor(): m_k(0.0) {} ; + ~ConvertToConcentrationRelativeFunctor() {}; + + void initialize(double factor) + { + + m_k = factor; + } + + bool operator!=( const ConvertToConcentrationRelativeFunctor & other)const + { + return !(*this == other); + } + bool operator==( const ConvertToConcentrationRelativeFunctor & other) const + { + return (this->m_k == other.m_k); + } + + inline TOutputpixel operator()( const TInputPixel1 & value, const TInputPixel2 & baseline) + { + TOutputpixel concentration(0); + + if(baseline != 0) + { + concentration = this->m_k * (double)(value- baseline)/baseline ; + } + + return concentration; + } + + private: + double m_k; + + }; + +} +#endif // mitkConvertToConcentrationRelativeFunctor_h diff --git a/Modules/Pharmacokinetics/include/mitkConvertToConcentrationTurboFlashFunctor.h b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationTurboFlashFunctor.h new file mode 100644 index 0000000000..599bc3a4dc --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationTurboFlashFunctor.h @@ -0,0 +1,55 @@ +#ifndef MITKCONVERTTOCONCENTRATIONTURBOFLASCHFUNCTOR_H +#define MITKCONVERTTOCONCENTRATIONTURBOFLASCHFUNCTOR_H + +#include "MitkPharmacokineticsExports.h" + +namespace mitk { + + template + class MITKPHARMACOKINETICS_EXPORT ConvertToConcentrationTurboFlashFunctor + { + + public: + ConvertToConcentrationTurboFlashFunctor() : m_Trec(0), m_alpha(0), m_T10(0) {}; + ~ConvertToConcentrationTurboFlashFunctor() {}; + + void initialize(double relaxationtime, double relaxivity, double recoverytime) + { + m_Trec = relaxationtime; + m_alpha = relaxivity; + m_T10 = recoverytime; + } + + bool operator!=( const ConvertToConcentrationTurboFlashFunctor & other)const + { + return !(*this == other); + } + bool operator==( const ConvertToConcentrationTurboFlashFunctor & other) const + { + return (this->m_Trec == other.m_Trec) && (this->m_alpha == other.m_alpha) && (this->m_T10 == other.m_T10); + } + + inline TOutputpixel operator()( const TInputPixel1 & value, const TInputPixel2 & baseline) + { + TOutputpixel concentration(0); + + + //Only for TurboFLASH sequencen + if (baseline != 0 && ((double)value/baseline - exp(m_Trec/m_T10) * ((double)value/baseline - 1)) > 0 ) + { + concentration = -1 / (m_Trec * m_alpha) * log((double)value/baseline - exp(m_Trec/m_T10) * ((double)value/baseline - 1)); + } + + + return concentration; + } + + private: + double m_Trec; + double m_alpha; + double m_T10; + }; + +} + +#endif // MITKCONVERTTOCONCENTRATIONTURBOFLASCHFUNCTOR_H diff --git a/Modules/Pharmacokinetics/include/mitkConvertToConcentrationViaT1Functor.h b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationViaT1Functor.h new file mode 100644 index 0000000000..780d6b704d --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkConvertToConcentrationViaT1Functor.h @@ -0,0 +1,67 @@ +#ifndef MITKCONVERTTOCONCENTRATIONVIAT1CALCFUNCTOR_H +#define MITKCONVERTTOCONCENTRATIONVIAT1CALCFUNCTOR_H + +#include "itkMath.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk { + + template + class MITKPHARMACOKINETICS_EXPORT ConvertToConcentrationViaT1CalcFunctor + { + + public: + ConvertToConcentrationViaT1CalcFunctor(): m_relaxivity(0.0), m_TR(0.0), m_flipangle(0.0) {}; + ~ConvertToConcentrationViaT1CalcFunctor() {}; + + void initialize(double relaxivity, double TR, double flipangle) + { + + m_relaxivity = relaxivity; + m_TR = TR; + m_flipangle = flipangle; + } + + bool operator!=( const ConvertToConcentrationViaT1CalcFunctor & other) const + { + return !(*this == other); + + } + bool operator==( const ConvertToConcentrationViaT1CalcFunctor & other) const + { + return (this->m_relaxivity == other.m_relaxivity) && (this->m_TR == other.m_TR) && (this->m_flipangle == other.m_flipangle); + } + + + inline TOutputpixel operator()( const TInputPixel1 & value, const TInputPixel2 & baseline, const TInputPixel3 & nativeT1) + { + TOutputpixel concentration(0); + double R10, R1; + if (baseline !=0 && nativeT1 != 0 && value != 0) + { + double s = (double) value/baseline; + R10 = (double) 1/nativeT1; + double tmp1 = log(1-s + s*exp(-R10*m_TR) - exp(-R10*m_TR)* cos(m_flipangle)); + double tmp2 = (1-s*cos(m_flipangle) + s*exp(-R10*m_TR)*cos(m_flipangle) - exp(-R10*m_TR)* cos(m_flipangle)); + + R1 = (double) -1/m_TR * tmp1/tmp2 ; + + concentration = (double) (R1 - R10)/ m_relaxivity; + } + else + { + concentration = 0; + } + + return concentration; + } + private: + double m_relaxivity; + double m_TR; + double m_flipangle; + + }; + +} +#endif // MITKCONVERTTOCONCENTRATIONVIAT1CALCFUNCTOR_H diff --git a/Modules/Pharmacokinetics/include/mitkConvolutionHelper.h b/Modules/Pharmacokinetics/include/mitkConvolutionHelper.h new file mode 100644 index 0000000000..8c32455899 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkConvolutionHelper.h @@ -0,0 +1,157 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef mitkConvolutionHelper_h +#define mitkConvolutionHelper_h + +#include "itkArray.h" +#include "mitkAIFBasedModelBase.h" +#include +#include "MitkPharmacokineticsExports.h" + +namespace mitk { +/** @namespace convolution + * @brief Helper for itk implementation of vnl fourier transformation + * This namespace provides functions for the preperation of vnl_fft_1d, including a wrapper + * for wrapping the convolution kernel (turning it inside out) and a function for zeropadding + * to avoid convolution artefacts. */ + namespace convolution { + + /** Some typedefs concerning data structures needed for vnl_fft_1d, which has vnl_vector< vcl_complex< double > > + * as output typ of the forward transformation fwd_transform. Input is of type vnl_vector< vcl_complex< T > > + * but since itk::Array is derived from vnl_vector, this works as well*/ + + + + /** @brief Function that wraps the kernel */ +inline itk::Array wrap1d(itk::Array kernel) + { + int dim = kernel.GetNumberOfElements(); + itk::Array wrappedKernel(dim); + wrappedKernel.fill(0.); + for(int i=0; i< dim; ++i) + { + wrappedKernel.SetElement(i, kernel.GetElement((i+(dim/2))%dim)); + } + + return wrappedKernel; + } + + /** @brief Fuction for zeropadding (adding zeros) of an Array/vnl_vector, so that is has size paddedDimensions + * @param paddedDimensions Dimensions that the Array should have after padding (convolution dimensions) + * \remark dim = Dimensions of padded image --> PaddedDimension + * \remark m dimensions of larger image + * \remark n dimensions of image to be padded --> InitialDimension*/ + inline itk::Array zeropadding1d(itk::Array unpaddedSpectrum, int paddedDimension) + { + + int initialDimension = unpaddedSpectrum.GetNumberOfElements(); + + itk::Array paddedSpectrum(paddedDimension); + paddedSpectrum.fill(0.); + + if(paddedDimension > initialDimension) + { + unsigned int padding = paddedDimension - initialDimension; + + for(int i=0; i unpadAndScale(itk::Array convolutionResult, int initialDimension) + { + int transformationDimension = convolutionResult.size(); + unsigned int padding = transformationDimension - initialDimension; + + itk::Array scaledResult(initialDimension); + scaledResult.fill(0.0); + + for(int i = 0; i >, ready to + * be entered in fwd_transform*/ + + inline void prepareConvolution(const itk::Array& kernel, const itk::Array& spectrum, itk::Array& preparedKernel, itk::Array& preparedSpectrum ){ + int convolutionDimensions = kernel.GetSize() + spectrum.GetSize(); + +// itk::Array paddedKernel = zeropadding1d(kernel,convolutionDimensions); + preparedKernel=zeropadding1d(kernel,convolutionDimensions); + + preparedSpectrum = zeropadding1d(spectrum,convolutionDimensions); +// preparedKernel = wrap1d(paddedKernel); + } + + } + + inline itk::Array convoluteAIFWithExponential(mitk::ModelBase::TimeGridType timeGrid, mitk::AIFBasedModelBase::AterialInputFunctionType aif, double lambda) + { + /** @brief Iterative Formula to Convolve aif(t) with an exponential Residuefunction R(t) = exp(lambda*t) + **/ + typedef itk::Array ConvolutionResultType; + ConvolutionResultType convolution(timeGrid.GetSize()); + convolution.fill(0.0); + + convolution(0) = 0; + for(int i = 0; i< (timeGrid.GetSize()-1); ++i) + { + double dt = timeGrid(i+1) - timeGrid(i); + double m = (aif(i+1) - aif(i))/dt; + double edt = exp(-lambda *dt); + + convolution(i+1) =edt * convolution(i) + + (aif(i) - m*timeGrid(i))/lambda * (1 - edt ) + + m/(lambda * lambda) * ((lambda * timeGrid(i+1) - 1) - edt*(lambda*timeGrid(i) -1)); + + } + return convolution; + } + + + inline itk::Array convoluteAIFWithConstant(mitk::ModelBase::TimeGridType timeGrid, mitk::AIFBasedModelBase::AterialInputFunctionType aif, double constant) + { + /** @brief Iterative Formula to Convolve aif(t) with a constant value by linear interpolation of the Aif between sampling points + **/ + typedef itk::Array ConvolutionResultType; + ConvolutionResultType convolution(timeGrid.GetSize()); + convolution.fill(0.0); + + convolution(0) = 0; + for(int i = 0; i< (timeGrid.GetSize()-1); ++i) + { + double dt = timeGrid(i+1) - timeGrid(i); + double m = (aif(i+1) - aif(i))/dt; + + convolution(i+1) = convolution(i) + constant * (aif(i)*dt + m*timeGrid(i)*dt + m/2*(timeGrid(i+1)*timeGrid(i+1) - timeGrid(i)*timeGrid(i))); + + } + return convolution; + } + +} + +#endif // mitkConvolutionHelper_h diff --git a/Modules/Pharmacokinetics/include/mitkCurveDescriptionParameterBase.h b/Modules/Pharmacokinetics/include/mitkCurveDescriptionParameterBase.h new file mode 100644 index 0000000000..086f89d029 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkCurveDescriptionParameterBase.h @@ -0,0 +1,80 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef CURVEDESCRIPTIONPARAMETERBASE_H +#define CURVEDESCRIPTIONPARAMETERBASE_H + +#include + +#include +#include +#include +#include +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + /** Base class for functor that compute descriptive values for + a curve (e.g. like Area under the Curve, Time to peek, maximum,...) + @remark The derived classes must be implemented thread safe because GetCurveDescriptionParameter() + and GetDescriptionParameterName() of one instance may be called in + multi-threaded context (e.g. DescriptionParameterImageGeneratorBase + and derived classes). */ +class MITKPHARMACOKINETICS_EXPORT CurveDescriptionParameterBase : public itk::Object + { + public: + typedef CurveDescriptionParameterBase Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(CurveDescriptionParameterBase, itk::Object) + + typedef itk::Array CurveType; + typedef itk::Array CurveGridType; + + typedef double CurveDescriptionParameterResultType; + typedef std::string CurveDescriptionParameterNameType; + + typedef std::vector DescriptionParameterResultsType; + typedef std::vector DescriptionParameterNamesType; + + /** Returns the concrete description values for a curve. + * @pre Curve value vector and curve grid must have the same size*/ + DescriptionParameterResultsType GetCurveDescriptionParameter(const CurveType& curve, const CurveGridType& grid) const; + + /**Return the names of all descrition values that will be computed by the class. + * @post The order of names equales the order of the results of GetCurveDescriptionParameter().*/ + virtual DescriptionParameterNamesType GetDescriptionParameterName() const = 0 ; + + protected: + + /** Slot to implement the computation of the descriptor values.*/ + virtual DescriptionParameterResultsType ComputeCurveDescriptionParameter(const CurveType& curve, const CurveGridType& grid) const = 0; + + CurveDescriptionParameterBase(); + virtual ~CurveDescriptionParameterBase(); + + private: + + //No copy constructor allowed + CurveDescriptionParameterBase(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; +} + +#endif // CURVEDESCRIPTIONPARAMETERBASE_H diff --git a/Modules/Pharmacokinetics/include/mitkCurveParameterFunctor.h b/Modules/Pharmacokinetics/include/mitkCurveParameterFunctor.h new file mode 100644 index 0000000000..0ae6ca5ffc --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkCurveParameterFunctor.h @@ -0,0 +1,77 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef CURVE_PARAMETER_FUNCTOR_H +#define CURVE_PARAMETER_FUNCTOR_H + +#include "mitkCurveDescriptionParameterBase.h" +#include "mitkSimpleFunctorBase.h" +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + /**Functor for the curve description values by using the itkMulitOutputNaryImageFilter. + * You may register any number of CurveDescriptionParamterBase instances to the functor. + * The Functor will compute all values. + * @warning the functor must be threadsafe and so must be the registered CurveDescriptionParamterBase instances.*/ + class MITKPHARMACOKINETICS_EXPORT CurveParameterFunctor : public SimpleFunctorBase + { + public: + typedef CurveParameterFunctor Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkFactorylessNewMacro(Self); + itkTypeMacro(CurveParameterFunctor, SimpleFunctorBase); + + typedef CurveDescriptionParameterBase::CurveDescriptionParameterNameType ParameterNameType; + typedef CurveDescriptionParameterBase::DescriptionParameterNamesType ParameterNamesType; + using GridArrayType = SimpleFunctorBase::GridArrayType; + + virtual SimpleFunctorBase::OutputPixelVectorType Compute(const InputPixelVectorType & value) const override; + + virtual unsigned int GetNumberOfOutputs() const override; + + virtual GridArrayType GetGrid() const override; + itkSetMacro(Grid, GridArrayType); + + ParameterNamesType GetDescriptionParameterNames() const; + + /**@warning Teh function is currently not thread safe. + @todo reimplement with shareable lock to allow other class methods to be used parallel but lock this one exclusively.*/ + void ResetDescriptionParameters(); + /**@warning Teh function is currently not thread safe. + @todo reimplement with shareable lock to allow other class methods to be used parallel but lock this one exclusively.*/ + void RegisterDescriptionParameter(const ParameterNameType& parameterName, CurveDescriptionParameterBase* parameterFunction); + /**@warning Teh function is currently not thread safe. + @todo reimplement with shareable lock to allow other class methods to be used parallel but lock this one exclusively.*/ + const CurveDescriptionParameterBase* GetDescriptionParameterFunction(const ParameterNameType& parameterName) const; + + protected: + CurveParameterFunctor(); + ~CurveParameterFunctor(); + + private: + typedef std::map DescriptionParameterMapType; + DescriptionParameterMapType m_DescriptorMap; + GridArrayType m_Grid; + }; + +} + +#endif // CURVE_PARAMETER_FUNCTOR_H diff --git a/Modules/Pharmacokinetics/include/mitkDescriptionParameterImageGeneratorBase.h b/Modules/Pharmacokinetics/include/mitkDescriptionParameterImageGeneratorBase.h new file mode 100644 index 0000000000..1c74f80816 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkDescriptionParameterImageGeneratorBase.h @@ -0,0 +1,67 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_DESCRIPTION_PARAMETER_IMAGE_GENERATOR_BASE_H_ +#define __MITK_DESCRIPTION_PARAMETER_IMAGE_GENERATOR_BASE_H_ + +#include + +#include "mitkImage.h" + +#include "mitkCurveDescriptionParameterBase.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + class MITKPHARMACOKINETICS_EXPORT DescriptionParameterImageGeneratorBase: public ::itk::Object + { + public: + + mitkClassMacroItkParent(DescriptionParameterImageGeneratorBase, ::itk::Object); + + typedef ScalarType ParameterImagePixelType; + + typedef CurveDescriptionParameterBase::CurveDescriptionParameterNameType ParameterNameType; + + typedef std::map ParameterImageMapType; + + virtual double GetProgress() const = 0; + + void Generate(); + + ParameterImageMapType GetParameterImages(); + + protected: + DescriptionParameterImageGeneratorBase(); + virtual ~DescriptionParameterImageGeneratorBase(); + + virtual bool HasOutdatedResult() const; + + virtual void CheckValidInputs() const; + virtual void DoParameterCalculationAndGetResults(ParameterImageMapType& parameterImages) = 0; + + itk::TimeStamp m_GenerationTimeStamp; + + private: + + ParameterImageMapType m_ParameterImageMap; + + }; + +} + +#endif //__MITK_DESCRIPTION_PARAMETER_IMAGE_GENERATOR_BASE_H_ diff --git a/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModel.h b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModel.h new file mode 100644 index 0000000000..2473c86144 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModel.h @@ -0,0 +1,135 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef DESCRIPTIVEPHARMACOKINETICBRIXMODEL_H +#define DESCRIPTIVEPHARMACOKINETICBRIXMODEL_H + +#include + +#include "mitkModelBase.h" +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT DescriptivePharmacokineticBrixModel : public ModelBase + { + + public: + typedef DescriptivePharmacokineticBrixModel Self; + typedef ModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(DescriptivePharmacokineticBrixModel, ModelBase); + + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_A; + static const std::string NAME_PARAMETER_kep; + static const std::string NAME_PARAMETER_kel; + static const std::string NAME_PARAMETER_tlag; + static const std::string NAME_STATIC_PARAMETER_Tau; + static const std::string NAME_STATIC_PARAMETER_S0; + + static const std::string UNIT_PARAMETER_A; + static const std::string UNIT_PARAMETER_kep; + static const std::string UNIT_PARAMETER_kel; + static const std::string UNIT_PARAMETER_tlag; + static const std::string UNIT_STATIC_PARAMETER_Tau; + static const std::string UNIT_STATIC_PARAMETER_S0; + + static const unsigned int POSITION_PARAMETER_A; + static const unsigned int POSITION_PARAMETER_kep; + static const unsigned int POSITION_PARAMETER_kel; + + //tlag in minutes + static const unsigned int POSITION_PARAMETER_tlag; + + static const unsigned int NUMBER_OF_PARAMETERS; + + itkSetMacro(Tau, double); + itkGetConstReferenceMacro(Tau, double); + + itkSetMacro(S0, double); + itkGetConstReferenceMacro(S0, double); + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual std::string GetXAxisName() const override; + + virtual std::string GetXAxisUnit() const override; + + virtual std::string GetYAxisName() const override; + + virtual std::string GetYAxisUnit() const override; + + virtual ParameterNamesType GetParameterNames() const override; + + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + + virtual ParameterNamesType GetStaticParameterNames() const override; + virtual ParametersSizeType GetNumberOfStaticParameters() const override; + virtual ParamterUnitMapType GetStaticParameterUnits() const override; + + protected: + DescriptivePharmacokineticBrixModel(); + virtual ~DescriptivePharmacokineticBrixModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + + virtual void SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values) override; + virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const + override; + + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const; + + private: + /**injection time Tau in minutes [min]*/ + double m_Tau; + + /**Value of the first time step, thus base value to scale the signal. + * Default is 1.*/ + double m_S0; + + //No copy constructor allowed + DescriptivePharmacokineticBrixModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + + }; +} + + +#endif //DESCRIPTIVEPHARMACOKINETICBRIXMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModelFactory.h b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModelFactory.h new file mode 100644 index 0000000000..abf2721d68 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModelFactory.h @@ -0,0 +1,57 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __DESCRIPTIVEPHARMACOKINETICBRIXMODEL_FACTORY_H +#define __DESCRIPTIVEPHARMACOKINETICBRIXMODEL_FACTORY_H + +#include + +#include "mitkConcreteModelFactoryBase.h" +#include "mitkDescriptivePharmacokineticBrixModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT DescriptivePharmacokineticBrixModelFactory : public + ConcreteModelFactoryBase + { + public: + mitkClassMacro(DescriptivePharmacokineticBrixModelFactory, + ConcreteModelFactoryBase); + itkFactorylessNewMacro(Self); + + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + virtual ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit) + const; + + DescriptivePharmacokineticBrixModelFactory(); + + virtual ~DescriptivePharmacokineticBrixModelFactory(); + + private: + + //No copy constructor allowed + DescriptivePharmacokineticBrixModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + + +#endif //__DESCRIPTIVEPHARMACOKINETICBRIXMODEL_FACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModelParameterizer.h new file mode 100644 index 0000000000..c2c216409c --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModelParameterizer.h @@ -0,0 +1,96 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __DESCRIPTIVEPHARMACOKINETICBRIXMODEL_PARAMETERIZER_H +#define __DESCRIPTIVEPHARMACOKINETICBRIXMODEL_PARAMETERIZER_H + +#include "mitkConcreteModelParameterizerBase.h" +#include "mitkDescriptivePharmacokineticBrixModel.h" + +namespace mitk +{ + /** Parameterizer for the DescriptivePharmacokineticBrixModel that use an image + for initializing the model. This parameterizer is amongst others used for pixel based fiting + strategies. + @sa DescriptivePharmacokineticBrixModelParameterizer*/ + class MITKPHARMACOKINETICS_EXPORT DescriptivePharmacokineticBrixModelParameterizer : public + ConcreteModelParameterizerBase + { + public: + typedef DescriptivePharmacokineticBrixModelParameterizer Self; + typedef ConcreteModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ConcreteModelParameterizerBase, ModelParameterizerBase); + itkNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef Superclass::ModelPointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef itk::Image BaseImageType; + + typedef Superclass::IndexType IndexType; + + itkSetMacro(Tau, double); + itkGetConstReferenceMacro(Tau, double); + + itkSetConstObjectMacro(BaseImage, BaseImageType); + itkGetConstObjectMacro(BaseImage, BaseImageType); + + /* Returns the global static parameters for the model. + * @remark this default implementation assumes no global static parameters exist. + * Thus an empty map is returned.*/ + virtual StaticParameterMapType GetGlobalStaticParameters() const; + + /* Returns the local static parameters for the model at the given index. + * @remark this default implementation assumes no local static parameters exist. + * Thus an empty map is returned.*/ + virtual StaticParameterMapType GetLocalStaticParameters(const IndexType& currentPosition) const; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + + DescriptivePharmacokineticBrixModelParameterizer(); + + virtual ~DescriptivePharmacokineticBrixModelParameterizer(); + + /**injection time Tau in minutes [min]*/ + double m_Tau; + + /**Pointer to the image that containes the values of the first timestep + (base value of the series that should be modelled)*/ + BaseImageType::ConstPointer m_BaseImage; + + private: + + //No copy constructor allowed + DescriptivePharmacokineticBrixModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // __DESCRIPTIVEPHARMACOKINETICBRIXMODEL_PARAMETERIZER_H diff --git a/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModelValueBasedParameterizer.h b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModelValueBasedParameterizer.h new file mode 100644 index 0000000000..7c9f0b0b82 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkDescriptivePharmacokineticBrixModelValueBasedParameterizer.h @@ -0,0 +1,94 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __DESCRIPTIVEPHARMACOKINETICBRIXMODEL_VALUEBASED_PARAMETERIZER_H +#define __DESCRIPTIVEPHARMACOKINETICBRIXMODEL_VALUEBASED_PARAMETERIZER_H + +#include "mitkConcreteModelParameterizerBase.h" + +namespace mitk +{ + /** Parameterizer for the DescriptivePharmacokineticBrixModel that don't use an image + for initializing the model but a single signal value. This parameterizer is amongst + others used for ROI based fiting strategies where no complete image is needed/used. + @sa DescriptivePharmacokineticBrixModelParameterizer*/ + class MITKPHARMACOKINETICS_EXPORT DescriptivePharmacokineticBrixModelValueBasedParameterizer : public + ConcreteModelParameterizerBase + { + public: + typedef DescriptivePharmacokineticBrixModelValueBasedParameterizer Self; + typedef ConcreteModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ConcreteModelParameterizerBase, ModelParameterizerBase); + itkNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef Superclass::ModelPointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef itk::Image BaseImageType; + + typedef Superclass::IndexType IndexType; + + itkSetMacro(Tau, double); + itkGetConstReferenceMacro(Tau, double); + + itkSetMacro(BaseValue, double); + itkGetConstReferenceMacro(BaseValue, double); + + /* Returns the global static parameters for the model. + * @remark this default implementation assumes no global static parameters exist. + * Thus an empty map is returned.*/ + virtual StaticParameterMapType GetGlobalStaticParameters() const; + + /* Returns the local static parameters for the model at the given index. + * @remark this default implementation assumes no local static parameters exist. + * Thus an empty map is returned.*/ + virtual StaticParameterMapType GetLocalStaticParameters(const IndexType& currentPosition) const; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + + DescriptivePharmacokineticBrixModelValueBasedParameterizer(); + + virtual ~DescriptivePharmacokineticBrixModelValueBasedParameterizer(); + + /**injection time Tau in minutes [min]*/ + double m_Tau; + + /** Contains the base value that should be used by the model.*/ + double m_BaseValue; + + private: + + //No copy constructor allowed + DescriptivePharmacokineticBrixModelValueBasedParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // __DESCRIPTIVEPHARMACOKINETICBRIXMODEL_VALUEBASED_PARAMETERIZER_H diff --git a/Modules/Pharmacokinetics/include/mitkExtendedOneTissueCompartmentModel.h b/Modules/Pharmacokinetics/include/mitkExtendedOneTissueCompartmentModel.h new file mode 100644 index 0000000000..cf032ad43c --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkExtendedOneTissueCompartmentModel.h @@ -0,0 +1,84 @@ +#ifndef MITKEXTENDEDONETISSUECOMPARTMENTMODEL_H +#define MITKEXTENDEDONETISSUECOMPARTMENTMODEL_H + +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + /** @class OneTissueCompartmentModel + * @brief Implementation of the Model function of the Tofts pharmacokinetic model, using an Aterial Input Function + * The Model calculates the Concentration-Time-Curve as a convolution of the plasma curve Cp (the AIF) and a tissue specific + * residue function (in this case an exponential: R(t) = ktrans * exp(-ktrans/ve * (t)) ). + * C(t) = vp * Cp(t) + conv(Cp(t),R(t)) + * The parameters ktrans, ve and ve are subject to the fitting routine*/ + + class MITKPHARMACOKINETICS_EXPORT ExtendedOneTissueCompartmentModel : public AIFBasedModelBase + { + + public: + typedef ExtendedOneTissueCompartmentModel Self; + typedef AIFBasedModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ExtendedOneTissueCompartmentModel, ModelBase); + + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_k1; + static const std::string NAME_PARAMETER_k2; + static const std::string NAME_PARAMETER_VB; + + static const std::string UNIT_PARAMETER_k1; + static const std::string UNIT_PARAMETER_k2; + static const std::string UNIT_PARAMETER_VB; + + static const unsigned int POSITION_PARAMETER_k1; + static const unsigned int POSITION_PARAMETER_k2; + static const unsigned int POSITION_PARAMETER_VB; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual ParameterNamesType GetParameterNames() const override; + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + protected: + ExtendedOneTissueCompartmentModel(); + virtual ~ExtendedOneTissueCompartmentModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const override; + + private: + + + //No copy constructor allowed + ExtendedOneTissueCompartmentModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + + + + }; +} + +#endif // MITKEXTENDEDONETISSUECOMPARTMENTMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkExtendedOneTissueCompartmentModelFactory.h b/Modules/Pharmacokinetics/include/mitkExtendedOneTissueCompartmentModelFactory.h new file mode 100644 index 0000000000..cd57c9499d --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkExtendedOneTissueCompartmentModelFactory.h @@ -0,0 +1,58 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKEXTENDEDONETISSUECOMPARTMENTMODELFACTORY_H +#define MITKEXTENDEDONETISSUECOMPARTMENTMODELFACTORY_H + +#include "mitkConcreteAIFBasedModelFactory.h" +#include "mitkExtendedOneTissueCompartmentModel.h" +#include "mitkExtendedOneTissueCompartmentModelParameterizer.h" + +namespace mitk +{ + + + class MITKPHARMACOKINETICS_EXPORT ExtendedOneTissueCompartmentModelFactory : public + mitk::ConcreteAIFBasedModelFactory< ExtendedOneTissueCompartmentModelParameterizer> + { + public: + mitkClassMacro(ExtendedOneTissueCompartmentModelFactory, + ConcreteAIFBasedModelFactory); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelType ModelType; + typedef Superclass::ModelParameterizerType ModelParameterizerType; + + ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override; + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + + ExtendedOneTissueCompartmentModelFactory(); + + virtual ~ExtendedOneTissueCompartmentModelFactory(); + + private: + + //No copy constructor allowed + ExtendedOneTissueCompartmentModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} + +#endif // MITKEXTENDEDONETISSUECOMPARTMENTMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkExtendedOneTissueCompartmentModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkExtendedOneTissueCompartmentModelParameterizer.h new file mode 100644 index 0000000000..d0d74e03ee --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkExtendedOneTissueCompartmentModelParameterizer.h @@ -0,0 +1,70 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKEXTENDEDONETISSUECOMPARTMENTMODELPARAME_H +#define MITKEXTENDEDONETISSUECOMPARTMENTMODELPARAME_H + +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkExtendedOneTissueCompartmentModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT ExtendedOneTissueCompartmentModelParameterizer : public + mitk::AIFBasedModelParameterizerBase + { + public: + typedef ExtendedOneTissueCompartmentModelParameterizer Self; + typedef mitk::AIFBasedModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ExtendedOneTissueCompartmentModelParameterizer, + mitk::AIFBasedModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + ExtendedOneTissueCompartmentModelParameterizer(); + + virtual ~ExtendedOneTissueCompartmentModelParameterizer(); + + private: + + //No copy constructor allowed + ExtendedOneTissueCompartmentModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} + +#endif // MITKEXTENDEDONETISSUECOMPARTMENTMODELPARAME_H diff --git a/Modules/Pharmacokinetics/include/mitkExtendedToftsModel.h b/Modules/Pharmacokinetics/include/mitkExtendedToftsModel.h new file mode 100644 index 0000000000..cddc64c4e8 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkExtendedToftsModel.h @@ -0,0 +1,94 @@ +#ifndef MITKEXTENDEDTOFTSMODEL_H +#define MITKEXTENDEDTOFTSMODEL_H + +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + /** @class ExtendedToftsModel + * @brief Implementation of the Model function of the Tofts pharmacokinetic model, using an Aterial Input Function + * The Model calculates the Concentration-Time-Curve as a convolution of the plasma curve Cp (the AIF) and a tissue specific + * residue function (in this case an exponential: R(t) = ktrans * exp(-ktrans/ve * (t)) ). + * C(t) = vp * Cp(t) + conv(Cp(t),R(t)) + * The parameters ktrans, ve and ve are subject to the fitting routine*/ + + class MITKPHARMACOKINETICS_EXPORT ExtendedToftsModel : public AIFBasedModelBase + { + + public: + typedef ExtendedToftsModel Self; + typedef AIFBasedModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ExtendedToftsModel, ModelBase); + + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_Ktrans; + static const std::string NAME_PARAMETER_ve; + static const std::string NAME_PARAMETER_vp; + + static const std::string UNIT_PARAMETER_Ktrans; + static const std::string UNIT_PARAMETER_ve; + static const std::string UNIT_PARAMETER_vp; + + static const unsigned int POSITION_PARAMETER_Ktrans; + static const unsigned int POSITION_PARAMETER_ve; + static const unsigned int POSITION_PARAMETER_vp; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual ParameterNamesType GetParameterNames() const override; + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + virtual ParameterNamesType GetDerivedParameterNames() const override; + + virtual ParametersSizeType GetNumberOfDerivedParameters() const override; + virtual ParamterUnitMapType GetDerivedParameterUnits() const override; + + + protected: + ExtendedToftsModel(); + virtual ~ExtendedToftsModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + + virtual DerivedParameterMapType ComputeDerivedParameters(const mitk::ModelBase::ParametersType& + parameters) const; + + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const override; + + private: + + + //No copy constructor allowed + ExtendedToftsModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + + + + }; +} + +#endif // MITKEXTENDEDTOFTSMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkExtendedToftsModelFactory.h b/Modules/Pharmacokinetics/include/mitkExtendedToftsModelFactory.h new file mode 100644 index 0000000000..e4e5e49e0f --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkExtendedToftsModelFactory.h @@ -0,0 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef MITKEXTENDEDTOFTSMODELFACTORY_H +#define MITKEXTENDEDTOFTSMODELFACTORY_H + +#include "mitkConcreteAIFBasedModelFactory.h" +#include "mitkExtendedToftsModel.h" +#include "mitkExtendedToftsModelParameterizer.h" + +namespace mitk +{ + + + class MITKPHARMACOKINETICS_EXPORT ExtendedToftsModelFactory : public + mitk::ConcreteAIFBasedModelFactory + { + public: + mitkClassMacro(ExtendedToftsModelFactory, + ConcreteAIFBasedModelFactory); + itkFactorylessNewMacro(Self); + + using ModelType = Superclass::ModelType; + using ModelParameterizerType = Superclass::ModelParameterizerType; + + ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override; + virtual ParametersType GetDefaultInitialParameterization() const override; + + protected: + + ExtendedToftsModelFactory(); + + virtual ~ExtendedToftsModelFactory() override; + + private: + + //No copy constructor allowed + ExtendedToftsModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} +#endif // MITKEXTENDEDTOFTSMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkExtendedToftsModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkExtendedToftsModelParameterizer.h new file mode 100644 index 0000000000..c43a773193 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkExtendedToftsModelParameterizer.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKEXTENDEDTOFTSMODELPARAMETRIZER_H +#define MITKEXTENDEDTOFTSMODELPARAMETRIZER_H + +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkExtendedToftsModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT ExtendedToftsModelParameterizer : public + mitk::AIFBasedModelParameterizerBase + { + public: + typedef ExtendedToftsModelParameterizer Self; + typedef mitk::AIFBasedModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ExtendedToftsModelParameterizer, + mitk::AIFBasedModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + ExtendedToftsModelParameterizer(); + + virtual ~ExtendedToftsModelParameterizer(); + + private: + + //No copy constructor allowed + ExtendedToftsModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} +#endif diff --git a/Modules/Pharmacokinetics/include/mitkImageGenerationHelper.h b/Modules/Pharmacokinetics/include/mitkImageGenerationHelper.h new file mode 100644 index 0000000000..1eb4771a71 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkImageGenerationHelper.h @@ -0,0 +1,77 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __MITK_IMAGEGENERATIONHELPER_H +#define __MITK_IMAGEGENERATIONHELPER_H + +#include "itkImage.h" +#include "itkImageRegionIterator.h" + +#include "mitkImage.h" +#include "mitkImagePixelReadAccessor.h" + + + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + +/** @todo #3 this is a helper class for generating a 4D dynamic image of dimensions (x,y,z, t) from an itk::Array (t) + * The Array will be set at every (x,y,z), so the result is a homogeneous image in 3D, with the 4th dimension as the Array. + * Function GenerateDynamicImageMITK was copied from TestingHelper/TestArtifactGenerator. Maybe there is a better way to do this. + */ +class MITKPHARMACOKINETICS_EXPORT ImageGenerationHelper : public itk::Object +{ + +public: + mitkClassMacroItkParent(ImageGenerationHelper, ::itk::Object); + + itkNewMacro(Self); + + typedef itk::Image TestImageType; + typedef itk::Array TimeGridType; + typedef itk::Array CurveType; + + itkSetMacro(DimX, unsigned int); + itkSetMacro(DimY, unsigned int); + itkSetMacro(DimZ, unsigned int); + itkGetConstReferenceMacro(DimX, unsigned int); + itkGetConstReferenceMacro(DimY, unsigned int); + itkGetConstReferenceMacro(DimZ, unsigned int); + + itkSetMacro(Grid,TimeGridType); + itkGetConstReferenceMacro(Grid,TimeGridType); + + itkSetMacro(Curve, CurveType); + itkGetConstReferenceMacro(Curve,CurveType) + + Image::Pointer GenerateDynamicImageMITK(); + +private: + ImageGenerationHelper(): m_DimX(0), m_DimY(0), m_DimZ(0) {}; + ~ImageGenerationHelper(){}; + + mitk::Image::Pointer GenerateTestFrame(unsigned int timePointIndex); + unsigned int m_DimX, m_DimY, m_DimZ; + TimeGridType m_Grid; + CurveType m_Curve; + + +}; +} + +#endif //__MITK_IMAGEGENERATIONHELPER_H diff --git a/Modules/Pharmacokinetics/include/mitkMaximumCurveDescriptionParameter.h b/Modules/Pharmacokinetics/include/mitkMaximumCurveDescriptionParameter.h new file mode 100644 index 0000000000..4e8a2690ab --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkMaximumCurveDescriptionParameter.h @@ -0,0 +1,49 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKMAXIMUMCURVEDESCRIPTIONPARAMETER_H +#define MITKMAXIMUMCURVEDESCRIPTIONPARAMETER_H + +#include "mitkCurveDescriptionParameterBase.h" + +namespace mitk { + + /** Descriptor computes the maximum of the curve.*/ +class MITKPHARMACOKINETICS_EXPORT MaximumCurveDescriptionParameter : public mitk::CurveDescriptionParameterBase +{ +public: + typedef mitk::MaximumCurveDescriptionParameter Self; + typedef CurveDescriptionParameterBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + virtual DescriptionParameterNamesType GetDescriptionParameterName() const override; + +protected: + static const std::string PARAMETER_NAME; + + MaximumCurveDescriptionParameter(); + virtual ~MaximumCurveDescriptionParameter(); + + virtual DescriptionParameterResultsType ComputeCurveDescriptionParameter(const CurveType& curve, const CurveGridType& grid) const override; +}; + + + +} +#endif // MITKMAXIMUMCONCENTRATIONCURVEDESCRIPTIONPARAMETER_H diff --git a/Modules/Pharmacokinetics/include/mitkMeanResidenceTimeDescriptionParameter.h b/Modules/Pharmacokinetics/include/mitkMeanResidenceTimeDescriptionParameter.h new file mode 100644 index 0000000000..e6da1ddad3 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkMeanResidenceTimeDescriptionParameter.h @@ -0,0 +1,33 @@ +#ifndef MEANRESIDENCETIMEDESCRIPTIONPARAMETER_H +#define MEANRESIDENCETIMEDESCRIPTIONPARAMETER_H + + +#include "mitkCurveDescriptionParameterBase.h" + +namespace mitk +{ + + /** Description parameter that computes the area under the curve */ + class MITKPHARMACOKINETICS_EXPORT MeanResidenceTimeDescriptionParameter : public mitk::CurveDescriptionParameterBase + { + public: + typedef mitk::MeanResidenceTimeDescriptionParameter Self; + typedef CurveDescriptionParameterBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + virtual DescriptionParameterNamesType GetDescriptionParameterName() const override; + + protected: + static const std::string PARAMETER_NAME; + + MeanResidenceTimeDescriptionParameter(); + virtual ~MeanResidenceTimeDescriptionParameter(); + + virtual DescriptionParameterResultsType ComputeCurveDescriptionParameter(const CurveType& curve, const CurveGridType& grid) const override; + + }; +} +#endif // MEANRESIDENCETIMEDESCRIPTIONPARAMETER_H diff --git a/Modules/Pharmacokinetics/include/mitkNumericTwoCompartmentExchangeModel.h b/Modules/Pharmacokinetics/include/mitkNumericTwoCompartmentExchangeModel.h new file mode 100644 index 0000000000..38d6dd181c --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkNumericTwoCompartmentExchangeModel.h @@ -0,0 +1,116 @@ +#ifndef MITKNUMERICTWOCOMPARTMENTEXCHANGEMODEL_H +#define MITKNUMERICTWOCOMPARTMENTEXCHANGEMODEL_H + +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + + +namespace mitk +{ + /** @class NumericTwoCompartmentExchangeModel + * @brief Implementation of the numeric model function of the 2 Compartment Exchange model, using an Aterial Input Function + * The Model calculates the measured Concentration-Time-Curve from the mass balance equations of the 2-tissue compartent Model + * + * vp * dCp(t)/dt = F * (CA(t) - Cp(t)) - PS * (Cp(t) - Ci(t)) + * ve * dCi(t)/dt = PS * (Cp(t) - Ci(t)) + * + * with concentration curve Cp(t) of the Blood Plasma p and Ce(t) of the Extracellular Extravascular Space(EES)(interstitial volume). CA(t) is the aterial concentration, i.e. the AIF + * Cp(t) and Ce(t) are found numerical via Runge-Kutta methode, implemented in Boosts numeric library ODEINT. Here we use a runge_kutta_cash_karp54 stepper with + * adaptive step size and error controll. + * From the resulting curves Cp(t) and Ce(t) the measured concentration Ctotal(t) is found vial + * + * Ctotal(t) = vp * Cp(t) + ve * Ce(t) + * + * where vp=Vp/VT and ve=Ve/VT are the portion of Plasma/EES volume Vp/Ve of the total volume VT respectively. + * The parameters PS, F, vp and ve are subject to the fitting routine*/ + + class MITKPHARMACOKINETICS_EXPORT NumericTwoCompartmentExchangeModel : public AIFBasedModelBase + { + + public: + typedef NumericTwoCompartmentExchangeModel Self; + typedef AIFBasedModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** Run-time type information (and related methods). */ + itkTypeMacro(NumericTwoCompartmentExchangeModel, ModelBase) + + typedef std::vector state_type; + + + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_F; + static const std::string NAME_PARAMETER_PS; + static const std::string NAME_PARAMETER_ve; + static const std::string NAME_PARAMETER_vp; + static const std::string NAME_STATIC_PARAMETER_ODEINTStepSize; + + static const std::string UNIT_PARAMETER_F; + static const std::string UNIT_PARAMETER_PS; + static const std::string UNIT_PARAMETER_ve; + static const std::string UNIT_PARAMETER_vp; + + static const unsigned int POSITION_PARAMETER_F; + static const unsigned int POSITION_PARAMETER_PS; + static const unsigned int POSITION_PARAMETER_ve; + static const unsigned int POSITION_PARAMETER_vp; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + itkGetConstReferenceMacro(ODEINTStepSize, double); + itkSetMacro(ODEINTStepSize, double); + + + virtual ParameterNamesType GetParameterNames() const override; + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + virtual ParameterNamesType GetStaticParameterNames() const; + virtual ParametersSizeType GetNumberOfStaticParameters() const; + + + protected: + NumericTwoCompartmentExchangeModel(); + virtual ~NumericTwoCompartmentExchangeModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + + virtual void SetStaticParameter(const ParameterNameType& name, const StaticParameterValuesType& values); + virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const; + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const; + + private: + + + + //No copy constructor allowed + NumericTwoCompartmentExchangeModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + double m_ODEINTStepSize; + + + + }; +} + +#endif // MITKNUMERICTWOCOMPARTMENTEXCHANGEMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkNumericTwoCompartmentExchangeModelFactory.h b/Modules/Pharmacokinetics/include/mitkNumericTwoCompartmentExchangeModelFactory.h new file mode 100644 index 0000000000..0d845f7dab --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkNumericTwoCompartmentExchangeModelFactory.h @@ -0,0 +1,50 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef MITKNUMERICTWOCOMPARTMENTEXCHANGEMODELFACTORY_H +#define MITKNUMERICTWOCOMPARTMENTEXCHANGEMODELFACTORY_H + +#include "mitkTwoCompartmentExchangeModelFactoryBase.h" +#include "mitkNumericTwoCompartmentExchangeModelParameterizer.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT NumericTwoCompartmentExchangeModelFactory : public + mitk::TwoCompartmentExchangeModelFactoryBase + { + public: + mitkClassMacro(NumericTwoCompartmentExchangeModelFactory, + TwoCompartmentExchangeModelFactoryBase); + itkFactorylessNewMacro(Self); + + protected: + + ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit) const; + + NumericTwoCompartmentExchangeModelFactory(); + + virtual ~NumericTwoCompartmentExchangeModelFactory(); + + private: + + //No copy constructor allowed + NumericTwoCompartmentExchangeModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} +#endif // MITKTWOCOMPARTMENTEXCHANGEMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkNumericTwoCompartmentExchangeModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkNumericTwoCompartmentExchangeModelParameterizer.h new file mode 100644 index 0000000000..c548d2a8ba --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkNumericTwoCompartmentExchangeModelParameterizer.h @@ -0,0 +1,81 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKNUMERICTWOCOMPARTMENTEXCHANGEMODELPARAMETRIZER_H +#define MITKNUMERICTWOCOMPARTMENTEXCHANGEMODELPARAMETRIZER_H + +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkNumericTwoCompartmentExchangeModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT NumericTwoCompartmentExchangeModelParameterizer : public + mitk::AIFBasedModelParameterizerBase + { + public: + typedef NumericTwoCompartmentExchangeModelParameterizer Self; + typedef mitk::AIFBasedModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(NumericTwoCompartmentExchangeModelParameterizer, + mitk::AIFBasedModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + itkSetMacro(ODEINTStepSize, double); + itkGetConstReferenceMacro(ODEINTStepSize, double); + + /** Returns the global static parameters for the model. + * @remark this default implementation assumes only AIF and its timegrid as static parameters. + * Reimplement in derived classes to change this behavior.*/ + virtual StaticParameterMapType GetGlobalStaticParameters() const; + + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + + double m_ODEINTStepSize; + + NumericTwoCompartmentExchangeModelParameterizer(); + + virtual ~NumericTwoCompartmentExchangeModelParameterizer(); + + private: + + //No copy constructor allowed + NumericTwoCompartmentExchangeModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} +#endif diff --git a/Modules/Pharmacokinetics/include/mitkNumericTwoTissueCompartmentModel.h b/Modules/Pharmacokinetics/include/mitkNumericTwoTissueCompartmentModel.h new file mode 100644 index 0000000000..cc7eb67497 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkNumericTwoTissueCompartmentModel.h @@ -0,0 +1,101 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKNUMERICTWOTISSUECOMPARTMENTMODEL_H +#define MITKNUMERICTWOTISSUECOMPARTMENTMODEL_H + +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + + +namespace mitk +{ + class MITKPHARMACOKINETICS_EXPORT NumericTwoTissueCompartmentModel : public AIFBasedModelBase + { + + public: + typedef NumericTwoTissueCompartmentModel Self; + typedef AIFBasedModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** Run-time type information (and related methods). */ + itkTypeMacro(NumericTwoTissueCompartmentModel, ModelBase) + + typedef std::vector state_type; + + + /** Model Specifications */ + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_K1; + static const std::string NAME_PARAMETER_k2; + static const std::string NAME_PARAMETER_k3; + static const std::string NAME_PARAMETER_k4; + static const std::string NAME_PARAMETER_VB; + + static const std::string UNIT_PARAMETER_K1; + static const std::string UNIT_PARAMETER_k2; + static const std::string UNIT_PARAMETER_k3; + static const std::string UNIT_PARAMETER_k4; + static const std::string UNIT_PARAMETER_VB; + + static const unsigned int POSITION_PARAMETER_K1; + static const unsigned int POSITION_PARAMETER_k2; + static const unsigned int POSITION_PARAMETER_k3; + static const unsigned int POSITION_PARAMETER_k4; + static const unsigned int POSITION_PARAMETER_VB; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual ParameterNamesType GetParameterNames() const override; + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + protected: + NumericTwoTissueCompartmentModel(); + virtual ~NumericTwoTissueCompartmentModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const; + + private: + + + //No copy constructor allowed + NumericTwoTissueCompartmentModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; +} + +#endif // MITKNUMERICTWOTISSUECOMPARTMENTMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkNumericTwoTissueCompartmentModelFactory.h b/Modules/Pharmacokinetics/include/mitkNumericTwoTissueCompartmentModelFactory.h new file mode 100644 index 0000000000..bfaedf7d82 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkNumericTwoTissueCompartmentModelFactory.h @@ -0,0 +1,52 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKNUMERICTWOTISSUECOMPARTMENTMODELFACTORY_H +#define MITKNUMERICTWOTISSUECOMPARTMENTMODELFACTORY_H + +#include "mitkTwoTissueCompartmentModelFactoryBase.h" +#include "mitkNumericTwoTissueCompartmentModelParameterizer.h" + +namespace mitk +{ + + + class MITKPHARMACOKINETICS_EXPORT NumericTwoTissueCompartmentModelFactory : public + mitk::TwoTissueCompartmentModelFactoryBase + { + public: + mitkClassMacro(NumericTwoTissueCompartmentModelFactory, + TwoTissueCompartmentModelFactoryBase); + itkFactorylessNewMacro(Self); + + protected: + + NumericTwoTissueCompartmentModelFactory(); + + virtual ~NumericTwoTissueCompartmentModelFactory(); + + private: + + //No copy constructor allowed + NumericTwoTissueCompartmentModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} + + +#endif // MITKNUMERICTWOTISSUECOMPARTMENTMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkNumericTwoTissueCompartmentModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkNumericTwoTissueCompartmentModelParameterizer.h new file mode 100644 index 0000000000..dfea16aec5 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkNumericTwoTissueCompartmentModelParameterizer.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKNUMERICTWOTISSUECOMPARTMENTMODELPARAMETERIZER_H +#define MITKNUMERICTWOTISSUECOMPARTMENTMODELPARAMETERIZER_H + +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkNumericTwoTissueCompartmentModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT NumericTwoTissueCompartmentModelParameterizer : public + mitk::AIFBasedModelParameterizerBase + { + public: + typedef NumericTwoTissueCompartmentModelParameterizer Self; + typedef mitk::AIFBasedModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(NumericTwoTissueCompartmentModelParameterizer, + mitk::AIFBasedModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + NumericTwoTissueCompartmentModelParameterizer(); + + virtual ~NumericTwoTissueCompartmentModelParameterizer(); + + private: + + //No copy constructor allowed + NumericTwoTissueCompartmentModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} +#endif diff --git a/Modules/Pharmacokinetics/include/mitkOneTissueCompartmentModel.h b/Modules/Pharmacokinetics/include/mitkOneTissueCompartmentModel.h new file mode 100644 index 0000000000..b9d2ea989a --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkOneTissueCompartmentModel.h @@ -0,0 +1,82 @@ +#ifndef MITKONETISSUECOMPARTMENTMODEL_H +#define MITKONETISSUECOMPARTMENTMODEL_H + +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + /** @class OneTissueCompartmentModel + * @brief Implementation of the Model function of the Tofts pharmacokinetic model, using an Aterial Input Function + * The Model calculates the Concentration-Time-Curve as a convolution of the plasma curve Cp (the AIF) and a tissue specific + * residue function (in this case an exponential: R(t) = ktrans * exp(-ktrans/ve * (t)) ). + * C(t) = vp * Cp(t) + conv(Cp(t),R(t)) + * The parameters ktrans, ve and ve are subject to the fitting routine*/ + + class MITKPHARMACOKINETICS_EXPORT OneTissueCompartmentModel : public AIFBasedModelBase + { + + public: + typedef OneTissueCompartmentModel Self; + typedef AIFBasedModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(OneTissueCompartmentModel, ModelBase); + + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_k1; + static const std::string NAME_PARAMETER_k2; + + static const std::string UNIT_PARAMETER_k1; + static const std::string UNIT_PARAMETER_k2; + + static const unsigned int POSITION_PARAMETER_k1; + static const unsigned int POSITION_PARAMETER_k2; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual ParameterNamesType GetParameterNames() const override; + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + + protected: + OneTissueCompartmentModel(); + virtual ~OneTissueCompartmentModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const override; + + private: + + + //No copy constructor allowed + OneTissueCompartmentModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + + + + }; +} + +#endif // MITKONETISSUECOMPARTMENTMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkOneTissueCompartmentModelFactory.h b/Modules/Pharmacokinetics/include/mitkOneTissueCompartmentModelFactory.h new file mode 100644 index 0000000000..ceae49150c --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkOneTissueCompartmentModelFactory.h @@ -0,0 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef MITKONETISSUECOMPARTMENTMODELFACTORY_H +#define MITKONETISSUECOMPARTMENTMODELFACTORY_H + +#include "mitkConcreteAIFBasedModelFactory.h" +#include "mitkOneTissueCompartmentModel.h" +#include "mitkOneTissueCompartmentModelParameterizer.h" + +namespace mitk +{ + + + class MITKPHARMACOKINETICS_EXPORT OneTissueCompartmentModelFactory : public + mitk::ConcreteAIFBasedModelFactory + { + public: + mitkClassMacro(OneTissueCompartmentModelFactory, + ConcreteAIFBasedModelFactory); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelType ModelType; + typedef Superclass::ModelParameterizerType ModelParameterizerType; + + ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override; + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + + OneTissueCompartmentModelFactory(); + + virtual ~OneTissueCompartmentModelFactory(); + + private: + + //No copy constructor allowed + OneTissueCompartmentModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} +#endif // MITKONETISSUECOMPARTMENTMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkOneTissueCompartmentModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkOneTissueCompartmentModelParameterizer.h new file mode 100644 index 0000000000..616d61f49e --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkOneTissueCompartmentModelParameterizer.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKONETISSUECOMPARTMENTMODELPARAMETRIZER_H +#define MITKONETISSUECOMPARTMENTMODELPARAMETRIZER_H + +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkOneTissueCompartmentModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT OneTissueCompartmentModelParameterizer : public + mitk::AIFBasedModelParameterizerBase + { + public: + typedef OneTissueCompartmentModelParameterizer Self; + typedef mitk::AIFBasedModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(OneTissueCompartmentModelParameterizer, + mitk::AIFBasedModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + OneTissueCompartmentModelParameterizer(); + + virtual ~OneTissueCompartmentModelParameterizer(); + + private: + + //No copy constructor allowed + OneTissueCompartmentModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} +#endif diff --git a/Modules/Pharmacokinetics/include/mitkPerfusionDataGenerator.h b/Modules/Pharmacokinetics/include/mitkPerfusionDataGenerator.h new file mode 100644 index 0000000000..c675ef7984 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkPerfusionDataGenerator.h @@ -0,0 +1,75 @@ +#ifndef PERFUSIONDATAGENERATOR_H +#define PERFUSIONDATAGENERATOR_H + + +#include "MitkPharmacokineticsExports.h" +#include "mitkModelBase.h" +#include "mitkModelDataGenerationFunctor.h" +#include "mitkSimpleFunctorPolicy.h" +#include "mitkImage.h" + + +namespace mitk { + + class MITKPHARMACOKINETICS_EXPORT PerfusionDataGenerator: public ::itk::Object + { + public: + + mitkClassMacroItkParent(PerfusionDataGenerator, itk::Object); + itkFactorylessNewMacro(Self); + + typedef mitk::Image::Pointer ParameterImageType; + typedef std::vector ParameterNamesType; + typedef unsigned int ParametersIndexType; + typedef std::vector ParameterVectorType; + typedef std::map ParameterMapType; + + + typedef ModelDataGenerationFunctor FunctorType; + typedef mitk::Image::Pointer ResultImageType; + typedef mitk::Image::Pointer MaskType; + + typedef mitk::ModelBase::TimeGridType GridType; + + itkSetObjectMacro(Functor, FunctorType); + itkGetObjectMacro(Functor, FunctorType); + + void SetParameterInputImage(const ParametersIndexType index, ParameterImageType inputParameterImage); + + ResultImageType GetGeneratedImage(); + void Generate(); + + + + protected: + PerfusionDataGenerator() + {}; + ~PerfusionDataGenerator() + {}; + + template + void DoGenerateData(itk::Image* image); + + template + void DoPrepareMask(itk::Image* image); + + private: + ParameterMapType m_ParameterInputMap; + ParameterVectorType m_InputParameterImages; + + void SortParameterImages(); + + + MaskType m_Mask; + + typedef itk::Image InternalMaskType; + InternalMaskType::Pointer m_InternalMask; + + ResultImageType m_ResultImage; + FunctorType::Pointer m_Functor; + + }; +} + + +#endif // MITKPHARMACOKINETICSDATAGENERATOR_H diff --git a/Modules/Pharmacokinetics/include/mitkPixelBasedDescriptionParameterImageGenerator.h b/Modules/Pharmacokinetics/include/mitkPixelBasedDescriptionParameterImageGenerator.h new file mode 100644 index 0000000000..7014be58dd --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkPixelBasedDescriptionParameterImageGenerator.h @@ -0,0 +1,104 @@ +/*=================================================================== + + The Medical Imaging Interaction Toolkit (MITK) + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. + + See LICENSE.txt or http://www.mitk.org for details. + + ===================================================================*/ + +#ifndef __MITK_PIXEL_BASED_DESCRIPTION_PARAMETER_IMAGE_GENERATOR_H_ +#define __MITK_PIXEL_BASED_DESCRIPTION_PARAMETER_IMAGE_GENERATOR_H_ + +#include + +#include + +#include "mitkCurveParameterFunctor.h" +#include "mitkDescriptionParameterImageGeneratorBase.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + /** Class for generating curve descriptor images based on a given 4D mitk image. + * The class uses curve parameter functor to generate the curve description image(s). + * Depending on the chosen functor several images may be generated as output. + * @remark This generator fits every pixel on its own. If you want to fit the mean value of the given mask use + * ROIBasedDescriptionParameterImageGenerator. + */ + class MITKPHARMACOKINETICS_EXPORT PixelBasedDescriptionParameterImageGenerator : public DescriptionParameterImageGeneratorBase + { + public: + mitkClassMacro(PixelBasedDescriptionParameterImageGenerator, DescriptionParameterImageGeneratorBase); + + itkNewMacro(Self); + + + typedef ScalarType ParameterImagePixelType; + typedef std::vector FunctorValueArrayType; + + typedef CurveParameterFunctor FunctorType; + + typedef DescriptionParameterImageGeneratorBase::ParameterNameType ParameterNameType; + typedef DescriptionParameterImageGeneratorBase::ParameterImageMapType ParameterImageMapType; + + itkSetObjectMacro(DynamicImage, Image); + itkGetConstObjectMacro(DynamicImage, Image); + + itkSetObjectMacro(Mask, Image); + itkGetConstObjectMacro(Mask, Image); + + itkSetObjectMacro(Functor, FunctorType); + itkGetObjectMacro(Functor, FunctorType); + + virtual double GetProgress() const override; + + protected: + PixelBasedDescriptionParameterImageGenerator() : m_Progress(0) + { + m_InternalMask = NULL; + m_Mask = NULL; + m_DynamicImage = NULL; + }; + + ~PixelBasedDescriptionParameterImageGenerator() {}; + + template + void DoParameterCalculation(itk::Image* image); + + template + void DoPrepareMask(itk::Image* image); + + void onFitProgressEvent(::itk::Object* caller, const ::itk::EventObject& eventObject); + + virtual bool HasOutdatedResult() const override; + virtual void CheckValidInputs() const override; + virtual void DoParameterCalculationAndGetResults(ParameterImageMapType& parameterImages) override; + + private: + Image::Pointer m_DynamicImage; + Image::Pointer m_Mask; + + typedef itk::Image InternalMaskType; + InternalMaskType::Pointer m_InternalMask; + + FunctorType::Pointer m_Functor; + + + ParameterImageMapType m_TempResultMap; + + double m_Progress; + }; + +} + +#endif // __MITK_PIXEL_BASED_DESCRIPTION_PARAMETER_IMAGE_GENERATOR_H_ diff --git a/Modules/Pharmacokinetics/include/mitkStandardToftsModel.h b/Modules/Pharmacokinetics/include/mitkStandardToftsModel.h new file mode 100644 index 0000000000..255d294093 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkStandardToftsModel.h @@ -0,0 +1,94 @@ +#ifndef MITKSTANDARDTOFTSMODEL_H +#define MITKSTANDARDTOFTSMODEL_H + +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + /** @class StandardToftsModel + * @brief Implementation of the Model function of the Tofts pharmacokinetic model, using an Aterial Input Function + * The Model calculates the Concentration-Time-Curve as a convolution of the plasma curve Cp (the AIF) and a tissue specific + * residue function (in this case an exponential: R(t) = ktrans * exp(-ktrans/ve * (t)) ). + * C(t) = vp * Cp(t) + conv(Cp(t),R(t)) + * The parameters ktrans, ve and ve are subject to the fitting routine*/ + + class MITKPHARMACOKINETICS_EXPORT StandardToftsModel : public AIFBasedModelBase + { + + public: + typedef StandardToftsModel Self; + typedef AIFBasedModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(StandardToftsModel, ModelBase); + + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_Ktrans; + static const std::string NAME_PARAMETER_ve; + static const std::string NAME_PARAMETER_vp; + + static const std::string UNIT_PARAMETER_Ktrans; + static const std::string UNIT_PARAMETER_ve; + static const std::string UNIT_PARAMETER_vp; + + static const unsigned int POSITION_PARAMETER_Ktrans; + static const unsigned int POSITION_PARAMETER_ve; + static const unsigned int POSITION_PARAMETER_vp; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual ParameterNamesType GetParameterNames() const override; + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + virtual ParameterNamesType GetDerivedParameterNames() const override; + + virtual ParametersSizeType GetNumberOfDerivedParameters() const override; + + virtual ParamterUnitMapType GetDerivedParameterUnits() const override; + + protected: + StandardToftsModel(); + virtual ~StandardToftsModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + + virtual DerivedParameterMapType ComputeDerivedParameters(const mitk::ModelBase::ParametersType& + parameters) const; + + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const override; + + private: + + + //No copy constructor allowed + StandardToftsModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + + + + }; +} + +#endif // MITKSTANDARDTOFTSMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkStandardToftsModelFactory.h b/Modules/Pharmacokinetics/include/mitkStandardToftsModelFactory.h new file mode 100644 index 0000000000..e784b6ed07 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkStandardToftsModelFactory.h @@ -0,0 +1,55 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef MITKSTANDARDTOFTSMODELFACTORY_H +#define MITKSTANDARDTOFTSMODELFACTORY_H + +#include "mitkConcreteAIFBasedModelFactory.h" +#include "mitkStandardToftsModel.h" +#include "mitkStandardToftsModelParameterizer.h" + +namespace mitk +{ + + + class MITKPHARMACOKINETICS_EXPORT StandardToftsModelFactory : public + mitk::ConcreteAIFBasedModelFactory + { + public: + mitkClassMacro(StandardToftsModelFactory, ConcreteAIFBasedModelFactory); + itkFactorylessNewMacro(Self); + + using ModelType = Superclass::ModelType; + using ModelParameterizerType = Superclass::ModelParameterizerType; + + ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override; + virtual ParametersType GetDefaultInitialParameterization() const override; + + protected: + + StandardToftsModelFactory(); + + virtual ~StandardToftsModelFactory() override; + + private: + + //No copy constructor allowed + StandardToftsModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} +#endif // MITKSTANDARDTOFTSMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkStandardToftsModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkStandardToftsModelParameterizer.h new file mode 100644 index 0000000000..4b8d710cd9 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkStandardToftsModelParameterizer.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKSTANDARDTOFTSMODELPARAMETRIZER_H +#define MITKSTANDARDTOFTSMODELPARAMETRIZER_H + +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkStandardToftsModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT StandardToftsModelParameterizer : public + mitk::AIFBasedModelParameterizerBase + { + public: + typedef StandardToftsModelParameterizer Self; + typedef mitk::AIFBasedModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(StandardToftsModelParameterizer, + mitk::AIFBasedModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + StandardToftsModelParameterizer(); + + virtual ~StandardToftsModelParameterizer(); + + private: + + //No copy constructor allowed + StandardToftsModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} +#endif diff --git a/Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h b/Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h new file mode 100644 index 0000000000..162aa66043 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkThreeStepLinearModel.h @@ -0,0 +1,111 @@ +#ifndef MITKTHREESTEPLINEARMODEL_H +#define MITKTHREESTEPLINEARMODEL_H + +#include "mitkModelBase.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT ThreeStepLinearModel : public mitk::ModelBase + { + + public: + typedef ThreeStepLinearModel Self; + typedef mitk::ModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef Superclass::ParameterNameType ParameterNameType; + typedef Superclass::ParametersSizeType ParametersSizeType; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ThreeStepLinearModel, ModelBase) + + static const std::string MODEL_DISPLAY_NAME; + static const std::string NAME_PARAMETER_S0; + static const std::string NAME_PARAMETER_t1; + static const std::string NAME_PARAMETER_t2; + static const std::string NAME_PARAMETER_a1; + static const std::string NAME_PARAMETER_a2; + static const std::string NAME_PARAMETER_b1; + static const std::string NAME_PARAMETER_b2; + + static const std::string UNIT_PARAMETER_S0; + static const std::string UNIT_PARAMETER_t1; + static const std::string UNIT_PARAMETER_t2; + static const std::string UNIT_PARAMETER_a1; + static const std::string UNIT_PARAMETER_a2; + static const std::string UNIT_PARAMETER_b1; + static const std::string UNIT_PARAMETER_b2; + + static const unsigned int POSITION_PARAMETER_S0; + static const unsigned int POSITION_PARAMETER_t1; + static const unsigned int POSITION_PARAMETER_t2; + static const unsigned int POSITION_PARAMETER_a1; + static const unsigned int POSITION_PARAMETER_a2; + static const unsigned int POSITION_PARAMETER_b1; + static const unsigned int POSITION_PARAMETER_b2; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual FunctionStringType GetFunctionString() const override; + + virtual std::string GetXName() const override; + + virtual ParameterNamesType GetParameterNames() const override; + + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + virtual ParameterNamesType GetStaticParameterNames() const override; + + virtual ParametersSizeType GetNumberOfStaticParameters() const override; + + virtual ParameterNamesType GetDerivedParameterNames() const override; + + virtual ParametersSizeType GetNumberOfDerivedParameters() const override; + + virtual ParamterUnitMapType GetDerivedParameterUnits() const override; + + + protected: + ThreeStepLinearModel() {}; + virtual ~ThreeStepLinearModel(){}; + + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const; + virtual DerivedParameterMapType ComputeDerivedParameters(const mitk::ModelBase::ParametersType& + parameters) const; + + virtual void SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values); + virtual StaticParameterValuesType GetStaticParameterValue(const ParameterNameType& name) const; + + private: + + //No copy constructor allowed + ThreeStepLinearModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; +} + + +#endif // MITKTHREESTEPLINEARMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkThreeStepLinearModelFactory.h b/Modules/Pharmacokinetics/include/mitkThreeStepLinearModelFactory.h new file mode 100644 index 0000000000..432b50dede --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkThreeStepLinearModelFactory.h @@ -0,0 +1,43 @@ +#ifndef MITKTHREESTEPLINEARMODELFACTORY_H +#define MITKTHREESTEPLINEARMODELFACTORY_H + +#include + +#include "mitkConcreteModelFactoryBase.h" +#include "mitkThreeStepLinearModel.h" +#include "mitkThreeStepLinearModelParameterizer.h" + +#include "MitkPharmacokineticsExports.h" +namespace mitk +{ + + + class MITKPHARMACOKINETICS_EXPORT ThreeStepLinearModelFactory : public ConcreteModelFactoryBase + { + public: + mitkClassMacroItkParent(ThreeStepLinearModelFactory, ConcreteModelFactoryBase); + itkFactorylessNewMacro(Self); + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + virtual ModelParameterizerBase::Pointer DoCreateParameterizer(const modelFit::ModelFitInfo* fit) + const; + + ThreeStepLinearModelFactory(); + + virtual ~ThreeStepLinearModelFactory(); + + private: + + //No copy constructor allowed + ThreeStepLinearModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} + +#endif // MITKTHREESTEPLINEARMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkThreeStepLinearModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkThreeStepLinearModelParameterizer.h new file mode 100644 index 0000000000..44d4a860fe --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkThreeStepLinearModelParameterizer.h @@ -0,0 +1,66 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTHREESTEPLINEARMODELPARAMETERIZER_H +#define MITKTHREESTEPLINEARMODELPARAMETERIZER_H + +#include "mitkConcreteModelParameterizerBase.h" +#include "mitkThreeStepLinearModel.h" + +namespace mitk +{ + +class MITKPHARMACOKINETICS_EXPORT ThreeStepLinearModelParameterizer : public + mitk::ConcreteModelParameterizerBase +{ +public: + typedef ThreeStepLinearModelParameterizer Self; + typedef mitk::ConcreteModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(ThreeStepLinearModelParameterizer, ConcreteModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef Superclass::ModelPointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + +protected: + ThreeStepLinearModelParameterizer(){}; + + virtual ~ThreeStepLinearModelParameterizer(){}; + +private: + + //No copy constructor allowed + ThreeStepLinearModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented +};} + +#endif // MITKTHREESTEPLINEARMODELPARAMETERIZER_H diff --git a/Modules/Pharmacokinetics/include/mitkTimeToPeakCurveDescriptionParameter.h b/Modules/Pharmacokinetics/include/mitkTimeToPeakCurveDescriptionParameter.h new file mode 100644 index 0000000000..3e056de79c --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTimeToPeakCurveDescriptionParameter.h @@ -0,0 +1,52 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTIMETOPEAKCURVEDESCRIPTIONPARAMETER_H +#define MITKTIMETOPEAKCURVEDESCRIPTIONPARAMETER_H +#include "mitkCurveDescriptionParameterBase.h" + +namespace mitk { + +/** Computes the position of the first maximum of the curve. As a secondary + * aspect it also returns the value of the curve.*/ +class MITKPHARMACOKINETICS_EXPORT TimeToPeakCurveDescriptionParameter : public mitk::CurveDescriptionParameterBase +{ +public: + typedef mitk::TimeToPeakCurveDescriptionParameter Self; + typedef CurveDescriptionParameterBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + virtual DescriptionParameterNamesType GetDescriptionParameterName() const override; + + +protected: + static const std::string PARAMETER_PEAK_NAME; + static const std::string PARAMETER_TIME_NAME; + + TimeToPeakCurveDescriptionParameter(); + virtual ~TimeToPeakCurveDescriptionParameter(); + + virtual DescriptionParameterResultsType ComputeCurveDescriptionParameter(const CurveType& curve, const CurveGridType& grid) const override; +}; + + + +} + +#endif // MITKTIMETOPEAKCURVEDESCRIPTIONPARAMETER_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModel.h b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModel.h new file mode 100644 index 0000000000..3b8c8faf1a --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModel.h @@ -0,0 +1,118 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTWOCOMPARTMENTEXCHANGEMODEL_H +#define MITKTWOCOMPARTMENTEXCHANGEMODEL_H + +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + + +namespace mitk +{ + /** @class TwoCompartmentExchangeModel + * @brief Implementation of the analystical model function of the Physiological Pharmacokinetic Brix model, using an Aterial Input Function + * The Model calculates the Concentration-Time-Curve as a convolution of the Aterial Input funciton CA(t) and a tissue specific + * residue function R(t). The Residue funktion consists of two parts: The Residue funktion Qp(t) of the Blood Plasma p and the residue funktion Qi(t) of the + * interstitial volume I. + * Ctotal(t) = vp * Cp(t) + fi * Ci(t) = [vp * Qp(t) + fi * Qi(t)] conv CA(t) + * = Qtotal(t) conv CA(t) + * where vp=Vp/VT and fi=Vi/VT are the portion of Plasma/interstitial volume Vp/VI of the total volume VT respectively. + * The Residuefunctions are described by + * Qp(t) = F/Vp * PS/Vp * 1/(l2 - l1) *[ µ2 exp(l1*t) - µ1 exp(l2*t)]* sig(t) + * Qi(t) = F/Vp * PS/Vi * 1/(l1 - l2) *[ exp(l1*t) - exp(l2*t)]* sig(t) + * = F/Vp * PS/Vp * vp/fi * 1/(l1 - l2) *[ exp(l1*t) - exp(l2*t)]* sig(t) + * with + * l1/2 = -1/2 (PS/Vp * vp/fi + PS/Vp + F/Vp) +/- sqrt((PS/Vp * vp/fi + PS/Vp + F/Vp)² - 4* F/Vp * PS/Vp * vp/fi) + * µ1/2 = F/Vp * Vp/PS + 1 + Vp/PS* l1/2 + * + * The parameters PS/Vp, F/Vp, vp and fi are subject to the fitting routine*/ + + class MITKPHARMACOKINETICS_EXPORT TwoCompartmentExchangeModel : public AIFBasedModelBase + { + + public: + typedef TwoCompartmentExchangeModel Self; + typedef AIFBasedModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** Run-time type information (and related methods). */ + itkTypeMacro(TwoCompartmentExchangeModel, ModelBase) + + + /** Model Specifications */ + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_F; + static const std::string NAME_PARAMETER_PS; + static const std::string NAME_PARAMETER_ve; + static const std::string NAME_PARAMETER_vp; + + static const unsigned int POSITION_PARAMETER_F; + static const unsigned int POSITION_PARAMETER_PS; + static const unsigned int POSITION_PARAMETER_ve; + static const unsigned int POSITION_PARAMETER_vp; + + static const std::string UNIT_PARAMETER_F; + static const std::string UNIT_PARAMETER_PS; + static const std::string UNIT_PARAMETER_ve; + static const std::string UNIT_PARAMETER_vp; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual ParameterNamesType GetParameterNames() const override; + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + + protected: + TwoCompartmentExchangeModel(); + virtual ~TwoCompartmentExchangeModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const; + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const; + + private: + + + //No copy constructor allowed + TwoCompartmentExchangeModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + + + + }; +} + +#endif // MITKTWOCOMPARTMENTEXCHANGEMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelDifferentialEquations.h b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelDifferentialEquations.h new file mode 100644 index 0000000000..39fc35a1e7 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelDifferentialEquations.h @@ -0,0 +1,118 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTWOCOMPARTMENTEXCHANGEMODELDIFFERENTIALEQUATIONS_H +#define MITKTWOCOMPARTMENTEXCHANGEMODELDIFFERENTIALEQUATIONS_H + +#include "mitkNumericTwoCompartmentExchangeModel.h" + +namespace mitk{ +/** @class TwoCompartmentExchangeModelDifferentialEquations + * @brief Helper Class for NumericTwoCompartmentExchangeModel: Defines the differential equations (Mass Balance Equations) in the 2 Compartment Exchange model. + * The 2 Compartment Exchange model is defined via the mass balance equations + * vp * dCp(t)/dt = F * (CA(t) - Cp(t)) - PS * (Cp(t) - Ce(t)) + * ve * dCe(t)/dt = PS * (Cp(t) - Ce(t)) + * Boost ODEINT performs a stepwise numeric integration (e.g. via Runge-Kutta method) of the initial value problem + * x' = dx/dt = f(x,t) + * It needs an operator () (a functor) that calculates dx/dt = dxdt for a given x and t. + * Parameters are F, PS, ve and vp and the time dependent Ca(t) =AIF, that is interpolated to the current step t +*/ + +class TwoCompartmentExchangeModelDifferentialEquations +{ +public: + + typedef std::vector< double > AIFType; + + /** @brief Functor for differential equation of Physiological Pharmacokinetic Brix Model + * Takes current state x = x(t) and time t and calculates the corresponding dxdt = dx/dt + */ + void operator() (const mitk::NumericTwoCompartmentExchangeModel::state_type &x, mitk::NumericTwoCompartmentExchangeModel::state_type &dxdt, const double t) + { + double Ca_t = InterpolateAIFToCurrentTimeStep(t); + +// dxdt[0] = -(this->FVP + this->PSVP)*x[0] - this->PSVP*x[1]+this->FVP*Ca_t; + dxdt[0] = (1/this->vp) * ( this->F*(Ca_t - x[0]) - this->PS*(x[0] - x[1]) ); + dxdt[1] = (1/this->ve) * this->PS * (x[0] - x[1]); + + } + + TwoCompartmentExchangeModelDifferentialEquations() : F(0), PS(0), ve(0), vp(0), m_AIF(0), m_AIFTimeGrid(0) + { + } + + /** @brief Initialize class with parameters F/Vp, PS/Vp, fi and fp that are free fit parameters*/ + void initialize(double Fp, double ps, double fi, double fp) + { + this->F = Fp; + this->PS = ps; + this->ve = fi; + this->vp = fp; + } + + + void setAIF(AIFType &aif) + { + this->m_AIF = aif; + } + + + void setAIFTimeGrid(AIFType &grid) + { + this->m_AIFTimeGrid = grid; + } + +private: + + double F; + double PS; + double ve; + double vp; + + AIFType m_AIF; + AIFType m_AIFTimeGrid; + + + /** @brief Internal routine to interpolate the AIF to the current time point t used for integration + * The numerical integration of ODEINT is performed on an adaptive timegrid (adaptive step size dt) different from the time grid of the AIF and model function. + * Thus, the AIF value Ca(t) has to be interpolated from the set AIF + */ + double InterpolateAIFToCurrentTimeStep(double t) + { + double lastValue = m_AIF[0]; + double lastTime = std::numeric_limits::min(); + + AIFType::const_iterator posITime = m_AIFTimeGrid.begin(); + AIFType::const_iterator posValue = m_AIF.begin(); + + while(t > *posITime) + { + lastValue = *posValue; + lastTime = *posITime; + ++posValue; + ++posITime; + } + double weightLast = 1 - (t - lastTime)/(*posITime - lastTime); + double weightNext = 1- (*posITime - t)/(*posITime - lastTime); + double result = weightLast * lastValue + weightNext * (*posValue); + + return result; + } + +}; +} + +#endif // MITKTWOCOMPARTMENTEXCHANGEMODELDIFFERENTIALEQUATIONS_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelFactory.h b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelFactory.h new file mode 100644 index 0000000000..ae7083f6b9 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelFactory.h @@ -0,0 +1,47 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef MITKTWOCOMPARTMENTEXCHANGEMODELFACTORY_H +#define MITKTWOCOMPARTMENTEXCHANGEMODELFACTORY_H + +#include "mitkTwoCompartmentExchangeModelFactoryBase.h" +#include "mitkTwoCompartmentExchangeModelParameterizer.h" + +namespace mitk +{ + class MITKPHARMACOKINETICS_EXPORT TwoCompartmentExchangeModelFactory : public + mitk::TwoCompartmentExchangeModelFactoryBase + { + public: + mitkClassMacro(TwoCompartmentExchangeModelFactory, + TwoCompartmentExchangeModelFactoryBase); + itkFactorylessNewMacro(Self); + + protected: + + TwoCompartmentExchangeModelFactory(); + + virtual ~TwoCompartmentExchangeModelFactory(); + + private: + + //No copy constructor allowed + TwoCompartmentExchangeModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + }; + + +} +#endif // MITKTWOCOMPARTMENTEXCHANGEMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelFactoryBase.h b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelFactoryBase.h new file mode 100644 index 0000000000..235d07d8b2 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelFactoryBase.h @@ -0,0 +1,83 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef MITKTWOCOMPARTMENTEXCHANGEMODELFACTORYBASE_H +#define MITKTWOCOMPARTMENTEXCHANGEMODELFACTORYBASE_H + +#include "mitkConcreteAIFBasedModelFactory.h" +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkSimpleBarrierConstraintChecker.h" + +namespace mitk +{ + template + class TwoCompartmentExchangeModelFactoryBase : public + mitk::ConcreteAIFBasedModelFactory< TModelParameterizer > + { + public: + mitkClassMacro(TwoCompartmentExchangeModelFactoryBase, + ConcreteAIFBasedModelFactory< TModelParameterizer >); + itkFactorylessNewMacro(Self); + + + typedef typename Superclass::ModelType ModelType; + typedef typename Superclass::ModelParameterizerType ModelParameterizerType; + typedef typename Superclass::ParametersType ParametersType; + + ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override + { + SimpleBarrierConstraintChecker::Pointer constraints = SimpleBarrierConstraintChecker::New(); + + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_ve, 0.0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_ve, 1.0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_vp, 0.0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_vp, 1.0); + + SimpleBarrierConstraintChecker::ParameterIndexVectorType indices; + indices.push_back(ModelType::POSITION_PARAMETER_ve); + indices.push_back(ModelType::POSITION_PARAMETER_vp); + + constraints->SetUpperSumBarrier(indices, 1.0); + + return constraints.GetPointer(); + }; + + virtual ParametersType GetDefaultInitialParameterization() const + { + typename ModelParameterizerType::Pointer modelParameterizer = + ModelParameterizerType::New(); + + return modelParameterizer->GetDefaultInitialParameterization(); + }; + + protected: + + TwoCompartmentExchangeModelFactoryBase() + { + }; + + virtual ~TwoCompartmentExchangeModelFactoryBase() + { + }; + + private: + + //No copy constructor allowed + TwoCompartmentExchangeModelFactoryBase(const Self& source); + void operator=(const Self&); //purposely not implemented + }; + +} +#endif // MITKTWOCOMPARTMENTEXCHANGEMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelParameterizer.h new file mode 100644 index 0000000000..1979057eb4 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoCompartmentExchangeModelParameterizer.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTWOCOMPARTMENTEXCHANGEMODELPARAMETRIZER_H +#define MITKTWOCOMPARTMENTEXCHANGEMODELPARAMETRIZER_H + +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkTwoCompartmentExchangeModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT TwoCompartmentExchangeModelParameterizer : public + mitk::AIFBasedModelParameterizerBase + { + public: + typedef TwoCompartmentExchangeModelParameterizer Self; + typedef mitk::AIFBasedModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(TwoCompartmentExchangeModelParameterizer, + mitk::AIFBasedModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + TwoCompartmentExchangeModelParameterizer(); + + virtual ~TwoCompartmentExchangeModelParameterizer(); + + private: + + //No copy constructor allowed + TwoCompartmentExchangeModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} +#endif diff --git a/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentFDGModel.h b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentFDGModel.h new file mode 100644 index 0000000000..c3cb903ea7 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentFDGModel.h @@ -0,0 +1,97 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTWOTISSUECOMPARTMENTFDGMODEL_H +#define MITKTWOTISSUECOMPARTMENTFDGMODEL_H + +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + + +namespace mitk +{ + class MITKPHARMACOKINETICS_EXPORT TwoTissueCompartmentFDGModel : public AIFBasedModelBase + { + + public: + typedef TwoTissueCompartmentFDGModel Self; + typedef AIFBasedModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** Run-time type information (and related methods). */ + itkTypeMacro(TwoTissueCompartmentFDGModel, ModelBase) + + + /** Model Specifications */ + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_K1; + static const std::string NAME_PARAMETER_k2; + static const std::string NAME_PARAMETER_k3; + static const std::string NAME_PARAMETER_VB; + + static const std::string UNIT_PARAMETER_K1; + static const std::string UNIT_PARAMETER_k2; + static const std::string UNIT_PARAMETER_k3; + static const std::string UNIT_PARAMETER_VB; + + static const unsigned int POSITION_PARAMETER_K1; + static const unsigned int POSITION_PARAMETER_k2; + static const unsigned int POSITION_PARAMETER_k3; + static const unsigned int POSITION_PARAMETER_VB; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual ParameterNamesType GetParameterNames() const override; + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + + protected: + TwoTissueCompartmentFDGModel(); + virtual ~TwoTissueCompartmentFDGModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const; + + private: + + + //No copy constructor allowed + TwoTissueCompartmentFDGModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; +} + +#endif // MITKTWOTISSUECOMPARTMENTFDGMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentFDGModelFactory.h b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentFDGModelFactory.h new file mode 100644 index 0000000000..02992a958c --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentFDGModelFactory.h @@ -0,0 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef MITKTWOTISSUECOMPARTMENTFDGMODELFACTORY_H +#define MITKTWOTISSUECOMPARTMENTFDGMODELFACTORY_H + +#include "mitkConcreteAIFBasedModelFactory.h" +#include "mitkTwoTissueCompartmentFDGModel.h" +#include "mitkTwoTissueCompartmentFDGModelParameterizer.h" + +namespace mitk +{ + + + class MITKPHARMACOKINETICS_EXPORT TwoTissueCompartmentFDGModelFactory : public + mitk::ConcreteAIFBasedModelFactory + { + public: + mitkClassMacro(TwoTissueCompartmentFDGModelFactory, + ConcreteAIFBasedModelFactory); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelType ModelType; + typedef Superclass::ModelParameterizerType ModelParameterizerType; + + ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override; + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + + TwoTissueCompartmentFDGModelFactory(); + + virtual ~TwoTissueCompartmentFDGModelFactory(); + + private: + + //No copy constructor allowed + TwoTissueCompartmentFDGModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} +#endif // MITKTWOTISSUECOMPARTMENTFDGMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentFDGModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentFDGModelParameterizer.h new file mode 100644 index 0000000000..df4cee1c8f --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentFDGModelParameterizer.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTWOTISSUECOMPARTMENTFDGMODELPARAMETERIZER_H +#define MITKTWOTISSUECOMPARTMENTFDGMODELPARAMETERIZER_H + +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkTwoTissueCompartmentFDGModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT TwoTissueCompartmentFDGModelParameterizer : public + mitk::AIFBasedModelParameterizerBase + { + public: + typedef TwoTissueCompartmentFDGModelParameterizer Self; + typedef mitk::AIFBasedModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(TwoTissueCompartmentFDGModelParameterizer, + mitk::AIFBasedModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + TwoTissueCompartmentFDGModelParameterizer(); + + virtual ~TwoTissueCompartmentFDGModelParameterizer(); + + private: + + //No copy constructor allowed + TwoTissueCompartmentFDGModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} +#endif diff --git a/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModel.h b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModel.h new file mode 100644 index 0000000000..24a20b7834 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModel.h @@ -0,0 +1,99 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTWOTISSUECOMPARTMENTMODEL_H +#define MITKTWOTISSUECOMPARTMENTMODEL_H + +#include "mitkAIFBasedModelBase.h" +#include "MitkPharmacokineticsExports.h" + + +namespace mitk +{ + class MITKPHARMACOKINETICS_EXPORT TwoTissueCompartmentModel : public AIFBasedModelBase + { + + public: + typedef TwoTissueCompartmentModel Self; + typedef AIFBasedModelBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** Run-time type information (and related methods). */ + itkTypeMacro(TwoTissueCompartmentModel, ModelBase) + + + /** Model Specifications */ + static const std::string MODEL_DISPLAY_NAME; + + static const std::string NAME_PARAMETER_K1; + static const std::string NAME_PARAMETER_k2; + static const std::string NAME_PARAMETER_k3; + static const std::string NAME_PARAMETER_k4; + static const std::string NAME_PARAMETER_VB; + + static const std::string UNIT_PARAMETER_K1; + static const std::string UNIT_PARAMETER_k2; + static const std::string UNIT_PARAMETER_k3; + static const std::string UNIT_PARAMETER_k4; + static const std::string UNIT_PARAMETER_VB; + + static const unsigned int POSITION_PARAMETER_K1; + static const unsigned int POSITION_PARAMETER_k2; + static const unsigned int POSITION_PARAMETER_k3; + static const unsigned int POSITION_PARAMETER_k4; + static const unsigned int POSITION_PARAMETER_VB; + + static const unsigned int NUMBER_OF_PARAMETERS; + + virtual std::string GetModelDisplayName() const override; + + virtual std::string GetModelType() const override; + + virtual ParameterNamesType GetParameterNames() const override; + virtual ParametersSizeType GetNumberOfParameters() const override; + + virtual ParamterUnitMapType GetParameterUnits() const override; + + protected: + TwoTissueCompartmentModel(); + virtual ~TwoTissueCompartmentModel(); + + /** + * Actual implementation of the clone method. This method should be reimplemeted + * in subclasses to clone the extra required parameters. + */ + virtual itk::LightObject::Pointer InternalClone() const; + + virtual ModelResultType ComputeModelfunction(const ParametersType& parameters) const override; + + virtual void PrintSelf(std::ostream& os, ::itk::Indent indent) const; + + private: + + + //No copy constructor allowed + TwoTissueCompartmentModel(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; +} + +#endif // MITKTWOTISSUECOMPARTMENTMODEL_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelDifferentialEquations.h b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelDifferentialEquations.h new file mode 100644 index 0000000000..5752317452 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelDifferentialEquations.h @@ -0,0 +1,118 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTWOTISSUECOMPARTMENTMODELDIFFERENTIALEQUATIONS_H +#define MITKTWOTISSUECOMPARTMENTMODELDIFFERENTIALEQUATIONS_H +#include "mitkNumericTwoTissueCompartmentModel.h" + +namespace mitk{ +/** @class TwoTissueCompartmentModelDifferentialEquations + * @brief Helper Class for NumericTwoTissueCompartment Model: Defines the differential equations (Mass Balance Equations) in the + * 2-tissue-compartment model for dynamic PET data modeling. + * The 2-Tissue Compartment model is defined via the mass balance equations + * dC1(t)/dt = K1*Ca(t) - (k2 + k3)*C1(t) + k4*C2(t) + * dC2(t)/dt = k3*C1(t) - k4*C2(t) + * CT(t) = C_a(t)*VB + (1-VB)*(C1(t)+C2(t) + * where Ca(t) is the plasma concentration(aterial input function) + * Boost ODEINT performs a stepwise numeric integration (e.g. via Runge-Kutta method) of the initial value problem + * x' = dx/dt = f(x,t) + * It needs an operator () (a functor) that calculates dx/dt = dxdt for a given x and t. + * Parameters are K1,k2,k3,k4, VB and the time dependent Ca(t) =AIF, that is interpolated to the current step t +*/ + +class TwoTissueCompartmentModelDifferentialEquations +{ +public: + + typedef std::vector< double > AIFType; + + /** @brief Functor for differential equation of Two Tissue Compartment Model + * Takes current state x = x(t) and time t and calculates the corresponding dxdt = dx/dt + */ + void operator() (const mitk::NumericTwoTissueCompartmentModel::state_type &x, mitk::NumericTwoTissueCompartmentModel::state_type &dxdt, const double t) + { + double Ca_t = InterpolateAIFToCurrentTimeStep(t); + + dxdt[0] = this->K1*Ca_t-(this->k2+this->k3)*x[0] + this->k4*x[1]; + dxdt[1] = this->k3*x[0] - this->k4*x[1]; + } + + TwoTissueCompartmentModelDifferentialEquations() : K1(0), k2(0), k3(0), k4(0), m_AIF(0), m_AIFTimeGrid(0) + { + } + + /** @brief Initialize class with parameters K1, k2, k3 and k4 that are free fit parameters*/ + void initialize(double k_1, double k_2, double k_3, double k_4) + { + this->K1 = k_1; + this->k2 = k_2; + this->k3 = k_3; + this->k4 = k_4; + } + + + void setAIF(AIFType &aif) + { + this->m_AIF = aif; + } + + + void setAIFTimeGrid(AIFType &grid) + { + this->m_AIFTimeGrid = grid; + } + +private: + + double K1; + double k2; + double k3; + double k4; + + AIFType m_AIF; + AIFType m_AIFTimeGrid; + + + /** @brief Internal routine to interpolate the AIF to the current time point t used for integration + * The numerical integration of ODEINT is performed on an adaptive timegrid (adaptive step size dt) different from the time grid of the AIF and model function. + * Thus, the AIF value Ca(t) has to be interpolated from the set AIF + */ + double InterpolateAIFToCurrentTimeStep(double t) + { + double lastValue = m_AIF[0]; + double lastTime = std::numeric_limits::min(); + + AIFType::const_iterator posITime = m_AIFTimeGrid.begin(); + AIFType::const_iterator posValue = m_AIF.begin(); + + while(t > *posITime) + { + lastValue = *posValue; + lastTime = *posITime; + ++posValue; + ++posITime; + } + double weightLast = 1 - (t - lastTime)/(*posITime - lastTime); + double weightNext = 1- (*posITime - t)/(*posITime - lastTime); + double result = weightLast * lastValue + weightNext * (*posValue); + + return result; + } + +}; +} + +#endif // MITKTWOTISSUECOMPARTMENTMODELDIFFERENTIALEQUATIONS_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelFactory.h b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelFactory.h new file mode 100644 index 0000000000..ce54c2584a --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelFactory.h @@ -0,0 +1,51 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTWOTISSUECOMPARTMENTMODELFACTORY_H +#define MITKTWOTISSUECOMPARTMENTMODELFACTORY_H + +#include "mitkTwoTissueCompartmentModelFactoryBase.h" +#include "mitkTwoTissueCompartmentModelParameterizer.h" + +namespace mitk +{ + + + class MITKPHARMACOKINETICS_EXPORT TwoTissueCompartmentModelFactory : public + mitk::TwoTissueCompartmentModelFactoryBase + { + public: + mitkClassMacro(TwoTissueCompartmentModelFactory, + TwoTissueCompartmentModelFactoryBase); + itkFactorylessNewMacro(Self); + + protected: + + TwoTissueCompartmentModelFactory(); + + virtual ~TwoTissueCompartmentModelFactory(); + + private: + + //No copy constructor allowed + TwoTissueCompartmentModelFactory(const Self& source); + void operator=(const Self&); //purposely not implemented + + }; + +} + +#endif // MITKTWOTISSUECOMPARTMENTMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelFactoryBase.h b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelFactoryBase.h new file mode 100644 index 0000000000..83db60e14f --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelFactoryBase.h @@ -0,0 +1,85 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef MITKTWOTISSUECOMPARTMENTFACTORYBASE_H +#define MITKTWOTISSUECOMPARTMENTFACTORYBASE_H + +#include "mitkConcreteAIFBasedModelFactory.h" +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkSimpleBarrierConstraintChecker.h" + +namespace mitk +{ + template + class TwoTissueCompartmentModelFactoryBase : public + mitk::ConcreteAIFBasedModelFactory< TModelParameterizer > + { + public: + mitkClassMacro(TwoTissueCompartmentModelFactoryBase, + ConcreteAIFBasedModelFactory< TModelParameterizer >); + itkFactorylessNewMacro(Self); + + typedef typename Superclass::ModelType ModelType; + typedef typename Superclass::ModelParameterizerType ModelParameterizerType; + typedef typename Superclass::ParametersType ParametersType; + + ConstraintCheckerBase::Pointer CreateDefaultConstraints() const override + { + SimpleBarrierConstraintChecker::Pointer constraints = SimpleBarrierConstraintChecker::New(); + + /**@TODO: Mit Charlie klaren ob es eine sinnvolle default Einstellung gibt.*/ + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_K1, 0, 0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_k2, 0, 0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_k3, 0, 0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_k4, 0, 0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_VB, 0, 0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_VB, 1, 0); + + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_K1, 1.0, 0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_k2, 1.0, 0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_k3, 1.0, 0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_k4, 1.0, 0); + + + return constraints.GetPointer(); + }; + + virtual ParametersType GetDefaultInitialParameterization() const + { + typename ModelParameterizerType::Pointer modelParameterizer = + ModelParameterizerType::New(); + + return modelParameterizer->GetDefaultInitialParameterization(); + }; + + protected: + + TwoTissueCompartmentModelFactoryBase() + { + }; + + virtual ~TwoTissueCompartmentModelFactoryBase() + { + }; + + private: + + //No copy constructor allowed + TwoTissueCompartmentModelFactoryBase(const Self& source); + void operator=(const Self&); //purposely not implemented + }; + +} +#endif // MITKTWOCOMPARTMENTEXCHANGEMODELFACTORY_H diff --git a/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelParameterizer.h b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelParameterizer.h new file mode 100644 index 0000000000..3034cbf555 --- /dev/null +++ b/Modules/Pharmacokinetics/include/mitkTwoTissueCompartmentModelParameterizer.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKTWOTISSUECOMPARTMENTMODELPARAMETERIZER_H +#define MITKTWOTISSUECOMPARTMENTMODELPARAMETERIZER_H + +#include "mitkAIFBasedModelParameterizerBase.h" +#include "mitkTwoTissueCompartmentModel.h" + +#include "MitkPharmacokineticsExports.h" + +namespace mitk +{ + + class MITKPHARMACOKINETICS_EXPORT TwoTissueCompartmentModelParameterizer : public + mitk::AIFBasedModelParameterizerBase + { + public: + typedef TwoTissueCompartmentModelParameterizer Self; + typedef mitk::AIFBasedModelParameterizerBase Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro(TwoTissueCompartmentModelParameterizer, + mitk::AIFBasedModelParameterizerBase); + itkFactorylessNewMacro(Self); + + typedef Superclass::ModelBaseType ModelBaseType; + typedef Superclass::ModelBasePointer ModelBasePointer; + + typedef Superclass::ModelType ModelType; + typedef ModelType::Pointer ModelPointer; + + typedef Superclass::StaticParameterValueType StaticParameterValueType; + typedef Superclass::StaticParameterValuesType StaticParameterValuesType; + typedef Superclass::StaticParameterMapType StaticParameterMapType; + + typedef Superclass::IndexType IndexType; + + /** This function returns the default parameterization (e.g. initial parametrization for fitting) + defined by the model developer for for the given model.*/ + virtual ParametersType GetDefaultInitialParameterization() const; + + protected: + TwoTissueCompartmentModelParameterizer(); + + virtual ~TwoTissueCompartmentModelParameterizer(); + + private: + + //No copy constructor allowed + TwoTissueCompartmentModelParameterizer(const Self& source); + void operator=(const Self&); //purposely not implemented + }; +} +#endif diff --git a/Modules/Pharmacokinetics/src/Common/mitkAIFParametrizerHelper.cpp b/Modules/Pharmacokinetics/src/Common/mitkAIFParametrizerHelper.cpp new file mode 100644 index 0000000000..9d0b924691 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Common/mitkAIFParametrizerHelper.cpp @@ -0,0 +1,23 @@ +#include "mitkAIFParametrizerHelper.h" + +mitk::ModelBase::StaticParameterValuesType mitk::convertArrayToParameter(itk::Array array) +{ + ModelBase::StaticParameterValuesType parameter; + for(itk::Array::const_iterator pos = array.begin(); pos != array.end(); ++pos) + { + parameter.push_back(*pos); + } + return parameter; +} + +itk::Array mitk::convertParameterToArray(ModelBase::StaticParameterValuesType parameter) +{ + itk::Array array(parameter.size()); + array.fill(0.0); + itk::Array::iterator arrayPos = array.begin(); + for(ModelBase::StaticParameterValuesType::const_iterator pos = parameter.begin(); pos != parameter.end(); ++pos, ++arrayPos) + { + *arrayPos = *pos; + } + return array; +} diff --git a/Modules/Pharmacokinetics/src/Common/mitkAterialInputFunctionGenerator.cpp b/Modules/Pharmacokinetics/src/Common/mitkAterialInputFunctionGenerator.cpp new file mode 100644 index 0000000000..c0a2065d78 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Common/mitkAterialInputFunctionGenerator.cpp @@ -0,0 +1,141 @@ +/*=================================================================== + + The Medical Imaging Interaction Toolkit (MITK) + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. + + See LICENSE.txt or http://www.mitk.org for details. + + ===================================================================*/ + +#include "mitkAterialInputFunctionGenerator.h" + +#include "mitkMaskedDynamicImageStatisticsGenerator.h" +#include "mitkImageTimeSelector.h" +#include "mitkImageCast.h" +#include "itkArray2D.h" +#include "mitkImageAccessByItk.h" +#include "mitkExtractTimeGrid.h" +#include "mitkAIFBasedModelBase.h" +#include "mitkImageCast.h" + +#include +#include + +const double mitk::AterialInputFunctionGenerator::DEFAULT_HEMATOCRIT_LEVEL = 0.45; + +mitk::AIFBasedModelBase::AterialInputFunctionType mitk::AterialInputFunctionGenerator::GetAterialInputFunction() +{ + if(this->HasOutdatedResults()) + { + CheckValidInputs(); + CalculateAIFAndGetResult(); + } + return this->m_AIFValues; + +} + +mitk::ModelBase::TimeGridType mitk::AterialInputFunctionGenerator::GetAterialInputFunctionTimeGrid() +{ + if(this->HasOutdatedResults()){ + CheckValidInputs(); + CalculateAIFAndGetResult(); + } + return this->m_AIFTimeGrid; + +} + + + + +void mitk::AterialInputFunctionGenerator::CalculateAIFAndGetResult() +{ + + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = mitk::MaskedDynamicImageStatisticsGenerator::New(); + + + + m_AIFValues.SetSize(this->m_DynamicImage->GetTimeSteps()); + m_AIFValues.Fill(0.); + m_AIFTimeGrid.SetSize(this->m_DynamicImage->GetTimeSteps()); + m_AIFTimeGrid.Fill(0.); + + + // = not defined for array??? + mitk::ModelBase::TimeGridType timeGrid = ExtractTimeGrid(m_DynamicImage); + m_AIFTimeGrid = timeGrid; + + + signalGenerator->SetDynamicImage(m_DynamicImage); + signalGenerator->SetMask(m_Mask); + signalGenerator->Generate(); + + + //Convert from aterial curve Ca to Plasma curve Cp + // m_AIFValues = signalGenerator->GetMean()/(1-this->m_HCL); + mitk::MaskedDynamicImageStatisticsGenerator::ResultType temp = signalGenerator->GetMean(); + + + mitk::AIFBasedModelBase::AterialInputFunctionType::iterator aif = this->m_AIFValues.begin(); + for( mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = temp.begin(); pos != temp.end(); ++pos, ++aif) + { + *aif = *pos /(1-this->m_HCL); + + } + + + this->m_GenerationTimeStamp.Modified(); + +} + + + +void + mitk::AterialInputFunctionGenerator::CheckValidInputs() const +{ + + if (m_DynamicImage.IsNull()) + { + mitkThrow() << "Cannot generate Aterial Input Function. Input dynamic image is not set."; + } + if (m_Mask.IsNull()) + { + mitkThrow() << "Cannot generate Aterial Input Function. ROI is not set."; + } +} + +bool mitk::AterialInputFunctionGenerator::HasOutdatedResults() +{ + bool result = false; + + if (m_DynamicImage.IsNull()) + { + result = true; + } + else + { + if (m_DynamicImage->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + if (m_Mask.IsNull()) + { + result = true; + } + else + { + if (m_Mask->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + return result; +}; diff --git a/Modules/Pharmacokinetics/src/Common/mitkConcentrationCurveGenerator.cpp b/Modules/Pharmacokinetics/src/Common/mitkConcentrationCurveGenerator.cpp new file mode 100644 index 0000000000..d17529ef06 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Common/mitkConcentrationCurveGenerator.cpp @@ -0,0 +1,265 @@ +#include "mitkConcentrationCurveGenerator.h" +#include "mitkConvertToConcentrationTurboFlashFunctor.h" +#include "mitkConvertT2ConcentrationFunctor.h" +#include "mitkConvertToConcentrationViaT1Functor.h" +#include "mitkImageTimeSelector.h" +#include "mitkImageCast.h" +#include "mitkITKImageImport.h" +#include "mitkModelBase.h" +#include "mitkExtractTimeGrid.h" +#include "mitkArbitraryTimeGeometry.h" +#include "itkImageIOBase.h" + +#include "itkBinaryFunctorImageFilter.h" +#include "itkTernaryFunctorImageFilter.h" + +mitk::ConcentrationCurveGenerator::ConcentrationCurveGenerator() : m_isT2weightedImage(false), m_UsingT1Map(false), m_isTurboFlashSequence(false), + m_AbsoluteSignalEnhancement(false), m_RelativeSignalEnhancement(0.0), m_Factor(0.0), m_RecoveryTime(0.0), m_RelaxationTime(0.0), + m_Relaxivity(0.0), m_T2Factor(0.0), m_T2EchoTime(0.0), m_FlipAngle(0.0) +{ +} + +mitk::ConcentrationCurveGenerator::~ConcentrationCurveGenerator() +{ + +} + +mitk::Image::Pointer mitk::ConcentrationCurveGenerator::GetConvertedImage() +{ + if(this->m_DynamicImage.IsNull()) + { + itkExceptionMacro( << "Dynamic Image not set!"); + } + else { + Convert(); + } + return m_ConvertedImage; + +} + +void mitk::ConcentrationCurveGenerator::Convert() +{ + + mitk::Image::Pointer tempImage = mitk::Image::New(); + mitk::PixelType pixeltype = mitk::MakeScalarPixelType(); + + tempImage->Initialize(pixeltype,*this->m_DynamicImage->GetTimeGeometry()); + + mitk::TimeGeometry::Pointer timeGeometry = (this->m_DynamicImage->GetTimeGeometry())->Clone(); + tempImage->SetTimeGeometry(timeGeometry); + + + PrepareBaselineImage(); + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(this->m_DynamicImage); + + + + for(unsigned int i = 0; i< this->m_DynamicImage->GetTimeSteps(); ++i) + { + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer mitkInputImage = imageTimeSelector->GetOutput(); + mitk::Image::Pointer outputImage = mitk::Image::New(); + + outputImage = ConvertSignalToConcentrationCurve(mitkInputImage,this->m_BaselineImage); + + mitk::ImageReadAccessor accessor(outputImage); + tempImage->SetVolume(accessor.GetData(), i); + } + + this->m_ConvertedImage = tempImage; + +} + +void mitk::ConcentrationCurveGenerator::PrepareBaselineImage() +{ + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(this->m_DynamicImage); + imageTimeSelector->SetTimeNr(0); + imageTimeSelector->UpdateLargestPossibleRegion(); + + this->m_BaselineImage = imageTimeSelector->GetOutput(); + +} + +mitk::Image::Pointer mitk::ConcentrationCurveGenerator::ConvertSignalToConcentrationCurve(mitk::Image::Pointer inputImage,mitk::Image::Pointer baselineImage) +{ + + + + mitk::PixelType m_PixelType = inputImage->GetPixelType(); + mitk::Image::Pointer outputImage; + + if(inputImage->GetPixelType().GetComponentType() != baselineImage->GetPixelType().GetComponentType()) + { + mitkThrow() << "Input Image and Baseline Image have different Pixel Types. Data not supported"; + } + + + if(m_PixelType.GetComponentType() == itk::ImageIOBase::USHORT) + { + outputImage = convertToConcentration(inputImage, baselineImage); + } + else if(m_PixelType.GetComponentType() == itk::ImageIOBase::UINT) + { + outputImage = convertToConcentration(inputImage, baselineImage); + } + else if(m_PixelType.GetComponentType() == itk::ImageIOBase::INT) + { + outputImage = convertToConcentration(inputImage, baselineImage); + } + else if(m_PixelType.GetComponentType() == itk::ImageIOBase::SHORT) + { + outputImage = convertToConcentration(inputImage, baselineImage); + } + /*else if(m_PixelType.GetComponentType() == itk::ImageIOBase::ULONG) + { + outputImage = convertToConcentration(inputImage, baselineImage); + } + else if(m_PixelType.GetComponentType() == itk::ImageIOBase::LONG) + { + outputImage = convertToConcentration(inputImage, baselineImage); + }*/ + else if(m_PixelType.GetComponentType() == itk::ImageIOBase::DOUBLE) + { + outputImage = convertToConcentration(inputImage, baselineImage); + } + else if(m_PixelType.GetComponentType() == itk::ImageIOBase::FLOAT) + { + outputImage = convertToConcentration(inputImage, baselineImage); + } + else + { + mitkThrow() << "PixelType is "< +mitk::Image::Pointer mitk::ConcentrationCurveGenerator::convertToConcentration(mitk::Image::Pointer inputImage,mitk::Image::Pointer baselineImage) +{ + typedef itk::Image InputImageType; + + typename InputImageType::Pointer itkInputImage = InputImageType::New(); + typename InputImageType::Pointer itkBaselineImage = InputImageType::New(); + + mitk::CastToItkImage(inputImage, itkInputImage ); + mitk::CastToItkImage(baselineImage, itkBaselineImage ); + + + + mitk::Image::Pointer outputImage; + if(this->m_isT2weightedImage) + { + typedef mitk::ConvertT2ConcentrationFunctor ConversionFunctorT2Type; + typedef itk::BinaryFunctorImageFilter FilterT2Type; + + ConversionFunctorT2Type ConversionT2Functor; + ConversionT2Functor.initialize(this->m_T2Factor, this->m_T2EchoTime); + + typename FilterT2Type::Pointer ConversionT2Filter = FilterT2Type::New(); + + ConversionT2Filter->SetFunctor(ConversionT2Functor); + ConversionT2Filter->SetInput1(itkInputImage); + ConversionT2Filter->SetInput2(itkBaselineImage); + + ConversionT2Filter->Update(); + + outputImage = mitk::ImportItkImage(ConversionT2Filter->GetOutput())->Clone(); + } + + else + { + if(this->m_isTurboFlashSequence) + { + typedef mitk::ConvertToConcentrationTurboFlashFunctor ConversionFunctorTurboFlashType; + typedef itk::BinaryFunctorImageFilter FilterTurboFlashType; + + ConversionFunctorTurboFlashType ConversionTurboFlashFunctor; + ConversionTurboFlashFunctor.initialize(this->m_RelaxationTime, this->m_Relaxivity, this->m_RecoveryTime); + + typename FilterTurboFlashType::Pointer ConversionTurboFlashFilter = FilterTurboFlashType::New(); + + ConversionTurboFlashFilter->SetFunctor(ConversionTurboFlashFunctor); + ConversionTurboFlashFilter->SetInput1(itkInputImage); + ConversionTurboFlashFilter->SetInput2(itkBaselineImage); + + ConversionTurboFlashFilter->Update(); + outputImage = mitk::ImportItkImage(ConversionTurboFlashFilter->GetOutput())->Clone(); + + + } + else if(this->m_UsingT1Map) + { + typename InputImageType::Pointer itkT10Image = InputImageType::New(); + mitk::CastToItkImage(m_T10Image, itkT10Image); + + typedef mitk::ConvertToConcentrationViaT1CalcFunctor ConvertToConcentrationViaT1CalcFunctorType; + typedef itk::TernaryFunctorImageFilter FilterT1MapType; + + ConvertToConcentrationViaT1CalcFunctorType ConversionT1MapFunctor; + ConversionT1MapFunctor.initialize(this->m_Relaxivity, this->m_RecoveryTime, this->m_FlipAngle); + + typename FilterT1MapType::Pointer ConversionT1MapFilter = FilterT1MapType::New(); + + ConversionT1MapFilter->SetFunctor(ConversionT1MapFunctor); + ConversionT1MapFilter->SetInput1(itkInputImage); + ConversionT1MapFilter->SetInput2(itkBaselineImage); + ConversionT1MapFilter->SetInput3(itkT10Image); + + ConversionT1MapFilter->Update(); + outputImage = mitk::ImportItkImage(ConversionT1MapFilter->GetOutput())->Clone(); + + + } + + else if(this->m_AbsoluteSignalEnhancement) + { + typedef mitk::ConvertToConcentrationAbsoluteFunctor ConversionFunctorAbsoluteType; + typedef itk::BinaryFunctorImageFilter FilterAbsoluteType; + + ConversionFunctorAbsoluteType ConversionAbsoluteFunctor; + ConversionAbsoluteFunctor.initialize(this->m_Factor); + + typename FilterAbsoluteType::Pointer ConversionAbsoluteFilter = FilterAbsoluteType::New(); + + ConversionAbsoluteFilter->SetFunctor(ConversionAbsoluteFunctor); + ConversionAbsoluteFilter->SetInput1(itkInputImage); + ConversionAbsoluteFilter->SetInput2(itkBaselineImage); + + ConversionAbsoluteFilter->Update(); + + outputImage = mitk::ImportItkImage(ConversionAbsoluteFilter->GetOutput())->Clone(); + } + + else if(this->m_RelativeSignalEnhancement) + { + typedef mitk::ConvertToConcentrationRelativeFunctor ConversionFunctorRelativeType; + typedef itk::BinaryFunctorImageFilter FilterRelativeType; + + ConversionFunctorRelativeType ConversionRelativeFunctor; + ConversionRelativeFunctor.initialize(this->m_Factor); + + typename FilterRelativeType::Pointer ConversionRelativeFilter = FilterRelativeType::New(); + + ConversionRelativeFilter->SetFunctor(ConversionRelativeFunctor); + ConversionRelativeFilter->SetInput1(itkInputImage); + ConversionRelativeFilter->SetInput2(itkBaselineImage); + + ConversionRelativeFilter->Update(); + + outputImage = mitk::ImportItkImage(ConversionRelativeFilter->GetOutput())->Clone(); + } + } + + + + return outputImage; + +} + + diff --git a/Modules/Pharmacokinetics/src/Common/mitkDescriptionParameterImageGeneratorBase.cpp b/Modules/Pharmacokinetics/src/Common/mitkDescriptionParameterImageGeneratorBase.cpp new file mode 100644 index 0000000000..831b736f3c --- /dev/null +++ b/Modules/Pharmacokinetics/src/Common/mitkDescriptionParameterImageGeneratorBase.cpp @@ -0,0 +1,66 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkDescriptionParameterImageGeneratorBase.h" + +mitk::DescriptionParameterImageGeneratorBase::DescriptionParameterImageGeneratorBase() = default; +mitk::DescriptionParameterImageGeneratorBase::~DescriptionParameterImageGeneratorBase() = default; + +bool + mitk::DescriptionParameterImageGeneratorBase::HasOutdatedResult() const +{ + bool result = this->GetMTime() > this->m_GenerationTimeStamp; + + return result; +}; + +void + mitk::DescriptionParameterImageGeneratorBase::CheckValidInputs() const +{ +}; + + +void + mitk::DescriptionParameterImageGeneratorBase::Generate() +{ + CheckValidInputs(); + + if (!this->HasOutdatedResult()) + { //still up to date -> nothing to do + return; + } + + ParameterImageMapType paramImages; + + DoParameterCalculationAndGetResults(paramImages); + + m_ParameterImageMap = paramImages; + + this->m_GenerationTimeStamp.Modified(); +}; + +mitk::DescriptionParameterImageGeneratorBase::ParameterImageMapType + mitk::DescriptionParameterImageGeneratorBase::GetParameterImages() +{ + if (this->HasOutdatedResult()) + { + Generate(); + } + + + return m_ParameterImageMap; +}; + diff --git a/Modules/Pharmacokinetics/src/Common/mitkPixelBasedDescriptionParameterImageGenerator.cpp b/Modules/Pharmacokinetics/src/Common/mitkPixelBasedDescriptionParameterImageGenerator.cpp new file mode 100644 index 0000000000..c4f240d5c6 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Common/mitkPixelBasedDescriptionParameterImageGenerator.cpp @@ -0,0 +1,195 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "itkCommand.h" +#include "itkMultiOutputNaryFunctorImageFilter.h" + +#include "mitkPixelBasedDescriptionParameterImageGenerator.h" +#include "mitkImageTimeSelector.h" +#include "mitkImageAccessByItk.h" +#include "mitkImageCast.h" +#include "mitkSimpleFunctorPolicy.h" +#include "mitkModelBase.h" + +void + mitk::PixelBasedDescriptionParameterImageGenerator:: + onFitProgressEvent(::itk::Object* caller, const ::itk::EventObject& /*eventObject*/) +{ + this->InvokeEvent(::itk::ProgressEvent()); + + itk::ProcessObject* process = dynamic_cast(caller); + if (process) + { + this->m_Progress = process->GetProgress(); + } +}; + +template +void + mitk::PixelBasedDescriptionParameterImageGenerator::DoPrepareMask(itk::Image* image) +{ + m_InternalMask = dynamic_cast(image); + + if (m_InternalMask.IsNull()) + { + MITK_INFO << "Parameter Fit Generator. Need to cast mask for parameter fit."; + typedef itk::Image InputImageType; + typedef itk::CastImageFilter< InputImageType, InternalMaskType > CastFilterType; + typename CastFilterType::Pointer spImageCaster = CastFilterType::New(); + + spImageCaster->SetInput(image); + + m_InternalMask = spImageCaster->GetOutput(); + spImageCaster->Update(); + } +} + +template +mitk::PixelBasedDescriptionParameterImageGenerator::ParameterImageMapType StoreResultImages(const mitk::CurveParameterFunctor::ParameterNamesType ¶mNames, itk::ImageSource* source) +{ + if (source->GetNumberOfOutputs() != paramNames.size()) + { + mitkThrow() << "Error while generating fitted parameter images. Number of sources does not match expected parameter number. Output size: " << source->GetNumberOfOutputs() << "; number of param names: " << paramNames.size(); + } + + mitk::PixelBasedDescriptionParameterImageGenerator::ParameterImageMapType result; + for (mitk::CurveParameterFunctor::ParameterNamesType::size_type j = 0; j < paramNames.size(); ++j) + { + mitk::Image::Pointer paramImage = mitk::Image::New(); + typename TImage::ConstPointer outputImg = source->GetOutput(j); + mitk::CastToMitkImage(outputImg, paramImage); + + result.insert(std::make_pair(paramNames[j],paramImage)); + } + + return result; +} + +template +void + mitk::PixelBasedDescriptionParameterImageGenerator::DoParameterCalculation(itk::Image* /*image*/) +{ + typedef itk::Image InputFrameImageType; + typedef itk::Image ParameterImageType; + + typedef itk::MultiOutputNaryFunctorImageFilter DescriptorFilterType; + + typename DescriptorFilterType::Pointer descFilter = DescriptorFilterType::New(); + + typename ::itk::MemberCommand::Pointer spProgressCommand = ::itk::MemberCommand::New(); + spProgressCommand->SetCallbackFunction(this, &Self::onFitProgressEvent); + descFilter->AddObserver(::itk::ProgressEvent(), spProgressCommand); + + //add the time frames to the descriptor filter + std::vector frameCache; + for (unsigned int i = 0; i < this->m_DynamicImage->GetTimeSteps(); ++i) + { + typename InputFrameImageType::Pointer frameImage; + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(this->m_DynamicImage); + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + Image::Pointer frameMITKImage = imageTimeSelector->GetOutput(); + frameCache.push_back(frameMITKImage); + mitk::CastToItkImage(frameMITKImage, frameImage); + descFilter->SetInput(i,frameImage); + } + + + SimpleFunctorPolicy functor; + + functor.SetFunctor(this->m_Functor); + descFilter->SetFunctor(functor); + if (this->m_InternalMask.IsNotNull()) + { + descFilter->SetMask(this->m_InternalMask); + } + + //generate the fits + descFilter->Update(); + + //convert the outputs into mitk images and fill the parameter image map + CurveParameterFunctor::ParameterNamesType paramNames = this->m_Functor->GetDescriptionParameterNames(); + + if (descFilter->GetNumberOfOutputs() != (paramNames.size())) + { + mitkThrow() << "Error while generating fitted parameter images. Fit filter output size does not match expected parameter number. Output size: "<< descFilter->GetNumberOfOutputs(); + } + + this->m_TempResultMap = StoreResultImages(paramNames,descFilter); +} + +bool + mitk::PixelBasedDescriptionParameterImageGenerator::HasOutdatedResult() const +{ + bool result = Superclass::HasOutdatedResult(); + + if (m_DynamicImage.IsNotNull()) + { + if (m_DynamicImage->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + if (m_Mask.IsNotNull()) + { + if (m_Mask->GetMTime() > this->m_GenerationTimeStamp) + { + result = true; + } + } + + return result; + +}; + +void + mitk::PixelBasedDescriptionParameterImageGenerator::CheckValidInputs() const +{ + Superclass::CheckValidInputs(); + + if (m_DynamicImage.IsNull()) + { + mitkThrow() << "Cannot generate fitted parameter images. Input dynamic image is not set."; + } + +}; + +void mitk::PixelBasedDescriptionParameterImageGenerator::DoParameterCalculationAndGetResults(ParameterImageMapType& parameterImages) +{ + this->m_Progress = 0; + + if(this->m_Mask.IsNotNull()) + { + AccessFixedDimensionByItk(m_Mask, mitk::PixelBasedDescriptionParameterImageGenerator::DoPrepareMask, 3); + } + else + { + this->m_InternalMask = NULL; + } + + AccessFixedDimensionByItk(m_DynamicImage, mitk::PixelBasedDescriptionParameterImageGenerator::DoParameterCalculation, 4); + + parameterImages = this->m_TempResultMap; + }; + +double + mitk::PixelBasedDescriptionParameterImageGenerator::GetProgress() const +{ + return m_Progress; +}; diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp new file mode 100644 index 0000000000..f72b4173f3 --- /dev/null +++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderFirstMomentDescriptionParameter.cpp @@ -0,0 +1,38 @@ +#include "mitkAreaUnderFirstMomentDescriptionParameter.h" + +const std::string mitk::AreaUnderFirstMomentDescriptionParameter::PARAMETER_NAME = "AreaUnderFirstMoment"; + +mitk::AreaUnderFirstMomentDescriptionParameter::AreaUnderFirstMomentDescriptionParameter() +{ +} + +mitk::AreaUnderFirstMomentDescriptionParameter::~AreaUnderFirstMomentDescriptionParameter() +{ +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::AreaUnderFirstMomentDescriptionParameter::GetDescriptionParameterName() const +{ + DescriptionParameterNamesType result = { PARAMETER_NAME }; + return result; +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::AreaUnderFirstMomentDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const +{ + DescriptionParameterResultsType results; + CurveDescriptionParameterResultType aumc = 0; + int steps = grid.GetSize(); + + for (CurveGridType::size_type i = 0; i < steps - 1; ++i) + { + double deltaX = grid(i + 1) - grid(i); + double deltaY = curve(i + 1)*grid(i + 1) - curve(i)*grid(i); + double Yi = curve(i)*grid(i); + + double intI = 1 / 2 * deltaX * deltaY + Yi * deltaX; + + aumc += std::abs(intI); + + } + results.push_back(aumc); + return results; +} diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp new file mode 100644 index 0000000000..2c558707fd --- /dev/null +++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkAreaUnderTheCurveDescriptionParameter.cpp @@ -0,0 +1,55 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "mitkAreaUnderTheCurveDescriptionParameter.h" + +const std::string mitk::AreaUnderTheCurveDescriptionParameter::PARAMETER_NAME = "AreaUnderCurve"; + +mitk::AreaUnderTheCurveDescriptionParameter::AreaUnderTheCurveDescriptionParameter() +{ +} + +mitk::AreaUnderTheCurveDescriptionParameter::~AreaUnderTheCurveDescriptionParameter() +{ +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::AreaUnderTheCurveDescriptionParameter::GetDescriptionParameterName() const +{ + DescriptionParameterNamesType result = { PARAMETER_NAME }; + return result; +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::AreaUnderTheCurveDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const +{ + DescriptionParameterResultsType results; + CurveDescriptionParameterResultType auc = 0; + int steps = grid.GetSize(); + + for (CurveGridType::size_type i = 0; i < steps - 1; ++i) + { + double deltaX = grid(i + 1) - grid(i); + double deltaY = curve(i + 1) - curve(i); + double Yi = curve(i); + + double intI = 1 / 2 * deltaX * deltaY + Yi * deltaX; + + auc += std::abs(intI); + + } + results.push_back(auc); + return results; +} diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkCurveDescriptionParameterBase.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkCurveDescriptionParameterBase.cpp new file mode 100644 index 0000000000..7b0c29cbf5 --- /dev/null +++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkCurveDescriptionParameterBase.cpp @@ -0,0 +1,44 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkCurveDescriptionParameterBase.h" +#include "itkMacro.h" + +#include + + +mitk::CurveDescriptionParameterBase::CurveDescriptionParameterBase() +{ +} + +mitk::CurveDescriptionParameterBase::~CurveDescriptionParameterBase() +{ +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::CurveDescriptionParameterBase::GetCurveDescriptionParameter(const CurveType& curve, const CurveGridType& grid) const +{ + if(curve.GetSize() != grid.GetSize()) + { + itkExceptionMacro("Cannot calculate Curve Description Parameter. Signal and Time Grid do not match!"); + } + + DescriptionParameterResultsType parameter = ComputeCurveDescriptionParameter(curve, grid); + + return parameter; +} + + + diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMaximumCurveDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMaximumCurveDescriptionParameter.cpp new file mode 100644 index 0000000000..aed8579d5d --- /dev/null +++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMaximumCurveDescriptionParameter.cpp @@ -0,0 +1,49 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkMaximumCurveDescriptionParameter.h" +#include + +const std::string mitk::MaximumCurveDescriptionParameter::PARAMETER_NAME = "MaximumConcentrationUptake"; + +mitk::MaximumCurveDescriptionParameter::MaximumCurveDescriptionParameter() +{ +} + +mitk::MaximumCurveDescriptionParameter::~MaximumCurveDescriptionParameter() +{ +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::MaximumCurveDescriptionParameter::GetDescriptionParameterName() const +{ + DescriptionParameterNamesType result = { PARAMETER_NAME }; + return result; +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::MaximumCurveDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const +{ + DescriptionParameterResultsType results; + CurveDescriptionParameterResultType maximum = itk::NumericTraits::NonpositiveMin(); + int steps = grid.GetSize(); + + for (int i = 0; i < steps - 1; ++i) + { + maximum = std::max(maximum, curve(i)); + } + + results.push_back(maximum); + return results; +} diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp new file mode 100644 index 0000000000..26d74b549f --- /dev/null +++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkMeanResidenceTimeDescriptionParameter.cpp @@ -0,0 +1,51 @@ +#include "mitkMeanResidenceTimeDescriptionParameter.h" + +const std::string mitk::MeanResidenceTimeDescriptionParameter::PARAMETER_NAME = "MeanResidenceTime"; + +mitk::MeanResidenceTimeDescriptionParameter::MeanResidenceTimeDescriptionParameter() +{ +} + +mitk::MeanResidenceTimeDescriptionParameter::~MeanResidenceTimeDescriptionParameter() +{ +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::MeanResidenceTimeDescriptionParameter::GetDescriptionParameterName() const +{ + DescriptionParameterNamesType result = { PARAMETER_NAME }; + return result; +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::MeanResidenceTimeDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const +{ + DescriptionParameterResultsType results; + CurveDescriptionParameterResultType aumc = 0; + CurveDescriptionParameterResultType auc = 0; + CurveDescriptionParameterResultType mrt = 0; + + int steps = grid.GetSize(); + + for (CurveGridType::size_type i = 0; i < steps - 1; ++i) + { + double deltaX = grid(i + 1) - grid(i); + + double deltaY1 = curve(i + 1)*grid(i + 1) - curve(i)*grid(i); + double Y1 = curve(i)*grid(i); + double intI1 = 1 / 2 * deltaX * deltaY1 + Y1 * deltaX; + aumc += std::abs(intI1); + + + double deltaY2 = curve(i + 1) - curve(i); + double Y2 = curve(i); + double intI2 = 1 / 2 * deltaX * deltaY2 + Y2 * deltaX; + auc += std::abs(intI2); + + + } + if(auc != 0) + { + mrt = aumc/auc; + } + results.push_back(mrt); + return results; +} diff --git a/Modules/Pharmacokinetics/src/DescriptionParameters/mitkTimeToPeakCurveDescriptionParameter.cpp b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkTimeToPeakCurveDescriptionParameter.cpp new file mode 100644 index 0000000000..214581c0d7 --- /dev/null +++ b/Modules/Pharmacokinetics/src/DescriptionParameters/mitkTimeToPeakCurveDescriptionParameter.cpp @@ -0,0 +1,55 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTimeToPeakCurveDescriptionParameter.h" + +const std::string mitk::TimeToPeakCurveDescriptionParameter::PARAMETER_PEAK_NAME = "Peak"; +const std::string mitk::TimeToPeakCurveDescriptionParameter::PARAMETER_TIME_NAME = "Time"; + +mitk::TimeToPeakCurveDescriptionParameter::TimeToPeakCurveDescriptionParameter() +{ +} + +mitk::TimeToPeakCurveDescriptionParameter::~TimeToPeakCurveDescriptionParameter() +{ +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterNamesType mitk::TimeToPeakCurveDescriptionParameter::GetDescriptionParameterName() const +{ + DescriptionParameterNamesType result = { PARAMETER_TIME_NAME, PARAMETER_PEAK_NAME }; + return result; +} + +mitk::CurveDescriptionParameterBase::DescriptionParameterResultsType mitk::TimeToPeakCurveDescriptionParameter::ComputeCurveDescriptionParameter(const CurveType &curve, const CurveGridType &grid) const +{ + DescriptionParameterResultsType result; + CurveDescriptionParameterResultType time = itk::NumericTraits::NonpositiveMin(); + CurveDescriptionParameterResultType maximum = itk::NumericTraits::NonpositiveMin(); + int steps = grid.GetSize(); + + for (int i = 0; i < steps - 1; ++i) + { + if (curve(i) > maximum) + { + maximum = curve(i); + time = grid(i); + } + } + + result.push_back(time); + result.push_back(maximum); + return result; +} diff --git a/Modules/Pharmacokinetics/src/Functors/mitkCurveParameterFunctor.cpp b/Modules/Pharmacokinetics/src/Functors/mitkCurveParameterFunctor.cpp new file mode 100644 index 0000000000..af7f89376c --- /dev/null +++ b/Modules/Pharmacokinetics/src/Functors/mitkCurveParameterFunctor.cpp @@ -0,0 +1,141 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkCurveParameterFunctor.h" + +mitk::SimpleFunctorBase::OutputPixelVectorType +mitk::CurveParameterFunctor::Compute(const mitk::SimpleFunctorBase::InputPixelVectorType& value) +const +{ + if (this->m_Grid.GetSize() == 0) + { + itkExceptionMacro("Error. Cannot compute Curve Description Parameters. No Curve Grid set!"); + } + + if (this->m_DescriptorMap.size() == 0) + { + itkGenericExceptionMacro( << + "Error. Cannot compute Curve Description Parameters. No Parameters registered!"); + } + + CurveDescriptionParameterBase::CurveType sample(value.size()); + + for (CurveDescriptionParameterBase::CurveType::SizeValueType i = 0; i < sample.Size(); ++i) + { + sample[i] = value [i]; + } + + mitk::SimpleFunctorBase::OutputPixelVectorType result; + result.reserve(m_DescriptorMap.size()); //we will have at least this number of values + + unsigned int i = 0; + + for (DescriptionParameterMapType::const_iterator pos = m_DescriptorMap.begin(); + pos != m_DescriptorMap.end(); ++pos, ++i) + { + CurveDescriptionParameterBase* paramFct = const_cast + (pos->second.GetPointer()); + + CurveDescriptionParameterBase::DescriptionParameterResultsType fctResults = + paramFct->GetCurveDescriptionParameter(sample, this->m_Grid); + result.insert(result.end(), fctResults.begin(), fctResults.end()); + } + + if (this->GetDescriptionParameterNames().size() != result.size()) + { + itkGenericExceptionMacro( << + "Error. Curve parameter functor has an invalid state. Number of parameter names and number of computed values does not match. Names count: " + << this->GetDescriptionParameterNames().size() << "; value count: " << result.size()); + } + + return result; +}; + +unsigned int +mitk::CurveParameterFunctor::GetNumberOfOutputs() const +{ + return GetDescriptionParameterNames().size(); +}; + +mitk::CurveParameterFunctor::GridArrayType +mitk::CurveParameterFunctor::GetGrid() const +{ + return m_Grid; +}; + +void +mitk::CurveParameterFunctor::ResetDescriptionParameters() +{ + m_DescriptorMap.clear(); +}; + +void +mitk::CurveParameterFunctor::RegisterDescriptionParameter(const std::string& parameterName, + CurveDescriptionParameterBase* parameterFunction) +{ + CurveDescriptionParameterBase::Pointer paramFunctPtr = parameterFunction; + + m_DescriptorMap.insert(std::make_pair(parameterName, paramFunctPtr)); +}; + +mitk::CurveParameterFunctor::ParameterNamesType +mitk::CurveParameterFunctor::GetDescriptionParameterNames() const +{ + ParameterNamesType result; + + for (auto descriptor : m_DescriptorMap) + { + CurveDescriptionParameterBase::DescriptionParameterNamesType fctResults = + descriptor.second->GetDescriptionParameterName(); + + if (fctResults.size() > 1) + { + for (auto fctName : fctResults) + { + result.push_back(descriptor.first + "_" + fctName); + } + } + else + { //if the descriptor has only one parameter just use the registered descriptor name. + result.push_back(descriptor.first); + } + } + + return result; +}; + +const mitk::CurveDescriptionParameterBase* +mitk::CurveParameterFunctor::GetDescriptionParameterFunction(const std::string& parameterName) const +{ + const CurveDescriptionParameterBase* result = NULL; + + DescriptionParameterMapType::const_iterator pos = m_DescriptorMap.find(parameterName); + + if (pos != m_DescriptorMap.end()) + { + result = (pos->second).GetPointer(); + } + + return result; +}; + +mitk::CurveParameterFunctor:: +CurveParameterFunctor() +{}; + +mitk::CurveParameterFunctor:: +~CurveParameterFunctor() {}; + diff --git a/Modules/Pharmacokinetics/src/Models/mitkAIFBasedModelBase.cpp b/Modules/Pharmacokinetics/src/Models/mitkAIFBasedModelBase.cpp new file mode 100644 index 0000000000..374a81ca1c --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkAIFBasedModelBase.cpp @@ -0,0 +1,171 @@ +#include "mitkAIFBasedModelBase.h" +#include "mitkTimeGridHelper.h" +#include "mitkAIFParametrizerHelper.h" + +#include "itkArray2D.h" + + +const std::string mitk::AIFBasedModelBase::NAME_STATIC_PARAMETER_AIF = "Aterial Input Function"; +const std::string mitk::AIFBasedModelBase::NAME_STATIC_PARAMETER_AIFTimeGrid = + "Aterial Input Function Timegrid"; + +//Assumed AIF is always extracted from concentration image +const std::string mitk::AIFBasedModelBase::UNIT_STATIC_PARAMETER_AIF = "C"; +const std::string mitk::AIFBasedModelBase::UNIT_STATIC_PARAMETER_AIFTimeGrid = + "s"; + +std::string mitk::AIFBasedModelBase::GetXAxisName() const +{ + return "Time"; +}; + +std::string mitk::AIFBasedModelBase::GetXAxisUnit() const +{ + return "s"; +} + +std::string mitk::AIFBasedModelBase::GetYAxisName() const +{ + return ""; +}; + +std::string mitk::AIFBasedModelBase::GetYAxisUnit() const +{ + return ""; +} + +mitk::AIFBasedModelBase::AIFBasedModelBase() +{ +} + +mitk::AIFBasedModelBase::~AIFBasedModelBase() +{ +} + +const mitk::AIFBasedModelBase::TimeGridType& +mitk::AIFBasedModelBase::GetCurrentAterialInputFunctionTimeGrid() const +{ + if (!m_AterialInputFunctionTimeGrid.empty()) + { + return m_AterialInputFunctionTimeGrid; + } + else + { + return m_TimeGrid; + } +}; + +const mitk::AIFBasedModelBase::AterialInputFunctionType +mitk::AIFBasedModelBase::GetAterialInputFunction(TimeGridType CurrentTimeGrid) const +{ + if (CurrentTimeGrid.GetSize() == 0) + { + return this->m_AterialInputFunctionValues; + } + else + { + return mitk::InterpolateSignalToNewTimeGrid(m_AterialInputFunctionValues, + GetCurrentAterialInputFunctionTimeGrid(), CurrentTimeGrid); + } +} + +mitk::AIFBasedModelBase::ParameterNamesType mitk::AIFBasedModelBase::GetStaticParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_STATIC_PARAMETER_AIF); + result.push_back(NAME_STATIC_PARAMETER_AIFTimeGrid); + + return result; +} + +mitk::AIFBasedModelBase::ParametersSizeType mitk::AIFBasedModelBase::GetNumberOfStaticParameters() +const +{ + return 2; +} + +mitk::AIFBasedModelBase::ParamterUnitMapType +mitk::AIFBasedModelBase::GetStaticParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_STATIC_PARAMETER_AIF, UNIT_STATIC_PARAMETER_AIF)); + result.insert(std::make_pair(NAME_STATIC_PARAMETER_AIFTimeGrid, UNIT_STATIC_PARAMETER_AIFTimeGrid)); + + return result; +}; + + +void mitk::AIFBasedModelBase::SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values) +{ + if (name == NAME_STATIC_PARAMETER_AIF) + { + AterialInputFunctionType aif = mitk::convertParameterToArray(values); + + SetAterialInputFunctionValues(aif); + } + + if (name == NAME_STATIC_PARAMETER_AIFTimeGrid) + { + TimeGridType timegrid = mitk::convertParameterToArray(values); + + SetAterialInputFunctionTimeGrid(timegrid); + } +}; + +mitk::AIFBasedModelBase::StaticParameterValuesType mitk::AIFBasedModelBase::GetStaticParameterValue( + const ParameterNameType& name) const +{ + StaticParameterValuesType result; + + if (name == NAME_STATIC_PARAMETER_AIF) + { + result = mitk::convertArrayToParameter(this->m_AterialInputFunctionValues); + } + + if (name == NAME_STATIC_PARAMETER_AIFTimeGrid) + { + result = mitk::convertArrayToParameter(this->m_AterialInputFunctionTimeGrid); + } + + return result; +}; + +bool mitk::AIFBasedModelBase::ValidateModel(std::string& error) const +{ + bool result = Superclass::ValidateModel(error); + + if (result) + { + if (m_AterialInputFunctionTimeGrid.empty()) + { + if (this->m_TimeGrid.GetSize() != m_AterialInputFunctionValues.GetSize()) + { + result = false; + error = "Number of elements of Model Time Grid does not match number of elements in Aterial Input Function! Set valid aif or aif time grid."; + } + } + else + { + if (m_AterialInputFunctionTimeGrid.GetSize() != m_AterialInputFunctionValues.GetSize()) + { + result = false; + error = "Number of elements of Aterial Input Function Time Grid does not match number of elements of Aterial Input Function Values! Set valid curve"; + } + } + } + + return result; +}; + +void mitk::AIFBasedModelBase::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "Aterial Input Function: " << m_AterialInputFunctionValues; + os << indent << "Aterial Input Function Time Grid: " << m_AterialInputFunctionTimeGrid; +}; + + diff --git a/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModel.cpp new file mode 100644 index 0000000000..c6b2d6c32a --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModel.cpp @@ -0,0 +1,262 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkDescriptivePharmacokineticBrixModel.h" + +const std::string mitk::DescriptivePharmacokineticBrixModel::MODEL_DISPLAY_NAME = + "Descriptive Pharmacokinetic Brix Model"; + +const std::string mitk::DescriptivePharmacokineticBrixModel::NAME_PARAMETER_A = "A"; +const std::string mitk::DescriptivePharmacokineticBrixModel::NAME_PARAMETER_kep = "kep"; +const std::string mitk::DescriptivePharmacokineticBrixModel::NAME_PARAMETER_kel = "kel"; +//tlag in minutes +const std::string mitk::DescriptivePharmacokineticBrixModel::NAME_PARAMETER_tlag = "tlag"; + +const std::string mitk::DescriptivePharmacokineticBrixModel::UNIT_PARAMETER_A = "a.u."; +const std::string mitk::DescriptivePharmacokineticBrixModel::UNIT_PARAMETER_kep = "1/min"; +const std::string mitk::DescriptivePharmacokineticBrixModel::UNIT_PARAMETER_kel = "1/min"; +//tlag in minutes +const std::string mitk::DescriptivePharmacokineticBrixModel::UNIT_PARAMETER_tlag = "min"; + +const std::string mitk::DescriptivePharmacokineticBrixModel::NAME_STATIC_PARAMETER_Tau = "Tau"; +const std::string mitk::DescriptivePharmacokineticBrixModel::NAME_STATIC_PARAMETER_S0 = "S0"; + +const std::string mitk::DescriptivePharmacokineticBrixModel::UNIT_STATIC_PARAMETER_Tau = "min"; +const std::string mitk::DescriptivePharmacokineticBrixModel::UNIT_STATIC_PARAMETER_S0 = "I"; + +const unsigned int mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_A = 0; +const unsigned int mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kep = 1; +const unsigned int mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kel = 2; +const unsigned int mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_tlag = 3; + +const unsigned int mitk::DescriptivePharmacokineticBrixModel::NUMBER_OF_PARAMETERS = 4; + +std::string mitk::DescriptivePharmacokineticBrixModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::DescriptivePharmacokineticBrixModel::GetModelType() const +{ + return "Perfusion.MR"; +}; + +std::string mitk::DescriptivePharmacokineticBrixModel::GetXAxisName() const +{ + return "Time"; +}; + +std::string mitk::DescriptivePharmacokineticBrixModel::GetXAxisUnit() const +{ + return "s"; +} + +std::string mitk::DescriptivePharmacokineticBrixModel::GetYAxisName() const +{ + return ""; +}; + +std::string mitk::DescriptivePharmacokineticBrixModel::GetYAxisUnit() const +{ + return ""; +} + +mitk::DescriptivePharmacokineticBrixModel::DescriptivePharmacokineticBrixModel(): m_Tau(0), m_S0(1) +{ + +} + +mitk::DescriptivePharmacokineticBrixModel::~DescriptivePharmacokineticBrixModel() +{ + +} + +mitk::DescriptivePharmacokineticBrixModel::ParameterNamesType +mitk::DescriptivePharmacokineticBrixModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_A); + result.push_back(NAME_PARAMETER_kep); + result.push_back(NAME_PARAMETER_kel); + result.push_back(NAME_PARAMETER_tlag); + + return result; +} + +mitk::DescriptivePharmacokineticBrixModel::ParametersSizeType +mitk::DescriptivePharmacokineticBrixModel::GetNumberOfParameters() const +{ + return NUMBER_OF_PARAMETERS; +} + +mitk::DescriptivePharmacokineticBrixModel::ParamterUnitMapType +mitk::DescriptivePharmacokineticBrixModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_A, UNIT_PARAMETER_A)); + result.insert(std::make_pair(NAME_PARAMETER_kep, UNIT_PARAMETER_kep)); + result.insert(std::make_pair(NAME_PARAMETER_kel, UNIT_PARAMETER_kel)); + result.insert(std::make_pair(NAME_PARAMETER_tlag, UNIT_PARAMETER_tlag)); + + return result; +}; + +mitk::DescriptivePharmacokineticBrixModel::ParameterNamesType +mitk::DescriptivePharmacokineticBrixModel::GetStaticParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_STATIC_PARAMETER_Tau); + result.push_back(NAME_STATIC_PARAMETER_S0); + + return result; +} + +mitk::DescriptivePharmacokineticBrixModel::ParamterUnitMapType +mitk::DescriptivePharmacokineticBrixModel::GetStaticParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_STATIC_PARAMETER_Tau, UNIT_STATIC_PARAMETER_Tau)); + result.insert(std::make_pair(NAME_STATIC_PARAMETER_S0, UNIT_STATIC_PARAMETER_S0)); + + return result; +}; + +mitk::DescriptivePharmacokineticBrixModel::ParametersSizeType +mitk::DescriptivePharmacokineticBrixModel::GetNumberOfStaticParameters() const +{ + return 1; +} + + +mitk::DescriptivePharmacokineticBrixModel::ModelResultType +mitk::DescriptivePharmacokineticBrixModel::ComputeModelfunction(const ParametersType& parameters) +const +{ + if (m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + if (m_Tau == 0) + { + itkExceptionMacro("Injection time is 0! Cannot Calculate Signal"); + } + + unsigned int timeSteps = m_TimeGrid.GetSize(); + ModelResultType signal(m_TimeGrid.GetSize()); + + double tx = 0; + double amplitude = parameters[POSITION_PARAMETER_A]; + double kel = parameters[POSITION_PARAMETER_kel]; + double kep = parameters[POSITION_PARAMETER_kep]; + double tlag = parameters[POSITION_PARAMETER_tlag]; + + TimeGridType::const_iterator timeGridEnd = m_TimeGrid.end(); + ModelResultType::iterator signalPos = signal.begin(); + + for (TimeGridType::const_iterator gridPos = m_TimeGrid.begin(); gridPos != timeGridEnd; + ++gridPos, ++signalPos) + { + double t = (*gridPos) / 60.0; //convert from [sec] to [min] + + + if (t <= tlag) + { + tx = 0; + } + else if ((t > tlag) && (t < (m_Tau + tlag))) + { + tx = t - tlag; + } + else if (t >= (m_Tau + tlag)) + { + tx = m_Tau; + } + + double kDiff = kep - kel; + double tDiff = t - tlag; + + double expkel = (kep * exp(-kel * tDiff)); + double expkeltx = exp(kel * tx); + double expkep = exp(-kep * tDiff); + double expkeptx = exp(kep * tx); + + double value = 1 + (amplitude / m_Tau) * (((expkel / (kel * kDiff)) * (expkeltx - 1)) - (( + expkep / kDiff) * (expkeptx - 1))); + + *signalPos = value * m_S0; + } + + return signal; + +} + +void mitk::DescriptivePharmacokineticBrixModel::SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values) +{ + if (name == NAME_STATIC_PARAMETER_Tau) + { + SetTau(values[0]); + } + + if (name == NAME_STATIC_PARAMETER_S0) + { + SetS0(values[0]); + } +}; + +mitk::DescriptivePharmacokineticBrixModel::StaticParameterValuesType +mitk::DescriptivePharmacokineticBrixModel::GetStaticParameterValue(const ParameterNameType& name) +const +{ + StaticParameterValuesType result; + + if (name == NAME_STATIC_PARAMETER_Tau) + { + result.push_back(GetTau()); + } + + if (name == NAME_STATIC_PARAMETER_S0) + { + result.push_back(GetS0()); + } + + return result; +}; + +itk::LightObject::Pointer mitk::DescriptivePharmacokineticBrixModel::InternalClone() const +{ + DescriptivePharmacokineticBrixModel::Pointer newClone = DescriptivePharmacokineticBrixModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + newClone->SetTau(this->m_Tau); + newClone->SetS0(this->m_S0); + + return newClone.GetPointer(); +}; + +void mitk::DescriptivePharmacokineticBrixModel::PrintSelf(std::ostream& os, + ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "Tau (injection time): " << m_Tau; + os << indent << "S0 (base value): " << m_S0; +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModelFactory.cpp new file mode 100644 index 0000000000..4b6fffe0f8 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModelFactory.cpp @@ -0,0 +1,94 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +#include "mitkDescriptivePharmacokineticBrixModelFactory.h" +#include "mitkDescriptivePharmacokineticBrixModelParameterizer.h" +#include "mitkDescriptivePharmacokineticBrixModelValueBasedParameterizer.h" + +mitk::DescriptivePharmacokineticBrixModelFactory::DescriptivePharmacokineticBrixModelFactory() +{ +}; + +mitk::DescriptivePharmacokineticBrixModelFactory::~DescriptivePharmacokineticBrixModelFactory() +{ +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::DescriptivePharmacokineticBrixModelFactory::GetDefaultInitialParameterization() const +{ + return DescriptivePharmacokineticBrixModelParameterizer::New()->GetDefaultInitialParameterization(); +}; + +mitk::ModelParameterizerBase::Pointer +mitk::DescriptivePharmacokineticBrixModelFactory::DoCreateParameterizer( + const mitk::modelFit::ModelFitInfo* fit) const +{ + mitk::ModelParameterizerBase::Pointer result; + + if (fit->fitType == ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED()) + { + DescriptivePharmacokineticBrixModelParameterizer::Pointer modelParameterizer = + DescriptivePharmacokineticBrixModelParameterizer::New(); + + modelFit::StaticParameterMap::ValueType tau = fit->staticParamMap.Get( + DescriptivePharmacokineticBrixModel::NAME_STATIC_PARAMETER_Tau); + modelParameterizer->SetTau(tau[0]); + + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(fit->inputImage); + imageTimeSelector->SetTimeNr(0); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::DescriptivePharmacokineticBrixModelParameterizer::BaseImageType::Pointer baseImage; + mitk::CastToItkImage(imageTimeSelector->GetOutput(), baseImage); + + modelParameterizer->SetBaseImage(baseImage); + + result = modelParameterizer.GetPointer(); + } + else if (fit->fitType == ModelFitConstants::FIT_TYPE_VALUE_ROIBASED()) + { + DescriptivePharmacokineticBrixModelValueBasedParameterizer::Pointer modelParameterizer = + DescriptivePharmacokineticBrixModelValueBasedParameterizer::New(); + + modelFit::StaticParameterMap::ValueType tau = fit->staticParamMap.Get( + DescriptivePharmacokineticBrixModel::NAME_STATIC_PARAMETER_Tau); + modelParameterizer->SetTau(tau[0]); + + if (!fit->inputData.ValueExists("ROI")) + { + mitkThrow() << + "Cannot generate parameterizer for fit of type ROIbased. Input data with the lable \"ROI\" is missing in fit."; + } + + ScalarListLookupTable::ValueType signal = fit->inputData.GetTableValue("ROI"); + + if (signal.empty()) + { + mitkThrow() << + "Cannot generate parameterizer for fit of type ROIbased. Input data with the lable \"ROI\" is invalid: No values available."; + } + + modelParameterizer->SetBaseValue(signal[0]); + + result = modelParameterizer.GetPointer(); + } + + return result; +}; \ No newline at end of file diff --git a/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModelParameterizer.cpp new file mode 100644 index 0000000000..ac5a5ec38b --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModelParameterizer.cpp @@ -0,0 +1,66 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include "mitkDescriptivePharmacokineticBrixModel.h" +#include "mitkDescriptivePharmacokineticBrixModelParameterizer.h" + +mitk::DescriptivePharmacokineticBrixModelParameterizer::StaticParameterMapType +mitk::DescriptivePharmacokineticBrixModelParameterizer::GetGlobalStaticParameters() const +{ + StaticParameterMapType result; + StaticParameterValuesType values; + values.push_back(m_Tau); + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_Tau, values)); + return result; +}; + +mitk::DescriptivePharmacokineticBrixModelParameterizer::StaticParameterMapType +mitk::DescriptivePharmacokineticBrixModelParameterizer::GetLocalStaticParameters( + const IndexType& currentPosition) const +{ + StaticParameterMapType result; + + double s0 = m_BaseImage->GetPixel(currentPosition); + + StaticParameterValuesType values; + values.push_back(s0); + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_S0, values)); + + return result; +}; + +mitk::DescriptivePharmacokineticBrixModelParameterizer::ParametersType +mitk::DescriptivePharmacokineticBrixModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(4); + initialParameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_A] = 1.0; + initialParameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kep] = 4.0; + initialParameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kel] = 0.2; + initialParameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_tlag] = 1.0; + + return initialParameters; +} + +mitk::DescriptivePharmacokineticBrixModelParameterizer::DescriptivePharmacokineticBrixModelParameterizer() +{ +}; + +mitk::DescriptivePharmacokineticBrixModelParameterizer::~DescriptivePharmacokineticBrixModelParameterizer() +{ +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModelValueBasedParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModelValueBasedParameterizer.cpp new file mode 100644 index 0000000000..82a7bc23b9 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkDescriptivePharmacokineticBrixModelValueBasedParameterizer.cpp @@ -0,0 +1,65 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include "mitkDescriptivePharmacokineticBrixModel.h" +#include "mitkDescriptivePharmacokineticBrixModelValueBasedParameterizer.h" + +mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::StaticParameterMapType +mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::GetGlobalStaticParameters() const +{ + StaticParameterMapType result; + StaticParameterValuesType values; + values.push_back(m_Tau); + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_Tau, values)); + return result; +}; + +mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::StaticParameterMapType +mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::GetLocalStaticParameters( + const IndexType& currentPosition) const +{ + StaticParameterMapType result; + + StaticParameterValuesType values; + values.push_back(m_BaseValue); + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_S0, values)); + + return result; +}; + +mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::ParametersType +mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::GetDefaultInitialParameterization() +const +{ + ParametersType initialParameters; + initialParameters.SetSize(4); + initialParameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_A] = 1.0; + initialParameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kep] = 4.0; + initialParameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kel] = 0.2; + initialParameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_tlag] = 1.0; + + return initialParameters; +} + +mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::DescriptivePharmacokineticBrixModelValueBasedParameterizer() +{ +}; + +mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::~DescriptivePharmacokineticBrixModelValueBasedParameterizer() +{ +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkExtendedOneTissueCompartmentModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkExtendedOneTissueCompartmentModel.cpp new file mode 100644 index 0000000000..fcfd70e6e1 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkExtendedOneTissueCompartmentModel.cpp @@ -0,0 +1,151 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkExtendedOneTissueCompartmentModel.h" +#include "mitkConvolutionHelper.h" +#include +#include + +const std::string mitk::ExtendedOneTissueCompartmentModel::MODEL_DISPLAY_NAME = "Extended One Tissue Compartment Model (with blood volume)"; + +const std::string mitk::ExtendedOneTissueCompartmentModel::NAME_PARAMETER_k1 = "K1"; +const std::string mitk::ExtendedOneTissueCompartmentModel::NAME_PARAMETER_k2 = "k2"; +const std::string mitk::ExtendedOneTissueCompartmentModel::NAME_PARAMETER_VB = "VB"; + +const std::string mitk::ExtendedOneTissueCompartmentModel::UNIT_PARAMETER_k1 = "1/min"; +const std::string mitk::ExtendedOneTissueCompartmentModel::UNIT_PARAMETER_k2 = "1/min"; +const std::string mitk::ExtendedOneTissueCompartmentModel::UNIT_PARAMETER_VB = "ml/ml"; + +const unsigned int mitk::ExtendedOneTissueCompartmentModel::POSITION_PARAMETER_k1 = 0; +const unsigned int mitk::ExtendedOneTissueCompartmentModel::POSITION_PARAMETER_k2 = 1; +const unsigned int mitk::ExtendedOneTissueCompartmentModel::POSITION_PARAMETER_VB = 2; + +const unsigned int mitk::ExtendedOneTissueCompartmentModel::NUMBER_OF_PARAMETERS = 3; + +std::string mitk::ExtendedOneTissueCompartmentModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::ExtendedOneTissueCompartmentModel::GetModelType() const +{ + return "Dynamic.PET"; +}; + +mitk::ExtendedOneTissueCompartmentModel::ExtendedOneTissueCompartmentModel() +{ + +} + +mitk::ExtendedOneTissueCompartmentModel::~ExtendedOneTissueCompartmentModel() +{ + +} + +mitk::ExtendedOneTissueCompartmentModel::ParameterNamesType mitk::ExtendedOneTissueCompartmentModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_k1); + result.push_back(NAME_PARAMETER_k2); + result.push_back(NAME_PARAMETER_VB); + + return result; +} + +mitk::ExtendedOneTissueCompartmentModel::ParametersSizeType mitk::ExtendedOneTissueCompartmentModel::GetNumberOfParameters() +const +{ + return NUMBER_OF_PARAMETERS; +} + +mitk::ExtendedOneTissueCompartmentModel::ParamterUnitMapType +mitk::ExtendedOneTissueCompartmentModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_k1, UNIT_PARAMETER_k1)); + result.insert(std::make_pair(NAME_PARAMETER_k2, UNIT_PARAMETER_k2)); + result.insert(std::make_pair(NAME_PARAMETER_VB, UNIT_PARAMETER_VB)); + + return result; +}; + +mitk::ExtendedOneTissueCompartmentModel::ModelResultType mitk::ExtendedOneTissueCompartmentModel::ComputeModelfunction( + const ParametersType& parameters) const +{ + typedef itk::Array ResidueFunctionType; + + + if (this->m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + AterialInputFunctionType aterialInputFunction; + aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid); + + + + unsigned int timeSteps = this->m_TimeGrid.GetSize(); + + //Model Parameters + double K1 = (double) parameters[POSITION_PARAMETER_k1] / 60.0; + double k2 = (double) parameters[POSITION_PARAMETER_k2] / 60.0; + double VB = parameters[POSITION_PARAMETER_VB]; + + + + mitk::ModelBase::ModelResultType convolution = mitk::convoluteAIFWithExponential(this->m_TimeGrid, + aterialInputFunction, k2); + + //Signal that will be returned by ComputeModelFunction + mitk::ModelBase::ModelResultType signal(timeSteps); + signal.fill(0.0); + + mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); + + AterialInputFunctionType::const_iterator aifPos = aterialInputFunction.begin(); + + + for (mitk::ModelBase::ModelResultType::const_iterator res = convolution.begin(); res != convolution.end(); ++res, ++signalPos, ++aifPos) + { + *signalPos = VB * (*aifPos) + (1 - VB) * K1 * (*res); + } + + return signal; + +} + + + + +itk::LightObject::Pointer mitk::ExtendedOneTissueCompartmentModel::InternalClone() const +{ + ExtendedOneTissueCompartmentModel::Pointer newClone = ExtendedOneTissueCompartmentModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +}; + +void mitk::ExtendedOneTissueCompartmentModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + +}; + diff --git a/Modules/Pharmacokinetics/src/Models/mitkExtendedOneTissueCompartmentModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkExtendedOneTissueCompartmentModelFactory.cpp new file mode 100644 index 0000000000..add04aae08 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkExtendedOneTissueCompartmentModelFactory.cpp @@ -0,0 +1,41 @@ +#include "mitkExtendedOneTissueCompartmentModelFactory.h" + +#include +#include +#include + +mitk::ConstraintCheckerBase::Pointer +mitk::ExtendedOneTissueCompartmentModelFactory::CreateDefaultConstraints() const +{ + SimpleBarrierConstraintChecker::Pointer constraints = SimpleBarrierConstraintChecker::New(); + + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_k1, 0.0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_k2, 0.0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_VB, 0.0); + + constraints->SetUpperBarrier (ModelType::POSITION_PARAMETER_k1, 1.0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_k2, 1.0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_VB, 1.0); + + SimpleBarrierConstraintChecker::ParameterIndexVectorType indices; + indices.push_back(ModelType::POSITION_PARAMETER_k1); + indices.push_back(ModelType::POSITION_PARAMETER_k2); + indices.push_back(ModelType::POSITION_PARAMETER_VB); + + return constraints.GetPointer(); +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::ExtendedOneTissueCompartmentModelFactory::GetDefaultInitialParameterization() const +{ + return ExtendedOneTissueCompartmentModelParameterizer::New()->GetDefaultInitialParameterization(); +}; + +mitk::ExtendedOneTissueCompartmentModelFactory::ExtendedOneTissueCompartmentModelFactory() +{ +}; + +mitk::ExtendedOneTissueCompartmentModelFactory::~ExtendedOneTissueCompartmentModelFactory() +{ +}; + diff --git a/Modules/Pharmacokinetics/src/Models/mitkExtendedOneTissueCompartmentModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkExtendedOneTissueCompartmentModelParameterizer.cpp new file mode 100644 index 0000000000..37acff1b21 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkExtendedOneTissueCompartmentModelParameterizer.cpp @@ -0,0 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkExtendedOneTissueCompartmentModelParameterizer.h" + +mitk::ExtendedOneTissueCompartmentModelParameterizer::ParametersType +mitk::ExtendedOneTissueCompartmentModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(3); + initialParameters[mitk::ExtendedOneTissueCompartmentModel::POSITION_PARAMETER_k1] = 0.5; + initialParameters[mitk::ExtendedOneTissueCompartmentModel::POSITION_PARAMETER_k2] = 0.5; + initialParameters[mitk::ExtendedOneTissueCompartmentModel::POSITION_PARAMETER_VB] = 0.5; + + return initialParameters; +}; + +mitk::ExtendedOneTissueCompartmentModelParameterizer::ExtendedOneTissueCompartmentModelParameterizer() +{ +}; + +mitk::ExtendedOneTissueCompartmentModelParameterizer::~ExtendedOneTissueCompartmentModelParameterizer() +{ +}; + diff --git a/Modules/Pharmacokinetics/src/Models/mitkExtendedToftsModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkExtendedToftsModel.cpp new file mode 100644 index 0000000000..0f8a483fd9 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkExtendedToftsModel.cpp @@ -0,0 +1,184 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkExtendedToftsModel.h" +#include "mitkConvolutionHelper.h" +#include +#include + +const std::string mitk::ExtendedToftsModel::MODEL_DISPLAY_NAME = "Tofts Model"; + +const std::string mitk::ExtendedToftsModel::NAME_PARAMETER_Ktrans = "KTrans"; +const std::string mitk::ExtendedToftsModel::NAME_PARAMETER_ve = "ve"; +const std::string mitk::ExtendedToftsModel::NAME_PARAMETER_vp = "vp"; + +const std::string mitk::ExtendedToftsModel::UNIT_PARAMETER_Ktrans = "ml/min/100ml"; +const std::string mitk::ExtendedToftsModel::UNIT_PARAMETER_ve = "ml/ml"; +const std::string mitk::ExtendedToftsModel::UNIT_PARAMETER_vp = "ml/ml"; + +const unsigned int mitk::ExtendedToftsModel::POSITION_PARAMETER_Ktrans = 0; +const unsigned int mitk::ExtendedToftsModel::POSITION_PARAMETER_ve = 1; +const unsigned int mitk::ExtendedToftsModel::POSITION_PARAMETER_vp = 2; + +const unsigned int mitk::ExtendedToftsModel::NUMBER_OF_PARAMETERS = 3; + +std::string mitk::ExtendedToftsModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::ExtendedToftsModel::GetModelType() const +{ + return "Perfusion.MR"; +}; + +mitk::ExtendedToftsModel::ExtendedToftsModel() +{ + +} + +mitk::ExtendedToftsModel::~ExtendedToftsModel() +{ + +} + +mitk::ExtendedToftsModel::ParameterNamesType mitk::ExtendedToftsModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_Ktrans); + result.push_back(NAME_PARAMETER_ve); + result.push_back(NAME_PARAMETER_vp); + + return result; +} + +mitk::ExtendedToftsModel::ParametersSizeType mitk::ExtendedToftsModel::GetNumberOfParameters() +const +{ + return NUMBER_OF_PARAMETERS; +} + +mitk::ExtendedToftsModel::ParamterUnitMapType +mitk::ExtendedToftsModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_Ktrans, UNIT_PARAMETER_Ktrans)); + result.insert(std::make_pair(NAME_PARAMETER_vp, UNIT_PARAMETER_vp)); + result.insert(std::make_pair(NAME_PARAMETER_ve, UNIT_PARAMETER_ve)); + + return result; +}; + + + +mitk::ExtendedToftsModel::ParameterNamesType +mitk::ExtendedToftsModel::GetDerivedParameterNames() const +{ + ParameterNamesType result; + result.push_back("kep"); + return result; +}; + +mitk::ExtendedToftsModel::ParametersSizeType +mitk::ExtendedToftsModel::GetNumberOfDerivedParameters() const +{ + return 1; +}; + +mitk::ExtendedToftsModel::ParamterUnitMapType mitk::ExtendedToftsModel::GetDerivedParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair("kep", "1/min")); + + return result; +}; + +mitk::ExtendedToftsModel::ModelResultType mitk::ExtendedToftsModel::ComputeModelfunction( + const ParametersType& parameters) const +{ + typedef itk::Array ResidueFunctionType; + + + if (this->m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + AterialInputFunctionType aterialInputFunction; + aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid); + + + + unsigned int timeSteps = this->m_TimeGrid.GetSize(); + + //Model Parameters + double ktrans = parameters[POSITION_PARAMETER_Ktrans] / 6000.0; + double ve = parameters[POSITION_PARAMETER_ve]; + double vp = parameters[POSITION_PARAMETER_vp]; + + + double lambda = ktrans / ve; + + mitk::ModelBase::ModelResultType convolution = mitk::convoluteAIFWithExponential(this->m_TimeGrid, + aterialInputFunction, lambda); + + //Signal that will be returned by ComputeModelFunction + mitk::ModelBase::ModelResultType signal(timeSteps); + signal.fill(0.0); + + mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); + mitk::ModelBase::ModelResultType::const_iterator res = convolution.begin(); + + + for (AterialInputFunctionType::iterator Cp = aterialInputFunction.begin(); + Cp != aterialInputFunction.end(); ++res, ++signalPos, ++Cp) + { + *signalPos = (*Cp) * vp + ktrans * (*res); + } + + return signal; + +} + + +mitk::ModelBase::DerivedParameterMapType mitk::ExtendedToftsModel::ComputeDerivedParameters( + const mitk::ModelBase::ParametersType& parameters) const +{ + DerivedParameterMapType result; + double kep = parameters[POSITION_PARAMETER_Ktrans] / parameters[POSITION_PARAMETER_ve]; + result.insert(std::make_pair("kep", kep)); + return result; +}; + +itk::LightObject::Pointer mitk::ExtendedToftsModel::InternalClone() const +{ + ExtendedToftsModel::Pointer newClone = ExtendedToftsModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +}; + +void mitk::ExtendedToftsModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + +}; + diff --git a/Modules/Pharmacokinetics/src/Models/mitkExtendedToftsModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkExtendedToftsModelFactory.cpp new file mode 100644 index 0000000000..ba3c3088bc --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkExtendedToftsModelFactory.cpp @@ -0,0 +1,36 @@ +#include "mitkExtendedToftsModelFactory.h" + +#include +#include +#include + +mitk::ConstraintCheckerBase::Pointer +mitk::ExtendedToftsModelFactory::CreateDefaultConstraints() const +{ + SimpleBarrierConstraintChecker::Pointer constraints = SimpleBarrierConstraintChecker::New(); + + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_ve, 0.0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_ve, 1.0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_vp, 0.0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_vp, 1.0); + + SimpleBarrierConstraintChecker::ParameterIndexVectorType indices; + indices.push_back(ModelType::POSITION_PARAMETER_ve); + indices.push_back(ModelType::POSITION_PARAMETER_vp); + + constraints->SetUpperSumBarrier(indices, 1.0); + + return constraints.GetPointer(); +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::ExtendedToftsModelFactory::GetDefaultInitialParameterization() const +{ + return ExtendedToftsModelParameterizer::New()->GetDefaultInitialParameterization(); +}; + +mitk::ExtendedToftsModelFactory::ExtendedToftsModelFactory() += default; + +mitk::ExtendedToftsModelFactory::~ExtendedToftsModelFactory() += default; diff --git a/Modules/Pharmacokinetics/src/Models/mitkExtendedToftsModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkExtendedToftsModelParameterizer.cpp new file mode 100644 index 0000000000..538a643d8a --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkExtendedToftsModelParameterizer.cpp @@ -0,0 +1,37 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkExtendedToftsModelParameterizer.h" + +mitk::ExtendedToftsModelParameterizer::ParametersType +mitk::ExtendedToftsModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(3); + initialParameters[mitk::ExtendedToftsModel::POSITION_PARAMETER_Ktrans] = 15; + initialParameters[mitk::ExtendedToftsModel::POSITION_PARAMETER_ve] = 0.5; + initialParameters[mitk::ExtendedToftsModel::POSITION_PARAMETER_vp] = 0.05; + + return initialParameters; +}; + +mitk::ExtendedToftsModelParameterizer::ExtendedToftsModelParameterizer() +{ +}; + +mitk::ExtendedToftsModelParameterizer::~ExtendedToftsModelParameterizer() +{ +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkNumericTwoCompartmentExchangeModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoCompartmentExchangeModel.cpp new file mode 100644 index 0000000000..8d6fe16622 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoCompartmentExchangeModel.cpp @@ -0,0 +1,290 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNumericTwoCompartmentExchangeModel.h" +#include "mitkAIFParametrizerHelper.h" +#include "mitkTimeGridHelper.h" +#include "mitkTwoCompartmentExchangeModelDifferentialEquations.h" +#include +#include +#include + +const std::string mitk::NumericTwoCompartmentExchangeModel::MODEL_DISPLAY_NAME = + "Numeric Two Compartment Exchange Model"; + +const std::string mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_F = "F"; +const std::string mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_PS = "PS"; +const std::string mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_ve = "ve"; +const std::string mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_vp = "vp"; + +const std::string mitk::NumericTwoCompartmentExchangeModel::UNIT_PARAMETER_F = "ml/min/100ml"; +const std::string mitk::NumericTwoCompartmentExchangeModel::UNIT_PARAMETER_PS = "ml/min/100ml"; +const std::string mitk::NumericTwoCompartmentExchangeModel::UNIT_PARAMETER_ve = "ml/ml"; +const std::string mitk::NumericTwoCompartmentExchangeModel::UNIT_PARAMETER_vp = "ml/ml"; + +const unsigned int mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_F = 0; +const unsigned int mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_PS = 1; +const unsigned int mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_ve = 2; +const unsigned int mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_vp = 3; + +const unsigned int mitk::NumericTwoCompartmentExchangeModel::NUMBER_OF_PARAMETERS = 4; + +const std::string mitk::NumericTwoCompartmentExchangeModel::NAME_STATIC_PARAMETER_ODEINTStepSize = "ODEIntStepSize"; + + +std::string mitk::NumericTwoCompartmentExchangeModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::NumericTwoCompartmentExchangeModel::GetModelType() const +{ + return "Perfusion.MR"; +}; + + +mitk::NumericTwoCompartmentExchangeModel::NumericTwoCompartmentExchangeModel() +{ + +} + +mitk::NumericTwoCompartmentExchangeModel::~NumericTwoCompartmentExchangeModel() +{ + +} + +mitk::NumericTwoCompartmentExchangeModel::ParameterNamesType mitk::NumericTwoCompartmentExchangeModel::GetStaticParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_STATIC_PARAMETER_AIF); + result.push_back(NAME_STATIC_PARAMETER_AIFTimeGrid); + result.push_back(NAME_STATIC_PARAMETER_ODEINTStepSize); + + return result; +} + +mitk::NumericTwoCompartmentExchangeModel::ParametersSizeType mitk::NumericTwoCompartmentExchangeModel::GetNumberOfStaticParameters() +const +{ + return 3; +} + + +void mitk::NumericTwoCompartmentExchangeModel::SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values) +{ + if (name == NAME_STATIC_PARAMETER_AIF) + { + AterialInputFunctionType aif = mitk::convertParameterToArray(values); + + SetAterialInputFunctionValues(aif); + } + + if (name == NAME_STATIC_PARAMETER_AIFTimeGrid) + { + TimeGridType timegrid = mitk::convertParameterToArray(values); + + SetAterialInputFunctionTimeGrid(timegrid); + } + + if (name == NAME_STATIC_PARAMETER_ODEINTStepSize) + { + SetODEINTStepSize(values[0]); + } +}; + +mitk::NumericTwoCompartmentExchangeModel::StaticParameterValuesType mitk::NumericTwoCompartmentExchangeModel::GetStaticParameterValue( + const ParameterNameType& name) const +{ + StaticParameterValuesType result; + + if (name == NAME_STATIC_PARAMETER_AIF) + { + result = mitk::convertArrayToParameter(this->m_AterialInputFunctionValues); + } + + if (name == NAME_STATIC_PARAMETER_AIFTimeGrid) + { + result = mitk::convertArrayToParameter(this->m_AterialInputFunctionTimeGrid); + } + if (name == NAME_STATIC_PARAMETER_ODEINTStepSize) + { + result.push_back(GetODEINTStepSize()); + } + + return result; +}; + + +mitk::NumericTwoCompartmentExchangeModel::ParameterNamesType +mitk::NumericTwoCompartmentExchangeModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_F); + result.push_back(NAME_PARAMETER_PS); + result.push_back(NAME_PARAMETER_ve); + result.push_back(NAME_PARAMETER_vp); + + return result; +} + +mitk::NumericTwoCompartmentExchangeModel::ParametersSizeType +mitk::NumericTwoCompartmentExchangeModel::GetNumberOfParameters() const +{ + return NUMBER_OF_PARAMETERS; +} + + +mitk::NumericTwoCompartmentExchangeModel::ParamterUnitMapType +mitk::NumericTwoCompartmentExchangeModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_F, UNIT_PARAMETER_F)); + result.insert(std::make_pair(NAME_PARAMETER_PS, UNIT_PARAMETER_PS)); + result.insert(std::make_pair(NAME_PARAMETER_vp, UNIT_PARAMETER_vp)); + result.insert(std::make_pair(NAME_PARAMETER_ve, UNIT_PARAMETER_ve)); + + return result; +}; + +mitk::NumericTwoCompartmentExchangeModel::ModelResultType +mitk::NumericTwoCompartmentExchangeModel::ComputeModelfunction(const ParametersType& parameters) +const +{ + typedef itk::Array ConcentrationCurveType; + typedef std::vector ConcentrationVectorType; + + if (this->m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + AterialInputFunctionType aterialInputFunction; + aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid); + + unsigned int timeSteps = this->m_TimeGrid.GetSize(); + + /** @brief Boost::numeric::odeint works with type std::vector thus, aif and grid are converted to ModelParameters( of type std::vector) + */ + mitk::TwoCompartmentExchangeModelDifferentialEquations::AIFType aif = mitk::convertArrayToParameter( + aterialInputFunction); + mitk::TwoCompartmentExchangeModelDifferentialEquations::AIFType grid = + mitk::convertArrayToParameter(m_TimeGrid); + + mitk::TwoCompartmentExchangeModelDifferentialEquations::AIFType aifODE = aif; + aifODE.push_back(aif[timeSteps - 1]); + mitk::TwoCompartmentExchangeModelDifferentialEquations::AIFType gridODE = grid; + gridODE.push_back(grid[timeSteps - 1] + (grid[timeSteps - 1] - grid[timeSteps - 2])); + + + + //Model Parameters + double F = (double) parameters[POSITION_PARAMETER_F] / 6000.0; + double PS = (double) parameters[POSITION_PARAMETER_PS] / 6000.0; + double ve = (double) parameters[POSITION_PARAMETER_ve]; + double vp = (double) parameters[POSITION_PARAMETER_vp]; + + + /** @brief Initialize class TwoCompartmentExchangeModelDifferentialEquations defining the differential equations. AIF and Grid must be set so that at step t the aterial Concentration Ca(t) can be interpolated from AIF*/ + mitk::TwoCompartmentExchangeModelDifferentialEquations ode; + ode.initialize(F, PS, ve, vp); + ode.setAIF(aifODE); + ode.setAIFTimeGrid(gridODE); + + state_type x(2); + x[0] = 0.0; + x[1] = 0.0; + typedef boost::numeric::odeint::runge_kutta_cash_karp54 error_stepper_type; + //typedef boost::numeric::odeint::runge_kutta4< state_type > stepper_type; + + /** @brief Results of odeeint x[0] and x[1]*/ + ConcentrationVectorType Cp; + ConcentrationVectorType Ce; + ConcentrationVectorType odeTimeGrid; + + error_stepper_type stepper; + + + /** @brief Stepsize. Should be adapted by stepper (runge_kutta_cash_karp54) */ +// const double dt = 0.05; + const double dt = this->m_ODEINTStepSize; + + + /** @brief perform Step t -> t+dt to calculate approximate value x(t+dt)*/ + for (double t = 0.0; t < this->m_TimeGrid(this->m_TimeGrid.GetSize() - 1) - 2*dt; t += dt) + { + stepper.do_step(ode, x, t, dt); + Cp.push_back(x[0]); + Ce.push_back(x[1]); + odeTimeGrid.push_back(t); + } + + /** @brief transfom result of Differential equations back to itk::Array and interpolate to m_TimeGrid (they are calculated on a different grid defined by stepsize of odeint)*/ + ConcentrationCurveType plasmaConcentration = mitk::convertParameterToArray(Cp); + ConcentrationCurveType EESConcentration = mitk::convertParameterToArray(Ce); + ConcentrationCurveType rungeKuttaTimeGrid = mitk::convertParameterToArray(odeTimeGrid); + + mitk::ModelBase::ModelResultType C_Plasma = mitk::InterpolateSignalToNewTimeGrid(plasmaConcentration, rungeKuttaTimeGrid, m_TimeGrid); + mitk::ModelBase::ModelResultType C_EES = mitk::InterpolateSignalToNewTimeGrid(EESConcentration, rungeKuttaTimeGrid, m_TimeGrid); + + + //Signal that will be returned by ComputeModelFunction + mitk::ModelBase::ModelResultType signal(timeSteps); + signal.fill(0.0); + + mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); + mitk::ModelBase::ModelResultType::const_iterator CePos = C_EES.begin(); + + mitk::ModelBase::ModelResultType::const_iterator t = this->m_TimeGrid.begin(); + mitk::ModelBase::ModelResultType::const_iterator Cin = aterialInputFunction.begin(); + + + + for (mitk::ModelBase::ModelResultType::const_iterator CpPos = C_Plasma.begin(); + CpPos != C_Plasma.end(); ++CpPos, ++CePos, ++signalPos, ++t, ++Cin) + { + *signalPos = vp * (*CpPos) + ve * (*CePos); + + } + + return signal; + +} + + + + +itk::LightObject::Pointer mitk::NumericTwoCompartmentExchangeModel::InternalClone() const +{ + NumericTwoCompartmentExchangeModel::Pointer newClone = NumericTwoCompartmentExchangeModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +} + +void mitk::NumericTwoCompartmentExchangeModel::PrintSelf(std::ostream& os, + ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + +} + + diff --git a/Modules/Pharmacokinetics/src/Models/mitkNumericTwoCompartmentExchangeModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoCompartmentExchangeModelFactory.cpp new file mode 100644 index 0000000000..9a80c9c274 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoCompartmentExchangeModelFactory.cpp @@ -0,0 +1,58 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNumericTwoCompartmentExchangeModelFactory.h" + + +#include "mitkNumericTwoCompartmentExchangeModelParameterizer.h" +#include "mitkAIFParametrizerHelper.h" + +mitk::NumericTwoCompartmentExchangeModelFactory::NumericTwoCompartmentExchangeModelFactory() +{ +}; + +mitk::NumericTwoCompartmentExchangeModelFactory::~NumericTwoCompartmentExchangeModelFactory() +{ +}; + +mitk::ModelParameterizerBase::Pointer +mitk::NumericTwoCompartmentExchangeModelFactory::DoCreateParameterizer( + const modelFit::ModelFitInfo* fit) +const +{ + mitk::ModelParameterizerBase::Pointer result; + + ModelParameterizerType::Pointer modelParameterizer = + ModelParameterizerType::New(); + + modelFit::StaticParameterMap::ValueType aif = fit->staticParamMap.Get( + ModelType::NAME_STATIC_PARAMETER_AIF); + + modelParameterizer->SetAIF(mitk::convertParameterToArray(aif)); + + modelFit::StaticParameterMap::ValueType aifGrid = fit->staticParamMap.Get( + ModelType::NAME_STATIC_PARAMETER_AIFTimeGrid); + modelParameterizer->SetAIFTimeGrid(mitk::convertParameterToArray(aifGrid)); + + modelFit::StaticParameterMap::ValueType odeStepSize = fit->staticParamMap.Get( + ModelType::NAME_STATIC_PARAMETER_ODEINTStepSize); + modelParameterizer->SetODEINTStepSize(odeStepSize[0]); + + + result = modelParameterizer.GetPointer(); + + return result; +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkNumericTwoCompartmentExchangeModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoCompartmentExchangeModelParameterizer.cpp new file mode 100644 index 0000000000..40a6a83dc0 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoCompartmentExchangeModelParameterizer.cpp @@ -0,0 +1,53 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNumericTwoCompartmentExchangeModelParameterizer.h" + +mitk::NumericTwoCompartmentExchangeModelParameterizer::ParametersType +mitk::NumericTwoCompartmentExchangeModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(4); + initialParameters[mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_PS] = 5.0; + initialParameters[mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_F] = 20.0; + initialParameters[mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_ve] = 0.1; + initialParameters[mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_vp] = 0.04; + + return initialParameters; +}; + +mitk::NumericTwoCompartmentExchangeModelParameterizer::NumericTwoCompartmentExchangeModelParameterizer() +{ +}; + +mitk::NumericTwoCompartmentExchangeModelParameterizer::~NumericTwoCompartmentExchangeModelParameterizer() +{ +}; + +mitk::NumericTwoCompartmentExchangeModelParameterizer::StaticParameterMapType mitk::NumericTwoCompartmentExchangeModelParameterizer::GetGlobalStaticParameters() const +{ + StaticParameterMapType result; + StaticParameterValuesType valuesAIF = mitk::convertArrayToParameter(this->m_AIF); + StaticParameterValuesType valuesAIFGrid = mitk::convertArrayToParameter(this->m_AIFTimeGrid); + StaticParameterValuesType values; + values.push_back(m_ODEINTStepSize); + + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_AIF, valuesAIF)); + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_AIFTimeGrid, valuesAIFGrid)); + result.insert(std::make_pair(ModelType::NAME_STATIC_PARAMETER_ODEINTStepSize, values)); + + return result; +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkNumericTwoTissueCompartmentModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoTissueCompartmentModel.cpp new file mode 100644 index 0000000000..0da93c4115 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoTissueCompartmentModel.cpp @@ -0,0 +1,220 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNumericTwoTissueCompartmentModel.h" +#include "mitkAIFParametrizerHelper.h" +#include "mitkTimeGridHelper.h" +#include "mitkTwoTissueCompartmentModelDifferentialEquations.h" +#include +#include +#include + +const std::string mitk::NumericTwoTissueCompartmentModel::MODEL_DISPLAY_NAME = + "Numeric Two Tissue Compartment Model"; + +const std::string mitk::NumericTwoTissueCompartmentModel::NAME_PARAMETER_K1 = "K1"; +const std::string mitk::NumericTwoTissueCompartmentModel::NAME_PARAMETER_k2 = "k2"; +const std::string mitk::NumericTwoTissueCompartmentModel::NAME_PARAMETER_k3 = "k3"; +const std::string mitk::NumericTwoTissueCompartmentModel::NAME_PARAMETER_k4 = "k4"; +const std::string mitk::NumericTwoTissueCompartmentModel::NAME_PARAMETER_VB = "V_B"; + +const std::string mitk::NumericTwoTissueCompartmentModel::UNIT_PARAMETER_K1 = "1/min"; +const std::string mitk::NumericTwoTissueCompartmentModel::UNIT_PARAMETER_k2 = "1/min"; +const std::string mitk::NumericTwoTissueCompartmentModel::UNIT_PARAMETER_k3 = "1/min"; +const std::string mitk::NumericTwoTissueCompartmentModel::UNIT_PARAMETER_k4 = "1/min"; +const std::string mitk::NumericTwoTissueCompartmentModel::UNIT_PARAMETER_VB = "ml/ml"; + +const unsigned int mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_K1 = 0; +const unsigned int mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_k2 = 1; +const unsigned int mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_k3 = 2; +const unsigned int mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_k4 = 3; +const unsigned int mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_VB = 4; + +const unsigned int mitk::NumericTwoTissueCompartmentModel::NUMBER_OF_PARAMETERS = 5; + + +std::string mitk::NumericTwoTissueCompartmentModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::NumericTwoTissueCompartmentModel::GetModelType() const +{ + return "Dynamic.PET"; +}; + +mitk::NumericTwoTissueCompartmentModel::NumericTwoTissueCompartmentModel() +{ + +} + +mitk::NumericTwoTissueCompartmentModel::~NumericTwoTissueCompartmentModel() +{ + +} + +mitk::NumericTwoTissueCompartmentModel::ParameterNamesType +mitk::NumericTwoTissueCompartmentModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_K1); + result.push_back(NAME_PARAMETER_k2); + result.push_back(NAME_PARAMETER_k3); + result.push_back(NAME_PARAMETER_k4); + result.push_back(NAME_PARAMETER_VB); + + return result; +} + +mitk::NumericTwoTissueCompartmentModel::ParametersSizeType +mitk::NumericTwoTissueCompartmentModel::GetNumberOfParameters() const +{ + return NUMBER_OF_PARAMETERS; +} + +mitk::NumericTwoTissueCompartmentModel::ParamterUnitMapType +mitk::NumericTwoTissueCompartmentModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_K1, UNIT_PARAMETER_K1)); + result.insert(std::make_pair(NAME_PARAMETER_k2, UNIT_PARAMETER_k2)); + result.insert(std::make_pair(NAME_PARAMETER_k3, UNIT_PARAMETER_k3)); + result.insert(std::make_pair(NAME_PARAMETER_k4, UNIT_PARAMETER_k4)); + result.insert(std::make_pair(NAME_PARAMETER_VB, UNIT_PARAMETER_VB)); + + return result; +}; + + +mitk::NumericTwoTissueCompartmentModel::ModelResultType +mitk::NumericTwoTissueCompartmentModel::ComputeModelfunction(const ParametersType& parameters) const +{ + typedef itk::Array ConcentrationCurveType; + typedef std::vector ConcentrationVectorType; + + if (this->m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + AterialInputFunctionType aterialInputFunction; + aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid); + + unsigned int timeSteps = this->m_TimeGrid.GetSize(); + + /** @brief Boost::numeric::odeint works with type std::vector thus, aif and grid are converted to ModelParameters( of type std::vector) + */ + mitk::TwoTissueCompartmentModelDifferentialEquations::AIFType aif = mitk::convertArrayToParameter( + aterialInputFunction); + mitk::TwoTissueCompartmentModelDifferentialEquations::AIFType grid = mitk::convertArrayToParameter( + m_TimeGrid); + + mitk::TwoTissueCompartmentModelDifferentialEquations::AIFType aifODE = aif; + aifODE.push_back(aif[timeSteps - 1]); + mitk::TwoTissueCompartmentModelDifferentialEquations::AIFType gridODE = grid; + gridODE.push_back(grid[timeSteps - 1] + (grid[timeSteps - 1] - grid[timeSteps - 2])); + + //Model Parameters + double K1 = (double)parameters[POSITION_PARAMETER_K1] / 60.0; + double k2 = (double)parameters[POSITION_PARAMETER_k2] / 60.0; + double k3 = (double)parameters[POSITION_PARAMETER_k3] / 60.0; + double k4 = (double)parameters[POSITION_PARAMETER_k4] / 60.0; + double VB = parameters[POSITION_PARAMETER_VB]; + + + /** @brief Initialize class TwpTissueCompartmentModelDifferentialEquations defining the differential equations. AIF and Grid must be set so that at step t the aterial Concentration Ca(t) can be interpolated from AIF*/ + mitk::TwoTissueCompartmentModelDifferentialEquations ode; + ode.initialize(K1, k2, k3, k4); + ode.setAIF(aifODE); + ode.setAIFTimeGrid(gridODE); + + state_type x(2); + x[0] = 0.0; + x[1] = 0.0; + typedef boost::numeric::odeint::runge_kutta_cash_karp54 error_stepper_type; + //typedef boost::numeric::odeint::runge_kutta4< state_type > stepper_type; + + /** @brief Results of odeeint x[0] and x[1]*/ + ConcentrationVectorType C1; + ConcentrationVectorType C2; + ConcentrationVectorType odeTimeGrid; + + error_stepper_type stepper; + /** @brief Stepsize. Should be adapted by stepper (runge_kutta_cash_karp54) */ + const double dt = 0.1; + /** @brief perform Step t -> t+dt to calculate approximate value x(t+dt)*/ + + double T = this->m_TimeGrid(timeSteps - 1) + (grid[timeSteps - 1] - grid[timeSteps - 2]); + + for (double t = 0.0; t < T; t += dt) + { + stepper.do_step(ode, x, t, dt); + C1.push_back(x[0]); + C2.push_back(x[1]); + odeTimeGrid.push_back(t); + + } + + /** @brief transfom result of Differential equations back to itk::Array and interpolate to m_TimeGrid (they are calculated on a different grid defined by stepsize of odeint)*/ + ConcentrationCurveType ConcentrationCompartment1 = mitk::convertParameterToArray(C1); + ConcentrationCurveType ConcentrationCompartment2 = mitk::convertParameterToArray(C2); + ConcentrationCurveType rungeKuttaTimeGrid = mitk::convertParameterToArray(odeTimeGrid); + + mitk::ModelBase::ModelResultType C_1 = mitk::InterpolateSignalToNewTimeGrid( + ConcentrationCompartment1, rungeKuttaTimeGrid, m_TimeGrid); + mitk::ModelBase::ModelResultType C_2 = mitk::InterpolateSignalToNewTimeGrid( + ConcentrationCompartment2, rungeKuttaTimeGrid, m_TimeGrid); + + + //Signal that will be returned by ComputeModelFunction + mitk::ModelBase::ModelResultType signal(timeSteps); + signal.fill(0.0); + mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); + mitk::ModelBase::ModelResultType::const_iterator C1Pos = C_1.begin(); + mitk::ModelBase::ModelResultType::const_iterator C2Pos = C_2.begin(); + + + for (AterialInputFunctionType::const_iterator aifpos = aterialInputFunction.begin(); + aifpos != aterialInputFunction.end(); ++aifpos, ++C1Pos, ++C2Pos, ++signalPos) + { + *signalPos = VB * (*aifpos) + (1 - VB) * (*C1Pos + *C2Pos); + } + + return signal; + +} + +itk::LightObject::Pointer mitk::NumericTwoTissueCompartmentModel::InternalClone() const +{ + NumericTwoTissueCompartmentModel::Pointer newClone = NumericTwoTissueCompartmentModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +} + +void mitk::NumericTwoTissueCompartmentModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + +} + + + + diff --git a/Modules/Pharmacokinetics/src/Models/mitkNumericTwoTissueCompartmentModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoTissueCompartmentModelFactory.cpp new file mode 100644 index 0000000000..446cd7dccd --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoTissueCompartmentModelFactory.cpp @@ -0,0 +1,29 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNumericTwoTissueCompartmentModelFactory.h" + +#include "mitkNumericTwoTissueCompartmentModelParameterizer.h" +#include "mitkAIFParametrizerHelper.h" + +mitk::NumericTwoTissueCompartmentModelFactory::NumericTwoTissueCompartmentModelFactory() +{ +}; + +mitk::NumericTwoTissueCompartmentModelFactory::~NumericTwoTissueCompartmentModelFactory() +{ +}; + diff --git a/Modules/Pharmacokinetics/src/Models/mitkNumericTwoTissueCompartmentModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoTissueCompartmentModelParameterizer.cpp new file mode 100644 index 0000000000..6274fe8497 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkNumericTwoTissueCompartmentModelParameterizer.cpp @@ -0,0 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkNumericTwoTissueCompartmentModelParameterizer.h" + +mitk::NumericTwoTissueCompartmentModelParameterizer::ParametersType +mitk::NumericTwoTissueCompartmentModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(5); + initialParameters[mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_K1] = 0.23; + initialParameters[mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_k2] = 0.4; + initialParameters[mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_k3] = 0.13; + initialParameters[mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_k4] = 0.15; + initialParameters[mitk::NumericTwoTissueCompartmentModel::POSITION_PARAMETER_VB] = 0.03; + + return initialParameters; +}; + +mitk::NumericTwoTissueCompartmentModelParameterizer::NumericTwoTissueCompartmentModelParameterizer() +{ +}; + +mitk::NumericTwoTissueCompartmentModelParameterizer::~NumericTwoTissueCompartmentModelParameterizer() +{ +}; \ No newline at end of file diff --git a/Modules/Pharmacokinetics/src/Models/mitkOneTissueCompartmentModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkOneTissueCompartmentModel.cpp new file mode 100644 index 0000000000..3514eeaef2 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkOneTissueCompartmentModel.cpp @@ -0,0 +1,145 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkOneTissueCompartmentModel.h" +#include "mitkConvolutionHelper.h" +#include +#include + +const std::string mitk::OneTissueCompartmentModel::MODEL_DISPLAY_NAME = "One Tissue Compartment Model"; + +const std::string mitk::OneTissueCompartmentModel::NAME_PARAMETER_k1 = "K1"; +const std::string mitk::OneTissueCompartmentModel::NAME_PARAMETER_k2 = "k2"; + +const std::string mitk::OneTissueCompartmentModel::UNIT_PARAMETER_k1 = "1/min"; +const std::string mitk::OneTissueCompartmentModel::UNIT_PARAMETER_k2 = "1/min"; + +const unsigned int mitk::OneTissueCompartmentModel::POSITION_PARAMETER_k1 = 0; +const unsigned int mitk::OneTissueCompartmentModel::POSITION_PARAMETER_k2 = 1; + +const unsigned int mitk::OneTissueCompartmentModel::NUMBER_OF_PARAMETERS = 2; + +std::string mitk::OneTissueCompartmentModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::OneTissueCompartmentModel::GetModelType() const +{ + return "Dynamic.PET"; +}; + +mitk::OneTissueCompartmentModel::OneTissueCompartmentModel() +{ + +} + +mitk::OneTissueCompartmentModel::~OneTissueCompartmentModel() +{ + +} + +mitk::OneTissueCompartmentModel::ParameterNamesType mitk::OneTissueCompartmentModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_k1); + result.push_back(NAME_PARAMETER_k2); + + return result; +} + +mitk::OneTissueCompartmentModel::ParametersSizeType mitk::OneTissueCompartmentModel::GetNumberOfParameters() +const +{ + return NUMBER_OF_PARAMETERS; +} + + +mitk::OneTissueCompartmentModel::ParamterUnitMapType +mitk::OneTissueCompartmentModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_k1, UNIT_PARAMETER_k1)); + result.insert(std::make_pair(NAME_PARAMETER_k2, UNIT_PARAMETER_k2)); + + return result; +}; + +mitk::OneTissueCompartmentModel::ModelResultType mitk::OneTissueCompartmentModel::ComputeModelfunction( + const ParametersType& parameters) const +{ + typedef itk::Array ResidueFunctionType; + + + if (this->m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + AterialInputFunctionType aterialInputFunction; + aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid); + + + + unsigned int timeSteps = this->m_TimeGrid.GetSize(); + + //Model Parameters + double K1 = (double) parameters[POSITION_PARAMETER_k1] / 60.0; + double k2 = (double) parameters[POSITION_PARAMETER_k2] / 60.0; + + + + mitk::ModelBase::ModelResultType convolution = mitk::convoluteAIFWithExponential(this->m_TimeGrid, + aterialInputFunction, k2); + + //Signal that will be returned by ComputeModelFunction + mitk::ModelBase::ModelResultType signal(timeSteps); + signal.fill(0.0); + + mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); + + + + for (mitk::ModelBase::ModelResultType::const_iterator res = convolution.begin(); res != convolution.end(); ++res, ++signalPos) + { + *signalPos = K1 * (*res); + } + + return signal; + +} + + + + +itk::LightObject::Pointer mitk::OneTissueCompartmentModel::InternalClone() const +{ + OneTissueCompartmentModel::Pointer newClone = OneTissueCompartmentModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +}; + +void mitk::OneTissueCompartmentModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + +}; + diff --git a/Modules/Pharmacokinetics/src/Models/mitkOneTissueCompartmentModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkOneTissueCompartmentModelFactory.cpp new file mode 100644 index 0000000000..af01348e94 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkOneTissueCompartmentModelFactory.cpp @@ -0,0 +1,34 @@ +#include "mitkOneTissueCompartmentModelFactory.h" + +#include +#include +#include + +mitk::ConstraintCheckerBase::Pointer +mitk::OneTissueCompartmentModelFactory::CreateDefaultConstraints() const +{ + SimpleBarrierConstraintChecker::Pointer constraints = SimpleBarrierConstraintChecker::New(); + + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_k1, 0.0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_k2, 0.0); + + constraints->SetUpperBarrier (ModelType::POSITION_PARAMETER_k1, 1.0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_k2, 1.0); + + + return constraints.GetPointer(); +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::OneTissueCompartmentModelFactory::GetDefaultInitialParameterization() const +{ + return OneTissueCompartmentModelParameterizer::New()->GetDefaultInitialParameterization(); +}; + +mitk::OneTissueCompartmentModelFactory::OneTissueCompartmentModelFactory() +{ +}; + +mitk::OneTissueCompartmentModelFactory::~OneTissueCompartmentModelFactory() +{ +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkOneTissueCompartmentModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkOneTissueCompartmentModelParameterizer.cpp new file mode 100644 index 0000000000..b1030c1ad1 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkOneTissueCompartmentModelParameterizer.cpp @@ -0,0 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkOneTissueCompartmentModelParameterizer.h" + +mitk::OneTissueCompartmentModelParameterizer::ParametersType +mitk::OneTissueCompartmentModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(2); + initialParameters[mitk::OneTissueCompartmentModel::POSITION_PARAMETER_k1] = 0.5; + initialParameters[mitk::OneTissueCompartmentModel::POSITION_PARAMETER_k2] = 0.5; + + return initialParameters; +}; + +mitk::OneTissueCompartmentModelParameterizer::OneTissueCompartmentModelParameterizer() +{ +}; + +mitk::OneTissueCompartmentModelParameterizer::~OneTissueCompartmentModelParameterizer() +{ +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkStandardToftsModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkStandardToftsModel.cpp new file mode 100644 index 0000000000..b9df013da2 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkStandardToftsModel.cpp @@ -0,0 +1,175 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkStandardToftsModel.h" +#include "mitkConvolutionHelper.h" +#include +#include + +const std::string mitk::StandardToftsModel::MODEL_DISPLAY_NAME = "Standard Tofts Model"; + +const std::string mitk::StandardToftsModel::NAME_PARAMETER_Ktrans = "KTrans"; +const std::string mitk::StandardToftsModel::NAME_PARAMETER_ve = "ve"; + +const std::string mitk::StandardToftsModel::UNIT_PARAMETER_Ktrans = "ml/min/100ml"; +const std::string mitk::StandardToftsModel::UNIT_PARAMETER_ve = "ml/ml"; + +const unsigned int mitk::StandardToftsModel::POSITION_PARAMETER_Ktrans = 0; +const unsigned int mitk::StandardToftsModel::POSITION_PARAMETER_ve = 1; + +const unsigned int mitk::StandardToftsModel::NUMBER_OF_PARAMETERS = 2; + +std::string mitk::StandardToftsModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::StandardToftsModel::GetModelType() const +{ + return "Perfusion.MR"; +}; + +mitk::StandardToftsModel::StandardToftsModel() +{ + +} + +mitk::StandardToftsModel::~StandardToftsModel() +{ + +} + +mitk::StandardToftsModel::ParameterNamesType mitk::StandardToftsModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_Ktrans); + result.push_back(NAME_PARAMETER_ve); + + return result; +} + +mitk::StandardToftsModel::ParametersSizeType mitk::StandardToftsModel::GetNumberOfParameters() +const +{ + return NUMBER_OF_PARAMETERS; +} + +mitk::StandardToftsModel::ParamterUnitMapType mitk::StandardToftsModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_Ktrans, UNIT_PARAMETER_Ktrans)); + result.insert(std::make_pair(NAME_PARAMETER_ve, UNIT_PARAMETER_ve)); + + return result; +}; + +mitk::StandardToftsModel::ParameterNamesType +mitk::StandardToftsModel::GetDerivedParameterNames() const +{ + ParameterNamesType result; + result.push_back("kep"); + return result; +}; + +mitk::StandardToftsModel::ParametersSizeType +mitk::StandardToftsModel::GetNumberOfDerivedParameters() const +{ + return 1; +}; + +mitk::StandardToftsModel::ParamterUnitMapType mitk::StandardToftsModel::GetDerivedParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair("kep", "1/min")); + + return result; +}; + +mitk::StandardToftsModel::ModelResultType mitk::StandardToftsModel::ComputeModelfunction( + const ParametersType& parameters) const +{ + typedef itk::Array ResidueFunctionType; + + + if (this->m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + AterialInputFunctionType aterialInputFunction; + aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid); + + + + unsigned int timeSteps = this->m_TimeGrid.GetSize(); + + //Model Parameters + double ktrans = parameters[POSITION_PARAMETER_Ktrans] / 6000.0; + double ve = parameters[POSITION_PARAMETER_ve]; + + + double lambda = ktrans / ve; + + mitk::ModelBase::ModelResultType convolution = mitk::convoluteAIFWithExponential(this->m_TimeGrid, + aterialInputFunction, lambda); + + //Signal that will be returned by ComputeModelFunction + mitk::ModelBase::ModelResultType signal(timeSteps); + signal.fill(0.0); + + mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); + mitk::ModelBase::ModelResultType::const_iterator res = convolution.begin(); + + + for (AterialInputFunctionType::iterator Cp = aterialInputFunction.begin(); + Cp != aterialInputFunction.end(); ++res, ++signalPos, ++Cp) + { + *signalPos = ktrans * (*res); + } + + return signal; + +} + + +mitk::ModelBase::DerivedParameterMapType mitk::StandardToftsModel::ComputeDerivedParameters( + const mitk::ModelBase::ParametersType& parameters) const +{ + DerivedParameterMapType result; + double kep = parameters[POSITION_PARAMETER_Ktrans] / parameters[POSITION_PARAMETER_ve]; + result.insert(std::make_pair("kep", kep)); + return result; +}; + +itk::LightObject::Pointer mitk::StandardToftsModel::InternalClone() const +{ + StandardToftsModel::Pointer newClone = StandardToftsModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +}; + +void mitk::StandardToftsModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + +}; + diff --git a/Modules/Pharmacokinetics/src/Models/mitkStandardToftsModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkStandardToftsModelFactory.cpp new file mode 100644 index 0000000000..0eaf64f087 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkStandardToftsModelFactory.cpp @@ -0,0 +1,28 @@ +#include "mitkStandardToftsModelFactory.h" + +#include +#include +#include + +mitk::ConstraintCheckerBase::Pointer +mitk::StandardToftsModelFactory::CreateDefaultConstraints() const +{ + SimpleBarrierConstraintChecker::Pointer constraints = SimpleBarrierConstraintChecker::New(); + + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_ve, 0.0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_ve, 1.0); + + return constraints.GetPointer(); +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::StandardToftsModelFactory::GetDefaultInitialParameterization() const +{ + return StandardToftsModelParameterizer::New()->GetDefaultInitialParameterization(); +}; + +mitk::StandardToftsModelFactory::StandardToftsModelFactory() += default; + +mitk::StandardToftsModelFactory::~StandardToftsModelFactory() += default; diff --git a/Modules/Pharmacokinetics/src/Models/mitkStandardToftsModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkStandardToftsModelParameterizer.cpp new file mode 100644 index 0000000000..b4d54e0018 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkStandardToftsModelParameterizer.cpp @@ -0,0 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkStandardToftsModelParameterizer.h" + +mitk::StandardToftsModelParameterizer::ParametersType +mitk::StandardToftsModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(2); + initialParameters[mitk::StandardToftsModel::POSITION_PARAMETER_Ktrans] = 15; + initialParameters[mitk::StandardToftsModel::POSITION_PARAMETER_ve] = 0.5; + + return initialParameters; +}; + +mitk::StandardToftsModelParameterizer::StandardToftsModelParameterizer() +{ +}; + +mitk::StandardToftsModelParameterizer::~StandardToftsModelParameterizer() +{ +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModel.cpp new file mode 100644 index 0000000000..ff7d3af9f0 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModel.cpp @@ -0,0 +1,227 @@ +#include "mitkThreeStepLinearModel.h" + +const std::string mitk::ThreeStepLinearModel::MODEL_DISPLAY_NAME = "Three Step Linear Model"; + +const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_S0 = "Baseline"; +const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_t1 = "Time_point_1"; +const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_t2 = "Time_point_2"; +const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_a1 = "Slope_1"; +const std::string mitk::ThreeStepLinearModel::NAME_PARAMETER_a2 = "Slope_2"; + +// Assuming that Model is calculated on Signal intensities I +const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_S0 = "I"; +const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_t1 = "s"; +const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_t2 = "s"; +const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_a1 = "I/s"; +const std::string mitk::ThreeStepLinearModel::UNIT_PARAMETER_a2 = "I/s"; + +const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_S0 = 0; +const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_t1 = 1; +const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_t2 = 2; +const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_a1 = 3; +const unsigned int mitk::ThreeStepLinearModel::POSITION_PARAMETER_a2 = 4; + +const unsigned int mitk::ThreeStepLinearModel::NUMBER_OF_PARAMETERS = 5; + +std::string mitk::ThreeStepLinearModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::ThreeStepLinearModel::GetModelType() const +{ + return "Generic"; +}; + +mitk::ThreeStepLinearModel::FunctionStringType mitk::ThreeStepLinearModel::GetFunctionString() const +{ + return "Baseline if t= t1 && (*gridPos) <= t2) + { + *signalPos = a1*(*gridPos)+b1; + } + else + { + *signalPos = a2*(*gridPos)+b2; + } + } + + return signal; +}; + +mitk::ThreeStepLinearModel::ParameterNamesType mitk::ThreeStepLinearModel::GetStaticParameterNames() const +{ + ParameterNamesType result; + + return result; +} + +mitk::ThreeStepLinearModel::ParametersSizeType mitk::ThreeStepLinearModel::GetNumberOfStaticParameters() const +{ + return 0; +} + +void mitk::ThreeStepLinearModel::SetStaticParameter(const ParameterNameType& name, + const StaticParameterValuesType& values) +{ + //do nothing +}; + +mitk::ThreeStepLinearModel::StaticParameterValuesType mitk::ThreeStepLinearModel::GetStaticParameterValue( + const ParameterNameType& name) const +{ + StaticParameterValuesType result; + + //do nothing + + return result; +}; + +mitk::ModelBase::DerivedParameterMapType mitk::ThreeStepLinearModel::ComputeDerivedParameters( + const mitk::ModelBase::ParametersType& parameters) const +{ + double S0 = (double) parameters[POSITION_PARAMETER_S0]; + double tau = (double) parameters[POSITION_PARAMETER_t1] ; + double tmax = (double) parameters[POSITION_PARAMETER_t2] ; + double s1 = (double) parameters[POSITION_PARAMETER_a1] ; + double s2 = (double) parameters[POSITION_PARAMETER_a2] ; + + unsigned int timeSteps = m_TimeGrid.GetSize(); + + double Taq = 0; + Taq = m_TimeGrid.GetElement(timeSteps-1); + + double b1 = S0-s1*tau; + double Smax = s1*tmax+b1; + double b2 = Smax-s2*tmax; + double AUC = s1/2*(tmax*tmax-tau*tau) + +(b1-S0)*(tmax-tau) + +s2/2*(Taq*Taq-tmax*tmax) + +(b2-S0)*(Taq-tmax); + double Sfin = s2*Taq+b2; + + DerivedParameterMapType result; + + result.insert(std::make_pair("AUC", AUC)); + result.insert(std::make_pair("FinalTimePoint", Taq)); + result.insert(std::make_pair("FinalUptake", Sfin)); + result.insert(std::make_pair("Smax", Smax)); + result.insert(std::make_pair("y-intercept1", b1)); + result.insert(std::make_pair("y-intercept2", b2)); + + return result; +}; + +itk::LightObject::Pointer mitk::ThreeStepLinearModel::InternalClone() const +{ + ThreeStepLinearModel::Pointer newClone = ThreeStepLinearModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelFactory.cpp new file mode 100644 index 0000000000..e1b7bfdbc4 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelFactory.cpp @@ -0,0 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkThreeStepLinearModelFactory.h" +#include "mitkConcreteModelParameterizerBase.h" + +mitk::ThreeStepLinearModelFactory::ThreeStepLinearModelFactory() +{ +}; + +mitk::ThreeStepLinearModelFactory::~ThreeStepLinearModelFactory() +{ +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::ThreeStepLinearModelFactory::GetDefaultInitialParameterization() const +{ + return ThreeStepLinearModelParameterizer::New()->GetDefaultInitialParameterization(); +}; + +mitk::ModelParameterizerBase::Pointer mitk::ThreeStepLinearModelFactory::DoCreateParameterizer( + const modelFit::ModelFitInfo* fit) const +{ + return ConcreteModelParameterizerBase::New().GetPointer(); +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelParameterizer.cpp new file mode 100644 index 0000000000..0a90d90627 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkThreeStepLinearModelParameterizer.cpp @@ -0,0 +1,33 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkThreeStepLinearModelParameterizer.h" + +mitk::ThreeStepLinearModelParameterizer::ParametersType +mitk::ThreeStepLinearModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(5); + initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_S0] = 0.0; + initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_t1] = 50; + initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_t2] = 100; + initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_a1] = 1.0; + initialParameters[mitk:: ThreeStepLinearModel::POSITION_PARAMETER_a2] = -1.0; + + return initialParameters; +}; + + diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoCompartmentExchangeModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoCompartmentExchangeModel.cpp new file mode 100644 index 0000000000..eb56b6252d --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkTwoCompartmentExchangeModel.cpp @@ -0,0 +1,185 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTwoCompartmentExchangeModel.h" +#include "mitkConvolutionHelper.h" +#include + +const std::string mitk::TwoCompartmentExchangeModel::MODEL_DISPLAY_NAME = + "Two Compartment Exchange Model"; + +const std::string mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_F = "F"; +const std::string mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_PS = "PS"; +const std::string mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_ve = "ve"; +const std::string mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_vp = "vp"; + +const std::string mitk::TwoCompartmentExchangeModel::UNIT_PARAMETER_F = "ml/min/100ml"; +const std::string mitk::TwoCompartmentExchangeModel::UNIT_PARAMETER_PS = "ml/min/100ml"; +const std::string mitk::TwoCompartmentExchangeModel::UNIT_PARAMETER_ve = "ml/ml"; +const std::string mitk::TwoCompartmentExchangeModel::UNIT_PARAMETER_vp = "ml/ml"; + +const unsigned int mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_F = 0; +const unsigned int mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_PS = 1; +const unsigned int mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_ve = 2; +const unsigned int mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_vp = 3; + +const unsigned int mitk::TwoCompartmentExchangeModel::NUMBER_OF_PARAMETERS = 4; + + +inline double square(double a) +{ + return a * a; +} + +std::string mitk::TwoCompartmentExchangeModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::TwoCompartmentExchangeModel::GetModelType() const +{ + return "Perfusion.MR"; +}; + +mitk::TwoCompartmentExchangeModel::TwoCompartmentExchangeModel() +{ + +} + +mitk::TwoCompartmentExchangeModel::~TwoCompartmentExchangeModel() +{ + +} + +mitk::TwoCompartmentExchangeModel::ParameterNamesType +mitk::TwoCompartmentExchangeModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_F); + result.push_back(NAME_PARAMETER_PS); + result.push_back(NAME_PARAMETER_ve); + result.push_back(NAME_PARAMETER_vp); + + return result; +} + +mitk::TwoCompartmentExchangeModel::ParametersSizeType +mitk::TwoCompartmentExchangeModel::GetNumberOfParameters() const +{ + return NUMBER_OF_PARAMETERS; +} + +mitk::TwoCompartmentExchangeModel::ParamterUnitMapType +mitk::TwoCompartmentExchangeModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_F, UNIT_PARAMETER_F)); + result.insert(std::make_pair(NAME_PARAMETER_PS, UNIT_PARAMETER_PS)); + result.insert(std::make_pair(NAME_PARAMETER_vp, UNIT_PARAMETER_vp)); + result.insert(std::make_pair(NAME_PARAMETER_ve, UNIT_PARAMETER_ve)); + + return result; +}; + + +mitk::TwoCompartmentExchangeModel::ModelResultType +mitk::TwoCompartmentExchangeModel::ComputeModelfunction(const ParametersType& parameters) const +{ + typedef itk::Array ResidueFunctionType; + typedef mitk::ModelBase::ModelResultType ConvolutionResultType; + + if (this->m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + AterialInputFunctionType aterialInputFunction; + aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid); + + unsigned int timeSteps = this->m_TimeGrid.GetSize(); + mitk::ModelBase::ModelResultType signal(timeSteps); + signal.fill(0.0); + + //Model Parameters + double F = parameters[POSITION_PARAMETER_F] / 6000.0; + double PS = parameters[POSITION_PARAMETER_PS] / 6000.0; + double ve = parameters[POSITION_PARAMETER_ve]; + double vp = parameters[POSITION_PARAMETER_vp]; + + if(PS != 0) + { + double Tp = vp/(PS + F); + double Te = ve/PS; + double Tb = vp/F; + + double Kp = 0.5 *( 1/Tp + 1/Te + sqrt(( 1/Tp + 1/Te )*( 1/Tp + 1/Te ) - 4 * 1/Te*1/Tb) ); + double Km = 0.5 *( 1/Tp + 1/Te - sqrt(( 1/Tp + 1/Te )*( 1/Tp + 1/Te ) - 4 * 1/Te*1/Tb) ); + + double E = ( Kp - 1/Tb )/( Kp - Km ); + + + + ConvolutionResultType expp = mitk::convoluteAIFWithExponential(this->m_TimeGrid, aterialInputFunction,Kp); + ConvolutionResultType expm = mitk::convoluteAIFWithExponential(this->m_TimeGrid, aterialInputFunction,Km); + + //Signal that will be returned by ComputeModelFunction + + mitk::ModelBase::ModelResultType::const_iterator exppPos = expp.begin(); + mitk::ModelBase::ModelResultType::const_iterator expmPos = expm.begin(); + + for( mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); signalPos!=signal.end(); ++exppPos,++expmPos, ++signalPos) + { + *signalPos = F * ( *exppPos + E*(*expmPos - *exppPos) ); + } + } + + + else + { + double Kp = F/vp; + ConvolutionResultType exp = mitk::convoluteAIFWithExponential(this->m_TimeGrid, aterialInputFunction,Kp); + mitk::ModelBase::ModelResultType::const_iterator expPos = exp.begin(); + + for( mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); signalPos!=signal.end(); ++expPos, ++signalPos) + { + *signalPos = F * ( *expPos ); + } + + } + + return signal; +} + + +itk::LightObject::Pointer mitk::TwoCompartmentExchangeModel::InternalClone() const +{ + TwoCompartmentExchangeModel::Pointer newClone = TwoCompartmentExchangeModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +} + +void mitk::TwoCompartmentExchangeModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + +} + + diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoCompartmentExchangeModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoCompartmentExchangeModelFactory.cpp new file mode 100644 index 0000000000..dd4572ebec --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkTwoCompartmentExchangeModelFactory.cpp @@ -0,0 +1,29 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#include "mitkTwoCompartmentExchangeModelFactory.h" + +#include "mitkTwoCompartmentExchangeModelParameterizer.h" +#include "mitkAIFParametrizerHelper.h" + + +mitk::TwoCompartmentExchangeModelFactory::TwoCompartmentExchangeModelFactory() +{ +}; + +mitk::TwoCompartmentExchangeModelFactory::~TwoCompartmentExchangeModelFactory() +{ +}; + diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoCompartmentExchangeModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoCompartmentExchangeModelParameterizer.cpp new file mode 100644 index 0000000000..5841e78903 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkTwoCompartmentExchangeModelParameterizer.cpp @@ -0,0 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTwoCompartmentExchangeModelParameterizer.h" + +mitk::TwoCompartmentExchangeModelParameterizer::ParametersType +mitk::TwoCompartmentExchangeModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(4); + initialParameters[mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_PS] = 5.0; + initialParameters[mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_F] = 20.0; + initialParameters[mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_ve] = 0.1; + initialParameters[mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_vp] = 0.04; + + return initialParameters; +}; + +mitk::TwoCompartmentExchangeModelParameterizer::TwoCompartmentExchangeModelParameterizer() +{ +}; + +mitk::TwoCompartmentExchangeModelParameterizer::~TwoCompartmentExchangeModelParameterizer() +{ +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModel.cpp new file mode 100644 index 0000000000..550b3f17a7 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModel.cpp @@ -0,0 +1,162 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTwoTissueCompartmentFDGModel.h" +#include "mitkConvolutionHelper.h" +#include +const std::string mitk::TwoTissueCompartmentFDGModel::MODEL_DISPLAY_NAME = "Two Tissue Compartment Model for FDG (Sokoloff Model)"; + +const std::string mitk::TwoTissueCompartmentFDGModel::NAME_PARAMETER_K1 = "K1"; +const std::string mitk::TwoTissueCompartmentFDGModel::NAME_PARAMETER_k2 = "k2"; +const std::string mitk::TwoTissueCompartmentFDGModel::NAME_PARAMETER_k3 = "k3"; +const std::string mitk::TwoTissueCompartmentFDGModel::NAME_PARAMETER_VB = "V_B"; + +const std::string mitk::TwoTissueCompartmentFDGModel::UNIT_PARAMETER_K1 = "1/min"; +const std::string mitk::TwoTissueCompartmentFDGModel::UNIT_PARAMETER_k2 = "1/min"; +const std::string mitk::TwoTissueCompartmentFDGModel::UNIT_PARAMETER_k3 = "1/min"; +const std::string mitk::TwoTissueCompartmentFDGModel::UNIT_PARAMETER_VB = "ml/ml"; + +const unsigned int mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_K1 = 0; +const unsigned int mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_k2 = 1; +const unsigned int mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_k3 = 2; +const unsigned int mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_VB = 3; + +const unsigned int mitk::TwoTissueCompartmentFDGModel::NUMBER_OF_PARAMETERS = 4; + +std::string mitk::TwoTissueCompartmentFDGModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::TwoTissueCompartmentFDGModel::GetModelType() const +{ + return "Dynamic.PET"; +}; + +mitk::TwoTissueCompartmentFDGModel::TwoTissueCompartmentFDGModel() +{ + +} + +mitk::TwoTissueCompartmentFDGModel::~TwoTissueCompartmentFDGModel() +{ + +} + +mitk::TwoTissueCompartmentFDGModel::ParameterNamesType +mitk::TwoTissueCompartmentFDGModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_K1); + result.push_back(NAME_PARAMETER_k2); + result.push_back(NAME_PARAMETER_k3); + result.push_back(NAME_PARAMETER_VB); + + return result; +} + +mitk::TwoTissueCompartmentFDGModel::ParametersSizeType +mitk::TwoTissueCompartmentFDGModel::GetNumberOfParameters() const +{ + return NUMBER_OF_PARAMETERS; +} + +mitk::TwoTissueCompartmentFDGModel::ParamterUnitMapType +mitk::TwoTissueCompartmentFDGModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_K1, UNIT_PARAMETER_K1)); + result.insert(std::make_pair(NAME_PARAMETER_k2, UNIT_PARAMETER_k2)); + result.insert(std::make_pair(NAME_PARAMETER_k3, UNIT_PARAMETER_k3)); + result.insert(std::make_pair(NAME_PARAMETER_VB, UNIT_PARAMETER_VB)); + + return result; +}; + +mitk::TwoTissueCompartmentFDGModel::ModelResultType +mitk::TwoTissueCompartmentFDGModel::ComputeModelfunction(const ParametersType& parameters) const +{ + typedef itk::Array ResidueFunctionType; + + if (this->m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + AterialInputFunctionType aterialInputFunction; + aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid); + + + unsigned int timeSteps = this->m_TimeGrid.GetSize(); + + //Model Parameters + double k1 = (double)parameters[POSITION_PARAMETER_K1] / 60.0; + double k2 = (double)parameters[POSITION_PARAMETER_k2] / 60.0; + double k3 = (double)parameters[POSITION_PARAMETER_k3] / 60.0; + double VB = parameters[POSITION_PARAMETER_VB]; + + + + + double lambda = k2+k3; + //double lambda2 = -alpha2; + mitk::ModelBase::ModelResultType exp = mitk::convoluteAIFWithExponential(this->m_TimeGrid, + aterialInputFunction, lambda); + mitk::ModelBase::ModelResultType CA = mitk::convoluteAIFWithConstant(this->m_TimeGrid, aterialInputFunction, k3); + + + //Signal that will be returned by ComputeModelFunction + mitk::ModelBase::ModelResultType signal(timeSteps); + signal.fill(0.0); + + mitk::ModelBase::ModelResultType::const_iterator expPos = exp.begin(); + mitk::ModelBase::ModelResultType::const_iterator CAPos = CA.begin(); + AterialInputFunctionType::const_iterator aifPos = aterialInputFunction.begin(); + + for (mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); + signalPos != signal.end(); ++expPos, ++signalPos, ++aifPos) + { + double Ci = k1 * k2 /lambda *(*expPos) + k1*k3/lambda*(*CAPos); + *signalPos = VB * (*aifPos) + (1 - VB) * Ci; + } + + return signal; + +} + + + + +itk::LightObject::Pointer mitk::TwoTissueCompartmentFDGModel::InternalClone() const +{ + TwoTissueCompartmentFDGModel::Pointer newClone = TwoTissueCompartmentFDGModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +} + +void mitk::TwoTissueCompartmentFDGModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + +} + + + diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModelFactory.cpp new file mode 100644 index 0000000000..25469d559f --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModelFactory.cpp @@ -0,0 +1,38 @@ +#include "mitkTwoTissueCompartmentFDGModelFactory.h" + +#include +#include +#include + +mitk::ConstraintCheckerBase::Pointer +mitk::TwoTissueCompartmentFDGModelFactory::CreateDefaultConstraints() const +{ + SimpleBarrierConstraintChecker::Pointer constraints = SimpleBarrierConstraintChecker::New(); + + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_K1, 0.0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_k2, 0, 0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_k3, 0, 0); + constraints->SetLowerBarrier(ModelType::POSITION_PARAMETER_VB, 0, 0); + + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_K1, 1.0, 0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_k2, 1.0, 0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_k3, 1.0, 0); + constraints->SetUpperBarrier(ModelType::POSITION_PARAMETER_VB, 1, 0); + + + return constraints.GetPointer(); +}; + +mitk::ModelParameterizerBase::ParametersType +mitk::TwoTissueCompartmentFDGModelFactory::GetDefaultInitialParameterization() const +{ + return TwoTissueCompartmentFDGModelParameterizer::New()->GetDefaultInitialParameterization(); +}; + +mitk::TwoTissueCompartmentFDGModelFactory::TwoTissueCompartmentFDGModelFactory() +{ +}; + +mitk::TwoTissueCompartmentFDGModelFactory::~TwoTissueCompartmentFDGModelFactory() +{ +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModelParameterizer.cpp new file mode 100644 index 0000000000..982440c4aa --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentFDGModelParameterizer.cpp @@ -0,0 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTwoTissueCompartmentFDGModelParameterizer.h" + +mitk::TwoTissueCompartmentFDGModelParameterizer::ParametersType +mitk::TwoTissueCompartmentFDGModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(4); + initialParameters[mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_K1] = 0.5; + initialParameters[mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_k2] = 0.5; + initialParameters[mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_k3] = 0.5; + initialParameters[mitk::TwoTissueCompartmentFDGModel::POSITION_PARAMETER_VB] = 0.5; + + return initialParameters; +}; + +mitk::TwoTissueCompartmentFDGModelParameterizer::TwoTissueCompartmentFDGModelParameterizer() +{ +}; + +mitk::TwoTissueCompartmentFDGModelParameterizer::~TwoTissueCompartmentFDGModelParameterizer() +{ +}; diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModel.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModel.cpp new file mode 100644 index 0000000000..c314fac87c --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModel.cpp @@ -0,0 +1,178 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTwoTissueCompartmentModel.h" +#include "mitkConvolutionHelper.h" +#include +const std::string mitk::TwoTissueCompartmentModel::MODEL_DISPLAY_NAME = "Two Tissue Compartment Model"; + +const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_K1 = "K1"; +const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k2 = "k2"; +const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k3 = "k3"; +const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k4 = "k4"; +const std::string mitk::TwoTissueCompartmentModel::NAME_PARAMETER_VB = "V_B"; + +const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_K1 = "1/min"; +const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_k2 = "1/min"; +const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_k3 = "1/min"; +const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_k4 = "1/min"; +const std::string mitk::TwoTissueCompartmentModel::UNIT_PARAMETER_VB = "ml/ml"; + +const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_K1 = 0; +const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k2 = 1; +const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k3 = 2; +const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k4 = 3; +const unsigned int mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_VB = 4; + +const unsigned int mitk::TwoTissueCompartmentModel::NUMBER_OF_PARAMETERS = 5; + + +inline double square(double a) +{ + return a * a; +} + +std::string mitk::TwoTissueCompartmentModel::GetModelDisplayName() const +{ + return MODEL_DISPLAY_NAME; +}; + +std::string mitk::TwoTissueCompartmentModel::GetModelType() const +{ + return "Dynamic.PET"; +}; + +mitk::TwoTissueCompartmentModel::TwoTissueCompartmentModel() +{ + +} + +mitk::TwoTissueCompartmentModel::~TwoTissueCompartmentModel() +{ + +} + +mitk::TwoTissueCompartmentModel::ParameterNamesType +mitk::TwoTissueCompartmentModel::GetParameterNames() const +{ + ParameterNamesType result; + + result.push_back(NAME_PARAMETER_K1); + result.push_back(NAME_PARAMETER_k2); + result.push_back(NAME_PARAMETER_k3); + result.push_back(NAME_PARAMETER_k4); + result.push_back(NAME_PARAMETER_VB); + + return result; +} + +mitk::TwoTissueCompartmentModel::ParametersSizeType +mitk::TwoTissueCompartmentModel::GetNumberOfParameters() const +{ + return NUMBER_OF_PARAMETERS; +} + +mitk::TwoTissueCompartmentModel::ParamterUnitMapType +mitk::TwoTissueCompartmentModel::GetParameterUnits() const +{ + ParamterUnitMapType result; + + result.insert(std::make_pair(NAME_PARAMETER_K1, UNIT_PARAMETER_K1)); + result.insert(std::make_pair(NAME_PARAMETER_k2, UNIT_PARAMETER_k2)); + result.insert(std::make_pair(NAME_PARAMETER_k3, UNIT_PARAMETER_k3)); + result.insert(std::make_pair(NAME_PARAMETER_k4, UNIT_PARAMETER_k4)); + result.insert(std::make_pair(NAME_PARAMETER_VB, UNIT_PARAMETER_VB)); + + return result; +}; + +mitk::TwoTissueCompartmentModel::ModelResultType +mitk::TwoTissueCompartmentModel::ComputeModelfunction(const ParametersType& parameters) const +{ + typedef itk::Array ResidueFunctionType; + + if (this->m_TimeGrid.GetSize() == 0) + { + itkExceptionMacro("No Time Grid Set! Cannot Calculate Signal"); + } + + AterialInputFunctionType aterialInputFunction; + aterialInputFunction = GetAterialInputFunction(this->m_TimeGrid); + + + unsigned int timeSteps = this->m_TimeGrid.GetSize(); + + //Model Parameters + double k1 = (double)parameters[POSITION_PARAMETER_K1] / 60.0; + double k2 = (double)parameters[POSITION_PARAMETER_k2] / 60.0; + double k3 = (double)parameters[POSITION_PARAMETER_k3] / 60.0; + double k4 = (double)parameters[POSITION_PARAMETER_k4] / 60.0; + double VB = parameters[POSITION_PARAMETER_VB]; + + + + double alpha1 = 0.5 * ((k2 + k3 + k4) - sqrt(square(k2 + k3 + k4) - 4 * k2 * k4)); + double alpha2 = 0.5 * ((k2 + k3 + k4) + sqrt(square(k2 + k3 + k4) - 4 * k2 * k4)); + + //double lambda1 = -alpha1; + //double lambda2 = -alpha2; + mitk::ModelBase::ModelResultType exp1 = mitk::convoluteAIFWithExponential(this->m_TimeGrid, + aterialInputFunction, alpha1); + mitk::ModelBase::ModelResultType exp2 = mitk::convoluteAIFWithExponential(this->m_TimeGrid, + aterialInputFunction, alpha2); + + + //Signal that will be returned by ComputeModelFunction + mitk::ModelBase::ModelResultType signal(timeSteps); + signal.fill(0.0); + + mitk::ModelBase::ModelResultType::const_iterator exp1Pos = exp1.begin(); + mitk::ModelBase::ModelResultType::const_iterator exp2Pos = exp2.begin(); + AterialInputFunctionType::const_iterator aifPos = aterialInputFunction.begin(); + + for (mitk::ModelBase::ModelResultType::iterator signalPos = signal.begin(); + signalPos != signal.end(); ++exp1Pos, ++exp2Pos, ++signalPos, ++aifPos) + { + double Ci = k1 / (alpha2 - alpha1) * ((k4 - alpha1 + k3) * (*exp1Pos) + (alpha2 - k4 - k3) * + (*exp2Pos)); + *signalPos = VB * (*aifPos) + (1 - VB) * Ci; + } + + return signal; + +} + + + + +itk::LightObject::Pointer mitk::TwoTissueCompartmentModel::InternalClone() const +{ + TwoTissueCompartmentModel::Pointer newClone = TwoTissueCompartmentModel::New(); + + newClone->SetTimeGrid(this->m_TimeGrid); + + return newClone.GetPointer(); +} + +void mitk::TwoTissueCompartmentModel::PrintSelf(std::ostream& os, ::itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + +} + + + diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModelFactory.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModelFactory.cpp new file mode 100644 index 0000000000..2c5f08dc86 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModelFactory.cpp @@ -0,0 +1,28 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTwoTissueCompartmentModelFactory.h" + +#include "mitkTwoTissueCompartmentModelParameterizer.h" +#include "mitkAIFParametrizerHelper.h" + +mitk::TwoTissueCompartmentModelFactory::TwoTissueCompartmentModelFactory() +{ +}; + +mitk::TwoTissueCompartmentModelFactory::~TwoTissueCompartmentModelFactory() +{ +}; \ No newline at end of file diff --git a/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModelParameterizer.cpp b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModelParameterizer.cpp new file mode 100644 index 0000000000..a2a187e556 --- /dev/null +++ b/Modules/Pharmacokinetics/src/Models/mitkTwoTissueCompartmentModelParameterizer.cpp @@ -0,0 +1,39 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTwoTissueCompartmentModelParameterizer.h" + +mitk::TwoTissueCompartmentModelParameterizer::ParametersType +mitk::TwoTissueCompartmentModelParameterizer::GetDefaultInitialParameterization() const +{ + ParametersType initialParameters; + initialParameters.SetSize(5); + initialParameters[mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_K1] = 0.5; + initialParameters[mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k2] = 0.5; + initialParameters[mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k3] = 0.5; + initialParameters[mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k4] = 0.5; + initialParameters[mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_VB] = 0.5; + + return initialParameters; +}; + +mitk::TwoTissueCompartmentModelParameterizer::TwoTissueCompartmentModelParameterizer() +{ +}; + +mitk::TwoTissueCompartmentModelParameterizer::~TwoTissueCompartmentModelParameterizer() +{ +}; diff --git a/Modules/Pharmacokinetics/src/SimulationFramework/mitkImageGenerationHelper.cpp b/Modules/Pharmacokinetics/src/SimulationFramework/mitkImageGenerationHelper.cpp new file mode 100644 index 0000000000..fcd69410a9 --- /dev/null +++ b/Modules/Pharmacokinetics/src/SimulationFramework/mitkImageGenerationHelper.cpp @@ -0,0 +1,142 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkImageGenerationHelper.h" +#include "mitkArbitraryTimeGeometry.h" +#include "mitkImageCast.h" + + + typedef itk::Image FrameITKImageType; + typedef itk::Image DynamicITKImageType; + + + mitk::Image::Pointer mitk::ImageGenerationHelper::GenerateTestFrame(unsigned int timePointIndex) + { + FrameITKImageType::Pointer image = FrameITKImageType::New(); + + FrameITKImageType::IndexType start; + start[0] = 0; // first index on X + start[1] = 0; // first index on Y + start[2] = 0; // first index on Z + + FrameITKImageType::SizeType size; + size[0] = this->m_DimX; // size along X + size[1] = this->m_DimY; // size along Y + size[2] = this->m_DimZ; // size along Z + + FrameITKImageType::RegionType region; + region.SetSize( size ); + region.SetIndex( start ); + + image->SetRegions( region ); + image->Allocate(); + + itk::ImageRegionIterator it = itk::ImageRegionIterator(image,image->GetLargestPossibleRegion()); + + while (!it.IsAtEnd()) + { + it.Set(this->m_Curve[timePointIndex]); + ++it; + } + + mitk::Image::Pointer mitkImage = mitk::Image::New(); + mitkImage->InitializeByItk( image.GetPointer() ); + mitkImage->SetVolume( image->GetBufferPointer() ); + + return mitkImage; + } + + + + + mitk::Image::Pointer mitk::ImageGenerationHelper::GenerateDynamicImageMITK() + { + + unsigned int timeSteps = this->m_Grid.GetSize(); + + if(this->m_Curve.GetSize() != this->m_Grid.GetSize()) + { + itkExceptionMacro("Error. TimeGrid and ConcentrationCurve do not have same size. No Image Generation possible!"); + + } + if(this->m_DimX == 0 && this->m_DimY == 0 && this->m_DimZ == 0) + { + itkExceptionMacro("Error. No Dimensions for Image Set!"); + + } + if(this->m_Curve.GetSize() == 0 || this->m_Grid.GetSize() == 0) + { + itkExceptionMacro("Error. No Curve/Grid set!"); + + } + + mitk::Image::Pointer tempImage = GenerateTestFrame(0); + mitk::Image::Pointer dynamicImage = mitk::Image::New(); + + DynamicITKImageType::Pointer dynamicITKImage = DynamicITKImageType::New(); + DynamicITKImageType::RegionType dynamicITKRegion; + DynamicITKImageType::PointType dynamicITKOrigin; + DynamicITKImageType::IndexType dynamicITKIndex; + DynamicITKImageType::SpacingType dynamicITKSpacing; + + dynamicITKSpacing[0] = tempImage->GetGeometry()->GetSpacing()[0]; + dynamicITKSpacing[1] = tempImage->GetGeometry()->GetSpacing()[1]; + dynamicITKSpacing[2] = tempImage->GetGeometry()->GetSpacing()[2]; + dynamicITKSpacing[3] = 1.0; + + dynamicITKIndex[0] = 0; // The first pixel of the REGION + dynamicITKIndex[1] = 0; + dynamicITKIndex[2] = 0; + dynamicITKIndex[3] = 0; + + dynamicITKRegion.SetSize( 0,tempImage->GetDimension(0)); + dynamicITKRegion.SetSize( 1,tempImage->GetDimension(1)); + dynamicITKRegion.SetSize( 2,tempImage->GetDimension(2)); + dynamicITKRegion.SetSize( 3,timeSteps); + + dynamicITKRegion.SetIndex( dynamicITKIndex ); + + dynamicITKOrigin[0]=tempImage->GetGeometry()->GetOrigin()[0]; + dynamicITKOrigin[1]=tempImage->GetGeometry()->GetOrigin()[1]; + dynamicITKOrigin[2]=tempImage->GetGeometry()->GetOrigin()[2]; + + dynamicITKImage->SetOrigin(dynamicITKOrigin); + dynamicITKImage->SetSpacing(dynamicITKSpacing); + dynamicITKImage->SetRegions( dynamicITKRegion); + dynamicITKImage->Allocate(); + dynamicITKImage->FillBuffer(0); //not sure if this is necessary + + // Convert + mitk::CastToMitkImage(dynamicITKImage, dynamicImage); + + ArbitraryTimeGeometry::Pointer timeGeometry = ArbitraryTimeGeometry::New(); + timeGeometry->ClearAllGeometries(); + + + for (int i = 0; iSetVolume(frameImage->GetVolumeData()->GetData(),i); + + timeGeometry->AppendNewTimeStepClone(frameImage->GetGeometry(),this->m_Grid(i),this->m_Grid(i+1)); + } + + dynamicImage->SetTimeGeometry(timeGeometry); + + return dynamicImage; + } + + diff --git a/Modules/Pharmacokinetics/src/SimulationFramework/mitkPerfusionDataGenerator.cpp b/Modules/Pharmacokinetics/src/SimulationFramework/mitkPerfusionDataGenerator.cpp new file mode 100644 index 0000000000..31ebb2749e --- /dev/null +++ b/Modules/Pharmacokinetics/src/SimulationFramework/mitkPerfusionDataGenerator.cpp @@ -0,0 +1,252 @@ +#include "mitkPerfusionDataGenerator.h" +#include "itkMultiOutputNaryFunctorImageFilter.h" +#include "mitkArbitraryTimeGeometry.h" +#include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" +#include "mitkITKImageImport.h" + + +void mitk::PerfusionDataGenerator::SetParameterInputImage(const ParametersIndexType parameterIndex, ParameterImageType parameterImage) +{ + m_ParameterInputMap.insert(std::make_pair(parameterIndex,parameterImage)); + +} + +mitk::PerfusionDataGenerator::ResultImageType mitk::PerfusionDataGenerator::GetGeneratedImage() +{ + Generate(); + return m_ResultImage; +} + +template +void + mitk::PerfusionDataGenerator::DoPrepareMask(itk::Image* image) +{ + m_InternalMask = dynamic_cast(image); + + if (m_InternalMask.IsNull()) + { + MITK_INFO << "Parameter Fit Generator. Need to cast mask for parameter fit."; + typedef itk::Image InputImageType; + typedef itk::CastImageFilter< InputImageType, InternalMaskType > CastFilterType; + typename CastFilterType::Pointer spImageCaster = CastFilterType::New(); + + spImageCaster->SetInput(image); + + m_InternalMask = spImageCaster->GetOutput(); + spImageCaster->Update(); + } +} + +template +void mitk::PerfusionDataGenerator::DoGenerateData(itk::Image* image) +{ + typedef itk::Image InputFrameImageType; + typedef itk::Image OutputImageType; + + typedef itk::MultiOutputNaryFunctorImageFilter FilterType; + typename FilterType::Pointer filter; + + + for(unsigned int i=0; im_ParameterInputMap.size(); ++i) + { + typename InputFrameImageType::Pointer frameImage; + Image::Pointer parameterImage = m_InputParameterImages.at(i); + + mitk::CastToItkImage(parameterImage, frameImage); + filter->SetInput(i,frameImage); + + } + + SimpleFunctorPolicy functor; + functor.SetFunctor(this->m_Functor); + filter->SetFunctor(functor); + if (this->m_InternalMask.IsNotNull()) + { + filter->SetMask(this->m_InternalMask); + } + filter->Update(); + + + ArbitraryTimeGeometry::Pointer timeGeometry = ArbitraryTimeGeometry::New(); + timeGeometry->ClearAllGeometries(); + Image::Pointer dynamicImage= Image::New(); + + if(filter->GetNumberOfOutputs() != this->m_Functor->GetGrid().GetSize()) + { + itkExceptionMacro("Error. Number of computed output Images does not match Grid size!"); + } + + auto m_Grid = this->m_Functor->GetGrid(); + for (GridType::size_type i = 0; iGetOutput(i))->Clone(); + + dynamicImage->SetVolume(frameImage->GetVolumeData()->GetData(),i); + + auto currentTimePoint = m_Grid[i]; + auto nextTimePoint = m_Grid[i]; + if (i+1AppendNewTimeStepClone(frameImage->GetGeometry(), currentTimePoint, nextTimePoint); + } + + dynamicImage->SetTimeGeometry(timeGeometry); + + this->m_ResultImage = dynamicImage; +} + + + +void mitk::PerfusionDataGenerator::SortParameterImages() +{ + ParameterVectorType inputImages(this->m_ParameterInputMap.size()); + + unsigned int i = 0; + for (ParameterMapType::const_iterator pos = m_ParameterInputMap.begin(); pos != m_ParameterInputMap.end(); ++pos) + { + + i = pos->first; + inputImages[i] = pos->second; + } + + this->m_InputParameterImages = inputImages; + + +} + +void mitk::PerfusionDataGenerator::Generate() +{ + SortParameterImages(); + + if(this->m_Mask.IsNotNull()) + { + AccessFixedDimensionByItk(m_Mask, mitk::PerfusionDataGenerator::DoPrepareMask, 3); + } + else + { + this->m_InternalMask = NULL; + } + + /** @todo #1 This did not work! The Access-Routine would be a much nicer solution, but for some reasons, the handling did not work. + * Thats why the code for Generation the Data was pasted below + */ +// mitk::Image::Pointer firstParameterImage = this->m_InputParameterImages[0]; +// AccessFixedDimensionByItk(firstParameterImage, mitk::PerfusionDataGenerator::DoGenerateData, 3); + + + typedef itk::Image InputFrameImageType; + typedef itk::Image OutputImageType; + + typedef itk::MultiOutputNaryFunctorImageFilter FilterType; + /** @todo #3 The ParameterFitImageGenerator uses a typename instead of new. But this did not work somehow + */ + FilterType::Pointer filter = FilterType::New(); + + + for(unsigned int i=0; im_ParameterInputMap.size(); ++i) + { + /** @todo #3 The ParameterFitImageGenerator uses a typename instead of new. But this did not work somehow + */ + InputFrameImageType::Pointer frameImage = InputFrameImageType::New(); + Image::Pointer parameterImage = m_InputParameterImages.at(i); + + mitk::CastToItkImage(parameterImage, frameImage); + filter->SetInput(i,frameImage); + + } + + SimpleFunctorPolicy functor; + functor.SetFunctor(this->m_Functor); + filter->SetFunctor(functor); + if (this->m_InternalMask.IsNotNull()) + { + filter->SetMask(this->m_InternalMask); + } + filter->Update(); + + if (filter->GetNumberOfOutputs() != this->m_Functor->GetGrid().GetSize()) + { + itkExceptionMacro("Error. Number of computed output Images does not match Grid size!"); + } + + /** @todo #1 Better solution than all this code! + * This was copied from TestingHelper/TestArtifactGenerator. Just instantiating a mitk::Image and setting its Volumes + * in the for-loop did not work somehow. + * This was a work around + */ + + typedef itk::Image DynamicITKImageType; + + Image::Pointer dynamicImage= Image::New(); + mitk::Image::Pointer tempImage = mitk::ImportItkImage(filter->GetOutput(0))->Clone(); + + DynamicITKImageType::Pointer dynamicITKImage = DynamicITKImageType::New(); + DynamicITKImageType::RegionType dynamicITKRegion; + DynamicITKImageType::PointType dynamicITKOrigin; + DynamicITKImageType::IndexType dynamicITKIndex; + DynamicITKImageType::SpacingType dynamicITKSpacing; + + dynamicITKSpacing[0] = tempImage->GetGeometry()->GetSpacing()[0]; + dynamicITKSpacing[1] = tempImage->GetGeometry()->GetSpacing()[1]; + dynamicITKSpacing[2] = tempImage->GetGeometry()->GetSpacing()[2]; + dynamicITKSpacing[3] = 3.0; + + dynamicITKIndex[0] = 0; // The first pixel of the REGION + dynamicITKIndex[1] = 0; + dynamicITKIndex[2] = 0; + dynamicITKIndex[3] = 0; + + dynamicITKRegion.SetSize( 0,tempImage->GetDimension(0)); + dynamicITKRegion.SetSize( 1,tempImage->GetDimension(1)); + dynamicITKRegion.SetSize( 2,tempImage->GetDimension(2)); + dynamicITKRegion.SetSize(3, filter->GetNumberOfOutputs()); + + dynamicITKRegion.SetIndex( dynamicITKIndex ); + + dynamicITKOrigin[0]=tempImage->GetGeometry()->GetOrigin()[0]; + dynamicITKOrigin[1]=tempImage->GetGeometry()->GetOrigin()[1]; + dynamicITKOrigin[2]=tempImage->GetGeometry()->GetOrigin()[2]; + + dynamicITKImage->SetOrigin(dynamicITKOrigin); + dynamicITKImage->SetSpacing(dynamicITKSpacing); + dynamicITKImage->SetRegions( dynamicITKRegion); + dynamicITKImage->Allocate(); + dynamicITKImage->FillBuffer(0); //not sure if this is necessary + + // Convert + mitk::CastToMitkImage(dynamicITKImage, dynamicImage); + + + + ArbitraryTimeGeometry::Pointer timeGeometry = ArbitraryTimeGeometry::New(); + timeGeometry->ClearAllGeometries(); + + auto nrOfOutputs = filter->GetNumberOfOutputs(); + auto grid = this->m_Functor->GetGrid(); + for (unsigned int i = 0; iGetOutput(i))->Clone(); + + dynamicImage->SetVolume(frame->GetVolumeData()->GetData(),i); + + double tmax = 0; + if (i<(nrOfOutputs - 1)) + { + tmax = grid[i + 1] * 1000; + } + else + { + tmax = grid[i] * 1000; + } + timeGeometry->AppendNewTimeStepClone(frame->GetGeometry(), grid[i] * 1000, tmax); + } + + dynamicImage->SetTimeGeometry(timeGeometry); + + this->m_ResultImage = dynamicImage->Clone(); + +} diff --git a/Modules/Pharmacokinetics/test/CMakeLists.txt b/Modules/Pharmacokinetics/test/CMakeLists.txt new file mode 100644 index 0000000000..d45daf111d --- /dev/null +++ b/Modules/Pharmacokinetics/test/CMakeLists.txt @@ -0,0 +1 @@ +MITK_CREATE_MODULE_TESTS() \ No newline at end of file diff --git a/Modules/Pharmacokinetics/test/ConvertToConcentrationTest.cpp b/Modules/Pharmacokinetics/test/ConvertToConcentrationTest.cpp new file mode 100644 index 0000000000..3d82434113 --- /dev/null +++ b/Modules/Pharmacokinetics/test/ConvertToConcentrationTest.cpp @@ -0,0 +1,142 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include "mitkTestingMacros.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" + +#include "itkBinaryFunctorImageFilter.h" + +#include "mitkConvertToConcentrationFunctor.h" + + +int ConvertToConcentrationTest(int argc , char* argv[]) +{ + // always start with this! + MITK_TEST_BEGIN("ConvertToConcentration"); + + //Initialization Parameters + double RelaxationTime = 1.2; + double RecoveryTime = 0.125; + double Relaxivity = 4.3; + + + + //Test1: Functor calculation + mitk::ConvertToConcentrationFunctor testFunctor; + testFunctor.initialize(RelaxationTime, Relaxivity, RecoveryTime); + + + double s0 = 197.0; + double sCM = 278.0; + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0.009,testFunctor(sCM,s0), 1e-6, true)==true,"Check Functor Calculation with Input Value and baseline: 1"); + s0 = 157.0; + sCM = 207.0; + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0.0069,testFunctor(sCM,s0), 1e-6, true)==true,"Check Functor Calculation with Input Value and baseline: 2"); + s0 = 195.0; + sCM = 270.0; + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0.0084,testFunctor(sCM,s0), 1e-6, true)==true,"Check Functor Calculation with Input Value and baseline: 3"); + s0 = 177.0; + sCM = 308.0; + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(0.0164,testFunctor(sCM,s0), 1e-6, true)==true,"Check Functor Calculation with Input Value and baseline: 4"); + + //Test2: Filter usage with Functor + + typedef itk::Image ImageType; + typedef mitk::ConvertToConcentrationFunctor ConversionFunctorType; + typedef itk::BinaryFunctorImageFilter FilterType; + + //Definition of testimages + ImageType::Pointer image = ImageType::New(); + ImageType::Pointer BaselineImage = ImageType::New(); + ImageType::IndexType start; + start[0] = 0; // first index on X + start[1] = 0; // first index on Y + start[2] = 0; // first index on Z + ImageType::SizeType size; + size[0] = 2; // size along X + size[1] = 2; // size along Y + size[2] = 2; // size along Z + ImageType::RegionType region; + region.SetSize( size ); + region.SetIndex( start ); + image->SetRegions( region ); + image->Allocate(); + BaselineImage->SetRegions( region ); + BaselineImage->Allocate(); + itk::ImageRegionIterator it = itk::ImageRegionIterator(image,image->GetLargestPossibleRegion()); + itk::ImageRegionIterator Bit = itk::ImageRegionIterator(BaselineImage,BaselineImage->GetLargestPossibleRegion()); + int count = 0; + while (!it.IsAtEnd()&& !Bit.IsAtEnd()) + { + Bit.Set(150); + it.Set(count*50+150); + ++it; + ++Bit; + ++count; + } + //Filterinitialization + FilterType::Pointer ConversionFilter = FilterType::New(); + ConversionFilter->SetFunctor(testFunctor); + ConversionFilter->SetInput1(image); + ConversionFilter->SetInput2(BaselineImage); + + ConversionFilter->Update(); + ImageType::Pointer convertedImage = ImageType::New(); + convertedImage = ConversionFilter->GetOutput(); + + MITK_TEST_EQUAL(image->GetImageDimension(),convertedImage->GetImageDimension(),"Check dimensions of result image"); + + itk::Index<3> idx; + idx[0]=0; + idx[1]=0; + idx[2]=0; + MITK_TEST_EQUAL(0,convertedImage->GetPixel(idx),"Check pixel of converted image index <0,0,0>"); + idx[0]=1; + idx[1]=0; + idx[2]=0; + MITK_TEST_EQUAL(0.0072,convertedImage->GetPixel(idx),"Check pixel of converted image index <1,0,0>"); + idx[0]=0; + idx[1]=1; + idx[2]=0; + MITK_TEST_EQUAL(0.0147,convertedImage->GetPixel(idx),"Check pixel of converted image index <0,1,0>"); + idx[0]=1; + idx[1]=1; + idx[2]=0; + MITK_TEST_EQUAL(0.0225,convertedImage->GetPixel(idx),"Check pixel of converted image index <1,1,0>"); + idx[0]=0; + idx[1]=0; + idx[2]=1; + MITK_TEST_EQUAL(0.0307 ,convertedImage->GetPixel(idx),"Check pixel of converted image index <0,0,1>"); + idx[0]=1; + idx[1]=0; + idx[2]=1; + MITK_TEST_EQUAL(0.0392,convertedImage->GetPixel(idx),"Check pixel of converted image index <1,0,1>"); + idx[0]=0; + idx[1]=1; + idx[2]=1; + MITK_TEST_EQUAL(0.0480,convertedImage->GetPixel(idx),"Check pixel of converted image index <0,1,1>"); + idx[0]=1; + idx[1]=1; + idx[2]=1; + MITK_TEST_EQUAL(0.0574,convertedImage->GetPixel(idx),"Check pixel of converted image index <1,1,1>"); + + + + MITK_TEST_END() +} diff --git a/Modules/Pharmacokinetics/test/files.cmake b/Modules/Pharmacokinetics/test/files.cmake new file mode 100644 index 0000000000..713e14913f --- /dev/null +++ b/Modules/Pharmacokinetics/test/files.cmake @@ -0,0 +1,4 @@ +SET(MODULE_TESTS + mitkDescriptivePharmacokineticBrixModelTest.cpp + #ConvertToConcentrationTest.cpp +) diff --git a/Modules/Pharmacokinetics/test/mitkDescriptivePharmacokineticBrixModelTest.cpp b/Modules/Pharmacokinetics/test/mitkDescriptivePharmacokineticBrixModelTest.cpp new file mode 100644 index 0000000000..fede48176f --- /dev/null +++ b/Modules/Pharmacokinetics/test/mitkDescriptivePharmacokineticBrixModelTest.cpp @@ -0,0 +1,48 @@ +#include "mitkTestingMacros.h" +#include "mitkVector.h" + +#include "mitkDescriptivePharmacokineticBrixModel.h" + + + +int mitkDescriptivePharmacokineticBrixModelTest(int /*argc*/ , char*[] /*argv[]*/){ + + MITK_TEST_BEGIN("DescriptivePharmacokineticBrixModel") + + mitk::ModelBase::TimeGridType grid(22); + mitk::ModelBase::ModelResultType output; + mitk::ModelBase::ParametersType testparameters(4); + + testparameters[mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_A] = 1.25; + testparameters(mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kep) = 3.89; + testparameters(mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_kel) = 0.12; + testparameters(mitk::DescriptivePharmacokineticBrixModel::POSITION_PARAMETER_tlag) = 1.14; + + + + for (int i = 0; i<22; ++i) + { + // time grid in seconds, 14s between frames + grid[i]=(double) 14*i; + } + //injection time in minutes --> 60s + double injectiontime = 0.5; + mitk::DescriptivePharmacokineticBrixModel::Pointer testmodel = mitk::DescriptivePharmacokineticBrixModel::New(); + testmodel->SetTimeGrid(grid); + testmodel->SetTau(injectiontime); + + CPPUNIT_ASSERT_MESSAGE("Check number of parameters in Model.", 4 == testmodel->GetNumberOfParameters()); + output = testmodel->GetSignal(testparameters); + //precision of output ? + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(1,output[0], 1e-6, true)==true,"Check Output signal values - 0"); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(1,output[4], 1e-6, true)==true,"Check Output signal values - 4"); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(1.003338,output[5], 1e-6, true)==true,"Check Output signal values - 5"); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(1.238392,output[6], 1e-6, true)==true,"Check Output signal values - 6"); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(1.669835,output[7], 1e-6, true)==true,"Check Output signal values - 7"); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(1.982948,output[8], 1e-6, true)==true,"Check Output signal values - 8"); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(2.089685,output[9], 1e-6, true)==true,"Check Output signal values - 9"); + MITK_TEST_CONDITION_REQUIRED(mitk::Equal(2.113611,output[10], 1e-6, true)==true,"Check Output signal values - 10"); + + MITK_TEST_END() + +} diff --git a/Modules/PharmacokineticsUI/CMakeLists.txt b/Modules/PharmacokineticsUI/CMakeLists.txt new file mode 100644 index 0000000000..a407d55023 --- /dev/null +++ b/Modules/PharmacokineticsUI/CMakeLists.txt @@ -0,0 +1,6 @@ +MITK_CREATE_MODULE(PharmacokineticsUI + INCLUDE_DIRS Common Qmitk + DEPENDS MitkPharmacokinetics MitkQtWidgets MitkQtWidgetsExt + PACKAGE_DEPENDS Qt5|Core CTK|CTKWidgets Boost +WARNINGS_NO_ERRORS +) diff --git a/Modules/PharmacokineticsUI/Qmitk/QmitkDescriptionParameterBackgroundJob.cpp b/Modules/PharmacokineticsUI/Qmitk/QmitkDescriptionParameterBackgroundJob.cpp new file mode 100644 index 0000000000..0040e4d63a --- /dev/null +++ b/Modules/PharmacokineticsUI/Qmitk/QmitkDescriptionParameterBackgroundJob.cpp @@ -0,0 +1,129 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Software Development for +Integrated Diagnostic and Therapy. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#include "QmitkDescriptionParameterBackgroundJob.h" +#include "mitkModelFitInfo.h" + +void DescriptionParameterBackgroundJob::OnComputeEvent(::itk::Object* caller, + const itk::EventObject& event) +{ + itk::ProgressEvent progressEvent; + itk::InitializeEvent initEvent; + itk::StartEvent startEvent; + itk::EndEvent endEvent; + + if (progressEvent.CheckEvent(&event)) + { + mitk::DescriptionParameterImageGeneratorBase* castedReporter = + dynamic_cast(caller); + emit JobProgress(castedReporter->GetProgress()); + } + else if (initEvent.CheckEvent(&event)) + { + emit JobStatusChanged(QString("Initializing description parameter generator")); + } + else if (startEvent.CheckEvent(&event)) + { + emit JobStatusChanged(QString("Started parameter computation process.")); + } + else if (endEvent.CheckEvent(&event)) + { + emit JobStatusChanged(QString("Finished parameter computation process.")); + } +} + +DescriptionParameterBackgroundJob:: +DescriptionParameterBackgroundJob(mitk::DescriptionParameterImageGeneratorBase* generator, + mitk::DataNode* parentNode) +{ + if (!generator) + { + mitkThrow() << "Cannot create description parameter background job. Passed fit generator is NULL."; + } + + m_Generator = generator; + m_ParentNode = parentNode; + + m_spCommand = ::itk::MemberCommand::New(); + m_spCommand->SetCallbackFunction(this, &DescriptionParameterBackgroundJob::OnComputeEvent); + m_ObserverID = m_Generator->AddObserver(::itk::AnyEvent(), m_spCommand); +}; + +mitk::DataNode* +DescriptionParameterBackgroundJob:: +GetParentNode() const +{ + return m_ParentNode; +}; + +DescriptionParameterBackgroundJob:: +~DescriptionParameterBackgroundJob() +{ + m_Generator->RemoveObserver(m_ObserverID); +}; + +mitk::modelFit::ModelFitResultNodeVectorType DescriptionParameterBackgroundJob::CreateResultNodes( + const mitk::DescriptionParameterImageGeneratorBase::ParameterImageMapType& paramimages) +{ + mitk::modelFit::ModelFitResultNodeVectorType results; + + for (auto image : paramimages) + { + if (image.second.IsNull()) + { + mitkThrow() << "Cannot generate result node. Passed parameterImage is null. parameter name: " << + image.first; + } + + mitk::DataNode::Pointer result = mitk::DataNode::New(); + result->SetData(image.second); + result->SetName(image.first); + result->SetVisibility(true); + results.push_back(result); + } + + return results; +}; + +void +DescriptionParameterBackgroundJob:: +run() +{ + try + { + emit JobStatusChanged(QString("Started session...")); + + m_Generator->Generate(); + + emit JobStatusChanged(QString("Generate result nodes.")); + + m_Results = CreateResultNodes(m_Generator->GetParameterImages()); + + emit ResultsAreAvailable(m_Results, this); + } + catch (::std::exception& e) + { + emit Error(QString("Error while processing data. Details: ") + QString::fromLatin1(e.what())); + } + catch (...) + { + emit Error(QString("Unkown error when processing the data.")); + } + + emit Finished(); +}; diff --git a/Modules/PharmacokineticsUI/Qmitk/QmitkDescriptionParameterBackgroundJob.h b/Modules/PharmacokineticsUI/Qmitk/QmitkDescriptionParameterBackgroundJob.h new file mode 100644 index 0000000000..a543fbc242 --- /dev/null +++ b/Modules/PharmacokineticsUI/Qmitk/QmitkDescriptionParameterBackgroundJob.h @@ -0,0 +1,79 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Software Development for +Integrated Diagnostic and Therapy. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef __QMITK_DESCRIPTION_PARAMETER_BACKGROUND_JOB_H +#define __QMITK_DESCRIPTION_PARAMETER_BACKGROUND_JOB_H + + +//QT +#include +#include + +//MITK +#include + +#include +#include +#include + +// ITK +#include + +#include "MitkPharmacokineticsUIExports.h" + +class MITKPHARMACOKINETICSUI_EXPORT DescriptionParameterBackgroundJob : public QObject, public QRunnable +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + +public: + DescriptionParameterBackgroundJob(mitk::DescriptionParameterImageGeneratorBase* generator, mitk::DataNode* parentNode = NULL); + ~DescriptionParameterBackgroundJob(); + + void run(); + + /**Returns the node (if defined), that is the parent object for the results of the job. + May be null.*/ + mitk::DataNode* GetParentNode() const; + +signals: + void Finished(); + void Error(QString err); + void ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType resultMap, const DescriptionParameterBackgroundJob* pJob); + void JobProgress(double progress); + void JobStatusChanged(QString info); + +protected: + static mitk::modelFit::ModelFitResultNodeVectorType CreateResultNodes(const mitk::DescriptionParameterImageGeneratorBase::ParameterImageMapType& paramimages); + + //Inputs + mitk::DescriptionParameterImageGeneratorBase::Pointer m_Generator; + mitk::DataNode::Pointer m_ParentNode; + + // Results + mitk::modelFit::ModelFitResultNodeVectorType m_Results; + + ::itk::MemberCommand::Pointer m_spCommand; + unsigned long m_ObserverID; + + void OnComputeEvent(::itk::Object *, const itk::EventObject &event); +}; + +#endif + diff --git a/Modules/PharmacokineticsUI/files.cmake b/Modules/PharmacokineticsUI/files.cmake new file mode 100644 index 0000000000..afb8e68b31 --- /dev/null +++ b/Modules/PharmacokineticsUI/files.cmake @@ -0,0 +1,16 @@ +set(CPP_FILES + Qmitk/QmitkDescriptionParameterBackgroundJob.cpp +) + +set(H_FILES +) + +set(TPP_FILES +) + +set(UI_FILES +) + +set(MOC_H_FILES + Qmitk/QmitkDescriptionParameterBackgroundJob.h +) diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index ecfb25c700..c529e1d9df 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,103 +1,111 @@ # Plug-ins must be ordered according to their dependencies set(MITK_PLUGINS org.blueberry.core.runtime:ON org.blueberry.core.expressions:OFF org.blueberry.core.commands:OFF org.blueberry.core.jobs:OFF org.blueberry.ui.qt:OFF org.blueberry.ui.qt.help:ON org.blueberry.ui.qt.log:ON org.blueberry.ui.qt.objectinspector:OFF #org.blueberry.test:ON #org.blueberry.uitest:ON #Testing/org.blueberry.core.runtime.tests:ON #Testing/org.blueberry.osgi.tests:ON org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.datastorageviewertest:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.dicominspector:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.diffusionimaging.connectomics:OFF org.mitk.gui.qt.diffusionimaging.denoising:OFF org.mitk.gui.qt.diffusionimaging.fiberfox:OFF org.mitk.gui.qt.diffusionimaging.fiberprocessing:OFF org.mitk.gui.qt.diffusionimaging.ivim:OFF org.mitk.gui.qt.diffusionimaging.odfpeaks:OFF org.mitk.gui.qt.diffusionimaging.partialvolume:OFF org.mitk.gui.qt.diffusionimaging.preprocessing:OFF org.mitk.gui.qt.diffusionimaging.reconstruction:OFF org.mitk.gui.qt.diffusionimaging.registration:OFF org.mitk.gui.qt.diffusionimaging.tbss:OFF org.mitk.gui.qt.diffusionimaging.tractography:OFF org.mitk.gui.qt.diffusionimaging.python:OFF org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.lasercontrol:OFF org.mitk.gui.qt.openigtlink:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.renderwindowmanager:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.photoacoustics.pausviewer:OFF org.mitk.gui.qt.photoacoustics.imageprocessing:OFF org.mitk.gui.qt.photoacoustics.simulation:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF org.mitk.gui.qt.igt.app.echotrack:OFF org.mitk.gui.qt.spectrocamrecorder:OFF org.mitk.gui.qt.classificationsegmentation:OFF org.mitk.gui.qt.overlaymanager:OFF org.mitk.gui.qt.igt.app.hummelprotocolmeasurements:OFF org.mitk.gui.qt.multilabelsegmentation:OFF org.mitk.matchpoint.core.helper:OFF org.mitk.gui.qt.matchpoint.algorithm.browser:OFF org.mitk.gui.qt.matchpoint.algorithm.control:OFF org.mitk.gui.qt.matchpoint.algorithm.batch:OFF org.mitk.gui.qt.matchpoint.mapper:OFF org.mitk.gui.qt.matchpoint.framereg:OFF org.mitk.gui.qt.matchpoint.visualizer:OFF org.mitk.gui.qt.matchpoint.evaluator:OFF org.mitk.gui.qt.matchpoint.manipulator:OFF org.mitk.gui.qt.preprocessing.resampling:OFF org.mitk.gui.qt.cest:OFF + org.mitk.gui.qt.fit.demo:OFF + org.mitk.gui.qt.fit.inspector:OFF + org.mitk.gui.qt.fit.genericfitting:OFF + org.mitk.gui.qt.pharmacokinetics.mri:OFF + org.mitk.gui.qt.pharmacokinetics.pet:OFF + org.mitk.gui.qt.pharmacokinetics.simulation:OFF + org.mitk.gui.qt.pharmacokinetics.curvedescriptor:OFF + org.mitk.gui.qt.pharmacokinetics.concentration.mri:OFF ) diff --git a/Plugins/org.mitk.gui.qt.fit.demo/CMakeLists.txt b/Plugins/org.mitk.gui.qt.fit.demo/CMakeLists.txt new file mode 100644 index 0000000000..c4a48e7ffc --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/CMakeLists.txt @@ -0,0 +1,7 @@ +project(org_mitk_gui_qt_fit_demo) + +mitk_create_plugin( + EXPORT_DIRECTIVE FitGeneratorDemo_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkModelFit MitkModelFitUI +) diff --git a/Plugins/org.mitk.gui.qt.fit.demo/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.fit.demo/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..e6ce7d7afa --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/documentation/UserManual/Manual.dox @@ -0,0 +1,9 @@ +/** +\page org_mitk_gui_qt_fit_demo The Fit Demo View + +\li \ref FDEMO_Introduction + +\section FDEMO_Introduction Introduction +This is a very simple view that demonstrates how a fit generator can be implemented using the module ModelFit. +In addition the view can be used to generate a demo fit to explore other components like the fit explorer. +*/ \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.fit.demo/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.fit.demo/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..497d73b1ef --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_fit_demo org.mitk.gui.qt.fit.demo + \ingroup MITKPlugins + + \brief Plugin to demonstrate the fitting module ModelFit and a simple fit generator. + +*/ + +/** + \defgroup org_mitk_gui_qt_fit_demo_internal Internal + \ingroup org_mitk_gui_qt_fit_demo + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.fit.demo plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.fit.demo/files.cmake b/Plugins/org.mitk.gui.qt.fit.demo/files.cmake new file mode 100644 index 0000000000..978d11fb67 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/files.cmake @@ -0,0 +1,42 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_FitGeneratorDemo_Activator.cpp + FitGeneratorDemoView.cpp +) + +set(UI_FILES + src/internal/FitGeneratorDemoView.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_FitGeneratorDemo_Activator.h + src/internal/FitGeneratorDemoView.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/demo.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.fit.demo/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.fit.demo/manifest_headers.cmake new file mode 100644 index 0000000000..03480fff78 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Fit Generator Demo") +set(Plugin-Version "1.0") +set(Plugin-Vendor "DKFZ, Software Development For Integrated Diagnostics and Therapy") +set(Plugin-ContactAddress "r.floca@dkfz.de") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.fit.demo/plugin.xml b/Plugins/org.mitk.gui.qt.fit.demo/plugin.xml new file mode 100644 index 0000000000..671cc92071 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.fit.demo/resources/demo.png b/Plugins/org.mitk.gui.qt.fit.demo/resources/demo.png new file mode 100644 index 0000000000..245959d54e Binary files /dev/null and b/Plugins/org.mitk.gui.qt.fit.demo/resources/demo.png differ diff --git a/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.cpp b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.cpp new file mode 100644 index 0000000000..5bab2c3967 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.cpp @@ -0,0 +1,259 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "FitGeneratorDemoView.h" +#include +#include + +#include +#include + +#include "mitkWorkbenchUtil.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +const std::string FitGeneratorDemoView::VIEW_ID = "org.mitk.gui.qt.fit.demo"; + +typedef itk::Image FrameITKImageType; +typedef itk::Image DynamicITKImageType; + +void FitGeneratorDemoView::SetFocus() +{ + m_Controls.btnModelling->setFocus(); +} + +void FitGeneratorDemoView::CreateQtPartControl(QWidget* parent) +{ + m_Controls.setupUi(parent); + m_Controls.btnModelling->setEnabled(false); + + connect(m_Controls.btnModelling, SIGNAL(clicked()), this, SLOT(OnModellingButtonClicked())); + connect(m_Controls.btnGenerateTestData, SIGNAL(clicked()), this, + SLOT(OnGenerateTestDataButtonClicked())); + + m_Controls.leFitName->setText(tr("demo")); +} + +void FitGeneratorDemoView::OnModellingButtonClicked() +{ + Generate(); +} + +void FitGeneratorDemoView::OnGenerateTestDataButtonClicked() +{ + mitk::Image::Pointer testImage = mitk::GenerateDynamicTestImageMITK(); + + mitk::DataNode::Pointer testNode = mitk::DataNode::New(); + + testNode->SetData(testImage); + testNode->SetName("LinearModel_4DTestImage"); + + this->GetDataStorage()->Add(testNode); +} + +void FitGeneratorDemoView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, + const QList& /*nodes*/) +{ + + QList dataNodes = this->GetDataManagerSelection(); + + m_selectedNode = NULL; + m_selectedImage = NULL; + m_selectedMaskNode = NULL; + m_selectedMask = NULL; + + if (!dataNodes.empty()) + { + m_selectedNode = dataNodes[0]; + mitk::Image* selectedImage = dynamic_cast(m_selectedNode->GetData()); + + if (selectedImage && selectedImage->GetDimension(3) > 1) + { + m_selectedImage = selectedImage; + } + + if (dataNodes.size() > 1) + { + m_selectedMaskNode = dataNodes[1]; + + mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage"); + mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image"); + mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); + mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary); + + mitk::NodePredicateOr::Pointer maskPredicate = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet); + + mitk::Image* selectedMask = dynamic_cast(this->m_selectedMaskNode->GetData()); + + if (selectedMask && maskPredicate->CheckNode(m_selectedMaskNode)) + { + m_selectedMask = selectedMask; + + if (this->m_selectedMask->GetTimeSteps() > 1) + { + MITK_INFO << + "Selected mask has multiple timesteps. Only use first timestep to mask model fit. Mask name: " << + m_selectedMaskNode->GetName() ; + mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); + maskedImageTimeSelector->SetInput(this->m_selectedMask); + maskedImageTimeSelector->SetTimeNr(0); + maskedImageTimeSelector->UpdateLargestPossibleRegion(); + this->m_selectedMask = maskedImageTimeSelector->GetOutput(); + } + } + + } + } + + if (m_selectedImage) + { + m_Controls.lTimeseries->setText((m_selectedNode->GetName()).c_str()); + } + else + { + if (m_selectedNode.IsNull()) + { + m_Controls.lTimeseries->setText("None"); + } + else + { + m_Controls.lTimeseries->setText("Error. Selected node #1 is no 4D image!"); + } + } + + if (m_selectedMask) + { + m_Controls.lMask->setText((m_selectedMaskNode->GetName()).c_str()); + } + else + { + if (m_selectedMaskNode.IsNull()) + { + m_Controls.lMask->setText("None"); + } + else + { + m_Controls.lMask->setText("Error. Selected node #2 is no mask!"); + } + } + + m_Controls.btnModelling->setEnabled(m_selectedImage.IsNotNull()); +} + +void FitGeneratorDemoView::Generate() +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + //Model configuration (static parameters) can be done now + + //Specify fitting strategy and evaluation parameters + mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor = + mitk::LevenbergMarquardtModelFitFunctor::New(); + mitk::SumOfSquaredDifferencesFitCostFunction::Pointer evaluation = + mitk::SumOfSquaredDifferencesFitCostFunction::New(); + + fitFunctor->RegisterEvaluationParameter("sum_diff^2", evaluation); + + //Parametrize fit generator + mitk::LinearModelParameterizer::Pointer parameterizer = mitk::LinearModelParameterizer::New(); + fitGenerator->SetModelParameterizer(parameterizer); + fitGenerator->SetDynamicImage(m_selectedImage); + fitGenerator->SetFitFunctor(fitFunctor); + + if (m_selectedMask.IsNotNull()) + { + fitGenerator->SetMask(m_selectedMask); + } + + mitk::modelFit::ModelFitInfo::Pointer fitSession = + mitk::modelFit::CreateFitInfoFromModelParameterizer(parameterizer, m_selectedNode->GetData(), + mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED()); + + ///////////////////////// + //create job and put it into the thread pool + ParameterFitBackgroundJob* pJob = new ParameterFitBackgroundJob(fitGenerator, fitSession, + m_Controls.leFitName->text().toStdString(), m_selectedNode); + pJob->setAutoDelete(true); + + connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnJobError(QString))); + connect(pJob, SIGNAL(Finished()), this, SLOT(OnJobFinished())); + connect(pJob, SIGNAL(ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const ParameterFitBackgroundJob*)), this, + SLOT(OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const ParameterFitBackgroundJob*)), Qt::BlockingQueuedConnection); + + connect(pJob, SIGNAL(JobProgress(double)), this, SLOT(OnJobProgress(double))); + connect(pJob, SIGNAL(JobStatusChanged(QString)), this, SLOT(OnJobStatusChanged(QString))); + + QThreadPool* threadPool = QThreadPool::globalInstance(); + threadPool->start(pJob); +} + +FitGeneratorDemoView::FitGeneratorDemoView() +{ + m_selectedImage = NULL; + m_selectedNode = NULL; + +} + +void FitGeneratorDemoView::OnJobFinished() +{ + this->m_Controls.textEdit->append(QString("Fitting finished")); +}; + +void FitGeneratorDemoView::OnJobError(QString err) +{ + MITK_ERROR << err.toStdString().c_str(); + + m_Controls.textEdit->append(QString("") + err + QString("")); + +}; + +void FitGeneratorDemoView::OnJobResultsAreAvailable( + mitk::modelFit::ModelFitResultNodeVectorType results, const ParameterFitBackgroundJob* pJob) +{ + //Store the resulting parameter fit image via convenience helper function in data storage + //(handles the correct generation of the nodes and their properties) + mitk::modelFit::StoreResultsInDataStorage(this->GetDataStorage(), results, pJob->GetParentNode()); +}; + +void FitGeneratorDemoView::OnJobProgress(double progress) +{ + QString report = QString("Progress. ") + QString::number(progress); + this->m_Controls.textEdit->append(report); +}; + +void FitGeneratorDemoView::OnJobStatusChanged(QString info) +{ + this->m_Controls.textEdit->append(info); +} diff --git a/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.h b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.h new file mode 100644 index 0000000000..bd18351721 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.h @@ -0,0 +1,93 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef FitGeneratorDemoView_h +#define FitGeneratorDemoView_h + +#include + +#include + +#include + +#include "ui_FitGeneratorDemoView.h" +#include +#include +#include +#include + +/*! +* @brief Test Plugin for generation of model parameter images +*/ +class FitGeneratorDemoView : public QmitkAbstractView +{ + Q_OBJECT + +public: + + /*! @brief The view's unique ID - required by MITK */ + static const std::string VIEW_ID; + + FitGeneratorDemoView(); + + protected slots: + + void OnModellingButtonClicked(); + void OnGenerateTestDataButtonClicked(); + void OnJobFinished(); + void OnJobError(QString err); + void OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType results, const ParameterFitBackgroundJob* pJob); + void OnJobProgress(double progress); + void OnJobStatusChanged(QString info); + +protected: + + // Overridden base class functions + + /*! + * @brief Sets up the UI controls and connects the slots and signals. Gets + * called by the framework to create the GUI at the right time. + * @param[in,out] parent The parent QWidget, as this class itself is not a QWidget + * subclass. + */ + void CreateQtPartControl(QWidget* parent); + + /*! + * @brief Sets the focus to the plot curve button. Gets called by the framework to set the + * focus on the right widget. + */ + void SetFocus(); + + void Generate(); + + /*! \brief called by QmitkFunctionality when DataManager's selection has changed + */ + virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, + const QList& nodes); + + Ui::FitGeneratorDemoViewControls m_Controls; + + mitk::DataNode::Pointer m_selectedNode; + mitk::Image::Pointer m_selectedImage; + + mitk::DataNode::Pointer m_selectedMaskNode; + mitk::Image::Pointer m_selectedMask; + + mitk::ModelFactoryBase::Pointer m_ModelFactory; + +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.ui b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.ui new file mode 100644 index 0000000000..56d8afc77f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/FitGeneratorDemoView.ui @@ -0,0 +1,101 @@ + + + FitGeneratorDemoViewControls + + + + 0 + 0 + 349 + 671 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + <html><head/><body><p><span style=" font-weight:600;">Simple demo for a parameter map generator</span><br/>Computes the fit of a linear model (model parameters are slope and offset).</p><p>Demo steps:</p><p>[0. Press &quot;Generate test data&quot;, if you dont want to try your own]<br/>1. Choose the data node that should be used as input. (If you want to select a mask, press &quot;CTRL&quot; and select the mask node.)<br/>2. Press &quot;Start Modelling&quot;<br/>3. Wait and see...<br/>4. The output nodes &quot;slope&quot; and &quot;offset&quot; can be found as child nodes for the chosen input.</p></body></html> + + + true + + + + + + + + + Selected Time Series: + + + + + + + None + + + + + + + Mask (optional): + + + + + + + None + + + + + + + + + Generate test data + + + + + + + + + Fit name: + + + + + + + + + + + + Start Modelling + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.fit.demo/src/internal/org_mitk_FitGeneratorDemo_Activator.cpp b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/org_mitk_FitGeneratorDemo_Activator.cpp new file mode 100644 index 0000000000..6f17ef86ed --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/org_mitk_FitGeneratorDemo_Activator.cpp @@ -0,0 +1,29 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "org_mitk_FitGeneratorDemo_Activator.h" + +#include "FitGeneratorDemoView.h" + + void org_mitk_gui_qt_fit_demo_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(FitGeneratorDemoView, context); + } + + void org_mitk_gui_qt_fit_demo_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context); + } diff --git a/Plugins/org.mitk.gui.qt.fit.demo/src/internal/org_mitk_FitGeneratorDemo_Activator.h b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/org_mitk_FitGeneratorDemo_Activator.h new file mode 100644 index 0000000000..1185560c0f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.demo/src/internal/org_mitk_FitGeneratorDemo_Activator.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef org_mitk_gui_qt_fit_demo_Activator_h +#define org_mitk_gui_qt_fit_demo_Activator_h + +#include + + class org_mitk_gui_qt_fit_demo_Activator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_fit_demo") + Q_INTERFACES(ctkPluginActivator) + + public: + + /*! + * @brief Registers the plug-in. Gets called by the framework when the plug-in is + * first loaded. + * @param context The corresponding CTK plug-in context in which the plug-in is loaded. + */ + void start(ctkPluginContext* context); + + /*! + * @brief Deregisters the plug-in. Gets called by the framework when the plug-in + * is unloaded. + * @param context The corresponding CTK plug-in context in which the plug-in was loaded. + */ + void stop(ctkPluginContext* context); + }; + +#endif diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/CMakeLists.txt b/Plugins/org.mitk.gui.qt.fit.genericfitting/CMakeLists.txt new file mode 100644 index 0000000000..5727a1f439 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/CMakeLists.txt @@ -0,0 +1,9 @@ +project(org_mitk_gui_qt_fit_genericfitting) + +mitk_create_plugin( + EXPORT_DIRECTIVE MRPERFUSION_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkModelFit MitkModelFitUI + PACKAGE_DEPENDS + PRIVATE Boost +) diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..f4022f946f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/UserManual/Manual.dox @@ -0,0 +1,8 @@ +/** +\page org_mitk_gui_qt_fit_genericfitting The Generic Fitting View + +\section org_mitk_gui_qt_fit_genericfitting_Overview Overview +This plug-in offers a generic fitting component for time resolved image data. + + +*/ diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..90a9f82801 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_fit_genericfitting org.mitk.gui.qt.fit.genericfitting + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_fit_genericfitting_internal Internal + \ingroup org_mitk_gui_qt_fit_genericfitting + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.fit.genericfitting plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/files.cmake b/Plugins/org.mitk.gui.qt.fit.genericfitting/files.cmake new file mode 100644 index 0000000000..177d57ce0e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/files.cmake @@ -0,0 +1,42 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_GenericDataFittingView_Activator.cpp + GenericDataFittingView.cpp +) + +set(UI_FILES + src/internal/GenericDataFittingViewControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_GenericDataFittingView_Activator.h + src/internal/GenericDataFittingView.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/gdf.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.fit.genericfitting/manifest_headers.cmake new file mode 100644 index 0000000000..670a894787 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Modelfit Generic Data Fitting") +set(Plugin-Version "1.0") +set(Plugin-Vendor "DKFZ, Software Development For Integrated Diagnostics and Therapy") +set(Plugin-ContactAddress "r.floca@dkfz.de") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/plugin.xml b/Plugins/org.mitk.gui.qt.fit.genericfitting/plugin.xml new file mode 100644 index 0000000000..5ab18734b8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/resources/gdf.png b/Plugins/org.mitk.gui.qt.fit.genericfitting/resources/gdf.png new file mode 100644 index 0000000000..c6c3dd3d93 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.fit.genericfitting/resources/gdf.png differ diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp new file mode 100644 index 0000000000..1f3b5cfe9f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.cpp @@ -0,0 +1,643 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "GenericDataFittingView.h" + +#include "mitkWorkbenchUtil.h" + +#include +#include +#include +#include +#include +#include + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// Includes for image casting between ITK and MITK +#include +#include "mitkImageCast.h" +#include "mitkITKImageImport.h" +#include +#include +#include + + +const std::string GenericDataFittingView::VIEW_ID = "org.mitk.gui.qt.fit.genericfitting"; + +void GenericDataFittingView::SetFocus() +{ + m_Controls.btnModelling->setFocus(); +} + +void GenericDataFittingView::CreateQtPartControl(QWidget* parent) +{ + m_Controls.setupUi(parent); + + m_Controls.btnModelling->setEnabled(false); + + this->InitModelComboBox(); + + connect(m_Controls.btnModelling, SIGNAL(clicked()), this, SLOT(OnModellingButtonClicked())); + + connect(m_Controls.comboModel, SIGNAL(currentIndexChanged(int)), this, SLOT(OnModellSet(int))); + connect(m_Controls.radioPixelBased, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + + //Gerneric setting + m_Controls.groupGeneric->hide(); + m_Controls.labelFormulaInfo->hide(); + connect(m_Controls.editFormula, SIGNAL(textChanged(const QString&)), this, + SLOT(UpdateGUIControls())); + connect(m_Controls.checkFormulaInfo, SIGNAL(toggled(bool)), m_Controls.labelFormulaInfo, + SLOT(setVisible(bool))); + connect(m_Controls.nrOfParams, SIGNAL(valueChanged(int)), this, SLOT(OnNrOfParamsChanged())); + + + //Model fit configuration + m_Controls.groupBox_FitConfiguration->hide(); + + m_Controls.checkBox_Constraints->setEnabled(false); + m_Controls.constraintManager->setEnabled(false); + m_Controls.initialValuesManager->setEnabled(false); + + connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)), this, + SLOT(UpdateGUIControls())); + connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), this, + SLOT(UpdateGUIControls())); + + connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)), + m_Controls.initialValuesManager, + SLOT(setEnabled(bool))); + connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager, + SLOT(setEnabled(bool))); + connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager, + SLOT(setVisible(bool))); + + UpdateGUIControls(); +} + +void GenericDataFittingView::UpdateGUIControls() +{ + m_Controls.lineFitName->setPlaceholderText(QString::fromStdString(this->GetDefaultFitName())); + m_Controls.lineFitName->setEnabled(!m_FittingInProgress); + + m_Controls.checkBox_Constraints->setEnabled(m_modelConstraints.IsNotNull()); + + bool isGenericFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + m_Controls.groupGeneric->setVisible(isGenericFactory); + + m_Controls.groupBox_FitConfiguration->setVisible(m_selectedModelFactory); + + m_Controls.groupBox->setEnabled(!m_FittingInProgress); + m_Controls.comboModel->setEnabled(!m_FittingInProgress); + m_Controls.groupGeneric->setEnabled(!m_FittingInProgress); + m_Controls.groupBox_FitConfiguration->setEnabled(!m_FittingInProgress); + + m_Controls.radioROIbased->setEnabled(m_selectedMask.IsNotNull()); + + m_Controls.btnModelling->setEnabled(m_selectedImage.IsNotNull() + && m_selectedModelFactory.IsNotNull() && !m_FittingInProgress && CheckModelSettings()); +} + +std::string GenericDataFittingView::GetDefaultFitName() const +{ + std::string defaultName = "undefined model"; + + if (this->m_selectedModelFactory.IsNotNull()) + { + defaultName = this->m_selectedModelFactory->GetClassID(); + } + + if (this->m_Controls.radioPixelBased->isChecked()) + { + defaultName += "_pixel"; + } + else + { + defaultName += "_roi"; + } + + return defaultName; +} + + +void GenericDataFittingView::OnNrOfParamsChanged() +{ + PrepareFitConfiguration(); + UpdateGUIControls(); +} + + +void GenericDataFittingView::OnModellSet(int index) +{ + m_selectedModelFactory = NULL; + + if (index > 0) + { + if (static_cast(index) <= m_FactoryStack.size() ) + { + m_selectedModelFactory = m_FactoryStack[index - 1]; + } + else + { + MITK_WARN << "Invalid model index. Index outside of the factory stack. Factory stack size: "<< m_FactoryStack.size() << "; invalid index: "<< index; + } + } + + UpdateGUIControls(); +} + +bool GenericDataFittingView::IsGenericParamFactorySelected() const +{ + return dynamic_cast + (m_selectedModelFactory.GetPointer()) != nullptr; +} + +void GenericDataFittingView::PrepareFitConfiguration() +{ + if (m_selectedModelFactory) + { + mitk::ModelBase::ParameterNamesType paramNames = m_selectedModelFactory->GetParameterNames(); + unsigned int nrOfPools = this->m_Controls.nrOfParams->value(); + + //init values + if (this->IsGenericParamFactorySelected()) + { + mitk::modelFit::ModelFitInfo::Pointer fitInfo = mitk::modelFit::ModelFitInfo::New(); + fitInfo->staticParamMap.Add(mitk::GenericParamModel::NAME_STATIC_PARAMETER_number, { static_cast(nrOfPools) }); + + auto parameterizer = m_selectedModelFactory->CreateParameterizer(fitInfo); + paramNames = parameterizer->GetParameterNames(); + + m_Controls.initialValuesManager->setInitialValues(paramNames, parameterizer->GetDefaultInitialParameterization()); + } + else + { + m_Controls.initialValuesManager->setInitialValues(paramNames, this->m_selectedModelFactory->GetDefaultInitialParameterization()); + } + + //constraints + this->m_modelConstraints = dynamic_cast + (m_selectedModelFactory->CreateDefaultConstraints().GetPointer()); + + if (this->m_modelConstraints.IsNull()) + { + this->m_modelConstraints = mitk::SimpleBarrierConstraintChecker::New(); + } + + m_Controls.constraintManager->setChecker(this->m_modelConstraints, paramNames); + } +}; + +void GenericDataFittingView::OnModellingButtonClicked() +{ + //check if all static parameters set + if (m_selectedModelFactory.IsNotNull() && CheckModelSettings()) + { + mitk::ParameterFitImageGeneratorBase::Pointer generator = NULL; + mitk::modelFit::ModelFitInfo::Pointer fitSession = NULL; + + bool isLinearFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isGenericFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isT2DecayFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + if (isLinearFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateModelFit_ROIBased(fitSession, generator); + } + } + else if (isGenericFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateModelFit_ROIBased(fitSession, generator); + } + } + else if (isT2DecayFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateModelFit_ROIBased(fitSession, generator); + } + } + //add other models with else if + + if (generator.IsNotNull() && fitSession.IsNotNull()) + { + m_FittingInProgress = true; + UpdateGUIControls(); + DoFit(fitSession, generator); + } + else + { + QMessageBox box; + box.setText("Fitting error!"); + box.setInformativeText("Could not establish fitting job. Error when setting ab generator, model parameterizer or session info."); + box.setStandardButtons(QMessageBox::Ok); + box.setDefaultButton(QMessageBox::Ok); + box.setIcon(QMessageBox::Warning); + box.exec(); + } + + } + else + { + QMessageBox box; + box.setText("Static parameters for model are not set!"); + box.setInformativeText("Some static parameters, that are needed for calculation are not set and equal to zero. Modeling not possible"); + box.setStandardButtons(QMessageBox::Ok); + box.setDefaultButton(QMessageBox::Ok); + box.setIcon(QMessageBox::Warning); + box.exec(); + } +} + + +void GenericDataFittingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, + const QList& selectedNodes) +{ + m_selectedNode = NULL; + m_selectedImage = NULL; + m_selectedMaskNode = NULL; + m_selectedMask = NULL; + + m_Controls.masklabel->setText("No (valid) mask selected."); + m_Controls.timeserieslabel->setText("No (valid) series selected."); + + QList nodes = selectedNodes; + + mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage"); + mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image"); + mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); + mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary); + + mitk::NodePredicateOr::Pointer maskPredicate = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet); + + if (nodes.size() > 0 && isImage->CheckNode(nodes.front())) + { + this->m_selectedNode = nodes.front(); + this->m_selectedImage = dynamic_cast(this->m_selectedNode->GetData()); + m_Controls.timeserieslabel->setText((this->m_selectedNode->GetName()).c_str()); + nodes.pop_front(); + } + + if (nodes.size() > 0 && maskPredicate->CheckNode(nodes.front())) + { + this->m_selectedMaskNode = nodes.front(); + this->m_selectedMask = dynamic_cast(this->m_selectedMaskNode->GetData()); + + if (this->m_selectedMask->GetTimeSteps() > 1) + { + MITK_INFO << + "Selected mask has multiple timesteps. Only use first timestep to mask model fit. Mask name: " << + m_selectedMaskNode->GetName(); + mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); + maskedImageTimeSelector->SetInput(this->m_selectedMask); + maskedImageTimeSelector->SetTimeNr(0); + maskedImageTimeSelector->UpdateLargestPossibleRegion(); + this->m_selectedMask = maskedImageTimeSelector->GetOutput(); + } + + m_Controls.masklabel->setText((this->m_selectedMaskNode->GetName()).c_str()); + } + + if (m_selectedMask.IsNull()) + { + this->m_Controls.radioPixelBased->setChecked(true); + } + + UpdateGUIControls(); +} + +bool GenericDataFittingView::CheckModelSettings() const +{ + bool ok = true; + + //check wether any model is set at all. Otherwise exit with false + if (m_selectedModelFactory.IsNotNull()) + { + bool isGenericFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + + if (isGenericFactory) + { + ok = !m_Controls.editFormula->text().isEmpty(); + } + } + else + { + ok = false; + } + + return ok; +} + +void GenericDataFittingView::ConfigureInitialParametersOfParameterizer(mitk::ModelParameterizerBase* + parameterizer) const +{ + if (m_Controls.radioButton_StartParameters->isChecked()) + { + //use user defined initial parameters + mitk::ValueBasedParameterizationDelegate::Pointer paramDelegate = + mitk::ValueBasedParameterizationDelegate::New(); + paramDelegate->SetInitialParameterization(m_Controls.initialValuesManager->getInitialValues()); + + parameterizer->SetInitialParameterizationDelegate(paramDelegate); + } + + mitk::GenericParamModelParameterizer* genericParameterizer = + dynamic_cast(parameterizer); + + if (genericParameterizer) + { + genericParameterizer->SetFunctionString(m_Controls.editFormula->text().toStdString()); + } +} + +template +void GenericDataFittingView::GenerateModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + auto genericParameterizer = dynamic_cast(modelParameterizer.GetPointer()); + if (genericParameterizer) + { + genericParameterizer->SetNumberOfParameters(this->m_Controls.nrOfParams->value()); + } + + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + std::string roiUID = ""; + + if (m_selectedMask.IsNotNull()) + { + fitGenerator->SetMask(m_selectedMask); + roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + } + + mitk::EnsureModelFitUID(this->m_selectedNode); + + fitGenerator->SetDynamicImage(this->m_selectedImage); + fitGenerator->SetFitFunctor(fitFunctor); + + generator = fitGenerator.GetPointer(); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), + roiUID); +} + +template +void GenericDataFittingView::GenerateModelFit_ROIBased( + mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::ROIBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + auto genericParameterizer = dynamic_cast(modelParameterizer.GetPointer()); + if (genericParameterizer) + { + genericParameterizer->SetNumberOfParameters(this->m_Controls.nrOfParams->value()); + } + + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + //Compute ROI signal + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = + mitk::MaskedDynamicImageStatisticsGenerator::New(); + signalGenerator->SetMask(m_selectedMask); + signalGenerator->SetDynamicImage(m_selectedImage); + signalGenerator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + fitGenerator->SetMask(m_selectedMask); + fitGenerator->SetFitFunctor(fitFunctor); + fitGenerator->SetSignal(roiSignal); + fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(m_selectedImage)); + + generator = fitGenerator.GetPointer(); + + mitk::EnsureModelFitUID(this->m_selectedNode); + std::string roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), + roiUID); + + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = + roiSignal.begin(); pos != roiSignal.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("ROI", infoSignal); +} + + +void GenericDataFittingView::DoFit(const mitk::modelFit::ModelFitInfo* fitSession, + mitk::ParameterFitImageGeneratorBase* generator) +{ + QString message = "Fitting Data Set . . ."; + m_Controls.infoBox->append(message); + + ///////////////////////// + //create job and put it into the thread pool + std::string fitName = m_Controls.lineFitName->text().toStdString(); + if (fitName.empty()) + { + fitName = m_Controls.lineFitName->placeholderText().toStdString(); + } + + ParameterFitBackgroundJob* pJob = new ParameterFitBackgroundJob(generator, fitSession, fitName, this->m_selectedNode); + pJob->setAutoDelete(true); + + connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnJobError(QString))); + connect(pJob, SIGNAL(Finished()), this, SLOT(OnJobFinished())); + connect(pJob, SIGNAL(ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const ParameterFitBackgroundJob*)), this, + SLOT(OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const ParameterFitBackgroundJob*)), Qt::BlockingQueuedConnection); + + connect(pJob, SIGNAL(JobProgress(double)), this, SLOT(OnJobProgress(double))); + connect(pJob, SIGNAL(JobStatusChanged(QString)), this, SLOT(OnJobStatusChanged(QString))); + + QThreadPool* threadPool = QThreadPool::globalInstance(); + threadPool->start(pJob); +} + +GenericDataFittingView::GenericDataFittingView() : m_FittingInProgress(false) +{ + m_selectedImage = NULL; + m_selectedMask = NULL; + + mitk::ModelFactoryBase::Pointer factory = + mitk::LinearModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::GenericParamModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::T2DecayModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + + this->m_IsNotABinaryImagePredicate = mitk::NodePredicateAnd::New( + mitk::TNodePredicateDataType::New(), + mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("binary", + mitk::BoolProperty::New(true))), + mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer(); + this->m_IsBinaryImagePredicate = mitk::NodePredicateAnd::New( + mitk::TNodePredicateDataType::New(), + mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)), + mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer(); +} + +void GenericDataFittingView::OnJobFinished() +{ + this->m_Controls.infoBox->append(QString("Fitting finished")); + this->m_FittingInProgress = false; + this->UpdateGUIControls(); +}; + +void GenericDataFittingView::OnJobError(QString err) +{ + MITK_ERROR << err.toStdString().c_str(); + + m_Controls.infoBox->append(QString("") + err + QString("")); + +}; + +void GenericDataFittingView::OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType + results, + const ParameterFitBackgroundJob* pJob) +{ + //Store the resulting parameter fit image via convenience helper function in data storage + //(handles the correct generation of the nodes and their properties) + mitk::modelFit::StoreResultsInDataStorage(this->GetDataStorage(), results, pJob->GetParentNode()); +}; + +void GenericDataFittingView::OnJobProgress(double progress) +{ + QString report = QString("Progress. ") + QString::number(progress); + this->m_Controls.infoBox->append(report); +}; + +void GenericDataFittingView::OnJobStatusChanged(QString info) +{ + this->m_Controls.infoBox->append(info); +} + + +void GenericDataFittingView::InitModelComboBox() const +{ + this->m_Controls.comboModel->clear(); + this->m_Controls.comboModel->addItem(tr("No model selected")); + + for (ModelFactoryStackType::const_iterator pos = m_FactoryStack.begin(); + pos != m_FactoryStack.end(); ++pos) + { + this->m_Controls.comboModel->addItem(QString::fromStdString((*pos)->GetClassID())); + } + + this->m_Controls.comboModel->setCurrentIndex(0); +}; + +mitk::ModelFitFunctorBase::Pointer GenericDataFittingView::CreateDefaultFitFunctor( + const mitk::ModelParameterizerBase* parameterizer) const +{ + mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor = + mitk::LevenbergMarquardtModelFitFunctor::New(); + + mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::Pointer chi2 = + mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::New(); + fitFunctor->RegisterEvaluationParameter("Chi^2", chi2); + + if (m_Controls.checkBox_Constraints->isChecked()) + { + fitFunctor->SetConstraintChecker(m_modelConstraints); + } + + mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel(); + + ::itk::LevenbergMarquardtOptimizer::ScalesType scales; + scales.SetSize(refModel->GetNumberOfParameters()); + scales.Fill(1.0); + fitFunctor->SetScales(scales); + + fitFunctor->SetDebugParameterMaps(m_Controls.checkDebug->isChecked()); + + return fitFunctor.GetPointer(); +} diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.h b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.h new file mode 100644 index 0000000000..cf8d5884c4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingView.h @@ -0,0 +1,155 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef GenericDataFittingView_h +#define GenericDataFittingView_h + +#include + +#include "QmitkAbstractView.h" + +#include "itkCommand.h" + +#include "ui_GenericDataFittingViewControls.h" +#include "mitkModelBase.h" +#include "QmitkParameterFitBackgroundJob.h" +#include "mitkModelFitResultHelper.h" +#include "mitkModelFactoryBase.h" +#include "mitkLevenbergMarquardtModelFitFunctor.h" +#include "mitkSimpleBarrierConstraintChecker.h" + +#include + +/*! +* @brief Plugin for generic dynamic image data fitting +*/ +class GenericDataFittingView : public QmitkAbstractView +{ + Q_OBJECT + +public: + + /*! @brief The view's unique ID - required by MITK */ + static const std::string VIEW_ID; + + GenericDataFittingView(); + +protected slots: + + void OnModellingButtonClicked(); + + void OnJobFinished(); + void OnJobError(QString err); + void OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType results, + const ParameterFitBackgroundJob* pJob); + void OnJobProgress(double progress); + void OnJobStatusChanged(QString info); + + void OnModellSet(int); + + void OnNrOfParamsChanged(); + + /**Sets visibility and enabled state of the GUI depending on the settings and workflow state.*/ + void UpdateGUIControls(); + +protected: + typedef QList SelectedDataNodeVectorType; + + // Overridden base class functions + + /*! + * @brief Sets up the UI controls and connects the slots and signals. Gets + * called by the framework to create the GUI at the right time. + * @param[in,out] parent The parent QWidget, as this class itself is not a QWidget + * subclass. + */ + void CreateQtPartControl(QWidget* parent); + + /*! + * @brief Sets the focus to the plot curve button. Gets called by the framework to set the + * focus on the right widget. + */ + void SetFocus(); + + template + void GenerateModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + + template + void GenerateModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + + /** Helper function that configures the initial parameter strategy of a parameterizer + according to the settings of the GUI.*/ + void ConfigureInitialParametersOfParameterizer(mitk::ModelParameterizerBase* parameterizer) const; + + void PrepareFitConfiguration(); + + bool IsGenericParamFactorySelected() const; + + /*! Starts the fitting job with the passed generator and session info*/ + void DoFit(const mitk::modelFit::ModelFitInfo* fitSession, + mitk::ParameterFitImageGeneratorBase* generator); + + /**Checks if the settings in the GUI are valid for the chosen model.*/ + bool CheckModelSettings() const; + + void InitModelComboBox() const; + + /*! \brief called by QmitkFunctionality when DataManager's selection has changed + */ + virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, + const QList& selectedNodes); + + // Variables + + /*! @brief The view's UI controls */ + Ui::GeneralDataFittingViewControls m_Controls; + + /* Nodes selected by user/ui for the fit */ + mitk::DataNode::Pointer m_selectedNode; + mitk::DataNode::Pointer m_selectedMaskNode; + + /* Images selected by user/ui for the fit */ + mitk::Image::Pointer m_selectedImage; + mitk::Image::Pointer m_selectedMask; + + mitk::ModelFactoryBase::Pointer m_selectedModelFactory; + + mitk::SimpleBarrierConstraintChecker::Pointer m_modelConstraints; + +private: + + bool m_FittingInProgress; + + typedef std::vector ModelFactoryStackType; + ModelFactoryStackType m_FactoryStack; + + /**Helper function that generates a default fitting functor + * default is a levenberg marquart based optimizer with all scales set to 1.0. + * Constraint setter will be set based on the gui setting and a evaluation parameter + * "sum of squared differences" will always be set.*/ + mitk::ModelFitFunctorBase::Pointer CreateDefaultFitFunctor(const mitk::ModelParameterizerBase* + parameterizer) const; + + /**Returns the default fit name, derived from the current GUI settings.*/ + std::string GetDefaultFitName() const; + + mitk::NodePredicateBase::Pointer m_IsNotABinaryImagePredicate; + mitk::NodePredicateBase::Pointer m_IsBinaryImagePredicate; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingViewControls.ui b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingViewControls.ui new file mode 100644 index 0000000000..69eafcff00 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/GenericDataFittingViewControls.ui @@ -0,0 +1,379 @@ + + + GeneralDataFittingViewControls + + + + 0 + 0 + 556 + 1124 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + + + + Selected Time Series: + + + + + + + No series selected. + + + + + + + + + + + Selected Mask: + + + + + + + No mask selected. + + + + + + + + + Fitting strategy + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + Pixel based + + + true + + + + + + + ROI based + + + + + + + + + + + + + Select fitting model... + + + + + + + + Generic model settings: + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + Formula: + + + + + + + + + + Number of parameters: + + + + + + + -1 + + + 1 + + + 10 + + + 1 + + + + + + + + + Show formula info + + + + + + + <html><head/><body><p>You may evaluate/fit simple mathematical formulas (e.g. &quot;<span style=" font-style:italic;">3.5 + a * x * sin(x) - 1 / 2</span>&quot;).</p><p>The parser is able to recognize:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">sums, differences, products and divisions (a + b, 4 - 3, 2 * x, 9 / 3)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">algebraic signs ( +5, -5)</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">exponentiation ( 2 ^ 4 )</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">parentheses (3 * (4 + 2))</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">following unary functions: <span style=" font-style:italic;">abs</span>, <span style=" font-style:italic;">exp</span>, <span style=" font-style:italic;">sin</span>, <span style=" font-style:italic;">cos</span>, <span style=" font-style:italic;">tan</span>, <span style=" font-style:italic;">sind</span> (sine in degrees), <span style=" font-style:italic;">cosd</span> (cosine in degrees), <span style=" font-style:italic;">tand</span> (tangent in degrees)</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">variables (x, a, b, c, ... , j)</li></ul><p>Remark: The variable &quot;x&quot; is reserved. It is the signal position / timepoint. Don't use it for a model parameter that should be deduced by fitting (these are represented by a..j).</p></body></html> + + + true + + + + + + + + + + + 0 + 0 + + + + Model Fit Configuration + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + + + 0 + 0 + 518 + 105 + + + + Start parameter + + + + + + Enter Fit Starting Parameters manually + + + + + + + + 0 + 0 + + + + + + + + + + 0 + 0 + 492 + 258 + + + + Constraints + + + + + + Enter Constraints for Fit Parameters + + + + + + + + 0 + 0 + + + + + 0 + 200 + + + + + + + + + + + + + + + 5 + + + + + Fitting name: + + + + + + + <html><head/><body><p>Name/prefix that should be used for the fitting results.</p><p>May be explicitly defined by the user.</p></body></html> + + + + + + default fit name + + + + + + + + + Start Modelling + + + + + + + Generate debug parameter images + + + + + + + + 0 + 0 + + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + QmitkSimpleBarrierManagerWidget + QWidget +
    QmitkSimpleBarrierManagerWidget.h
    +
    + + QmitkInitialValuesManagerWidget + QWidget +
    QmitkInitialValuesManagerWidget.h
    +
    +
    + + +
    diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/org_mitk_GenericDataFittingView_Activator.cpp b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/org_mitk_GenericDataFittingView_Activator.cpp new file mode 100644 index 0000000000..a72124a9bc --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/org_mitk_GenericDataFittingView_Activator.cpp @@ -0,0 +1,30 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "org_mitk_GenericDataFittingView_Activator.h" + + +#include "GenericDataFittingView.h" + +void org_mitk_GenericDataFittingView_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(GenericDataFittingView, context); + } + + void org_mitk_GenericDataFittingView_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context); + } diff --git a/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/org_mitk_GenericDataFittingView_Activator.h b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/org_mitk_GenericDataFittingView_Activator.h new file mode 100644 index 0000000000..a86a8072ca --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.genericfitting/src/internal/org_mitk_GenericDataFittingView_Activator.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef org_mitk_GenericDataFittingView_Activator_h +#define org_mitk_GenericDataFittingView_Activator_h + +#include + + class org_mitk_GenericDataFittingView_Activator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_fit_genericfitting") + Q_INTERFACES(ctkPluginActivator) + + public: + + /*! + * @brief Registers the plug-in. Gets called by the framework when the plug-in is + * first loaded. + * @param context The corresponding CTK plug-in context in which the plug-in is loaded. + */ + void start(ctkPluginContext* context); + + /*! + * @brief Deregisters the plug-in. Gets called by the framework when the plug-in + * is unloaded. + * @param context The corresponding CTK plug-in context in which the plug-in was loaded. + */ + void stop(ctkPluginContext* context); + }; + +#endif diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/CMakeLists.txt b/Plugins/org.mitk.gui.qt.fit.inspector/CMakeLists.txt new file mode 100644 index 0000000000..a3af7cd4ef --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/CMakeLists.txt @@ -0,0 +1,7 @@ +project(org_mitk_gui_qt_fit_inspector) + +mitk_create_plugin( + EXPORT_DIRECTIVE MODELFIT_INSPECTOR_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkModelFit MitkModelFitUI +) diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.fit.inspector/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..e8e7fcb587 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/documentation/UserManual/Manual.dox @@ -0,0 +1,14 @@ +/** +\page org_mitk_gui_qt_fit_inspector Model Fit Inspector + +\image html mf.png "Icon of Model Fit Inspector" + +Available sections: + - \ref org_mitk_gui_qt_fit_inspectorOverview + +\section org_mitk_gui_qt_fit_inspectorOverview Overview +The view can be used to inspect the following things: +#1 raw data if it has multiple time steps +#2 Fits and the fitted data + +*/ diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/documentation/UserManual/mf.png b/Plugins/org.mitk.gui.qt.fit.inspector/documentation/UserManual/mf.png new file mode 100644 index 0000000000..68c73e7bba Binary files /dev/null and b/Plugins/org.mitk.gui.qt.fit.inspector/documentation/UserManual/mf.png differ diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.fit.inspector/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..bdb3e18022 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_fit_inspector org.mitk.gui.qt.fit.inspector + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_fit_inspector_internal Internal + \ingroup org_mitk_gui_qt_fit_inspector + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.fit.inspector plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/files.cmake b/Plugins/org.mitk.gui.qt.fit.inspector/files.cmake new file mode 100644 index 0000000000..8c449f52ae --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/files.cmake @@ -0,0 +1,42 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_gui_qt_fit_inspector_Activator.cpp + ModelFitInspectorView.cpp +) + +set(UI_FILES + src/internal/ModelFitInspectorViewControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_gui_qt_fit_inspector_Activator.h + src/internal/ModelFitInspectorView.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/mf.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + resources/ModelFitInspector.qrc +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.fit.inspector/manifest_headers.cmake new file mode 100644 index 0000000000..df38cd0082 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Modelfit Inspector Plugin") +set(Plugin-Version "1.0") +set(Plugin-Vendor "DKFZ, Software Development For Integrated Diagnostics and Therapy") +set(Plugin-ContactAddress "r.floca@dkfz.de") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/plugin.xml b/Plugins/org.mitk.gui.qt.fit.inspector/plugin.xml new file mode 100644 index 0000000000..10c679659b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/resources/ModelFitInspector.qrc b/Plugins/org.mitk.gui.qt.fit.inspector/resources/ModelFitInspector.qrc new file mode 100644 index 0000000000..2aa92f096a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/resources/ModelFitInspector.qrc @@ -0,0 +1,8 @@ + + + parameter_image.png + derived_image.png + criterion_image.png + eval_image.png + + diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/resources/criterion_image.png b/Plugins/org.mitk.gui.qt.fit.inspector/resources/criterion_image.png new file mode 100644 index 0000000000..a6408e99a1 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.fit.inspector/resources/criterion_image.png differ diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/resources/derived_image.png b/Plugins/org.mitk.gui.qt.fit.inspector/resources/derived_image.png new file mode 100644 index 0000000000..75d44a312e Binary files /dev/null and b/Plugins/org.mitk.gui.qt.fit.inspector/resources/derived_image.png differ diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/resources/eval_image.png b/Plugins/org.mitk.gui.qt.fit.inspector/resources/eval_image.png new file mode 100644 index 0000000000..1dc54cd6c2 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.fit.inspector/resources/eval_image.png differ diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/resources/mf.png b/Plugins/org.mitk.gui.qt.fit.inspector/resources/mf.png new file mode 100644 index 0000000000..d5e1d3d4fe Binary files /dev/null and b/Plugins/org.mitk.gui.qt.fit.inspector/resources/mf.png differ diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/resources/parameter_image.png b/Plugins/org.mitk.gui.qt.fit.inspector/resources/parameter_image.png new file mode 100644 index 0000000000..f74e390b0d Binary files /dev/null and b/Plugins/org.mitk.gui.qt.fit.inspector/resources/parameter_image.png differ diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp new file mode 100644 index 0000000000..7a5c2abbab --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.cpp @@ -0,0 +1,1342 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +// Blueberry +#include +#include +#include + +// mitk +#include + +// Qt +#include +#include +#include +#include + +#include "mitkFormulaParser.h" +#include "mitkScalarListLookupTableProperty.h" +#include "mitkModelFitConstants.h" +#include "mitkExtractTimeGrid.h" +#include "mitkModelGenerator.h" +#include "mitkModelFitException.h" +#include "mitkModelFitParameterValueExtraction.h" + +#include "ModelFitInspectorView.h" + +#include +const std::string ModelFitInspectorView::VIEW_ID = "org.mitk.gui.gt.fit.inspector"; +const unsigned int ModelFitInspectorView::INTERPOLATION_STEPS = 100; + +ModelFitInspectorView::ObserverInfo::ObserverInfo(mitk::SliceNavigationController* controller, + int observerTag, const std::string& renderWindowName, mitk::IRenderWindowPart* part) : controller(controller), observerTag(observerTag), + renderWindowName(renderWindowName), renderWindowPart(part) +{ +} + +ModelFitInspectorView::ModelFitInspectorView() : + m_renderWindowPart(nullptr), + m_PendingSliceChangedEvent(false), + m_internalUpdateFlag(false), + m_currentFit(nullptr), + m_currentModelParameterizer(nullptr), + m_currentModelProviderService(nullptr), + m_currentSelectedTimeStep(0), + m_currentSelectedNode(nullptr) + +{ + m_currentSelectedPosition.Fill(0.0); + m_modelfitList.clear(); +} + +ModelFitInspectorView::~ModelFitInspectorView() +{ + this->RemoveAllObservers(); +} + + +bool ModelFitInspectorView::InitObservers() +{ + + bool result = true; + + typedef QHash WindowMapType; + WindowMapType windowMap = m_renderWindowPart->GetQmitkRenderWindows(); + + auto i = windowMap.begin(); + + while (i != windowMap.end()) + { + mitk::SliceNavigationController* sliceNavController = + i.value()->GetSliceNavigationController(); + + if (sliceNavController) + { + itk::ReceptorMemberCommand::Pointer cmdSliceEvent = + itk::ReceptorMemberCommand::New(); + cmdSliceEvent->SetCallbackFunction(this, &ModelFitInspectorView::OnSliceChanged); + int tag = sliceNavController->AddObserver( + mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), + cmdSliceEvent); + + m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag, + i.key().toStdString(), m_renderWindowPart))); + + itk::ReceptorMemberCommand::Pointer cmdTimeEvent = + itk::ReceptorMemberCommand::New(); + cmdTimeEvent->SetCallbackFunction(this, &ModelFitInspectorView::OnSliceChanged); + tag = sliceNavController->AddObserver( + mitk::SliceNavigationController::GeometryTimeEvent(nullptr, 0), + cmdTimeEvent); + + m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag, + i.key().toStdString(), m_renderWindowPart))); + + itk::MemberCommand::Pointer cmdDelEvent = + itk::MemberCommand::New(); + cmdDelEvent->SetCallbackFunction(this, + &ModelFitInspectorView::OnSliceNavigationControllerDeleted); + tag = sliceNavController->AddObserver( + itk::DeleteEvent(), cmdDelEvent); + + m_ObserverMap.insert(std::make_pair(sliceNavController, ObserverInfo(sliceNavController, tag, + i.key().toStdString(), m_renderWindowPart))); + } + + ++i; + + result = result && sliceNavController; + } + + return result; +} + +void ModelFitInspectorView::RemoveObservers(const mitk::SliceNavigationController* + deletedSlicer) +{ + + std::pair < ObserverMapType::const_iterator, ObserverMapType::const_iterator> obsRange = + m_ObserverMap.equal_range(deletedSlicer); + + for (ObserverMapType::const_iterator pos = obsRange.first; pos != obsRange.second; ++pos) + { + pos->second.controller->RemoveObserver(pos->second.observerTag); + } + + m_ObserverMap.erase(deletedSlicer); +} + +void ModelFitInspectorView::RemoveAllObservers(mitk::IRenderWindowPart* deletedPart) +{ + for (ObserverMapType::const_iterator pos = m_ObserverMap.begin(); pos != m_ObserverMap.end(); ) + { + ObserverMapType::const_iterator delPos = pos++; + + if (deletedPart == nullptr || deletedPart == delPos->second.renderWindowPart) + { + delPos->second.controller->RemoveObserver(delPos->second.observerTag); + m_ObserverMap.erase(delPos); + } + } +} + +void ModelFitInspectorView::OnSliceNavigationControllerDeleted(const itk::Object* sender, + const itk::EventObject& /*e*/) +{ + const mitk::SliceNavigationController* sendingSlicer = + dynamic_cast(sender); + + this->RemoveObservers(sendingSlicer); +} + +void ModelFitInspectorView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) +{ + if (m_renderWindowPart != renderWindowPart) + { + m_renderWindowPart = renderWindowPart; + + if (!InitObservers()) + { + QMessageBox::information(nullptr, "Error", "Unable to set up the event observers. The " \ + "plot will not be triggered on changing the crosshair, " \ + "position or time step."); + } + } +} + +void ModelFitInspectorView::RenderWindowPartDeactivated( + mitk::IRenderWindowPart* renderWindowPart) +{ + m_renderWindowPart = nullptr; + this->RemoveAllObservers(renderWindowPart); +} + +void ModelFitInspectorView::CreateQtPartControl(QWidget* parent) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi(parent); + connect(m_Controls.cmbFit, SIGNAL(currentIndexChanged(int)), this, + SLOT(OnFitSelectionChanged(int))); + + connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.sbFixMin, + SLOT(setEnabled(bool))); + connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.sbFixMax, + SLOT(setEnabled(bool))); + connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.labelFixMin, + SLOT(setEnabled(bool))); + connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.labelFixMax, + SLOT(setEnabled(bool))); + connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), m_Controls.btnScaleToData, + SLOT(setEnabled(bool))); + + connect(m_Controls.radioScaleFixed, SIGNAL(toggled(bool)), this, SLOT(OnScaleFixedYChecked(bool))); + + connect(m_Controls.btnScaleToData, SIGNAL(clicked()), this, SLOT(OnScaleToDataYClicked())); + connect(m_Controls.sbFixMax, SIGNAL(valueChanged(double)), this, + SLOT(OnFixedScalingYChanged(double))); + connect(m_Controls.sbFixMin, SIGNAL(valueChanged(double)), this, + SLOT(OnFixedScalingYChanged(double))); + + connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.sbFixMin_x, + SLOT(setEnabled(bool))); + connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.sbFixMax_x, + SLOT(setEnabled(bool))); + connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.labelFixMin_x, + SLOT(setEnabled(bool))); + connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.labelFixMax_x, + SLOT(setEnabled(bool))); + connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), m_Controls.btnScaleToData_x, + SLOT(setEnabled(bool))); + + connect(m_Controls.radioScaleFixed_x, SIGNAL(toggled(bool)), this, SLOT(OnScaleFixedXChecked(bool))); + + connect(m_Controls.btnScaleToData_x, SIGNAL(clicked()), this, SLOT(OnScaleToDataXClicked())); + connect(m_Controls.sbFixMax_x, SIGNAL(valueChanged(double)), this, + SLOT(OnFixedScalingXChanged(double))); + connect(m_Controls.sbFixMin_x, SIGNAL(valueChanged(double)), this, + SLOT(OnFixedScalingXChanged(double))); + + + connect(m_Controls.btnExport, SIGNAL(clicked()), this, SLOT(OnExportClicked())); + + // Add SIGNAL and SLOT for "Copy to clipboard" functionality + + connect(m_Controls.btnCopyResultsToClipboard, SIGNAL(clicked()), this, SLOT(OnClipboardResultsButtonClicked())); + + + // For some reason this needs to be called to set the plot widget's minimum width to an + // acceptable level (since Qwt 6). + // Otherwise it tries to keep both axes equal in length, resulting in a minimum width of + // 400-500px which is way too much. + m_Controls.widgetPlot->GetPlot()->updateAxes(); + + m_Controls.cmbFit->clear(); + + mitk::IRenderWindowPart* renderWindowPart = GetRenderWindowPart(); + RenderWindowPartActivated(renderWindowPart); +} + +void ModelFitInspectorView::SetFocus() +{ +} + +void ModelFitInspectorView::OnScaleFixedYChecked(bool checked) +{ + m_Controls.widgetPlot->GetPlot()->setAxisAutoScale(QwtPlot::yLeft, !checked); + + if (checked) + { + OnScaleToDataYClicked(); + } + + m_Controls.widgetPlot->GetPlot()->replot(); +}; + +void ModelFitInspectorView::OnScaleFixedXChecked(bool checked) +{ + m_Controls.widgetPlot->GetPlot()->setAxisAutoScale(QwtPlot::xBottom, !checked); + + if (checked) + { + OnScaleToDataXClicked(); + } + + m_Controls.widgetPlot->GetPlot()->replot(); +}; + +void CheckYMinMaxFromXYData(const QmitkPlotWidget::XYDataVector& data, double& min, double& max) +{ + for (const auto & pos : data) + { + if (max < pos.second) + { + max = pos.second; + } + + if (min > pos.second) + { + min = pos.second; + } + } +} + +void CheckXMinMaxFromXYData(const QmitkPlotWidget::XYDataVector& data, double& min, double& max) +{ + for (const auto & pos : data) + { + if (max < pos.first) + { + max = pos.first; + } + + if (min > pos.first) + { + min = pos.first; + } + } +} + +void ModelFitInspectorView::OnScaleToDataYClicked() +{ + double max = itk::NumericTraits::NonpositiveMin(); + double min = itk::NumericTraits::max(); + + CheckYMinMaxFromXYData(this->m_ImagePlotCurve, min, max); + CheckYMinMaxFromXYData(this->m_ModelPlotCurve, min, max); + + for (CurveMapType::const_iterator pos = this->m_InputDataPlotCurves.begin(); + pos != this->m_InputDataPlotCurves.end(); ++pos) + { + CheckYMinMaxFromXYData(pos->second, min, max); + } + + min -= abs(min) * 0.01; + max += abs(max) * 0.01; + + m_Controls.sbFixMax->setValue(max); + m_Controls.sbFixMin->setValue(min); + +}; + +void ModelFitInspectorView::OnScaleToDataXClicked() +{ + double max = itk::NumericTraits::NonpositiveMin(); + double min = itk::NumericTraits::max(); + + CheckXMinMaxFromXYData(this->m_ImagePlotCurve, min, max); + CheckXMinMaxFromXYData(this->m_ModelPlotCurve, min, max); + + for (CurveMapType::const_iterator pos = this->m_InputDataPlotCurves.begin(); + pos != this->m_InputDataPlotCurves.end(); ++pos) + { + CheckXMinMaxFromXYData(pos->second, min, max); + } + + min -= abs(min) * 0.01; + max += abs(max) * 0.01; + + m_Controls.sbFixMax_x->setValue(max); + m_Controls.sbFixMin_x->setValue(min); + +}; + +void ModelFitInspectorView::OnFixedScalingYChanged(double /*value*/) +{ + m_Controls.widgetPlot->GetPlot()->setAxisScale(QwtPlot::yLeft, m_Controls.sbFixMin->value(), + m_Controls.sbFixMax->value()); + m_Controls.widgetPlot->GetPlot()->replot(); +}; + +void ModelFitInspectorView::OnFixedScalingXChanged(double /*value*/) +{ + m_Controls.widgetPlot->GetPlot()->setAxisScale(QwtPlot::xBottom, m_Controls.sbFixMin_x->value(), + m_Controls.sbFixMax_x->value()); + m_Controls.widgetPlot->GetPlot()->replot(); +}; + +void ModelFitInspectorView::OnExportClicked() +{ + QString fileName = QFileDialog::getSaveFileName(nullptr, tr("Save File")); + + if (fileName.isEmpty()) + { + QMessageBox::critical(nullptr, tr("No file selected!"), + tr("Cannot export pixel dump. Please selected a file.")); + } + else + { + std::ofstream file; + + std::ios_base::openmode iOpenFlag = std::ios_base::out | std::ios_base::trunc; + file.open(fileName.toStdString().c_str(), iOpenFlag); + + if (!file.is_open()) + { + QMessageBox::critical(nullptr, tr("Cannot create/open selected file!"), + tr("Cannot open or create the selected file. Export will be aborted. Selected file name: ") + + fileName); + return; + } + + for (int i = 0; i < m_Controls.tableData->columnCount(); ++i) + { + file << m_Controls.tableData->horizontalHeaderItem(i)->text().toStdString(); + + if (i < m_Controls.tableData->columnCount() - 1) + { + file << ","; + } + } + + file << std::endl; + + for (int row = 0; row < m_Controls.tableData->rowCount(); ++row) + { + for (int i = 0; i < m_Controls.tableData->columnCount(); ++i) + { + file << m_Controls.tableData->item(row, i)->text().toStdString(); + + if (i < m_Controls.tableData->columnCount() - 1) + { + file << ","; + } + } + + file << std::endl; + } + + file.close(); + } +} + +void ModelFitInspectorView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, + const QList& nodes) +{ + if (nodes.size() > 0) + { + if (nodes.front() != this->m_currentSelectedNode) + { + + m_internalUpdateFlag = true; + + this->m_currentSelectedNode = nodes.front(); + + mitk::DataStorage::Pointer storage = this->GetDataStorage(); + + mitk::NodeUIDType selectedFitUD = ""; + bool isModelFitNode = this->m_currentSelectedNode->GetData()->GetPropertyList()->GetStringProperty( + mitk::ModelFitConstants::FIT_UID_PROPERTY_NAME().c_str(), selectedFitUD); + + if (isModelFitNode) + { + this->m_currentSelectedNode = this->GetParentNode(this->m_currentSelectedNode); + } + + mitk::modelFit::NodeUIDSetType fitUIDs = mitk::modelFit::GetFitUIDsOfNode( + this->m_currentSelectedNode, storage); + + this->m_modelfitList.clear(); + this->m_Controls.cmbFit->clear(); + + for (const auto & fitUID : fitUIDs) + { + mitk::modelFit::ModelFitInfo::ConstPointer info = mitk::modelFit::CreateFitInfoFromNode(fitUID, + storage).GetPointer(); + + if (info.IsNotNull()) + { + this->m_modelfitList.insert(std::make_pair(info->uid, info)); + + QVariant data(info->uid.c_str()); + m_Controls.cmbFit->addItem(QString::fromStdString(info->modelName), data); + } + else + { + MITK_ERROR << + "Was not able to extract model fit information from storage. Node properties in storage may be invalid. Failed fit UID:" + << fitUID; + } + } + + int cmbIndex = 0; + + if (m_modelfitList.empty()) + { + cmbIndex = -1; + }; + + if (isModelFitNode) + { + //model was selected, thus select this one in combobox + QVariant data(selectedFitUD.c_str()); + cmbIndex = m_Controls.cmbFit->findData(data); + + if (cmbIndex == -1) + { + MITK_WARN << + "Model fit Inspector in invalid state. Selected fit seems to be not avaible in plugin selection. Failed fit UID:" + << selectedFitUD; + } + }; + + m_Controls.cmbFit->setCurrentIndex(cmbIndex); + + m_internalUpdateFlag = false; + + m_selectedNodeTime.Modified(); + + if (cmbIndex == -1) + { + //only raw 4D data selected. Just update plots for current position + m_currentFit = nullptr; + m_currentFitTime.Modified(); + OnSliceChangedDelayed(); + } + else + { + //refresh fit selection (and implicitly update plots) + OnFitSelectionChanged(cmbIndex); + } + } + } + else + { + if (this->m_currentSelectedNode.IsNotNull()) + { + m_internalUpdateFlag = true; + this->m_currentSelectedNode = nullptr; + this->m_currentFit = nullptr; + this->m_modelfitList.clear(); + this->m_Controls.cmbFit->clear(); + m_internalUpdateFlag = false; + + m_selectedNodeTime.Modified(); + OnFitSelectionChanged(0); + } + } + +} + +mitk::DataNode::ConstPointer +ModelFitInspectorView::GetParentNode(mitk::DataNode::ConstPointer node) +{ + if (node.IsNotNull()) + { + mitk::DataStorage::SetOfObjects::ConstPointer parentNodeList = + GetDataStorage()->GetSources(node); + + if (parentNodeList->size() > 0) + { + return parentNodeList->front().GetPointer(); + } + } + + return mitk::DataNode::ConstPointer(); +} + + +void ModelFitInspectorView::ValidateAndSetCurrentPosition() +{ + mitk::Point3D currentSelectedPosition = GetRenderWindowPart()->GetSelectedPosition(nullptr); + unsigned int currentSelectedTimestep = m_renderWindowPart->GetTimeNavigationController()->GetTime()-> + GetPos(); + + if (m_currentSelectedPosition != currentSelectedPosition + || m_currentSelectedTimeStep != currentSelectedTimestep + || m_selectedNodeTime > m_currentPositionTime) + { + //the current position has been changed or the selected node has been changed since the last position validation -> check position + m_currentSelectedPosition = currentSelectedPosition; + m_currentSelectedTimeStep = currentSelectedTimestep; + m_currentPositionTime.Modified(); + m_validSelectedPosition = false; + + mitk::Image::Pointer inputImage = this->GetCurrentInputImage(); + + if (inputImage.IsNull()) + { + return; + } + + mitk::BaseGeometry::Pointer geometry = inputImage->GetTimeGeometry()->GetGeometryForTimeStep( + m_currentSelectedTimeStep); + + // check for invalid time step + if (geometry.IsNull()) + { + geometry = inputImage->GetTimeGeometry()->GetGeometryForTimeStep(0); + } + + if (geometry.IsNull()) + { + return; + } + + m_validSelectedPosition = geometry->IsInside(m_currentSelectedPosition); + + } +} + +mitk::Image::Pointer ModelFitInspectorView::GetCurrentInputImage() const +{ + mitk::Image::Pointer result = nullptr; + + if (this->m_currentFit.IsNotNull()) + { + result = m_currentFit->inputImage; + } + else if (this->m_currentSelectedNode.IsNotNull()) + { + result = dynamic_cast(this->m_currentSelectedNode->GetData()); + + if (result.IsNotNull() && result->GetTimeSteps() <= 1) + { + //if the image is not dynamic, we can't use it. + result = nullptr; + } + } + + return result; +}; + +const mitk::ModelBase::TimeGridType ModelFitInspectorView::GetCurrentTimeGrid() const +{ + if (m_currentModelProviderService && m_currentFit.IsNotNull()) + { + return m_currentModelProviderService->GetVariableGrid(m_currentFit); + } + else + { //fall back if there is no model provider we assume to use the normal time grid. + return ExtractTimeGrid(GetCurrentInputImage()); + } +}; + +void ModelFitInspectorView::OnSliceChanged(const itk::EventObject&) +{ + // Taken from QmitkStdMultiWidget::HandleCrosshairPositionEvent(). + // Since there are always 3 events arriving (one for each render window) every time the slice + // or time changes, the slot OnSliceChangedDelayed is triggered - and only if it hasn't been + // triggered yet - so it is only executed once for every slice/time change. + if (!m_PendingSliceChangedEvent) + { + m_PendingSliceChangedEvent = true; + QTimer::singleShot(0, this, SLOT(OnSliceChangedDelayed())); + } +} + +void ModelFitInspectorView::OnSliceChangedDelayed() +{ + m_PendingSliceChangedEvent = false; + + ValidateAndSetCurrentPosition(); + + m_Controls.widgetPlot->setEnabled(m_validSelectedPosition); + + if (m_currentSelectedNode.IsNotNull()) + { + if (RefreshPlotData()) + { + RenderPlot(); + RenderFitInfo(); + } + } +} + +mitk::ModelBase::TimeGridType +ModelFitInspectorView::GenerateInterpolatedTimeGrid(const mitk::ModelBase::TimeGridType& grid) +const +{ + unsigned int origGridSize = grid.size(); + + mitk::ModelBase::TimeGridType interpolatedTimeGrid(((origGridSize - 1) * INTERPOLATION_STEPS) + 1); + + for (unsigned int t = 0; t < origGridSize - 1; ++t) + { + double delta = (grid[t + 1] - grid[t]) / INTERPOLATION_STEPS; + + for (unsigned int i = 0; i < INTERPOLATION_STEPS; ++i) + { + interpolatedTimeGrid[(t * INTERPOLATION_STEPS) + i] = grid[t] + i * delta; + } + } + + interpolatedTimeGrid[interpolatedTimeGrid.size() - 1] = grid[grid.size() - 1]; + + return interpolatedTimeGrid; +}; + + +QmitkPlotWidget::XYDataVector +ModelFitInspectorView::CalcCurveFromModel(const mitk::Point3D& position) +{ + assert(m_currentModelParameterizer.IsNotNull()); + assert(m_currentFit.IsNotNull()); + + mitk::Image::Pointer inputImage = this->GetCurrentInputImage(); + assert(inputImage.IsNotNull()); + + // Calculate index + ::itk::Index<3> index; + mitk::BaseGeometry::Pointer geometry = inputImage->GetTimeGeometry()->GetGeometryForTimeStep(0); + + geometry->WorldToIndex(position, index); + + //model generation + mitk::ModelBase::Pointer model = m_currentModelParameterizer->GenerateParameterizedModel(index); + + mitk::ParameterValueMapType parameterMap = mitk::ExtractParameterValueMapFromModelFit(m_currentFit, position); + + mitk::ModelBase::ParametersType paramArray = mitk::ConvertParameterMapToParameterVector(parameterMap, model); + + mitk::ModelBase::ModelResultType curveDataY = model->GetSignal(paramArray); + QmitkPlotWidget::XYDataVector result; + mitk::ModelBase::TimeGridType timeGrid = model->GetTimeGrid(); + + for (unsigned int t = 0; t < timeGrid.size(); ++t) + { + double x = timeGrid[t]; + double y = curveDataY[t]; + result.push_back(std::make_pair(x, y)); + } + + return result; +} + +QmitkPlotWidget::XYDataVector +ModelFitInspectorView::CalcCurveFromFunction(const mitk::Point3D& position, + const mitk::ModelBase::TimeGridType& timeGrid) +{ + assert(m_currentFit.IsNotNull()); + assert(m_renderWindowPart != nullptr); + + mitk::Image::Pointer inputImage = this->GetCurrentInputImage(); + assert(inputImage.IsNotNull()); + + QmitkPlotWidget::XYDataVector result; + + // Calculate index + ::itk::Index<3> index;; + mitk::BaseGeometry::Pointer geometry = inputImage->GetTimeGeometry()->GetGeometryForTimeStep(0); + + geometry->WorldToIndex(position, index); + + mitk::ParameterValueMapType parameterMap = mitk::ExtractParameterValueMapFromModelFit(m_currentFit, position); + + mitk::FormulaParser parser(¶meterMap); + unsigned int timestep = m_renderWindowPart->GetTimeNavigationController()->GetTime()-> + GetPos(); + + for (unsigned int t = 0; t < timeGrid.size(); ++t) + { + // Set up static parameters + foreach (const mitk::modelFit::StaticParameterMap::StaticParameterType& var, + m_currentFit->staticParamMap) + { + const std::string& name = var.first; + const mitk::modelFit::StaticParameterMap::ValueType& list = var.second; + + if (list.size() == 1) + { + parameterMap[name] = list.front(); + } + else + { + parameterMap[name] = list.at(timestep); + } + } + + // Calculate curve data + double x = timeGrid[t]; + parameterMap[m_currentFit->x] = x; + + double y = parser.parse(m_currentFit->function); + result.push_back(std::make_pair(x, y)); + } + + return result; +} + +void ModelFitInspectorView::OnFitSelectionChanged(int index) +{ + if (!m_internalUpdateFlag) + { + MITK_DEBUG << "selected fit index: " << index; + + std::string uid = ""; + + + if (m_Controls.cmbFit->count() > index) + { + uid = m_Controls.cmbFit->itemData(index).toString().toStdString(); + } + + mitk::modelFit::ModelFitInfo::ConstPointer newFit = nullptr; + + ModelFitInfoListType::iterator finding = m_modelfitList.find(uid); + + if (finding != m_modelfitList.end()) + { + newFit = finding->second; + } + + if (m_currentFit != newFit) + { + m_currentModelParameterizer = nullptr; + m_currentModelProviderService = nullptr; + + if (newFit.IsNotNull()) + { + m_currentModelParameterizer = mitk::ModelGenerator::GenerateModelParameterizer(*newFit); + m_currentModelProviderService = mitk::ModelGenerator::GetProviderService(newFit->functionClassID); + } + + m_currentFit = newFit; + + m_currentFitTime.Modified(); + + OnSliceChangedDelayed(); + } + } +} + +bool ModelFitInspectorView::RefreshPlotData() +{ + bool changed = false; + + if (m_currentSelectedNode.IsNull()) + { + this->m_ImagePlotCurve.clear(); + this->m_ModelPlotCurve.clear(); + this->m_InputDataPlotCurves.clear(); + + changed = m_selectedNodeTime > m_lastRefreshTime; + m_lastRefreshTime.Modified(); + } + else + { + assert(GetRenderWindowPart() != NULL); + + const mitk::Image* input = GetCurrentInputImage(); + const mitk::ModelBase::TimeGridType timeGrid = GetCurrentTimeGrid(); + + //image data curve + if (m_selectedNodeTime > m_lastRefreshTime || m_currentFitTime > m_lastRefreshTime + || m_currentPositionTime > m_lastRefreshTime) + { + m_ImagePlotCurve.clear(); + + if (input && m_validSelectedPosition) + { + QmitkPlotWidget::XYDataVector pointData; + + for (unsigned int t = 0; t < timeGrid.size(); ++t) + { + double x = timeGrid[t]; + double y = ReadVoxel(input, m_currentSelectedPosition, t); + pointData.push_back(std::make_pair(x, y)); + } + + m_ImagePlotCurve = pointData; + } + + changed = true; + } + + //model curve + if (m_currentFitTime > m_lastRefreshTime || m_currentPositionTime > m_lastRefreshTime) + { + m_ModelPlotCurve.clear(); + + if (m_currentFit.IsNotNull() && m_validSelectedPosition) + { + QmitkPlotWidget::XYDataVector curveData; + + // Interpolate time grid (x values) so the curve looks smooth + const mitk::ModelBase::TimeGridType interpolatedTimeGrid = GenerateInterpolatedTimeGrid(timeGrid); + + if (m_currentModelParameterizer.IsNotNull()) + { + // Use model instead of formula parser + m_currentModelParameterizer->SetDefaultTimeGrid(interpolatedTimeGrid); + curveData = CalcCurveFromModel(m_currentSelectedPosition); + } + else + { + // Use formula parser to parse function string + try + { + curveData = CalcCurveFromFunction(m_currentSelectedPosition, interpolatedTimeGrid); + } + catch (const mitk::FormulaParserException& e) + { + MITK_ERROR << "Error while parsing modelfit function: " << e.what(); + } + } + + m_ModelPlotCurve = curveData; + } + + changed = true; + } + + // input data curve + if (m_currentFitTime > m_lastRefreshTime) + { + m_InputDataPlotCurves.clear(); + + if (m_currentFit.IsNotNull()) + { + for (mitk::ScalarListLookupTable::LookupTableType::const_iterator pos = + m_currentFit->inputData.GetLookupTable().begin(); + pos != m_currentFit->inputData.GetLookupTable().end(); ++pos) + { + if (pos->second.size() != timeGrid.size()) + { + MITK_ERROR << + "Error while refreshing input data for visualization. Size of data and input image time grid differ. Invalid data name: " + << pos->first; + } + else + { + QmitkPlotWidget::XYDataVector pointData; + + for (unsigned int t = 0; t < timeGrid.size(); ++t) + { + double x = timeGrid[t]; + double y = pos->second[t]; + pointData.push_back(std::make_pair(x, y)); + } + + m_InputDataPlotCurves.insert(std::make_pair(pos->first, pointData)); + } + } + } + + changed = true; + } + + if (m_selectedNodeTime > m_lastRefreshTime || m_currentFitTime > m_lastRefreshTime + || m_currentPositionTime > m_lastRefreshTime) + { + InitDataTable(); + } + + m_lastRefreshTime.Modified(); + } + + return changed; +} + +void ModelFitInspectorView::RenderFitInfo() +{ + assert(m_renderWindowPart != nullptr); + + // configure fit information + + if (m_currentFit.IsNull()) + { + m_Controls.lFitType->setText(""); + m_Controls.lFitUID->setText(""); + m_Controls.lModelName->setText(""); + m_Controls.lModelType->setText(""); + } + else + { + m_Controls.lFitType->setText(QString::fromStdString(m_currentFit->fitType)); + m_Controls.lFitUID->setText(QString::fromStdString(m_currentFit->uid)); + m_Controls.lModelName->setText(QString::fromStdString(m_currentFit->modelName)); + m_Controls.lModelType->setText(QString::fromStdString(m_currentFit->modelType)); + } + + // print results + std::stringstream infoOutput; + + m_Controls.grpParams->setVisible(false); + m_Controls.groupSettings->setVisible(false); + m_Controls.tableResults->clearContents(); + + if (m_currentFit.IsNull()) + { + infoOutput << "No fit selected. Only raw image data is plotted."; + } + else if (!m_validSelectedPosition) + { + infoOutput << + "Current position is outside of the input image of the selected fit.\nInspector is deactivated."; + } + else + { + m_Controls.grpParams->setVisible(true); + // Set sorting to false. Wait with sorting until all parameters are set in the table. + + m_Controls.tableResults->setSortingEnabled(false); + m_Controls.tableResults->setRowCount(m_currentFit->GetParameters().size() + + m_currentFit->staticParamMap.Size()); + + unsigned int timestep = m_renderWindowPart->GetTimeNavigationController()->GetTime()->GetPos(); + unsigned int rowIndex = 0; + + assert(GetRenderWindowPart() != NULL); + + for (mitk::modelFit::ModelFitInfo::ConstIterType paramIter = m_currentFit->GetParameters().begin(); + paramIter != m_currentFit->GetParameters().end(); + ++paramIter, ++rowIndex) + { + mitk::modelFit::Parameter::ConstPointer p = + static_cast(*paramIter); + double value = ReadVoxel(p->image, m_currentSelectedPosition, timestep); + + std::string paramType = mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_PARAMETER(); + + if (p->type == mitk::modelFit::Parameter::DerivedType) + { + paramType = mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_DERIVED_PARAMETER(); + } + else if (p->type == mitk::modelFit::Parameter::CriterionType) + { + paramType = mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_CRITERION(); + } + else if (p->type == mitk::modelFit::Parameter::EvaluationType) + { + paramType = mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_EVALUATION_PARAMETER(); + } + + QTableWidgetItem* newItem = new QTableWidgetItem(QString::fromStdString(p->name)); + m_Controls.tableResults->setItem(rowIndex, 0, newItem); + newItem = new QTableWidgetItem(QString::number(value)); + m_Controls.tableResults->setItem(rowIndex, 1, newItem); + newItem = new QTableWidgetItem(QString::fromStdString(paramType)); + m_Controls.tableResults->setItem(rowIndex, 2, newItem); + } + + foreach(const mitk::modelFit::StaticParameterMap::StaticParameterType& var, + m_currentFit->staticParamMap) + { + const std::string& name = var.first; + const mitk::modelFit::StaticParameterMap::ValueType& list = var.second; + + QTableWidgetItem* newItem = new QTableWidgetItem(QString::fromStdString(name)); + m_Controls.tableResults->setItem(rowIndex, 0, newItem); + newItem = new QTableWidgetItem(QString::number(list.front())); + m_Controls.tableResults->setItem(rowIndex, 1, newItem); + newItem = new QTableWidgetItem(tr("static")); + m_Controls.tableResults->setItem(rowIndex, 2, newItem); + ++rowIndex; + } + // Here the sorting function is enabled and the table entries are sorted alphabetically in descending order. + // This way the parameters are always displayed in the same order. + + m_Controls.tableResults->setSortingEnabled(true); + m_Controls.tableResults->sortItems(0, Qt::DescendingOrder); + + + } + + // configure data table + m_Controls.tableInputData->clearContents(); + + if (m_currentFit.IsNull()) + { + infoOutput << "No fit selected. Only raw image data is plotted."; + } + else + { + m_Controls.groupSettings->setVisible(true); + m_Controls.tableInputData->setRowCount(m_InputDataPlotCurves.size()); + + unsigned int rowIndex = 0; + + for (CurveMapType::const_iterator pos = m_InputDataPlotCurves.begin(); + pos != m_InputDataPlotCurves.end(); ++pos, ++rowIndex) + { + QColor dataColor; + + if (pos->first == "ROI") + { + dataColor = QColor(0, 190, 0); + } + else + { + //Use HSV schema of QColor to calculate a different color depending on the + //number of already existing free iso lines. + dataColor.setHsv(((rowIndex + 1) * 85) % 360, 255, 255); + } + + QTableWidgetItem* newItem = new QTableWidgetItem(QString::fromStdString(pos->first)); + m_Controls.tableInputData->setItem(rowIndex, 0, newItem); + newItem = new QTableWidgetItem(); + newItem->setBackgroundColor(dataColor); + m_Controls.tableInputData->setItem(rowIndex, 1, newItem); + } + } + + m_Controls.lInfo->setText(QString::fromStdString(infoOutput.str())); +} + +void ModelFitInspectorView::RenderPlot() +{ + m_Controls.widgetPlot->Clear(); + + std::string xAxis = "Time [s]"; + std::string yAxis = "Intensity"; + std::string plotTitle = "Raw data plot: no data"; + + if (m_currentSelectedNode.IsNotNull()) + { + plotTitle = "Raw data plot: " + m_currentSelectedNode->GetName(); + } + + if (m_currentFit.IsNotNull()) + { + plotTitle = m_currentFit->modelName.c_str(); + xAxis = m_currentFit->xAxisName; + + if (!m_currentFit->xAxisUnit.empty()) + { + xAxis += " [" + m_currentFit->xAxisUnit + "]"; + } + + yAxis = m_currentFit->yAxisName; + + if (!m_currentFit->yAxisUnit.empty()) + { + yAxis += " [" + m_currentFit->yAxisUnit + "]"; + } + } + + m_Controls.widgetPlot->SetAxisTitle(QwtPlot::xBottom, xAxis.c_str()); + m_Controls.widgetPlot->SetAxisTitle(QwtPlot::yLeft, yAxis.c_str()); + m_Controls.widgetPlot->SetPlotTitle(plotTitle.c_str()); + + // Draw input data points + unsigned int colorIndex = 0; + + for (CurveMapType::const_iterator pos = m_InputDataPlotCurves.begin(); + pos != m_InputDataPlotCurves.end(); ++pos) + { + QColor dataColor; + + unsigned int curveId = m_Controls.widgetPlot->InsertCurve(pos->first.c_str()); + m_Controls.widgetPlot->SetCurveData(curveId, pos->second); + + if (pos->first == "ROI") + { + dataColor = QColor(0, 190, 0); + QPen pen; + pen.setColor(dataColor); + pen.setStyle(Qt::SolidLine); + m_Controls.widgetPlot->SetCurvePen(curveId, pen); + } + else + { + //Use HSV schema of QColor to calculate a different color depending on the + //number of already existing free iso lines. + dataColor.setHsv((++colorIndex * 85) % 360, 255, 150); + m_Controls.widgetPlot->SetCurvePen(curveId, QPen(Qt::NoPen)); + } + + // QwtSymbol needs to passed as a real pointer from MITK v2013.09.0 on + // (QwtPlotCurve deletes it on destruction and assignment). + QwtSymbol* dataSymbol = new QwtSymbol(QwtSymbol::Triangle, dataColor, dataColor, + QSize(8, 8)); + m_Controls.widgetPlot->SetCurveSymbol(curveId, dataSymbol); + + // Again, there is no way to set a curve's legend attributes via QmitkPlotWidget so this + // gets unnecessarily complicated. + QwtPlotCurve* measurementCurve = dynamic_cast(m_Controls.widgetPlot-> + GetPlot()->itemList(QwtPlotItem::Rtti_PlotCurve).back()); + measurementCurve->setLegendAttribute(QwtPlotCurve::LegendShowSymbol); + measurementCurve->setLegendIconSize(QSize(8, 8)); + } + + // Draw image points + if (!m_ImagePlotCurve.empty()) + { + unsigned int curveId = m_Controls.widgetPlot->InsertCurve("measurement"); + m_Controls.widgetPlot->SetCurveData(curveId, m_ImagePlotCurve); + m_Controls.widgetPlot->SetCurvePen(curveId, QPen(Qt::NoPen)); + + // QwtSymbol needs to passed as a real pointer from MITK v2013.09.0 on + // (QwtPlotCurve deletes it on destruction and assignment). + QwtSymbol* redSymbol = new QwtSymbol(QwtSymbol::Diamond, QColor(Qt::red), QColor(Qt::red), + QSize(8, 8)); + m_Controls.widgetPlot->SetCurveSymbol(curveId, redSymbol); + + // Again, there is no way to set a curve's legend attributes via QmitkPlotWidget so this + // gets unnecessarily complicated. + QwtPlotCurve* measurementCurve = dynamic_cast(m_Controls.widgetPlot-> + GetPlot()->itemList(QwtPlotItem::Rtti_PlotCurve).back()); + measurementCurve->setLegendAttribute(QwtPlotCurve::LegendShowSymbol); + measurementCurve->setLegendIconSize(QSize(8, 8)); + + // Highlight the current time step + unsigned int timestep = m_renderWindowPart->GetTimeNavigationController()->GetTime()-> + GetPos(); + + if (timestep < m_ImagePlotCurve.size()) + { + QwtSymbol* blueSymbol = new QwtSymbol(QwtSymbol::Diamond, QColor(Qt::blue), + QColor(Qt::blue), QSize(8, 8)); + QwtPlotMarker* marker = new QwtPlotMarker(); + marker->setSymbol(blueSymbol); + marker->setValue(m_ImagePlotCurve[timestep].first, m_ImagePlotCurve[timestep].second); + marker->attach(m_Controls.widgetPlot->GetPlot()); + } + + for (QmitkPlotWidget::XYDataVector::size_type i = 0; i < m_ImagePlotCurve.size(); ++i) + { + m_Controls.tableData->item(i, 1)->setText(QString::number(m_ImagePlotCurve[i].second)); + } + } + + //draw model curve + if (!m_ModelPlotCurve.empty()) + { + QPen pen; + pen.setColor(QColor(Qt::black)); + pen.setWidth(2); + unsigned int curveId = m_Controls.widgetPlot->InsertCurve("fit"); + m_Controls.widgetPlot->SetCurveData(curveId, m_ModelPlotCurve); + m_Controls.widgetPlot->SetCurvePen(curveId, pen); + + // Manually set the legend attribute to use the symbol as the legend icon and alter its + // size. Otherwise it would revert to default which is drawing a square which is the color + // of the curve's pen, so in this case none which defaults to black. + // Unfortunately, QmitkPlotWidget offers no way to set the legend attribute and icon size so + // this looks a bit hacky. + QwtPlotCurve* fitCurve = dynamic_cast(m_Controls.widgetPlot->GetPlot()-> + itemList(QwtPlotItem::Rtti_PlotCurve).back()); + fitCurve->setLegendAttribute(QwtPlotCurve::LegendShowLine); + + for (QmitkPlotWidget::XYDataVector::size_type i = 0; i < m_ImagePlotCurve.size(); ++i) + { + m_Controls.tableData->item(i, 2)->setText(QString::number(m_ModelPlotCurve[i * + INTERPOLATION_STEPS].second)); + } + } + + QwtLegend* legend = new QwtLegend(); + legend->setFrameShape(QFrame::Box); + legend->setFrameShadow(QFrame::Sunken); + legend->setLineWidth(1); + m_Controls.widgetPlot->SetLegend(legend, QwtPlot::BottomLegend); + + m_Controls.widgetPlot->Replot(); +} + +void ModelFitInspectorView::InitDataTable() +{ + QStringList headers; + headers.push_back(QString("Time")); + headers.push_back(QString("Input image")); + + if (!this->m_ModelPlotCurve.empty()) + { + headers.push_back(QString("Model")); + } + + for (CurveMapType::const_iterator pos = this->m_InputDataPlotCurves.begin(); + pos != this->m_InputDataPlotCurves.end(); ++pos) + { + headers.push_back(QString::fromStdString(pos->first)); + } + + m_Controls.tableData->setRowCount(m_ImagePlotCurve.size()); + m_Controls.tableData->setColumnCount(headers.size()); + + m_Controls.tableData->setHorizontalHeaderLabels(headers); + m_Controls.tableData->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); + + for (QmitkPlotWidget::XYDataVector::size_type i = 0; i < m_ImagePlotCurve.size(); ++i) + { + int column = 0; + QTableWidgetItem* newItem = new QTableWidgetItem(QString::number(m_ImagePlotCurve[i].first)); + m_Controls.tableData->setItem(i, column++, newItem); + newItem = new QTableWidgetItem(QString::number(m_ImagePlotCurve[i].second)); + m_Controls.tableData->setItem(i, column++, newItem); + + if (!m_ModelPlotCurve.empty()) + { + newItem = new QTableWidgetItem(QString::number(m_ModelPlotCurve[i * INTERPOLATION_STEPS].second)); + m_Controls.tableData->setItem(i, column++, newItem); + } + + for (CurveMapType::const_iterator pos = this->m_InputDataPlotCurves.begin(); + pos != this->m_InputDataPlotCurves.end(); ++pos, ++column) + { + newItem = new QTableWidgetItem(QString::number(pos->second[i].second)); + m_Controls.tableData->setItem(i, column, newItem); + } + } +} + + +void ModelFitInspectorView::OnClipboardResultsButtonClicked() +{ + QLocale tempLocal; + QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); + std::stringstream infoOutput; + QString clipboard; + QVector< QVector > resultsTable; + if (m_currentFit.IsNotNull()) + { + int rowNumber = m_currentFit->GetParameters().size() + m_currentFit->staticParamMap.Size(); + + // set headline as in results table: "Name", "Value", "Type" + QStringList headlineText; + QVector headline; + // Create Headline + headlineText << "Name" << "Value" << "Type"; + + for (int i = 0; i < headlineText.size(); i++) + { + headline.append(headlineText.at(i)); + } + resultsTable.append(headline); + + // fill table with values from the displayed results table + for (int i = 0; i < rowNumber; i++) + { + QVector rowValues; + for (int j = 0; j < 3; j++) + { + rowValues.append((m_Controls.tableResults->item(i, j)->text())); + + } + resultsTable.append(rowValues); + + } + + // Create output string for clipboard + for (int i = 0; i < resultsTable.size(); i++) + { + for (int t = 0; t < resultsTable.at(i).size(); t++) + { + clipboard.append(resultsTable.at(i).at(t)); + clipboard.append("\t"); + } + clipboard.append("\n"); + } + QApplication::clipboard()->setText(clipboard, QClipboard::Clipboard); + } + else + { + infoOutput << "Results table is empty."; + } + QLocale::setDefault(tempLocal); +} diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.h b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.h new file mode 100644 index 0000000000..6b57146539 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorView.h @@ -0,0 +1,232 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef ModelFitInspectorView_h +#define ModelFitInspectorView_h + +// Blueberry +//#include +#include + +// mitk +#include +#include + +#include "mitkModelFitStaticParameterMap.h" +#include "mitkModelParameterizerBase.h" +#include "mitkModelFitInfo.h" +#include "mitkIModelFitProvider.h" + +// Qt +#include "ui_ModelFitInspectorViewControls.h" + + +/** + * @brief View class defining the UI part of the ModelFitInspector plug-in. + */ +class ModelFitInspectorView : + public QmitkAbstractView, + public mitk::IRenderWindowPartListener +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + +public: + + ModelFitInspectorView(); + ~ModelFitInspectorView(); + + static const std::string VIEW_ID; + +protected slots: + + /** + * @brief Triggered when the selection of the "Modelfit" combo box changes. + * Sets the selected fit as the current one. + * @param index The index (in the combo box) of the selected item. + */ + void OnFitSelectionChanged(int index); + + /** + * @brief Triggered when the voxel or time step selection changes. + * Calculates the curve and points for the current fit if the visualization is running. + */ + void OnSliceChangedDelayed(); + + /** Triggered when the selection of "fixed" y axis scaling changes*/ + void OnScaleFixedYChecked(bool checked); + void OnScaleToDataYClicked(); + void OnFixedScalingYChanged(double value); + + + /** Triggered when the selection of "fixed" x axis scaling changes*/ + void OnScaleFixedXChecked(bool checked); + void OnScaleToDataXClicked(); + void OnFixedScalingXChanged(double value); + + void OnExportClicked(); + + + /** @brief Saves the results table to clipboard */ + void OnClipboardResultsButtonClicked(); + + +protected: + + virtual void CreateQtPartControl(QWidget* parent); + + virtual void SetFocus(); + + /** @brief called by QmitkFunctionality when DataManager's selection has changed */ + virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, + const QList& nodes); + + /** @brief Calls OnSliceChangedDelayed so the event isn't triggered multiple times. */ + void OnSliceChanged(const itk::EventObject& e); + + void OnSliceNavigationControllerDeleted(const itk::Object* sender, const itk::EventObject& /*e*/); + + virtual void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart); + virtual void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart); + + /** Initializes and sets the observers that are used to monitor changes in the selected position + or time point in order to actualize the view.h*/ + bool InitObservers(); + void RemoveObservers(const mitk::SliceNavigationController* deletedSlicer); + /** Removes all observers of the deletedPart. If null pointer is passed all observers will be removed.*/ + void RemoveAllObservers(mitk::IRenderWindowPart* deletedPart = NULL); + + /** + * @brief Calculates the curve data using the current fit's model and parameterizer. + * @param position Indicating the point in the input image for which the model curve should be calculated. + * @return A vector of points for the curve data. + */ + QmitkPlotWidget::XYDataVector CalcCurveFromModel(const mitk::Point3D& position); + + /** + * @brief Calculates the curve data using the current fit's function string. + * @param timeGrid The time grid containing the (interpolated) x values for the curve data. + * @return A vector of points for the curve data. + */ + QmitkPlotWidget::XYDataVector CalcCurveFromFunction(const mitk::Point3D& position, + const mitk::ModelBase::TimeGridType& + timeGrid); + + /** + * @brief Returns the parent node of the given node if it exists. + * @param node The node whose parent node should be returned. + * @return The parent node of the given node or NULL if it doesn't exist. + */ + mitk::DataNode::ConstPointer GetParentNode(mitk::DataNode::ConstPointer node); + + /** Super sample passed time grid with the factor INTERPOLATION_STEPS and interpolates linear in between.*/ + mitk::ModelBase::TimeGridType GenerateInterpolatedTimeGrid(const mitk::ModelBase::TimeGridType& + grid) const; + + /** Sets m_currentSelectedPosition to the current selection and validates if this position is valid + * for the input image of the currently selected fit. If it is valid, m_validSelectedPosition is set to true. + * If the fit, his input image or geometry is not specified, it will also handled as invalid.*/ + void ValidateAndSetCurrentPosition(); + + /** Returns the current input image. If a current fit is set it will be its input image. + * Otherwise it will be the image stored in the currently selected node. If the node is not set, contains no image + * or the image is not 4D, NULL will be returned.*/ + mitk::Image::Pointer GetCurrentInputImage() const; + + /** Returns the variable/time grid of the GetCurrentInputImage(). If a model fit is selected its provider will be used + to get the correct grid, otherwise just a simple time grid will be extracted.*/ + const mitk::ModelBase::TimeGridType GetCurrentTimeGrid() const; + + Ui::ModelFitInspectorViewControls m_Controls; + mitk::IRenderWindowPart* m_renderWindowPart; + + // Needed for observing the events for when a slice or time step is changed. + bool m_PendingSliceChangedEvent; + + /**Helper structure to manage the registered observer events.*/ + struct ObserverInfo + { + mitk::SliceNavigationController* controller; + int observerTag; + std::string renderWindowName; + mitk::IRenderWindowPart* renderWindowPart; + + ObserverInfo(mitk::SliceNavigationController* controller, int observerTag, + const std::string& renderWindowName, mitk::IRenderWindowPart* part); + }; + + typedef std::multimap ObserverMapType; + ObserverMapType m_ObserverMap; + + /** @brief Is a visualization currently running? */ + bool m_internalUpdateFlag; + /** @brief List of modelfits currently in the data manager */ + typedef std::map + ModelFitInfoListType; + ModelFitInfoListType m_modelfitList; + /** @brief The currently selected modelfit */ + mitk::modelFit::ModelFitInfo::ConstPointer m_currentFit; + + /** @brief Pointer to the instance of the model parameterizer for the current fit */ + mitk::ModelParameterizerBase::Pointer m_currentModelParameterizer; + mitk::IModelFitProvider* m_currentModelProviderService; + + /** @brief currently valid selected position in the inspector*/ + mitk::Point3D m_currentSelectedPosition; + /** @brief indicates if the currently selected position is valid for the currently selected fit. + * This it is within the input image */ + bool m_validSelectedPosition; + + /** @brief currently selected time step of the selected node for the visualization logic*/ + unsigned int m_currentSelectedTimeStep; + + /** @brief currently selected node for the visualization logic*/ + mitk::DataNode::ConstPointer m_currentSelectedNode; + + /** @brief Number of interpolation steps between two x values */ + static const unsigned int INTERPOLATION_STEPS; + + /*************************************/ + /* Members for visualizing the model */ + + itk::TimeStamp m_selectedNodeTime; + itk::TimeStamp m_currentFitTime; + itk::TimeStamp m_currentPositionTime; + itk::TimeStamp m_lastRefreshTime; + + QmitkPlotWidget::XYDataVector m_ImagePlotCurve; + QmitkPlotWidget::XYDataVector m_ModelPlotCurve; + + typedef std::map CurveMapType; + CurveMapType m_InputDataPlotCurves; + + /** Check and updates the plot data if needed. + * @return indicates if something was refreshed (true)*/ + bool RefreshPlotData(); + + + void RenderPlot(); + void RenderFitInfo(); + + /** (re)initializes the headers of the data table*/ + void InitDataTable(); + + +}; + +#endif // ModelFitInspectorView_h diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorViewControls.ui b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorViewControls.ui new file mode 100644 index 0000000000..fb53fa3ea7 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/ModelFitInspectorViewControls.ui @@ -0,0 +1,784 @@ + + + ModelFitInspectorViewControls + + + + 0 + 0 + 349 + 843 + + + + + 0 + 0 + + + + QmitkTemplate + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + Modelfit: + + + + + + + + + + true + + + + 0 + 0 + + + + + 0 + 400 + + + + + + + + + + + + + + + true + + + 1 + + + + Fit info + + + + + + + 50 + 16777215 + + + + Fit type + + + + + + + + 0 + 0 + + + + + + + + + + + Fit uid: + + + + + + + + 0 + 0 + + + + + + + + + + + Model name: + + + + + + + Model type: + + + + + + + + + + + + + + + + + + + + + + Results + + + Information of the fit + + + + 3 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + Parameters + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 8 + + + + QAbstractItemView::NoEditTriggers + + + false + + + QAbstractItemView::NoSelection + + + true + + + 110 + + + false + + + true + + + true + + + false + + + 20 + + + 20 + + + + Name + + + + + + + + Value + + + + + + + + Type + + + + + + + + + + + + + Copy to Clipboard + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + View settings + + + Settings for the visualization of fittings + + + + + + X-axis scaling: + + + + + + true + + + automatic + + + true + + + + + + + true + + + fixed + + + false + + + + + + + + + false + + + + 40 + 16777215 + + + + min: + + + + + + + false + + + -9999.000000000000000 + + + 9999.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + 40 + 16777215 + + + + max: + + + + + + + false + + + -9999.000000000000000 + + + 9999.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Sets the min and max to the current range of data +-10% + + + Scale to data + + + + + + + + + + + + Y-axis scaling: + + + + + + true + + + automatic + + + true + + + + + + + true + + + fixed + + + false + + + + + + + + + false + + + + 40 + 16777215 + + + + min: + + + + + + + false + + + -9999.000000000000000 + + + 9999.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + 40 + 16777215 + + + + max: + + + + + + + false + + + -9999.000000000000000 + + + 9999.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Sets the min and max to the current range of data +-10% + + + Scale to data + + + + + + + + + + + + Additional input data visibility: + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 8 + + + + 150 + + + false + + + true + + + false + + + 20 + + + 20 + + + + Name + + + + + + + + Color + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Data / Export + + + Export options for the current data/fitting information + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + Export to csv file + + + + + + + + 80 + 0 + + + + true + + + 45 + + + true + + + + + + + + + + + + + QmitkPlotWidget + QWidget +
    QmitkPlotWidget.h
    +
    +
    + + + + radioScaleFixed + clicked(bool) + sbFixMin + setEnabled(bool) + + + 66 + 528 + + + 86 + 559 + + + + + radioScaleFixed + clicked(bool) + sbFixMax + setEnabled(bool) + + + 208 + 535 + + + 195 + 559 + + + + + radioScaleFixed + clicked(bool) + btnScaleToData + setEnabled(bool) + + + 299 + 530 + + + 292 + 557 + + + + +
    diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/org_mitk_gui_qt_fit_inspector_Activator.cpp b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/org_mitk_gui_qt_fit_inspector_Activator.cpp new file mode 100644 index 0000000000..666ee04f11 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/org_mitk_gui_qt_fit_inspector_Activator.cpp @@ -0,0 +1,55 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#include "org_mitk_gui_qt_fit_inspector_Activator.h" + +#include "ModelFitInspectorView.h" +#include "mitkModelFitConstants.h" + +#include +#include +#include +#include + +void org_mitk_gui_qt_fit_inspector_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(ModelFitInspectorView, context) + + QmitkNodeDescriptorManager* manager = QmitkNodeDescriptorManager::GetInstance(); + + mitk::StringProperty::Pointer parameterProp = mitk::StringProperty::New(mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_PARAMETER().c_str()); + mitk::NodePredicateProperty::Pointer isModelFitParameter = mitk::NodePredicateProperty::New(mitk::ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(), parameterProp); + manager->AddDescriptor(new QmitkNodeDescriptor(tr("Image"), QString(":/ModelFitVisualization/parameter_image.png"), isModelFitParameter, manager)); + + mitk::StringProperty::Pointer derivedProp = mitk::StringProperty::New(mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_DERIVED_PARAMETER().c_str()); + mitk::NodePredicateProperty::Pointer isModelFitDerived = mitk::NodePredicateProperty::New(mitk::ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(), derivedProp); + manager->AddDescriptor(new QmitkNodeDescriptor(tr("Image"), QString(":/ModelFitVisualization/derived_image.png"), isModelFitDerived, manager)); + + mitk::StringProperty::Pointer criterionProp = mitk::StringProperty::New(mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_CRITERION().c_str()); + mitk::NodePredicateProperty::Pointer isModelFitCriterion = mitk::NodePredicateProperty::New(mitk::ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(), criterionProp); + manager->AddDescriptor(new QmitkNodeDescriptor(tr("Image"), QString(":/ModelFitVisualization/criterion_image.png"), isModelFitCriterion, manager)); + + mitk::StringProperty::Pointer evalProp = mitk::StringProperty::New(mitk::ModelFitConstants::PARAMETER_TYPE_VALUE_EVALUATION_PARAMETER().c_str()); + mitk::NodePredicateProperty::Pointer isModelFitEvaluation = mitk::NodePredicateProperty::New(mitk::ModelFitConstants::PARAMETER_TYPE_PROPERTY_NAME().c_str(), evalProp); + manager->AddDescriptor(new QmitkNodeDescriptor(tr("Image"), QString(":/ModelFitVisualization/eval_image.png"), isModelFitEvaluation, manager)); + + } + + void org_mitk_gui_qt_fit_inspector_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context) + } diff --git a/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/org_mitk_gui_qt_fit_inspector_Activator.h b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/org_mitk_gui_qt_fit_inspector_Activator.h new file mode 100644 index 0000000000..ad2d19a956 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.fit.inspector/src/internal/org_mitk_gui_qt_fit_inspector_Activator.h @@ -0,0 +1,36 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef org_mitk_gui_qt_fit_inspector_Activator_h +#define org_mitk_gui_qt_fit_inspector_Activator_h + +#include + + + class org_mitk_gui_qt_fit_inspector_Activator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_guit_qt_fit_inspector") + Q_INTERFACES(ctkPluginActivator) + public: + + void start(ctkPluginContext* context); + void stop(ctkPluginContext* context); + + }; // org_mitk_modelfit_visualization_Activator + +#endif // org_mitk_modelfit_visualization_Activator_h diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/CMakeLists.txt b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/CMakeLists.txt new file mode 100644 index 0000000000..840fc6a0da --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/CMakeLists.txt @@ -0,0 +1,9 @@ +project(org_mitk_gui_qt_pharmacokinetics_concentration_mri) + +mitk_create_plugin( + EXPORT_DIRECTIVE CONCENTRATIONCURVECONVERTER_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkPharmacokinetics + PACKAGE_DEPENDS ITK|ITKOptimizers + +) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..8bb4491add --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/documentation/UserManual/Manual.dox @@ -0,0 +1,10 @@ +/** +\page org_mitk_gui_qt_pharmacokinetics_concentration_mri The Concentration Curve Converter View + +\li \ref org_mitk_gui_qt_pharmacokinetics_concentration_mri_Introduction + +\section org_mitk_gui_qt_pharmacokinetics_concentration_mri_Introduction Introduction +This view offers the to posibility to convert MRI image signals into concentration images. +Theses concentration images can e.g. be used for perfusion model fitting. + +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..571345107f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_concentration_mri org.mitk.gui.qt.pharmacokinetics.concentration.mri + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_concentration_mri_internal Internal + \ingroup org_mitk_gui_qt_pharmacokinetics_concentration_mri + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.pharmacokinetics.concentration.mri plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/files.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/files.cmake new file mode 100644 index 0000000000..17c9dffd99 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/files.cmake @@ -0,0 +1,42 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_ConcentrationCurveConverterView_Activator.cpp + ConcentrationCurveConverterView.cpp +) + +set(UI_FILES + src/internal/ConcentrationCurveConverterViewControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_ConcentrationCurveConverterView_Activator.h + src/internal/ConcentrationCurveConverterView.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/Convert.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/manifest_headers.cmake new file mode 100644 index 0000000000..2266f968b7 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Concentration Curve Converter Plugin") +set(Plugin-Version "1.0") +set(Plugin-Vendor "DKFZ, Software Development For Integrated Diagnostics and Therapy") +set(Plugin-ContactAddress "c.debus@dkfz.de") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/plugin.xml b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/plugin.xml new file mode 100644 index 0000000000..fead26d528 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/resources/Convert.png b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/resources/Convert.png new file mode 100644 index 0000000000..5c18097572 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/resources/Convert.png differ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.cpp new file mode 100644 index 0000000000..829114a84c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.cpp @@ -0,0 +1,401 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include "mitkWorkbenchUtil.h" + +#include "ConcentrationCurveConverterView.h" +#include "mitkConcentrationCurveGenerator.h" +#include "mitkNodePredicateDataType.h" +#include "mitkConvertToConcentrationTurboFlashFunctor.h" +#include "mitkConvertToConcentrationAbsoluteFunctor.h" +#include "mitkConvertToConcentrationRelativeFunctor.h" +#include "itkBinaryFunctorImageFilter.h" + + + +// Includes for image casting between ITK and MITK +#include "mitkImageTimeSelector.h" +#include "mitkImageCast.h" +#include "mitkITKImageImport.h" +#include + +#include + +const std::string ConcentrationCurveConverterView::VIEW_ID = "org.mitk.ConcentrationCurveConverterView"; + +void ConcentrationCurveConverterView::SetFocus() +{ + m_Controls.btnConvertToConcentration->setFocus(); +} + +void ConcentrationCurveConverterView::CreateQtPartControl(QWidget* parent) +{ + m_Controls.setupUi(parent); + m_Controls.btnConvertToConcentration->setEnabled(false); + + connect(m_Controls.btnConvertToConcentration, SIGNAL(clicked()), this, SLOT(OnConvertToConcentrationButtonClicked())); + + m_Controls.groupBox_T1->hide(); + m_Controls.groupBox_T2->hide(); + m_Controls.groupBox3D->hide(); + m_Controls.groupBox4D->hide(); + m_Controls.groupBoxTurboFlash->hide(); + m_Controls.factorSpinBox->setEnabled(false); + m_Controls.groupBox_ConcentrationParameters->hide(); + + connect(m_Controls.radioButton_T1, SIGNAL(toggled(bool)),this, SLOT(OnSettingChanged())); + connect(m_Controls.radioButton_T2, SIGNAL(toggled(bool)),this, SLOT(OnSettingChanged())); + + connect(m_Controls.radioButton3D, SIGNAL(toggled(bool)),this, SLOT(OnSettingChanged())); + connect(m_Controls.radioButton4D, SIGNAL(toggled(bool)),this, SLOT(OnSettingChanged())); + + connect(m_Controls.radioButtonTurboFlash, SIGNAL(toggled(bool)), m_Controls.groupBoxTurboFlash, + SLOT(setVisible(bool))); + + connect(m_Controls.radioButtonTurboFlash, SIGNAL(toggled(bool)), this, + SLOT(OnSettingChanged())); + connect(m_Controls.relaxationTime, SIGNAL(valueChanged(double)), this, + SLOT(OnSettingChanged())); + connect(m_Controls.recoveryTime, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged())); + connect(m_Controls.relaxivity, SIGNAL(valueChanged(double)), this, SLOT(OnSettingChanged())); + + connect(m_Controls.radioButton_absoluteEnhancement, SIGNAL(toggled(bool)), this, + SLOT(OnSettingChanged())); + connect(m_Controls.radioButton_relativeEnchancement, SIGNAL(toggled(bool)), this, + SLOT(OnSettingChanged())); + connect(m_Controls.radioButton_absoluteEnhancement, SIGNAL(toggled(bool)), m_Controls.factorSpinBox, + SLOT(setEnabled(bool))); + connect(m_Controls.radioButton_relativeEnchancement, SIGNAL(toggled(bool)), + m_Controls.factorSpinBox, + SLOT(setEnabled(bool))); + connect(m_Controls.factorSpinBox, SIGNAL(valueChanged(double)), this, + SLOT(OnSettingChanged())); + +} + + +void ConcentrationCurveConverterView::OnSettingChanged() +{ + bool ok = true; + m_Controls.groupBox_T1->setVisible(m_Controls.radioButton_T1->isChecked()); + m_Controls.groupBox_T2->setVisible(m_Controls.radioButton_T2->isChecked()); + + if(m_Controls.radioButton_T1->isChecked()) + { + m_Controls.groupBox_ConcentrationParameters->setVisible(true); + m_Controls.groupBox3D->setVisible(m_Controls.radioButton3D->isChecked()); + m_Controls.groupBox4D->setVisible(m_Controls.radioButton4D->isChecked()); + + if(m_Controls.radioButton4D->isChecked()) + { + ok = m_selectedImage.IsNotNull() && CheckSettings(); + } + else if(m_Controls.radioButton3D->isChecked()) + { + ok = m_selectedImage.IsNotNull() && m_selectedBaselineImage.IsNotNull() && CheckSettings(); + + } + } + else if (m_Controls.radioButton_T2->isChecked()) + { + m_Controls.groupBox_ConcentrationParameters->setVisible(false); + + ok = m_selectedImage.IsNotNull() && CheckSettings(); + + } + + m_Controls.btnConvertToConcentration->setEnabled(ok); +} + + +bool ConcentrationCurveConverterView::CheckSettings() const +{ + bool ok = true; + + if(m_Controls.radioButton_T1->isChecked()) + { + if (this->m_Controls.radioButtonTurboFlash->isChecked()) + { + ok = ok && (m_Controls.recoveryTime->value() > 0); + ok = ok && (m_Controls.relaxationTime->value() > 0); + ok = ok && (m_Controls.relaxivity->value() > 0); + + } + else if (this->m_Controls.radioButton_absoluteEnhancement->isChecked() + || this->m_Controls.radioButton_relativeEnchancement->isChecked()) + { + ok = ok && (m_Controls.factorSpinBox->value() > 0); + } + else + { + ok = false; + } + } + else if (this->m_Controls.radioButton_T2->isChecked()) + { + ok = ok && m_Controls.T2EchoTimeSpinBox->value() > 0; + ok = ok && m_Controls.T2FactorSpinBox->value() > 0; + } + else + { + ok=false; + } + + + return ok; +} + +void ConcentrationCurveConverterView::OnConvertToConcentrationButtonClicked() +{ + + mitk::Image::Pointer concentrationImage; + mitk::DataNode::Pointer concentrationNode; + + if(m_Controls.radioButton_T1->isChecked()) + { + if(m_Controls.radioButton4D->isChecked()) + { + concentrationImage = this->Convert4DConcentrationImage(this->m_selectedImage); + } + else if(m_Controls.radioButton3D->isChecked()) + { + concentrationImage = Convert3DConcentrationImage(this->m_selectedImage, this->m_selectedBaselineImage); + } + } + else if(m_Controls.radioButton_T2->isChecked()) + { + concentrationImage = this->ConvertT2ConcentrationImgage(this->m_selectedImage); + } + std::string nameOfResultImage = m_selectedNode->GetName(); + nameOfResultImage.append("_Concentration"); + + concentrationNode = AddConcentrationImage(concentrationImage,nameOfResultImage); + +} + + +mitk::Image::Pointer ConcentrationCurveConverterView::Convert3DConcentrationImage(mitk::Image::Pointer inputImage,mitk::Image::Pointer baselineImage) + { + typedef itk::Image InputImageType; + + InputImageType::Pointer itkInputImage = InputImageType::New(); + InputImageType::Pointer itkBaselineImage = InputImageType::New(); + + mitk::CastToItkImage(inputImage, itkInputImage ); + mitk::CastToItkImage(baselineImage, itkBaselineImage ); + + + mitk::Image::Pointer outputImage; + + if(this->m_Controls.radioButtonTurboFlash->isChecked()) + { + typedef mitk::ConvertToConcentrationTurboFlashFunctor ConversionFunctorTurboFlashType; + typedef itk::BinaryFunctorImageFilter FilterTurboFlashType; + + ConversionFunctorTurboFlashType ConversionTurboFlashFunctor; + ConversionTurboFlashFunctor.initialize(m_Controls.relaxationTime->value(), m_Controls.relaxivity->value(), m_Controls.recoveryTime->value()); + + FilterTurboFlashType::Pointer ConversionTurboFlashFilter = FilterTurboFlashType::New(); + + ConversionTurboFlashFilter->SetFunctor(ConversionTurboFlashFunctor); + ConversionTurboFlashFilter->SetInput1(itkInputImage); + ConversionTurboFlashFilter->SetInput2(itkBaselineImage); + + ConversionTurboFlashFilter->Update(); + outputImage = mitk::ImportItkImage(ConversionTurboFlashFilter->GetOutput())->Clone(); + + + } + else if(this->m_Controls.radioButton_absoluteEnhancement->isChecked()) + { + typedef mitk::ConvertToConcentrationAbsoluteFunctor ConversionFunctorAbsoluteType; + typedef itk::BinaryFunctorImageFilter FilterAbsoluteType; + + ConversionFunctorAbsoluteType ConversionAbsoluteFunctor; + ConversionAbsoluteFunctor.initialize(m_Controls.factorSpinBox->value()); + + FilterAbsoluteType::Pointer ConversionAbsoluteFilter = FilterAbsoluteType::New(); + + ConversionAbsoluteFilter->SetFunctor(ConversionAbsoluteFunctor); + ConversionAbsoluteFilter->SetInput1(itkInputImage); + ConversionAbsoluteFilter->SetInput2(itkBaselineImage); + + ConversionAbsoluteFilter->Update(); + + outputImage = mitk::ImportItkImage(ConversionAbsoluteFilter->GetOutput())->Clone(); + } + + else if(m_Controls.radioButton_relativeEnchancement->isChecked()) + { + typedef mitk::ConvertToConcentrationRelativeFunctor ConversionFunctorRelativeType; + typedef itk::BinaryFunctorImageFilter FilterRelativeType; + + ConversionFunctorRelativeType ConversionRelativeFunctor; + ConversionRelativeFunctor.initialize(m_Controls.factorSpinBox->value()); + + FilterRelativeType::Pointer ConversionRelativeFilter = FilterRelativeType::New(); + + ConversionRelativeFilter->SetFunctor(ConversionRelativeFunctor); + ConversionRelativeFilter->SetInput1(itkInputImage); + ConversionRelativeFilter->SetInput2(itkBaselineImage); + + ConversionRelativeFilter->Update(); + + outputImage = mitk::ImportItkImage(ConversionRelativeFilter->GetOutput())->Clone(); + } + + + + return outputImage; +} + + +mitk::DataNode::Pointer ConcentrationCurveConverterView::AddConcentrationImage(mitk::Image* image, std::string nodeName) const +{ + if (!image) + { + mitkThrow() << "Cannot generate concentration node. Passed image is null. parameter name: "; + } + + mitk::DataNode::Pointer result = mitk::DataNode::New(); + + result->SetData(image); + + result->SetName(nodeName); + + result->SetVisibility(true); + + + this->GetDataStorage()->Add(result, m_selectedNode); + + return result; +}; + + +mitk::Image::Pointer ConcentrationCurveConverterView::Convert4DConcentrationImage(mitk::Image::Pointer inputImage) +{ + //Compute Concentration image + mitk::ConcentrationCurveGenerator::Pointer concentrationGen = + mitk::ConcentrationCurveGenerator::New(); + concentrationGen->SetDynamicImage(inputImage); + + concentrationGen->SetisTurboFlashSequence(m_Controls.radioButtonTurboFlash->isChecked()); + concentrationGen->SetAbsoluteSignalEnhancement(m_Controls.radioButton_absoluteEnhancement->isChecked()); + concentrationGen->SetRelativeSignalEnhancement(m_Controls.radioButton_relativeEnchancement->isChecked()); + + concentrationGen->SetisT2weightedImage(false); + + if (m_Controls.radioButtonTurboFlash->isChecked()) + { + concentrationGen->SetRecoveryTime(m_Controls.recoveryTime->value()); + concentrationGen->SetRelaxationTime(m_Controls.relaxationTime->value()); + concentrationGen->SetRelaxivity(m_Controls.relaxivity->value()); + } + + else + { + concentrationGen->SetFactor(m_Controls.factorSpinBox->value()); + } + + mitk::Image::Pointer concentrationImage = concentrationGen->GetConvertedImage(); + + return concentrationImage; +} + + +mitk::Image::Pointer ConcentrationCurveConverterView::ConvertT2ConcentrationImgage(mitk::Image::Pointer inputImage) +{ + //Compute Concentration image + mitk::ConcentrationCurveGenerator::Pointer concentrationGen = + mitk::ConcentrationCurveGenerator::New(); + concentrationGen->SetDynamicImage(inputImage); + + concentrationGen->SetisTurboFlashSequence(false); + concentrationGen->SetAbsoluteSignalEnhancement(false); + concentrationGen->SetRelativeSignalEnhancement(false); + + concentrationGen->SetisT2weightedImage(true); + + + concentrationGen->SetT2Factor(m_Controls.T2FactorSpinBox->value()); + concentrationGen->SetT2EchoTime(m_Controls.T2EchoTimeSpinBox->value()); + + + mitk::Image::Pointer concentrationImage = concentrationGen->GetConvertedImage(); + + return concentrationImage; +} + +void ConcentrationCurveConverterView::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/,const QList& selectedNodes ){ + + m_selectedNode = NULL; + m_selectedImage = NULL; + m_selectedBaselineNode = NULL; + m_selectedBaselineImage = NULL; + + m_Controls.timeserieslabel->setText("No (valid) series selected."); + m_Controls.BaselineImageLabel->setText("No (valid) baseline image selected."); + m_Controls.ImageLabel->setText("No (valid) image selected."); + m_Controls.T2_SeriesLabel->setText("No (valid) series selected."); + + m_Controls.btnConvertToConcentration->setEnabled(false); + + QList nodes = selectedNodes; + mitk::NodePredicateDataType::Pointer imagePredicate = mitk::NodePredicateDataType::New("Image"); + + if(m_Controls.radioButton_T1->isChecked()) + { + if (nodes.size() > 0 && imagePredicate->CheckNode(nodes.front())) + { + this->m_selectedNode = nodes.front(); + this->m_selectedImage = dynamic_cast(this->m_selectedNode->GetData()); + m_Controls.timeserieslabel->setText((this->m_selectedNode->GetName()).c_str()); + nodes.pop_front(); + } + + if (nodes.size() > 0 && imagePredicate->CheckNode(nodes.front())) + { + + this->m_selectedBaselineNode = nodes.front(); + this->m_selectedBaselineImage = dynamic_cast(this->m_selectedBaselineNode->GetData()); + this->m_Controls.BaselineImageLabel->setText((this->m_selectedBaselineNode->GetName()).c_str()); + } + } + else if(m_Controls.radioButton_T2->isChecked()) + { + if (nodes.size() > 0 && imagePredicate->CheckNode(nodes.front())) + { + this->m_selectedNode = nodes.front(); + this->m_selectedImage = dynamic_cast(this->m_selectedNode->GetData()); + m_Controls.T2_SeriesLabel->setText((this->m_selectedNode->GetName()).c_str()); + nodes.pop_front(); + } + } + + + m_Controls.btnConvertToConcentration->setEnabled(m_selectedImage.IsNotNull() && CheckSettings()); + + + +} + + + +ConcentrationCurveConverterView::ConcentrationCurveConverterView() +{ +} diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.h new file mode 100644 index 0000000000..0574104ef8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterView.h @@ -0,0 +1,103 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef ConcentrationCurveConverterView_h +#define ConcentrationCurveConverterView_h + +#include + +#include +#include "ui_ConcentrationCurveConverterViewControls.h" + +#include + + +/*! + * @brief Test Plugin for SUV calculations of PET images + */ +class ConcentrationCurveConverterView : public QmitkAbstractView +{ + Q_OBJECT + +public: +// typedef itk::Image ImageType; + typedef itk::Image ConvertedImageType; + + + /*! @brief The view's unique ID - required by MITK */ + static const std::string VIEW_ID; + + ConcentrationCurveConverterView(); + +protected slots: + + /*! + * @brief Is triggered of the update button is clicked and the selected node should get the (new) iso level set. + */ + void OnConvertToConcentrationButtonClicked(); + void OnSettingChanged(); + bool CheckSettings() const; + + + +protected: + + // Overridden base class functions + + /*! + * @brief Sets up the UI controls and connects the slots and signals. Gets + * called by the framework to create the GUI at the right time. + * @param[in,out] parent The parent QWidget, as this class itself is not a QWidget + * subclass. + */ + void CreateQtPartControl(QWidget* parent); + + /*! + * @brief Sets the focus to the plot curve button. Gets called by the framework to set the + * focus on the right widget. + */ + void SetFocus(); + + /*! Helper method that adds an concentration image as child node to the current m_selectedNode and returns this new child node.*/ + mitk::DataNode::Pointer AddConcentrationImage(mitk::Image* image, std::string nodeName) const; + + + /*! \brief called by QmitkFunctionality when DataManager's selection has changed + */ + virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, + const QList& nodes); + + // Variables + + /*! @brief The view's UI controls */ + Ui::ConcentrationCurveConverterViewControls m_Controls; + + mitk::DataNode::Pointer m_selectedNode; + mitk::Image::Pointer m_selectedImage; + mitk::DataNode::Pointer m_selectedBaselineNode; + mitk::Image::Pointer m_selectedBaselineImage; + +private: + + /**Converts the selected image to a concentration image based on the given gui settings.*/ + mitk::Image::Pointer Convert4DConcentrationImage(mitk::Image::Pointer inputImage); + mitk::Image::Pointer Convert3DConcentrationImage(mitk::Image::Pointer inputImage, mitk::Image::Pointer baselineImage); + + mitk::Image::Pointer ConvertT2ConcentrationImgage(mitk::Image::Pointer inputImage); + +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterViewControls.ui b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterViewControls.ui new file mode 100644 index 0000000000..15dec472cf --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/ConcentrationCurveConverterViewControls.ui @@ -0,0 +1,354 @@ + + + ConcentrationCurveConverterViewControls + + + + 0 + 0 + 475 + 671 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + 10 + + + + + T1 weighted MRI + + + + + + + T2 weighted MRI + + + + + + + + + T1 weighted images + + + + + + 10 + + + 10 + + + + + 10 + + + + + 3D Image + + + + + + + 4D Image + + + + + + + + + 4D Image + + + + + + Selected Time Series: + + + + + + + No series selected + + + + + + + + + + 3D Image + + + + + + Selected 3D Image + + + + + + + No Image selected + + + + + + + Baseline Image (without CA): + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + No Baseline Image selected + + + + + + + + + + + + Configuration + + + + + + 10 + + + 10 + + + + + Relative Signal Enhancement + + + + + + + Absolute Signal Enhancement + + + + + + + Conversion Faktor k: + + + + + + + + + + + + 10 + + + 10 + + + + + Turbo FLASH Sequence + + + + + + + 20 + + + + + Turbo FLASH Parameters: + + + + + + + + + Relaxivity + + + + + + + + + + + + + Recovery Time + + + + + + + Relaxation Time + + + + + + + true + + + + 0 + 0 + + + + [s] + + + + + + + [] + + + + + + + [s] + + + + + + + + + + + + + + + + + + + + T2 weighted images + + + + + + + + + + + + Conversion Factor k + + + + + + + Echo Time TE + + + + + + + Selected Time Series: + + + + + + + No Series Selected + + + + + + + + + + Convert To Concentration + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/org_mitk_ConcentrationCurveConverterView_Activator.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/org_mitk_ConcentrationCurveConverterView_Activator.cpp new file mode 100644 index 0000000000..58fabbeab1 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/org_mitk_ConcentrationCurveConverterView_Activator.cpp @@ -0,0 +1,29 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "org_mitk_ConcentrationCurveConverterView_Activator.h" + +#include "ConcentrationCurveConverterView.h" + + void org_mitk_ConcentrationCurveConverterView_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(ConcentrationCurveConverterView, context); + } + + void org_mitk_ConcentrationCurveConverterView_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context); + } \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/org_mitk_ConcentrationCurveConverterView_Activator.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/org_mitk_ConcentrationCurveConverterView_Activator.h new file mode 100644 index 0000000000..85b05bf091 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.concentration.mri/src/internal/org_mitk_ConcentrationCurveConverterView_Activator.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef org_mitk_ConcentrationCurveConverterView_Activator_h +#define org_mitk_ConcentrationCurveConverterView_Activator_h + +#include + + + class org_mitk_ConcentrationCurveConverterView_Activator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_pharmacokinetics_concentration_mri") + Q_INTERFACES(ctkPluginActivator) + public: + + /*! + * @brief Registers the plug-in. Gets called by the framework when the plug-in is + * first loaded. + * @param context The corresponding CTK plug-in context in which the plug-in is loaded. + */ + void start(ctkPluginContext* context); + + /*! + * @brief Deregisters the plug-in. Gets called by the framework when the plug-in + * is unloaded. + * @param context The corresponding CTK plug-in context in which the plug-in was loaded. + */ + void stop(ctkPluginContext* context); + }; + +#endif diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/CMakeLists.txt b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/CMakeLists.txt new file mode 100644 index 0000000000..6ce35d9cd8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/CMakeLists.txt @@ -0,0 +1,8 @@ +project(org_mitk_gui_qt_pharmacokinetics_curvedescriptor) + +mitk_create_plugin( + EXPORT_DIRECTIVE CURVEDESCRIPTORS_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS + PRIVATE MitkQtWidgetsExt MitkPharmacokinetics MitkModelFitUI MitkPharmacokineticsUI +) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..494b785680 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/UserManual/Manual.dox @@ -0,0 +1,4 @@ +/** +\page org_mitk_gui_qt_pharmacokinetics_curvedescriptor The Perfusion Curve Description Parameters View + +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..2175fe0a9c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_curvedescriptor org.mitk.gui.qt.pharmacokinetics.curvedescriptor + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_curvedescriptor_internal Internal + \ingroup org_mitk_gui_qt_pharmacokinetics_curvedescriptor + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.pharmacokinetics.curvedescriptor plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/files.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/files.cmake new file mode 100644 index 0000000000..4d3cf1bb68 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/files.cmake @@ -0,0 +1,42 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_PerfusionCurveDescriptionParameterView_Activator.cpp + PerfusionCurveDescriptionParameterView.cpp +) + +set(UI_FILES + src/internal/PerfusionCurveDescriptionParameterViewControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_PerfusionCurveDescriptionParameterView_Activator.h + src/internal/PerfusionCurveDescriptionParameterView.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/icon.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/manifest_headers.cmake new file mode 100644 index 0000000000..3323290acb --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Perfusion Curve Description Parameter Plugin") +set(Plugin-Version "1.0") +set(Plugin-Vendor "DKFZ, Software Development For Integrated Diagnostics and Therapy") +set(Plugin-ContactAddress "c.debus@dkfz.de") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/plugin.xml b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/plugin.xml new file mode 100644 index 0000000000..42dadcd43e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/resources/icon.png b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/resources/icon.png new file mode 100644 index 0000000000..08673d42f2 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/resources/icon.png differ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/resources/icon_PerfusionCurveDescriptors.png b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/resources/icon_PerfusionCurveDescriptors.png new file mode 100644 index 0000000000..fb87d9e608 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/resources/icon_PerfusionCurveDescriptors.png differ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/resources/petsuv.png b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/resources/petsuv.png new file mode 100644 index 0000000000..2dc586dfd4 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/resources/petsuv.png differ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.cpp new file mode 100644 index 0000000000..06be4190d6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.cpp @@ -0,0 +1,217 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +#include "mitkWorkbenchUtil.h" + +#include "PerfusionCurveDescriptionParameterView.h" +#include "QmitkDescriptionParameterBackgroundJob.h" +#include "mitkAreaUnderTheCurveDescriptionParameter.h" +#include "mitkAreaUnderFirstMomentDescriptionParameter.h" +#include "mitkMeanResidenceTimeDescriptionParameter.h" +#include "mitkTimeToPeakCurveDescriptionParameter.h" +#include "mitkMaximumCurveDescriptionParameter.h" +#include "mitkPixelBasedDescriptionParameterImageGenerator.h" +#include "mitkCurveParameterFunctor.h" +#include "mitkExtractTimeGrid.h" + +#include + +const std::string PerfusionCurveDescriptionParameterView::VIEW_ID = + "org.mitk.gui.qt.pharmacokinetics.curvedescriptor"; + +void PerfusionCurveDescriptionParameterView::SetFocus() +{ + m_Controls.btnCalculateParameters->setFocus(); +} + +void PerfusionCurveDescriptionParameterView::CreateQtPartControl(QWidget* parent) +{ + m_Controls.setupUi(parent); + m_Controls.btnCalculateParameters->setEnabled(false); + + + + connect(m_Controls.btnCalculateParameters, SIGNAL(clicked()), this, + SLOT(OnCalculateParametersButtonClicked())); + + + InitParameterList(); +} + + +void PerfusionCurveDescriptionParameterView::OnSelectionChanged( + berry::IWorkbenchPart::Pointer /*source*/, const QList& /*nodes*/) +{ + + m_Controls.btnCalculateParameters->setEnabled(false); + + + + QList dataNodes = this->GetDataManagerSelection(); + + if (dataNodes.empty()) + { + m_selectedNode = NULL; + m_selectedImage = NULL; + } + else + { + m_selectedNode = dataNodes[0]; + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + } + + if (m_selectedImage.IsNotNull()) + { + if (m_selectedImage->GetTimeGeometry()->CountTimeSteps() > 1) + { + m_Controls.btnCalculateParameters->setEnabled(true); + } + else + { + this->OnJobStatusChanged("Cannot compute parameters. Selected image must have multiple time steps."); + } + } + else if (m_selectedNode.IsNotNull()) + { + this->OnJobStatusChanged("Cannot compute parameters. Selected node is not an image."); + } + else + { + this->OnJobStatusChanged("Cannot compute parameters. No node selected."); + } +} + +PerfusionCurveDescriptionParameterView::PerfusionCurveDescriptionParameterView() +{ + m_selectedNode = NULL; + m_selectedImage = NULL; + m_selectedMask = NULL; +} + +void PerfusionCurveDescriptionParameterView::InitParameterList() +{ + m_ParameterMap.clear(); + + mitk::CurveDescriptionParameterBase::Pointer parameterFunction = + mitk::AreaUnderTheCurveDescriptionParameter::New().GetPointer(); + m_ParameterMap.insert(std::make_pair(ParameterNameType("AUC"), parameterFunction)); + parameterFunction = mitk::AreaUnderFirstMomentDescriptionParameter::New().GetPointer(); + m_ParameterMap.insert(std::make_pair(ParameterNameType("AUMC"), parameterFunction)); + parameterFunction = mitk::MeanResidenceTimeDescriptionParameter::New().GetPointer(); + m_ParameterMap.insert(std::make_pair(ParameterNameType("MRT"), parameterFunction)); + parameterFunction = mitk::MaximumCurveDescriptionParameter::New().GetPointer(); + m_ParameterMap.insert(std::make_pair(ParameterNameType("Maximum"), parameterFunction)); + parameterFunction = mitk::TimeToPeakCurveDescriptionParameter::New().GetPointer(); + m_ParameterMap.insert(std::make_pair(ParameterNameType("TimeToPeak"), parameterFunction)); + + for (ParameterMapType::const_iterator pos = m_ParameterMap.begin(); pos != m_ParameterMap.end(); + ++pos) + { + QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(pos->first), + this->m_Controls.parameterlist); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState(Qt::Unchecked); + } +}; + +void PerfusionCurveDescriptionParameterView::ConfigureFunctor(mitk::CurveParameterFunctor* functor) +const +{ + functor->SetGrid(mitk::ExtractTimeGrid(m_selectedImage)); + + for (int pos = 0; pos < this->m_Controls.parameterlist->count(); ++pos) + { + QListWidgetItem* item = this->m_Controls.parameterlist->item(pos); + mitk::CurveDescriptionParameterBase::Pointer parameterFunction = m_ParameterMap.at( + item->text().toStdString()); + + if (item->checkState() == Qt::Checked) + { + functor->RegisterDescriptionParameter(item->text().toStdString(), parameterFunction); + } + } +} + +void PerfusionCurveDescriptionParameterView::OnCalculateParametersButtonClicked() +{ + mitk::PixelBasedDescriptionParameterImageGenerator::Pointer generator = + mitk::PixelBasedDescriptionParameterImageGenerator::New(); + mitk::CurveParameterFunctor::Pointer functor = mitk::CurveParameterFunctor::New(); + this->ConfigureFunctor(functor); + + + + generator->SetFunctor(functor); + generator->SetDynamicImage(m_selectedImage); + generator->SetMask(m_selectedMask); + + + ///////////////////////// + //create job and put it into the thread pool + DescriptionParameterBackgroundJob* pJob = new DescriptionParameterBackgroundJob(generator, + this->m_selectedNode); + pJob->setAutoDelete(true); + + connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnJobError(QString))); + connect(pJob, SIGNAL(Finished()), this, SLOT(OnJobFinished())); + connect(pJob, SIGNAL(ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const DescriptionParameterBackgroundJob*)), this, + SLOT(OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const DescriptionParameterBackgroundJob*)), Qt::BlockingQueuedConnection); + + connect(pJob, SIGNAL(JobProgress(double)), this, SLOT(OnJobProgress(double))); + connect(pJob, SIGNAL(JobStatusChanged(QString)), this, SLOT(OnJobStatusChanged(QString))); + + QThreadPool* threadPool = QThreadPool::globalInstance(); + threadPool->start(pJob); +} + +void PerfusionCurveDescriptionParameterView::OnJobFinished() +{ + this->m_Controls.infoBox->append(QString("Fitting finished")); +}; + +void PerfusionCurveDescriptionParameterView::OnJobError(QString err) +{ + MITK_ERROR << err.toStdString().c_str(); + m_Controls.infoBox->append(QString("") + err + QString("")); +}; + +void PerfusionCurveDescriptionParameterView::OnJobResultsAreAvailable( + mitk::modelFit::ModelFitResultNodeVectorType results, const DescriptionParameterBackgroundJob* pJob) +{ + for (auto image : results) + { + this->GetDataStorage()->Add(image, pJob->GetParentNode()); + } +}; + +void PerfusionCurveDescriptionParameterView::OnJobProgress(double progress) +{ + this->m_Controls.progressBar->setValue(100 * progress); + QString report = QString("Progress. ") + QString::number(progress); + this->m_Controls.infoBox->append(report); +}; + +void PerfusionCurveDescriptionParameterView::OnJobStatusChanged(QString info) +{ + this->m_Controls.infoBox->append(info); + MITK_INFO << info.toStdString().c_str(); +} + diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.h new file mode 100644 index 0000000000..b7ef3c55b0 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterView.h @@ -0,0 +1,110 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef PerfusionCurveDescriptionParameterView_h +#define PerfusionCurveDescriptionParameterView_h + +#include + +#include +#include "ui_PerfusionCurveDescriptionParameterViewControls.h" +#include "mitkCurveDescriptionParameterBase.h" +#include + +#include + +namespace mitk +{ + class CurveParameterFunctor; +} + +/*! + * @brief Test Plugin for SUV calculations of PET images + */ +class PerfusionCurveDescriptionParameterView : public QmitkAbstractView +{ + Q_OBJECT + +public: + + typedef mitk::CurveDescriptionParameterBase::CurveDescriptionParameterNameType ParameterNameType; + + /*! @brief The view's unique ID - required by MITK */ + static const std::string VIEW_ID; + + PerfusionCurveDescriptionParameterView(); + +protected slots: + + void InitParameterList(); + + void OnJobFinished(); + void OnJobError(QString err); + void OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType results, + const DescriptionParameterBackgroundJob* pJob); + void OnJobProgress(double progress); + void OnJobStatusChanged(QString info); + + /*! + * @brief Is triggered of the update button is clicked and the selected node should get the (new) iso level set. + */ + void OnCalculateParametersButtonClicked(); + +protected: + + // Overridden base class functions + + /*! + * @brief Sets up the UI controls and connects the slots and signals. Gets + * called by the framework to create the GUI at the right time. + * @param[in,out] parent The parent QWidget, as this class itself is not a QWidget + * subclass. + */ + void CreateQtPartControl(QWidget* parent); + + /*! + * @brief Sets the focus to the plot curve button. Gets called by the framework to set the + * focus on the right widget. + */ + void SetFocus(); + + /** Configures the passed functor according to the selected image and parameters*/ + void ConfigureFunctor(mitk::CurveParameterFunctor* functor) const; + + /*! \brief called by QmitkFunctionality when DataManager's selection has changed + */ + virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, + const QList& nodes) override; + + // Variables + + /*! @brief The view's UI controls */ + Ui::PerfusionCurveDescriptionParameterViewControls m_Controls; + mitk::DataNode::Pointer m_selectedNode; + +private: + + + + typedef std::map ParameterMapType; + + ParameterMapType m_ParameterMap; + + mitk::Image::Pointer m_selectedImage; + mitk::Image::Pointer m_selectedMask; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterViewControls.ui b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterViewControls.ui new file mode 100644 index 0000000000..90af6e4802 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/PerfusionCurveDescriptionParameterViewControls.ui @@ -0,0 +1,85 @@ + + + PerfusionCurveDescriptionParameterViewControls + + + + 0 + 0 + 390 + 671 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + + Selected Time Series: + + + + + + + No Series Selected! + + + + + + + + + QAbstractItemView::NoEditTriggers + + + false + + + true + + + + + + + Calculate Parameters + + + + + + + Status: + + + + + + 0 + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/org_mitk_PerfusionCurveDescriptionParameterView_Activator.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/org_mitk_PerfusionCurveDescriptionParameterView_Activator.cpp new file mode 100644 index 0000000000..5a630a529a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/org_mitk_PerfusionCurveDescriptionParameterView_Activator.cpp @@ -0,0 +1,32 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "org_mitk_PerfusionCurveDescriptionParameterView_Activator.h" + +#include "PerfusionCurveDescriptionParameterView.h" + +namespace mitk +{ + void org_mitk_PerfusionCurveDescriptionParameterView_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(PerfusionCurveDescriptionParameterView, context); + } + + void org_mitk_PerfusionCurveDescriptionParameterView_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context); + } +} diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/org_mitk_PerfusionCurveDescriptionParameterView_Activator.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/org_mitk_PerfusionCurveDescriptionParameterView_Activator.h new file mode 100644 index 0000000000..7f9c25b53c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.curvedescriptor/src/internal/org_mitk_PerfusionCurveDescriptionParameterView_Activator.h @@ -0,0 +1,53 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef org_mitk_PerfusionCurveDescriptionParameterView_Activator_h +#define org_mitk_PerfusionCurveDescriptionParameterView_Activator_h + +#include + +namespace mitk +{ + /*! + * @brief Activator class for the @ref CurveDescriptorParameterView. + * @details This small helper class is necessary for the integration as a CTK plug-in. + * @author Sascha Diatschuk + */ + class org_mitk_PerfusionCurveDescriptionParameterView_Activator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_pharmacokinetics_curvedescriptor") + Q_INTERFACES(ctkPluginActivator) + + public: + + /*! + * @brief Registers the plug-in. Gets called by the framework when the plug-in is + * first loaded. + * @param context The corresponding CTK plug-in context in which the plug-in is loaded. + */ + void start(ctkPluginContext* context); + + /*! + * @brief Deregisters the plug-in. Gets called by the framework when the plug-in + * is unloaded. + * @param context The corresponding CTK plug-in context in which the plug-in was loaded. + */ + void stop(ctkPluginContext* context); + }; +} + +#endif diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/CMakeLists.txt b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/CMakeLists.txt new file mode 100644 index 0000000000..b0d7d47b86 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/CMakeLists.txt @@ -0,0 +1,9 @@ +project(org_mitk_gui_qt_pharmacokinetics_mri) + +mitk_create_plugin( + EXPORT_DIRECTIVE MRPERFUSION_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkPharmacokinetics MitkModelFitUI + PACKAGE_DEPENDS + PRIVATE Boost +) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..b5529a4a2e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/documentation/UserManual/Manual.dox @@ -0,0 +1,8 @@ +/** +\page org_mitk_gui_qt_pharmacokinetics_mri The DCE MR Perfusion Datafit View + +\section org_mitk_gui_qt_pharmacokinetics_mri_Overview Overview + +This plug-in offers the possibilities to fit several pharmacokinetic modells onto DCE MR perfusion images. + +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..3d5cc3aea5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_mri org.mitk.gui.qt.pharmacokinetics.mri + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_mri_internal Internal + \ingroup org_mitk_gui_qt_pharmacokinetics_mri + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.pharmacokinetics.mri plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/files.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/files.cmake new file mode 100644 index 0000000000..d3b5a6f4ce --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/files.cmake @@ -0,0 +1,42 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_MRPerfusionView_Activator.cpp + MRPerfusionView.cpp +) + +set(UI_FILES + src/internal/MRPerfusionViewControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_MRPerfusionView_Activator.h + src/internal/MRPerfusionView.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/DCEMRI.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/manifest_headers.cmake new file mode 100644 index 0000000000..e3fff30e06 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "DCE MR Perfusion Datafit Plugin") +set(Plugin-Version "1.0") +set(Plugin-Vendor "DKFZ, Software Development For Integrated Diagnostics and Therapy") +set(Plugin-ContactAddress "c.debus@dkfz.de") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/plugin.xml b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/plugin.xml new file mode 100644 index 0000000000..672a061a8a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/resources/DCEMRI.png b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/resources/DCEMRI.png new file mode 100644 index 0000000000..3a91919a13 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/resources/DCEMRI.png differ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp new file mode 100644 index 0000000000..dd56a085c6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.cpp @@ -0,0 +1,1396 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "MRPerfusionView.h" + +#include "boost/tokenizer.hpp" +#include "boost/math/constants/constants.hpp" +#include + +#include "mitkWorkbenchUtil.h" + +#include "mitkAterialInputFunctionGenerator.h" +#include "mitkConcentrationCurveGenerator.h" + +#include +#include +#include +#include "mitkThreeStepLinearModelFactory.h" +#include "mitkThreeStepLinearModelParameterizer.h" +#include +#include +#include +#include +#include "mitkTwoCompartmentExchangeModelFactory.h" +#include "mitkTwoCompartmentExchangeModelParameterizer.h" +#include "mitkNumericTwoCompartmentExchangeModelFactory.h" +#include "mitkNumericTwoCompartmentExchangeModelParameterizer.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +// Includes for image casting between ITK and MITK +#include +#include "mitkImageCast.h" +#include "mitkITKImageImport.h" +#include +#include + + +const std::string MRPerfusionView::VIEW_ID = "org.mitk.gui.qt.pharmacokinetics.mri"; + +inline double convertToDouble(const std::string& data) +{ + std::istringstream stepStream(data); + stepStream.imbue(std::locale("C")); + double value = 0.0; + + if (!(stepStream >> value) || !(stepStream.eof())) + { + mitkThrow() << "Cannot convert string to double. String: " << data; + } + return value; +} + +void MRPerfusionView::SetFocus() +{ + m_Controls.btnModelling->setFocus(); +} + +void MRPerfusionView::CreateQtPartControl(QWidget* parent) +{ + m_Controls.setupUi(parent); + + m_Controls.btnModelling->setEnabled(false); + m_Controls.errorMessageLabel->hide(); + + this->InitModelComboBox(); + + connect(m_Controls.btnModelling, SIGNAL(clicked()), this, SLOT(OnModellingButtonClicked())); + + connect(m_Controls.comboModel, SIGNAL(currentIndexChanged(int)), this, SLOT(OnModellSet(int))); + connect(m_Controls.radioPixelBased, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + + //AIF setting + m_Controls.groupAIF->hide(); + m_Controls.btnAIFFile->setEnabled(false); + m_Controls.btnAIFFile->setEnabled(false); + m_Controls.radioAIFImage->setChecked(true); + m_Controls.comboAIFMask->SetDataStorage(this->GetDataStorage()); + m_Controls.comboAIFMask->SetPredicate(m_IsMaskPredicate); + m_Controls.comboAIFMask->setVisible(true); + m_Controls.comboAIFMask->setEnabled(true); + m_Controls.comboAIFImage->SetDataStorage(this->GetDataStorage()); + m_Controls.comboAIFImage->SetPredicate(m_IsNoMaskImagePredicate); + m_Controls.comboAIFImage->setEnabled(false); + m_Controls.checkDedicatedAIFImage->setEnabled(true); + m_Controls.HCLSpinBox->setValue(mitk::AterialInputFunctionGenerator::DEFAULT_HEMATOCRIT_LEVEL); + + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.comboAIFMask, SLOT(setVisible(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.labelAIFMask, SLOT(setVisible(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.checkDedicatedAIFImage, SLOT(setVisible(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.comboAIFMask, SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.checkDedicatedAIFImage, SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.checkDedicatedAIFImage, SLOT(setVisible(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.comboAIFImage, SLOT(setVisible(bool))); + connect(m_Controls.checkDedicatedAIFImage, SIGNAL(toggled(bool)), m_Controls.comboAIFImage, SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.radioAIFFile, SIGNAL(toggled(bool)), m_Controls.btnAIFFile, SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFFile, SIGNAL(toggled(bool)), m_Controls.aifFilePath, SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFFile, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + + connect(m_Controls.btnAIFFile, SIGNAL(clicked()), this, SLOT(LoadAIFfromFile())); + + //Brix setting + m_Controls.groupDescBrix->hide(); + connect(m_Controls.injectiontime, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); + + //Num2CX setting + m_Controls.groupNum2CXM->hide(); + connect(m_Controls.odeStepSize, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); + + //Model fit configuration + m_Controls.groupBox_FitConfiguration->hide(); + + m_Controls.checkBox_Constraints->setEnabled(false); + m_Controls.constraintManager->setEnabled(false); + m_Controls.initialValuesManager->setEnabled(false); + m_Controls.initialValuesManager->setDataStorage(this->GetDataStorage()); + + connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.initialValuesManager, SIGNAL(initialValuesChanged(void)), this, SLOT(UpdateGUIControls())); + + + connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)), m_Controls.initialValuesManager, SLOT(setEnabled(bool))); + connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager, SLOT(setEnabled(bool))); + connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager, SLOT(setVisible(bool))); + + //Concentration + m_Controls.groupConcentration->hide(); + m_Controls.groupBoxTurboFlash->hide(); + m_Controls.radioButtonNoConversion->setChecked(true); + m_Controls.factorSpinBox->setEnabled(false); + m_Controls.groupBox_viaT1Map->hide(); + + connect(m_Controls.radioButtonTurboFlash, SIGNAL(toggled(bool)), m_Controls.groupBoxTurboFlash, SLOT(setVisible(bool))); + connect(m_Controls.radioButtonTurboFlash, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.relaxationtime, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.recoverytime, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.relaxivity, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); + + connect(m_Controls.radioButton_absoluteEnhancement, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.radioButton_relativeEnchancement, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.radioButton_absoluteEnhancement, SIGNAL(toggled(bool)), m_Controls.factorSpinBox, SLOT(setEnabled(bool))); + connect(m_Controls.radioButton_relativeEnchancement, SIGNAL(toggled(bool)), m_Controls.factorSpinBox, SLOT(setEnabled(bool))); + connect(m_Controls.factorSpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); + + connect(m_Controls.radioButtonUsingT1, SIGNAL(toggled(bool)), m_Controls.groupBox_viaT1Map, SLOT(setVisible(bool))); + connect(m_Controls.radioButtonUsingT1, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.FlipangleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.RelaxivitySpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.TRSpinBox, SIGNAL(valueChanged(double)), this, SLOT(UpdateGUIControls())); + m_Controls.ComboT1Map->SetDataStorage(this->GetDataStorage()); + m_Controls.ComboT1Map->SetPredicate(m_IsNoMaskImagePredicate); + m_Controls.ComboT1Map->setEnabled(false); + connect(m_Controls.radioButtonUsingT1, SIGNAL(toggled(bool)), m_Controls.ComboT1Map, SLOT(setEnabled(bool))); + + UpdateGUIControls(); +} + +bool MRPerfusionView::IsTurboFlashSequenceFlag() const +{ + return this->m_Controls.radioButtonTurboFlash->isChecked(); +}; + + + +void MRPerfusionView::UpdateGUIControls() +{ + m_Controls.lineFitName->setPlaceholderText(QString::fromStdString(this->GetDefaultFitName())); + m_Controls.lineFitName->setEnabled(!m_FittingInProgress); + + m_Controls.checkBox_Constraints->setEnabled(m_modelConstraints.IsNotNull()); + + bool isDescBrixFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isToftsFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL || + dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool is2CXMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL || + dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + bool isNum2CXMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + m_Controls.groupAIF->setVisible(isToftsFactory || is2CXMFactory); + m_Controls.groupDescBrix->setVisible(isDescBrixFactory); + m_Controls.groupNum2CXM->setVisible(isNum2CXMFactory); + m_Controls.groupConcentration->setVisible(isToftsFactory || is2CXMFactory); + + m_Controls.groupBox_FitConfiguration->setVisible(m_selectedModelFactory); + + m_Controls.groupBox->setEnabled(!m_FittingInProgress); + m_Controls.comboModel->setEnabled(!m_FittingInProgress); + m_Controls.groupAIF->setEnabled(!m_FittingInProgress); + m_Controls.groupDescBrix->setEnabled(!m_FittingInProgress); + m_Controls.groupNum2CXM->setEnabled(!m_FittingInProgress); + m_Controls.groupConcentration->setEnabled(!m_FittingInProgress); + m_Controls.groupBox_FitConfiguration->setEnabled(!m_FittingInProgress); + + m_Controls.radioROIbased->setEnabled(m_selectedMask.IsNotNull()); + + m_Controls.btnModelling->setEnabled(m_selectedImage.IsNotNull() + && m_selectedModelFactory.IsNotNull() && !m_FittingInProgress && CheckModelSettings()); +} + +void MRPerfusionView::OnModellSet(int index) +{ + m_selectedModelFactory = NULL; + + if (index > 0) + { + if (static_cast(index) <= m_FactoryStack.size() ) + { + m_selectedModelFactory = m_FactoryStack[index - 1]; + } + else + { + MITK_WARN << "Invalid model index. Index outside of the factory stack. Factory stack size: "<< m_FactoryStack.size() << "; invalid index: "<< index; + } + } + + if (m_selectedModelFactory) + { + this->m_modelConstraints = dynamic_cast + (m_selectedModelFactory->CreateDefaultConstraints().GetPointer()); + + m_Controls.initialValuesManager->setInitialValues(m_selectedModelFactory->GetParameterNames(), + m_selectedModelFactory->GetDefaultInitialParameterization()); + + if (this->m_modelConstraints.IsNull()) + { + this->m_modelConstraints = mitk::SimpleBarrierConstraintChecker::New(); + } + + m_Controls.constraintManager->setChecker(this->m_modelConstraints, + this->m_selectedModelFactory->GetParameterNames()); + + } + + UpdateGUIControls(); +} + +std::string MRPerfusionView::GetDefaultFitName() const +{ + std::string defaultName = "undefined model"; + + if (this->m_selectedModelFactory.IsNotNull()) + { + defaultName = this->m_selectedModelFactory->GetClassID(); + } + + if (this->m_Controls.radioPixelBased->isChecked()) + { + defaultName += "_pixel"; + } + else + { + defaultName += "_roi"; + } + + return defaultName; +} + +void MRPerfusionView::OnModellingButtonClicked() +{ + //check if all static parameters set + if (m_selectedModelFactory.IsNotNull() && CheckModelSettings()) + { + mitk::ParameterFitImageGeneratorBase::Pointer generator = NULL; + mitk::modelFit::ModelFitInfo::Pointer fitSession = NULL; + + bool isDescBrixFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool is3LinearFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isExtToftsFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isStanToftsFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool is2CXMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isNum2CXMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + if (isDescBrixFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateDescriptiveBrixModel_PixelBased(fitSession, generator); + } + else + { + GenerateDescriptiveBrixModel_ROIBased(fitSession, generator); + } + } + else if (is3LinearFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + Generate3StepLinearModelFit_PixelBased(fitSession, generator); + } + else + { + Generate3StepLinearModelFit_ROIBased(fitSession, generator); + } + } + else if (isStanToftsFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateAIFbasedModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateAIFbasedModelFit_ROIBased(fitSession, generator); + } + } + else if (isExtToftsFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateAIFbasedModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateAIFbasedModelFit_ROIBased(fitSession, generator); + } + } + else if (is2CXMFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateAIFbasedModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateAIFbasedModelFit_ROIBased(fitSession, generator); + } + } + else if (isNum2CXMFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateAIFbasedModelFit_PixelBased(fitSession, + generator); + } + else + { + GenerateAIFbasedModelFit_ROIBased(fitSession, + generator); + } + } + + //add other models with else if + + if (generator.IsNotNull() && fitSession.IsNotNull()) + { + m_FittingInProgress = true; + UpdateGUIControls(); + DoFit(fitSession, generator); + } + else + { + QMessageBox box; + box.setText("Fitting error!"); + box.setInformativeText("Could not establish fitting job. Error when setting ab generator, model parameterizer or session info."); + box.setStandardButtons(QMessageBox::Ok); + box.setDefaultButton(QMessageBox::Ok); + box.setIcon(QMessageBox::Warning); + box.exec(); + } + + } + else + { + QMessageBox box; + box.setText("Static parameters for model are not set!"); + box.setInformativeText("Some static parameters, that are needed for calculation are not set and equal to zero. Modeling not possible"); + box.setStandardButtons(QMessageBox::Ok); + box.setDefaultButton(QMessageBox::Ok); + box.setIcon(QMessageBox::Warning); + box.exec(); + } +} + + +void MRPerfusionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, + const QList& selectedNodes) +{ + m_selectedMaskNode = NULL; + m_selectedMask = NULL; + + m_Controls.errorMessageLabel->setText(""); + m_Controls.masklabel->setText("No (valid) mask selected."); + m_Controls.timeserieslabel->setText("No (valid) series selected."); + + QList nodes = selectedNodes; + + if (nodes.size() > 0 && this->m_IsNoMaskImagePredicate->CheckNode(nodes.front())) + { + this->m_selectedNode = nodes.front(); + auto selectedImage = dynamic_cast(this->m_selectedNode->GetData()); + m_Controls.timeserieslabel->setText((this->m_selectedNode->GetName()).c_str()); + + if (selectedImage != this->m_selectedImage) + { + if (selectedImage) + { + this->m_Controls.initialValuesManager->setReferenceImageGeometry(selectedImage->GetGeometry()); + } + else + { + this->m_Controls.initialValuesManager->setReferenceImageGeometry(nullptr); + } + } + this->m_selectedImage = selectedImage; + nodes.pop_front(); + } + else + { + this->m_selectedNode = NULL; + this->m_selectedImage = NULL; + this->m_Controls.initialValuesManager->setReferenceImageGeometry(nullptr); + } + + if (nodes.size() > 0 && this->m_IsMaskPredicate->CheckNode(nodes.front())) + { + this->m_selectedMaskNode = nodes.front(); + this->m_selectedMask = dynamic_cast(this->m_selectedMaskNode->GetData()); + + if (this->m_selectedMask->GetTimeSteps() > 1) + { + MITK_INFO << + "Selected mask has multiple timesteps. Only use first timestep to mask model fit. Mask name: " << + m_selectedMaskNode->GetName(); + mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); + maskedImageTimeSelector->SetInput(this->m_selectedMask); + maskedImageTimeSelector->SetTimeNr(0); + maskedImageTimeSelector->UpdateLargestPossibleRegion(); + this->m_selectedMask = maskedImageTimeSelector->GetOutput(); + } + + m_Controls.masklabel->setText((this->m_selectedMaskNode->GetName()).c_str()); + } + + if (m_selectedMask.IsNull()) + { + this->m_Controls.radioPixelBased->setChecked(true); + } + + m_Controls.errorMessageLabel->show(); + + UpdateGUIControls(); +} + +bool MRPerfusionView::CheckModelSettings() const +{ + bool ok = true; + + //check wether any model is set at all. Otherwise exit with false + if (m_selectedModelFactory.IsNotNull()) + { + bool isDescBrixFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool is3LinearFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isToftsFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL|| + dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool is2CXMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isNum2CXMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + if (isDescBrixFactory) + { + //if all static parameters for this model are set, exit with true, Otherwise exit with false + ok = m_Controls.injectiontime->value() > 0; + } + else if (is3LinearFactory) + { + if (this->m_Controls.radioButtonTurboFlash->isChecked()) + { + ok = ok && (m_Controls.recoverytime->value() > 0); + ok = ok && (m_Controls.relaxationtime->value() > 0); + ok = ok && (m_Controls.relaxivity->value() > 0); + ok = ok && (m_Controls.AifRecoverytime->value() > 0); + + } + else if (this->m_Controls.radioButton_absoluteEnhancement->isChecked() + || this->m_Controls.radioButton_relativeEnchancement->isChecked()) + { + ok = ok && (m_Controls.factorSpinBox->value() > 0); + } + else if (this->m_Controls.radioButtonUsingT1->isChecked()) + { + ok = ok && (m_Controls.FlipangleSpinBox->value() > 0); + ok = ok && (m_Controls.TRSpinBox->value() > 0); + ok = ok && (m_Controls.RelaxivitySpinBox->value() > 0); + ok = ok && (m_Controls.ComboT1Map->GetSelectedNode().IsNotNull()); + + } + else if (this->m_Controls.radioButtonNoConversion->isChecked()) + { + ok = ok; + } + else + { + ok = false; + } + } + else if (isToftsFactory || is2CXMFactory || isNum2CXMFactory) + { + if (this->m_Controls.radioAIFImage->isChecked()) + { + ok = ok && m_Controls.comboAIFMask->GetSelectedNode().IsNotNull(); + + if (this->m_Controls.checkDedicatedAIFImage->isChecked()) + { + ok = ok && m_Controls.comboAIFImage->GetSelectedNode().IsNotNull(); + } + } + else if (this->m_Controls.radioAIFFile->isChecked()) + { + ok = ok && (this->AIFinputGrid.size() != 0) && (this->AIFinputFunction.size() != 0); + } + else + { + ok = false; + } + + if (this->m_Controls.radioButtonTurboFlash->isChecked()) + { + ok = ok && (m_Controls.recoverytime->value() > 0); + ok = ok && (m_Controls.relaxationtime->value() > 0); + ok = ok && (m_Controls.relaxivity->value() > 0); + ok = ok && (m_Controls.AifRecoverytime->value() > 0); + + } + else if (this->m_Controls.radioButton_absoluteEnhancement->isChecked() + || this->m_Controls.radioButton_relativeEnchancement->isChecked()) + { + ok = ok && (m_Controls.factorSpinBox->value() > 0); + } + else if (this->m_Controls.radioButtonUsingT1->isChecked()) + { + ok = ok && (m_Controls.FlipangleSpinBox->value() > 0); + ok = ok && (m_Controls.TRSpinBox->value() > 0); + ok = ok && (m_Controls.RelaxivitySpinBox->value() > 0); + ok = ok && (m_Controls.ComboT1Map->GetSelectedNode().IsNotNull()); + + } + else if (this->m_Controls.radioButtonNoConversion->isChecked()) + { + ok = ok; + } + else + { + ok = false; + } + + if (isNum2CXMFactory) + { + ok = ok && (this->m_Controls.odeStepSize->value() > 0); + } + + } + //add other models as else if and check wether all needed static parameters are set + else + { + ok = false; + } + + if (this->m_Controls.radioButton_StartParameters->isChecked() && !this->m_Controls.initialValuesManager->hasValidInitialValues()) + { + std::string warning = "Warning. Invalid start parameters. At least one parameter as an invalid image setting as source."; + MITK_ERROR << warning; + m_Controls.infoBox->append(QString("") + QString::fromStdString(warning) + QString("")); + + ok = false; + }; + } + else + { + ok = false; + } + + return ok; +} + +void MRPerfusionView::ConfigureInitialParametersOfParameterizer(mitk::ModelParameterizerBase* + parameterizer) const +{ + if (m_Controls.radioButton_StartParameters->isChecked()) + { + //use user defined initial parameters + mitk::InitialParameterizationDelegateBase::Pointer paramDelegate = m_Controls.initialValuesManager->getInitialParametrizationDelegate(); + parameterizer->SetInitialParameterizationDelegate(paramDelegate); + } +} + +void MRPerfusionView::GenerateDescriptiveBrixModel_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + mitk::DescriptivePharmacokineticBrixModelParameterizer::Pointer modelParameterizer = + mitk::DescriptivePharmacokineticBrixModelParameterizer::New(); + + //Model configuration (static parameters) can be done now + modelParameterizer->SetTau(m_Controls.injectiontime->value()); + + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(this->m_selectedImage); + imageTimeSelector->SetTimeNr(0); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::DescriptivePharmacokineticBrixModelParameterizer::BaseImageType::Pointer baseImage; + mitk::CastToItkImage(imageTimeSelector->GetOutput(), baseImage); + + modelParameterizer->SetBaseImage(baseImage); + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + std::string roiUID = ""; + + if (m_selectedMask.IsNotNull()) + { + fitGenerator->SetMask(m_selectedMask); + roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + } + + fitGenerator->SetDynamicImage(m_selectedImage); + fitGenerator->SetFitFunctor(fitFunctor); + + generator = fitGenerator.GetPointer(); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), roiUID); +} + +void MRPerfusionView::GenerateDescriptiveBrixModel_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + if (m_selectedMask.IsNull()) + { + return; + } + + mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::ROIBasedParameterFitImageGenerator::New(); + + mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::Pointer modelParameterizer = + mitk::DescriptivePharmacokineticBrixModelValueBasedParameterizer::New(); + + //Compute ROI signal + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = + mitk::MaskedDynamicImageStatisticsGenerator::New(); + signalGenerator->SetMask(m_selectedMask); + signalGenerator->SetDynamicImage(m_selectedImage); + signalGenerator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); + + //Model configuration (static parameters) can be done now + modelParameterizer->SetTau(m_Controls.injectiontime->value()); + modelParameterizer->SetBaseValue(roiSignal[0]); + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + fitGenerator->SetMask(m_selectedMask); + fitGenerator->SetFitFunctor(fitFunctor); + fitGenerator->SetSignal(roiSignal); + fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(m_selectedImage)); + + generator = fitGenerator.GetPointer(); + + std::string roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), roiUID); + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = + roiSignal.begin(); pos != roiSignal.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("ROI", infoSignal); +} + +void MRPerfusionView::Generate3StepLinearModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + mitk::ThreeStepLinearModelParameterizer::Pointer modelParameterizer = + mitk::ThreeStepLinearModelParameterizer::New(); + + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + std::string roiUID = ""; + + if (m_selectedMask.IsNotNull()) + { + fitGenerator->SetMask(m_selectedMask); + roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + } + + fitGenerator->SetDynamicImage(m_selectedImage); + fitGenerator->SetFitFunctor(fitFunctor); + + generator = fitGenerator.GetPointer(); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), roiUID); +} + +void MRPerfusionView::Generate3StepLinearModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + if (m_selectedMask.IsNull()) + { + return; + } + + mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::ROIBasedParameterFitImageGenerator::New(); + + mitk::ThreeStepLinearModelParameterizer::Pointer modelParameterizer = + mitk::ThreeStepLinearModelParameterizer::New(); + + //Compute ROI signal + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = + mitk::MaskedDynamicImageStatisticsGenerator::New(); + signalGenerator->SetMask(m_selectedMask); + signalGenerator->SetDynamicImage(m_selectedImage); + signalGenerator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); + + //Model configuration (static parameters) can be done now + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + fitGenerator->SetMask(m_selectedMask); + fitGenerator->SetFitFunctor(fitFunctor); + fitGenerator->SetSignal(roiSignal); + fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(m_selectedImage)); + + generator = fitGenerator.GetPointer(); + + std::string roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), roiUID); + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = + roiSignal.begin(); pos != roiSignal.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("ROI", infoSignal); +} + +template +void MRPerfusionView::GenerateAIFbasedModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& + modelFitInfo, mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + mitk::Image::Pointer concentrationImage; + mitk::DataNode::Pointer concentrationNode; + GetConcentrationImage(concentrationImage, concentrationNode, false); + + mitk::AIFBasedModelBase::AterialInputFunctionType aif; + mitk::AIFBasedModelBase::AterialInputFunctionType aifTimeGrid; + GetAIF(aif, aifTimeGrid); + + modelParameterizer->SetAIF(aif); + modelParameterizer->SetAIFTimeGrid(aifTimeGrid); + + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + mitk::NumericTwoCompartmentExchangeModelParameterizer* numTCXParametrizer = + dynamic_cast + (modelParameterizer.GetPointer()); + + if (numTCXParametrizer) + { + numTCXParametrizer->SetODEINTStepSize(this->m_Controls.odeStepSize->value()); + } + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + std::string roiUID = ""; + + if (m_selectedMask.IsNotNull()) + { + fitGenerator->SetMask(m_selectedMask); + roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + } + + fitGenerator->SetDynamicImage(concentrationImage); + fitGenerator->SetFitFunctor(fitFunctor); + + generator = fitGenerator.GetPointer(); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + concentrationNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), + roiUID); + + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = + aif.begin(); pos != aif.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("AIF", infoSignal); +} + +template +void MRPerfusionView::GenerateAIFbasedModelFit_ROIBased( + mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + if (m_selectedMask.IsNull()) + { + return; + } + + mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::ROIBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + mitk::Image::Pointer concentrationImage; + mitk::DataNode::Pointer concentrationNode; + GetConcentrationImage(concentrationImage, concentrationNode, false); + + mitk::AIFBasedModelBase::AterialInputFunctionType aif; + mitk::AIFBasedModelBase::AterialInputFunctionType aifTimeGrid; + GetAIF(aif, aifTimeGrid); + + modelParameterizer->SetAIF(aif); + modelParameterizer->SetAIFTimeGrid(aifTimeGrid); + + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + mitk::NumericTwoCompartmentExchangeModelParameterizer* numTCXParametrizer = + dynamic_cast + (modelParameterizer.GetPointer()); + + if (numTCXParametrizer) + { + numTCXParametrizer->SetODEINTStepSize(this->m_Controls.odeStepSize->value()); + } + + //Compute ROI signal + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = + mitk::MaskedDynamicImageStatisticsGenerator::New(); + signalGenerator->SetMask(m_selectedMask); + signalGenerator->SetDynamicImage(concentrationImage); + signalGenerator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + fitGenerator->SetMask(m_selectedMask); + fitGenerator->SetFitFunctor(fitFunctor); + fitGenerator->SetSignal(roiSignal); + fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(concentrationImage)); + + generator = fitGenerator.GetPointer(); + + std::string roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + concentrationNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), + roiUID); + + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = + roiSignal.begin(); pos != roiSignal.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("ROI", infoSignal); + + infoSignal.clear(); + + for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = + aif.begin(); pos != aif.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("AIF", infoSignal); +} + + +void MRPerfusionView::DoFit(const mitk::modelFit::ModelFitInfo* fitSession, + mitk::ParameterFitImageGeneratorBase* generator) +{ + std::stringstream message; + message << "" << "Fitting Data Set . . ." << ""; + m_Controls.errorMessageLabel->setText(message.str().c_str()); + m_Controls.errorMessageLabel->show(); + + ///////////////////////// + //create job and put it into the thread pool + std::string fitName = m_Controls.lineFitName->text().toStdString(); + if (fitName.empty()) + { + fitName = m_Controls.lineFitName->placeholderText().toStdString(); + } + + ParameterFitBackgroundJob* pJob = new ParameterFitBackgroundJob(generator, fitSession, fitName, + this->m_selectedNode); + pJob->setAutoDelete(true); + + connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnJobError(QString))); + connect(pJob, SIGNAL(Finished()), this, SLOT(OnJobFinished())); + connect(pJob, SIGNAL(ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const ParameterFitBackgroundJob*)), this, + SLOT(OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const ParameterFitBackgroundJob*)), Qt::BlockingQueuedConnection); + + connect(pJob, SIGNAL(JobProgress(double)), this, SLOT(OnJobProgress(double))); + connect(pJob, SIGNAL(JobStatusChanged(QString)), this, SLOT(OnJobStatusChanged(QString))); + + QThreadPool* threadPool = QThreadPool::globalInstance(); + threadPool->start(pJob); +} + +MRPerfusionView::MRPerfusionView() : m_FittingInProgress(false) +{ + m_selectedImage = NULL; + m_selectedMask = NULL; + + mitk::ModelFactoryBase::Pointer factory = + mitk::DescriptivePharmacokineticBrixModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::ThreeStepLinearModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::StandardToftsModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::ExtendedToftsModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::TwoCompartmentExchangeModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::NumericTwoCompartmentExchangeModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + + mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage"); + mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image"); + mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); + mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary); + + mitk::NodePredicateOr::Pointer isMask = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet); + mitk::NodePredicateAnd::Pointer isNoMask = mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isMask)); + + this->m_IsMaskPredicate = mitk::NodePredicateAnd::New(isMask, mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer(); + + this->m_IsNoMaskImagePredicate = mitk::NodePredicateAnd::New(isNoMask, mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer(); +} + +void MRPerfusionView::OnJobFinished() +{ + this->m_Controls.infoBox->append(QString("Fitting finished")); + this->m_FittingInProgress = false; + this->UpdateGUIControls(); +}; + +void MRPerfusionView::OnJobError(QString err) +{ + MITK_ERROR << err.toStdString().c_str(); + + m_Controls.infoBox->append(QString("") + err + QString("")); +}; + +void MRPerfusionView::OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType results, + const ParameterFitBackgroundJob* pJob) +{ + //Store the resulting parameter fit image via convenience helper function in data storage + //(handles the correct generation of the nodes and their properties) + mitk::modelFit::StoreResultsInDataStorage(this->GetDataStorage(), results, pJob->GetParentNode()); + + m_Controls.errorMessageLabel->setText(""); + m_Controls.errorMessageLabel->hide(); +}; + +void MRPerfusionView::OnJobProgress(double progress) +{ + QString report = QString("Progress. ") + QString::number(progress); + this->m_Controls.infoBox->append(report); +}; + +void MRPerfusionView::OnJobStatusChanged(QString info) +{ + this->m_Controls.infoBox->append(info); +} + + +void MRPerfusionView::InitModelComboBox() const +{ + this->m_Controls.comboModel->clear(); + this->m_Controls.comboModel->addItem(tr("No model selected")); + + for (ModelFactoryStackType::const_iterator pos = m_FactoryStack.begin(); + pos != m_FactoryStack.end(); ++pos) + { + this->m_Controls.comboModel->addItem(QString::fromStdString((*pos)->GetClassID())); + } + + this->m_Controls.comboModel->setCurrentIndex(0); +}; + +mitk::DataNode::Pointer MRPerfusionView::AddConcentrationImage(mitk::Image* image, + const std::string& nodeName) const +{ + if (!image) + { + mitkThrow() << "Cannot generate concentration node. Passed image is null. parameter name: "; + } + + mitk::DataNode::Pointer result = mitk::DataNode::New(); + + result->SetData(image); + + result->SetName(nodeName); + + result->SetVisibility(true); + + mitk::EnsureModelFitUID(result); + + this->GetDataStorage()->Add(result, m_selectedNode); + + return result; +}; + + +mitk::Image::Pointer MRPerfusionView::ConvertConcentrationImage(bool AIFMode) +{ + //Compute Concentration image + mitk::ConcentrationCurveGenerator::Pointer concentrationGen = + mitk::ConcentrationCurveGenerator::New(); + + if (m_Controls.checkDedicatedAIFImage->isChecked() && AIFMode) + { + concentrationGen->SetDynamicImage(this->m_selectedAIFImage); + } + else + { + concentrationGen->SetDynamicImage(this->m_selectedImage); + } + + concentrationGen->SetisTurboFlashSequence(IsTurboFlashSequenceFlag()); + concentrationGen->SetAbsoluteSignalEnhancement(m_Controls.radioButton_absoluteEnhancement->isChecked()); + concentrationGen->SetRelativeSignalEnhancement(m_Controls.radioButton_relativeEnchancement->isChecked()); + concentrationGen->SetUsingT1Map(m_Controls.radioButtonUsingT1->isChecked()); + + + if (IsTurboFlashSequenceFlag()) + { + if (AIFMode) + { + concentrationGen->SetRecoveryTime(m_Controls.AifRecoverytime->value()); + } + else + { + concentrationGen->SetRecoveryTime(m_Controls.recoverytime->value()); + } + + concentrationGen->SetRelaxationTime(m_Controls.relaxationtime->value()); + concentrationGen->SetRelaxivity(m_Controls.relaxivity->value()); + } + else if (this->m_Controls.radioButtonUsingT1->isChecked()) + { + concentrationGen->SetRecoveryTime(m_Controls.TRSpinBox->value()); + concentrationGen->SetRelaxivity(m_Controls.RelaxivitySpinBox->value()); + concentrationGen->SetT10Image(dynamic_cast(m_Controls.ComboT1Map->GetSelectedNode()->GetData())); + + //Convert Flipangle from degree to radiant + double alpha = m_Controls.FlipangleSpinBox->value()/360*2* boost::math::constants::pi(); + concentrationGen->SetFlipAngle(alpha); + } + else + { + concentrationGen->SetFactor(m_Controls.factorSpinBox->value()); + } + + mitk::Image::Pointer concentrationImage = concentrationGen->GetConvertedImage(); + + return concentrationImage; +} + +void MRPerfusionView::GetAIF(mitk::AIFBasedModelBase::AterialInputFunctionType& aif, + mitk::AIFBasedModelBase::AterialInputFunctionType& aifTimeGrid) +{ + if (this->m_Controls.radioAIFFile->isChecked()) + { + aif.clear(); + aifTimeGrid.clear(); + + aif.SetSize(AIFinputFunction.size()); + aifTimeGrid.SetSize(AIFinputGrid.size()); + + aif.fill(0.0); + aifTimeGrid.fill(0.0); + + itk::Array::iterator aifPos = aif.begin(); + + for (std::vector::const_iterator pos = AIFinputFunction.begin(); + pos != AIFinputFunction.end(); ++pos, ++aifPos) + { + *aifPos = *pos; + } + + itk::Array::iterator gridPos = aifTimeGrid.begin(); + + for (std::vector::const_iterator pos = AIFinputGrid.begin(); pos != AIFinputGrid.end(); + ++pos, ++gridPos) + { + *gridPos = *pos; + } + } + else if (this->m_Controls.radioAIFImage->isChecked()) + { + aif.clear(); + aifTimeGrid.clear(); + + mitk::AterialInputFunctionGenerator::Pointer aifGenerator = + mitk::AterialInputFunctionGenerator::New(); + + //Hematocrit level + aifGenerator->SetHCL(this->m_Controls.HCLSpinBox->value()); + + //mask settings + this->m_selectedAIFMaskNode = m_Controls.comboAIFMask->GetSelectedNode(); + this->m_selectedAIFMask = dynamic_cast(this->m_selectedAIFMaskNode->GetData()); + + if (this->m_selectedAIFMask->GetTimeSteps() > 1) + { + MITK_INFO << + "Selected AIF mask has multiple timesteps. Only use first timestep to mask model fit. AIF Mask name: " + << + m_selectedAIFMaskNode->GetName() ; + mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); + maskedImageTimeSelector->SetInput(this->m_selectedAIFMask); + maskedImageTimeSelector->SetTimeNr(0); + maskedImageTimeSelector->UpdateLargestPossibleRegion(); + this->m_selectedAIFMask = maskedImageTimeSelector->GetOutput(); + } + + if (this->m_selectedAIFMask.IsNotNull()) + { + aifGenerator->SetMask(this->m_selectedAIFMask); + } + + //image settings + if (this->m_Controls.checkDedicatedAIFImage->isChecked()) + { + this->m_selectedAIFImageNode = m_Controls.comboAIFImage->GetSelectedNode(); + this->m_selectedAIFImage = dynamic_cast(this->m_selectedAIFImageNode->GetData()); + } + else + { + this->m_selectedAIFImageNode = m_selectedNode; + this->m_selectedAIFImage = m_selectedImage; + } + + mitk::Image::Pointer concentrationImage; + mitk::DataNode::Pointer concentrationNode; + this->GetConcentrationImage(concentrationImage, concentrationNode, true); + + aifGenerator->SetDynamicImage(concentrationImage); + + aif = aifGenerator->GetAterialInputFunction(); + aifTimeGrid = aifGenerator->GetAterialInputFunctionTimeGrid(); + } + else + { + mitkThrow() << "Cannot generate AIF. View is in a invalide state. No AIF mode selected."; + } + +} + + +void MRPerfusionView::LoadAIFfromFile() +{ + QFileDialog dialog; + dialog.setNameFilter(tr("Images (*.csv")); + + QString fileName = dialog.getOpenFileName(); + + m_Controls.aifFilePath->setText(fileName); + + std::string m_aifFilePath = fileName.toStdString(); + //Read Input + typedef boost::tokenizer< boost::escaped_list_separator > Tokenizer; + ///////////////////////////////////////////////////////////////////////////////////////////////// + //AIF Data + + std::ifstream in1(m_aifFilePath.c_str()); + + if (!in1.is_open()) + { + m_Controls.errorMessageLabel->setText("Could not open AIF File!"); + } + + + std::vector< std::string > vec1; + std::string line1; + + while (getline(in1, line1)) + { + Tokenizer tok(line1); + vec1.assign(tok.begin(), tok.end()); + + // if (vec1.size() < 3) continue; + + this->AIFinputGrid.push_back(convertToDouble(vec1[0])); + this->AIFinputFunction.push_back(convertToDouble(vec1[1])); + + } + +} + +void MRPerfusionView::GetConcentrationImage(mitk::Image::Pointer& concentrationImage, + mitk::DataNode::Pointer& concentrationNode, bool AIFMode) +{ + if (this->m_Controls.radioButtonNoConversion->isChecked()) + { + if (this->m_Controls.checkDedicatedAIFImage->isChecked() && AIFMode) + { + concentrationImage = this->m_selectedAIFImage; + concentrationNode = this->m_selectedAIFImageNode; + } + else + { + concentrationImage = this->m_selectedImage; + concentrationNode = this->m_selectedNode; + } + } + else + { + if (AIFMode && !IsTurboFlashSequenceFlag() && !this->m_Controls.checkDedicatedAIFImage->isChecked()) + { + //we can directly use the input image/node for the AIF + if (m_inputImage.IsNull()) + { + mitkThrow() << + "Cannot get AIF concentration image. Invalid view state. Input image is not defined yet, but should be."; + } + + concentrationImage = this->m_inputImage; + concentrationNode = this->m_inputNode; + } + else + { + concentrationImage = this->ConvertConcentrationImage(AIFMode); + + if (AIFMode) + { + concentrationNode = AddConcentrationImage(concentrationImage, "AIF Concentration"); + } + else + { + concentrationNode = AddConcentrationImage(concentrationImage, "Concentration"); + } + } + } + + if (AIFMode) + { + m_inputAIFImage = concentrationImage; + m_inputAIFNode = concentrationNode; + } + else + { + m_inputImage = concentrationImage; + m_inputNode = concentrationNode; + } + + mitk::EnsureModelFitUID(concentrationNode); +} + +mitk::ModelFitFunctorBase::Pointer MRPerfusionView::CreateDefaultFitFunctor( + const mitk::ModelParameterizerBase* parameterizer) const +{ + mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor = + mitk::LevenbergMarquardtModelFitFunctor::New(); + + mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::Pointer chi2 = + mitk::NormalizedSumOfSquaredDifferencesFitCostFunction::New(); + fitFunctor->RegisterEvaluationParameter("Chi^2", chi2); + + if (m_Controls.checkBox_Constraints->isChecked()) + { + fitFunctor->SetConstraintChecker(m_modelConstraints); + } + + mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel(); + + ::itk::LevenbergMarquardtOptimizer::ScalesType scales; + scales.SetSize(refModel->GetNumberOfParameters()); + scales.Fill(1.0); + fitFunctor->SetScales(scales); + + fitFunctor->SetDebugParameterMaps(m_Controls.checkDebug->isChecked()); + + return fitFunctor.GetPointer(); +} diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.h new file mode 100644 index 0000000000..2924dbeadb --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionView.h @@ -0,0 +1,203 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MRPerfusionView_h +#define MRPerfusionView_h + +#include + +#include "QmitkAbstractView.h" + +#include "itkCommand.h" + +#include "ui_MRPerfusionViewControls.h" +#include "mitkModelBase.h" +#include "QmitkParameterFitBackgroundJob.h" +#include "mitkModelFitResultHelper.h" +#include "mitkModelFactoryBase.h" +#include "mitkLevenbergMarquardtModelFitFunctor.h" +#include "mitkSimpleBarrierConstraintChecker.h" +#include "mitkAIFBasedModelBase.h" + + + +/*! +* @brief Test Plugin for SUV calculations of PET images +*/ +class MRPerfusionView : public QmitkAbstractView +{ + Q_OBJECT + +public: + + /*! @brief The view's unique ID - required by MITK */ + static const std::string VIEW_ID; + + MRPerfusionView(); + +protected slots: + + void OnModellingButtonClicked(); + + void OnJobFinished(); + void OnJobError(QString err); + void OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType results, + const ParameterFitBackgroundJob* pJob); + void OnJobProgress(double progress); + void OnJobStatusChanged(QString info); + + void OnModellSet(int); + void LoadAIFfromFile(); + + /**Sets visibility and enabled state of the GUI depending on the settings and workflow state.*/ + void UpdateGUIControls(); + +protected: + typedef QList SelectedDataNodeVectorType; + + // Overridden base class functions + + /*! + * @brief Sets up the UI controls and connects the slots and signals. Gets + * called by the framework to create the GUI at the right time. + * @param[in,out] parent The parent QWidget, as this class itself is not a QWidget + * subclass. + */ + void CreateQtPartControl(QWidget* parent); + + /*! + * @brief Sets the focus to the plot curve button. Gets called by the framework to set the + * focus on the right widget. + */ + void SetFocus(); + + /*! @brief Generates a configured fit generator and the corresponding modelinfo for a descriptive brix model with pixel based strategy. + * @remark add GenerateFunction for each model in the Combo box*/ + void GenerateDescriptiveBrixModel_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + void GenerateDescriptiveBrixModel_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + + void Generate3StepLinearModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + void Generate3StepLinearModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + + + template + void GenerateAIFbasedModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + + template + void GenerateAIFbasedModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + + /** Helper function that configures the initial parameter strategy of a parameterizer + according to the settings of the GUI.*/ + void ConfigureInitialParametersOfParameterizer(mitk::ModelParameterizerBase* parameterizer) const; + + /*! Starts the fitting job with the passed generator and session info*/ + void DoFit(const mitk::modelFit::ModelFitInfo* fitSession, + mitk::ParameterFitImageGeneratorBase* generator); + + /**Checks if the settings in the GUI are valid for the chosen model.*/ + bool CheckModelSettings() const; + + void InitModelComboBox() const; + + /*! Helper method that adds an concentration image as child node to the current m_selectedNode and returns this new child node.*/ + mitk::DataNode::Pointer AddConcentrationImage(mitk::Image* image, const std::string& nodeName) const; + + + + /*! \brief called by QmitkFunctionality when DataManager's selection has changed + */ + virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, + const QList& selectedNodes); + + // Variables + + /*! @brief The view's UI controls */ + Ui::MRPerfusionViewControls m_Controls; + + /* Nodes selected by user/ui for the fit */ + mitk::DataNode::Pointer m_selectedNode; + mitk::DataNode::Pointer m_selectedMaskNode; + mitk::DataNode::Pointer m_selectedAIFMaskNode; + mitk::DataNode::Pointer m_selectedAIFImageNode; + + /* Images selected by user/ui for the fit */ + mitk::Image::Pointer m_selectedImage; + mitk::Image::Pointer m_selectedMask; + mitk::Image::Pointer m_selectedAIFMask; + mitk::Image::Pointer m_selectedAIFImage; + + /* Node used for the fit (my be the selected image + or converted ones (depending on the ui settings */ + mitk::DataNode::Pointer m_inputNode; + mitk::DataNode::Pointer m_inputAIFNode; + + /* Image used for the fit (my be the selected image + or converted ones (depending on the ui settings */ + mitk::Image::Pointer m_inputImage; + mitk::Image::Pointer m_inputAIFImage; + + mitk::ModelFactoryBase::Pointer m_selectedModelFactory; + + mitk::SimpleBarrierConstraintChecker::Pointer m_modelConstraints; + +private: + bool IsTurboFlashSequenceFlag() const; + + bool m_FittingInProgress; + + typedef std::vector ModelFactoryStackType; + ModelFactoryStackType m_FactoryStack; + + /**Converts the selected image to a concentration image based on the given gui settings. + AIFMode controls if the concentration image for the fit input or the AIF will be converted.*/ + mitk::Image::Pointer ConvertConcentrationImage(bool AIFMode); + + /**Helper function that (depending on the gui settings) directly pass back the selected image/node + or the newly generated concentration image/node. The result is always what should be used as input for + the fitting. If AIFMode is true the function will generate the data for the AIF.*/ + void GetConcentrationImage(mitk::Image::Pointer& concentrationImage, + mitk::DataNode::Pointer& concentrationNode, bool AIFMode); + + /**Helper function that (depending on the gui settings) generates and passes back the AIF and its time grid + that should be used for fitting. + @remark the parameters aif and aifTimeGrid will be initialized accordingly if the method returns.*/ + void GetAIF(mitk::AIFBasedModelBase::AterialInputFunctionType& aif, + mitk::AIFBasedModelBase::AterialInputFunctionType& aifTimeGrid); + + /**Helper function that generates a default fitting functor + * default is a levenberg marquart based optimizer with all scales set to 1.0. + * Constraint setter will be set based on the gui setting and a evaluation parameter + * "sum of squared differences" will always be set.*/ + mitk::ModelFitFunctorBase::Pointer CreateDefaultFitFunctor(const mitk::ModelParameterizerBase* + parameterizer) const; + + /**Returns the default fit name, derived from the current GUI settings.*/ + std::string GetDefaultFitName() const; + + std::vector AIFinputGrid; + std::vector AIFinputFunction; + + mitk::NodePredicateBase::Pointer m_IsNoMaskImagePredicate; + mitk::NodePredicateBase::Pointer m_IsMaskPredicate; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionViewControls.ui b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionViewControls.ui new file mode 100644 index 0000000000..7202a701b1 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/MRPerfusionViewControls.ui @@ -0,0 +1,680 @@ + + + MRPerfusionViewControls + + + + 0 + 0 + 556 + 1124 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + + + + Selected Time Series: + + + + + + + No series selected. + + + + + + + + + + + Selected Mask: + + + + + + + No mask selected. + + + + + + + + + Fitting strategy + + + + 5 + + + 5 + + + + + Pixel based + + + true + + + + + + + ROI based + + + + + + + + + + + + Message + + + + + + + - + + + + + + + + + + + + Select pharmacokinetic modell... + + + + + + + + AIF Mask: + + + + + + Select AIF from Image: + + + + + + + 20 + + + + + + 0 + 0 + + + + + + + + AIF Mask: + + + + + + + false + + + Dedicated AIF Image: + + + + + + + false + + + + 0 + 0 + + + + + + + + + + 0 + + + + + Select AIF from File: + + + + + + + + + + false + + + Browse + + + + + + + + + 5 + + + + + Hematocrit Level [ ]: + + + + + + + 1.000000000000000 + + + 0.010000000000000 + + + + + + + + + + + + Descriptive Brix-Model Parameters: + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Injection Time [min]: + + + + + + + + + + + + + Numeric Two Compartment Exchange Model Parameters: + + + + + + ODE Int Step Size [s]: + + + + + + + 3 + + + 0.001000000000000 + + + 0.050000000000000 + + + + + + + + + + + 0 + 0 + + + + Model Fit Configuration + + + + + + + 0 + 0 + + + + + + 0 + 0 + 512 + 73 + + + + Start parameter + + + + + + Enter Fit Starting Parameters + + + + + + + + 0 + 0 + + + + + + + + + + 0 + 0 + 303 + 246 + + + + Constraints + + + + + + Enter Constraints for Fit Parameters + + + + + + + + 0 + 0 + + + + + 0 + 200 + + + + + + + + + + 0 + -34 + 499 + 516 + + + + Conversion: Signal to Concentration + + + + 9 + + + + + No Signal Conversion + + + true + + + + + + + 10 + + + + + Using T1 Map + + + + + + + 10 + + + + + Parameters: + + + + + + Flip Angle [ ° ] : + + + + + + + Repetition Time TR [ms] : + + + + + + + T1 Map [ms] : + + + + + + + + + + 10000.000000000000000 + + + + + + + Relaxivity [mMâ»Â¹ sâ»Â¹] : + + + + + + + + + + + + + + + + + + + + 6 + + + + + Relative Signal Enhancement + + + + + + + Absolute Signal Enhancement + + + + + + + + + + Conversion Factor k: + + + + + + + + + 2 + + + + + TurboFLASH Sequence + + + + + + + 5 + + + 20 + + + + + true + + + Turbo FLASH Parameters: + + + + + + Recovery Time [s]: + + + + + + + + + + Relaxation Time [s]: + + + + + + + + + + Relaxivity [ ]: + + + + + + + + + + AIF Recovery Time [s]: + + + + + + + + + + + + + + + + + + + + + + + + 5 + + + + + Fitting name: + + + + + + + <html><head/><body><p>Name/prefix that should be used for the fitting results.</p><p>May be explicitly defined by the user.</p></body></html> + + + + + + default fit name + + + + + + + + + Start Modelling + + + + + + + Generate debug parameter images + + + + + + + + 0 + 0 + + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + QmitkSimpleBarrierManagerWidget + QWidget +
    QmitkSimpleBarrierManagerWidget.h
    +
    + + QmitkInitialValuesManagerWidget + QWidget +
    QmitkInitialValuesManagerWidget.h
    +
    + + QmitkDataStorageComboBox + QWidget +
    QmitkDataStorageComboBox.h
    +
    +
    + + +
    diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/org_mitk_MRPerfusionView_Activator.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/org_mitk_MRPerfusionView_Activator.cpp new file mode 100644 index 0000000000..3364241759 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/org_mitk_MRPerfusionView_Activator.cpp @@ -0,0 +1,29 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "org_mitk_MRPerfusionView_Activator.h" + +#include "MRPerfusionView.h" + +void org_mitk_MRPerfusionView_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(MRPerfusionView, context); + } + + void org_mitk_MRPerfusionView_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context); + } diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/org_mitk_MRPerfusionView_Activator.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/org_mitk_MRPerfusionView_Activator.h new file mode 100644 index 0000000000..9fb289d5b9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.mri/src/internal/org_mitk_MRPerfusionView_Activator.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef org_mitk_MRPerfusionView_Activator_h +#define org_mitk_MRPerfusionView_Activator_h + +#include + + class org_mitk_MRPerfusionView_Activator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_pharmacokinetics_mri") + Q_INTERFACES(ctkPluginActivator) + + public: + + /*! + * @brief Registers the plug-in. Gets called by the framework when the plug-in is + * first loaded. + * @param context The corresponding CTK plug-in context in which the plug-in is loaded. + */ + void start(ctkPluginContext* context); + + /*! + * @brief Deregisters the plug-in. Gets called by the framework when the plug-in + * is unloaded. + * @param context The corresponding CTK plug-in context in which the plug-in was loaded. + */ + void stop(ctkPluginContext* context); + }; + +#endif diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/CMakeLists.txt b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/CMakeLists.txt new file mode 100644 index 0000000000..713e3fedb7 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/CMakeLists.txt @@ -0,0 +1,7 @@ +project(org_mitk_gui_qt_pharmacokinetics_pet) + +mitk_create_plugin( + EXPORT_DIRECTIVE MRPERFUSION_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkModelFitUI MitkPharmacokinetics +) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..7e19a3b864 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/documentation/UserManual/Manual.dox @@ -0,0 +1,7 @@ +/** +\page org_mitk_gui_qt_pharmacokinetics_pet The Dynamic PET DataFit View + +\section org_mitk_gui_qt_pharmacokinetics_pet_Overview Overview +This plug-in allows to fit dynamic PET images to different given models. + +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..06c7ca3583 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_pet org.mitk.gui.qt.pharmacokinetics.pet + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_pet_internal Internal + \ingroup org_mitk_gui_qt_pharmacokinetics_pet + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.pharmacokinetics.pet. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/files.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/files.cmake new file mode 100644 index 0000000000..6ff409c29e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/files.cmake @@ -0,0 +1,42 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_PETDynamicView_Activator.cpp + PETDynamicView.cpp +) + +set(UI_FILES + src/internal/PETDynamicViewControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_PETDynamicView_Activator.h + src/internal/PETDynamicView.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/PETDynamic.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/manifest_headers.cmake new file mode 100644 index 0000000000..87c3fac8ac --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "PET Dynamic DataFit Plugin") +set(Plugin-Version "1.0") +set(Plugin-Vendor "DKFZ, Software Development For Integrated Diagnostics and Therapy") +set(Plugin-ContactAddress "c.debus@dkfz.de") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/plugin.xml b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/plugin.xml new file mode 100644 index 0000000000..3631159e50 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/resources/PETDynamic.png b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/resources/PETDynamic.png new file mode 100644 index 0000000000..36aec5f5bd Binary files /dev/null and b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/resources/PETDynamic.png differ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/PETDynamicView.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/PETDynamicView.cpp new file mode 100644 index 0000000000..63bcebd4dc --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/PETDynamicView.cpp @@ -0,0 +1,942 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "PETDynamicView.h" + +#include "mitkWorkbenchUtil.h" + + +#include "mitkAterialInputFunctionGenerator.h" + +#include "mitkOneTissueCompartmentModelFactory.h" +#include "mitkOneTissueCompartmentModelParameterizer.h" +#include "mitkExtendedOneTissueCompartmentModelFactory.h" +#include "mitkExtendedOneTissueCompartmentModelParameterizer.h" +#include "mitkTwoTissueCompartmentFDGModelFactory.h" +#include "mitkTwoTissueCompartmentFDGModelParameterizer.h" +#include "mitkTwoTissueCompartmentModelFactory.h" +#include "mitkTwoTissueCompartmentModelParameterizer.h" +#include "mitkNumericTwoTissueCompartmentModelFactory.h" +#include "mitkNumericTwoTissueCompartmentModelParameterizer.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +// Includes for image casting between ITK and MITK +#include +#include "mitkImageCast.h" +#include "mitkITKImageImport.h" +#include +#include +#include + + +const std::string PETDynamicView::VIEW_ID = "org.mitk.gui.qt.pharmacokinetics.pet"; + +inline double convertToDouble(const std::string& data) +{ + std::istringstream stepStream(data); + double value = 0.0; + stepStream >> value; + return value; +} + +void PETDynamicView::SetFocus() +{ + m_Controls.btnModelling->setFocus(); +} + +void PETDynamicView::CreateQtPartControl(QWidget* parent) +{ + m_Controls.setupUi(parent); + + m_Controls.btnModelling->setEnabled(false); + m_Controls.errorMessageLabel->hide(); + + this->InitModelComboBox(); + + connect(m_Controls.btnModelling, SIGNAL(clicked()), this, SLOT(OnModellingButtonClicked())); + + connect(m_Controls.comboModel, SIGNAL(currentIndexChanged(int)), this, SLOT(OnModellSet(int))); + connect(m_Controls.radioPixelBased, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + + //AIF setting + m_Controls.groupAIF->hide(); + m_Controls.btnAIFFile->setEnabled(false); + m_Controls.btnAIFFile->setEnabled(false); + m_Controls.radioAIFImage->setChecked(true); + m_Controls.comboAIFMask->SetDataStorage(this->GetDataStorage()); + m_Controls.comboAIFMask->SetPredicate(m_IsMaskPredicate); + m_Controls.comboAIFMask->setVisible(true); + m_Controls.comboAIFMask->setEnabled(true); + m_Controls.comboAIFImage->SetDataStorage(this->GetDataStorage()); + m_Controls.comboAIFImage->SetPredicate(m_IsNoMaskImagePredicate); + m_Controls.comboAIFImage->setEnabled(false); + m_Controls.checkDedicatedAIFImage->setEnabled(true); + m_Controls.HCLSpinBox->setValue(0.0); + + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.comboAIFMask, + SLOT(setVisible(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.labelAIFMask, + SLOT(setVisible(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.checkDedicatedAIFImage, + SLOT(setVisible(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.comboAIFMask, + SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.checkDedicatedAIFImage, + SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.checkDedicatedAIFImage, + SLOT(setVisible(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), m_Controls.comboAIFImage, + SLOT(setVisible(bool))); + connect(m_Controls.checkDedicatedAIFImage, SIGNAL(toggled(bool)), m_Controls.comboAIFImage, + SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFImage, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + connect(m_Controls.radioAIFFile, SIGNAL(toggled(bool)), m_Controls.btnAIFFile, + SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFFile, SIGNAL(toggled(bool)), m_Controls.aifFilePath, + SLOT(setEnabled(bool))); + connect(m_Controls.radioAIFFile, SIGNAL(toggled(bool)), this, SLOT(UpdateGUIControls())); + + connect(m_Controls.btnAIFFile, SIGNAL(clicked()), this, SLOT(LoadAIFfromFile())); + + //Model fit configuration + m_Controls.groupBox_FitConfiguration->hide(); + + m_Controls.checkBox_Constraints->setEnabled(false); + m_Controls.constraintManager->setEnabled(false); + m_Controls.initialValuesManager->setEnabled(false); + m_Controls.initialValuesManager->setDataStorage(this->GetDataStorage()); + + connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)), this, + SLOT(UpdateGUIControls())); + connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), this, + SLOT(UpdateGUIControls())); + connect(m_Controls.initialValuesManager, SIGNAL(initialValuesChanged(void)), this, SLOT(UpdateGUIControls())); + + + connect(m_Controls.radioButton_StartParameters, SIGNAL(toggled(bool)), + m_Controls.initialValuesManager, + SLOT(setEnabled(bool))); + connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager, + SLOT(setEnabled(bool))); + connect(m_Controls.checkBox_Constraints, SIGNAL(toggled(bool)), m_Controls.constraintManager, + SLOT(setVisible(bool))); + + + UpdateGUIControls(); + +} + +void PETDynamicView::UpdateGUIControls() +{ + m_Controls.lineFitName->setPlaceholderText(QString::fromStdString(this->GetDefaultFitName())); + m_Controls.lineFitName->setEnabled(!m_FittingInProgress); + + m_Controls.checkBox_Constraints->setEnabled(m_modelConstraints.IsNotNull()); + + bool is1TCMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isExt1TCMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isFDGCMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + bool is2TCMFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL || + dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + + m_Controls.groupAIF->setVisible(is1TCMFactory || isExt1TCMFactory || isFDGCMFactory || is2TCMFactory); + + m_Controls.groupBox_FitConfiguration->setVisible(m_selectedModelFactory); + + m_Controls.groupBox->setEnabled(!m_FittingInProgress); + m_Controls.comboModel->setEnabled(!m_FittingInProgress); + m_Controls.groupAIF->setEnabled(!m_FittingInProgress); + m_Controls.groupBox_FitConfiguration->setEnabled(!m_FittingInProgress); + + m_Controls.radioROIbased->setEnabled(m_selectedMask.IsNotNull()); + + m_Controls.btnModelling->setEnabled(m_selectedImage.IsNotNull() + && m_selectedModelFactory.IsNotNull() && !m_FittingInProgress && CheckModelSettings()); +} + +//void PETDynamicView::OnModelSettingChanged() +//{ +// bool ok = m_selectedImage.IsNotNull() && m_selectedModelFactory.IsNotNull() && !m_FittingInProgress && CheckModelSettings(); + +// m_Controls.btnModelling->setEnabled(ok); +//} + + +void PETDynamicView::OnModellSet(int index) +{ + m_selectedModelFactory = NULL; + + if (index > 0) + { + if (static_cast(index) <= m_FactoryStack.size() ) + { + m_selectedModelFactory = m_FactoryStack[index - 1]; + } + else + { + MITK_WARN << "Invalid model index. Index outside of the factory stack. Factory stack size: "<< m_FactoryStack.size() << "; invalid index: "<< index; + } + } + + if (m_selectedModelFactory) + { + this->m_modelConstraints = dynamic_cast + (m_selectedModelFactory->CreateDefaultConstraints().GetPointer()); + + m_Controls.initialValuesManager->setInitialValues(m_selectedModelFactory->GetParameterNames(), + m_selectedModelFactory->GetDefaultInitialParameterization()); + + if (this->m_modelConstraints.IsNull()) + { + this->m_modelConstraints = mitk::SimpleBarrierConstraintChecker::New(); + } + + m_Controls.constraintManager->setChecker(this->m_modelConstraints, + this->m_selectedModelFactory->GetParameterNames()); + } + + m_Controls.checkBox_Constraints->setEnabled(m_modelConstraints.IsNotNull()); + + + UpdateGUIControls(); +} + +std::string PETDynamicView::GetDefaultFitName() const +{ + std::string defaultName = "undefined model"; + + if (this->m_selectedModelFactory.IsNotNull()) + { + defaultName = this->m_selectedModelFactory->GetClassID(); + } + + if (this->m_Controls.radioPixelBased->isChecked()) + { + defaultName += "_pixel"; + } + else + { + defaultName += "_roi"; + } + + return defaultName; +} + + +void PETDynamicView::OnModellingButtonClicked() +{ + //check if all static parameters set + if (m_selectedModelFactory.IsNotNull() && CheckModelSettings()) + { + mitk::ParameterFitImageGeneratorBase::Pointer generator = NULL; + mitk::modelFit::ModelFitInfo::Pointer fitSession = NULL; + + + bool isOTCFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isextOTCFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + bool isFDGFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + bool isTTCFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isNumTTCFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + + if (isOTCFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateModelFit_ROIBased(fitSession, generator); + } + } + + else if (isextOTCFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateModelFit_ROIBased(fitSession, generator); + } + } + else if (isFDGFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateModelFit_ROIBased(fitSession, generator); + } + } + + + else if (isTTCFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateModelFit_PixelBased(fitSession, generator); + } + else + { + GenerateModelFit_ROIBased(fitSession, generator); + } + } + + else if (isNumTTCFactory) + { + if (this->m_Controls.radioPixelBased->isChecked()) + { + GenerateModelFit_PixelBased(fitSession, + generator); + } + else + { + GenerateModelFit_ROIBased(fitSession, + generator); + } + } + + //add other models with else if + + if (generator.IsNotNull() && fitSession.IsNotNull()) + { + m_FittingInProgress = true; + DoFit(fitSession, generator); + } + else + { + QMessageBox box; + box.setText("Fitting error!"); + box.setInformativeText("Could not establish fitting job. Error when setting ab generator, model parameterizer or session info."); + box.setStandardButtons(QMessageBox::Ok); + box.setDefaultButton(QMessageBox::Ok); + box.setIcon(QMessageBox::Warning); + box.exec(); + } + + } + else + { + QMessageBox box; + box.setText("Static parameters for model are not set!"); + box.setInformativeText("Some static parameters, that are needed for calculation are not set and equal to zero. Modeling not possible"); + box.setStandardButtons(QMessageBox::Ok); + box.setDefaultButton(QMessageBox::Ok); + box.setIcon(QMessageBox::Warning); + box.exec(); + } +} + + +void PETDynamicView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, + const QList& selectedNodes) +{ + m_selectedMaskNode = NULL; + m_selectedMask = NULL; + + m_Controls.errorMessageLabel->setText(""); + m_Controls.masklabel->setText("No (valid) mask selected."); + m_Controls.timeserieslabel->setText("No (valid) series selected."); + + QList nodes = selectedNodes; + + if (nodes.size() > 0 && this->m_IsNoMaskImagePredicate->CheckNode(nodes.front())) + { + this->m_selectedNode = nodes.front(); + auto selectedImage = dynamic_cast(this->m_selectedNode->GetData()); + m_Controls.timeserieslabel->setText((this->m_selectedNode->GetName()).c_str()); + + if (selectedImage != this->m_selectedImage) + { + if (selectedImage) + { + this->m_Controls.initialValuesManager->setReferenceImageGeometry(selectedImage->GetGeometry()); + } + else + { + this->m_Controls.initialValuesManager->setReferenceImageGeometry(nullptr); + } + } + this->m_selectedImage = selectedImage; + nodes.pop_front(); + } + else + { + this->m_selectedNode = NULL; + this->m_selectedImage = NULL; + this->m_Controls.initialValuesManager->setReferenceImageGeometry(nullptr); + } + + if (nodes.size() > 0 && this->m_IsMaskPredicate->CheckNode(nodes.front())) + { + this->m_selectedMaskNode = nodes.front(); + this->m_selectedMask = dynamic_cast(this->m_selectedMaskNode->GetData()); + + if (this->m_selectedMask->GetTimeSteps() > 1) + { + MITK_INFO << + "Selected mask has multiple timesteps. Only use first timestep to mask model fit. Mask name: " << + m_selectedMaskNode->GetName(); + mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); + maskedImageTimeSelector->SetInput(this->m_selectedMask); + maskedImageTimeSelector->SetTimeNr(0); + maskedImageTimeSelector->UpdateLargestPossibleRegion(); + this->m_selectedMask = maskedImageTimeSelector->GetOutput(); + } + + m_Controls.masklabel->setText((this->m_selectedMaskNode->GetName()).c_str()); + } + + if (m_selectedMask.IsNull()) + { + this->m_Controls.radioPixelBased->setChecked(true); + } + + m_Controls.errorMessageLabel->show(); + + UpdateGUIControls(); +} + +bool PETDynamicView::CheckModelSettings() const +{ + bool ok = true; + + //check wether any model is set at all. Otherwise exit with false + if (m_selectedModelFactory.IsNotNull()) + { + + bool isOTCFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isextOTCFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isFDGFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isTTCFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + bool isNumTTCFactory = dynamic_cast + (m_selectedModelFactory.GetPointer()) != NULL; + + if (isOTCFactory || isextOTCFactory || isFDGFactory || isTTCFactory || isNumTTCFactory) + { + if (this->m_Controls.radioAIFImage->isChecked()) + { + ok = ok && m_Controls.comboAIFMask->GetSelectedNode().IsNotNull(); + + if (this->m_Controls.checkDedicatedAIFImage->isChecked()) + { + ok = ok && m_Controls.comboAIFImage->GetSelectedNode().IsNotNull(); + } + } + else if (this->m_Controls.radioAIFFile->isChecked()) + { + ok = ok && (this->AIFinputGrid.size() != 0) && (this->AIFinputFunction.size() != 0); + } + else + { + ok = false; + } + + } + //add other models as else if and check wether all needed static parameters are set + else + { + ok = false; + } + + if (this->m_Controls.radioButton_StartParameters->isChecked() && !this->m_Controls.initialValuesManager->hasValidInitialValues()) + { + std::string warning = "Warning. Invalid start parameters. At least one parameter as an invalid image setting as source."; + MITK_ERROR << warning; + m_Controls.infoBox->append(QString("") + QString::fromStdString(warning) + QString("")); + + ok = false; + }; + } + else + { + ok = false; + } + + return ok; +} + +void PETDynamicView::ConfigureInitialParametersOfParameterizer(mitk::ModelParameterizerBase* + parameterizer) const +{ + if (m_Controls.radioButton_StartParameters->isChecked()) + { + //use user defined initial parameters + mitk::InitialParameterizationDelegateBase::Pointer paramDelegate = m_Controls.initialValuesManager->getInitialParametrizationDelegate(); + parameterizer->SetInitialParameterizationDelegate(paramDelegate); + } +} + +template +void PETDynamicView::GenerateModelFit_PixelBased( + mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::PixelBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::PixelBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + + mitk::AIFBasedModelBase::AterialInputFunctionType aif; + mitk::AIFBasedModelBase::TimeGridType aifTimeGrid; + + GetAIF(aif, aifTimeGrid); + + //Model configuration (static parameters) can be done now + modelParameterizer->SetAIF(aif); + modelParameterizer->SetAIFTimeGrid(aifTimeGrid); + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + std::string roiUID = ""; + + if (m_selectedMask.IsNotNull()) + { + fitGenerator->SetMask(m_selectedMask); + roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + } + + fitGenerator->SetDynamicImage(this->m_selectedImage); + fitGenerator->SetFitFunctor(fitFunctor); + + generator = fitGenerator.GetPointer(); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_PIXELBASED(), roiUID); + + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = aif.begin(); + pos != aif.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("AIF", infoSignal); +} + + +template +void PETDynamicView::GenerateModelFit_ROIBased( + mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator) +{ + mitk::ROIBasedParameterFitImageGenerator::Pointer fitGenerator = + mitk::ROIBasedParameterFitImageGenerator::New(); + + typename TParameterizer::Pointer modelParameterizer = + TParameterizer::New(); + + + //Compute AIF + mitk::AterialInputFunctionGenerator::Pointer aifGenerator = + mitk::AterialInputFunctionGenerator::New(); + aifGenerator->SetDynamicImage(this->m_selectedImage); + aifGenerator->SetMask(this->m_selectedAIFMask); + + mitk::AIFBasedModelBase::AterialInputFunctionType aif = aifGenerator->GetAterialInputFunction(); + mitk::AIFBasedModelBase::TimeGridType aifTimeGrid = aifGenerator->GetAterialInputFunctionTimeGrid(); + + //Model configuration (static parameters) can be done now + modelParameterizer->SetAIF(aif); + modelParameterizer->SetAIFTimeGrid(aifTimeGrid); + + this->ConfigureInitialParametersOfParameterizer(modelParameterizer); + + //Compute ROI signal + mitk::MaskedDynamicImageStatisticsGenerator::Pointer signalGenerator = + mitk::MaskedDynamicImageStatisticsGenerator::New(); + signalGenerator->SetMask(m_selectedMask); + signalGenerator->SetDynamicImage(m_selectedImage); + signalGenerator->Generate(); + + mitk::MaskedDynamicImageStatisticsGenerator::ResultType roiSignal = signalGenerator->GetMean(); + + //Specify fitting strategy and criterion parameters + mitk::ModelFitFunctorBase::Pointer fitFunctor = CreateDefaultFitFunctor(modelParameterizer); + + //Parametrize fit generator + fitGenerator->SetModelParameterizer(modelParameterizer); + fitGenerator->SetMask(m_selectedMask); + fitGenerator->SetFitFunctor(fitFunctor); + fitGenerator->SetSignal(roiSignal); + fitGenerator->SetTimeGrid(mitk::ExtractTimeGrid(m_selectedImage)); + + generator = fitGenerator.GetPointer(); + + std::string roiUID = mitk::EnsureModelFitUID(this->m_selectedMaskNode); + + //Create model info + modelFitInfo = mitk::modelFit::CreateFitInfoFromModelParameterizer(modelParameterizer, + m_selectedNode->GetData(), mitk::ModelFitConstants::FIT_TYPE_VALUE_ROIBASED(), roiUID); + + mitk::ScalarListLookupTable::ValueType infoSignal; + + for (mitk::MaskedDynamicImageStatisticsGenerator::ResultType::const_iterator pos = + roiSignal.begin(); pos != roiSignal.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("ROI", infoSignal); + + infoSignal.clear(); + + for (mitk::AIFBasedModelBase::AterialInputFunctionType::const_iterator pos = aif.begin(); + pos != aif.end(); ++pos) + { + infoSignal.push_back(*pos); + } + + modelFitInfo->inputData.SetTableValue("AIF", infoSignal); +} + +void PETDynamicView::DoFit(const mitk::modelFit::ModelFitInfo* fitSession, + mitk::ParameterFitImageGeneratorBase* generator) +{ + std::stringstream message; + message << "" << "Fitting Data Set . . ." << ""; + m_Controls.errorMessageLabel->setText(message.str().c_str()); + m_Controls.errorMessageLabel->show(); + + ///////////////////////// + //create job and put it into the thread pool + std::string fitName = m_Controls.lineFitName->text().toStdString(); + if (fitName.empty()) + { + fitName = m_Controls.lineFitName->placeholderText().toStdString(); + } + + ParameterFitBackgroundJob* pJob = new ParameterFitBackgroundJob(generator, fitSession, fitName, + this->m_selectedNode); + + pJob->setAutoDelete(true); + + connect(pJob, SIGNAL(Error(QString)), this, SLOT(OnJobError(QString))); + connect(pJob, SIGNAL(Finished()), this, SLOT(OnJobFinished())); + connect(pJob, SIGNAL(ResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const ParameterFitBackgroundJob*)), this, + SLOT(OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType, + const ParameterFitBackgroundJob*)), Qt::BlockingQueuedConnection); + + connect(pJob, SIGNAL(JobProgress(double)), this, SLOT(OnJobProgress(double))); + connect(pJob, SIGNAL(JobStatusChanged(QString)), this, SLOT(OnJobStatusChanged(QString))); + + QThreadPool* threadPool = QThreadPool::globalInstance(); + threadPool->start(pJob); +} + +PETDynamicView::PETDynamicView() : m_FittingInProgress(false) +{ + m_selectedImage = NULL; + m_selectedMask = NULL; + + mitk::ModelFactoryBase::Pointer factory = + mitk::OneTissueCompartmentModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::ExtendedOneTissueCompartmentModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::TwoTissueCompartmentModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::TwoTissueCompartmentFDGModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::NumericTwoTissueCompartmentModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + + mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage"); + mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image"); + mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); + mitk::NodePredicateAnd::Pointer isLegacyMask = mitk::NodePredicateAnd::New(isImage, isBinary); + + mitk::NodePredicateOr::Pointer isMask = mitk::NodePredicateOr::New(isLegacyMask, isLabelSet); + mitk::NodePredicateAnd::Pointer isNoMask = mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isMask)); + + this->m_IsMaskPredicate = mitk::NodePredicateAnd::New(isMask, mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer(); + + this->m_IsNoMaskImagePredicate = mitk::NodePredicateAnd::New(isNoMask, mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer(); + +} + +void PETDynamicView::OnJobFinished() +{ + this->m_Controls.infoBox->append(QString("Fitting finished")); + this->m_FittingInProgress = false; +}; + +void PETDynamicView::OnJobError(QString err) +{ + MITK_ERROR << err.toStdString().c_str(); + + m_Controls.infoBox->append(QString("") + err + QString("")); + +}; + +void PETDynamicView::OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType results, + const ParameterFitBackgroundJob* pJob) +{ + //Store the resulting parameter fit image via convenience helper function in data storage + //(handles the correct generation of the nodes and their properties) + mitk::modelFit::StoreResultsInDataStorage(this->GetDataStorage(), results, pJob->GetParentNode()); + + m_Controls.errorMessageLabel->setText(""); + m_Controls.errorMessageLabel->hide(); +}; + +void PETDynamicView::OnJobProgress(double progress) +{ + QString report = QString("Progress. ") + QString::number(progress); + this->m_Controls.infoBox->append(report); +}; + +void PETDynamicView::OnJobStatusChanged(QString info) +{ + this->m_Controls.infoBox->append(info); +} + + +void PETDynamicView::InitModelComboBox() const +{ + this->m_Controls.comboModel->clear(); + this->m_Controls.comboModel->addItem(tr("No model selected")); + + for (ModelFactoryStackType::const_iterator pos = m_FactoryStack.begin(); + pos != m_FactoryStack.end(); ++pos) + { + this->m_Controls.comboModel->addItem(QString::fromStdString((*pos)->GetClassID())); + } + + this->m_Controls.comboModel->setCurrentIndex(0); +}; + +mitk::ModelFitFunctorBase::Pointer PETDynamicView::CreateDefaultFitFunctor( + const mitk::ModelParameterizerBase* parameterizer) const +{ + mitk::LevenbergMarquardtModelFitFunctor::Pointer fitFunctor = + mitk::LevenbergMarquardtModelFitFunctor::New(); + mitk::SumOfSquaredDifferencesFitCostFunction::Pointer evaluation = + mitk::SumOfSquaredDifferencesFitCostFunction::New(); + + fitFunctor->RegisterEvaluationParameter("sum_diff^2", evaluation); + + mitk::ChiSquareFitCostFunction::Pointer chi2 = + mitk::ChiSquareFitCostFunction::New(); + fitFunctor->RegisterEvaluationParameter("Chi^2", chi2); + + mitk::ReducedChiSquareFitCostFunction::Pointer redchi2 = + mitk::ReducedChiSquareFitCostFunction::New(); + fitFunctor->RegisterEvaluationParameter("redChi^2", redchi2); + + + + if (m_Controls.checkBox_Constraints->isChecked()) + { + fitFunctor->SetConstraintChecker(m_modelConstraints); + } + + mitk::ModelBase::Pointer refModel = parameterizer->GenerateParameterizedModel(); + + ::itk::LevenbergMarquardtOptimizer::ScalesType scales; + scales.SetSize(refModel->GetNumberOfParameters()); + scales.Fill(1.0); + fitFunctor->SetScales(scales); + + return fitFunctor.GetPointer(); +} + +void PETDynamicView::GetAIF(mitk::AIFBasedModelBase::AterialInputFunctionType& aif, + mitk::AIFBasedModelBase::AterialInputFunctionType& aifTimeGrid) +{ + if (this->m_Controls.radioAIFFile->isChecked()) + { + aif.clear(); + aifTimeGrid.clear(); + + aif.SetSize(AIFinputFunction.size()); + aifTimeGrid.SetSize(AIFinputGrid.size()); + + aif.fill(0.0); + aifTimeGrid.fill(0.0); + + itk::Array::iterator aifPos = aif.begin(); + + for (std::vector::const_iterator pos = AIFinputFunction.begin(); + pos != AIFinputFunction.end(); ++pos, ++aifPos) + { + *aifPos = *pos; + } + + itk::Array::iterator gridPos = aifTimeGrid.begin(); + + for (std::vector::const_iterator pos = AIFinputGrid.begin(); pos != AIFinputGrid.end(); + ++pos, ++gridPos) + { + *gridPos = *pos; + } + } + else if (this->m_Controls.radioAIFImage->isChecked()) + { + aif.clear(); + aifTimeGrid.clear(); + + mitk::AterialInputFunctionGenerator::Pointer aifGenerator = + mitk::AterialInputFunctionGenerator::New(); + + //Hematocrit level + aifGenerator->SetHCL(this->m_Controls.HCLSpinBox->value()); + + //mask settings + this->m_selectedAIFMaskNode = m_Controls.comboAIFMask->GetSelectedNode(); + this->m_selectedAIFMask = dynamic_cast(this->m_selectedAIFMaskNode->GetData()); + + if (this->m_selectedAIFMask->GetTimeSteps() > 1) + { + MITK_INFO << + "Selected AIF mask has multiple timesteps. Only use first timestep to mask model fit. AIF Mask name: " + << + m_selectedAIFMaskNode->GetName() ; + mitk::ImageTimeSelector::Pointer maskedImageTimeSelector = mitk::ImageTimeSelector::New(); + maskedImageTimeSelector->SetInput(this->m_selectedAIFMask); + maskedImageTimeSelector->SetTimeNr(0); + maskedImageTimeSelector->UpdateLargestPossibleRegion(); + this->m_selectedAIFMask = maskedImageTimeSelector->GetOutput(); + } + + if (this->m_selectedAIFMask.IsNotNull()) + { + aifGenerator->SetMask(this->m_selectedAIFMask); + } + + //image settings + if (this->m_Controls.checkDedicatedAIFImage->isChecked()) + { + this->m_selectedAIFImageNode = m_Controls.comboAIFImage->GetSelectedNode(); + this->m_selectedAIFImage = dynamic_cast(this->m_selectedAIFImageNode->GetData()); + } + else + { + this->m_selectedAIFImageNode = m_selectedNode; + this->m_selectedAIFImage = m_selectedImage; + } + + + aifGenerator->SetDynamicImage(this->m_selectedAIFImage); + + aif = aifGenerator->GetAterialInputFunction(); + aifTimeGrid = aifGenerator->GetAterialInputFunctionTimeGrid(); + } + else + { + mitkThrow() << "Cannot generate AIF. View is in a invalide state. No AIF mode selected."; + } + +} + + +void PETDynamicView::LoadAIFfromFile() +{ + QFileDialog dialog; + dialog.setNameFilter(tr("Images (*.csv")); + + QString fileName = dialog.getOpenFileName(); + + m_Controls.aifFilePath->setText(fileName); + + std::string m_aifFilePath = fileName.toStdString(); + //Read Input + typedef boost::tokenizer< boost::escaped_list_separator > Tokenizer; + ///////////////////////////////////////////////////////////////////////////////////////////////// + //AIF Data + + std::ifstream in1(m_aifFilePath.c_str()); + + if (!in1.is_open()) + { + m_Controls.errorMessageLabel->setText("Could not open AIF File!"); + } + + + std::vector< std::string > vec1; + std::string line1; + + while (getline(in1, line1)) + { + Tokenizer tok(line1); + vec1.assign(tok.begin(), tok.end()); + + // if (vec1.size() < 3) continue; + + this->AIFinputGrid.push_back(convertToDouble(vec1[0])); + this->AIFinputFunction.push_back(convertToDouble(vec1[1])); + + } + +} diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/PETDynamicView.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/PETDynamicView.h new file mode 100644 index 0000000000..0e6ab0e70e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/PETDynamicView.h @@ -0,0 +1,174 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef PETDynamicView_h +#define PETDynamicView_h + +#include + +#include "QmitkAbstractView.h" + +#include "itkCommand.h" + +#include "ui_PETDynamicViewControls.h" +#include "mitkModelBase.h" +#include "QmitkParameterFitBackgroundJob.h" +#include "mitkModelFitResultHelper.h" +#include "mitkModelFactoryBase.h" +#include "mitkLevenbergMarquardtModelFitFunctor.h" +#include "mitkSimpleBarrierConstraintChecker.h" +#include "mitkAIFBasedModelBase.h" + +/*! +* @brief Test Plugin for SUV calculations of PET images +*/ +class PETDynamicView : public QmitkAbstractView +{ + Q_OBJECT + +public: + + /*! @brief The view's unique ID - required by MITK */ + static const std::string VIEW_ID; + + PETDynamicView(); + +protected slots: + + + void OnModellingButtonClicked(); + + void OnJobFinished(); + void OnJobError(QString err); + void OnJobResultsAreAvailable(mitk::modelFit::ModelFitResultNodeVectorType results, + const ParameterFitBackgroundJob* pJob); + void OnJobProgress(double progress); + void OnJobStatusChanged(QString info); + + void OnModellSet(int); + void LoadAIFfromFile(); + +// void OnModelSettingChanged(); + void UpdateGUIControls(); + +protected: + typedef QList SelectedDataNodeVectorType; + + // Overridden base class functions + + /*! + * @brief Sets up the UI controls and connects the slots and signals. Gets + * called by the framework to create the GUI at the right time. + * @param[in,out] parent The parent QWidget, as this class itself is not a QWidget + * subclass. + */ + void CreateQtPartControl(QWidget* parent); + + /*! + * @brief Sets the focus to the plot curve button. Gets called by the framework to set the + * focus on the right widget. + */ + void SetFocus(); + + /*! @brief Generates a configured fit generator and the corresponding modelinfo for a descriptive brix model with pixel based strategy. + * @remark add GenerateFunction for each model in the Combo box*/ + + template + void GenerateModelFit_ROIBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + + template + void GenerateModelFit_PixelBased(mitk::modelFit::ModelFitInfo::Pointer& modelFitInfo, + mitk::ParameterFitImageGeneratorBase::Pointer& generator); + + /** Helper function that configures the initial parameter strategy of a parameterizer + according to the settings of the GUI.*/ + void ConfigureInitialParametersOfParameterizer(mitk::ModelParameterizerBase* parameterizer) const; + + /*! Starts the fitting job with the passed generator and session info*/ + void DoFit(const mitk::modelFit::ModelFitInfo* fitSession, + mitk::ParameterFitImageGeneratorBase* generator); + + bool CheckModelSettings() const; + + void InitModelComboBox() const; + + /*! \brief called by QmitkFunctionality when DataManager's selection has changed + */ + virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, + const QList& selectedNodes); + + + /*! @brief The view's UI controls */ + Ui::PETDynamicViewControls m_Controls; + + mitk::DataNode::Pointer m_selectedNode; + mitk::DataNode::Pointer m_selectedMaskNode; + mitk::DataNode::Pointer m_selectedAIFMaskNode; + mitk::DataNode::Pointer m_selectedAIFImageNode; + + mitk::Image::Pointer m_selectedImage; + mitk::Image::Pointer m_selectedMask; + mitk::Image::Pointer m_selectedAIFMask; + mitk::Image::Pointer m_selectedAIFImage; + + /* Node used for the fit (my be the selected image + or converted ones (depending on the ui settings */ + mitk::DataNode::Pointer m_inputNode; + mitk::DataNode::Pointer m_inputAIFNode; + + /* Image used for the fit (my be the selected image + or converted ones (depending on the ui settings */ + mitk::Image::Pointer m_inputImage; + mitk::Image::Pointer m_inputAIFImage; + + mitk::ModelFactoryBase::Pointer m_selectedModelFactory; + + mitk::SimpleBarrierConstraintChecker::Pointer m_modelConstraints; + + +private: + bool m_FittingInProgress; + + + typedef std::vector ModelFactoryStackType; + ModelFactoryStackType m_FactoryStack; + + /**Helper function that (depending on the gui settings) generates and passes back the AIF and its time grid + that should be used for fitting. + @remark the parameters aif and aifTimeGrid will be initialized accordingly if the method returns.*/ + void GetAIF(mitk::AIFBasedModelBase::AterialInputFunctionType& aif, + mitk::AIFBasedModelBase::AterialInputFunctionType& aifTimeGrid); + + /**Helper function that generates a default fitting functor + * default is a levenberg marquart based optimizer with all scales set to 1.0. + * Constraint setter will be set based on the gui setting and a evaluation parameter + * "sum of squared differences" will always be set.*/ + mitk::ModelFitFunctorBase::Pointer CreateDefaultFitFunctor(const mitk::ModelParameterizerBase* + parameterizer) const; + + /**Returns the default fit name, derived from the current GUI settings.*/ + std::string GetDefaultFitName() const; + + std::vector AIFinputGrid; + std::vector AIFinputFunction; + + mitk::NodePredicateBase::Pointer m_IsNoMaskImagePredicate; + mitk::NodePredicateBase::Pointer m_IsMaskPredicate; + +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/PETDynamicViewControls.ui b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/PETDynamicViewControls.ui new file mode 100644 index 0000000000..7d15ec19da --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/PETDynamicViewControls.ui @@ -0,0 +1,325 @@ + + + PETDynamicViewControls + + + + 0 + 0 + 745 + 898 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + + + + Selected Time Series: + + + + + + + No series selected. + + + + + + + + + + + Selected Mask: + + + + + + + No mask selected. + + + + + + + + + Fitting strategy + + + + 5 + + + 5 + + + + + Pixel based + + + true + + + + + + + ROI based + + + + + + + + + + + + Message + + + + + + + - + + + + + + + + + + + + Select pharmacokinetic modell... + + + + + + + + AIF Mask: + + + + + + Select AIF from Image: + + + + + + + + + AIF Mask: + + + + + + + Dedicated AIF Image: + + + + + + + + + + + + + + + + + Select AIF from File: + + + + + + + + + + Browse + + + + + + + + + + + Whole Blood to Plasma Correction: + + + + + + + + + + + + + + + Model Fit Configuration + + + + + + 1 + + + + + 0 + 0 + 701 + 129 + + + + + + + + + + Start Parameters + + + + + + Enter parameter starting values manually: + + + + + + + + + + + + 0 + 0 + 701 + 129 + + + + Constraints + + + + + + Enter Constraints for Fit Parameters + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + Fitting name: + + + + + + + + + + + + Start Modelling + + + + + + + true + + + + + + + + + QmitkSimpleBarrierManagerWidget + QWidget +
    QmitkSimpleBarrierManagerWidget.h
    +
    + + QmitkInitialValuesManagerWidget + QWidget +
    QmitkInitialValuesManagerWidget.h
    +
    + + QmitkDataStorageComboBox + QWidget +
    QmitkDataStorageComboBox.h
    +
    +
    + + +
    diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/org_mitk_PETDynamicView_Activator.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/org_mitk_PETDynamicView_Activator.cpp new file mode 100644 index 0000000000..2af122c47b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/org_mitk_PETDynamicView_Activator.cpp @@ -0,0 +1,29 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "org_mitk_PETDynamicView_Activator.h" + +#include "PETDynamicView.h" + + void org_mitk_PETDynamicView_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(PETDynamicView, context); + } + + void org_mitk_PETDynamicView_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context); + } diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/org_mitk_PETDynamicView_Activator.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/org_mitk_PETDynamicView_Activator.h new file mode 100644 index 0000000000..8d365615ee --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.pet/src/internal/org_mitk_PETDynamicView_Activator.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef org_mitk_PETDynamicView_Activator_h +#define org_mitk_PETDynamicView_Activator_h + +#include + + class org_mitk_PETDynamicView_Activator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_pharmacokinetics_pet") + Q_INTERFACES(ctkPluginActivator) + + public: + + /*! + * @brief Registers the plug-in. Gets called by the framework when the plug-in is + * first loaded. + * @param context The corresponding CTK plug-in context in which the plug-in is loaded. + */ + void start(ctkPluginContext* context); + + /*! + * @brief Deregisters the plug-in. Gets called by the framework when the plug-in + * is unloaded. + * @param context The corresponding CTK plug-in context in which the plug-in was loaded. + */ + void stop(ctkPluginContext* context); + }; + +#endif diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/CMakeLists.txt b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/CMakeLists.txt new file mode 100644 index 0000000000..945352fc13 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/CMakeLists.txt @@ -0,0 +1,9 @@ +project(org_mitk_gui_qt_pharmacokinetics_simulation) + +mitk_create_plugin( + EXPORT_DIRECTIVE PERFUSIONDATASIMULATION_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkPharmacokinetics + PACKAGE_DEPENDS + PRIVATE Boost +) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..667143d2b5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/documentation/UserManual/Manual.dox @@ -0,0 +1,5 @@ +/** +\page org_mitk_gui_qt_pharmacokinetics_simulation The Perfusion Data Simulation View + + +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..f949cca550 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_simulation org.mitk.gui.qt.pharmacokinetics.simulation + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_pharmacokinetics_simulation_internal Internal + \ingroup org_mitk_gui_qt_pharmacokinetics_simulation + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.pharmacokinetics.simulation plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/files.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/files.cmake new file mode 100644 index 0000000000..f1b410b7ce --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/files.cmake @@ -0,0 +1,43 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_PerfusionDataSimulationView_Activator.cpp + PerfusionDataSimulationView.cpp + +) + +set(UI_FILES + src/internal/PerfusionDataSimulationViewControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_PerfusionDataSimulationView_Activator.h + src/internal/PerfusionDataSimulationView.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/icon_PerfusionDataGeneration.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/manifest_headers.cmake new file mode 100644 index 0000000000..4134f6923e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Perfusion Data Simulation Plugin") +set(Plugin-Version "1.0") +set(Plugin-Vendor "DKFZ, Software Development For Integrated Diagnostics and Therapy") +set(Plugin-ContactAddress "c.debus@dkfz.de") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/plugin.xml b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/plugin.xml new file mode 100644 index 0000000000..8528041735 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/resources/icon_PerfusionDataGeneration.png b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/resources/icon_PerfusionDataGeneration.png new file mode 100644 index 0000000000..14a7784dd2 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/resources/icon_PerfusionDataGeneration.png differ diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/PerfusionDataSimulationView.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/PerfusionDataSimulationView.cpp new file mode 100644 index 0000000000..b2d30bc4a9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/PerfusionDataSimulationView.cpp @@ -0,0 +1,1024 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include "mitkWorkbenchUtil.h" + +#include "PerfusionDataSimulationView.h" + +#include "itkUnaryFunctorImageFilter.h" +#include +#include "mitkImageCast.h" +#include "mitkImageTimeSelector.h" +#include "mitkITKImageImport.h" +#include "mitkGaussianNoiseFunctor.h" +#include "mitkTwoCompartmentExchangeModel.h" +#include "mitkTwoCompartmentExchangeModelParameterizer.h" +#include "mitkTwoCompartmentExchangeModelFactory.h" +#include "mitkNumericTwoCompartmentExchangeModel.h" +#include "mitkNumericTwoCompartmentExchangeModelParameterizer.h" +#include "mitkNumericTwoCompartmentExchangeModelFactory.h" +#include "mitkExtendedToftsModel.h" +#include "mitkExtendedToftsModelFactory.h" +#include "mitkExtendedToftsModelParameterizer.h" +#include "mitkTwoTissueCompartmentModel.h" +#include "mitkTwoTissueCompartmentModelParameterizer.h" +#include "mitkTwoTissueCompartmentModelFactory.h" +#include "mitkOneTissueCompartmentModel.h" +#include "mitkOneTissueCompartmentModelParameterizer.h" +#include "mitkOneTissueCompartmentModelFactory.h" +#include "mitkPerfusionDataGenerator.h" +#include +#include +#include +#include +#include "mitkSimpleFunctorBase.h" +#include "mitkArbitraryTimeGeometry.h" +#include + #include + +const std::string PerfusionDataSimulationView::VIEW_ID = "org.mitk.gui.qt.pharmacokinetics.simulation"; + +inline double convertToDouble(const std::string& data) +{ + std::istringstream stepStream(data); + stepStream.imbue(std::locale("C")); + double value = 0.0; + + if (!(stepStream >> value) || !(stepStream.eof())) + { + mitkThrow() << "Cannot convert string to double. String: " << data; + } + return value; +} + +inline double FindeMaxConcentration(std::vector Concentration) +{ + double maximum = Concentration[0]; + for (std::vector::size_type i =0; isetFocus(); +} + +void PerfusionDataSimulationView::CreateQtPartControl(QWidget* parent) +{ + m_Controls.setupUi(parent); + m_Controls.GenerateBtn->setEnabled(false); + + m_Controls.groupBox_TM->hide(); + m_Controls.groupBox_2CXM->hide(); + m_Controls.groupBox_2TCM->hide(); + m_Controls.groupBox_1TCM->hide(); + m_Controls.groupBox_CNR->hide(); + + this->InitModelComboBox(); + /** #2 @todo Reduce code ? + */ + + m_Controls.comboBox_F->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_F->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_PS->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_PS->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_fp->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_fp->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_fi->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_fi->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_Ktrans->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_Ktrans->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_vp->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_vp->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_ve->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_ve->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_K1->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_K1->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_K2->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_K2->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_K3->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_K3->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_K4->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_K4->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_VB->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_VB->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_k1->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_k1->SetPredicate(m_IsNotABinaryImagePredicate); + + m_Controls.comboBox_k2->SetDataStorage(this->GetDataStorage()); + m_Controls.comboBox_k2->SetPredicate(m_IsNotABinaryImagePredicate); + + connect(m_Controls.AifFileBtn, SIGNAL(clicked()), this, SLOT(LoadAIFFile())); + connect(m_Controls.ModelSelection, SIGNAL(currentIndexChanged(int)), this, SLOT(OnModellSet(int))); + connect(m_Controls.GenerateBtn, SIGNAL(clicked()), this, SLOT(OnGenerateDataButtonClicked())); + connect(m_Controls.comboBox_F, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_PS, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_fp, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_fi, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_VB, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_K1, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_K2, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_K3, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_K4, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_k1, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_k2, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_Ktrans, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_vp, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.comboBox_ve, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.CNRSpinBox, SIGNAL(valueChanged(double)),this, SLOT(OnSimulationConfigurationChanged())); + connect(m_Controls.NoiseCheckBox, SIGNAL(stateChanged(int)),this, SLOT(OnSimulationConfigurationChanged())); + +// UpdateDataSelection(); + + } + +void PerfusionDataSimulationView::UpdateDataSelection() +{ + + +} + +//void PerfusionDataSimulationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, +// const QList& selectedNodes) +//{ +// UpdateDataSelection(); +// m_Controls.GenerateBtn->setEnabled(CheckModelSettings()); + +//} + +void PerfusionDataSimulationView::OnSimulationConfigurationChanged() +{ +// UpdateDataSelection(); + + m_Controls.groupBox_CNR->setVisible(m_Controls.NoiseCheckBox->isChecked()); + + this->m_CNR = m_Controls.CNRSpinBox->value(); + + m_Controls.GenerateBtn->setEnabled( CheckModelSettings() ); + + +} + + +void PerfusionDataSimulationView::OnModellSet(int index) +{ + m_selectedModelFactory = NULL; + + if (index > 0) + { + if (static_cast(index) <= m_FactoryStack.size() ) + { + m_selectedModelFactory = m_FactoryStack[index - 1]; + } + else + { + MITK_WARN << "Invalid model index. Index outside of the factory stack. Factory stack size: "<< m_FactoryStack.size() << "; invalid index: "<< index; + } + } + + bool isToftsFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool is2CXMFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL || dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool is2TCMFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool is1TCMFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + + m_Controls.groupBox_TM->setVisible(isToftsFactory); + m_Controls.groupBox_2CXM->setVisible(is2CXMFactory ); + m_Controls.groupBox_2TCM->setVisible(is2TCMFactory ); + m_Controls.groupBox_1TCM->setVisible(is1TCMFactory ); + + + m_Controls.GenerateBtn->setEnabled( CheckModelSettings() ); +// UpdateDataSelection(); + + +} + +bool PerfusionDataSimulationView::CheckModelSettings() +{ + bool ok = true; + if(m_selectedModelFactory.IsNull()) + { + return false; + } + + if(this->m_AterialInputFunction.GetSize() == 0 || this->m_TimeGrid.GetSize() == 0) + { + return false; + + } + + bool isToftsFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool is2CXMFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL || dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool is2TCMFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool is1TCMFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + + + if(isToftsFactory) + { + ok = ok && m_Controls.comboBox_Ktrans->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_vp->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_ve->GetSelectedNode().IsNotNull(); + } + else if(is2CXMFactory) + { + ok = ok && m_Controls.comboBox_F->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_PS->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_fp->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_fi->GetSelectedNode().IsNotNull(); + } + + else if(is2TCMFactory) + { + ok = ok && m_Controls.comboBox_K1->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_K2->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_K3->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_K4->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_VB->GetSelectedNode().IsNotNull(); + } + else if(is1TCMFactory) + { + ok = ok && m_Controls.comboBox_k1->GetSelectedNode().IsNotNull(); + ok = ok && m_Controls.comboBox_k2->GetSelectedNode().IsNotNull(); + } + + else + { + return false; + + } + if(m_Controls.NoiseCheckBox->isChecked()) + { + if(m_CNR !=0 && m_MaxConcentration !=0) + { + this->m_Sigma = m_MaxConcentration/m_CNR; + } + if(m_Sigma==0) + { + return false; + } + } + + + + return ok; + +} + + +void PerfusionDataSimulationView::InitModelComboBox() const +{ + this->m_Controls.ModelSelection->clear(); + this->m_Controls.ModelSelection->addItem(tr("No model selected")); + + for (ModelFactoryStackType::const_iterator pos = m_FactoryStack.begin(); pos != m_FactoryStack.end(); ++pos) + { + this->m_Controls.ModelSelection->addItem(QString::fromStdString((*pos)->GetClassID())); + } + this->m_Controls.ModelSelection->setCurrentIndex(0); +}; + + +void PerfusionDataSimulationView::LoadAIFFile() +{ + QFileDialog dialog; + dialog.setNameFilter(tr("Images (*.csv")); + + QString fileName = dialog.getOpenFileName(); + + m_Controls.AifFilePath->setText( fileName ); + + std::string aifFilePath = fileName.toStdString(); + + //Read Input + typedef boost::tokenizer< boost::escaped_list_separator > Tokenizer; + ///////////////////////////////////////////////////////////////////////////////////////////////// + //AIF Data + + std::vector inputFunction; + std::vector inputGrid; + + std::ifstream in1(aifFilePath.c_str()); + + if(!in1.is_open()) + { + m_Controls.errorMessageLabel->setText("Could not open AIF File!"); + } + + + std::vector< std::string > vec1; + std::string line1; + + while (getline(in1,line1)) + { + Tokenizer tok(line1); + vec1.assign(tok.begin(),tok.end()); + +// if (vec1.size() < 3) continue; + + inputGrid.push_back(convertToDouble(vec1[0])); + inputFunction.push_back(convertToDouble(vec1[1])); + + } + + this->m_MaxConcentration = FindeMaxConcentration(inputFunction); + + itk::Array aif; + itk::Array grid; + + aif.SetSize(inputFunction.size()); + grid.SetSize(inputGrid.size()); + + aif.fill(0.0); + grid.fill(0.0); + + itk::Array::iterator aifPos = aif.begin(); + for(std::vector::const_iterator pos = inputFunction.begin(); pos != inputFunction.end(); ++pos, ++aifPos) + { + *aifPos = *pos; + } + itk::Array::iterator gridPos = grid.begin(); + for(std::vector::const_iterator pos = inputGrid.begin(); pos != inputGrid.end(); ++pos, ++gridPos) + { + *gridPos = *pos; + } + + this->m_AterialInputFunction = aif; + this->m_TimeGrid = grid; + + + m_Controls.GenerateBtn->setEnabled( CheckModelSettings() ); +// UpdateDataSelection(); + + + +} +/** @todo #2 Same function for Numeric and analytic version of FillParameterMap2CXM + */ +void PerfusionDataSimulationView::FillParameterMap2CXM() +{ + ParameterMapType stack; + + mitk::DataNode::Pointer m_selectedNode = m_Controls.comboBox_F->GetSelectedNode(); + mitk::Image::Pointer m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_F,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_PS->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_PS,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_fp->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_vp,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_fi->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_ve,m_selectedImage)); + + this->m_ParameterImageMap = stack; + +} + + +void PerfusionDataSimulationView::FillParameterMapNumeric2CXM() +{ + ParameterMapType stack; + + mitk::DataNode::Pointer m_selectedNode = m_Controls.comboBox_F->GetSelectedNode(); + mitk::Image::Pointer m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_F,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_PS->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_PS,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_fp->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_vp,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_fi->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_ve,m_selectedImage)); + + this->m_ParameterImageMap = stack; + +} + + +void PerfusionDataSimulationView::FillParameterMapETM() +{ + ParameterMapType stack; + + mitk::DataNode::Pointer m_selectedNode = m_Controls.comboBox_Ktrans->GetSelectedNode(); + mitk::Image::Pointer m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::ExtendedToftsModel::NAME_PARAMETER_Ktrans,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_vp->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::ExtendedToftsModel::NAME_PARAMETER_vp,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_ve->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::ExtendedToftsModel::NAME_PARAMETER_ve,m_selectedImage)); + + + this->m_ParameterImageMap = stack; + +} + +void PerfusionDataSimulationView::FillParameterMap2TCM() +{ + ParameterMapType stack; + + mitk::DataNode::Pointer m_selectedNode = m_Controls.comboBox_K1->GetSelectedNode(); + mitk::Image::Pointer m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::TwoTissueCompartmentModel::NAME_PARAMETER_K1,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_K2->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k2,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_K3->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k3,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_K4->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k4,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_VB->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::TwoTissueCompartmentModel::NAME_PARAMETER_VB,m_selectedImage)); + + this->m_ParameterImageMap = stack; + +} + +void PerfusionDataSimulationView::FillParameterMap1TCM() +{ + ParameterMapType stack; + + mitk::DataNode::Pointer m_selectedNode = m_Controls.comboBox_k1->GetSelectedNode(); + mitk::Image::Pointer m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::OneTissueCompartmentModel::NAME_PARAMETER_k1,m_selectedImage)); + + m_selectedNode = m_Controls.comboBox_k2->GetSelectedNode(); + m_selectedImage = dynamic_cast(m_selectedNode->GetData()); + stack.insert(std::make_pair(mitk::OneTissueCompartmentModel::NAME_PARAMETER_k2,m_selectedImage)); + + this->m_ParameterImageMap = stack; + +} + +void PerfusionDataSimulationView::OnGenerateDataButtonClicked() +{ + mitk::Image::Pointer m_DynamicImage = mitk::Image::New(); + + bool isToftsFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool isPhysBrixFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool isNumPhysBrixFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool is2TCMFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + bool is1TCMFactory = dynamic_cast(m_selectedModelFactory.GetPointer()) != NULL; + + + if(isToftsFactory) + { + this->FillParameterMapETM(); + m_DynamicImage = this->GenerateETModelData(); + } + + if (isPhysBrixFactory) + { + this->FillParameterMap2CXM(); + m_DynamicImage = this->Generate2CXModelData(); + } + + if (isNumPhysBrixFactory) + { + this->FillParameterMapNumeric2CXM(); + m_DynamicImage = this->GenerateNumeric2CXModelData(); + } + + if (is2TCMFactory) + { + this->FillParameterMap2TCM(); + m_DynamicImage = this->Generate2TCModelData(); + } + if (is1TCMFactory) + { + this->FillParameterMap1TCM(); + m_DynamicImage = this->Generate1TCModelData(); + } + + + + mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); + std::string nameOfResultImage = "SimulationData_"; + nameOfResultImage.append(m_selectedModelFactory->GetModelDisplayName()); + resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) ); + resultNode->SetData(m_DynamicImage); // set data of new node + this->GetDataStorage()->Add(resultNode); + + +} + +mitk::Image::Pointer PerfusionDataSimulationView::Generate2CXModelData() +{ +mitk::PerfusionDataGenerator::Pointer generator = mitk::PerfusionDataGenerator::New(); +mitk::TwoCompartmentExchangeModelParameterizer::Pointer modelParameterizer = mitk::TwoCompartmentExchangeModelParameterizer::New(); + +/** @todo #2 necessary? Generator need to have a map with Parameters in order of Model in order to pass vector parameters correctly to Model. + * I wanted to make it independend from the order the images are passed on + */ +for(ParameterMapType::const_iterator pos = this->m_ParameterImageMap.begin(); pos != this->m_ParameterImageMap.end(); ++pos) +{ + if(pos->first == mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_F) + { + generator->SetParameterInputImage(mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_F, pos->second); + } + if(pos->first == mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_PS) + { + generator->SetParameterInputImage(mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_PS, pos->second); + } + if(pos->first == mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_ve) + { + generator->SetParameterInputImage(mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_ve, pos->second); + } + if(pos->first == mitk::TwoCompartmentExchangeModel::NAME_PARAMETER_vp) + { + generator->SetParameterInputImage(mitk::TwoCompartmentExchangeModel::POSITION_PARAMETER_vp, pos->second); + } +} + +modelParameterizer->SetAIF(this->m_AterialInputFunction); +modelParameterizer->SetAIFTimeGrid(this->m_TimeGrid); +modelParameterizer->SetDefaultTimeGrid(this->m_TimeGrid); + +mitk::ModelDataGenerationFunctor::Pointer m_ComputationFunctor = mitk::ModelDataGenerationFunctor::New(); + +m_ComputationFunctor->SetModelParameterizer(modelParameterizer); + +generator->SetFunctor(m_ComputationFunctor); + +mitk::Image::Pointer generatedImage = generator->GetGeneratedImage(); + + mitk::Image::Pointer resultImage = mitk::Image::New(); +if(m_Controls.NoiseCheckBox->isChecked()) +{ + typedef itk::Image ImageType; + + mitk::Image::Pointer tempImage = mitk::Image::New(); + tempImage->Initialize(generatedImage); + + mitk::ArbitraryTimeGeometry* timeGeometry = dynamic_cast (generatedImage->GetTimeGeometry()); + + tempImage->SetTimeGeometry(timeGeometry); + + ImageType::Pointer itkImage = ImageType::New(); + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(generatedImage); + + for(unsigned int i = 0; i< generatedImage->GetTimeSteps(); ++i) + { + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer mitkInputImage = imageTimeSelector->GetOutput(); + + mitk::CastToItkImage(mitkInputImage, itkImage ); + + typedef mitk::GaussianNoiseFunctor NoiseFunctorType; + typedef itk::UnaryFunctorImageFilter NoiseFilterType; + NoiseFilterType::Pointer noiseFilter = NoiseFilterType::New(); + NoiseFunctorType noiseFunctor; + noiseFunctor.SetMean(0.0); + noiseFunctor.SetSigma(this->m_Sigma); + noiseFilter->SetFunctor(noiseFunctor); + + noiseFilter->SetInput(itkImage); + + mitk::Image::Pointer outputImage = mitk::ImportItkImage(noiseFilter->GetOutput())->Clone(); + + mitk::ImageReadAccessor accessor(outputImage); + tempImage->SetVolume(accessor.GetData(), i); + } + + resultImage = tempImage->Clone(); +} +else +{ + resultImage = generatedImage; +} +return resultImage; +} + + +/** @todo #2 Synergie? Function implementation for every Model to complicated? + */ +mitk::Image::Pointer PerfusionDataSimulationView::GenerateNumeric2CXModelData() +{ +mitk::PerfusionDataGenerator::Pointer generator = mitk::PerfusionDataGenerator::New(); +mitk::NumericTwoCompartmentExchangeModelParameterizer::Pointer modelParameterizer = mitk::NumericTwoCompartmentExchangeModelParameterizer::New(); + +for(ParameterMapType::const_iterator pos = this->m_ParameterImageMap.begin(); pos != this->m_ParameterImageMap.end(); ++pos) +{ + if(pos->first == mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_F) + { + generator->SetParameterInputImage(mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_F, pos->second); + } + if(pos->first == mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_PS) + { + generator->SetParameterInputImage(mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_PS, pos->second); + } + if(pos->first == mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_ve) + { + generator->SetParameterInputImage(mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_ve, pos->second); + } + if(pos->first == mitk::NumericTwoCompartmentExchangeModel::NAME_PARAMETER_vp) + { + generator->SetParameterInputImage(mitk::NumericTwoCompartmentExchangeModel::POSITION_PARAMETER_vp, pos->second); + } +} + +modelParameterizer->SetAIF(this->m_AterialInputFunction); +modelParameterizer->SetAIFTimeGrid(this->m_TimeGrid); +modelParameterizer->SetDefaultTimeGrid(this->m_TimeGrid); +modelParameterizer->SetODEINTStepSize(0.05); + +mitk::ModelDataGenerationFunctor::Pointer m_ComputationFunctor = mitk::ModelDataGenerationFunctor::New(); + +m_ComputationFunctor->SetModelParameterizer(modelParameterizer); + +generator->SetFunctor(m_ComputationFunctor); + +mitk::Image::Pointer generatedImage = generator->GetGeneratedImage(); + + +mitk::Image::Pointer resultImage = mitk::Image::New(); +if(m_Controls.NoiseCheckBox->isChecked()) +{ + typedef itk::Image ImageType; + + mitk::Image::Pointer tempImage = mitk::Image::New(); + tempImage->Initialize(generatedImage); + + mitk::ArbitraryTimeGeometry* timeGeometry = dynamic_cast (generatedImage->GetTimeGeometry()); + + tempImage->SetTimeGeometry(timeGeometry); + + ImageType::Pointer itkImage = ImageType::New(); + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(generatedImage); + + for(unsigned int i = 0; i< generatedImage->GetTimeSteps(); ++i) + { + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer mitkInputImage = imageTimeSelector->GetOutput(); + + mitk::CastToItkImage(mitkInputImage, itkImage ); + + typedef mitk::GaussianNoiseFunctor NoiseFunctorType; + typedef itk::UnaryFunctorImageFilter NoiseFilterType; + NoiseFilterType::Pointer noiseFilter = NoiseFilterType::New(); + NoiseFunctorType noiseFunctor; + noiseFunctor.SetMean(0.0); + noiseFunctor.SetSigma(this->m_Sigma); + noiseFilter->SetFunctor(noiseFunctor); + + noiseFilter->SetInput(itkImage); + + mitk::Image::Pointer outputImage = mitk::ImportItkImage(noiseFilter->GetOutput())->Clone(); + + mitk::ImageReadAccessor accessor(outputImage); + tempImage->SetVolume(accessor.GetData(), i); + } + + resultImage = tempImage->Clone(); +} +else +{ + resultImage = generatedImage; +} +return resultImage; +} + +mitk::Image::Pointer PerfusionDataSimulationView::GenerateETModelData() +{ +mitk::PerfusionDataGenerator::Pointer generator = mitk::PerfusionDataGenerator::New(); +mitk::ExtendedToftsModelParameterizer::Pointer modelParameterizer = mitk::ExtendedToftsModelParameterizer::New(); + +for(ParameterMapType::const_iterator pos = this->m_ParameterImageMap.begin(); pos != this->m_ParameterImageMap.end(); ++pos) +{ + if(pos->first == mitk::ExtendedToftsModel::NAME_PARAMETER_Ktrans) + { + generator->SetParameterInputImage(mitk::ExtendedToftsModel::POSITION_PARAMETER_Ktrans, pos->second); + } + if(pos->first == mitk::ExtendedToftsModel::NAME_PARAMETER_vp) + { + generator->SetParameterInputImage(mitk::ExtendedToftsModel::POSITION_PARAMETER_vp, pos->second); + } + if(pos->first == mitk::ExtendedToftsModel::NAME_PARAMETER_ve) + { + generator->SetParameterInputImage(mitk::ExtendedToftsModel::POSITION_PARAMETER_ve, pos->second); + } + +} + +modelParameterizer->SetAIF(this->m_AterialInputFunction); +modelParameterizer->SetAIFTimeGrid(this->m_TimeGrid); +modelParameterizer->SetDefaultTimeGrid(this->m_TimeGrid); + +mitk::ModelDataGenerationFunctor::Pointer m_ComputationFunctor = mitk::ModelDataGenerationFunctor::New(); + +m_ComputationFunctor->SetModelParameterizer(modelParameterizer); + +generator->SetFunctor(m_ComputationFunctor); + +mitk::Image::Pointer generatedImage = generator->GetGeneratedImage(); + + +mitk::Image::Pointer resultImage = mitk::Image::New(); +if(m_Controls.NoiseCheckBox->isChecked()) +{ + typedef itk::Image ImageType; + + mitk::Image::Pointer tempImage = mitk::Image::New(); + tempImage->Initialize(generatedImage); + + mitk::ArbitraryTimeGeometry* timeGeometry = dynamic_cast (generatedImage->GetTimeGeometry()); + + tempImage->SetTimeGeometry(timeGeometry); + + ImageType::Pointer itkImage = ImageType::New(); + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(generatedImage); + + for(unsigned int i = 0; i< generatedImage->GetTimeSteps(); ++i) + { + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer mitkInputImage = imageTimeSelector->GetOutput(); + + mitk::CastToItkImage(mitkInputImage, itkImage ); + + typedef mitk::GaussianNoiseFunctor NoiseFunctorType; + typedef itk::UnaryFunctorImageFilter NoiseFilterType; + NoiseFilterType::Pointer noiseFilter = NoiseFilterType::New(); + NoiseFunctorType noiseFunctor; + noiseFunctor.SetMean(0.0); + noiseFunctor.SetSigma(this->m_Sigma); + noiseFilter->SetFunctor(noiseFunctor); + + noiseFilter->SetInput(itkImage); + + mitk::Image::Pointer outputImage = mitk::ImportItkImage(noiseFilter->GetOutput())->Clone(); + + mitk::ImageReadAccessor accessor(outputImage); + tempImage->SetVolume(accessor.GetData(), i); + } + + resultImage = tempImage->Clone(); +} +else +{ + resultImage = generatedImage; +} +return resultImage; +} + + +mitk::Image::Pointer PerfusionDataSimulationView::Generate2TCModelData() +{ +mitk::PerfusionDataGenerator::Pointer generator = mitk::PerfusionDataGenerator::New(); +mitk::TwoTissueCompartmentModelParameterizer::Pointer modelParameterizer = mitk::TwoTissueCompartmentModelParameterizer::New(); + + +for(ParameterMapType::const_iterator pos = this->m_ParameterImageMap.begin(); pos != this->m_ParameterImageMap.end(); ++pos) +{ + if(pos->first == mitk::TwoTissueCompartmentModel::NAME_PARAMETER_K1) + { + generator->SetParameterInputImage(mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_K1, pos->second); + } + if(pos->first == mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k2) + { + generator->SetParameterInputImage(mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k2, pos->second); + } + if(pos->first == mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k3) + { + generator->SetParameterInputImage(mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k3, pos->second); + } + if(pos->first == mitk::TwoTissueCompartmentModel::NAME_PARAMETER_k4) + { + generator->SetParameterInputImage(mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_k4, pos->second); + } + if(pos->first == mitk::TwoTissueCompartmentModel::NAME_PARAMETER_VB) + { + generator->SetParameterInputImage(mitk::TwoTissueCompartmentModel::POSITION_PARAMETER_VB, pos->second); + } + +} + +modelParameterizer->SetAIF(this->m_AterialInputFunction); +modelParameterizer->SetAIFTimeGrid(this->m_TimeGrid); +modelParameterizer->SetDefaultTimeGrid(this->m_TimeGrid); + +mitk::ModelDataGenerationFunctor::Pointer m_ComputationFunctor = mitk::ModelDataGenerationFunctor::New(); + +m_ComputationFunctor->SetModelParameterizer(modelParameterizer); + +generator->SetFunctor(m_ComputationFunctor); + +mitk::Image::Pointer generatedImage = generator->GetGeneratedImage(); + + mitk::Image::Pointer resultImage = mitk::Image::New(); +if(m_Controls.NoiseCheckBox->isChecked()) +{ + typedef itk::Image ImageType; + + mitk::Image::Pointer tempImage = mitk::Image::New(); + tempImage->Initialize(generatedImage); + + mitk::ArbitraryTimeGeometry* timeGeometry = dynamic_cast (generatedImage->GetTimeGeometry()); + + tempImage->SetTimeGeometry(timeGeometry); + + ImageType::Pointer itkImage = ImageType::New(); + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(generatedImage); + + for(unsigned int i = 0; i< generatedImage->GetTimeSteps(); ++i) + { + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer mitkInputImage = imageTimeSelector->GetOutput(); + + mitk::CastToItkImage(mitkInputImage, itkImage ); + + typedef mitk::GaussianNoiseFunctor NoiseFunctorType; + typedef itk::UnaryFunctorImageFilter NoiseFilterType; + NoiseFilterType::Pointer noiseFilter = NoiseFilterType::New(); + NoiseFunctorType noiseFunctor; + noiseFunctor.SetMean(0.0); + noiseFunctor.SetSigma(this->m_Sigma); + noiseFilter->SetFunctor(noiseFunctor); + + noiseFilter->SetInput(itkImage); + + mitk::Image::Pointer outputImage = mitk::ImportItkImage(noiseFilter->GetOutput())->Clone(); + + mitk::ImageReadAccessor accessor(outputImage); + tempImage->SetVolume(accessor.GetData(), i); + } + + resultImage = tempImage->Clone(); +} +else +{ + resultImage = generatedImage; +} +return resultImage; +} + + +mitk::Image::Pointer PerfusionDataSimulationView::Generate1TCModelData() +{ +mitk::PerfusionDataGenerator::Pointer generator = mitk::PerfusionDataGenerator::New(); +mitk::OneTissueCompartmentModelParameterizer::Pointer modelParameterizer = mitk::OneTissueCompartmentModelParameterizer::New(); + + +for(ParameterMapType::const_iterator pos = this->m_ParameterImageMap.begin(); pos != this->m_ParameterImageMap.end(); ++pos) +{ + if(pos->first == mitk::OneTissueCompartmentModel::NAME_PARAMETER_k1) + { + generator->SetParameterInputImage(mitk::OneTissueCompartmentModel::POSITION_PARAMETER_k1, pos->second); + } + if(pos->first == mitk::OneTissueCompartmentModel::NAME_PARAMETER_k2) + { + generator->SetParameterInputImage(mitk::OneTissueCompartmentModel::POSITION_PARAMETER_k2, pos->second); + } + +} + +modelParameterizer->SetAIF(this->m_AterialInputFunction); +modelParameterizer->SetAIFTimeGrid(this->m_TimeGrid); +modelParameterizer->SetDefaultTimeGrid(this->m_TimeGrid); + +mitk::ModelDataGenerationFunctor::Pointer m_ComputationFunctor = mitk::ModelDataGenerationFunctor::New(); + +m_ComputationFunctor->SetModelParameterizer(modelParameterizer); + +generator->SetFunctor(m_ComputationFunctor); + +mitk::Image::Pointer generatedImage = generator->GetGeneratedImage(); + + mitk::Image::Pointer resultImage = mitk::Image::New(); +if(m_Controls.NoiseCheckBox->isChecked()) +{ + typedef itk::Image ImageType; + + mitk::Image::Pointer tempImage = mitk::Image::New(); + tempImage->Initialize(generatedImage); + + mitk::ArbitraryTimeGeometry* timeGeometry = dynamic_cast (generatedImage->GetTimeGeometry()); + + tempImage->SetTimeGeometry(timeGeometry); + + ImageType::Pointer itkImage = ImageType::New(); + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(generatedImage); + + for(unsigned int i = 0; i< generatedImage->GetTimeSteps(); ++i) + { + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + + mitk::Image::Pointer mitkInputImage = imageTimeSelector->GetOutput(); + + mitk::CastToItkImage(mitkInputImage, itkImage ); + + typedef mitk::GaussianNoiseFunctor NoiseFunctorType; + typedef itk::UnaryFunctorImageFilter NoiseFilterType; + NoiseFilterType::Pointer noiseFilter = NoiseFilterType::New(); + NoiseFunctorType noiseFunctor; + noiseFunctor.SetMean(0.0); + noiseFunctor.SetSigma(this->m_Sigma); + noiseFilter->SetFunctor(noiseFunctor); + + noiseFilter->SetInput(itkImage); + + mitk::Image::Pointer outputImage = mitk::ImportItkImage(noiseFilter->GetOutput())->Clone(); + + mitk::ImageReadAccessor accessor(outputImage); + tempImage->SetVolume(accessor.GetData(), i); + } + + resultImage = tempImage->Clone(); +} +else +{ + resultImage = generatedImage; +} +return resultImage; +} + + +PerfusionDataSimulationView::PerfusionDataSimulationView() +{ + m_Sigma = 0; + m_CNR=0; + m_MaxConcentration=0; + m_selectedModelFactory = NULL; + + + mitk::ModelFactoryBase::Pointer factory = mitk::ExtendedToftsModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::TwoCompartmentExchangeModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::NumericTwoCompartmentExchangeModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::TwoTissueCompartmentModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + factory = mitk::OneTissueCompartmentModelFactory::New().GetPointer(); + m_FactoryStack.push_back(factory); + + + + m_IsNotABinaryImagePredicate = mitk::NodePredicateAnd::New( + mitk::TNodePredicateDataType::New(), + mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true))), + mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))).GetPointer(); + +} diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/PerfusionDataSimulationView.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/PerfusionDataSimulationView.h new file mode 100644 index 0000000000..3c90e4fd22 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/PerfusionDataSimulationView.h @@ -0,0 +1,133 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef PerfusionDataSimulationView_h +#define PerfusionDataSimulationView_h + +#include + +#include +#include "ui_PerfusionDataSimulationViewControls.h" +#include "mitkModelBase.h" +#include + +#include "itkArray.h" +#include "mitkImage.h" + + +#include + + +/*! + * @brief Test Plugin for SUV calculations of PET images + */ +class PerfusionDataSimulationView : public QmitkAbstractView +{ + Q_OBJECT + +public: + + /*! @brief The view's unique ID - required by MITK */ + static const std::string VIEW_ID; + + PerfusionDataSimulationView(); + +protected slots: + + /*! + * @brief Is triggered of the update button is clicked and the selected node should get the (new) iso level set. + */ + void OnGenerateDataButtonClicked(); + void LoadAIFFile(); + void OnModellSet(int); + + void OnSimulationConfigurationChanged(); + + void UpdateDataSelection(); + + +protected: + typedef std::map ParameterMapType; + + // Overridden base class functions + + /*! + * @brief Sets up the UI controls and connects the slots and signals. Gets + * called by the framework to create the GUI at the right time. + * @param[in,out] parent The parent QWidget, as this class itself is not a QWidget + * subclass. + */ + void CreateQtPartControl(QWidget* parent); + + /*! + * @brief Sets the focus to the plot curve button. Gets called by the framework to set the + * focus on the right widget. + */ + void SetFocus(); + + + void InitModelComboBox() const; + + + mitk::Image::Pointer Generate2CXModelData(); + mitk::Image::Pointer GenerateNumeric2CXModelData(); + mitk::Image::Pointer GenerateETModelData(); + void FillParameterMap2CXM(); + void FillParameterMapNumeric2CXM(); + void FillParameterMapETM(); + + + + ///////////////////// dynamic PET Models/////////////// + mitk::Image::Pointer Generate2TCModelData(); + mitk::Image::Pointer Generate1TCModelData(); + void FillParameterMap2TCM(); + void FillParameterMap1TCM(); + + + bool CheckModelSettings(); + + + /*! \brief called by QmitkFunctionality when DataManager's selection has changed + */ +// virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, +// const QList& selectedNodes); + + + // Variables + + /*! @brief The view's UI controls */ + Ui::PerfusionDataSimulationViewControls m_Controls; + mitk::DataNode::Pointer m_selectedNode; + + ParameterMapType m_ParameterImageMap; + itk::Array m_AterialInputFunction; + itk::Array m_TimeGrid; + + mitk::ModelFactoryBase::Pointer m_selectedModelFactory; + + +private: + + typedef std::vector ModelFactoryStackType; + ModelFactoryStackType m_FactoryStack; + mitk::NodePredicateBase::Pointer m_IsNotABinaryImagePredicate; + + double m_CNR, m_MaxConcentration, m_Sigma; + +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/PerfusionDataSimulationViewControls.ui b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/PerfusionDataSimulationViewControls.ui new file mode 100644 index 0000000000..7936e1fdf5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/PerfusionDataSimulationViewControls.ui @@ -0,0 +1,346 @@ + + + PerfusionDataSimulationViewControls + + + + 0 + 0 + 555 + 1037 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + + + + Message: + + + + + + + TextLabel + + + + + + + + + Model + + + + + + Select a Model for Data Generation: + + + + + + + + + + + + + Aterial Input Function + + + + + + + + + Browse + + + + + + + Select AIF & Time Grid File + + + + + + + + + + Parameter Images + + + + + + 2 Compartment Exchange Model: + + + + + + vi + + + + + + + vp + + + + + + + F + + + + + + + PS + + + + + + + + + + + + + + + + + + + + + + Extended Tofts Model: + + + + + + ve + + + + + + + vp + + + + + + + KTrans + + + + + + + + + + + + + + + + + + + 2 Tissue Compartment Model + + + + + + K1 + + + + + + + + + + k2 + + + + + + + k4 + + + + + + + k3 + + + + + + + VB + + + + + + + + + + + + + + + + + + + + + + 1 Tissue Compartment Model + + + + + + k1 + + + + + + + + + + k2 + + + + + + + + + + + + + + + + Noise Settings + + + + + + Use Noise? + + + + + + + + + + + + + Contrast-To-Noise Ratio + + + + + + + 1000.000000000000000 + + + + + + + + + + + + + Generate Data + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + QmitkDataStorageComboBox + QComboBox +
    QmitkDataStorageComboBox.h
    +
    +
    + + +
    diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/org_mitk_PerfusionDataSimulationView_Activator.cpp b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/org_mitk_PerfusionDataSimulationView_Activator.cpp new file mode 100644 index 0000000000..2fa919c8ee --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/org_mitk_PerfusionDataSimulationView_Activator.cpp @@ -0,0 +1,31 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "org_mitk_PerfusionDataSimulationView_Activator.h" + +#include + +#include "PerfusionDataSimulationView.h" + + void org_mitk_PerfusionDataSimulationView_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(PerfusionDataSimulationView, context); + } + + void org_mitk_PerfusionDataSimulationView_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context); + } diff --git a/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/org_mitk_PerfusionDataSimulationView_Activator.h b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/org_mitk_PerfusionDataSimulationView_Activator.h new file mode 100644 index 0000000000..faa534d6db --- /dev/null +++ b/Plugins/org.mitk.gui.qt.pharmacokinetics.simulation/src/internal/org_mitk_PerfusionDataSimulationView_Activator.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef org_mitk_PerfusionDataSimulationView_Activator_h +#define org_mitk_PerfusionDataSimulationView_Activator_h + +#include + + class org_mitk_PerfusionDataSimulationView_Activator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_pharmacokinetics_simulation") + Q_INTERFACES(ctkPluginActivator) + + public: + + /*! + * @brief Registers the plug-in. Gets called by the framework when the plug-in is + * first loaded. + * @param context The corresponding CTK plug-in context in which the plug-in is loaded. + */ + void start(ctkPluginContext* context); + + /*! + * @brief Deregisters the plug-in. Gets called by the framework when the plug-in + * is unloaded. + * @param context The corresponding CTK plug-in context in which the plug-in was loaded. + */ + void stop(ctkPluginContext* context); + }; + +#endif