diff --git a/Modules/DiffusionImaging/DiffusionCore/MiniApps/QballReconstruction.cpp b/Modules/DiffusionImaging/DiffusionCore/MiniApps/QballReconstruction.cpp index f011965583..7a5df1b518 100644 --- a/Modules/DiffusionImaging/DiffusionCore/MiniApps/QballReconstruction.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/MiniApps/QballReconstruction.cpp @@ -1,176 +1,215 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY 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 -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include "itkVectorContainer.h" -#include "vnl/vnl_vector_fixed.h" -#include "itkVectorImage.h" #include "mitkBaseDataIOFactory.h" #include "mitkDiffusionImage.h" -#include "mitkBaseData.h" #include "mitkDiffusionCoreObjectFactory.h" -#include "mitkCoreObjectFactory.h" -#include "mitkCoreExtObjectFactory.h" -#include "mitkImageWriter.h" #include "itkAnalyticalDiffusionQballReconstructionImageFilter.h" #include #include +#include "ctkCommandLineParser.h" +#include +#include using namespace mitk; /** - * Convert files from one ending to the other + * Perform Q-ball reconstruction using a spherical harmonics basis */ int QballReconstruction(int argc, char* argv[]) { - - if ( argc<6 ) - { - std::cout << std::endl; - std::cout << "Perform QBall reconstruction on an dwi file" << std::endl; - std::cout << std::endl; - std::cout << "usage: " << argv[0] << " " << argv[1] << " " << std::endl; - std::cout << std::endl; + ctkCommandLineParser parser; + parser.setArgumentPrefix("--", "-"); + parser.addArgument("input", "i", ctkCommandLineParser::String, "input raw dwi (.dwi or .fsl/.fslgz)", us::Any(), false); + parser.addArgument("outFile", "o", ctkCommandLineParser::String, "output file", us::Any(), false); + parser.addArgument("shOrder", "sh", ctkCommandLineParser::Int, "spherical harmonics order", 4, true); + parser.addArgument("b0Threshold", "t", ctkCommandLineParser::Int, "baseline image intensity threshold", 0, true); + parser.addArgument("lambda", "r", ctkCommandLineParser::Float, "ragularization factor lambda", 0.006, true); + parser.addArgument("csa", "csa", ctkCommandLineParser::Bool, "use constant solid angle consideration"); + parser.addArgument("outputCoeffs", "shc", ctkCommandLineParser::Bool, "output file containing the SH coefficients"); + + map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0) return EXIT_FAILURE; - } + + std::string inFileName = us::any_cast(parsedArgs["input"]); + std::string outfilename = us::any_cast(parsedArgs["outFile"]); + outfilename = itksys::SystemTools::GetFilenameWithoutExtension(outfilename); + + int threshold = 0; + if (parsedArgs.count("b0Threshold")) + threshold = us::any_cast(parsedArgs["b0Threshold"]); + + int shOrder = 4; + if (parsedArgs.count("shOrder")) + shOrder = us::any_cast(parsedArgs["shOrder"]); + + float lambda = 0.006; + if (parsedArgs.count("lambda")) + lambda = us::any_cast(parsedArgs["lambda"]); + + int normalization = 0; + if (parsedArgs.count("csa") && us::any_cast(parsedArgs["csa"])) + normalization = 6; + + bool outCoeffs = false; + if (parsedArgs.count("outputCoeffs")) + outCoeffs = us::any_cast(parsedArgs["outputCoeffs"]); try { RegisterDiffusionCoreObjectFactory(); MITK_INFO << "Loading image ..."; const std::string s1="", s2=""; - std::vector infile = BaseDataIO::LoadBaseDataFromFile( argv[2], s1, s2, false ); + std::vector infile = BaseDataIO::LoadBaseDataFromFile( inFileName, s1, s2, false ); DiffusionImage::Pointer dwi = dynamic_cast*>(infile.at(0).GetPointer()); dwi->AverageRedundantGradients(0.001); mitk::QBallImage::Pointer image = mitk::QBallImage::New(); + mitk::Image::Pointer coeffsImage = mitk::Image::New(); - - int shOrder = 4; - if ( argc>6 ) - shOrder = boost::lexical_cast(argv[6]); - MITK_INFO << "Using SH order of " << shOrder; + MITK_INFO << "SH order: " << shOrder; + MITK_INFO << "lambda: " << lambda; + MITK_INFO << "B0 threshold: " << threshold; switch ( shOrder ) { case 4: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( dwi->GetDirections(), dwi->GetVectorImage() ); filter->SetBValue(dwi->GetB_Value()); - filter->SetThreshold( boost::lexical_cast(argv[4]) ); - filter->SetLambda(boost::lexical_cast(argv[3])); - filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); + filter->SetThreshold( threshold ); + filter->SetLambda(lambda); + if (normalization==0) + filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); + else + filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); + coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); + coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 6: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( dwi->GetDirections(), dwi->GetVectorImage() ); filter->SetBValue(dwi->GetB_Value()); - filter->SetThreshold( boost::lexical_cast(argv[4]) ); - filter->SetLambda(boost::lexical_cast(argv[3])); - filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); + filter->SetThreshold( threshold ); + filter->SetLambda(lambda); + if (normalization==0) + filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); + else + filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); + coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); + coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 8: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( dwi->GetDirections(), dwi->GetVectorImage() ); filter->SetBValue(dwi->GetB_Value()); - filter->SetThreshold( boost::lexical_cast(argv[4]) ); - filter->SetLambda(boost::lexical_cast(argv[3])); - filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); + filter->SetThreshold( threshold ); + filter->SetLambda(lambda); + if (normalization==0) + filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); + else + filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); + coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); + coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } case 10: { typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( dwi->GetDirections(), dwi->GetVectorImage() ); filter->SetBValue(dwi->GetB_Value()); - filter->SetThreshold( boost::lexical_cast(argv[4]) ); - filter->SetLambda(boost::lexical_cast(argv[3])); - filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); + filter->SetThreshold( threshold ); + filter->SetLambda(lambda); + if (normalization==0) + filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); + else + filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); + coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); + coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); break; } default: { MITK_INFO << "Supplied SH order not supported. Using default order of 4."; typedef itk::AnalyticalDiffusionQballReconstructionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetGradientImage( dwi->GetDirections(), dwi->GetVectorImage() ); filter->SetBValue(dwi->GetB_Value()); - filter->SetThreshold( boost::lexical_cast(argv[4]) ); - filter->SetLambda(boost::lexical_cast(argv[3])); - filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); + filter->SetThreshold( threshold ); + filter->SetLambda(lambda); + if (normalization==0) + filter->SetNormalizationMethod(FilterType::QBAR_STANDARD); + else + filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE); filter->Update(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); + coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() ); + coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() ); } } - std::string outfilename = argv[5]; + std::string coeffout = outfilename; + coeffout += "_shcoeffs.nrrd"; + + outfilename += ".qbi"; MITK_INFO << "writing image " << outfilename; mitk::NrrdQBallImageWriter::Pointer writer = mitk::NrrdQBallImageWriter::New(); writer->SetInput(image.GetPointer()); writer->SetFileName(outfilename.c_str()); writer->Update(); + + if (outCoeffs) + mitk::IOUtil::SaveImage(coeffsImage, coeffout); } catch ( itk::ExceptionObject &err) { MITK_INFO << "Exception: " << err; } catch ( std::exception err) { MITK_INFO << "Exception: " << err.what(); } catch ( ... ) { MITK_INFO << "Exception!"; } return EXIT_SUCCESS; } RegisterDiffusionCoreMiniApp(QballReconstruction); diff --git a/Modules/DiffusionImaging/DiffusionCore/MiniApps/TensorReconstruction.cpp b/Modules/DiffusionImaging/DiffusionCore/MiniApps/TensorReconstruction.cpp index 1f9eea61a3..f50ee7c625 100644 --- a/Modules/DiffusionImaging/DiffusionCore/MiniApps/TensorReconstruction.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/MiniApps/TensorReconstruction.cpp @@ -1,89 +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 "MiniAppManager.h" #include "mitkBaseDataIOFactory.h" #include "mitkDiffusionImage.h" #include "mitkBaseData.h" #include "mitkDiffusionCoreObjectFactory.h" #include #include #include #include +#include "ctkCommandLineParser.h" +#include using namespace mitk; /** * Convert files from one ending to the other */ int TensorReconstruction(int argc, char* argv[]) { - if ( argc!=4 ) - { - std::cout << std::endl; - std::cout << "Perform Tensor estimation on an dwi file" << std::endl; - std::cout << std::endl; - std::cout << "usage: " << argv[0] << " " << argv[1] << " " << std::endl; - std::cout << std::endl; + ctkCommandLineParser parser; + parser.setArgumentPrefix("--", "-"); + parser.addArgument("input", "i", ctkCommandLineParser::String, "input raw dwi (.dwi or .fsl/.fslgz)", us::Any(), false); + parser.addArgument("outFile", "o", ctkCommandLineParser::String, "output file", us::Any(), false); + parser.addArgument("b0Threshold", "t", ctkCommandLineParser::Int, "baseline image intensity threshold", 0, true); + + map parsedArgs = parser.parseArguments(argc, argv); + if (parsedArgs.size()==0) return EXIT_FAILURE; - } + + std::string inFileName = us::any_cast(parsedArgs["input"]); + std::string outfilename = us::any_cast(parsedArgs["outFile"]); + outfilename = itksys::SystemTools::GetFilenameWithoutExtension(outfilename); + outfilename += ".dti"; + + int threshold = 0; + if (parsedArgs.count("b0Threshold")) + threshold = us::any_cast(parsedArgs["b0Threshold"]); try { RegisterDiffusionCoreObjectFactory(); MITK_INFO << "Loading image ..."; const std::string s1="", s2=""; - std::vector infile = BaseDataIO::LoadBaseDataFromFile( argv[2], s1, s2, false ); + std::vector infile = BaseDataIO::LoadBaseDataFromFile( inFileName, s1, s2, false ); DiffusionImage::Pointer dwi = dynamic_cast*>(infile.at(0).GetPointer()); - std::string outfilename = argv[3]; - + MITK_INFO << "B0 threshold: " << threshold; typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( dwi->GetDirections(), dwi->GetVectorImage() ); filter->SetBValue(dwi->GetB_Value()); + filter->SetThreshold(threshold); filter->Update(); // Save tensor image MITK_INFO << "writing image " << outfilename; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::New(); writer->SetInput(filter->GetOutput()); writer->SetFileName(outfilename); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); } catch ( itk::ExceptionObject &err) { MITK_INFO << "Exception: " << err; } catch ( std::exception err) { MITK_INFO << "Exception: " << err.what(); } catch ( ... ) { MITK_INFO << "Exception!"; } return EXIT_SUCCESS; } RegisterDiffusionCoreMiniApp(TensorReconstruction);