diff --git a/apps/BioModelCalc/BioModelCalc.cpp b/apps/BioModelCalc/BioModelCalc.cpp index 875c8de..2cf06b3 100644 --- a/apps/BioModelCalc/BioModelCalc.cpp +++ b/apps/BioModelCalc/BioModelCalc.cpp @@ -1,145 +1,148 @@ // ----------------------------------------------------------------------- // 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; + 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_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 217744e..a732d3b 100644 --- a/apps/BioModelCalc/BioModelCalcApplicationData.cpp +++ b/apps/BioModelCalc/BioModelCalcApplicationData.cpp @@ -1,66 +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: 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(); } void ApplicationData:: reset() { _doseFileName = ""; _outputFileName = ""; _doseScaling = 1.0; + _nFractions = 1; _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); 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); + } + if (argParser->isSet(argParser->OPTION_N_FRACTIONS)){ + appData._nFractions = argParser->get(argParser->OPTION_N_FRACTIONS); } } } } } diff --git a/apps/BioModelCalc/BioModelCalcApplicationData.h b/apps/BioModelCalc/BioModelCalcApplicationData.h index ddda668..31375f3 100644 --- a/apps/BioModelCalc/BioModelCalcApplicationData.h +++ b/apps/BioModelCalc/BioModelCalcApplicationData.h @@ -1,72 +1,73 @@ // ----------------------------------------------------------------------- // 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; + unsigned int _nFractions; std::string _outputFileName; std::string _model; std::vector _modelParameters; std::vector _modelParameterMapsFilename; 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 fe3da7d..deae45e 100644 --- a/apps/BioModelCalc/BioModelCalcHelper.cpp +++ b/apps/BioModelCalc/BioModelCalcHelper.cpp @@ -1,154 +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... "; rttb::core::AccessorInterface::AccessorPointer bioModelAccessor; if (!appData._modelParameters.empty()){ - bioModelAccessor = generateBioModel(appData._dose, appData._model, appData._modelParameters, + bioModelAccessor = generateBioModel(appData._dose, appData._model, appData._modelParameters, appData._nFractions, appData._doseScaling); } else { - bioModelAccessor = generateBioModelWithMaps(appData._dose, appData._model, appData._modelParameterMaps, + bioModelAccessor = generateBioModelWithMaps(appData._dose, appData._model, appData._modelParameterMaps, appData._nFractions, 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) + const std::vector& modelParameters, unsigned int nFractions, double doseScaling) { if (model == "LQ") { return boost::make_shared(dose, modelParameters.at(0), - modelParameters.at(1), + modelParameters.at(1), nFractions, 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) + const std::vector& modelParameterMaps, unsigned int nFractions, double doseScaling) { if (model == "LQ") { return boost::make_shared(dose, modelParameterMaps.at(0), - modelParameterMaps.at(1), doseScaling); + modelParameterMaps.at(1), nFractions, 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 3a5315a..479db6c 100644 --- a/apps/BioModelCalc/BioModelCalcHelper.h +++ b/apps/BioModelCalc/BioModelCalcHelper.h @@ -1,79 +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); + const std::vector& modelParameters, unsigned int nFractions=1, 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); + const std::vector& modelParameterMaps, unsigned int nFractions=1, double doseScaling = 1.0); } } } #endif diff --git a/apps/BioModelCalc/BioModelCmdLineParser.cpp b/apps/BioModelCalc/BioModelCmdLineParser.cpp index ef4360e..30c65ef 100644 --- a/apps/BioModelCalc/BioModelCmdLineParser.cpp +++ b/apps/BioModelCalc/BioModelCmdLineParser.cpp @@ -1,120 +1,122 @@ #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\"", + "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); 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'); 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 (!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 132b55d..94bd76f 100644 --- a/apps/BioModelCalc/BioModelCmdLineParser.h +++ b/apps/BioModelCalc/BioModelCmdLineParser.h @@ -1,44 +1,45 @@ #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"; + const std::string OPTION_N_FRACTIONS = "nFractions"; bool _virtuosSupport; }; } } } #endif \ No newline at end of file diff --git a/code/models/rttbDoseBasedModels.cpp b/code/models/rttbDoseBasedModels.cpp index c2559dc..51f935c 100644 --- a/code/models/rttbDoseBasedModels.cpp +++ b/code/models/rttbDoseBasedModels.cpp @@ -1,42 +1,42 @@ // ----------------------------------------------------------------------- // 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 "rttbDoseBasedModels.h" #include "rttbInvalidParameterException.h" #include namespace rttb { namespace models { - rttb::models::BioModelValueType calcLQ(const DoseTypeGy dose, const DoseCalcType alpha, - const DoseCalcType beta) + rttb::models::BioModelValueType calcLQ(DoseTypeGy dose, DoseCalcType alpha, + DoseCalcType beta, unsigned int nFractions) { if (dose < 0 || alpha < 0 || beta < 0) { throw core::InvalidParameterException("Parameter invalid: dose, alpha, beta must be >=0!"); } - return exp(-((alpha * dose) + (beta * dose * dose))); + return exp(-((alpha * dose) + (beta * dose * dose / DoseCalcType(nFractions)))); } } } \ No newline at end of file diff --git a/code/models/rttbDoseBasedModels.h b/code/models/rttbDoseBasedModels.h index 6f93287..f09103d 100644 --- a/code/models/rttbDoseBasedModels.h +++ b/code/models/rttbDoseBasedModels.h @@ -1,43 +1,43 @@ // ----------------------------------------------------------------------- // 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 "rttbBaseType.h" #include "rttbBaseTypeModels.h" namespace rttb { namespace models { /*! @brief Calculate biological LinearQuadratic Model of a dose @details LQ = exp(-(alpha*d+beta*d^2)) @param dose @param alpha @param beta @pre dose>=0 @pre alpha>=0 @pre beta>=0 @return The LQ value @exception InvalidParameterException Thrown if parameters were not set correctly. */ - BioModelValueType calcLQ(const DoseTypeGy dose, const DoseCalcType alpha, - const DoseCalcType beta); + BioModelValueType calcLQ(DoseTypeGy dose, DoseCalcType alpha, + DoseCalcType beta, unsigned int nFractions=1); } } \ No newline at end of file diff --git a/code/models/rttbLQModelAccessor.cpp b/code/models/rttbLQModelAccessor.cpp index f2a7caf..51a231a 100644 --- a/code/models/rttbLQModelAccessor.cpp +++ b/code/models/rttbLQModelAccessor.cpp @@ -1,100 +1,105 @@ // ----------------------------------------------------------------------- // 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" +#include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace models { LQModelAccessor::~LQModelAccessor() { } LQModelAccessor::LQModelAccessor(DoseAccessorPointer dose, BioModelParamType alpha, - BioModelParamType beta, + BioModelParamType beta, unsigned int nFractions, double doseScaling) : - _dose(dose), _alpha(alpha), _beta(beta), _betaMap(nullptr), _alphaMap(nullptr), _doseScaling(doseScaling), _withAlphaBetaMaps(false) + _dose(dose), _alpha(alpha), _beta(beta), _nFractions(nFractions), _betaMap(nullptr), _alphaMap(nullptr), _doseScaling(doseScaling), _withAlphaBetaMaps(false) { - if (_dose == NULL) + if (_dose == nullptr) { - throw core::InvalidDoseException("Dose is NULL"); + throw core::InvalidDoseException("Dose is nullptr"); } 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) + LQModelAccessor::LQModelAccessor(DoseAccessorPointer dose, DoseAccessorPointer alphaMap, DoseAccessorPointer betaMap, unsigned int nFractions, + double doseScaling) :_dose(dose), _alpha(-1.), _beta(-1.), _nFractions(nFractions), _betaMap(alphaMap), _alphaMap(betaMap), _doseScaling(doseScaling), _withAlphaBetaMaps(true) { - if (_dose == NULL || _alphaMap == nullptr || _betaMap == nullptr) + if (_dose == nullptr || _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 { - if (_withAlphaBetaMaps){ - return calcLQ(_dose->getValueAt(aID) * _doseScaling, _alphaMap->getValueAt(aID), _betaMap->getValueAt(aID)); + VoxelGridIndex3D aVoxelGridIndex3D; + + if (_geoInfo.convert(aID, aVoxelGridIndex3D)) + { + return getValueAt(aVoxelGridIndex3D); } - else { - return calcLQ(_dose->getValueAt(aID) * _doseScaling, _alpha, _beta); + else + { + throw core::MappingOutsideOfImageException("Error in conversion from index to world coordinates"); } } GenericValueType LQModelAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const { if (_withAlphaBetaMaps){ - return calcLQ(_dose->getValueAt(aIndex) * _doseScaling, _alphaMap->getValueAt(aIndex), _betaMap->getValueAt(aIndex)); + return calcLQ(_dose->getValueAt(aIndex) * _doseScaling, _alphaMap->getValueAt(aIndex), _betaMap->getValueAt(aIndex), _nFractions); } else { - return calcLQ(_dose->getValueAt(aIndex) * _doseScaling, _alpha, _beta); + return calcLQ(_dose->getValueAt(aIndex) * _doseScaling, _alpha, _beta, _nFractions); } } bool LQModelAccessor::assembleGeometricInfo() { _geoInfo = _dose->getGeometricInfo(); return true; } } } diff --git a/code/models/rttbLQModelAccessor.h b/code/models/rttbLQModelAccessor.h index 22e5546..933ea7d 100644 --- a/code/models/rttbLQModelAccessor.h +++ b/code/models/rttbLQModelAccessor.h @@ -1,92 +1,93 @@ // ----------------------------------------------------------------------- // 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; + unsigned int _nFractions; 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, + LQModelAccessor(DoseAccessorPointer dose, BioModelParamType alpha, BioModelParamType beta, unsigned int nFractions=1, 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, + LQModelAccessor(DoseAccessorPointer dose, DoseAccessorPointer alphaMap, DoseAccessorPointer betaMap, unsigned int nFractions = 1, 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/BioModelCalcParameterMapsTest.cpp b/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp index 927cee7..2c1c82e 100644 --- a/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp +++ b/testing/apps/BioModelCalc/BioModelCalcParameterMapsTest.cpp @@ -1,106 +1,102 @@ // ----------------------------------------------------------------------- // 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 index 6af6ab8..bd78caa 100644 --- a/testing/apps/BioModelCalc/BioModelCalcSimpleTest.cpp +++ b/testing/apps/BioModelCalc/BioModelCalcSimpleTest.cpp @@ -1,103 +1,130 @@ // ----------------------------------------------------------------------- // 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; + std::string referenceWithNFractionsFilename; boost::filesystem::path callingPath(_callingAppPath); - if (argc > 6) + if (argc > 7) { bioModelCalcExecutable = argv[1]; doseFilename = argv[2]; doseFilenameLoadStyle = argv[3]; modelName = argv[4]; modelArguments = argv[5]; referenceFilename = argv[6]; + referenceWithNFractionsFilename = argv[7]; } 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); + std::string defaultOutputWithNFractionsFilename = "bioModelWithNFractionsOutput.nrrd"; + std::string baseCommandWithNFractions = bioModelCalcExeWithPath; + baseCommandWithNFractions += " -d " + doseFilename; + baseCommandWithNFractions += " -t " + doseFilenameLoadStyle; + baseCommandWithNFractions += " -o " + defaultOutputWithNFractionsFilename; + baseCommandWithNFractions += " -m " + modelName; + baseCommandWithNFractions += " -p " + modelArguments; + baseCommandWithNFractions += " -f 2"; + + std::cout << "Command line call: " + baseCommandWithNFractions << std::endl; + CHECK_EQUAL(system(baseCommandWithNFractions.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); + CHECK_EQUAL(boost::filesystem::exists(defaultOutputWithNFractionsFilename), true); + + // Check result against reference + + TestImageType::Pointer referenceImageNFractions = io::itk::readITKDoubleImage(referenceWithNFractionsFilename); + TestImageType::Pointer outputImageNFractions = io::itk::readITKDoubleImage(defaultOutputWithNFractionsFilename); + + lit::ImageTester testerWithNFractions; + testerWithNFractions.setExpectedImage(referenceImageNFractions); + testerWithNFractions.setActualImage(outputImageNFractions); + testerWithNFractions.setCheckThreshold(0.0); + + CHECK_TESTER(testerWithNFractions); + + //CHECK_EQUAL(std::remove(defaultOutputWithNFractionsFilename.c_str()), 0); + RETURN_AND_REPORT_TEST_SUCCESS; } } //namespace testing } //namespace rttb diff --git a/testing/apps/BioModelCalc/CMakeLists.txt b/testing/apps/BioModelCalc/CMakeLists.txt index e6d1a50..17c5c7b 100644 --- a/testing/apps/BioModelCalc/CMakeLists.txt +++ b/testing/apps/BioModelCalc/CMakeLists.txt @@ -1,32 +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") +"${TEST_DATA_ROOT}/BioModel/Images/simpleReference.nrrd" "${TEST_DATA_ROOT}/BioModel/Images/simpleReferenceWithNFractions.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/models/LQModelAccessorTest.cpp b/testing/models/LQModelAccessorTest.cpp index f1d0cfc..b0457c3 100644 --- a/testing/models/LQModelAccessorTest.cpp +++ b/testing/models/LQModelAccessorTest.cpp @@ -1,143 +1,155 @@ // ----------------------------------------------------------------------- // 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 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, LQWithConstantDoseDoseScalingTwo, LQWithIncreaseXDose, LQWithConstantDoseAndMap; + core::AccessorInterface::AccessorPointer LQWithConstantDose, LQWithConstantDoseDoseScalingTwo, LQWithConstantNFractionsTwo, 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), + CHECK_THROW_EXPLICIT(models::LQModelAccessor(doseAccessor1, 0.2, 0.02, 1, -1), core::InvalidParameterException); CHECK_THROW_EXPLICIT(models::LQModelAccessor(doseAccessorNull, doseAccessorNull, doseAccessorNull), core::InvalidDoseException); + CHECK_THROW_EXPLICIT(models::LQModelAccessor(doseAccessor1, doseAccessor1, doseAccessorNull), core::InvalidDoseException); + CHECK_THROW_EXPLICIT(models::LQModelAccessor(doseAccessor1, doseAccessorNull, doseAccessor1), core::InvalidDoseException); + CHECK_THROW_EXPLICIT(models::LQModelAccessor(doseAccessorNull, doseAccessor1, doseAccessor1), core::InvalidDoseException); CHECK_NO_THROW(LQWithConstantDose = boost::make_shared(doseAccessor1, 0.2, 0.02)); + CHECK_NO_THROW(LQWithConstantNFractionsTwo = boost::make_shared(doseAccessor1, + 0.2, 0.02, 2)); CHECK_NO_THROW(LQWithConstantDoseDoseScalingTwo = boost::make_shared (doseAccessor1, - 0.2, 0.02, 2.0)); + 0.2, 0.02, 1, 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 expectedLQWithDoseTwoNFractionsTwo = exp(-(0.2 * 2 + (0.02 * 2 * 2/2))); + CHECK_EQUAL(LQWithConstantNFractionsTwo->getValueAt(0), expectedLQWithDoseTwoNFractionsTwo); + CHECK_EQUAL(LQWithConstantNFractionsTwo->getValueAt(LQWithConstantNFractionsTwo->getGridSize() - 1), + expectedLQWithDoseTwoNFractionsTwo); + CHECK_EQUAL(LQWithConstantNFractionsTwo->getValueAt(VoxelGridIndex3D(1, 2, 6)), expectedLQWithDoseTwoNFractionsTwo); + CHECK_EQUAL(LQWithConstantNFractionsTwo->getValueAt(VoxelGridIndex3D(65, 40, 60)), expectedLQWithDoseTwoNFractionsTwo); + 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