diff --git a/apps/BioModelCalc/BioModelCalc.cpp b/apps/BioModelCalc/BioModelCalc.cpp index 418a260..d189a7f 100644 --- a/apps/BioModelCalc/BioModelCalc.cpp +++ b/apps/BioModelCalc/BioModelCalc.cpp @@ -1,147 +1,150 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1334 $ (last changed revision) // @date $Date: 2016-04-22 11:13:22 +0200 (Fr, 22 Apr 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "BioModelCalcApplicationData.h" #include "BioModelCalcHelper.h" #include "BioModelCmdLineParser.h" #include "boost/shared_ptr.hpp" #include "boost/make_shared.hpp" #include "RTToolboxConfigure.h" #include "rttbException.h" int main(int argc, const char** argv) { int result = 0; rttb::apps::bioModelCalc::ApplicationData appData; boost::shared_ptr argParser; + const std::string appCategory = "RT-Toolbox App"; + const std::string appName = "BioModelCalc"; + const std::string appDesc = "An App to calculate the Linear quadratic (LQ) BioModel. This app is currently under development and in an experimental state."; + const std::string appContributor = "SIDT@DKFZ"; + const std::string appVersion = RTTB_FULL_VERSION_STRING; try { - std::string appName = "BioModelCalc"; - std::string appVersion = RTTB_FULL_VERSION_STRING; argParser = boost::make_shared(argc, argv, appName, - appVersion); + appVersion, appDesc, appContributor, appCategory); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return -1; } // This is vital. The application needs to exit if the "help" or "version" parameter is set // because this means the other parameters won't be parsed. - if (argParser->isSet(argParser->OPTION_HELP) || argParser->isSet(argParser->OPTION_VERSION)) + if (argParser->isSet(argParser->OPTION_HELP) || argParser->isSet(argParser->OPTION_VERSION) || argParser->isSet(argParser->OPTION_XML)) { return 0; } rttb::apps::bioModelCalc::populateAppData(argParser, appData); std::cout << std::endl << "*******************************************" << std::endl; std::cout << "Dose file: " << appData._doseFileName << std::endl; std::cout << "Bio model output file: " << appData._outputFileName << std::endl; std::cout << "Model: " << appData._model << std::endl; std::cout << "Model parameters: "; for (size_t i = 0; i < appData._modelParameters.size(); i++) { if (i != 0) { std::cout << ", "; } std::cout << appData._modelParameters.at(i); } for (size_t i = 0; i < appData._modelParameterMapsFilename.size(); i++) { if (i != 0) { std::cout << ", "; } std::cout << appData._modelParameterMapsFilename.at(i); } std::cout << std::endl; std::cout << "Dose scaling: " << appData._doseScaling << std::endl; if (argParser->isSet(argParser->OPTION_N_FRACTIONS)){ std::cout << "#Fractions: " << appData._nFractions << std::endl; } std::cout << std::endl; try { appData._dose = rttb::apps::bioModelCalc::loadDose(appData._doseFileName, appData._doseLoadStyle); for (const auto& filename : appData._modelParameterMapsFilename){ appData._modelParameterMaps.push_front(rttb::apps::bioModelCalc::loadDose(filename, appData._parameterMapsLoadStyle)); } } catch (rttb::core::Exception& e) { std::cerr << "RTTB Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 1; } catch (const std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Error!!! unknown error while reading input image." << std::endl; return 1; } try { rttb::apps::bioModelCalc::processData(appData); } catch (rttb::core::Exception& e) { std::cerr << "RTTB Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 2; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 2; } catch (...) { std::cerr << "Error!!! unknown error while calculating the bioModel or writing the image." << std::endl; return 2; } return result; } diff --git a/apps/BioModelCalc/BioModelCmdLineParser.cpp b/apps/BioModelCalc/BioModelCmdLineParser.cpp index 30c65ef..ff83d1d 100644 --- a/apps/BioModelCalc/BioModelCmdLineParser.cpp +++ b/apps/BioModelCalc/BioModelCmdLineParser.cpp @@ -1,122 +1,140 @@ #include "BioModelCmdLineParser.h" namespace rttb { namespace apps { namespace bioModelCalc { - - BioModelCmdLineParser::BioModelCmdLineParser(int argc, const char** argv, const std::string& name, - const std::string& version, bool virtuosSupport) : - CmdLineParserBase(name, version), _virtuosSupport(virtuosSupport) + BioModelCmdLineParser::BioModelCmdLineParser(int argc, const char** argv, const std::string& name, const std::string& version, + const std::string& description, const std::string& contributor, const std::string& category, bool virtuosSupport) : + CmdLineParserBase(name, version, description, contributor, category), _virtuosSupport(virtuosSupport) { + //REQUIRED addOption(OPTION_DOSE_FILE, OPTION_GROUP_REQUIRED, - "The name of the dose file. Can be omitted if used as " - "positional argument (see above).", 'd', true); + "The name of the dose file. Can be omitted if used as " + "positional argument (see above).", 'd', true); + addInformationForXML(OPTION_DOSE_FILE, cmdlineparsing::XMLGenerator::paramType::INPUT, { "mhd", "*" }); + addOption(OPTION_OUTPUT_FILE, OPTION_GROUP_REQUIRED, - "The name of the output file. Can be omitted if used as " - "positional argument (see above).", 'o', true); + "The name of the output file. Can be omitted if used as " + "positional argument (see above).", 'o', true); + addInformationForXML(OPTION_OUTPUT_FILE, cmdlineparsing::XMLGenerator::paramType::OUTPUT, { "mhd", "*" }); + addPositionalOption(OPTION_DOSE_FILE, 1); addPositionalOption(OPTION_OUTPUT_FILE, 1); + addOptionWithDefaultValue(OPTION_MODEL, OPTION_GROUP_REQUIRED, - "The used radiobiological model the dose should be analyzed with. Available models are:\n \"LQ\", Formula: exp(-(alpha * D + beta * D^2/n))", - "LQ", "LQ", 'm'); - addOption >(OPTION_MODEL_PARAMETERS, OPTION_GROUP_OPTIONAL, - "The parameters for the radiobiological model.", 'p', false, true); - addOption >(OPTION_MODEL_PARAMETER_MAPS, OPTION_GROUP_OPTIONAL, - "The parameters maps as itk readable image files for the radiobiological model.", 'a', false, true); + "The used radiobiological model the dose should be analyzed with. Available models are:\n \"LQ\", Formula: exp(-(alpha * D + beta * D^2/n))", + "LQ", "LQ", 'm'); + addInformationForXML(OPTION_MODEL, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "LQ" }); + addOptionWithDefaultValue(OPTION_DOSE_SCALING, OPTION_GROUP_REQUIRED, - "Dose scaling that should be applied.", 1.0, "1.0", 'e'); - addOption(OPTION_N_FRACTIONS, OPTION_GROUP_OPTIONAL, - "The number of fractions (n in the formula).", 'f'); + "Dose scaling that should be applied.", 1.0, "1.0", 'e'); + addInformationForXML(OPTION_DOSE_SCALING, cmdlineparsing::XMLGenerator::paramType::DOUBLE); + std::vector defaultLoadingStyle; defaultLoadingStyle.push_back("itk"); std::string doseLoadStyleDescription = "The loading style for the dose. Available styles are:\n" - "\"dicom\": normal dicom dose\n" - "\"itk\": use itk image loading\n" - "\"helax\": load a helax dose (choosing this style, the dose path should only be a directory)."; + "\"dicom\": normal dicom dose\n" + "\"itk\": use itk image loading\n" + "\"helax\": load a helax dose (choosing this style, the dose path should only be a directory)."; if (_virtuosSupport) { doseLoadStyleDescription += "\n" - "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" - + OPTION_LOAD_STYLE + " virtuos myFavorite.pln\")"; + "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" + + OPTION_LOAD_STYLE + " virtuos myFavorite.pln\")"; } - addOptionWithDefaultValue >(OPTION_LOAD_STYLE, OPTION_GROUP_REQUIRED, doseLoadStyleDescription, - defaultLoadingStyle, defaultLoadingStyle.at(0), - 't', true, true); - addOptionWithDefaultValue >(OPTION_LOAD_STYLE_PARAMETER_MAPS, OPTION_GROUP_OPTIONAL, doseLoadStyleDescription, - defaultLoadingStyle, defaultLoadingStyle.at(0), - 'u', true, true); + defaultLoadingStyle, defaultLoadingStyle.at(0), + 't', true, true); + addInformationForXML(OPTION_LOAD_STYLE, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "itk", "dicom", "helax" }); + + //OPTIONAL + addOption >(OPTION_MODEL_PARAMETERS, OPTION_GROUP_OPTIONAL, + "The parameters for the radiobiological model.", 'p', false, true); + addInformationForXML(OPTION_MODEL_PARAMETERS, cmdlineparsing::XMLGenerator::paramType::STRING); + + addOption >(OPTION_MODEL_PARAMETER_MAPS, OPTION_GROUP_OPTIONAL, + "The parameters maps as itk readable image files for the radiobiological model.", 'a', false, true); + addInformationForXML(OPTION_MODEL_PARAMETER_MAPS, cmdlineparsing::XMLGenerator::paramType::INPUT, { "*" }); + + addOption(OPTION_N_FRACTIONS, OPTION_GROUP_OPTIONAL, + "The number of fractions (n in the formula).", 'f'); + addInformationForXML(OPTION_N_FRACTIONS, cmdlineparsing::XMLGenerator::paramType::INTEGER); + + addOptionWithDefaultValue >(OPTION_LOAD_STYLE_PARAMETER_MAPS, OPTION_GROUP_OPTIONAL, doseLoadStyleDescription, + defaultLoadingStyle, defaultLoadingStyle.at(0), + 'u', true, true); + addInformationForXML(OPTION_LOAD_STYLE_PARAMETER_MAPS, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "itk", "dicom", "helax" }); parse(argc, argv); } void BioModelCmdLineParser::validateInput() const { std::string model = get(OPTION_MODEL); if (model != "LQ") { throw cmdlineparsing::InvalidConstraintException("Unknown model: " + model + ".\nPlease refer to the help for valid models."); } else { if (!isSet(OPTION_MODEL_PARAMETERS) && !isSet(OPTION_MODEL_PARAMETER_MAPS)){ throw cmdlineparsing::InvalidConstraintException("Either the model parameters or model parameter maps must be specified!"); } if ((isSet(OPTION_MODEL_PARAMETERS) && get >(OPTION_MODEL_PARAMETERS).size() != 2) || (isSet(OPTION_MODEL_PARAMETER_MAPS) && get >(OPTION_MODEL_PARAMETER_MAPS).size() != 2)) { throw cmdlineparsing::InvalidConstraintException("The LQ Model requires two parameters or parameter maps!"); } } std::vector loadStyle = get >(OPTION_LOAD_STYLE); std::string loadStyleAbbreviation = loadStyle.at(0); if (loadStyleAbbreviation != "dicom" && (!_virtuosSupport || loadStyleAbbreviation != "virtuos") && loadStyleAbbreviation != "itk" && loadStyleAbbreviation != "helax") { throw cmdlineparsing::InvalidConstraintException("Unknown load style: " + loadStyleAbbreviation + ".\nPlease refer to the help for valid loading style settings."); } else if (_virtuosSupport && loadStyleAbbreviation == "virtuos") { if (loadStyle.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io style argument."); } } double doseScaling = get(OPTION_DOSE_SCALING); if (doseScaling <= 0) { throw cmdlineparsing::InvalidConstraintException("Negative dose scaling is not allowed. Dose scaling has to be >0."); } } void BioModelCmdLineParser::printHelp() const { cmdlineparsing::CmdLineParserBase::printHelp(); std::cout << "Example:" << std::endl << std::endl; std::cout << m_programName << " dose.mhd result.mhd -m LQ -p 0.2 0.02" << std::endl << std::endl; std::cout << "This will calculate the Linear quadratic (LQ) BioModel from \"dose.mhd\" and will write the result to \"result.mhd\". " "The alpha and beta parameters for the LQ model are 0.2 and 0.02, respectively." << std::endl; } } } } diff --git a/apps/BioModelCalc/BioModelCmdLineParser.h b/apps/BioModelCalc/BioModelCmdLineParser.h index 94bd76f..5121642 100644 --- a/apps/BioModelCalc/BioModelCmdLineParser.h +++ b/apps/BioModelCalc/BioModelCmdLineParser.h @@ -1,45 +1,47 @@ #ifndef __BIO_MODEL_CMD_LINE_PARSER #define __BIO_MODEL_CMD_LINE_PARSER #include "CmdLineParserBase.h" namespace rttb { namespace apps { namespace bioModelCalc { /*! @class BioModelCmdLineParser @brief Argument parsing is parametrized here based on ArgParserLib @see cmdlineparsing::CmdLineParserBase */ class BioModelCmdLineParser : public cmdlineparsing::CmdLineParserBase { public: BioModelCmdLineParser(int argc, const char** argv, const std::string& name, - const std::string& version, bool virtuosSupport = false); + const std::string& version, bool virtuosSupport = false); + BioModelCmdLineParser(int argc, const char** argv, const std::string& name, const std::string& version, + const std::string& description, const std::string& contributor, const std::string& category, bool virtuosSupport = false); void validateInput() const; void printHelp() const; // Option groups const std::string OPTION_GROUP_REQUIRED = "Required Arguments"; const std::string OPTION_GROUP_OPTIONAL = "Optional Arguments"; // Parameters const std::string OPTION_DOSE_FILE = "dose"; const std::string OPTION_OUTPUT_FILE = "outputFile"; const std::string OPTION_MODEL = "model"; const std::string OPTION_MODEL_PARAMETERS = "modelParameters"; const std::string OPTION_MODEL_PARAMETER_MAPS = "modelParameterMaps"; const std::string OPTION_LOAD_STYLE = "loadStyle"; const std::string OPTION_LOAD_STYLE_PARAMETER_MAPS = "loadStyleParameterMaps"; const std::string OPTION_DOSE_SCALING = "doseScaling"; const std::string OPTION_N_FRACTIONS = "nFractions"; bool _virtuosSupport; }; } } } #endif \ No newline at end of file diff --git a/apps/DoseAcc/DoseAcc.cpp b/apps/DoseAcc/DoseAcc.cpp index 6e4b120..019d091 100644 --- a/apps/DoseAcc/DoseAcc.cpp +++ b/apps/DoseAcc/DoseAcc.cpp @@ -1,170 +1,174 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1107 $ (last changed revision) // @date $Date: 2015-09-17 12:47:41 +0200 (Do, 17 Sep 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseAccApplicationData.h" #include "DoseAccHelper.h" #include "DoseAccCmdLineParser.h" #include "boost/shared_ptr.hpp" #include "boost/make_shared.hpp" #include "RTToolboxConfigure.h" int main(int argc, const char** argv) { int result = 0; rttb::apps::doseAcc::ApplicationData appData; boost::shared_ptr argParser; + + const std::string appCategory = "RT-Toolbox App"; + const std::string appName = "DoseAcc"; + const std::string appDesc = "An App to accumulate two doses. This app is currently under development and in an experimental state."; + const std::string appContributor = "SIDT@DKFZ"; + const std::string appVersion = RTTB_FULL_VERSION_STRING; try { - std::string appName = "DoseAcc"; - std::string appVersion = RTTB_FULL_VERSION_STRING; argParser = boost::make_shared(argc, argv, appName, - appVersion, false); + appVersion, appDesc, appContributor, appCategory, false); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return 5; } // This is vital. The application needs to exit if the "help" or "version" parameter is set // because this means the other parameters won't be parsed. - if (argParser->isSet(argParser->OPTION_HELP) || argParser->isSet(argParser->OPTION_VERSION)) + if (argParser->isSet(argParser->OPTION_HELP) || argParser->isSet(argParser->OPTION_VERSION) || argParser->isSet(argParser->OPTION_XML)) { return 0; } rttb::apps::doseAcc::populateAppData(argParser, appData); std::cout << std::endl << "*******************************************" << std::endl; std::cout << "Dose 1 file: " << appData._dose1FileName << std::endl; std::cout << "Dose 2 file: " << appData._dose2FileName << std::endl; std::cout << "Dose output file: " << appData._outputFileName << std::endl; if (!(appData._regFileName.empty())) { std::cout << "Registration file: " << appData._regFileName << std::endl; } std::cout << "Dose 1 weight: " << appData._weightDose1 << std::endl; std::cout << "Dose 2 weight: " << appData._weightDose2 << std::endl; std::cout << "Operator: " << appData._operator << std::endl; try { appData._dose1 = rttb::apps::doseAcc::loadDose(appData._dose1FileName, appData._dose1LoadStyle); } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; return 4; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 4; } catch (...) { std::cerr << "Error!!! unknown error while reading input image." << std::endl; return 4; } try { appData._dose2 = rttb::apps::doseAcc::loadDose(appData._dose2FileName, appData._dose2LoadStyle); } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; return 4; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 4; } catch (...) { std::cerr << "Error!!! unknown error while reading input image." << std::endl; return 4; } if (!(appData._regFileName.empty())) { try { appData._spReg = rttb::apps::doseAcc::loadRegistration(appData._regFileName); } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; return 5; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 5; } catch (...) { std::cerr << "Error!!! unknown error while reading registration file." << std::endl; return 5; } } try { rttb::apps::doseAcc::processData(appData); } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; return 9; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 9; } catch (...) { std::cerr << "Error!!! unknown error while mapping and writing image." << std::endl; return 9; } std::cout << std::endl; return result; } diff --git a/apps/DoseAcc/DoseAccCmdLineParser.cpp b/apps/DoseAcc/DoseAccCmdLineParser.cpp index 8603721..7763543 100644 --- a/apps/DoseAcc/DoseAccCmdLineParser.cpp +++ b/apps/DoseAcc/DoseAccCmdLineParser.cpp @@ -1,175 +1,191 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1374 $ (last changed revision) // @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseAccCmdLineParser.h" namespace rttb { namespace apps { namespace doseAcc { - - DoseAccCmdLineParser::DoseAccCmdLineParser(int argc, const char** argv, const std::string& name, - const std::string& version, bool virtuosSupport) : - CmdLineParserBase(name, version), _virtuosSupport(virtuosSupport) + DoseAccCmdLineParser::DoseAccCmdLineParser(int argc, const char** argv, const std::string& name, const std::string& version, + const std::string& description, const std::string& contributor, const std::string& category, bool virtuosSupport) : + CmdLineParserBase(name, version, description, contributor, category), _virtuosSupport(virtuosSupport) { - addOption(OPTION_DOSE1_FILENAME, OPTION_GROUP_REQUIRED, - "File path to the first dose.", 'd', true); - addOption(OPTION_DOSE2_FILENAME, OPTION_GROUP_REQUIRED, - "File path to the second dose.", 'e', true); - addOption(OPTION_OUTPUT_FILENAME, OPTION_GROUP_REQUIRED, - "File path where the output should be stored.", 'o', true); - addOptionWithDefaultValue(OPTION_INTERPOLATOR, OPTION_GROUP_REQUIRED, - "Specifies the interpolator that should be used for mapping. Available options are: " - "\"nn\": nearest neighbour, \"linear\": linear interpolation, \"rosu\" interpolation based on the concept of Rosu et al..", - "linear", "linear", 'i', true); - addOptionWithDefaultValue(OPTION_WEIGHT1, OPTION_GROUP_REQUIRED, - "Specifies the weight for dose 1.", - 1.0, "1.0", 'w', true); - addOptionWithDefaultValue(OPTION_WEIGHT2, OPTION_GROUP_REQUIRED, - "Specifies the weight for dose 2.", - 1.0, "1.0", 'z', true); - addOptionWithDefaultValue(OPTION_REGISTRATION_FILENAME, OPTION_GROUP_REQUIRED, - "Specifies name and location of the registration file that should be used to map dose 2 before accumulating it with dose 1." - "The registration should be stored as MatchPoint registration.", - "", "no mapping", 'r', true); - - std::vector defaultLoadingStyle; - defaultLoadingStyle.push_back("dicom"); - std::string doseLoadStyleDescription = "Options are:\n \"dicom\": normal dicom dose\n" - "\"itk\": use itk image loading\n\"helax\": load a helax dose (choosing this style, the dose path should only be a directory)."; - - - if (_virtuosSupport) - { - doseLoadStyleDescription += "\n" - "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" - + OPTION_LOAD_STYLE_DOSE1 + " or " + OPTION_LOAD_STYLE_DOSE2 + " virtuos myFavorite.pln\")"; - } + //REQUIRED + addOption(OPTION_DOSE1_FILENAME, OPTION_GROUP_REQUIRED, + "File path to the first dose.", 'd', true); + addInformationForXML(OPTION_DOSE1_FILENAME, cmdlineparsing::XMLGenerator::paramType::INPUT, { "mhd", "*" }); - addOptionWithDefaultValue >(OPTION_LOAD_STYLE_DOSE1, OPTION_GROUP_REQUIRED, - "Load style for dose 1. "+ doseLoadStyleDescription, - defaultLoadingStyle, defaultLoadingStyle.at(0), - 't', true, true); + addOption(OPTION_DOSE2_FILENAME, OPTION_GROUP_REQUIRED, + "File path to the second dose.", 'e', true); + addInformationForXML(OPTION_DOSE2_FILENAME, cmdlineparsing::XMLGenerator::paramType::INPUT, { "mhd", "*" }); - addOptionWithDefaultValue >(OPTION_LOAD_STYLE_DOSE2, OPTION_GROUP_REQUIRED, - "Load style for dose 2. See " + OPTION_LOAD_STYLE_DOSE1, - defaultLoadingStyle, defaultLoadingStyle.at(0), - 'u', true, true); + addOption(OPTION_OUTPUT_FILENAME, OPTION_GROUP_REQUIRED, + "File path where the output should be stored.", 'o', true); + addInformationForXML(OPTION_OUTPUT_FILENAME, cmdlineparsing::XMLGenerator::paramType::OUTPUT, { "mhd", "*" }); - addOptionWithDefaultValue(OPTION_OPERATOR, OPTION_GROUP_REQUIRED, - "Specifies the operator used. Available operators are '+' and '*'. Operator '*' has implemented no weight option.", - "+", "+", 'p', true); + addOptionWithDefaultValue(OPTION_INTERPOLATOR, OPTION_GROUP_REQUIRED, + "Specifies the interpolator that should be used for mapping. Available options are: " + "\"nn\": nearest neighbour, \"linear\": linear interpolation, \"rosu\" interpolation based on the concept of Rosu et al..", + "linear", "linear", 'i', true); + addInformationForXML(OPTION_INTERPOLATOR, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "linear", "nn", "rosu" }); + + addOptionWithDefaultValue(OPTION_WEIGHT1, OPTION_GROUP_REQUIRED, + "Specifies the weight for dose 1.", + 1.0, "1.0", 'w', true); + addInformationForXML(OPTION_WEIGHT1, cmdlineparsing::XMLGenerator::paramType::DOUBLE); + + addOptionWithDefaultValue(OPTION_WEIGHT2, OPTION_GROUP_REQUIRED, + "Specifies the weight for dose 2.", + 1.0, "1.0", 'z', true); + addInformationForXML(OPTION_WEIGHT2, cmdlineparsing::XMLGenerator::paramType::DOUBLE); + + addOptionWithDefaultValue(OPTION_REGISTRATION_FILENAME, OPTION_GROUP_REQUIRED, + "Specifies name and location of the registration file that should be used to map dose 2 before accumulating it with dose 1." + "The registration should be stored as MatchPoint registration.", + "", "no mapping", 'r', true); + addInformationForXML(OPTION_REGISTRATION_FILENAME, cmdlineparsing::XMLGenerator::paramType::INPUT, { "mapr", "*" }); + + std::vector defaultLoadingStyle; + defaultLoadingStyle.push_back("dicom"); + std::string doseLoadStyleDescription = "Options are:\n \"dicom\": normal dicom dose\n" + "\"itk\": use itk image loading\n\"helax\": load a helax dose (choosing this style, the dose path should only be a directory)."; + + + if (_virtuosSupport) + { + doseLoadStyleDescription += "\n" + "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" + + OPTION_LOAD_STYLE_DOSE1 + " or " + OPTION_LOAD_STYLE_DOSE2 + " virtuos myFavorite.pln\")"; + } - addPositionalOption(OPTION_DOSE1_FILENAME, 1); - addPositionalOption(OPTION_DOSE2_FILENAME, 1); - addPositionalOption(OPTION_OUTPUT_FILENAME, 1); + addOptionWithDefaultValue >(OPTION_LOAD_STYLE_DOSE1, OPTION_GROUP_REQUIRED, + "Load style for dose 1. " + doseLoadStyleDescription, + defaultLoadingStyle, defaultLoadingStyle.at(0), + 't', true, true); + addInformationForXML(OPTION_LOAD_STYLE_DOSE1, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "dicom","itk","helax" }); + + addOptionWithDefaultValue >(OPTION_LOAD_STYLE_DOSE2, OPTION_GROUP_REQUIRED, + "Load style for dose 2. See " + OPTION_LOAD_STYLE_DOSE1, + defaultLoadingStyle, defaultLoadingStyle.at(0), + 'u', true, true); + addInformationForXML(OPTION_LOAD_STYLE_DOSE2, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "dicom","itk","helax" }); + + addOptionWithDefaultValue(OPTION_OPERATOR, OPTION_GROUP_REQUIRED, + "Specifies the operator used. Available operators are '+' and '*'. Operator '*' has implemented no weight option.", + "+", "+", 'p', true); + addInformationForXML(OPTION_OPERATOR, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "+","*"}); + + addPositionalOption(OPTION_DOSE1_FILENAME, 1); + addPositionalOption(OPTION_DOSE2_FILENAME, 1); + addPositionalOption(OPTION_OUTPUT_FILENAME, 1); parse(argc, argv); } void DoseAccCmdLineParser::validateInput() const { std::vector doseLoadStyle1 = get >(OPTION_LOAD_STYLE_DOSE1); std::string doseLoadStyleAbbreviation1 = doseLoadStyle1.at(0); if (doseLoadStyleAbbreviation1 != "dicom" && (!_virtuosSupport || doseLoadStyleAbbreviation1 != "virtuos") && doseLoadStyleAbbreviation1 != "itk" && doseLoadStyleAbbreviation1 != "helax") { throw cmdlineparsing::InvalidConstraintException("Unknown load style for dose1 file: " + doseLoadStyleAbbreviation1 + ".\nPlease refer to the help for valid loading style settings."); } if (_virtuosSupport && doseLoadStyleAbbreviation1 == "virtuos") { if (doseLoadStyle1.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io style argument."); } } std::vector doseLoadStyle2 = get >(OPTION_LOAD_STYLE_DOSE2); std::string doseLoadStyleAbbreviation2 = doseLoadStyle2.at(0); if (doseLoadStyleAbbreviation2 != "dicom" && (!_virtuosSupport || doseLoadStyleAbbreviation2 != "virtuos") && doseLoadStyleAbbreviation2 != "itk" && doseLoadStyleAbbreviation2 != "helax") { throw cmdlineparsing::InvalidConstraintException("Unknown load style for dose2 file: " + doseLoadStyleAbbreviation2 + ".\nPlease refer to the help for valid loading style settings."); } if (_virtuosSupport && doseLoadStyleAbbreviation2 == "virtuos") { if (doseLoadStyle2.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io style argument."); } } std::string interpolator = get(OPTION_INTERPOLATOR); if (interpolator != "nn" && interpolator != "linear" && interpolator != "rosu") { throw cmdlineparsing::InvalidConstraintException("Unknown interpolator: " + interpolator + ".\nPlease refer to the help for valid interpolator settings."); } std::string operatorString = get(OPTION_OPERATOR); if (operatorString != "+" && operatorString != "*") { throw cmdlineparsing::InvalidConstraintException("Unknown operator: " + operatorString + ".\nPlease refer to the help for valid operator settings."); } if (operatorString == "*"){ double weight1 = get(OPTION_WEIGHT1); double weight2 = get(OPTION_WEIGHT2); if (weight1 != 1.0 || weight2 != 1.0){ throw cmdlineparsing::InvalidConstraintException("Operator \"*\" has no weight option implemented. Options --" + OPTION_WEIGHT1 + " and --" + OPTION_WEIGHT2 + " are invalid."); } } } void DoseAccCmdLineParser::printHelp() const { cmdlineparsing::CmdLineParserBase::printHelp(); std::cout << " Example:" << std::endl << std::endl; std::cout << " DoseAcc dose1.mhd dose2.mhd result.mhd --" + OPTION_LOAD_STYLE_DOSE1 + " itk --" + OPTION_LOAD_STYLE_DOSE2 + " itk --" + OPTION_WEIGHT1 + " 2 -r reg.mapr" << std::endl << std::endl; std::cout << " This will accumulate \"dose1.mhd\" and \"dose2.mhd\" by using \"reg.mapr\" to map dose 2."; std::cout << " For the accumulation, dose 1 will be multiplied by 2. The resulting dose will be stored in \"result.mhd\"." << std::endl << std::endl; if (_virtuosSupport){ std::cout << " DoseAcc dose1.dcm dose2.dos.gz result.mhd --" + OPTION_LOAD_STYLE_DOSE2 + " virtuos dose2.pln -r reg.mapr" << std::endl << std::endl; std::cout << " This will accumulate \"dose1.dcm\" (using default dicom io) and \"dose2.dos.gz\" (using virtuos io and plan file dose2.pln)"; std::cout << " by using \"reg.mapr\" to map dose 2. The resulting dose will be stored in \"result.mhd\"." << std::endl; } } } } } diff --git a/apps/DoseAcc/DoseAccCmdLineParser.h b/apps/DoseAcc/DoseAccCmdLineParser.h index bcf3e13..7e0a8f3 100644 --- a/apps/DoseAcc/DoseAccCmdLineParser.h +++ b/apps/DoseAcc/DoseAccCmdLineParser.h @@ -1,67 +1,69 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1374 $ (last changed revision) // @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __DOSEACC_CMD_LINE_PARSER #define __DOSEACC_CMD_LINE_PARSER #include "CmdLineParserBase.h" namespace rttb { namespace apps { namespace doseAcc { /*! @class DoseAccCmdLineParser @brief Argument parsing is parametrized here based on ArgParserLib @see cmdlineparsing::CmdLineParserBase */ class DoseAccCmdLineParser : public cmdlineparsing::CmdLineParserBase { public: DoseAccCmdLineParser(int argc, const char** argv, const std::string& name, const std::string& version, bool virtuosSupport = false); + DoseAccCmdLineParser(int argc, const char** argv, const std::string& name, const std::string& version, + const std::string& description, const std::string& contributor, const std::string& category, bool virtuosSupport = false); void validateInput() const override; void printHelp() const override; // Option groups const std::string OPTION_GROUP_REQUIRED = "Required Arguments"; const std::string OPTION_GROUP_OPTIONAL = "Optional Arguments"; // Parameters const std::string OPTION_DOSE1_FILENAME = "dose1"; const std::string OPTION_DOSE2_FILENAME = "dose2"; const std::string OPTION_OUTPUT_FILENAME = "output"; const std::string OPTION_INTERPOLATOR = "interpolator"; const std::string OPTION_WEIGHT1 = "weight1"; const std::string OPTION_WEIGHT2 = "weight2"; const std::string OPTION_REGISTRATION_FILENAME = "registration"; const std::string OPTION_LOAD_STYLE_DOSE1 = "loadStyle1"; const std::string OPTION_LOAD_STYLE_DOSE2 = "loadStyle2"; const std::string OPTION_OPERATOR = "operator"; bool _virtuosSupport; }; } } } #endif \ No newline at end of file diff --git a/apps/DoseTool/DoseTool.cpp b/apps/DoseTool/DoseTool.cpp index 5b79414..c4e1b37 100644 --- a/apps/DoseTool/DoseTool.cpp +++ b/apps/DoseTool/DoseTool.cpp @@ -1,161 +1,164 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1315 $ (last changed revision) // @date $Date: 2016-04-12 14:18:24 +0200 (Di, 12 Apr 2016) $ (last change date) // @author $Author: floca $ (last changed by) */ #include "DoseToolApplicationData.h" #include "DoseToolHelper.h" #include "DoseToolCmdLineParser.h" #include "boost/shared_ptr.hpp" #include "boost/make_shared.hpp" #include "RTToolboxConfigure.h" #include "rttbException.h" /*! \file DoseTool.cpp main function for DoseTool */ int main(int argc, const char** argv) { int result = 0; rttb::apps::doseTool::ApplicationData appData; boost::shared_ptr argParser; + const std::string appCategory = "RT-Toolbox App"; + const std::string appName = "DoseTool"; + const std::string appDesc = "An App to calculate the dose statistics and compute the DVH. This app is currently under development and in an experimental state."; + const std::string appContributor = "SIDT@DKFZ"; + const std::string appVersion = RTTB_FULL_VERSION_STRING; + try { - std::string appName = "DoseTool"; - std::string appVersion = RTTB_FULL_VERSION_STRING; - argParser = boost::make_shared(argc, argv, appName, - appVersion); + appVersion, appDesc, appContributor, appCategory); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return 5; } // This is vital. The application needs to exit if the "help" or "version" parameter is set // because this means the other parameters won't be parsed. - if (argParser->isSet(argParser->OPTION_HELP) || argParser->isSet(argParser->OPTION_VERSION)) + if (argParser->isSet(argParser->OPTION_HELP) || argParser->isSet(argParser->OPTION_VERSION) || argParser->isSet(argParser->OPTION_XML)) { return 0; } rttb::apps::doseTool::populateAppData(argParser, appData); std::cout << std::endl << "*******************************************" << std::endl; std::cout << "Dose file: " << appData._doseFileName << std::endl; std::cout << "Struct file: " << appData._structFileName << std::endl; std::cout << "Struct name: " << appData._structNameRegex << std::endl; if (appData._computeDoseStatistics) { std::cout << "Dose statistic output file: " << appData._doseStatisticOutputFileName << std::endl; std::cout << "Compute complex statistics: " << appData._computeComplexDoseStatistics << std::endl; if (appData._computeComplexDoseStatistics) { std::cout << "Prescribed dose: " << appData._prescribedDose << std::endl; } std::cout << "Allow self intersections: " << appData._allowSelfIntersection << std::endl; } if (appData._computeDVH) { std::cout << "DVH output file: " << appData._dvhOutputFilename << std::endl; } try { appData._dose = rttb::apps::doseTool::loadDose(appData._doseFileName, appData._doseLoadStyle); } catch (rttb::core::Exception& e) { std::cerr << "RTTB Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 1; } catch (const std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "Error!!! unknown error while reading dose image." << std::endl; return 1; } //loading of structure file not necessary in ITK case as it can be used directly as mask input. if (appData._structLoadStyle.front() != "itk") { try { appData._struct = rttb::apps::doseTool::loadStruct(appData._structFileName, appData._structLoadStyle, appData._structNameRegex); } catch (rttb::core::Exception& e) { std::cerr << "RTTB Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 2; } catch (const std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 2; } catch (...) { std::cerr << "Error!!! unknown error while reading struct image." << std::endl; return 2; } } try { rttb::apps::doseTool::processData(appData); } catch (rttb::core::Exception& e) { std::cerr << "RTTB Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 3; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 3; } catch (...) { std::cerr << "Error!!! unknown error while processing the data or writing the image." << std::endl; return 3; } return result; } diff --git a/apps/DoseTool/DoseToolCmdLineParser.cpp b/apps/DoseTool/DoseToolCmdLineParser.cpp index 9c59f90..a5f04d3 100644 --- a/apps/DoseTool/DoseToolCmdLineParser.cpp +++ b/apps/DoseTool/DoseToolCmdLineParser.cpp @@ -1,197 +1,216 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1374 $ (last changed revision) // @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseToolCmdLineParser.h" namespace rttb { namespace apps { namespace doseTool { - DoseToolCmdLineParser::DoseToolCmdLineParser(int argc, const char** argv, const std::string& name, - const std::string& version, bool virtuosSupport) : - CmdLineParserBase(name, version), _virtuosSupport(virtuosSupport) + DoseToolCmdLineParser::DoseToolCmdLineParser(int argc, const char** argv, const std::string& name, const std::string& version, + const std::string& description, const std::string& contributor, const std::string& category, bool virtuosSupport) : + CmdLineParserBase(name, version, description, contributor, category), _virtuosSupport(virtuosSupport) { + //REQUIRED typedef double DoseTypeGy; addOption(OPTION_DOSE_FILE, OPTION_GROUP_REQUIRED, - "The name of the dose file. Can be omitted if used as " - "positional argument (see above).", 'd', true); + "The name of the dose file. Can be omitted if used as " + "positional argument (see above).", 'd', true); + addInformationForXML(OPTION_DOSE_FILE, cmdlineparsing::XMLGenerator::paramType::INPUT, {"dcm", "*" }); + addOption(OPTION_STRUCT_FILE, OPTION_GROUP_REQUIRED, - "The name of the struct file. Can be omitted if used as " - "positional argument (see above).", 's', true); + "The name of the struct file. Can be omitted if used as " + "positional argument (see above).", 's', true); + addInformationForXML(OPTION_STRUCT_FILE, cmdlineparsing::XMLGenerator::paramType::INPUT, {"dcm", "*" }); + addOptionWithDefaultValue(OPTION_STRUCT_NAME, OPTION_GROUP_REQUIRED, - "The name of the struct as regular expression. Can be omitted if used as " - "positional argument or with itk struct loadingStyle (see above).", "", "", 'n', true); + "The name of the struct as regular expression. Can be omitted if used as " + "positional argument or with itk struct loadingStyle (see above).", "", "", 'n', true); + addInformationForXML(OPTION_STRUCT_NAME, cmdlineparsing::XMLGenerator::paramType::STRING); + addPositionalOption(OPTION_DOSE_FILE, 1); addPositionalOption(OPTION_STRUCT_FILE, 1); addPositionalOption(OPTION_STRUCT_NAME, 1); addPositionalOption(OPTION_DOSE_STATISTICS, 1); std::vector defaultLoadingStyle; defaultLoadingStyle.push_back("dicom"); std::string doseLoadStyleDescription = "\"dicom\": normal dicom dose\n" - "\"itk\": use itk image loading\n\"helax\": load a helax dose (choosing this style, the dose path should only be a directory)."; + "\"itk\": use itk image loading\n\"helax\": load a helax dose (choosing this style, the dose path should only be a directory)."; if (_virtuosSupport) { doseLoadStyleDescription += "\n" - "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" - + OPTION_DOSE_LOAD_STYLE + " virtuos myFavorite.pln\")"; + "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" + + OPTION_DOSE_LOAD_STYLE + " virtuos myFavorite.pln\")"; } addOptionWithDefaultValue >(OPTION_DOSE_LOAD_STYLE, OPTION_GROUP_REQUIRED, - doseLoadStyleDescription, - defaultLoadingStyle, defaultLoadingStyle.at(0), - 't', true, true); + doseLoadStyleDescription, + defaultLoadingStyle, defaultLoadingStyle.at(0), + 't', true, true); + addInformationForXML(OPTION_DOSE_LOAD_STYLE, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "dicom", "itk", "helax" }); std::string structLoadStyleDescription = "\"dicom\": normal dicom dose\n" - "\"itk\": use itk image loading\""; + "\"itk\": use itk image loading\""; if (_virtuosSupport) { structLoadStyleDescription += "\n" - "\"virtuos\": load of a virtuos struct file (This style is a multi argument. The second argument specifies the ctx file, e.g. : \"--" - + OPTION_STRUCT_LOAD_STYLE + " virtuos myImage.ctx\")"; + "\"virtuos\": load of a virtuos struct file (This style is a multi argument. The second argument specifies the ctx file, e.g. : \"--" + + OPTION_STRUCT_LOAD_STYLE + " virtuos myImage.ctx\")"; } addOptionWithDefaultValue >(OPTION_STRUCT_LOAD_STYLE, - OPTION_GROUP_REQUIRED, structLoadStyleDescription, - defaultLoadingStyle, defaultLoadingStyle.at(0), - 'u', true, true); + OPTION_GROUP_REQUIRED, structLoadStyleDescription, + defaultLoadingStyle, defaultLoadingStyle.at(0), + 'u', true, true); + addInformationForXML(OPTION_STRUCT_LOAD_STYLE, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "dicom", "itk"}); + //OPTIONAL addOption(OPTION_DOSE_STATISTICS, OPTION_GROUP_OPTIONAL, - "If dose statistics should be computed. The argument is the output file. Can be omitted if used as " - "positional argument (see above).", 'y'); + "If dose statistics should be computed. The argument is the output file. Can be omitted if used as " + "positional argument (see above).", 'y'); + addInformationForXML(OPTION_DOSE_STATISTICS, cmdlineparsing::XMLGenerator::paramType::OUTPUT, {"xml", "*" }); addOption(OPTION_DVH, OPTION_GROUP_OPTIONAL, - "If the DVH should be computed. The argument is the output file", 'z'); + "If the DVH should be computed. The argument is the output file", 'z'); + addInformationForXML(OPTION_DVH, cmdlineparsing::XMLGenerator::paramType::OUTPUT, { "xml", "*" }); addOption(OPTION_COMPLEX_STATISTICS, OPTION_GROUP_OPTIONAL, - "If the complex dose statistics (Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx) should be computed.", 'f'); + "If the complex dose statistics (Dx, Vx, MOHx, MOCx, MaxOHx, MinOCx) should be computed.", 'f'); + addInformationForXML(OPTION_COMPLEX_STATISTICS, cmdlineparsing::XMLGenerator::paramType::BOOLEAN); + addOption(OPTION_PRESCRIBED_DOSE, OPTION_GROUP_OPTIONAL, - "The prescribed dose in Gy.", 'p'); + "The prescribed dose in Gy.", 'p'); + addInformationForXML(OPTION_PRESCRIBED_DOSE, cmdlineparsing::XMLGenerator::paramType::DOUBLE); + addOption(OPTION_ALLOW_SELF_INTERSECTION_STRUCT, OPTION_GROUP_OPTIONAL, - "If a struct file contains self intersecting contours: Allow the processing of these structures and ignore potential problems." - "WARNING: only use this parameter if you know what you are doing.", 'a'); + "If a struct file contains self intersecting contours: Allow the processing of these structures and ignore potential problems." + "WARNING: only use this parameter if you know what you are doing.", 'a'); + addInformationForXML(OPTION_ALLOW_SELF_INTERSECTION_STRUCT, cmdlineparsing::XMLGenerator::paramType::BOOLEAN); + addOption(OPTION_MULTIPLE_STRUCTS_MODE, OPTION_GROUP_OPTIONAL, - "If the regex agrees with multiple structs: write a dose statistic for every struct file." - "The struct name will be appended to the chosen output filename.", 'm'); + "If the regex agrees with multiple structs: write a dose statistic for every struct file." + "The struct name will be appended to the chosen output filename.", 'm'); + addInformationForXML(OPTION_MULTIPLE_STRUCTS_MODE, cmdlineparsing::XMLGenerator::paramType::BOOLEAN); parse(argc, argv); } void DoseToolCmdLineParser::validateInput() const { std::vector doseLoadStyle = get >(OPTION_DOSE_LOAD_STYLE); std::string doseLoadStyleAbbreviation = doseLoadStyle.at(0); if (doseLoadStyleAbbreviation != "dicom" && (!_virtuosSupport || doseLoadStyleAbbreviation != "virtuos") && doseLoadStyleAbbreviation != "itk" && doseLoadStyleAbbreviation != "helax") { throw cmdlineparsing::InvalidConstraintException("Unknown load style for dose file:" + doseLoadStyleAbbreviation + ".\nPlease refer to the help for valid loading style settings."); } if (_virtuosSupport && doseLoadStyleAbbreviation == "virtuos") { if (doseLoadStyle.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io style argument."); } } std::vector structLoadStyle = get >(OPTION_STRUCT_LOAD_STYLE); std::string structLoadStyleAbbreviation = structLoadStyle.at(0); if (structLoadStyleAbbreviation != "dicom" && (!_virtuosSupport || structLoadStyleAbbreviation != "virtuos") && structLoadStyleAbbreviation != "itk") { throw cmdlineparsing::InvalidConstraintException("Unknown load style for struct file:" + structLoadStyleAbbreviation + ".\nPlease refer to the help for valid loading style settings."); } if (structLoadStyleAbbreviation == "dicom" || (_virtuosSupport && structLoadStyleAbbreviation == "virtuos") || structLoadStyleAbbreviation == "helax") { if (get(OPTION_STRUCT_NAME) == "") { throw cmdlineparsing::InvalidConstraintException("The struct name (--" + OPTION_STRUCT_NAME + ") has to be defined for dicom, virtuos or helax struct files."); } } if (_virtuosSupport && structLoadStyleAbbreviation == "virtuos") { if (structLoadStyle.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos struct file. CTX file is missing. Specify CTX file as 2nd io style argument."); } } if (!isSet(OPTION_DVH) && !isSet(OPTION_DOSE_STATISTICS)) { throw cmdlineparsing::InvalidConstraintException("Neither the Dose statistics (--" + OPTION_DOSE_STATISTICS + "), nor the DVH (--" + OPTION_DVH + ") option was used."); } if (isSet(OPTION_DOSE_STATISTICS) && isSet(OPTION_COMPLEX_STATISTICS)) { if (!isSet(OPTION_PRESCRIBED_DOSE)) { throw cmdlineparsing::InvalidConstraintException("The prescribed dose (--" + OPTION_PRESCRIBED_DOSE + ") has to be set for computation of complex dose statistics."); } else { if (get(OPTION_PRESCRIBED_DOSE) <= 0) { throw cmdlineparsing::InvalidConstraintException("The prescribed dose (--" + OPTION_PRESCRIBED_DOSE + ") has to be >0!"); } } } } void DoseToolCmdLineParser::printHelp() const { cmdlineparsing::CmdLineParserBase::printHelp(); std::cout << "Example:" << std::endl << std::endl; std::cout << m_programName << " dose.dcm struct.dcm Liver result.xml --" + OPTION_DVH + " dvh.xml" << std::endl << std::endl; std::cout << "This will calculate the Dose statistic for liver using \"dose.dcm\" and the struct file \"struct.dcm\" and will write the dose statistics to \"result.xml\". " " The DVH is computed as well, its values are written to \"dvh.xml\". " << std::endl; } } } } diff --git a/apps/DoseTool/DoseToolCmdLineParser.h b/apps/DoseTool/DoseToolCmdLineParser.h index a88954d..94db354 100644 --- a/apps/DoseTool/DoseToolCmdLineParser.h +++ b/apps/DoseTool/DoseToolCmdLineParser.h @@ -1,68 +1,70 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1374 $ (last changed revision) // @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __DOSETOOL_CMD_LINE_PARSER #define __DOSETOOL_CMD_LINE_PARSER #include "CmdLineParserBase.h" namespace rttb { namespace apps { namespace doseTool { /*! @class DoseToolCmdLineParser @brief Argument parsing is parametrized here based on ArgParserLib @see cmdlineparsing::CmdLineParserBase */ class DoseToolCmdLineParser : public cmdlineparsing::CmdLineParserBase { public: DoseToolCmdLineParser(int argc, const char** argv, const std::string& name, - const std::string& version, bool virtuosSupport = false); + const std::string& version, bool virtuosSupport = false); + DoseToolCmdLineParser(int argc, const char** argv, const std::string& name, const std::string& version, + const std::string& description, const std::string& contributor, const std::string& category, bool virtuosSupport = false); void validateInput() const; void printHelp() const; // Option groups const std::string OPTION_GROUP_REQUIRED = "Required Arguments"; const std::string OPTION_GROUP_OPTIONAL = "Optional Arguments"; // Parameters const std::string OPTION_DOSE_FILE = "doseFile"; const std::string OPTION_STRUCT_FILE = "structFile"; const std::string OPTION_STRUCT_NAME = "structName"; const std::string OPTION_DOSE_STATISTICS = "doseStatistics"; const std::string OPTION_DVH = "DVH"; const std::string OPTION_DOSE_LOAD_STYLE = "doseLoadStyle"; const std::string OPTION_STRUCT_LOAD_STYLE = "structLoadStyle"; const std::string OPTION_COMPLEX_STATISTICS = "complexStatistics"; const std::string OPTION_PRESCRIBED_DOSE = "prescribedDose"; const std::string OPTION_ALLOW_SELF_INTERSECTION_STRUCT = "allowSelfIntersection"; const std::string OPTION_MULTIPLE_STRUCTS_MODE = "multipleStructsMode"; bool _virtuosSupport; }; } } } #endif \ No newline at end of file diff --git a/apps/VoxelizerTool/VoxelizerToolCmdLineParser.cpp b/apps/VoxelizerTool/VoxelizerToolCmdLineParser.cpp index ab7955b..f6044fe 100644 --- a/apps/VoxelizerTool/VoxelizerToolCmdLineParser.cpp +++ b/apps/VoxelizerTool/VoxelizerToolCmdLineParser.cpp @@ -1,124 +1,124 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1221 $ (last changed revision) // @date $Date: 2015-12-01 13:43:31 +0100 (Di, 01 Dez 2015) $ (last change date) // @author $Author: strubel $ (last changed by) */ #include "VoxelizerToolCmdLineParser.h" namespace rttb { namespace apps { namespace voxelizerTool { VoxelizerCmdLineParser::VoxelizerCmdLineParser(int argc, const char** argv, const std::string& name, const std::string& version, const std::string& description, const std::string& contributor, const std::string& category) : CmdLineParserBase(name, version, description, contributor, category) { //REQUIRED addOption(OPTION_STRUCT_FILE, OPTION_GROUP_REQUIRED, "Filename of the structfile (*.dcm)", 's', true); - addInformationForXML(OPTION_STRUCT_FILE, cmdlineparsing::XMLGenerator::paramType::INPUT, {"dcm"}); + addInformationForXML(OPTION_STRUCT_FILE, cmdlineparsing::XMLGenerator::paramType::INPUT, {"dcm", "*"}); addOption(OPTION_REFERENCE_FILE, OPTION_GROUP_REQUIRED, "Filename of the reference image (*.dcm)", 'r', true); - addInformationForXML(OPTION_REFERENCE_FILE, cmdlineparsing::XMLGenerator::paramType::INPUT, { "dcm" }); + addInformationForXML(OPTION_REFERENCE_FILE, cmdlineparsing::XMLGenerator::paramType::INPUT, { "dcm", "*" }); addOptionWithDefaultValue(OPTION_OUTPUT_FILE_NAME, OPTION_GROUP_REQUIRED, "Set output file name. Remark: if it used in conjunction with flag -m, it is only regarded as " "hint for the file name pattern. VoxelizerTool will add a suffix indicating the voxelized " "structure to each filename.","out.hdr","out.hdr", 'o', true); - addInformationForXML(OPTION_OUTPUT_FILE_NAME, cmdlineparsing::XMLGenerator::paramType::OUTPUT, { "nrrd", "hdr" }); + addInformationForXML(OPTION_OUTPUT_FILE_NAME, cmdlineparsing::XMLGenerator::paramType::OUTPUT, { "hdr", "nrrd", "*" }); addPositionalOption(OPTION_STRUCT_FILE,1); addPositionalOption(OPTION_REFERENCE_FILE, 1); addPositionalOption(OPTION_OUTPUT_FILE_NAME, 1); std::vector defaultLoadingStyle; defaultLoadingStyle.push_back("dicom"); addOptionWithDefaultValue(OPTION_REGEX, OPTION_GROUP_REQUIRED, "set a regular expression describing the structs of interest", "", "",'e', true); addInformationForXML(OPTION_REGEX, cmdlineparsing::XMLGenerator::paramType::STRING); addOptionWithDefaultValue>(OPTION_REFERENCE_FILE_LOAD_STYLE, OPTION_GROUP_REQUIRED, "set the load style for the reference file. Available styles are: " "dicom: normal dicom dose" "itk: use itk image loading.", defaultLoadingStyle, defaultLoadingStyle.at(0), 'y', true); addInformationForXML(OPTION_REFERENCE_FILE_LOAD_STYLE, cmdlineparsing::XMLGenerator::paramType::STRINGENUMERATION, { "dicom", "itk" }); //OPTIONAL addOption(OPTION_MULTIPLE_STRUCTS, OPTION_GROUP_OPTIONAL, "if multiple structs match the regular expression" + OPTION_STRUCT_FILE + ", save all in files\n" "If structures 'Kidney_left' and 'Kidney_right' are defined,\n" "both are written under the names outputFile_Kidney_left.mhd and outputFile_Kidney_right.mhd",'m'); addInformationForXML(OPTION_MULTIPLE_STRUCTS, cmdlineparsing::XMLGenerator::paramType::BOOLEAN); addOption(OPTION_BOOLEAN_VOXELIZATION, OPTION_GROUP_OPTIONAL, "Determines if the voxelization should be binarized (only values 0 or 1), the threshold value is by 0.5",'z'); addInformationForXML(OPTION_BOOLEAN_VOXELIZATION, cmdlineparsing::XMLGenerator::paramType::BOOLEAN); addOption(OPTION_ADDSTRUCTURES, OPTION_GROUP_OPTIONAL, "Voxelizes multiple structs in one result file.",'a'); addInformationForXML(OPTION_ADDSTRUCTURES, cmdlineparsing::XMLGenerator::paramType::BOOLEAN); addOption(OPTION_NO_STRICT_VOXELIZATION, OPTION_GROUP_OPTIONAL, "Deviations of wrong voxel volumes are tolerated and corrected.",'i'); addInformationForXML(OPTION_NO_STRICT_VOXELIZATION, cmdlineparsing::XMLGenerator::paramType::BOOLEAN); parse(argc, argv); } void VoxelizerCmdLineParser::validateInput() const { std::vector referenceLoadStyle = get >(OPTION_REFERENCE_FILE_LOAD_STYLE); std::string referenceLoadStyleString = referenceLoadStyle.at(0); if (referenceLoadStyleString != "dicom" && referenceLoadStyleString != "itk") { throw cmdlineparsing::InvalidConstraintException("Unknown load style for reference file:" + referenceLoadStyleString+ ".\nPlease refer to the help for valid loading style settings."); } if (get(OPTION_OUTPUT_FILE_NAME).find('.') == std::string::npos) { throw cmdlineparsing::InvalidConstraintException(OPTION_OUTPUT_FILE_NAME + " has to specify a file format (e.g. output.hdr). None is given: " + get(OPTION_OUTPUT_FILE_NAME) ); } } void VoxelizerCmdLineParser::printHelp() const { cmdlineparsing::CmdLineParserBase::printHelp(); std::cout << "Example: VoxelizerTool -s structFile.dcm -r referenceFile.dcm -e Kidney -o outputFile.mhd -m" << std::endl; std::cout << "Computes a voxelization file outputFile.mhd based on the DICOMRT-STRUCT structFile.dcm " "in the geometry of referenceFile.dcm where "; std::cout << "the name of the struct matches the regular expression 'Kidney'.\n"; std::cout << "If structures 'Kidney_left' and 'Kidney_right' are defined, "; std::cout << "both are written under the names outputFile_Kidney_left.mhd and outputFile_Kidney_right.mhd (parameter -m)." << std::endl; } } } } \ No newline at end of file diff --git a/testing/io/other/CMakeLists.txt b/testing/io/other/CMakeLists.txt index 81c8e72..f6a423e 100644 --- a/testing/io/other/CMakeLists.txt +++ b/testing/io/other/CMakeLists.txt @@ -1,21 +1,22 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(OTHERIO_TEST ${EXECUTABLE_OUTPUT_PATH}/rttbOtherIOTests) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(DoseStatisticsIOTest ${OTHERIO_TEST} DoseStatisticsIOTest) ADD_TEST(DVHXMLIOTest ${OTHERIO_TEST} DVHXMLIOTest "${TEST_DATA_ROOT}/DVH/Text/dvh_1.txt") ADD_TEST(DVHTXTIOTest ${OTHERIO_TEST} DVHTXTIOTest "${TEST_DATA_ROOT}/DVH/Text/dvh_1.txt") +RTTB_CREATE_TEST_MODULE(rttbOtherIO DEPENDS RTTBOtherIO PACKAGE_DEPENDS Boost Litmus) \ No newline at end of file