diff --git a/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp b/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp index 5574d3ef2a..6e7ecdc5d0 100644 --- a/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp +++ b/Modules/DiffusionImaging/MiniApps/DwiDenoising.cpp @@ -1,168 +1,168 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY 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 "ctkCommandLineParser.h" #include #include #include #include #include typedef mitk::DiffusionImage DiffusionImageType; typedef itk::Image ImageType; mitk::BaseData::Pointer LoadFile(std::string filename) { if( filename.empty() ) return NULL; const std::string s1="", s2=""; std::vector infile = mitk::BaseDataIO::LoadBaseDataFromFile( filename, s1, s2, false ); if( infile.empty() ) { MITK_INFO << "File " << filename << " could not be read!"; return NULL; } mitk::BaseData::Pointer baseData = infile.at(0); return baseData; } /** * Denoises DWI using the Nonlocal - Means algorithm */ int DwiDenoising(int argc, char* argv[]) { ctkCommandLineParser parser; parser.setTitle("DWI Denoising"); parser.setCategory("Preprocessing Tools"); parser.setContributor("MBI"); parser.setDescription("Denoising for diffusion weighted images using a non-local means algorithm."); parser.setArgumentPrefix("--", "-"); parser.addArgument("input", "i", ctkCommandLineParser::InputFile, "Input:", "input image (DWI)", us::Any(), false); parser.addArgument("variance", "v", ctkCommandLineParser::Float, "Variance:", "noise variance", us::Any(), false); parser.addArgument("mask", "m", ctkCommandLineParser::InputFile, "Mask:", "brainmask for input image", us::Any(), true); parser.addArgument("search", "s", ctkCommandLineParser::Int, "Search radius:", "search radius", us::Any(), true); parser.addArgument("compare", "c", ctkCommandLineParser::Int, "Comparison radius:", "comparison radius", us::Any(), true); parser.addArgument("joint", "j", ctkCommandLineParser::Bool, "Joint information:", "use joint information"); parser.addArgument("rician", "r", ctkCommandLineParser::Bool, "Rician adaption:", "use rician adaption"); parser.changeParameterGroup("Output", "Output of this miniapp"); - parser.addArgument("output", "o", ctkCommandLineParser::OutputFile, "Output:", "output image (DWI)", us::Any(), false); + parser.addArgument("output", "o", ctkCommandLineParser::OutputFile, "Output:", "output image (DWI)", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFileName = us::any_cast(parsedArgs["input"]); double variance = static_cast(us::any_cast(parsedArgs["variance"])); string maskName; if (parsedArgs.count("mask")) maskName = us::any_cast(parsedArgs["mask"]); string outFileName = us::any_cast(parsedArgs["output"]); // boost::algorithm::erase_all(outFileName, ".dwi"); int search = 4; if (parsedArgs.count("search")) search = us::any_cast(parsedArgs["search"]); int compare = 1; if (parsedArgs.count("compare")) compare = us::any_cast(parsedArgs["compare"]); bool joint = false; if (parsedArgs.count("joint")) joint = true; bool rician = false; if (parsedArgs.count("rician")) rician = true; try { if( boost::algorithm::ends_with(inFileName, ".dwi")) { DiffusionImageType::Pointer dwi = dynamic_cast(LoadFile(inFileName).GetPointer()); itk::NonLocalMeansDenoisingFilter::Pointer filter = itk::NonLocalMeansDenoisingFilter::New(); filter->SetNumberOfThreads(12); filter->SetInputImage(dwi->GetVectorImage()); if (!maskName.empty()) { mitk::Image::Pointer mask = dynamic_cast(LoadFile(maskName).GetPointer()); ImageType::Pointer itkMask = ImageType::New(); mitk::CastToItkImage(mask, itkMask); filter->SetInputMask(itkMask); } filter->SetUseJointInformation(joint); filter->SetUseRicianAdaption(rician); filter->SetSearchRadius(search); filter->SetComparisonRadius(compare); filter->SetVariance(variance); filter->Update(); DiffusionImageType::Pointer output = DiffusionImageType::New(); output->SetVectorImage(filter->GetOutput()); output->SetReferenceBValue(dwi->GetReferenceBValue()); output->SetDirections(dwi->GetDirections()); output->InitializeFromVectorImage(); // std::stringstream name; // name << outFileName << "_NLM_" << search << "-" << compare << "-" << variance << ".dwi"; MITK_INFO << "Writing: " << outFileName; mitk::NrrdDiffusionImageWriter::Pointer writer = mitk::NrrdDiffusionImageWriter::New(); writer->SetInput(output); writer->SetFileName(outFileName/*.str()*/); writer->Update(); MITK_INFO << "Finish!"; } else { MITK_INFO << "Only supported for .dwi!"; } } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } RegisterDiffusionMiniApp(DwiDenoising); diff --git a/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp b/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp index 4489c1cd34..6f66eef245 100755 --- a/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberExtraction.cpp @@ -1,132 +1,138 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY 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 "ctkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int FiberExtraction(int argc, char* argv[]) { ctkCommandLineParser parser; + + parser.setTitle("Fiber Extraction"); + parser.setCategory("Fiber Tracking and Processing Methods"); + parser.setContributor("MBI"); + parser.setDescription(""); + parser.setArgumentPrefix("--", "-"); - parser.addArgument("input", "i", ctkCommandLineParser::String, "input tractogram (.fib, vtk ascii file format)", us::Any(), false); - parser.addArgument("out", "o", ctkCommandLineParser::String, "output tractogram", us::Any(), false); - parser.addArgument("planfirgure1", "pf1", ctkCommandLineParser::String, "first planar figure", us::Any(), false); - parser.addArgument("planfirgure2", "pf2", ctkCommandLineParser::String, "second planar figure", us::Any()); - parser.addArgument("operation", "op", ctkCommandLineParser::String, "logical operation (AND, OR, NOT)", us::Any()); + parser.addArgument("input", "i", ctkCommandLineParser::String, "Input:", "input tractogram (.fib, vtk ascii file format)", us::Any(), false); + parser.addArgument("out", "o", ctkCommandLineParser::String, "Output:", "output tractogram", us::Any(), false); + parser.addArgument("planfirgure1", "pf1", ctkCommandLineParser::String, "Figure 1:", "first planar figure", us::Any(), false); + parser.addArgument("planfirgure2", "pf2", ctkCommandLineParser::String, "Figure 2:", "second planar figure", us::Any()); + parser.addArgument("operation", "op", ctkCommandLineParser::String, "Operation:", "logical operation (AND, OR, NOT)", us::Any()); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; string inFib = us::any_cast(parsedArgs["input"]); string outFib = us::any_cast(parsedArgs["out"]); string pf1_path = us::any_cast(parsedArgs["planfirgure1"]); string operation(""); string pf2_path(""); if (parsedArgs.count("operation")) { operation = us::any_cast(parsedArgs["operation"]); if (parsedArgs.count("planfirgure2") && (operation=="AND" || operation=="OR")) pf2_path = us::any_cast(parsedArgs["planfirgure2"]); } try { typedef itk::Image ItkUcharImgType; // load fiber bundle mitk::FiberBundleX::Pointer inputTractogram = dynamic_cast(mitk::IOUtil::LoadDataNode(inFib)->GetData()); mitk::PlanarFigure::Pointer pf1 = dynamic_cast(mitk::IOUtil::LoadDataNode(pf1_path)->GetData()); mitk::PlanarFigure::Pointer pf2; if (!pf2_path.empty()) pf2 = dynamic_cast(mitk::IOUtil::LoadDataNode(pf2_path)->GetData()); mitk::PlanarFigureComposite::Pointer pfc = mitk::PlanarFigureComposite::New(); mitk::FiberBundleX::Pointer result; if (operation.empty()) { result = inputTractogram->ExtractFiberSubset(pf1); } else if (operation=="NOT") { pfc->setOperationType(mitk::PFCOMPOSITION_NOT_OPERATION); pfc->addPlanarFigure(pf1); result = inputTractogram->ExtractFiberSubset(pfc); } else if (operation=="AND" && pf2.IsNotNull()) { pfc->setOperationType(mitk::PFCOMPOSITION_AND_OPERATION); pfc->addPlanarFigure(pf1); pfc->addPlanarFigure(pf2); result = inputTractogram->ExtractFiberSubset(pfc); } else if (operation=="OR" && pf2.IsNotNull()) { pfc->setOperationType(mitk::PFCOMPOSITION_OR_OPERATION); pfc->addPlanarFigure(pf1); pfc->addPlanarFigure(pf2); result = inputTractogram->ExtractFiberSubset(pfc); } else { MITK_INFO << "Could not process input:"; MITK_INFO << pf1_path; MITK_INFO << pf2_path; MITK_INFO << operation; } if (result.IsNotNull()) { mitk::IOUtil::SaveBaseData(result, outFib); } else MITK_INFO << "No valid fiber bundle extracted."; MITK_INFO << "DONE"; } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } RegisterDiffusionMiniApp(FiberExtraction); diff --git a/Modules/DiffusionImaging/MiniApps/FiberJoin.cpp b/Modules/DiffusionImaging/MiniApps/FiberJoin.cpp index 351c6efb4b..2728b666e5 100755 --- a/Modules/DiffusionImaging/MiniApps/FiberJoin.cpp +++ b/Modules/DiffusionImaging/MiniApps/FiberJoin.cpp @@ -1,83 +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 "MiniAppManager.h" #include #include #include "ctkCommandLineParser.h" #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include int FiberJoin(int argc, char* argv[]) -{ + { ctkCommandLineParser parser; + + parser.setTitle("Fiber Join"); + parser.setCategory("Fiber Tracking and Processing Methods"); + parser.setContributor("MBI"); + parser.setDescription(""); + parser.setArgumentPrefix("--", "-"); - parser.addArgument("input", "i", ctkCommandLineParser::StringList, "input tractograms (.fib, vtk file format)", us::Any(), false); - parser.addArgument("out", "o", ctkCommandLineParser::String, "output tractogram", us::Any(), false); + parser.addArgument("input", "i", ctkCommandLineParser::StringList, "Input:", "input tractograms (.fib, vtk file format)", us::Any(), false); + parser.addArgument("out", "o", ctkCommandLineParser::String, "Output:", "output tractogram", us::Any(), false); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; ctkCommandLineParser::StringContainerType inFibs = us::any_cast(parsedArgs["input"]); string outFib = us::any_cast(parsedArgs["out"]); if (inFibs.size()<=1) { MITK_INFO << "More than one input tractogram required!"; return EXIT_FAILURE; } try { mitk::FiberBundleX::Pointer result = dynamic_cast(mitk::IOUtil::LoadDataNode(inFibs.at(0))->GetData()); for (int i=1; i(mitk::IOUtil::LoadDataNode(inFibs.at(i))->GetData()); result = result->AddBundle(inputTractogram); } catch(...){ MITK_INFO << "could not load: " << inFibs.at(i); } } mitk::IOUtil::SaveBaseData(result, outFib); } catch (itk::ExceptionObject e) { MITK_INFO << e; return EXIT_FAILURE; } catch (std::exception e) { MITK_INFO << e.what(); return EXIT_FAILURE; } catch (...) { MITK_INFO << "ERROR!?!"; return EXIT_FAILURE; } return EXIT_SUCCESS; } RegisterDiffusionMiniApp(FiberJoin); diff --git a/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp b/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp index 270a1017f6..70ba901e54 100644 --- a/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp +++ b/Modules/DiffusionImaging/MiniApps/ImageResampler.cpp @@ -1,339 +1,344 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY 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" // CTK #include "ctkCommandLineParser.h" #include #include #include #include #include #include #include "mitkNrrdDiffusionImageWriter.h" #include #include // ITK #include #include #include "itkLinearInterpolateImageFunction.h" #include "itkWindowedSincInterpolateImageFunction.h" #include "itkIdentityTransform.h" #include "itkResampleImageFilter.h" #include "itkResampleDwiImageFilter.h" typedef itk::Image InputImageType; typedef mitk::DiffusionImage DiffusionImageType; static mitk::Image::Pointer TransformToReference(mitk::Image *reference, mitk::Image *moving, bool sincInterpol = false) { // Convert to itk Images InputImageType::Pointer itkReference = InputImageType::New(); InputImageType::Pointer itkMoving = InputImageType::New(); mitk::CastToItkImage(reference,itkReference); mitk::CastToItkImage(moving,itkMoving); // Identify Transform typedef itk::IdentityTransform T_Transform; T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 3> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typedef itk::ResampleImageFilter ResampleFilterType; ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(itkMoving); resampler->SetReferenceImage( itkReference ); resampler->UseReferenceImageOn(); resampler->SetTransform(_pTransform); resampler->SetInterpolator(sinc_interpolator); resampler->Update(); // Convert back to mitk mitk::Image::Pointer result = mitk::Image::New(); result->InitializeByItk(resampler->GetOutput()); GrabItkImageMemory( resampler->GetOutput() , result ); return result; } static std::vector &split(const std::string &s, char delim, std::vector &elems) { std::stringstream ss(s); std::string item; while (std::getline(ss, item, delim)) { elems.push_back(item); } return elems; } static std::vector split(const std::string &s, char delim) { std::vector < std::string > elems; return split(s, delim, elems); } static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing, bool useLinInt = true) { InputImageType::Pointer itkImage = InputImageType::New(); CastToItkImage(input,itkImage); /** * 1) Resampling * */ // Identity transform. // We don't want any transform on our image except rescaling which is not // specified by a transform but by the input/output spacing as we will see // later. // So no transform will be specified. typedef itk::IdentityTransform T_Transform; // The resampler type itself. typedef itk::ResampleImageFilter T_ResampleFilter; // Prepare the resampler. // Instantiate the transform and specify it should be the id transform. T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); // Instantiate the resampler. Wire in the transform and the interpolator. T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New(); // Specify the input. _pResizeFilter->SetInput(itkImage); _pResizeFilter->SetTransform(_pTransform); // Set the output origin. _pResizeFilter->SetOutputOrigin(itkImage->GetOrigin()); // Compute the size of the output. // The size (# of pixels) in the output is recomputed using // the ratio of the input and output sizes. InputImageType::SpacingType inputSpacing = itkImage->GetSpacing(); InputImageType::SpacingType outputSpacing; const InputImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion(); InputImageType::SizeType outputSize; typedef InputImageType::SizeType::SizeValueType SizeValueType; // Set the output spacing. outputSpacing[0] = spacing[0]; outputSpacing[1] = spacing[1]; outputSpacing[2] = spacing[2]; outputSize[0] = static_cast(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5); outputSize[1] = static_cast(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5); outputSize[2] = static_cast(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5); _pResizeFilter->SetOutputSpacing(outputSpacing); _pResizeFilter->SetSize(outputSize); typedef itk::LinearInterpolateImageFunction< InputImageType > LinearInterpolatorType; LinearInterpolatorType::Pointer lin_interpolator = LinearInterpolatorType::New(); typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 4> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); if (useLinInt) _pResizeFilter->SetInterpolator(lin_interpolator); else _pResizeFilter->SetInterpolator(sinc_interpolator); _pResizeFilter->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(_pResizeFilter->GetOutput()); mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image); return image; } /// Save images according to file type static void SaveImage(std::string fileName, mitk::Image* image, std::string fileType ) { MITK_INFO << "----Save to " << fileName; if (fileType == "dwi") // IOUtil does not handle dwi files properly Bug 15772 { mitk::NrrdDiffusionImageWriter< short >::Pointer dwiwriter = mitk::NrrdDiffusionImageWriter< short >::New(); dwiwriter->SetInput( dynamic_cast* > (image)); dwiwriter->SetFileName( fileName ); try { dwiwriter->Update(); } catch( const itk::ExceptionObject& e) { MITK_ERROR << "Caught exception: " << e.what(); mitkThrow() << "Failed with exception from subprocess!"; } } else { mitk::IOUtil::SaveImage(image, fileName); } } DiffusionImageType::Pointer ResampleDWIbySpacing(DiffusionImageType::Pointer input, float* spacing, bool useLinInt = true) { itk::Vector spacingVector; spacingVector[0] = spacing[0]; spacingVector[1] = spacing[1]; spacingVector[2] = spacing[2]; typedef itk::ResampleDwiImageFilter ResampleFilterType; ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(input->GetVectorImage()); resampler->SetInterpolation(ResampleFilterType::Interpolate_Linear); resampler->SetNewSpacing(spacingVector); resampler->Update(); DiffusionImageType::Pointer output = DiffusionImageType::New(); output->SetVectorImage(resampler->GetOutput()); output->SetDirections(input->GetDirections()); output->SetReferenceBValue(input->GetReferenceBValue()); output->InitializeFromVectorImage(); return output; } int ImageResampler( int argc, char* argv[] ) { ctkCommandLineParser parser; parser.setArgumentPrefix("--","-"); + + parser.setTitle("Image Resampler"); + parser.setCategory("Preprocessing Tools"); + parser.setContributor("MBI"); + parser.setDescription(""); + // Add command line argument names parser.addArgument("help", "h",ctkCommandLineParser::Bool, "Show this help text"); - parser.addArgument("xml", "x",ctkCommandLineParser::Bool, "Print a XML description of this modules command line interface"); - parser.addArgument("input", "i", ctkCommandLineParser::String, "Input file",us::Any(),false); - parser.addArgument("output", "o", ctkCommandLineParser::String, "Output folder (ending with /)",us::Any(),false); - parser.addArgument("spacing", "s", ctkCommandLineParser::String, "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any()); - parser.addArgument("reference", "r", ctkCommandLineParser::String, "Resample using supplied reference image. Also cuts image to same dimensions"); - parser.addArgument("sinc-int", "s", ctkCommandLineParser::Bool, "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any()); + parser.addArgument("input", "i", ctkCommandLineParser::String, "Input:", "Input file",us::Any(),false); + parser.addArgument("output", "o", ctkCommandLineParser::String, "Output:", "Output folder (ending with /)",us::Any(),false); + parser.addArgument("spacing", "s", ctkCommandLineParser::String, "Spacing:", "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any()); + parser.addArgument("reference", "r", ctkCommandLineParser::String, "Reference:", "Resample using supplied reference image. Also cuts image to same dimensions"); + parser.addArgument("sinc-int", "s", ctkCommandLineParser::Bool, "Windowed-sinc interpolation:", "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any()); map parsedArgs = parser.parseArguments(argc, argv); // Handle special arguments bool useSpacing = false; bool useLinearInterpol = true; { if (parsedArgs.size() == 0) { MITK_ERROR << "Missig arguements" ; return EXIT_FAILURE; } if (parsedArgs.count("xml")) { MITK_ERROR << "This is to be handled by shell script"; return EXIT_SUCCESS; } if (parsedArgs.count("sinc-int")) useLinearInterpol = false; // Show a help message if ( parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } } std::string outputPath = us::any_cast(parsedArgs["output"]); std::string inputFile = us::any_cast(parsedArgs["input"]); std::vector spacings; float spacing[3]; if (parsedArgs.count("spacing")) { std::string arg = us::any_cast(parsedArgs["spacing"]); spacings = split(arg ,','); spacing[0] = atoi(spacings.at(0).c_str()); spacing[1] = atoi(spacings.at(1).c_str()); spacing[2] = atoi(spacings.at(2).c_str()); useSpacing = true; } std::string refImageFile = ""; if (parsedArgs.count("reference")) { refImageFile = us::any_cast(parsedArgs["reference"]); } if (refImageFile =="" && useSpacing == false) { MITK_ERROR << "No information how to resample is supplied. Use eigther --spacing or --reference !"; return EXIT_FAILURE; } mitk::Image::Pointer refImage; if (!useSpacing) refImage = mitk::IOUtil::LoadImage(refImageFile); DiffusionImageType::Pointer inputDWI = dynamic_cast(mitk::IOUtil::LoadBaseData(inputFile).GetPointer()); if (inputDWI.IsNotNull()) { DiffusionImageType::Pointer outputImage; if (useSpacing) outputImage = ResampleDWIbySpacing(inputDWI, spacing); else { MITK_WARN << "Not supported yet, to resample a DWI please set a new spacing."; return EXIT_FAILURE; } std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(inputFile); mitk::NrrdDiffusionImageWriter::Pointer writer = mitk::NrrdDiffusionImageWriter::New(); writer->SetInput(outputImage); writer->SetFileName(outputPath + fileStem + "_res.dwi"); writer->Update(); return EXIT_SUCCESS; } mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(inputFile); mitk::Image::Pointer resultImage; if (useSpacing) resultImage = ResampleBySpacing(inputImage,spacing); else resultImage = TransformToReference(refImage,inputImage); std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(inputFile); mitk::IOUtil::SaveImage(resultImage, outputPath + fileStem + "_res.nrrd"); return EXIT_SUCCESS; } RegisterDiffusionMiniApp(ImageResampler); diff --git a/Modules/DiffusionImaging/MiniApps/ctkCommandLineParser.cpp b/Modules/DiffusionImaging/MiniApps/ctkCommandLineParser.cpp index dc3637c135..355c22d404 100755 --- a/Modules/DiffusionImaging/MiniApps/ctkCommandLineParser.cpp +++ b/Modules/DiffusionImaging/MiniApps/ctkCommandLineParser.cpp @@ -1,881 +1,881 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*========================================================================= Library: CTK Copyright (c) Kitware Inc. 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. =========================================================================*/ // STL includes #include // CTK includes #include "ctkCommandLineParser.h" using namespace std; namespace { // -------------------------------------------------------------------------- class CommandLineParserArgumentDescription { public: CommandLineParserArgumentDescription( const string& longArg, const string& longArgPrefix, const string& shortArg, const string& shortArgPrefix, ctkCommandLineParser::Type type, const string& argHelp, const string& argLabel, const us::Any& defaultValue, bool ignoreRest, bool deprecated, bool optional, string& argGroup, string& groupDescription) : LongArg(longArg), LongArgPrefix(longArgPrefix), ShortArg(shortArg), ShortArgPrefix(shortArgPrefix), ArgHelp(argHelp), ArgLabel(argLabel), IgnoreRest(ignoreRest), NumberOfParametersToProcess(0), Deprecated(deprecated), DefaultValue(defaultValue), Value(type), ValueType(type), Optional(optional), ArgGroup(argGroup), ArgGroupDescription(groupDescription) { Value = defaultValue; switch (type) { case ctkCommandLineParser::String: { NumberOfParametersToProcess = 1; } break; case ctkCommandLineParser::Bool: { NumberOfParametersToProcess = 0; } break; case ctkCommandLineParser::StringList: { NumberOfParametersToProcess = -1; } break; case ctkCommandLineParser::Int: { NumberOfParametersToProcess = 1; } break; case ctkCommandLineParser::Float: { NumberOfParametersToProcess = 1; } break; case ctkCommandLineParser::OutputDirectory: case ctkCommandLineParser::InputDirectory: { NumberOfParametersToProcess = 1; } break; case ctkCommandLineParser::OutputFile: case ctkCommandLineParser::InputFile: { NumberOfParametersToProcess = 1; } break; default: MITK_INFO << "Type not supported: " << static_cast(type); } } ~CommandLineParserArgumentDescription(){} bool addParameter(const string& value); string helpText(); string LongArg; string LongArgPrefix; string ShortArg; string ShortArgPrefix; string ArgHelp; string ArgLabel; string ArgGroup; string ArgGroupDescription; bool IgnoreRest; int NumberOfParametersToProcess; bool Deprecated; bool Optional; us::Any DefaultValue; us::Any Value; ctkCommandLineParser::Type ValueType; }; // -------------------------------------------------------------------------- bool CommandLineParserArgumentDescription::addParameter(const string &value) { switch (ValueType) { case ctkCommandLineParser::String: { Value = value; } break; case ctkCommandLineParser::Bool: { if (value.compare("true")==0) Value = true; else Value = false; } break; case ctkCommandLineParser::StringList: { try { ctkCommandLineParser::StringContainerType list = us::any_cast(Value); list.push_back(value); Value = list; } catch(...) { ctkCommandLineParser::StringContainerType list; list.push_back(value); Value = list; } } break; case ctkCommandLineParser::Int: { stringstream ss(value); int i; ss >> i; Value = i; } break; case ctkCommandLineParser::Float: { stringstream ss(value); float f; ss >> f; Value = f; } break; case ctkCommandLineParser::InputDirectory: case ctkCommandLineParser::OutputDirectory: { Value = value; } break; case ctkCommandLineParser::InputFile: case ctkCommandLineParser::OutputFile: { Value = value; } break; default: return false; } return true; } // -------------------------------------------------------------------------- string CommandLineParserArgumentDescription::helpText() { string text; string shortAndLongArg; if (!this->ShortArg.empty()) { shortAndLongArg = " "; shortAndLongArg += this->ShortArgPrefix; shortAndLongArg += this->ShortArg; } if (!this->LongArg.empty()) { if (this->ShortArg.empty()) shortAndLongArg.append(" "); else shortAndLongArg.append(", "); shortAndLongArg += this->LongArgPrefix; shortAndLongArg += this->LongArg; } text = text + shortAndLongArg + ", " + this->ArgHelp; if (this->Optional) text += " (optional)"; if (!this->DefaultValue.Empty()) { text = text + ", (default: " + this->DefaultValue.ToString() + ")"; } text += "\n"; return text; } } // -------------------------------------------------------------------------- // ctkCommandLineParser::ctkInternal class // -------------------------------------------------------------------------- class ctkCommandLineParser::ctkInternal { public: ctkInternal() : Debug(false), FieldWidth(0), StrictMode(false) {} ~ctkInternal() { } CommandLineParserArgumentDescription* argumentDescription(const string& argument); vector ArgumentDescriptionList; map ArgNameToArgumentDescriptionMap; map > GroupToArgumentDescriptionListMap; StringContainerType UnparsedArguments; StringContainerType ProcessedArguments; string ErrorString; bool Debug; int FieldWidth; string LongPrefix; string ShortPrefix; string CurrentGroup; string DisableQSettingsLongArg; string DisableQSettingsShortArg; bool StrictMode; }; // -------------------------------------------------------------------------- // ctkCommandLineParser::ctkInternal methods // -------------------------------------------------------------------------- CommandLineParserArgumentDescription* ctkCommandLineParser::ctkInternal::argumentDescription(const string& argument) { string unprefixedArg = argument; if (!LongPrefix.empty() && argument.compare(0, LongPrefix.size(), LongPrefix)==0) { // Case when (ShortPrefix + UnPrefixedArgument) matches LongPrefix if (argument == LongPrefix && !ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix)==0) { unprefixedArg = argument.substr(ShortPrefix.size(),argument.size()); } else { unprefixedArg = argument.substr(LongPrefix.size(),argument.size()); } } else if (!ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix)==0) { unprefixedArg = argument.substr(ShortPrefix.size(),argument.size()); } else if (!LongPrefix.empty() && !ShortPrefix.empty()) { return 0; } if (ArgNameToArgumentDescriptionMap.count(unprefixedArg)) { return this->ArgNameToArgumentDescriptionMap[unprefixedArg]; } return 0; } // -------------------------------------------------------------------------- // ctkCommandLineParser methods // -------------------------------------------------------------------------- ctkCommandLineParser::ctkCommandLineParser() { this->Internal = new ctkInternal(); this->Category = string(); this->Title = string(); this->Contributor = string(); this->Description = string(); this->ParameterGroupName = "Parameters"; this->ParameterGroupDescription = "Groupbox containing parameters."; } // -------------------------------------------------------------------------- ctkCommandLineParser::~ctkCommandLineParser() { delete this->Internal; } // -------------------------------------------------------------------------- map ctkCommandLineParser::parseArguments(const StringContainerType& arguments, bool* ok) { // Reset this->Internal->UnparsedArguments.clear(); this->Internal->ProcessedArguments.clear(); this->Internal->ErrorString.clear(); // foreach (CommandLineParserArgumentDescription* desc, this->Internal->ArgumentDescriptionList) for (unsigned int i=0; iArgumentDescriptionList.size(); i++) { CommandLineParserArgumentDescription* desc = Internal->ArgumentDescriptionList.at(i); desc->Value = us::Any(desc->ValueType); if (!desc->DefaultValue.Empty()) { desc->Value = desc->DefaultValue; } } bool error = false; bool ignoreRest = false; CommandLineParserArgumentDescription * currentArgDesc = 0; vector parsedArgDescriptions; for(unsigned int i = 1; i < arguments.size(); ++i) { string argument = arguments.at(i); if (this->Internal->Debug) { MITK_DEBUG << "Processing" << argument; } if (!argument.compare("--xml") || !argument.compare("-xml") || !argument.compare("--XML") || !argument.compare("-XML")) { - this->GetXML(); + this->generateXmlOutput(); return map(); } // should argument be ignored ? if (ignoreRest) { if (this->Internal->Debug) { MITK_DEBUG << " Skipping: IgnoreRest flag was been set"; } this->Internal->UnparsedArguments.push_back(argument); continue; } // Skip if the argument does not start with the defined prefix if (!(argument.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix)==0 || argument.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix)==0)) { if (this->Internal->StrictMode) { this->Internal->ErrorString = "Unknown argument "; this->Internal->ErrorString += argument; error = true; break; } if (this->Internal->Debug) { MITK_DEBUG << " Skipping: It does not start with the defined prefix"; } this->Internal->UnparsedArguments.push_back(argument); continue; } // Skip if argument has already been parsed ... bool alreadyProcessed = false; for (unsigned int i=0; iProcessedArguments.size(); i++) if (argument.compare(Internal->ProcessedArguments.at(i))==0) { alreadyProcessed = true; break; } if (alreadyProcessed) { if (this->Internal->StrictMode) { this->Internal->ErrorString = "Argument "; this->Internal->ErrorString += argument; this->Internal->ErrorString += " already processed !"; error = true; break; } if (this->Internal->Debug) { MITK_DEBUG << " Skipping: Already processed !"; } continue; } // Retrieve corresponding argument description currentArgDesc = this->Internal->argumentDescription(argument); // Is there a corresponding argument description ? if (currentArgDesc) { // If the argument is deprecated, print the help text but continue processing if (currentArgDesc->Deprecated) { MITK_WARN << "Deprecated argument " << argument << ": " << currentArgDesc->ArgHelp; } else { parsedArgDescriptions.push_back(currentArgDesc); } this->Internal->ProcessedArguments.push_back(currentArgDesc->ShortArg); this->Internal->ProcessedArguments.push_back(currentArgDesc->LongArg); int numberOfParametersToProcess = currentArgDesc->NumberOfParametersToProcess; ignoreRest = currentArgDesc->IgnoreRest; if (this->Internal->Debug && ignoreRest) { MITK_DEBUG << " IgnoreRest flag is True"; } // Is the number of parameters associated with the argument being processed known ? if (numberOfParametersToProcess == 0) { currentArgDesc->addParameter("true"); } else if (numberOfParametersToProcess > 0) { string missingParameterError = "Argument %1 has %2 value(s) associated whereas exacly %3 are expected."; for(int j=1; j <= numberOfParametersToProcess; ++j) { if (i + j >= arguments.size()) { // this->Internal->ErrorString = // missingParameterError.arg(argument).arg(j-1).arg(numberOfParametersToProcess); // if (this->Internal->Debug) { MITK_DEBUG << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } string parameter = arguments.at(i + j); if (this->Internal->Debug) { MITK_DEBUG << " Processing parameter" << j << ", value:" << parameter; } if (this->argumentAdded(parameter)) { // this->Internal->ErrorString = // missingParameterError.arg(argument).arg(j-1).arg(numberOfParametersToProcess); // if (this->Internal->Debug) { MITK_DEBUG << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } if (!currentArgDesc->addParameter(parameter)) { // this->Internal->ErrorString = string( // "Value(s) associated with argument %1 are incorrect. %2"). // arg(argument).arg(currentArgDesc->ExactMatchFailedMessage); // if (this->Internal->Debug) { MITK_DEBUG << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } } // Update main loop increment i = i + numberOfParametersToProcess; } else if (numberOfParametersToProcess == -1) { if (this->Internal->Debug) { MITK_DEBUG << " Proccessing StringList ..."; } int j = 1; while(j + i < arguments.size()) { if (this->argumentAdded(arguments.at(j + i))) { if (this->Internal->Debug) { MITK_DEBUG << " No more parameter for" << argument; } break; } string parameter = arguments.at(j + i); if (parameter.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix)==0 || parameter.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix)==0) { j--; break; } if (this->Internal->Debug) { MITK_DEBUG << " Processing parameter" << j << ", value:" << parameter; } if (!currentArgDesc->addParameter(parameter)) { // this->Internal->ErrorString = string( // "Value(s) associated with argument %1 are incorrect. %2"). // arg(argument).arg(currentArgDesc->ExactMatchFailedMessage); // if (this->Internal->Debug) { MITK_DEBUG << this->Internal->ErrorString; } if (ok) { *ok = false; } return map(); } j++; } // Update main loop increment i = i + j; } } else { if (this->Internal->StrictMode) { this->Internal->ErrorString = "Unknown argument "; this->Internal->ErrorString += argument; error = true; break; } if (this->Internal->Debug) { MITK_DEBUG << " Skipping: Unknown argument"; } this->Internal->UnparsedArguments.push_back(argument); } } if (ok) { *ok = !error; } map parsedArguments; int obligatoryArgs = 0; vector::iterator it; for(it = Internal->ArgumentDescriptionList.begin(); it != Internal->ArgumentDescriptionList.end();++it) { CommandLineParserArgumentDescription* desc = *it; if(!desc->Optional) obligatoryArgs++; } int parsedObligatoryArgs = 0; for(it = parsedArgDescriptions.begin(); it != parsedArgDescriptions.end();++it) { CommandLineParserArgumentDescription* desc = *it; string key; if (!desc->LongArg.empty()) { key = desc->LongArg; } else { key = desc->ShortArg; } if(!desc->Optional) parsedObligatoryArgs++; std::pair elem; elem.first = key; elem.second = desc->Value; parsedArguments.insert(elem); } if (obligatoryArgs>parsedObligatoryArgs) { parsedArguments.clear(); cout << helpText(); } return parsedArguments; } // ------------------------------------------------------------------------- map ctkCommandLineParser::parseArguments(int argc, char** argv, bool* ok) { StringContainerType arguments; // Create a StringContainerType of arguments for(int i = 0; i < argc; ++i) arguments.push_back(argv[i]); return this->parseArguments(arguments, ok); } // ------------------------------------------------------------------------- string ctkCommandLineParser::errorString() const { return this->Internal->ErrorString; } // ------------------------------------------------------------------------- const ctkCommandLineParser::StringContainerType& ctkCommandLineParser::unparsedArguments() const { return this->Internal->UnparsedArguments; } // -------------------------------------------------------------------------- void ctkCommandLineParser::addArgument(const string& longarg, const string& shortarg, Type type, const string& argLabel, const string& argHelp, const us::Any& defaultValue, bool optional, bool ignoreRest, bool deprecated) { if (longarg.empty() && shortarg.empty()) { return; } /* Make sure it's not already added */ bool added = this->Internal->ArgNameToArgumentDescriptionMap.count(longarg); if (added) { return; } added = this->Internal->ArgNameToArgumentDescriptionMap.count(shortarg); if (added) { return; } CommandLineParserArgumentDescription* argDesc = new CommandLineParserArgumentDescription(longarg, this->Internal->LongPrefix, shortarg, this->Internal->ShortPrefix, type, argHelp, argLabel, defaultValue, ignoreRest, deprecated, optional, ParameterGroupName, ParameterGroupDescription); int argWidth = 0; if (!longarg.empty()) { this->Internal->ArgNameToArgumentDescriptionMap[longarg] = argDesc; argWidth += longarg.size() + this->Internal->LongPrefix.size(); } if (!shortarg.empty()) { this->Internal->ArgNameToArgumentDescriptionMap[shortarg] = argDesc; argWidth += shortarg.size() + this->Internal->ShortPrefix.size() + 2; } argWidth += 5; // Set the field width for the arguments if (argWidth > this->Internal->FieldWidth) { this->Internal->FieldWidth = argWidth; } this->Internal->ArgumentDescriptionList.push_back(argDesc); this->Internal->GroupToArgumentDescriptionListMap[this->Internal->CurrentGroup].push_back(argDesc); } // -------------------------------------------------------------------------- void ctkCommandLineParser::addDeprecatedArgument( const string& longarg, const string& shortarg, const string& argLabel, const string& argHelp) { addArgument(longarg, shortarg, StringList, argLabel, argHelp, us::Any(), false, true, false); } // -------------------------------------------------------------------------- int ctkCommandLineParser::fieldWidth() const { return this->Internal->FieldWidth; } // -------------------------------------------------------------------------- void ctkCommandLineParser::beginGroup(const string& description) { this->Internal->CurrentGroup = description; } // -------------------------------------------------------------------------- void ctkCommandLineParser::endGroup() { this->Internal->CurrentGroup.clear(); } // -------------------------------------------------------------------------- string ctkCommandLineParser::helpText() const { string text; vector deprecatedArgs; // Loop over grouped argument descriptions map >::iterator it; for(it = Internal->GroupToArgumentDescriptionListMap.begin(); it != Internal->GroupToArgumentDescriptionListMap.end();++it) { if (!(*it).first.empty()) { text = text + "\n" + (*it).first + "\n"; } vector::iterator it2; for(it2 = (*it).second.begin(); it2 != (*it).second.end(); ++it2) { CommandLineParserArgumentDescription* argDesc = *it2; if (argDesc->Deprecated) { deprecatedArgs.push_back(argDesc); } else { text += argDesc->helpText(); } } } if (!deprecatedArgs.empty()) { text += "\nDeprecated arguments:\n"; vector::iterator it2; for(it2 = deprecatedArgs.begin(); it2 != deprecatedArgs.end(); ++it2) { CommandLineParserArgumentDescription* argDesc = *it2; text += argDesc->helpText(); } } return text; } // -------------------------------------------------------------------------- bool ctkCommandLineParser::argumentAdded(const string& argument) const { return this->Internal->ArgNameToArgumentDescriptionMap.count(argument); } // -------------------------------------------------------------------------- bool ctkCommandLineParser::argumentParsed(const string& argument) const { for (unsigned int i=0; iProcessedArguments.size(); i++) if (argument.compare(Internal->ProcessedArguments.at(i))==0) return true; return false; } // -------------------------------------------------------------------------- void ctkCommandLineParser::setArgumentPrefix(const string& longPrefix, const string& shortPrefix) { this->Internal->LongPrefix = longPrefix; this->Internal->ShortPrefix = shortPrefix; } // -------------------------------------------------------------------------- void ctkCommandLineParser::setStrictModeEnabled(bool strictMode) { this->Internal->StrictMode = strictMode; } -void ctkCommandLineParser::GetXML() +void ctkCommandLineParser::generateXmlOutput() { std::stringstream xml; xml << "" << endl; xml << "" << Category << "" << endl; xml << "" << Title <<"" << endl; xml << "" << Description << "" << endl; xml << "" << Contributor << "" << endl; xml << "" << endl; std::vector::iterator it; std::string lastParameterGroup = ""; for (it = this->Internal->ArgumentDescriptionList.begin(); it != this->Internal->ArgumentDescriptionList.end(); it++) { std::string type; switch ((*it)->ValueType) { case ctkCommandLineParser::String: type = "string"; break; case ctkCommandLineParser::Bool: type = "boolean"; break; case ctkCommandLineParser::StringList: type = "string-vector"; break; case ctkCommandLineParser::Int: type = "integer"; break; case ctkCommandLineParser::Float: type = "float"; break; case ctkCommandLineParser::OutputDirectory: case ctkCommandLineParser::InputDirectory: type = "directory"; break; case ctkCommandLineParser::OutputFile: case ctkCommandLineParser::InputFile: type = "file"; break; } if (lastParameterGroup.compare((*it)->ArgGroup)) { if (it != this->Internal->ArgumentDescriptionList.begin()) { xml << "" << endl; xml << "" << endl; } xml << "" << endl; xml << "" << (*it)->ArgGroupDescription << "" << endl; lastParameterGroup = (*it)->ArgGroup; } xml << "<" << type << ">" << endl; xml << "" << (*it)->LongArg << "" << endl; xml << "" << endl; xml << "" << (*it)->ArgHelp << "" << endl; xml << "" << (*it)->LongArg << "" << endl; xml << "" << (*it)->ShortArg << "" << endl; if ((*it)->ValueType == ctkCommandLineParser::InputDirectory || (*it)->ValueType == ctkCommandLineParser::InputFile) { xml << "input" << endl; } else if ((*it)->ValueType == ctkCommandLineParser::OutputDirectory || (*it)->ValueType == ctkCommandLineParser::OutputFile) { xml << "output" << endl; } xml << "" << endl; } xml << "" << endl; xml << "" << endl; cout << xml.str(); } void ctkCommandLineParser::setTitle(string title) { Title = title; } void ctkCommandLineParser::setContributor(string contributor) { Contributor = contributor; } void ctkCommandLineParser::setCategory(string category) { Category = category; } void ctkCommandLineParser::setDescription(string description) { Description = description; } -void ctkCommandLineParser::changeParameterGroup(string name, string description) +void ctkCommandLineParser::changeParameterGroup(string name, string tooltip) { ParameterGroupName = name; - ParameterGroupDescription = description; + ParameterGroupDescription = tooltip; } diff --git a/Modules/DiffusionImaging/MiniApps/ctkCommandLineParser.h b/Modules/DiffusionImaging/MiniApps/ctkCommandLineParser.h index 202fef074d..e6e0a356d0 100755 --- a/Modules/DiffusionImaging/MiniApps/ctkCommandLineParser.h +++ b/Modules/DiffusionImaging/MiniApps/ctkCommandLineParser.h @@ -1,441 +1,474 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*========================================================================= Library: CTK Copyright (c) Kitware Inc. 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 __ctkCommandLineParser_h #define __ctkCommandLineParser_h #include #include /** * \ingroup Core * * The CTK command line parser. * * Use this class to add information about the command line arguments * your program understands and to easily parse them from a given list * of strings. * * This parser provides the following features: * *
    *
  • Add arguments by supplying a long name and/or a short name. * Arguments are validated using a regular expression. They can have * a default value and a help string.
  • *
  • Deprecated arguments.
  • *
  • Custom regular expressions for argument validation.
  • *
  • Set different argument name prefixes for native platform look and feel.
  • *
  • QSettings support. Default values for arguments can be read from * a QSettings object.
  • *
  • Create a help text for the command line arguments with support for * grouping arguments.
  • *
* * Here is an example how to use this class inside a main function: * * \code * #include * #include * #include * * int main(int argc, char** argv) * { * QCoreApplication app(argc, argv); * // This is used by QSettings * QCoreApplication::setOrganizationName("MyOrg"); * QCoreApplication::setApplicationName("MyApp"); * * ctkCommandLineParser parser; * // Use Unix-style argument names * parser.setArgumentPrefix("--", "-"); * // Enable QSettings support * parser.enableSettings("disable-settings"); * * // Add command line argument names * parser.addArgument("disable-settings", "", us::Any::Bool, "Do not use QSettings"); * parser.addArgument("help", "h", us::Any::Bool, "Show this help text"); * parser.addArgument("search-paths", "s", us::Any::StringList, "A list of paths to search"); * * // Parse the command line arguments * bool ok = false; * map parsedArgs = parser.parseArguments(QCoreApplication::arguments(), &ok); * if (!ok) * { * QTextStream(stderr, QIODevice::WriteOnly) << "Error parsing arguments: " * << parser.errorString() << "\n"; * return EXIT_FAILURE; * } * * // Show a help message * if (parsedArgs.contains("help") || parsedArgs.contains("h")) * { * QTextStream(stdout, QIODevice::WriteOnly) << parser.helpText(); * return EXIT_SUCCESS; * } * * // Do something * * return EXIT_SUCCESS; * } * \endcode */ using namespace std; class ctkCommandLineParser { public: enum Type { String = 0, Bool = 1, StringList = 2, Int = 3, Float = 4, InputDirectory = 5, InputFile = 6, OutputDirectory = 7, OutputFile = 8 }; typedef std::vector< std::string > StringContainerType; /** * Constructs a parser instance. * * If QSettings support is enabled by a call to enableSettings() * a default constructed QSettings instance will be used when parsing * the command line arguments. Make sure to call QCoreApplication::setOrganizationName() * and QCoreApplication::setApplicationName() before using default * constructed QSettings objects. * * @param newParent The QObject parent. */ ctkCommandLineParser(); ~ctkCommandLineParser(); /** * Parse a given list of command line arguments. * * This method parses a list of string elements considering the known arguments * added by calls to addArgument(). If any one of the argument * values does not match the corresponding regular expression, * ok is set to false and an empty map object is returned. * * The keys in the returned map object correspond to the long argument string, * if it is not empty. Otherwise, the short argument string is used as key. The * us::Any values can safely be converted to the type specified in the * addArgument() method call. * * @param arguments A StringContainerType containing command line arguments. Usually * given by QCoreApplication::arguments(). * @param ok A pointer to a boolean variable. Will be set to true * if all regular expressions matched, false otherwise. * @return A map object mapping the long argument (if empty, the short one) * to a us::Any containing the value. */ map parseArguments(const StringContainerType &arguments, bool* ok = 0); /** * Convenient method allowing to parse a given list of command line arguments. * @see parseArguments(const StringContainerType &, bool*) */ map parseArguments(int argc, char** argv, bool* ok = 0); /** * Returns a detailed error description if a call to parseArguments() * failed. * * @return The error description, empty if no error occured. * @see parseArguments(const StringContainerType&, bool*) */ string errorString() const; /** * This method returns all unparsed arguments, i.e. all arguments * for which no long or short name has been registered via a call * to addArgument(). * * @see addArgument() * * @return A list containing unparsed arguments. */ const StringContainerType& unparsedArguments() const; /** * Checks if the given argument has been added via a call * to addArgument(). * * @see addArgument() * * @param argument The argument to be checked. * @return true if the argument was added, false * otherwise. */ bool argumentAdded(const string& argument) const; /** * Checks if the given argument has been parsed successfully by a previous * call to parseArguments(). * * @param argument The argument to be checked. * @return true if the argument was parsed, false * otherwise. */ bool argumentParsed(const string& argument) const; /** * Adds a command line argument. An argument can have a long name * (like --long-argument-name), a short name (like -l), or both. The type * of the argument can be specified by using the type parameter. * The following types are supported: * * * * * * * * *
Type# of parametersDefault regular exprExample
us::Any::String1.*--test-string StringParameter
us::Any::Bool0does not apply--enable-something
us::Any::StringList-1.*--test-list string1 string2
us::Any::Int1-?[0-9]+--test-int -5
* * The regular expressions are used to validate the parameters of command line * arguments. You can restrict the valid set of parameters by calling * setExactMatchRegularExpression() for your argument. * * Optionally, a help string and a default value can be provided for the argument. If * the us::Any type of the default value does not match type, an * exception is thrown. Arguments with default values are always returned by * parseArguments(). * * You can also declare an argument deprecated, by setting deprecated * to true. Alternatively you can add a deprecated argument by calling * addDeprecatedArgument(). * * If the long or short argument has already been added, or if both are empty strings, * the method call has no effect. * * @param longarg The long argument name. * @param shortarg The short argument name. * @param type The argument type (see the list above for supported types). + * @param argLabel The label of this argument, when auto generated interface is used. * @param argHelp A help string describing the argument. * @param defaultValue A default value for the argument. * @param ignoreRest All arguments after the current one will be ignored. * @param deprecated Declares the argument deprecated. * * @see setExactMatchRegularExpression() * @see addDeprecatedArgument() * @throws std::logic_error If the us::Any type of defaultValue * does not match type, a std::logic_error is thrown. */ void addArgument(const string& longarg, const string& shortarg, Type type, const string& argLabel, const string& argHelp = string(), const us::Any& defaultValue = us::Any(), bool optional=true, bool ignoreRest = false, bool deprecated = false); /** * Adds a deprecated command line argument. If a deprecated argument is provided * on the command line, argHelp is displayed in the console and * processing continues with the next argument. * * Deprecated arguments are grouped separately at the end of the help text * returned by helpText(). * * @param longarg The long argument name. * @param shortarg The short argument name. * @param argHelp A help string describing alternatives to the deprecated argument. */ void addDeprecatedArgument(const string& longarg, const string& shortarg, const string& argLabel, const string& argHelp); /** * Sets a custom regular expression for validating argument parameters. The method * errorString() can be used the get the last error description. * * @param argument The previously added long or short argument name. * @param expression A regular expression which the arugment parameters must match. * @param exactMatchFailedMessage An error message explaining why the parameter did * not match. * * @return true if the argument was found and the regular expression was set, * false otherwise. * * @see errorString() */ bool setExactMatchRegularExpression(const string& argument, const string& expression, const string& exactMatchFailedMessage); /** * The field width for the argument names without the help text. * * @return The argument names field width in the help text. */ int fieldWidth() const; /** * Creates a help text containing properly formatted argument names and help strings * provided by calls to addArgument(). The arguments can be grouped by * using beginGroup() and endGroup(). * * @param charPad The padding character. * @return The formatted help text. */ string helpText() const; /** * Sets the argument prefix for long and short argument names. This can be used * to create native command line arguments without changing the calls to * addArgument(). For example on Unix-based systems, long argument * names start with "--" and short names with "-", while on Windows argument names * always start with "/". * * Note that all methods in ctkCommandLineParser which take an argument name * expect the name as it was supplied to addArgument. * * Example usage: * * \code * ctkCommandLineParser parser; * parser.setArgumentPrefix("--", "-"); * parser.addArgument("long-argument", "l", us::Any::String); * StringContainerType args; * args << "program name" << "--long-argument Hi"; * parser.parseArguments(args); * \endcode * * @param longPrefix The prefix for long argument names. * @param shortPrefix The prefix for short argument names. */ void setArgumentPrefix(const string& longPrefix, const string& shortPrefix); /** * Begins a new group for documenting arguments. All newly added arguments via * addArgument() will be put in the new group. You can close the * current group by calling endGroup() or be opening a new group. * * Note that groups cannot be nested and all arguments which do not belong to * a group will be listed at the top of the text created by helpText(). * * @param description The description of the group */ void beginGroup(const string& description); /** * Ends the current group. * * @see beginGroup(const string&) */ void endGroup(); /** * Enables QSettings support in ctkCommandLineParser. If an argument name is found * in the QSettings instance with a valid us::Any, the value is considered as * a default value and overwrites default values registered with * addArgument(). User supplied values on the command line overwrite * values in the QSettings instance, except for arguments with multiple parameters * which are merged with QSettings values. Call mergeSettings(false) * to disable merging. * * See ctkCommandLineParser(QSettings*) for information about how to * supply a QSettings instance. * * Additionally, a long and short argument name can be specified which will disable * QSettings support if supplied on the command line. The argument name must be * registered as a regular argument via addArgument(). * * @param disableLongArg Long argument name. * @param disableShortArg Short argument name. * * @see ctkCommandLineParser(QSettings*) */ void enableSettings(const string& disableLongArg = "", const string& disableShortArg = ""); /** * Controlls the merging behavior of user values and QSettings values. * * If merging is on (the default), user supplied values for an argument * which can take more than one parameter are merged with values stored * in the QSettings instance. If merging is off, the user values overwrite * the QSettings values. * * @param merge true enables QSettings merging, false * disables it. */ void mergeSettings(bool merge); /** * Can be used to check if QSettings support has been enabled by a call to * enableSettings(). * * @return true if QSettings support is enabled, false * otherwise. */ bool settingsEnabled() const; /** * Can be used to teach the parser to stop parsing the arguments and return False when * an unknown argument is encountered. By default StrictMode is disabled. * * @see parseArguments(const StringContainerType &, bool*) */ void setStrictModeEnabled(bool strictMode); - void GetXML(); + /** + * Is used to generate an XML output for any commandline program. + */ + void generateXmlOutput(); + /** + * Is used to set the title of the auto generated interface. + * + * @param title The title of the app. + */ void setTitle(std::string title); + /** + * Is used to set the contributor for the help view in the auto generated interface. + * + * @param contributor Contributor of the app. + */ void setContributor(std::string contributor); + /** + * Is used to categorize the apps in the commandline module. + * + * @param category The category of the app. + */ void setCategory(std::string category); + /** + * Is used as the help text in the auto generated interface. + * + * @param description A short description for the app. + */ void setDescription(std::string description); - void changeParameterGroup(std::string name, std::string description); + /** + * Is used to group several Parameters in one groupbox in the auto generated interface. + * Default name is "Parameters", with the tooltip: "Groupbox containing parameters." + * + * To change the group of several arguments, call this method before the arguments are added. + * + * @param name The name of the groupbox. + * @param tooltip The tooltip of the groupbox. + */ + void changeParameterGroup(std::string name, std::string tooltip); private: class ctkInternal; ctkInternal * Internal; string Title; string Contributor; string Category; string Description; string ParameterGroupName; string ParameterGroupDescription; }; #endif