diff --git a/Modules/DiffusionImaging/MiniApps/ExtractImageStatistics.cpp b/Modules/DiffusionImaging/MiniApps/ExtractImageStatistics.cpp new file mode 100644 index 0000000000..1f47a6b043 --- /dev/null +++ b/Modules/DiffusionImaging/MiniApps/ExtractImageStatistics.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 "MiniAppManager.h" + +#include "ctkCommandLineParser.h" +#include "mitkImage.h" +#include "mitkImageStatisticsCalculator.h" +#include "mitkIOUtil.h" +#include +#include +#include + +int ExtractImageStatistics(int argc, char* argv[]) +{ + ctkCommandLineParser parser; + parser.setArgumentPrefix("--", "-"); + parser.addArgument("help", "h", ctkCommandLineParser::String, "Show this help text"); + parser.addArgument("input", "i", ctkCommandLineParser::String, "input image", us::Any(),false); + parser.addArgument("mask", "m", ctkCommandLineParser::String, "mask image / roi image denotin area on which statistics are calculated", us::Any(),false); + parser.addArgument("out", "o", ctkCommandLineParser::String, "output file (default: filenameOfRoi.nrrd_statistics.txt)", us::Any()); + + map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0 || parsedArgs.count("help") || parsedArgs.count("h")) + { + std::cout << "\n\n MiniApp Description: \nCalculates statistics on the supplied image using given mask." << endl; + std::cout << "Output is written to the designated output file in this order:" << endl; + std::cout << "Mean, Standard Deviation, RMS, Max, Min, Number of Voxels, Volume [mm3]" << endl; + std::cout << "\n\n Parameters:"<< endl; + std::cout << parser.helpText(); + return EXIT_SUCCESS; + } + + // Parameters: + bool ignoreZeroValues = false; + unsigned int timeStep = 0; + + std::string inputImageFile = us::any_cast(parsedArgs["input"]); + std::string maskImageFile = us::any_cast(parsedArgs["mask"]); + + std::string outFile; + if (parsedArgs.count("out") || parsedArgs.count("o") ) + outFile = us::any_cast(parsedArgs["out"]); + else + outFile = inputImageFile + "_statistics.txt"; + + // Load image and mask + mitk::Image::Pointer maskImage = mitk::IOUtil::LoadImage(maskImageFile); + mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(inputImageFile); + + // Calculate statistics + mitk::ImageStatisticsCalculator::Statistics statisticsStruct; + mitk::ImageStatisticsCalculator::Pointer calculator = mitk::ImageStatisticsCalculator::New(); + try + { + calculator->SetImage(inputImage); + calculator->SetImageMask(maskImage); + calculator->SetMaskingModeToImage(); + } + catch( const itk::ExceptionObject& e) + { + MITK_ERROR << "Statistic Calculation Failed - ITK Exception:" << e.what(); + return -1; + } + + + calculator->SetDoIgnorePixelValue(ignoreZeroValues); + calculator->SetIgnorePixelValue(0); + try + { + calculator->ComputeStatistics(timeStep); + } + catch ( mitk::Exception& e) + { + MITK_ERROR<< "MITK Exception: " << e.what(); + return -1; + } + + + statisticsStruct = calculator->GetStatistics(timeStep); + + + // Calculate Volume + double volume = 0; + const mitk::Geometry3D *geometry = inputImage->GetGeometry(); + if ( geometry != NULL ) + { + const mitk::Vector3D &spacing = inputImage->GetGeometry()->GetSpacing(); + volume = spacing[0] * spacing[1] * spacing[2] * (double) statisticsStruct.N; + } + + // Write Results to file + std::ofstream output; + output.open(outFile.c_str()); + output << statisticsStruct.Mean << " , "; + output << statisticsStruct.Sigma << " , "; + output << statisticsStruct.RMS << " , "; + output << statisticsStruct.Max << " , "; + output << statisticsStruct.Min << " , "; + output << statisticsStruct.N << " , "; + output << volume << "\n"; + + output.flush(); + output.close(); + return 0; +} + +RegisterDiffusionMiniApp(ExtractImageStatistics); diff --git a/Modules/DiffusionImaging/MiniApps/TensorDerivedMapsExtraction.cpp b/Modules/DiffusionImaging/MiniApps/TensorDerivedMapsExtraction.cpp new file mode 100644 index 0000000000..debbad083a --- /dev/null +++ b/Modules/DiffusionImaging/MiniApps/TensorDerivedMapsExtraction.cpp @@ -0,0 +1,190 @@ +/*=================================================================== + + The Medical Imaging Interaction Toolkit (MITK) + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. + + This software is distributed WITHOUT ANY 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 "MiniAppManager.h" + +#include + +#include "mitkImage.h" +#include +#include "mitkITKImageImport.h" +#include +#include +#include +#include + +#include "itkTensorDerivedMeasurementsFilter.h" +#include "itkDiffusionTensor3DReconstructionImageFilter.h" +#include "ctkCommandLineParser.h" + +#include +#include +#include + +typedef short DiffusionPixelType; +typedef double TTensorPixelType; + +static void ExtractMapsAndSave(mitk::TensorImage::Pointer tensorImage, std::string filename, std::string postfix = "") +{ + + mitk::Image* image = dynamic_cast (tensorImage.GetPointer()); + + typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType; + typedef itk::Image< TensorPixelType, 3 > TensorImageType; + + TensorImageType::Pointer itkvol = TensorImageType::New(); + mitk::CastToItkImage(image, itkvol); + + typedef itk::TensorDerivedMeasurementsFilter MeasurementsType; + + MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New(); + measurementsCalculator->SetInput(itkvol.GetPointer() ); + + mitk::Image::Pointer map = mitk::Image::New(); + // FA + measurementsCalculator->SetMeasure(MeasurementsType::FA); + measurementsCalculator->Update(); + map->InitializeByItk( measurementsCalculator->GetOutput() ); + map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); + mitk::IOUtil::SaveImage(map, filename + "_dti_FA" + postfix + ".nrrd"); + + // MD + measurementsCalculator->SetMeasure(MeasurementsType::MD); + measurementsCalculator->Update(); + map->InitializeByItk( measurementsCalculator->GetOutput() ); + map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); + mitk::IOUtil::SaveImage(map, filename + "_dti_MD" + postfix + ".nrrd"); + + // AD + measurementsCalculator->SetMeasure(MeasurementsType::AD); + measurementsCalculator->Update(); + map->InitializeByItk( measurementsCalculator->GetOutput() ); + map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); + mitk::IOUtil::SaveImage(map, filename + "_dti_AD" + postfix + ".nrrd"); + + + // CA + measurementsCalculator->SetMeasure(MeasurementsType::CA); + measurementsCalculator->Update(); + map->InitializeByItk( measurementsCalculator->GetOutput() ); + map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); + mitk::IOUtil::SaveImage(map, filename + "_dti_CA" + postfix + ".nrrd"); + + // RA + measurementsCalculator->SetMeasure(MeasurementsType::RA); + measurementsCalculator->Update(); + map->InitializeByItk( measurementsCalculator->GetOutput() ); + map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); + mitk::IOUtil::SaveImage(map, filename + "_dti_RA" + postfix + ".nrrd"); + + // RD + measurementsCalculator->SetMeasure(MeasurementsType::RD); + measurementsCalculator->Update(); + map->InitializeByItk( measurementsCalculator->GetOutput() ); + map->SetVolume( measurementsCalculator->GetOutput()->GetBufferPointer() ); + mitk::IOUtil::SaveImage(map, filename + "_dti_RD" + postfix + ".nrrd"); + +} + + +int TensorDerivedMapsExtraction(int argc, char* argv[]) +{ + + ctkCommandLineParser parser; + parser.setArgumentPrefix("--", "-"); + parser.addArgument("help", "h", ctkCommandLineParser::String, "Show this help text"); + parser.addArgument("input", "i", ctkCommandLineParser::String, "input dwi file", us::Any(),false); + parser.addArgument("out", "o", ctkCommandLineParser::String, "output folder and base name, e.g. /tmp/outPatient1 ", us::Any(),false); + + map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0 || parsedArgs.count("help") || parsedArgs.count("h")) + { + std::cout << "\n\nMiniApp Description: \nPerforms tensor reconstruction on DWI file," << endl; + std::cout << "and computes tensor derived measures." << endl; + std::cout << "\n\n For out parameter /tmp/outPatient1 it will produce :"<< endl; + std::cout << " /tmp/outPatient1_dti.dti , /tmp/outPatient1_dti_FA.nrrd, ..."<< endl; + std::cout << "\n\n Parameters:"<< endl; + std::cout << parser.helpText(); + return EXIT_SUCCESS; + } + + + + std::string inputFile = us::any_cast(parsedArgs["input"]); + std::string baseFileName = us::any_cast(parsedArgs["out"]); + + std::string dtiFileName = "_dti.dti"; + + MITK_INFO << "BaseFileName: " << baseFileName; + + + mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(inputFile); + mitk::DiffusionImage* diffusionImage = static_cast*>(inputImage.GetPointer()); + if (diffusionImage == NULL) // does NULL pointer check make sense after static cast ? + { + MITK_ERROR << "Invalid Input Image. Must be DWI. Aborting."; + return -1; + } + + mitk::DiffusionImage* vols = dynamic_cast *> (inputImage.GetPointer()); + + typedef itk::DiffusionTensor3DReconstructionImageFilter< DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType; + TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter = TensorReconstructionImageFilterType::New(); + + typedef mitk::DiffusionImage DiffusionImageType; + typedef DiffusionImageType::GradientDirectionContainerType GradientDirectionContainerType; + + GradientDirectionContainerType::Pointer gradientContainerCopy = GradientDirectionContainerType::New(); + for(GradientDirectionContainerType::ConstIterator it = vols->GetDirections()->Begin(); it != vols->GetDirections()->End(); it++) + { + gradientContainerCopy->push_back(it.Value()); + } + + tensorReconstructionFilter->SetGradientImage( gradientContainerCopy, vols->GetVectorImage() ); + tensorReconstructionFilter->SetBValue(vols->GetReferenceBValue()); + tensorReconstructionFilter->SetThreshold(50); + tensorReconstructionFilter->Update(); + + typedef itk::Image, 3> TensorImageType; + TensorImageType::Pointer tensorImage = tensorReconstructionFilter->GetOutput(); + tensorImage->SetDirection( vols->GetVectorImage()->GetDirection() ); + + mitk::TensorImage::Pointer tensorImageMitk = mitk::TensorImage::New(); + tensorImageMitk->InitializeByItk(tensorImage.GetPointer()); + tensorImageMitk->SetVolume( tensorImage->GetBufferPointer() ); + + + + itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); + io->SetFileType( itk::ImageIOBase::Binary ); + io->UseCompressionOn(); + + itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< double >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< double >, 3 > >::New(); + writer->SetInput(tensorReconstructionFilter->GetOutput()); + writer->SetFileName(baseFileName + dtiFileName); + writer->SetImageIO(io); + writer->UseCompressionOn(); + writer->Update(); + + ExtractMapsAndSave(tensorImageMitk,baseFileName); + + return EXIT_SUCCESS; + +} + + + +RegisterDiffusionMiniApp(TensorDerivedMapsExtraction); diff --git a/Modules/DiffusionImaging/MiniApps/files.cmake b/Modules/DiffusionImaging/MiniApps/files.cmake index bcd58b0f7e..16faf6666d 100644 --- a/Modules/DiffusionImaging/MiniApps/files.cmake +++ b/Modules/DiffusionImaging/MiniApps/files.cmake @@ -1,23 +1,25 @@ set(CPP_FILES mitkDiffusionMiniApps.cpp MiniAppManager.cpp FileFormatConverter.cpp TensorReconstruction.cpp + TensorDerivedMapsExtraction.cpp QballReconstruction.cpp DiffusionIndices.cpp + ExtractImageStatistics.cpp CopyGeometry.cpp GibbsTracking.cpp StreamlineTracking.cpp FiberProcessing.cpp LocalDirectionalFiberPlausibility.cpp #TractogramAngularError.cpp FiberDirectionExtraction.cpp PeakExtraction.cpp PeaksAngularError.cpp MultishellMethods.cpp #FiberFoxProcessing.cpp ExportShImage.cpp NetworkCreation.cpp NetworkStatistics.cpp DwiDenoising.cpp )