diff --git a/code/core/rttbMaskAccessorGeneratorBase.h b/code/core/rttbMaskAccessorGeneratorBase.h new file mode 100644 index 0000000..df7c5fc --- /dev/null +++ b/code/core/rttbMaskAccessorGeneratorBase.h @@ -0,0 +1,54 @@ +// ----------------------------------------------------------------------- +// 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: 707 $ (last changed revision) +// @date $Date: 2014-09-04 16:37:24 +0200 (Do, 04 Sep 2014) $ (last change date) +// @author $Author: floca $ (last changed by) +*/ +#ifndef __MASK_ACCESSOR_GENERATOR_BASE_H +#define __MASK_ACCESSOR_GENERATOR_BASE_H + +#include + +#include "rttbMaskAccessorGeneratorInterface.h" + +namespace rttb{ + namespace core + { + /*! @class MaskAccessorGeneratorBase + @brief Abstract class for all DoseAccessor generating classes + */ + class MaskAccessorGeneratorBase: public MaskAccessorGeneratorInterface + { + public: + typedef core::MaskAccessorInterface::MaskAccessorPointer MaskAccessorPointer; + + + private: + + + protected: + /*! @brief Mask accessor which should be generated */ + MaskAccessorPointer _maskAccessor; + + + public: + + }; + } + } + +#endif diff --git a/code/core/rttbMaskAccessorGeneratorInterface.h b/code/core/rttbMaskAccessorGeneratorInterface.h new file mode 100644 index 0000000..2176856 --- /dev/null +++ b/code/core/rttbMaskAccessorGeneratorInterface.h @@ -0,0 +1,60 @@ +// ----------------------------------------------------------------------- +// 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: 707 $ (last changed revision) +// @date $Date: 2014-09-04 16:37:24 +0200 (Do, 04 Sep 2014) $ (last change date) +// @author $Author: floca $ (last changed by) +*/ +#ifndef __MASK_ACCESSOR_GENERATOR_INTERFACE_H +#define __MASK_ACCESSOR_GENERATOR_INTERFACE_H + +#include + +#include "rttbMaskAccessorInterface.h" + +namespace rttb{ + namespace core + { + /*! @class MaskAccessorGeneratorInterface + @brief Interface for all MaskAccessor generating classes + */ + class MaskAccessorGeneratorInterface + { + public: + typedef core::MaskAccessorInterface::MaskAccessorPointer MaskAccessorPointer; + + + private: + MaskAccessorGeneratorInterface(const MaskAccessorGeneratorInterface&); //not implemented on purpose -> non-copyable + MaskAccessorGeneratorInterface& operator=(const MaskAccessorGeneratorInterface&);//not implemented on purpose -> non-copyable + + + protected: + MaskAccessorGeneratorInterface() {}; + virtual ~MaskAccessorGeneratorInterface() {}; + + public: + + + /*! @brief Generate MaskAccessor + @return Return shared pointer of MaskAccessor. + */ + virtual MaskAccessorPointer generateMaskAccessor() = 0; + }; + } + } + +#endif diff --git a/code/io/mask/files.cmake b/code/io/mask/files.cmake index d69f35f..a0cc7d6 100644 --- a/code/io/mask/files.cmake +++ b/code/io/mask/files.cmake @@ -1,14 +1,16 @@ SET(CPP_FILES rttbITKImageFileMaskAccessorGenerator.cpp rttbITKImageMaskAccessor.cpp rttbITKImageMaskAccessorGenerator.cpp rttbITKImageMaskAccessorConverter.cpp ) SET(H_FILES rttbITKImageFileMaskAccessorGenerator.h rttbITKImageFileMaskAccessorGenerator.tpp rttbITKImageMaskAccessor.h rttbITKImageMaskAccessorGenerator.h rttbITKImageMaskAccessorConverter.h + ../itk/rttbImageReader.h + ../itk/rttbImageReader.tpp ) diff --git a/code/io/mask/rttbITKImageMaskAccessor.cpp b/code/io/mask/rttbITKImageMaskAccessor.cpp index 3c2b8d4..400a465 100644 --- a/code/io/mask/rttbITKImageMaskAccessor.cpp +++ b/code/io/mask/rttbITKImageMaskAccessor.cpp @@ -1,173 +1,177 @@ // ----------------------------------------------------------------------- // 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: 793 $ (last changed revision) // @date $Date: 2014-10-10 10:24:45 +0200 (Fr, 10 Okt 2014) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include +#include +#include #include "rttbITKImageMaskAccessor.h" #include "rttbException.h" #include "rttbInvalidDoseException.h" namespace rttb { namespace io { namespace mask { ITKImageMaskAccessor::ITKImageMaskAccessor(ITKMaskImageType::ConstPointer aMaskImage) : _mask(aMaskImage) { if (_mask.IsNull()) { throw core::InvalidDoseException("Mask image = 0!") ; } assembleGeometricInfo(); } ITKImageMaskAccessor::~ITKImageMaskAccessor() { }; bool ITKImageMaskAccessor::assembleGeometricInfo() { + _geoInfo = boost::make_shared(); + _geoInfo->setSpacing(SpacingVectorType3D(_mask->GetSpacing()[0], _mask->GetSpacing()[1], _mask->GetSpacing()[2])); if (_geoInfo->getSpacing()[0] == 0 || _geoInfo->getSpacing()[1] == 0 || _geoInfo->getSpacing()[2] == 0) { throw core::InvalidDoseException("Pixel spacing = 0!"); } _geoInfo->setImagePositionPatient(WorldCoordinate3D(_mask->GetOrigin()[0], _mask->GetOrigin()[1], _mask->GetOrigin()[2])); OrientationMatrix OM(0); for (int col = 0; col < 3; ++col) { for (int row = 0; row < 3; ++row) { OM(col, row) = _mask->GetDirection()(col, row); } } _geoInfo->setOrientationMatrix(OM); _geoInfo->setNumColumns(_mask->GetLargestPossibleRegion().GetSize()[0]); _geoInfo->setNumRows(_mask->GetLargestPossibleRegion().GetSize()[1]); _geoInfo->setNumSlices(_mask->GetLargestPossibleRegion().GetSize()[2]); if (_geoInfo->getNumColumns() == 0 || _geoInfo->getNumRows() == 0 || _geoInfo->getNumSlices() == 0) { throw core::InvalidDoseException("Empty mask!") ; } return true; } void ITKImageMaskAccessor::updateMask() { return; } ITKImageMaskAccessor::MaskVoxelListPointer ITKImageMaskAccessor::getRelevantVoxelVector() { // if not already generated start voxelization here updateMask(); for(int gridIndex =0 ; gridIndex < _geoInfo->getNumColumns()*_geoInfo->getNumRows()*_geoInfo->getNumSlices(); gridIndex++){ core::MaskVoxel currentVoxel = core::MaskVoxel(gridIndex); if(getMaskAt(gridIndex, currentVoxel)){ if(currentVoxel.getRelevantVolumeFraction() > 0){ _spRelevantVoxelVector->push_back(currentVoxel); } } } return _spRelevantVoxelVector; } ITKImageMaskAccessor::MaskVoxelListPointer ITKImageMaskAccessor::getRelevantVoxelVector(float lowerThreshold) { MaskVoxelListPointer filteredVoxelVectorPointer(new MaskVoxelList); updateMask(); // filter relevant voxels ITKImageMaskAccessor::MaskVoxelList::iterator it = _spRelevantVoxelVector->begin(); while (it != _spRelevantVoxelVector->end()) { if ((*it).getRelevantVolumeFraction() > lowerThreshold) { filteredVoxelVectorPointer->push_back(*it); } ++it; } // if mask calculation was not successful this is empty! return filteredVoxelVectorPointer; } bool ITKImageMaskAccessor::getMaskAt(VoxelGridID aID, core::MaskVoxel& voxel) const { VoxelGridIndex3D aVoxelGridIndex; if (_geoInfo->convert(aID, aVoxelGridIndex)) { return getMaskAt(aVoxelGridIndex, voxel); } else { return false; } } bool ITKImageMaskAccessor::getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const { voxel.setRelevantVolumeFraction(0); if (_geoInfo->validIndex(aIndex)) { const ITKMaskImageType::IndexType pixelIndex = {{aIndex[0], aIndex[1], aIndex[2]}}; double value = _mask->GetPixel(pixelIndex); VoxelGridID gridId; _geoInfo->convert(aIndex, gridId); if(value >= 0 && value <=1 ){ voxel.setRelevantVolumeFraction(value); } else{ return false; } } else { return false; } } const core::GeometricInfo& ITKImageMaskAccessor::getGeometricInfo() const { return *_geoInfo; }; } } } diff --git a/testing/io/CMakeLists.txt b/testing/io/CMakeLists.txt index 7a2ce71..8a69dbe 100644 --- a/testing/io/CMakeLists.txt +++ b/testing/io/CMakeLists.txt @@ -1,26 +1,30 @@ MESSAGE (STATUS "Process All IO Tests...") #----------------------------------------------------------------------------- # Include sub directories #----------------------------------------------------------------------------- ADD_SUBDIRECTORY (other) IF(BUILD_IO_Dicom) ADD_SUBDIRECTORY(dicom) IF(BUILD_IO_HELAX) ADD_SUBDIRECTORY(helax) ENDIF(BUILD_IO_HELAX) ENDIF(BUILD_IO_Dicom) - IF(BUILD_IO_ITK) + IF(BUILD_IO_ITK) ADD_SUBDIRECTORY(itk) ENDIF(BUILD_IO_ITK) + + IF(BUILD_IO_Mask) + ADD_SUBDIRECTORY(mask) + ENDIF(BUILD_IO_Mask) IF(BUILD_IO_Virtuos) ADD_SUBDIRECTORY(virtuos) ENDIF(BUILD_IO_Virtuos) diff --git a/testing/io/mask/CMakeLists.txt b/testing/io/mask/CMakeLists.txt new file mode 100644 index 0000000..feff2ba --- /dev/null +++ b/testing/io/mask/CMakeLists.txt @@ -0,0 +1,26 @@ +#----------------------------------------------------------------------------- +# Setup the system information test. Write out some basic failsafe +# information in case the test doesn't run. +#----------------------------------------------------------------------------- + + +SET(MaskIO_TEST ${EXECUTABLE_OUTPUT_PATH}/rttbMaskIOTests) + +SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) + +SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) + + +#----------------------------------------------------------------------------- +ADD_TEST(MaskAccessorGeneratorTest ${MaskIO_TEST} MaskAccessorGeneratorTest +"${TEST_DATA_ROOT}/MatchPointLogo.mhd") + +ADD_TEST(MaskIOTest ${MaskIO_TEST} MaskIOTest +"${TEST_DATA_ROOT}/MatchPointLogo.mhd") + +ADD_TEST(MaskAccessorConverterTest ${MaskIO_TEST} MaskAccessorConverterTest + "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwo.dcm" "${TEST_DATA_ROOT}/MatchPointLogo.mhd" ) + + +RTTB_CREATE_TEST_MODULE(rttbMaskIO DEPENDS RTTBMaskIO RTTBDicomIO RTTBITKIO PACKAGE_DEPENDS Boost Litmus MatchPoint ITK DCMTK) + diff --git a/testing/io/mask/MaskAccessorConverterTest.cpp b/testing/io/mask/MaskAccessorConverterTest.cpp new file mode 100644 index 0000000..6857f59 --- /dev/null +++ b/testing/io/mask/MaskAccessorConverterTest.cpp @@ -0,0 +1,82 @@ +// ----------------------------------------------------------------------- +// 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: 793 $ (last changed revision) +// @date $Date: 2014-10-10 10:24:45 +0200 (Fr, 10 Okt 2014) $ (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 + +#include +#include + +#include "litCheckMacros.h" +#include "litImageTester.h" +#include "litTestImageIO.h" + +#include "itkImage.h" +#include "itkImageFileReader.h" + +#include "rttbBaseType.h" +#include "rttbDoseIteratorInterface.h" +#include "rttbDicomFileDoseAccessorGenerator.h" +#include "rttbDicomDoseAccessor.h" +#include "rttbInvalidDoseException.h" + + +namespace rttb +{ + + namespace testing + { + + /*!@brief MaskAccessorConverterTest - test the conversion rttb dose accessor ->itk + 1) test with dicom file (DicomDoseAccessorGenerator) + 2) test with mhd file (ITKImageFileDoseAccessorGenerator) + */ + + int MaskAccessorConverterTest(int argc, char* argv[]) + { + typedef core::DoseIteratorInterface::DoseAccessorPointer DoseAccessorPointer; + + PREPARE_DEFAULT_TEST_REPORTING; + //ARGUMENTS: + // 1: dose1 file name + // 2: dose2 file name + + std::string RTDOSE_FILENAME; + std::string RTDOSE2_FILENAME; + + if (argc > 1) + { + RTDOSE_FILENAME = argv[1]; + } + + if (argc > 2) + { + RTDOSE2_FILENAME = argv[2]; + } + + //1) Read dicomFile and test getITKImage() + + RETURN_AND_REPORT_TEST_SUCCESS; + } + + }//testing +}//rttb + diff --git a/testing/io/mask/MaskAccessorGeneratorTest.cpp b/testing/io/mask/MaskAccessorGeneratorTest.cpp new file mode 100644 index 0000000..e4d953e --- /dev/null +++ b/testing/io/mask/MaskAccessorGeneratorTest.cpp @@ -0,0 +1,94 @@ +// ----------------------------------------------------------------------- +// 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: 793 $ (last changed revision) +// @date $Date: 2014-10-10 10:24:45 +0200 (Fr, 10 Okt 2014) $ (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 + +#include +#include + +#include "litCheckMacros.h" + +#include "itkImage.h" +#include "itkImageFileReader.h" + +#include "rttbBaseType.h" +#include "rttbInvalidDoseException.h" +#include "rttbITKImageFileMaskAccessorGenerator.h" +#include "rttbITKImageMaskAccessorGenerator.h" + + +namespace rttb +{ + + namespace testing + { + + /*!@brief MaskAccessorGeneratorTest - test the generators for dicom data + 1) test itk file generator generateDoseAccessor() + 2) test itk generator generateDoseAccessor() + */ + + int MaskAccessorGeneratorTest(int argc, char* argv[]) + { + + PREPARE_DEFAULT_TEST_REPORTING; + //ARGUMENTS: + // 1: mhd/raw file name + + std::string Mask_FILENAME; + + if (argc > 1) + { + Mask_FILENAME = argv[1]; + } + + + /* test ITKFileDoseAccessorGenerator generateDoseAccessor()*/ + CHECK_THROW_EXPLICIT(io::mask::ITKImageFileMaskAccessorGenerator("test.test").generateMaskAccessor(), + core::InvalidDoseException); + CHECK_NO_THROW(io::mask::ITKImageFileMaskAccessorGenerator( + Mask_FILENAME.c_str()).generateMaskAccessor()); + + /* test ITKDoseAccessorGenerator generateDoseAccessor()*/ + typedef itk::Image< DoseTypeGy, 3 > MaskImageType; + typedef itk::ImageFileReader ReaderType; + + MaskImageType::ConstPointer invalidDose = MaskImageType::New(); + + ReaderType::Pointer reader = ReaderType::New(); + + CHECK_THROW_EXPLICIT(io::mask::ITKImageMaskAccessorGenerator( + invalidDose.GetPointer()).generateMaskAccessor(), core::InvalidDoseException); + + reader->SetFileName(Mask_FILENAME); + //important to update the reader (won't work without) + reader->Update(); + + CHECK_NO_THROW(io::mask::ITKImageMaskAccessorGenerator(reader->GetOutput()).generateMaskAccessor()); + + + RETURN_AND_REPORT_TEST_SUCCESS; + } + + }//testing +}//rttb + diff --git a/testing/io/mask/MaskIOTest.cpp b/testing/io/mask/MaskIOTest.cpp new file mode 100644 index 0000000..c4166c4 --- /dev/null +++ b/testing/io/mask/MaskIOTest.cpp @@ -0,0 +1,67 @@ +// ----------------------------------------------------------------------- +// 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: 793 $ (last changed revision) +// @date $Date: 2014-10-10 10:24:45 +0200 (Fr, 10 Okt 2014) $ (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 + +#include +#include + +#include "litCheckMacros.h" + +#include "rttbBaseType.h" +#include "rttbGeometricInfo.h" +#include "rttbDoseIteratorInterface.h" + + + +namespace rttb +{ + + namespace testing + { + + /*!@brief MaskIOTest - test the IO for mask data + + WARNING: The values for comparison need to be adjusted if the input files are changed! + */ + + int MaskIOTest(int argc, char* argv[]) + { + + PREPARE_DEFAULT_TEST_REPORTING; + //ARGUMENTS: + // 1: mhd file name + + std::string RTDOSE_FILENAME; + + if (argc > 1) + { + RTDOSE_FILENAME = argv[1]; + } + + + RETURN_AND_REPORT_TEST_SUCCESS; + } + + }//testing +}//rttb + diff --git a/testing/io/mask/files.cmake b/testing/io/mask/files.cmake new file mode 100644 index 0000000..ea8fc70 --- /dev/null +++ b/testing/io/mask/files.cmake @@ -0,0 +1,9 @@ +SET(CPP_FILES + MaskAccessorGeneratorTest.cpp + MaskAccessorConverterTest.cpp + MaskIOTest.cpp + rttbMaskIOTests.cpp + ) + +SET(H_FILES +) diff --git a/testing/io/mask/rttbMaskIOTests.cpp b/testing/io/mask/rttbMaskIOTests.cpp new file mode 100644 index 0000000..f146178 --- /dev/null +++ b/testing/io/mask/rttbMaskIOTests.cpp @@ -0,0 +1,60 @@ +// ----------------------------------------------------------------------- +// 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: 793 $ (last changed revision) +// @date $Date: 2014-10-10 10:24:45 +0200 (Fr, 10 Okt 2014) $ (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" + +namespace rttb{ + namespace testing{ + + void registerTests() + { + LIT_REGISTER_TEST(MaskAccessorGeneratorTest); + LIT_REGISTER_TEST(MaskAccessorConverterTest); + LIT_REGISTER_TEST(MaskIOTest); + } + } + } + +int main(int argc, char* argv[]) + { + int result = 0; + + rttb::testing::registerTests(); + + try + { + result = lit::multiTestsMain(argc,argv); + } + + catch(...) + { + result = -1; + } + + return result; + }