diff --git a/apps/BioModelCalc/BioModelCalc.cpp b/apps/BioModelCalc/BioModelCalc.cpp index 3bf0fc6..875c8de 100644 --- a/apps/BioModelCalc/BioModelCalc.cpp +++ b/apps/BioModelCalc/BioModelCalc.cpp @@ -1,133 +1,145 @@ // ----------------------------------------------------------------------- // 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" rttb::apps::bioModelCalc::ApplicationData appData; int main(int argc, const char** argv) { int result = 0; boost::shared_ptr argParser; try { std::string appName = "BioModelCalc"; std::string appVersion = RTTB_FULL_VERSION_STRING; argParser = boost::make_shared(argc, argv, appName, appVersion); } 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)) { 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; std::cout << std::endl; try { appData._dose = rttb::apps::bioModelCalc::loadDose(appData._doseFileName, appData._doseLoadStyle); + for (const auto& filename : appData._modelParameterMapsFilename){ + appData._modelParameterMaps.push_back(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/BioModelCalcApplicationData.cpp b/apps/BioModelCalc/BioModelCalcApplicationData.cpp index 0854fd8..217744e 100644 --- a/apps/BioModelCalc/BioModelCalcApplicationData.cpp +++ b/apps/BioModelCalc/BioModelCalcApplicationData.cpp @@ -1,57 +1,66 @@ // ----------------------------------------------------------------------- // 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: 1233 $ (last changed revision) // @date $Date: 2016-01-20 15:47:47 +0100 (Mi, 20 Jan 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "BioModelCalcApplicationData.h" namespace rttb { namespace apps { namespace bioModelCalc { ApplicationData:: ApplicationData() { - this->Reset(); + this->reset(); } void ApplicationData:: - Reset() + reset() { _doseFileName = ""; _outputFileName = ""; _doseScaling = 1.0; + _modelParameters.clear(); + _modelParameterMapsFilename.clear(); + _modelParameterMaps.clear(); } void populateAppData(boost::shared_ptr argParser, ApplicationData& appData) { appData._doseFileName = argParser->get(argParser->OPTION_DOSE_FILE); appData._doseLoadStyle = argParser->get >(argParser->OPTION_LOAD_STYLE); appData._doseScaling = argParser->get(argParser->OPTION_DOSE_SCALING); appData._outputFileName = argParser->get(argParser->OPTION_OUTPUT_FILE); appData._model = argParser->get(argParser->OPTION_MODEL); - appData._modelParameters = argParser->get >(argParser->OPTION_MODEL_PARAMETERS); + if (argParser->isSet(argParser->OPTION_MODEL_PARAMETERS)){ + appData._modelParameters = argParser->get >(argParser->OPTION_MODEL_PARAMETERS); + } + else { + appData._modelParameterMapsFilename = argParser->get >(argParser->OPTION_MODEL_PARAMETER_MAPS); + appData._parameterMapsLoadStyle = argParser->get >(argParser->OPTION_LOAD_STYLE_PARAMETER_MAPS); + } } } } } diff --git a/apps/BioModelCalc/BioModelCalcApplicationData.h b/apps/BioModelCalc/BioModelCalcApplicationData.h index 3804a41..ddda668 100644 --- a/apps/BioModelCalc/BioModelCalcApplicationData.h +++ b/apps/BioModelCalc/BioModelCalcApplicationData.h @@ -1,69 +1,72 @@ // ----------------------------------------------------------------------- // 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: 1210 $ (last changed revision) // @date $Date: 2015-11-24 15:52:45 +0100 (Di, 24 Nov 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __BIO_MODEL_CALC_APPLICATION_DATA_H #define __BIO_MODEL_CALC_APPLICATION_DATA_H #include #include "rttbDoseAccessorInterface.h" #include "BioModelCmdLineParser.h" namespace rttb { namespace apps { namespace bioModelCalc { /*! @class ApplicationData @brief Class for storing all relevant variables needed in BioModelCalc */ class ApplicationData { public: /**Vector of arguments used to specify the loading style (always the first argument) * and, if needed, additional arguments for the specified loading style (e.g. location of the * Virtuos plan file for the Virtuos IO style). */ typedef std::vector LoadingStyleArgType; core::DoseAccessorInterface::DoseAccessorPointer _dose; + std::vector _modelParameterMaps; std::string _doseFileName; LoadingStyleArgType _doseLoadStyle; + LoadingStyleArgType _parameterMapsLoadStyle; double _doseScaling; std::string _outputFileName; std::string _model; std::vector _modelParameters; + std::vector _modelParameterMapsFilename; - void Reset(); + void reset(); ApplicationData(); }; /*! @brief Reads the necessary arguments from the BioModelCmdLineParser and writes them in the respective variables of ApplicationData */ void populateAppData(boost::shared_ptr argParser, ApplicationData& appData); } } } #endif diff --git a/apps/BioModelCalc/BioModelCalcHelper.cpp b/apps/BioModelCalc/BioModelCalcHelper.cpp index 69e7f30..fe3da7d 100644 --- a/apps/BioModelCalc/BioModelCalcHelper.cpp +++ b/apps/BioModelCalc/BioModelCalcHelper.cpp @@ -1,131 +1,154 @@ // ----------------------------------------------------------------------- // 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 "BioModelCalcHelper.h" #include "boost/make_shared.hpp" #include "boost/shared_ptr.hpp" #include "rttbExceptionMacros.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomHelaxFileDoseAccessorGenerator.h" #include "rttbITKImageFileAccessorGenerator.h" #include "rttbITKImageAccessorConverter.h" #include "rttbImageWriter.h" #include "rttbLQModelAccessor.h" rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::bioModelCalc::loadDose(const std::string& fileName, const rttb::apps::bioModelCalc::ApplicationData::LoadingStyleArgType& args) { rttb::core::DoseAccessorInterface::DoseAccessorPointer result; std::cout << std::endl << "read dose file... "; if (args.empty() || args[0] == "dicom") { std::cout << "use RTTB dicom IO... "; result = loadDicomDose(fileName); } else if (args[0] == "helax") { std::cout << "use RTTB Helax IO... "; result = loadHelaxDose(fileName); } else if (args[0] == "itk") { std::cout << "use RTTB itk IO... "; result = loadITKDose(fileName); } else { rttbDefaultExceptionStaticMacro( << "Unknown io style selected. Cannot load data. Selected style: " << args[0]); } std::cout << "done." << std::endl; return result; }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::bioModelCalc::loadDicomDose(const std::string& fileName) { rttb::io::dicom::DicomFileDoseAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::bioModelCalc::loadHelaxDose(const std::string& path) { rttb::io::helax::DicomHelaxFileDoseAccessorGenerator generator(path); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::bioModelCalc::loadITKDose(const std::string& fileName) { rttb::io::itk::ITKImageFileAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; void rttb::apps::bioModelCalc::processData(rttb::apps::bioModelCalc::ApplicationData& appData) { rttb::core::DoseAccessorInterface::DoseAccessorPointer outputAccessor; std::cout << std::endl << "generate biomodel... "; - auto bioModelAccessor = generateBioModel(appData._dose, appData._model, appData._modelParameters, - appData._doseScaling); + rttb::core::AccessorInterface::AccessorPointer bioModelAccessor; + if (!appData._modelParameters.empty()){ + bioModelAccessor = generateBioModel(appData._dose, appData._model, appData._modelParameters, + appData._doseScaling); + } + else { + bioModelAccessor = generateBioModelWithMaps(appData._dose, appData._model, appData._modelParameterMaps, + appData._doseScaling); + } std::cout << "done." << std::endl; std::cout << std::endl << "generate output image... "; io::itk::ITKImageAccessorConverter converter(bioModelAccessor); converter.setFailOnInvalidIDs(true); converter.process(); io::itk::ITKImageAccessorConverter::ITKImageType::Pointer itkImage = converter.getITKImage(); std::cout << "done." << std::endl; std::cout << std::endl << "write output image... "; io::itk::ImageWriter writer(appData._outputFileName, itkImage); writer.writeFile(); std::cout << "done." << std::endl; }; rttb::core::AccessorInterface::AccessorPointer rttb::apps::bioModelCalc::generateBioModel( rttb::core::DoseAccessorInterface::DoseAccessorPointer dose, const std::string& model, const std::vector& modelParameters, double doseScaling) { if (model == "LQ") { return boost::make_shared(dose, modelParameters.at(0), modelParameters.at(1), doseScaling); } else { rttbDefaultExceptionStaticMacro( << "Unknown model selected. Cannot load data. Selected model: " << model); } } +rttb::core::AccessorInterface::AccessorPointer rttb::apps::bioModelCalc::generateBioModelWithMaps( + rttb::core::DoseAccessorInterface::DoseAccessorPointer dose, const std::string& model, + const std::vector& modelParameterMaps, double doseScaling) +{ + if (model == "LQ") + { + return boost::make_shared(dose, modelParameterMaps.at(0), + modelParameterMaps.at(1), doseScaling); + } + else + { + rttbDefaultExceptionStaticMacro(<< "Unknown model selected. Cannot load data. Selected model: " + << model); + } +} + diff --git a/apps/BioModelCalc/BioModelCalcHelper.h b/apps/BioModelCalc/BioModelCalcHelper.h index 0d7300a..3a5315a 100644 --- a/apps/BioModelCalc/BioModelCalcHelper.h +++ b/apps/BioModelCalc/BioModelCalcHelper.h @@ -1,75 +1,79 @@ // ----------------------------------------------------------------------- // 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: 1210 $ (last changed revision) // @date $Date: 2015-11-24 15:52:45 +0100 (Di, 24 Nov 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __BIO_MODEL_CALC_HELPER_H #define __BIO_MODEL_CALC_HELPER_H #include "BioModelCalcApplicationData.h" #include "rttbAccessorInterface.h" namespace rttb { namespace apps { namespace bioModelCalc { /*! @brief loads a dose from a file based on the loadingStyle. @details Throws an rttb::Exception if loading fails */ core::DoseAccessorInterface::DoseAccessorPointer loadDose(const std::string& fileName, const rttb::apps::bioModelCalc::ApplicationData::LoadingStyleArgType& args); /*! @brief loads a dicom dose from a file. @details Throws an rttb::Exception if loading fails @sa DicomFileDoseAccessorGenerator */ core::DoseAccessorInterface::DoseAccessorPointer loadDicomDose(const std::string& fileName); /*! @brief loads a helax dose from a file. @details Throws an rttb::Exception if loading fails @sa DicomHelaxFileDoseAccessorGenerator */ core::DoseAccessorInterface::DoseAccessorPointer loadHelaxDose(const std::string& path); /*! @brief loads an itk dose from a file. @details Throws an rttb::Exception if loading fails. Might be of all formats that ITK know (*.mhd, *.nrrd, ...). The absolute image values are taken as dose. @sa ITKImageFileAccessorGenerator */ core::DoseAccessorInterface::DoseAccessorPointer loadITKDose(const std::string& fileName); /*! @brief loads a virtuos dose from a file. @details Throws an rttb::Exception if loading fails @sa VirtuosPlanFileDoseAccessorGenerator */ core::DoseAccessorInterface::DoseAccessorPointer loadVirtuosDose(const std::string& fileName, const std::string& planFileName); /*! @brief Contains the business logic of processing all information to calculate a bioModel from the dose and writing it back to an image. @details Uses appData for the input data and the correct configuration. */ void processData(ApplicationData& appData); core::AccessorInterface::AccessorPointer generateBioModel( core::DoseAccessorInterface::DoseAccessorPointer dose, const std::string& model, const std::vector& modelParameters, double doseScaling = 1.0); + rttb::core::AccessorInterface::AccessorPointer generateBioModelWithMaps( + rttb::core::DoseAccessorInterface::DoseAccessorPointer dose, const std::string& model, + const std::vector& modelParameterMaps, double doseScaling = 1.0); + } } } #endif diff --git a/apps/BioModelCalc/BioModelCmdLineParser.cpp b/apps/BioModelCalc/BioModelCmdLineParser.cpp index dd51640..ef4360e 100644 --- a/apps/BioModelCalc/BioModelCmdLineParser.cpp +++ b/apps/BioModelCalc/BioModelCmdLineParser.cpp @@ -1,111 +1,120 @@ #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) { 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); 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); 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\"", "LQ", "LQ", 'm'); - addOption >(OPTION_MODEL_PARAMETERS, OPTION_GROUP_REQUIRED, - "The parameters for the radiobiological model.", 'p', true, true); + 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); addOptionWithDefaultValue(OPTION_DOSE_SCALING, OPTION_GROUP_REQUIRED, "Dose scaling that should be applied.", 1.0, "1.0", 'e'); 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)."; 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\")"; } 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); 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 (get >(OPTION_MODEL_PARAMETERS).size() != 2) + 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!"); + 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 + + 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 invalid. Dose scaling has to be >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 a0618a2..132b55d 100644 --- a/apps/BioModelCalc/BioModelCmdLineParser.h +++ b/apps/BioModelCalc/BioModelCmdLineParser.h @@ -1,42 +1,44 @@ #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); 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"; bool _virtuosSupport; }; } } } #endif \ No newline at end of file diff --git a/apps/BioModelCalc4V/BioModelCalc4V.cpp b/apps/BioModelCalc4V/BioModelCalc4V.cpp index 218cf7b..1cbbbee 100644 --- a/apps/BioModelCalc4V/BioModelCalc4V.cpp +++ b/apps/BioModelCalc4V/BioModelCalc4V.cpp @@ -1,134 +1,146 @@ // ----------------------------------------------------------------------- // 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 "../BioModelCalc/BioModelCalcApplicationData.h" #include "../BioModelCalc/BioModelCalcHelper.h" #include "../BioModelCalc/BioModelCmdLineParser.h" #include "../DoseTool4V/DoseTool4VHelper.h" #include "boost/shared_ptr.hpp" #include "boost/make_shared.hpp" #include "RTToolboxConfigure.h" #include "rttbException.h" rttb::apps::bioModelCalc::ApplicationData appData; int main(int argc, const char** argv) { int result = 0; boost::shared_ptr argParser; try { std::string appName = "BioModelCalc4V"; std::string appVersion = RTTB_FULL_VERSION_STRING; argParser = boost::make_shared(argc, argv, appName, appVersion, true); } 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)) { 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; std::cout << std::endl; try { appData._dose = rttb::apps::doseTool4V::loadDose(appData._doseFileName, appData._doseLoadStyle); + for (const auto& filename : appData._modelParameterMapsFilename){ + appData._modelParameterMaps.push_back(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/code/io/itk/rttbImageWriter.cpp b/code/io/itk/rttbImageWriter.cpp index ff449fb..5ed8023 100644 --- a/code/io/itk/rttbImageWriter.cpp +++ b/code/io/itk/rttbImageWriter.cpp @@ -1,60 +1,61 @@ // ----------------------------------------------------------------------- // 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$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "rttbImageWriter.h" #include "rttbITKException.h" namespace rttb { namespace io { namespace itk { ImageWriter::ImageWriter(FileNameString aFileName, ITKImageTypePointer aITKImage) : _fileName(aFileName), _itkImage(aITKImage) { } bool ImageWriter::writeFile() { WriterType::Pointer writer = WriterType::New(); writer->SetFileName(_fileName); + writer->SetUseCompression(true); writer->SetInput(_itkImage); try { writer->Update(); } catch (::itk::ExceptionObject& excp) { std::cerr << "Error: ITK Exception caught " << excp << std::endl; throw rttb::io::itk::ITKException("ITK Exception in writing image: writer->Update()!"); return false; } return true; } }//end namespace itk }//end namespace io }//end namespace rttb diff --git a/code/models/rttbLQModelAccessor.cpp b/code/models/rttbLQModelAccessor.cpp index 65e3c33..f2a7caf 100644 --- a/code/models/rttbLQModelAccessor.cpp +++ b/code/models/rttbLQModelAccessor.cpp @@ -1,73 +1,100 @@ // ----------------------------------------------------------------------- // 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$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "rttbLQModelAccessor.h" #include "rttbDoseBasedModels.h" #include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace models { LQModelAccessor::~LQModelAccessor() { } LQModelAccessor::LQModelAccessor(DoseAccessorPointer dose, BioModelParamType alpha, BioModelParamType beta, double doseScaling) : - _dose(dose), _alpha(alpha), _beta(beta), _doseScaling(doseScaling) + _dose(dose), _alpha(alpha), _beta(beta), _betaMap(nullptr), _alphaMap(nullptr), _doseScaling(doseScaling), _withAlphaBetaMaps(false) { if (_dose == NULL) { throw core::InvalidDoseException("Dose is NULL"); } if (_doseScaling < 0) { throw core::InvalidParameterException("Dose Scaling must be >0"); } assembleGeometricInfo(); } + LQModelAccessor::LQModelAccessor(DoseAccessorPointer dose, DoseAccessorPointer alphaMap, DoseAccessorPointer betaMap, + double doseScaling) :_dose(dose), _alpha(-1.), _beta(-1.), _betaMap(alphaMap), _alphaMap(betaMap), _doseScaling(doseScaling), _withAlphaBetaMaps(true) + { + if (_dose == NULL || _alphaMap == nullptr || _betaMap == nullptr) + { + throw core::InvalidDoseException("Dose or alphaMap or betaMap is NULL"); + } + + if (_doseScaling < 0) + { + throw core::InvalidParameterException("Dose Scaling must be >0"); + } + + assembleGeometricInfo(); + } + GenericValueType LQModelAccessor::getValueAt(const VoxelGridID aID) const { - return calcLQ(_dose->getValueAt(aID) * _doseScaling, _alpha, _beta); + if (_withAlphaBetaMaps){ + return calcLQ(_dose->getValueAt(aID) * _doseScaling, _alphaMap->getValueAt(aID), _betaMap->getValueAt(aID)); + } + else { + return calcLQ(_dose->getValueAt(aID) * _doseScaling, _alpha, _beta); + } } GenericValueType LQModelAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const { - return calcLQ(_dose->getValueAt(aIndex) * _doseScaling, _alpha, _beta); + if (_withAlphaBetaMaps){ + return calcLQ(_dose->getValueAt(aIndex) * _doseScaling, _alphaMap->getValueAt(aIndex), _betaMap->getValueAt(aIndex)); + } + else { + return calcLQ(_dose->getValueAt(aIndex) * _doseScaling, _alpha, _beta); + } + } bool LQModelAccessor::assembleGeometricInfo() { _geoInfo = _dose->getGeometricInfo(); return true; } } } diff --git a/code/models/rttbLQModelAccessor.h b/code/models/rttbLQModelAccessor.h index a403ce5..22e5546 100644 --- a/code/models/rttbLQModelAccessor.h +++ b/code/models/rttbLQModelAccessor.h @@ -1,82 +1,92 @@ // ----------------------------------------------------------------------- // 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$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #ifndef __LQ_MODEL_ACCESSOR_H #define __LQ_MODEL_ACCESSOR_H #include "rttbAccessorWithGeoInfoBase.h" #include "rttbDoseAccessorInterface.h" #include "rttbBaseTypeModels.h" namespace rttb { namespace models { /*! @class LQModelAccessor @brief This class gives access to the LQ Model information in an image */ class LQModelAccessor: public core::AccessorWithGeoInfoBase { public: typedef core::DoseAccessorInterface::DoseAccessorPointer DoseAccessorPointer; private: DoseAccessorPointer _dose; BioModelParamType _alpha; + DoseAccessorPointer _alphaMap; BioModelParamType _beta; + DoseAccessorPointer _betaMap; + bool _withAlphaBetaMaps; double _doseScaling; IDType _bioModelUID; LQModelAccessor(); /*! @brief get all required data from the dose geometric info */ bool assembleGeometricInfo(); public: ~LQModelAccessor(); /*! @brief Constructor. @pre dose must be a valid instance (and not null) @exception InvalidDoseException if _dose is NULL */ LQModelAccessor(DoseAccessorPointer dose, BioModelParamType alpha, BioModelParamType beta, double doseScaling = 1.0); + /*! @brief Constructor. + @pre dose must be a valid instance (and not null) + @exception InvalidDoseException if dose is NULL, if alphaMap is NULL or if betaMap is NULL + */ + LQModelAccessor(DoseAccessorPointer dose, DoseAccessorPointer alphaMap, DoseAccessorPointer betaMap, + double doseScaling = 1.0); + /*! @brief returns the LQ Model value for an id */ GenericValueType getValueAt(const VoxelGridID aID) const; /*! @brief returns the LQ Model value for an index */ GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const; const IDType getUID() const { return _bioModelUID; }; }; } } #endif diff --git a/testing/apps/BioModelCalc/BioModelCalcInvalidParametersTest.cpp b/testing/apps/BioModelCalc/BioModelCalcInvalidParametersTest.cpp new file mode 100644 index 0000000..ed5f185 --- /dev/null +++ b/testing/apps/BioModelCalc/BioModelCalcInvalidParametersTest.cpp @@ -0,0 +1,98 @@ +// ----------------------------------------------------------------------- +// 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: hentsch $ (last changed by) +*/ + +#include + +#include "litCheckMacros.h" + +#include "boost/filesystem.hpp" + +namespace rttb +{ + namespace testing + { + + //path to the current running directory. DoseTool is in the same directory (Debug/Release) + extern const char* _callingAppPath; + + int BioModelCalcInvalidParametersTest(int argc, char* argv[]) + { + PREPARE_DEFAULT_TEST_REPORTING; + + std::string bioModelCalcExecutable; + + if (argc > 1) + { + bioModelCalcExecutable = argv[1]; + } + + boost::filesystem::path callingPath(_callingAppPath); + std::string bioModelCalcExeWithPath = callingPath.parent_path().string() + "/" + bioModelCalcExecutable; + + //call with too few parameters + std::string toofewParametersCommand = bioModelCalcExeWithPath; + toofewParametersCommand += " test"; + std::cout << "Command line call: " + toofewParametersCommand << std::endl; + CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); + + toofewParametersCommand = bioModelCalcExeWithPath; + toofewParametersCommand += " test test"; + std::cout << "Command line call: " + toofewParametersCommand << std::endl; + CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); + + toofewParametersCommand = bioModelCalcExeWithPath; + toofewParametersCommand += " -d test"; + toofewParametersCommand += " -o test"; + std::cout << "Command line call: " + toofewParametersCommand << std::endl; + CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); + + //call with invalid model + std::string minimalCLI = bioModelCalcExeWithPath + " test test -p 1.0 1.0 "; + std::string invalidModelOption = minimalCLI; + invalidModelOption += "-m wrongModel"; + std::cout << "Command line call: " + invalidModelOption << std::endl; + CHECK_EQUAL(system(invalidModelOption.c_str()) != 0, true); + + //call with only one parameter + std::string toofewModelParameterOption = bioModelCalcExeWithPath + " test test -p 1.0"; + std::cout << "Command line call: " + toofewModelParameterOption << std::endl; + CHECK_EQUAL(system(toofewModelParameterOption.c_str()) != 0, true); + + toofewModelParameterOption = bioModelCalcExeWithPath + " test test -a parameterMapsTest"; + std::cout << "Command line call: " + toofewModelParameterOption << std::endl; + CHECK_EQUAL(system(toofewModelParameterOption.c_str()) != 0, true); + + //call with invalid dose load option + std::string invalidDoseLoadOption = minimalCLI; + invalidDoseLoadOption += "-t invalidLoadStyleOption"; + std::cout << "Command line call: " + invalidDoseLoadOption << std::endl; + CHECK_EQUAL(system(invalidDoseLoadOption.c_str()) != 0, true); + + //call with negative dose scaling + std::string negativeDoseScalingCommand = minimalCLI; + negativeDoseScalingCommand += "-e -1.0"; + std::cout << "Command line call: " + negativeDoseScalingCommand << std::endl; + CHECK_EQUAL(system(negativeDoseScalingCommand.c_str()) != 0, true); + + RETURN_AND_REPORT_TEST_SUCCESS; + } + } //namespace testing +} //namespace rttb diff --git a/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp b/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp new file mode 100644 index 0000000..927cee7 --- /dev/null +++ b/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp @@ -0,0 +1,106 @@ +// ----------------------------------------------------------------------- +// 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: hentsch $ (last changed by) +*/ + +#include +#include +#include + +#include "litCheckMacros.h" +#include "litImageTester.h" + +#include "boost/filesystem.hpp" +#include "boost/algorithm/string.hpp" + +#include "itkImage.h" + +#include "rttbITKIOHelper.h" + +namespace rttb +{ + namespace testing + { + + //path to the current running directory. DoseTool is in the same directory (Debug/Release) + extern const char* _callingAppPath; + + int BioModelCalcParameterMapsTest(int argc, char* argv[]) + { + PREPARE_DEFAULT_TEST_REPORTING; + + std::string bioModelCalcExecutable; + std::string doseFilename; + std::string doseFilenameLoadStyle; + std::string modelName; + std::string modelParameterMaps; + std::string modelParameterMapsLoadStyle; + std::string referenceFilename; + + boost::filesystem::path callingPath(_callingAppPath); + + + if (argc > 7) + { + bioModelCalcExecutable = argv[1]; + doseFilename = argv[2]; + doseFilenameLoadStyle = argv[3]; + modelName = argv[4]; + modelParameterMaps = argv[5]; + modelParameterMapsLoadStyle = argv[6]; + referenceFilename = argv[7]; + } + + std::string bioModelCalcExeWithPath = callingPath.parent_path().string() + "/" + bioModelCalcExecutable; + + std::string defaultOutputFilename = "bioModelParameterMapOutput.nrrd"; + + std::string baseCommand = bioModelCalcExeWithPath; + baseCommand += " -d " + doseFilename; + baseCommand += " -t " + doseFilenameLoadStyle; + baseCommand += " -o " + defaultOutputFilename; + baseCommand += " -m " + modelName; + baseCommand += " -a " + modelParameterMaps; + baseCommand += " -u " + modelParameterMapsLoadStyle; + + std::string defaultDoseStatisticsCommand = baseCommand; + std::cout << "Command line call: " + defaultDoseStatisticsCommand << std::endl; + CHECK_EQUAL(system(defaultDoseStatisticsCommand.c_str()), 0); + + CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); + + // Check result against reference + typedef ::itk::Image TestImageType; + + TestImageType::Pointer referenceImage = io::itk::readITKDoubleImage(referenceFilename); + TestImageType::Pointer outputImage = io::itk::readITKDoubleImage(defaultOutputFilename); + + lit::ImageTester tester; + tester.setExpectedImage(referenceImage); + tester.setActualImage(outputImage); + tester.setCheckThreshold(0.0); + + CHECK_TESTER(tester); + + CHECK_EQUAL(std::remove(defaultOutputFilename.c_str()), 0); + + RETURN_AND_REPORT_TEST_SUCCESS; + } + } //namespace testing +} //namespace rttb diff --git a/testing/apps/BioModelCalc/BioModelCalcSimpleTest.cpp b/testing/apps/BioModelCalc/BioModelCalcSimpleTest.cpp new file mode 100644 index 0000000..6af6ab8 --- /dev/null +++ b/testing/apps/BioModelCalc/BioModelCalcSimpleTest.cpp @@ -0,0 +1,103 @@ +// ----------------------------------------------------------------------- +// 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: hentsch $ (last changed by) +*/ + +#include +#include +#include + +#include "litCheckMacros.h" +#include "litImageTester.h" + +#include "boost/filesystem.hpp" +#include "boost/algorithm/string.hpp" + +#include "itkImage.h" + +#include "rttbITKIOHelper.h" + +namespace rttb +{ + namespace testing + { + + //path to the current running directory. DoseTool is in the same directory (Debug/Release) + extern const char* _callingAppPath; + + int BioModelCalcSimpleTest(int argc, char* argv[]) + { + PREPARE_DEFAULT_TEST_REPORTING; + + std::string bioModelCalcExecutable; + std::string doseFilename; + std::string doseFilenameLoadStyle; + std::string modelName; + std::string modelArguments; + std::string referenceFilename; + + boost::filesystem::path callingPath(_callingAppPath); + + + if (argc > 6) + { + bioModelCalcExecutable = argv[1]; + doseFilename = argv[2]; + doseFilenameLoadStyle = argv[3]; + modelName = argv[4]; + modelArguments = argv[5]; + referenceFilename = argv[6]; + } + + std::string bioModelCalcExeWithPath = callingPath.parent_path().string() + "/" + bioModelCalcExecutable; + + std::string defaultOutputFilename = "bioModelOutput.nrrd"; + + std::string baseCommand = bioModelCalcExeWithPath; + baseCommand += " -d " + doseFilename; + baseCommand += " -t " + doseFilenameLoadStyle; + baseCommand += " -o " + defaultOutputFilename; + baseCommand += " -m " + modelName; + baseCommand += " -p " + modelArguments; + + std::string defaultDoseStatisticsCommand = baseCommand; + std::cout << "Command line call: " + defaultDoseStatisticsCommand << std::endl; + CHECK_EQUAL(system(defaultDoseStatisticsCommand.c_str()), 0); + + CHECK_EQUAL(boost::filesystem::exists(defaultOutputFilename), true); + + // Check result against reference + typedef ::itk::Image TestImageType; + + TestImageType::Pointer referenceImage = io::itk::readITKDoubleImage(referenceFilename); + TestImageType::Pointer outputImage = io::itk::readITKDoubleImage(defaultOutputFilename); + + lit::ImageTester tester; + tester.setExpectedImage(referenceImage); + tester.setActualImage(outputImage); + tester.setCheckThreshold(0.0); + + CHECK_TESTER(tester); + + CHECK_EQUAL(std::remove(defaultOutputFilename.c_str()), 0); + + RETURN_AND_REPORT_TEST_SUCCESS; + } + } //namespace testing +} //namespace rttb diff --git a/testing/apps/BioModelCalc/BioModelCalcTests.cpp b/testing/apps/BioModelCalc/BioModelCalcTests.cpp new file mode 100644 index 0000000..4129c1a --- /dev/null +++ b/testing/apps/BioModelCalc/BioModelCalcTests.cpp @@ -0,0 +1,71 @@ +// ----------------------------------------------------------------------- +// 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) +*/ + +// this file defines the rttbCoreTests for the test driver +// and all it expects is that you have a function called registerTests() +#if defined(_MSC_VER) +#pragma warning ( disable : 4786 ) +#endif + +#include "litMultiTestsMain.h" + +#include "RTToolboxConfigure.h" + +namespace rttb +{ + namespace testing + { + + const char* _callingAppPath = NULL; + + void registerTests() + { + LIT_REGISTER_TEST(BioModelCalcInvalidParametersTest); + LIT_REGISTER_TEST(BioModelCalcSimpleTest); + LIT_REGISTER_TEST(BioModelCalcParameterMapsTest); + } + + } //namespace testing +} //namespace map + + +int main(int argc, char* argv[]) +{ + int result = 0; + + rttb::testing::registerTests(); + + if (argc > 0) + { + rttb::testing::_callingAppPath = argv[0]; + } + + try + { + result = lit::multiTestsMain(argc, argv); + } + catch (...) + { + result = -1; + } + + return result; +} diff --git a/testing/apps/BioModelCalc/CMakeLists.txt b/testing/apps/BioModelCalc/CMakeLists.txt new file mode 100644 index 0000000..e6d1a50 --- /dev/null +++ b/testing/apps/BioModelCalc/CMakeLists.txt @@ -0,0 +1,32 @@ +#----------------------------------------------------------------------------- +# Setup the system information test. Write out some basic failsafe +# information in case the test doesn't run. +#----------------------------------------------------------------------------- + + +SET(BIOMODELCALC_TEST ${EXECUTABLE_OUTPUT_PATH}/rttbBioModelCalcTests) + +SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) + +SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) + + +#----------------------------------------------------------------------------- + +IF(MSVC) + ADD_DEFINITIONS(/bigobj) +ENDIF() + +IF (WIN32) + SET(BIOMODELCALCEXE "BioModelCalc.exe") +ELSE (WIN32) + SET(BIOMODELCALCEXE "./BioModelCalc") +ENDIF (WIN32) + +ADD_TEST(BioModelCalcInvalidParametersTest ${BIOMODELCALC_TEST} BioModelCalcInvalidParametersTest ${BIOMODELCALCEXE}) +ADD_TEST(BioModelCalcSimpleTest ${BIOMODELCALC_TEST} BioModelCalcSimpleTest ${BIOMODELCALCEXE} "${TEST_DATA_ROOT}/Dose/DICOM/ConstantTwo.dcm" "dicom" "LQ" "0.1 0.01" +"${TEST_DATA_ROOT}/BioModel/Images/simpleReference.nrrd") +ADD_TEST(BioModelCalcParameterMapsTest ${BIOMODELCALC_TEST} BioModelCalcParameterMapsTest ${BIOMODELCALCEXE} "${TEST_DATA_ROOT}/Dose/DICOM/ConstantTwo.dcm" "dicom" "LQ" + "${TEST_DATA_ROOT}/Dose/DICOM/LinearIncrease3D.dcm ${TEST_DATA_ROOT}/Dose/DICOM/LinearIncrease3D.dcm" "dicom" "${TEST_DATA_ROOT}/BioModel/Images/parameterMapsReference.nrrd") + +RTTB_CREATE_APPLICATION_TESTS(BioModelCalc DEPENDS RTTBITKIO PACKAGE_DEPENDS Litmus ITK BoostBinaries) diff --git a/testing/apps/BioModelCalc/files.cmake b/testing/apps/BioModelCalc/files.cmake new file mode 100644 index 0000000..3d747c5 --- /dev/null +++ b/testing/apps/BioModelCalc/files.cmake @@ -0,0 +1,9 @@ +SET(CPP_FILES + BioModelCalcSimpleTest.cpp + BioModelCalcInvalidParametersTest.cpp + BioModelCalcParameterMapsTest.cpp + BioModelCalcTests.cpp + ) + +SET(H_FILES +) diff --git a/testing/apps/CMakeLists.txt b/testing/apps/CMakeLists.txt index 60492b6..4b00235 100644 --- a/testing/apps/CMakeLists.txt +++ b/testing/apps/CMakeLists.txt @@ -1,21 +1,24 @@ MESSAGE (STATUS "Process All apps Tests...") #----------------------------------------------------------------------------- # Include sub directories #----------------------------------------------------------------------------- IF(BUILD_App_DoseTool) ADD_SUBDIRECTORY (DoseTool) ENDIF(BUILD_App_DoseTool) IF(BUILD_App_VoxelizerTool) ADD_SUBDIRECTORY (VoxelizerTool) ENDIF(BUILD_App_VoxelizerTool) IF(BUILD_App_DoseMap) ADD_SUBDIRECTORY (DoseMap) ENDIF() +IF(BUILD_App_BioModelCalc) + ADD_SUBDIRECTORY (BioModelCalc) +ENDIF() IF(BUILD_App_DoseAcc) ADD_SUBDIRECTORY (DoseAcc) ENDIF() \ No newline at end of file diff --git a/testing/models/LQModelAccessorTest.cpp b/testing/models/LQModelAccessorTest.cpp index 5524047..f1d0cfc 100644 --- a/testing/models/LQModelAccessorTest.cpp +++ b/testing/models/LQModelAccessorTest.cpp @@ -1,136 +1,143 @@ // ----------------------------------------------------------------------- // 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$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "litCheckMacros.h" #include #include "rttbLQModelAccessor.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbInvalidDoseException.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { /*! @brief LQModelAccessorTest. - 1) Test constructor + 1) Test constructors 2) Test getGeometricInfo() 3) Test getValueAt() */ int LQModelAccessorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME_CONSTANT_TWO; std::string RTDOSE_FILENAME_INCREASE_X; if (argc > 2) { RTDOSE_FILENAME_CONSTANT_TWO = argv[1]; RTDOSE_FILENAME_INCREASE_X = argv[2]; } else { std::cout << "at least two parameters for LQModelAccessorTest are expected" << std::endl; return -1; } typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1( RTDOSE_FILENAME_CONSTANT_TWO.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2( RTDOSE_FILENAME_INCREASE_X.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); core::GeometricInfo doseAccessor1GeometricInfo = doseAccessor1->getGeometricInfo(); core::GeometricInfo doseAccessor2GeometricInfo = doseAccessor2->getGeometricInfo(); DoseAccessorPointer doseAccessorNull; - core::AccessorInterface::AccessorPointer LQWithConstantDose; - core::AccessorInterface::AccessorPointer LQWithConstantDoseDoseScalingTwo; - core::AccessorInterface::AccessorPointer LQWithIncreaseXDose; + core::AccessorInterface::AccessorPointer LQWithConstantDose, LQWithConstantDoseDoseScalingTwo, LQWithIncreaseXDose, LQWithConstantDoseAndMap; //1) test constructor CHECK_THROW_EXPLICIT(models::LQModelAccessor(doseAccessorNull, 0, 0), core::InvalidDoseException); CHECK_THROW_EXPLICIT(models::LQModelAccessor(doseAccessor1, 0.2, 0.02, -1), core::InvalidParameterException); + CHECK_THROW_EXPLICIT(models::LQModelAccessor(doseAccessorNull, doseAccessorNull, doseAccessorNull), core::InvalidDoseException); CHECK_NO_THROW(LQWithConstantDose = boost::make_shared(doseAccessor1, 0.2, 0.02)); CHECK_NO_THROW(LQWithConstantDoseDoseScalingTwo = boost::make_shared (doseAccessor1, 0.2, 0.02, 2.0)); CHECK_NO_THROW(LQWithIncreaseXDose = boost::make_shared(doseAccessor2, 0.3, 0.01)); + CHECK_NO_THROW(LQWithConstantDoseAndMap = boost::make_shared(doseAccessor1, + doseAccessor2, doseAccessor2)); //2) Test getGeometricInfo() CHECK_EQUAL(LQWithConstantDose->getGeometricInfo(), doseAccessor1GeometricInfo); CHECK_EQUAL(LQWithIncreaseXDose->getGeometricInfo(), doseAccessor2GeometricInfo); //3) Test getValueAt() models::BioModelParamType expectedLQWithDoseTwo = exp(-(0.2 * 2 + (0.02 * 2 * 2))); CHECK_EQUAL(LQWithConstantDose->getValueAt(0), expectedLQWithDoseTwo); CHECK_EQUAL(LQWithConstantDose->getValueAt(LQWithConstantDose->getGridSize() - 1), expectedLQWithDoseTwo); CHECK_EQUAL(LQWithConstantDose->getValueAt(VoxelGridIndex3D(1, 2, 6)), expectedLQWithDoseTwo); CHECK_EQUAL(LQWithConstantDose->getValueAt(VoxelGridIndex3D(65, 40, 60)), expectedLQWithDoseTwo); models::BioModelParamType expectedLQWithDoseFour = exp(-(0.2 * 4 + (0.02 * 4 * 4))); CHECK_EQUAL(LQWithConstantDoseDoseScalingTwo->getValueAt(0), expectedLQWithDoseFour); CHECK_EQUAL(LQWithConstantDoseDoseScalingTwo->getValueAt(LQWithConstantDose->getGridSize() - 1), expectedLQWithDoseFour); CHECK_EQUAL(LQWithConstantDoseDoseScalingTwo->getValueAt(VoxelGridIndex3D(1, 2, 6)), expectedLQWithDoseFour); CHECK_EQUAL(LQWithConstantDoseDoseScalingTwo->getValueAt(VoxelGridIndex3D(65, 40, 60)), expectedLQWithDoseFour); models::BioModelParamType expectedLQWithIncreaseX = exp(-(0.3 * 66 * 2.822386e-5 + (0.01 * 66 * 2.822386e-5 * 66 * 2.822386e-5))); CHECK_EQUAL(LQWithIncreaseXDose->getValueAt(0), 1); CHECK_CLOSE(LQWithIncreaseXDose->getValueAt(LQWithIncreaseXDose->getGridSize() - 1), expectedLQWithIncreaseX, errorConstant); expectedLQWithIncreaseX = exp(-(0.3 * 1 * 2.822386e-5 + (0.01 * 1 * 2.822386e-5 * 1 * 2.822386e-5))); CHECK_CLOSE(LQWithIncreaseXDose->getValueAt(VoxelGridIndex3D(1, 2, 6)), expectedLQWithIncreaseX, errorConstant); expectedLQWithIncreaseX = exp(-(0.3 * 45 * 2.822386e-5 + (0.01 * 45 * 2.822386e-5 * 45 * 2.822386e-5))); CHECK_CLOSE(LQWithIncreaseXDose->getValueAt(VoxelGridIndex3D(45, 40, 60)), expectedLQWithIncreaseX, errorConstant); + models::BioModelParamType expectedLQWithDoseAndMap = exp(-(66 * 2.822386e-5 * 2 + (66 * 2.822386e-5 * 2 * 2))); + CHECK_EQUAL(LQWithConstantDoseAndMap->getValueAt(0), 1); + CHECK_CLOSE(LQWithConstantDoseAndMap->getValueAt(LQWithIncreaseXDose->getGridSize() - 1), + expectedLQWithDoseAndMap, errorConstant); + CHECK_EQUAL(LQWithConstantDoseAndMap->getValueAt(0), LQWithConstantDoseAndMap->getValueAt(VoxelGridIndex3D(0, 0, 0))); + RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file