diff --git a/Modules/Pharmacokinetics/include/mitkConcentrationCurveGenerator.h b/Modules/Pharmacokinetics/include/mitkConcentrationCurveGenerator.h index f387543b4b..3b933970e7 100644 --- a/Modules/Pharmacokinetics/include/mitkConcentrationCurveGenerator.h +++ b/Modules/Pharmacokinetics/include/mitkConcentrationCurveGenerator.h @@ -1,146 +1,164 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY 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*/ itkSetConstObjectMacro(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*/ itkSetConstObjectMacro(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(BaselineStartTimePoint, int); + itkGetConstReferenceMacro(BaselineStartTimePoint, int); + + itkSetMacro(BaselineEndTimePoint, int); + itkGetConstReferenceMacro(BaselineEndTimePoint, int); + 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() override; template mitk::Image::Pointer convertToConcentration(const mitk::Image* inputImage, const mitk::Image* baselineImage); /** Calls ConvertToconcentrationFunctor for passed 3D itk::image*/ mitk::Image::Pointer ConvertSignalToConcentrationCurve(const mitk::Image* inputImage, const mitk::Image* 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(); + //template + //void mitk::(itk::Image* imageA, itk::Image* imageB) + //{ + //} + + private: Image::ConstPointer m_DynamicImage; Image::ConstPointer m_BaselineImage; Image::ConstPointer 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; + + int m_BaselineStartTimePoint; + int m_BaselineEndTimePoint; }; } #endif // CONCENTRATIONCURVEGENERATOR_H diff --git a/Modules/Pharmacokinetics/src/Common/mitkConcentrationCurveGenerator.cpp b/Modules/Pharmacokinetics/src/Common/mitkConcentrationCurveGenerator.cpp index 8ded94876d..386476e3b7 100644 --- a/Modules/Pharmacokinetics/src/Common/mitkConcentrationCurveGenerator.cpp +++ b/Modules/Pharmacokinetics/src/Common/mitkConcentrationCurveGenerator.cpp @@ -1,252 +1,291 @@ #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 "mitkArithmeticOperation.h" +#include "itkNaryAddImageFilter.h" +#include "mitkImageAccessByItk.h" +#include "itkImageIOBase.h" #include "itkBinaryFunctorImageFilter.h" #include "itkTernaryFunctorImageFilter.h" mitk::ConcentrationCurveGenerator::ConcentrationCurveGenerator() : m_isT2weightedImage(false), m_isTurboFlashSequence(false), m_AbsoluteSignalEnhancement(false), m_RelativeSignalEnhancement(0.0), m_UsingT1Map(false), m_Factor(0.0), m_RecoveryTime(0.0), m_RelaxationTime(0.0), m_Relaxivity(0.0), m_FlipAngle(0.0), m_T2Factor(0.0), m_T2EchoTime(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(); + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(this->m_DynamicImage); + imageTimeSelector->SetTimeNr(0); + imageTimeSelector->UpdateLargestPossibleRegion(); + mitk::Image::Pointer baselineImage0; + baselineImage0 = imageTimeSelector->GetOutput(); + this->m_BaselineImage = imageTimeSelector->GetOutput(); + + + + /* + typedef itk::NaryAddImageFilter itkAddBaselineImagesFilterType; + + typename itkAddBaselineImagesFilterType::Pointer itkNaryAddImageFilter = itkAddBaselineImagesFilterType::New(); + + mitk::ImageTimeSelector::Pointer imageTimeSelector1 = mitk::ImageTimeSelector::New(); + imageTimeSelector1->SetInput(this->m_DynamicImage); + imageTimeSelector1->SetTimeNr(1); + imageTimeSelector1->UpdateLargestPossibleRegion(); + mitk::Image::Pointer baselineImage1; + baselineImage1 = imageTimeSelector1->GetOutput(); + + + //add the time frames to the descriptor filter + std::vector baselineCache; + for (unsigned int i = 0; i < this->m_DynamicImage->GetTimeSteps(); ++i) + { + mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + imageTimeSelector->SetInput(this->m_DynamicImage); + imageTimeSelector->SetTimeNr(i); + imageTimeSelector->UpdateLargestPossibleRegion(); + Image::Pointer baselineImage = imageTimeSelector->GetOutput(); + baselineCache.push_back(baselineImage); + mitk::CastToItkImage(baselineImage, frameImage); + itkAddNaryImageFilter->SetInput(i, frameImage); + } + itkAddNaryImageFilter->GetOutput(); + + + //AccessFixedDimensionByItk_n(m_magnFIDImage.GetPointer(), mitkItkConversionHelper::CastMitkImageToDoubleItkImage, 4, (itkMagnFIDImage)); + //AccessTwoImagesFixedDimensionByItk(baselineImage0, baselineImage1, CalculateAverageImage); + */ +} - this->m_BaselineImage = imageTimeSelector->GetOutput(); -} mitk::Image::Pointer mitk::ConcentrationCurveGenerator::ConvertSignalToConcentrationCurve(const mitk::Image* inputImage, const mitk::Image* 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::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(const mitk::Image* inputImage, const mitk::Image* 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; }