diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index f4e1f76..a178888 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,59 +1,62 @@ MESSAGE(STATUS "processing RTToolbox apps") IF (WIN32) IF (MSVC_VERSION LESS 1800) MESSAGE(FATAL_ERROR "Some features of RTToolbox requires C++11 features that require Visual Studio 2013 or higher.") ENDIF(MSVC_VERSION LESS 1800) ENDIF(WIN32) #extract and build ArgumentParsingLib include(ExternalProject) message(STATUS "ArgumentParsingLib will be automatically downloaded and built.") set(ArgumentParsingLib_SOURCE_DIR "${CMAKE_BINARY_DIR}/external/ArgumentParsingLib-src") set(ArgumentParsingLib_BUILD_DIR "${CMAKE_BINARY_DIR}/external/ArgumentParsingLib-build") set(ArgumentParsingLib_CMAKE_DIR "${CMAKE_BINARY_DIR}/external/ArgumentParsingLib-cmake") ExternalProject_Add( ArgumentParsingLib URL ${RTToolbox_SOURCE_DIR}/utilities/ArgumentParsingLib/ArgumentParsingLib.tar.gz SOURCE_DIR ${ArgumentParsingLib_SOURCE_DIR} BINARY_DIR ${ArgumentParsingLib_BUILD_DIR} PREFIX ${ArgumentParsingLib_CMAKE_DIR} INSTALL_COMMAND "" UPDATE_COMMAND "" CMAKE_ARGS -DBUILD_TESTS:BOOL=OFF -DBoost_INCLUDE_DIR:STRING=${Boost_INCLUDE_DIR} -DBoost_DIR:STRING=${Boost_DIR} ) -OPTION(BUILD_App_DoseAcc "Determine if the application DoseAcc will be generated." OFF) -IF(BUILD_App_DoseAcc AND BUILD_IO_Virtuos) +OPTION(BUILD_App_DoseAcc "Determine if the demo application DoseAcc will be generated." OFF) +IF(BUILD_App_DoseAcc) ADD_SUBDIRECTORY(DoseAcc) + IF(RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) + ADD_SUBDIRECTORY(DoseAcc4V) + ENDIF() ENDIF() OPTION(BUILD_App_DoseMap "Determine if the application DoseMap will be generated." OFF) IF(BUILD_App_DoseMap AND BUILD_IO_Virtuos) ADD_SUBDIRECTORY(DoseMap) ENDIF() -OPTION(BUILD_App_DoseTool "Determine if the demo application DoseTool will be generated." OFF) +OPTION(BUILD_App_DoseTool "Determine if the application DoseTool will be generated." OFF) IF(BUILD_App_DoseTool) ADD_SUBDIRECTORY(DoseTool) IF(RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) ADD_SUBDIRECTORY(DoseTool4V) ENDIF() ENDIF(BUILD_App_DoseTool) OPTION(BUILD_App_VoxelizerTool "Determine if the application VoxelizerTool will be generated." OFF) IF(BUILD_App_VoxelizerTool) ADD_SUBDIRECTORY(VoxelizerTool) ENDIF(BUILD_App_VoxelizerTool) OPTION(BUILD_App_BioModelCalc "Determine if the demo application BioModelCalc will be generated." OFF) IF(BUILD_App_BioModelCalc) ADD_SUBDIRECTORY(BioModelCalc) IF(RTTB_VIRTUOS_SUPPORT AND BUILD_IO_Virtuos) ADD_SUBDIRECTORY(BioModelCalc4V) ENDIF() ENDIF(BUILD_App_BioModelCalc) \ No newline at end of file diff --git a/apps/DoseAcc/CMakeLists.txt b/apps/DoseAcc/CMakeLists.txt index 7e20818..52b17ad 100644 --- a/apps/DoseAcc/CMakeLists.txt +++ b/apps/DoseAcc/CMakeLists.txt @@ -1,3 +1,3 @@ MESSAGE (STATUS "generating demo app: DoseAcc - simple dose accumulation tool example") -RTTB_CREATE_APPLICATION(DoseAcc DEPENDS RTTBCore RTTBAlgorithms RTTBInterpolation RTTBInterpolationMatchPointTransformation RTTBITKIO RTTBVirtuosIO RTTBDicomIO RTTBHelaxIO PACKAGE_DEPENDS ArgumentParsingLib MatchPoint ITK) \ No newline at end of file +RTTB_CREATE_APPLICATION(DoseAcc DEPENDS RTTBCore RTTBAlgorithms RTTBInterpolation RTTBInterpolationMatchPointTransformation RTTBITKIO RTTBDicomIO RTTBHelaxIO PACKAGE_DEPENDS ArgumentParsingLib MatchPoint ITK) \ No newline at end of file diff --git a/apps/DoseAcc/DoseAcc.cpp b/apps/DoseAcc/DoseAcc.cpp index 7877b04..bb3a334 100644 --- a/apps/DoseAcc/DoseAcc.cpp +++ b/apps/DoseAcc/DoseAcc.cpp @@ -1,171 +1,171 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1107 $ (last changed revision) // @date $Date: 2015-09-17 12:47:41 +0200 (Do, 17 Sep 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseAccApplicationData.h" #include "DoseAccHelper.h" #include "DoseAccCmdLineParser.h" #include "boost/shared_ptr.hpp" #include "boost/make_shared.hpp" #include "RTToolboxConfigure.h" rttb::apps::doseAcc::ApplicationData appData; int main(int argc, const char** argv) { int result = 0; boost::shared_ptr argParser; try { std::string appName = "DoseAcc"; std::string appVersion = RTTB_FULL_VERSION_STRING; argParser = boost::make_shared(argc, argv, appName, - appVersion, true); + appVersion, false); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return 5; } // This is vital. The application needs to exit if the "help" or "version" parameter is set // because this means the other parameters won't be parsed. if (argParser->isSet(argParser->OPTION_HELP) || argParser->isSet(argParser->OPTION_VERSION)) { return 0; } rttb::apps::doseAcc::populateAppData(argParser, appData); std::cout << std::endl << "*******************************************" << std::endl; std::cout << "Dose 1 file: " << appData._dose1FileName << std::endl; std::cout << "Dose 2 file: " << appData._dose2FileName << std::endl; std::cout << "Dose output file: " << appData._outputFileName << std::endl; if (!(appData._regFileName.empty())) { std::cout << "Registration file: " << appData._regFileName << std::endl; } std::cout << "Dose 1 weight: " << appData._weightDose1 << std::endl; std::cout << "Dose 2 weight: " << appData._weightDose2 << std::endl; std::cout << "Operator: " << appData._operator << std::endl; try { appData._dose1 = rttb::apps::doseAcc::loadDose(appData._dose1FileName, appData._dose1LoadStyle); } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; return 4; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 4; } catch (...) { std::cerr << "Error!!! unknown error while reading input image." << std::endl; return 4; } try { appData._dose2 = rttb::apps::doseAcc::loadDose(appData._dose2FileName, appData._dose2LoadStyle); } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; return 4; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 4; } catch (...) { std::cerr << "Error!!! unknown error while reading input image." << std::endl; return 4; } if (!(appData._regFileName.empty())) { try { appData._spReg = rttb::apps::doseAcc::loadRegistration(appData._regFileName); } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; return 5; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 5; } catch (...) { std::cerr << "Error!!! unknown error while reading registration file." << std::endl; return 5; } } try { rttb::apps::doseAcc::processData(appData); } catch (::itk::ExceptionObject& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e << std::endl; return 9; } catch (std::exception& e) { std::cerr << "Error!!!" << std::endl; std::cerr << e.what() << std::endl; return 9; } catch (...) { std::cerr << "Error!!! unknown error while mapping and writing image." << std::endl; return 9; } std::cout << std::endl; return result; } diff --git a/apps/DoseAcc/DoseAccCmdLineParser.cpp b/apps/DoseAcc/DoseAccCmdLineParser.cpp index 3130c4d..6788b1e 100644 --- a/apps/DoseAcc/DoseAccCmdLineParser.cpp +++ b/apps/DoseAcc/DoseAccCmdLineParser.cpp @@ -1,167 +1,167 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ /*! // @file // @version $Revision: 1374 $ (last changed revision) // @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseAccCmdLineParser.h" namespace rttb { namespace apps { namespace doseAcc { DoseAccCmdLineParser::DoseAccCmdLineParser(int argc, const char** argv, const std::string& name, const std::string& version, bool virtuosSupport) : CmdLineParserBase(name, version), _virtuosSupport(virtuosSupport) { addOption(OPTION_DOSE1_FILENAME, OPTION_GROUP_REQUIRED, "File path to the first dose.", 'd', true); addOption(OPTION_DOSE2_FILENAME, OPTION_GROUP_REQUIRED, "File path to the second dose.", 'e', true); addOption(OPTION_OUTPUT_FILENAME, OPTION_GROUP_REQUIRED, "File path where the output should be stored.", 'o', true); addOptionWithDefaultValue(OPTION_INTERPOLATOR, OPTION_GROUP_REQUIRED, "Specifies the interpolator that should be used for mapping. Available options are: " "\"nn\": nearest neighbour, \"linear\": linear interpolation, \"rosu\" interpolation based on the concept of Rosu et al..", "linear", "linear", 'i', true); addOptionWithDefaultValue(OPTION_WEIGHT1, OPTION_GROUP_REQUIRED, "Specifies the weight for dose 1.", 1.0, "1.0", 'w', true); addOptionWithDefaultValue(OPTION_WEIGHT2, OPTION_GROUP_REQUIRED, "Specifies the weight for dose 2.", 1.0, "1.0", 'z', true); addOptionWithDefaultValue(OPTION_REGISTRATION_FILENAME, OPTION_GROUP_REQUIRED, "Specifies name and location of the registration file that should be used to map dose 2 before accumulating it with dose 1." "The registration should be stored as MatchPoint registration.", "", "no mapping", 'r', true); std::vector defaultLoadingStyle; defaultLoadingStyle.push_back("dicom"); std::string doseLoadStyleDescription = "Options are:\n \"dicom\": normal dicom dose\n" "\"itk\": use itk image loading\n\"helax\": load a helax dose (choosing this style, the dose path should only be a directory)."; if (_virtuosSupport) { doseLoadStyleDescription += "\n" "\"virtuos\": load of a virtuos dose (This style is a multi argument. The second argument specifies the virtuos plan file, e.g. : \"--" + OPTION_LOAD_STYLE_DOSE1 + " or " + OPTION_LOAD_STYLE_DOSE2 + " virtuos myFavorite.pln\")"; } addOptionWithDefaultValue >(OPTION_LOAD_STYLE_DOSE1, OPTION_GROUP_REQUIRED, "Load style for dose 1. "+ doseLoadStyleDescription, defaultLoadingStyle, defaultLoadingStyle.at(0), 't', true, true); addOptionWithDefaultValue >(OPTION_LOAD_STYLE_DOSE2, OPTION_GROUP_REQUIRED, "Load style for dose 2. See " + OPTION_LOAD_STYLE_DOSE1, defaultLoadingStyle, defaultLoadingStyle.at(0), 'u', true, true); addOptionWithDefaultValue(OPTION_OPERATOR, OPTION_GROUP_REQUIRED, "Specifies the operator used. Available operators are '+' and '*'.", "+", "+", 'p', true); addPositionalOption(OPTION_DOSE1_FILENAME, 1); addPositionalOption(OPTION_DOSE2_FILENAME, 1); addPositionalOption(OPTION_OUTPUT_FILENAME, 1); parse(argc, argv); } void DoseAccCmdLineParser::validateInput() const { std::vector doseLoadStyle1 = get >(OPTION_LOAD_STYLE_DOSE1); std::string doseLoadStyleAbbreviation1 = doseLoadStyle1.at(0); if (doseLoadStyleAbbreviation1 != "dicom" && (!_virtuosSupport || doseLoadStyleAbbreviation1 != "virtuos") && doseLoadStyleAbbreviation1 != "itk" && doseLoadStyleAbbreviation1 != "helax") { throw cmdlineparsing::InvalidConstraintException("Unknown load style for dose1 file: " + doseLoadStyleAbbreviation1 + ".\nPlease refer to the help for valid loading style settings."); } if (_virtuosSupport && doseLoadStyleAbbreviation1 == "virtuos") { if (doseLoadStyle1.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io style argument."); } } std::vector doseLoadStyle2 = get >(OPTION_LOAD_STYLE_DOSE2); std::string doseLoadStyleAbbreviation2 = doseLoadStyle2.at(0); if (doseLoadStyleAbbreviation2 != "dicom" && (!_virtuosSupport || doseLoadStyleAbbreviation2 != "virtuos") && doseLoadStyleAbbreviation2 != "itk" && doseLoadStyleAbbreviation2 != "helax") { throw cmdlineparsing::InvalidConstraintException("Unknown load style for dose2 file: " + doseLoadStyleAbbreviation2 + ".\nPlease refer to the help for valid loading style settings."); } if (_virtuosSupport && doseLoadStyleAbbreviation2 == "virtuos") { if (doseLoadStyle2.size() < 2) { throw cmdlineparsing::InvalidConstraintException("Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io style argument."); } } std::string interpolator = get(OPTION_INTERPOLATOR); if (interpolator != "nn" && interpolator != "linear" && interpolator != "rosu") { throw cmdlineparsing::InvalidConstraintException("Unknown interpolator: " + interpolator + ".\nPlease refer to the help for valid interpolator settings."); } std::string operatorString = get(OPTION_OPERATOR); if (operatorString != "+" && operatorString != "*") { throw cmdlineparsing::InvalidConstraintException("Unknown operator: " + operatorString + ".\nPlease refer to the help for valid operator settings."); } } void DoseAccCmdLineParser::printHelp() const { cmdlineparsing::CmdLineParserBase::printHelp(); std::cout << " Example:" << std::endl << std::endl; std::cout << " DoseAcc dose1.mhd dose2.mhd result.mhd --" + OPTION_LOAD_STYLE_DOSE1 + " itk --" + OPTION_LOAD_STYLE_DOSE2 + " itk --" + OPTION_WEIGHT1 + " 2 -r reg.mapr" << std::endl << std::endl; std::cout << " This will accumulate \"dose1.mhd\" and \"dose2.mhd\" by using \"reg.mapr\" to map dose 2."; std::cout << " For the accumulation, dose 1 will be multiplied by 2. The resulting dose will be stored in \"result.mhd\"." << std::endl << std::endl; if (_virtuosSupport){ std::cout << " DoseAcc dose1.dcm dose2.dos.gz result.mhd --" + OPTION_LOAD_STYLE_DOSE2 + " virtuos dose2.pln -r reg.mapr" << std::endl << std::endl; std::cout << " This will accumulate \"dose1.dcm\" (using default dicom io) and \"dose2.dos.gz\" (using virtuos io and plan file dose2.pln)"; - std::cout << "by using \"reg.mapr\" to map dose 2. The resulting dose will be stored in \"result.mhd\"." << std::endl; + std::cout << " by using \"reg.mapr\" to map dose 2. The resulting dose will be stored in \"result.mhd\"." << std::endl; } } } } } diff --git a/apps/DoseAcc/DoseAccHelper.cpp b/apps/DoseAcc/DoseAccHelper.cpp index 4e43317..ee7f05e 100644 --- a/apps/DoseAcc/DoseAccHelper.cpp +++ b/apps/DoseAcc/DoseAccHelper.cpp @@ -1,266 +1,246 @@ // ----------------------------------------------------------------------- // 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: 1132 $ (last changed revision) // @date $Date: 2015-10-06 14:48:56 +0200 (Di, 06 Okt 2015) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "DoseAccHelper.h" #include "mapRegistrationFileReader.h" #include "itkImageFileWriter.h" #include "rttbExceptionMacros.h" -#include "rttbVirtuosPlanFileDoseAccessorGenerator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomHelaxFileDoseAccessorGenerator.h" #include "rttbITKImageAccessorConverter.h" #include "rttbSimpleMappableDoseAccessor.h" #include "rttbMatchPointTransformation.h" #include "rttbLinearInterpolation.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbRosuMappableDoseAccessor.h" #include "rttbITKImageFileAccessorGenerator.h" #include "rttbArithmetic.h" #include "rttbBinaryFunctorAccessor.h" rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseAcc::loadDose(const std::string& fileName, const rttb::apps::doseAcc::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 if (args[0] == "virtuos") - { - if (args.size() < 2) - { - rttbDefaultExceptionStaticMacro( << - "Cannot load virtuos dose. Plan file is missing. Specify plan file as 2nd io stlye argument."); - } - - std::cout << "use RTTB virtuos IO... " << std::endl; - std::cout << " virtuos plan file: " << args[1] << " ... "; - result = loadVirtuosDose(fileName, args[1]); - } 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::doseAcc::loadDicomDose(const std::string& fileName) { rttb::io::dicom::DicomFileDoseAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseAcc::loadHelaxDose(const std::string& path) { rttb::io::helax::DicomHelaxFileDoseAccessorGenerator generator(path); return generator.generateDoseAccessor(); }; rttb::core::DoseAccessorInterface::DoseAccessorPointer rttb::apps::doseAcc::loadITKDose(const std::string& fileName) { rttb::io::itk::ITKImageFileAccessorGenerator generator(fileName); return generator.generateDoseAccessor(); }; -rttb::core::DoseAccessorInterface::DoseAccessorPointer -rttb::apps::doseAcc::loadVirtuosDose(const std::string& fileName, const std::string& planFileName) -{ - rttb::io::virtuos::VirtuosPlanFileDoseAccessorGenerator generator(fileName, planFileName); - return generator.generateDoseAccessor(); -}; - rttb::apps::doseAcc::ApplicationData::RegistrationType::Pointer rttb::apps::doseAcc::loadRegistration(const std::string& fileName) { map::io::RegistrationFileReader::Pointer spRegReader = map::io::RegistrationFileReader::New(); map::io::RegistrationFileReader::LoadedRegistrationPointer spReg; std::cout << std::endl << "read registration file... "; spReg = spRegReader->read(fileName); std::cout << "done." << std::endl; ApplicationData::RegistrationType::Pointer resultPtr = dynamic_cast(spReg.GetPointer()); if (resultPtr.IsNull()) { rttbDefaultExceptionStaticMacro( << "Loaded registration cannot be used. Only 3D 3D registrations are allowed."); } return resultPtr; }; rttb::core::DoseAccessorInterface::DoseAccessorPointer generateNNMappableAccessor( const rttb::core::GeometricInfo& geoInfoTargetImage, const rttb::core::DoseAccessorInterface::DoseAccessorPointer doseMovingImage, const rttb::interpolation::TransformationInterface::Pointer aTransformation) { rttb::interpolation::InterpolationBase::Pointer interpolate = rttb::interpolation::NearestNeighborInterpolation::Pointer(new rttb::interpolation::NearestNeighborInterpolation()); return rttb::core::DoseAccessorInterface::DoseAccessorPointer( new rttb::interpolation::SimpleMappableDoseAccessor(geoInfoTargetImage, doseMovingImage, aTransformation, interpolate)); } rttb::core::DoseAccessorInterface::DoseAccessorPointer generateLinearMappableAccessor( const rttb::core::GeometricInfo& geoInfoTargetImage, const rttb::core::DoseAccessorInterface::DoseAccessorPointer doseMovingImage, const rttb::interpolation::TransformationInterface::Pointer aTransformation) { rttb::interpolation::InterpolationBase::Pointer interpolate = rttb::interpolation::LinearInterpolation::Pointer(new rttb::interpolation::LinearInterpolation()); return rttb::core::DoseAccessorInterface::DoseAccessorPointer( new rttb::interpolation::SimpleMappableDoseAccessor(geoInfoTargetImage, doseMovingImage, aTransformation, interpolate)); } rttb::core::DoseAccessorInterface::DoseAccessorPointer generateRosuMappableAccessor( const rttb::core::GeometricInfo& geoInfoTargetImage, const rttb::core::DoseAccessorInterface::DoseAccessorPointer doseMovingImage, const rttb::interpolation::TransformationInterface::Pointer aTransformation) { return rttb::core::DoseAccessorInterface::DoseAccessorPointer( new rttb::interpolation::RosuMappableDoseAccessor(geoInfoTargetImage, doseMovingImage, aTransformation)); } /**Private helper function for processData(). Generates a suitable output accessor * (depending on the configuration in appData a suitable accessor pipeline is established) * which performs the accumulation of the doses and returns the output.to */ rttb::core::DoseAccessorInterface::DoseAccessorPointer assembleOutputAccessor(rttb::apps::doseAcc::ApplicationData& appData) { rttb::core::DoseAccessorInterface::DoseAccessorPointer dose2Accessor = appData._dose2; if (appData._spReg.IsNotNull()) { rttb::interpolation::TransformationInterface::Pointer transform = rttb::interpolation::TransformationInterface::Pointer(new rttb::interpolation::MatchPointTransformation(appData._spReg)); if (appData._interpolatorName == "rosu") { dose2Accessor = generateRosuMappableAccessor(appData._dose1->getGeometricInfo(), appData._dose2, transform); } else if (appData._interpolatorName == "nn") { dose2Accessor = generateNNMappableAccessor(appData._dose1->getGeometricInfo(), appData._dose2, transform); } else if (appData._interpolatorName == "linear") { dose2Accessor = generateLinearMappableAccessor(appData._dose1->getGeometricInfo(), appData._dose2, transform); } else { rttbDefaultExceptionStaticMacro( << "Unkown interpolation type selected. Cannot map dose. Interpolation type: " << appData._interpolatorName); } } rttb::core::DoseAccessorInterface::DoseAccessorPointer outputAccessor; if (appData._operator == "+") { rttb::algorithms::arithmetic::doseOp::AddWeighted addOp(appData._weightDose1, appData._weightDose2); outputAccessor = rttb::core::DoseAccessorInterface::DoseAccessorPointer(new rttb::algorithms::BinaryFunctorAccessor (appData._dose1, dose2Accessor, addOp)); } else if (appData._operator == "*") { outputAccessor = rttb::core::DoseAccessorInterface::DoseAccessorPointer(new rttb::algorithms::BinaryFunctorAccessor (appData._dose1, dose2Accessor, rttb::algorithms::arithmetic::doseOp::Multiply())); } else { rttbDefaultExceptionStaticMacro( << "Unkown operator selected. Cannot map dose. Operator: " << appData._interpolatorName); } return outputAccessor; } void rttb::apps::doseAcc::processData(rttb::apps::doseAcc::ApplicationData& appData) { rttb::core::DoseAccessorInterface::DoseAccessorPointer outputAccessor = assembleOutputAccessor( appData); std::cout << std::endl << "generate output image... "; io::itk::ITKImageAccessorConverter converter(outputAccessor); converter.setFailOnInvalidIDs(true); converter.process(); io::itk::ITKImageAccessorConverter::ITKImageType::Pointer itkImage = converter.getITKImage(); std::cout << "done." << std::endl; typedef ::itk::ImageFileWriter WriterType; std::cout << std::endl << "write output image... "; WriterType::Pointer writer = WriterType::New(); writer->SetInput(itkImage); writer->SetFileName(appData._outputFileName); writer->SetUseCompression(true); writer->Write(); std::cout << "done." << std::endl; }; diff --git a/apps/DoseAcc4V/CMakeLists.txt b/apps/DoseAcc4V/CMakeLists.txt new file mode 100644 index 0000000..c1074fb --- /dev/null +++ b/apps/DoseAcc4V/CMakeLists.txt @@ -0,0 +1,7 @@ +MESSAGE (STATUS "generating app: DoseAcc4V - simple dose accumulation tool with Virtuos") +SET(RTTB_Boost_ADDITIONAL_COMPONENT program_options) +RTTB_CREATE_APPLICATION(DoseAcc4V DEPENDS RTTBCore RTTBAlgorithms RTTBInterpolation RTTBInterpolationMatchPointTransformation RTTBITKIO RTTBVirtuosIO RTTBDicomIO RTTBHelaxIO PACKAGE_DEPENDS ArgumentParsingLib MatchPoint ITK) +IF (NOT WIN32) + #CMake 3.1 provides target_compile_features(RTTB_Interpolation cxx_auto_type cxx_nullptr cxx_override) to automatically add required compiler flags + set(CMAKE_CXX_FLAGS "-std=c++11 -fpermissive") +ENDIF() diff --git a/apps/DoseAcc4V/DoseAcc4V.cpp b/apps/DoseAcc4V/DoseAcc4V.cpp new file mode 100644 index 0000000..a2d5438 --- /dev/null +++ b/apps/DoseAcc4V/DoseAcc4V.cpp @@ -0,0 +1,174 @@ +// ----------------------------------------------------------------------- +// RTToolbox - DKFZ radiotherapy quantitative evaluation library +// +// Copyright (c) German Cancer Research Center (DKFZ), +// Software development for Integrated Diagnostics and Therapy (SIDT). +// ALL RIGHTS RESERVED. +// See rttbCopyright.txt or +// http://www.dkfz.de/en/sidt/projects/rttb/copyright.html +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notices for more information. +// +//------------------------------------------------------------------------ +/*! +// @file +// @version $Revision: 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 "../DoseAcc/DoseAccApplicationData.h" +#include "../DoseAcc/DoseAccHelper.h" +#include "../DoseAcc/DoseAccCmdLineParser.h" +#include "../DoseTool4V/DoseTool4VHelper.h" + +#include "boost/shared_ptr.hpp" +#include "boost/make_shared.hpp" + +#include "RTToolboxConfigure.h" + +#include "rttbException.h" + +rttb::apps::doseAcc::ApplicationData appData; + +int main(int argc, const char** argv) +{ + int result = 0; + + boost::shared_ptr argParser; + + try + { + std::string appName = "DoseAcc"; + 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::doseAcc::populateAppData(argParser, appData); + + std::cout << std::endl << "*******************************************" << std::endl; + std::cout << "Dose 1 file: " << appData._dose1FileName << std::endl; + std::cout << "Dose 2 file: " << appData._dose2FileName << std::endl; + std::cout << "Dose output file: " << appData._outputFileName << std::endl; + + if (!(appData._regFileName.empty())) + { + std::cout << "Registration file: " << appData._regFileName << std::endl; + } + + std::cout << "Dose 1 weight: " << appData._weightDose1 << std::endl; + std::cout << "Dose 2 weight: " << appData._weightDose2 << std::endl; + std::cout << "Operator: " << appData._operator << std::endl; + + try + { + appData._dose1 = rttb::apps::doseTool4V::loadDose(appData._dose1FileName, appData._dose1LoadStyle); + } + catch (::itk::ExceptionObject& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e << std::endl; + return 4; + } + catch (std::exception& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 4; + } + catch (...) + { + std::cerr << "Error!!! unknown error while reading input image." << std::endl; + return 4; + } + + try + { + appData._dose2 = rttb::apps::doseTool4V::loadDose(appData._dose2FileName, appData._dose2LoadStyle); + } + catch (::itk::ExceptionObject& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e << std::endl; + return 4; + } + catch (std::exception& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 4; + } + catch (...) + { + std::cerr << "Error!!! unknown error while reading input image." << std::endl; + return 4; + } + + if (!(appData._regFileName.empty())) + { + try + { + appData._spReg = rttb::apps::doseAcc::loadRegistration(appData._regFileName); + } + catch (::itk::ExceptionObject& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e << std::endl; + return 5; + } + catch (std::exception& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 5; + } + catch (...) + { + std::cerr << "Error!!! unknown error while reading registration file." << std::endl; + return 5; + } + } + + try + { + rttb::apps::doseAcc::processData(appData); + } + catch (::itk::ExceptionObject& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e << std::endl; + return 9; + } + catch (std::exception& e) + { + std::cerr << "Error!!!" << std::endl; + std::cerr << e.what() << std::endl; + return 9; + } + catch (...) + { + std::cerr << "Error!!! unknown error while mapping and writing image." << std::endl; + return 9; + } + + std::cout << std::endl; + + return result; +} diff --git a/apps/DoseAcc4V/files.cmake b/apps/DoseAcc4V/files.cmake new file mode 100644 index 0000000..8e3eac2 --- /dev/null +++ b/apps/DoseAcc4V/files.cmake @@ -0,0 +1,13 @@ +SET(CPP_FILES +DoseAcc4V.cpp +../DoseTool4V/DoseTool4VHelper.cpp +../DoseAcc/DoseAccHelper.cpp +../DoseAcc/DoseAccApplicationData.cpp +../DoseAcc/DoseAccCmdLineParser.cpp +) + +SET(H_FILES +../DoseTool4V/DoseTool4VHelper.h +../DoseAcc/DoseAccApplicationData.h +../DoseAcc/DoseAccCmdLineParser.h +) diff --git a/contributors.txt b/contributors.txt index ce7e423..22a5417 100644 --- a/contributors.txt +++ b/contributors.txt @@ -1,6 +1,8 @@ * Lanlan Zhang * Sarah Mang * Ralf Floca * Martina Hub * Clemens Hentschke -* Simon Strubel \ No newline at end of file +* Simon Strubel +* Fabrizio Ciccarese +* Melanie Braun \ No newline at end of file diff --git a/testing/apps/CMakeLists.txt b/testing/apps/CMakeLists.txt index 79b699d..60492b6 100644 --- a/testing/apps/CMakeLists.txt +++ b/testing/apps/CMakeLists.txt @@ -1,17 +1,21 @@ 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_DoseAcc) + ADD_SUBDIRECTORY (DoseAcc) +ENDIF() \ No newline at end of file diff --git a/testing/apps/DoseAcc/CMakeLists.txt b/testing/apps/DoseAcc/CMakeLists.txt new file mode 100644 index 0000000..172740a --- /dev/null +++ b/testing/apps/DoseAcc/CMakeLists.txt @@ -0,0 +1,29 @@ +#----------------------------------------------------------------------------- +# Setup the system information test. Write out some basic failsafe +# information in case the test doesn't run. +#----------------------------------------------------------------------------- + + +SET(DOSEACC_TEST ${EXECUTABLE_OUTPUT_PATH}/rttbDoseAccTests) + +SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) + +SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) + + +#----------------------------------------------------------------------------- + +IF(MSVC) + ADD_DEFINITIONS(/bigobj) +ENDIF() + +IF (WIN32) + SET(DOSEACCEXE "DoseAcc.exe") +ELSE (WIN32) + SET(DOSEACCEXE "./DoseAcc") +ENDIF (WIN32) + +ADD_TEST(DoseAccInvalidParametersTest ${DOSEACC_TEST} DoseAccInvalidParametersTest ${DOSEACCEXE}) +ADD_TEST(DoseAccSimpleTest ${DOSEACC_TEST} DoseAccSimpleTest ${DOSEACCEXE} "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwo.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantFifty.dcm" "${TEST_DATA_ROOT}/ITK/doseAccReference.nrrd") + +RTTB_CREATE_APPLICATION_TESTS(DoseAcc DEPENDS RTTBITKIO PACKAGE_DEPENDS Litmus ITK BoostBinaries) diff --git a/testing/apps/DoseAcc/DoseAccInvalidParametersTest.cpp b/testing/apps/DoseAcc/DoseAccInvalidParametersTest.cpp new file mode 100644 index 0000000..13bcf17 --- /dev/null +++ b/testing/apps/DoseAcc/DoseAccInvalidParametersTest.cpp @@ -0,0 +1,97 @@ +// ----------------------------------------------------------------------- +// 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 DoseAccInvalidParametersTest(int argc, char* argv[]) + { + PREPARE_DEFAULT_TEST_REPORTING; + + std::string doseAccExecutable; + + if (argc > 1) + { + doseAccExecutable = argv[1]; + } + + boost::filesystem::path callingPath(_callingAppPath); + std::string doseAccExeWithPath = callingPath.parent_path().string() + "/" + doseAccExecutable; + + //call with too few parameters + std::string toofewParametersCommand = doseAccExeWithPath; + toofewParametersCommand += " test"; + std::cout << "Command line call: " + toofewParametersCommand << std::endl; + CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); + + toofewParametersCommand = doseAccExeWithPath; + toofewParametersCommand += " test test"; + std::cout << "Command line call: " + toofewParametersCommand << std::endl; + CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); + + toofewParametersCommand = doseAccExeWithPath; + toofewParametersCommand += " -d test"; + toofewParametersCommand += " -e test"; + std::cout << "Command line call: " + toofewParametersCommand << std::endl; + CHECK_EQUAL(system(toofewParametersCommand.c_str()) != 0, true); + + std::string minimalCLI = doseAccExeWithPath + " test test test "; + + //call with invalid interpolator + + std::string invalidInterpolatorOption = minimalCLI; + invalidInterpolatorOption += "-i wrongInterpolator"; + std::cout << "Command line call: " + invalidInterpolatorOption << std::endl; + CHECK_EQUAL(system(invalidInterpolatorOption.c_str()) != 0, true); + + //call with invalid operator + std::string invalidOperatorOption = minimalCLI; + invalidOperatorOption += "-p -"; + std::cout << "Command line call: " + invalidOperatorOption << std::endl; + CHECK_EQUAL(system(invalidOperatorOption.c_str()) != 0, true); + + //call with invalid dose1 load option + std::string invalidDose1LoadOption = minimalCLI; + invalidDose1LoadOption += "-t invalidLoadStyleOption"; + std::cout << "Command line call: " + invalidDose1LoadOption << std::endl; + CHECK_EQUAL(system(invalidDose1LoadOption.c_str()) != 0, true); + + //call with invalid dose2 load option + std::string invalidDose2LoadOption = minimalCLI; + invalidDose2LoadOption += "-u invalidLoadStyleOption"; + std::cout << "Command line call: " + invalidDose2LoadOption << std::endl; + CHECK_EQUAL(system(invalidDose2LoadOption.c_str()) != 0, true); + + RETURN_AND_REPORT_TEST_SUCCESS; + } + } //namespace testing +} //namespace rttb diff --git a/testing/apps/DoseAcc/DoseAccSimpleTest.cpp b/testing/apps/DoseAcc/DoseAccSimpleTest.cpp new file mode 100644 index 0000000..56f0d45 --- /dev/null +++ b/testing/apps/DoseAcc/DoseAccSimpleTest.cpp @@ -0,0 +1,97 @@ +// ----------------------------------------------------------------------- +// 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 DoseAccSimpleTest(int argc, char* argv[]) + { + PREPARE_DEFAULT_TEST_REPORTING; + + std::string doseAccExecutable; + std::string dose1Filename; + std::string dose2Filename; + std::string referenceFilename; + + boost::filesystem::path callingPath(_callingAppPath); + + + if (argc > 4) + { + doseAccExecutable = argv[1]; + dose1Filename = argv[2]; + dose2Filename = argv[3]; + referenceFilename = argv[4]; + } + + std::string doseAccExeWithPath = callingPath.parent_path().string() + "/" + doseAccExecutable; + + std::string defaultOutputFilename = "doseAccOutput.nrrd"; + + std::string baseCommand = doseAccExeWithPath; + baseCommand += " -d " + dose1Filename; + baseCommand += " -e " + dose2Filename; + baseCommand += " -o " + defaultOutputFilename; + + std::string defaultDoseAccCommand = baseCommand + " --weight1 2.0"; + std::cout << "Command line call: " + defaultDoseAccCommand << std::endl; + CHECK_EQUAL(system(defaultDoseAccCommand.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/DoseAcc/DoseAccTests.cpp b/testing/apps/DoseAcc/DoseAccTests.cpp new file mode 100644 index 0000000..aba4b58 --- /dev/null +++ b/testing/apps/DoseAcc/DoseAccTests.cpp @@ -0,0 +1,70 @@ +// ----------------------------------------------------------------------- +// RTToolbox - DKFZ radiotherapy quantitative evaluation library +// +// Copyright (c) German Cancer Research Center (DKFZ), +// Software development for Integrated Diagnostics and Therapy (SIDT). +// ALL RIGHTS RESERVED. +// See rttbCopyright.txt or +// http://www.dkfz.de/en/sidt/projects/rttb/copyright.html +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notices for more information. +// +//------------------------------------------------------------------------ +/*! +// @file +// @version $Revision: 1374 $ (last changed revision) +// @date $Date: 2016-05-30 14:15:42 +0200 (Mo, 30 Mai 2016) $ (last change date) +// @author $Author: hentsch $ (last changed by) +*/ + +// 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(DoseAccInvalidParametersTest); + LIT_REGISTER_TEST(DoseAccSimpleTest); + } + + } //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/DoseAcc/files.cmake b/testing/apps/DoseAcc/files.cmake new file mode 100644 index 0000000..cb2ae19 --- /dev/null +++ b/testing/apps/DoseAcc/files.cmake @@ -0,0 +1,8 @@ +SET(CPP_FILES + DoseAccSimpleTest.cpp + DoseAccInvalidParametersTest.cpp + DoseAccTests.cpp + ) + +SET(H_FILES +)