diff --git a/code/io/CMakeLists.txt b/code/io/CMakeLists.txt index 917cfcb..612e52d 100644 --- a/code/io/CMakeLists.txt +++ b/code/io/CMakeLists.txt @@ -1,21 +1,27 @@ MESSAGE (STATUS "processing RTToolbox io") ADD_SUBDIRECTORY (other) OPTION(BUILD_IO_Dicom "Determine if the IO class wrappers for DICOM format will be generated." OFF) IF(BUILD_IO_Dicom) ADD_SUBDIRECTORY(dicom) OPTION(BUILD_IO_HELAX "Determine if the IO class wrappers for HELAX format will be generated." OFF) IF(BUILD_IO_HELAX) ADD_SUBDIRECTORY(helax) ENDIF(BUILD_IO_HELAX) ENDIF(BUILD_IO_Dicom) OPTION(BUILD_IO_ITK "Determine if the IO class wrappers for ITK image formats will be generated." OFF) IF(BUILD_IO_ITK) ADD_SUBDIRECTORY(itk) ENDIF(BUILD_IO_ITK) OPTION(BUILD_IO_Virtuos "Determine if the IO class wrappers for Virtuos format will be generated." OFF) IF(BUILD_IO_Virtuos) ADD_SUBDIRECTORY(virtuos) ENDIF(BUILD_IO_Virtuos) + +OPTION(BUILD_IO_Mask "Determine if the IO class wrappers for Mask Image will be generated." OFF) +IF(BUILD_IO_Mask) + ADD_SUBDIRECTORY(mask) +ENDIF(BUILD_IO_Mask) + diff --git a/code/io/mask/CMakeLists.txt b/code/io/mask/CMakeLists.txt new file mode 100644 index 0000000..c200743 --- /dev/null +++ b/code/io/mask/CMakeLists.txt @@ -0,0 +1 @@ +RTTB_CREATE_MODULE(RTTBMaskIO DEPENDS RTTBCore PACKAGE_DEPENDS Boost MatchPoint ITK) \ No newline at end of file diff --git a/code/io/mask/files.cmake b/code/io/mask/files.cmake new file mode 100644 index 0000000..e02dd40 --- /dev/null +++ b/code/io/mask/files.cmake @@ -0,0 +1,11 @@ +SET(CPP_FILES + rttbITKImageMaskAccessor.cpp + rttbITKImageMaskAccessorGenerator.cpp + rttbITKImageMaskAccessorConverter.cpp + ) + +SET(H_FILES + rttbITKImageMaskAccessor.h + rttbITKImageMaskAccessorGenerator.h + rttbITKImageMaskAccessorConverter.h +) diff --git a/code/io/mask/rttbITKImageMaskAccessor.cpp b/code/io/mask/rttbITKImageMaskAccessor.cpp new file mode 100644 index 0000000..5a63d4c --- /dev/null +++ b/code/io/mask/rttbITKImageMaskAccessor.cpp @@ -0,0 +1,173 @@ +// ----------------------------------------------------------------------- +// 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 "rttbITKImageMaskAccessor.h" +#include "rttbException.h" +#include "rttbInvalidDoseException.h" + +namespace rttb +{ + namespace io + { + namespace mask + { + ITKImagMaskAccessor::ITKImagMaskAccessor(ITKDoseImageType::ConstPointer aMaskImage) + : _mask(aMaskImage) + { + if (_mask.IsNull()) + { + throw core::InvalidDoseException("Dose image = 0!") ; + } + + assembleGeometricInfo(); + } + + + ITKImagMaskAccessor::~ITKImagMaskAccessor() + { + }; + + bool ITKImagMaskAccessor::assembleGeometricInfo() + { + _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 dicom dose!") ; + } + + return true; + + } + + + void ITKImagMaskAccessor::updateMask() + { + return; + } + + ITKImagMaskAccessor::MaskVoxelListPointer ITKImagMaskAccessor::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; + } + + ITKImagMaskAccessor::MaskVoxelListPointer ITKImagMaskAccessor::getRelevantVoxelVector(float lowerThreshold) + { + MaskVoxelListPointer filteredVoxelVectorPointer(new MaskVoxelList); + updateMask(); + // filter relevant voxels + ITKImagMaskAccessor::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 ITKImagMaskAccessor::getMaskAt(VoxelGridID aID, core::MaskVoxel& voxel) const + { + VoxelGridIndex3D aVoxelGridIndex; + + if (_geoInfo->convert(aID, aVoxelGridIndex)) + { + return getMaskAt(aVoxelGridIndex, voxel); + } + else + { + return false; + } + + } + + bool ITKImagMaskAccessor::getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const + { + voxel.setRelevantVolumeFraction(0); + + if (_geoInfo->validIndex(aIndex)) + { + const ITKDoseImageType::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& ITKImagMaskAccessor::getGeometricInfo() const + { + return *_geoInfo; + }; + } + } +} + diff --git a/code/io/mask/rttbITKImageMaskAccessor.h b/code/io/mask/rttbITKImageMaskAccessor.h new file mode 100644 index 0000000..ed2b6da --- /dev/null +++ b/code/io/mask/rttbITKImageMaskAccessor.h @@ -0,0 +1,121 @@ +// ----------------------------------------------------------------------- +// 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) +*/ +#ifndef __ITK_IMAGE_MASK_ACCESSOR_H +#define __ITK_IMAGE_MASK_ACCESSOR_H + +#include + +#include + +#include "rttbMaskAccessorInterface.h" +#include "rttbGeometricInfo.h" +#include "rttbBaseType.h" + +#include "itkImage.h" + +namespace rttb +{ + namespace io + { + namespace mask + { + + /*! @class ITKImageMaskAccessor + @brief This class gives access to mask information stored in an itk image + @details _doseGridScaling is always 1.0. Thus, it is assumed that the values in the itkImage are absolute. + */ + class ITKImagMaskAccessor: public core::MaskAccessorInterface + { + public: + typedef ::itk::Image ITKDoseImageType; + typedef ::itk::ImageBase<3> ITKImageBaseType; + typedef core::MaskAccessorInterface::MaskVoxelList MaskVoxelList; + typedef core::MaskAccessorInterface::MaskVoxelListPointer MaskVoxelListPointer; + + typedef boost::shared_ptr GeometricInfoPtr; + + private: + + /** @brief The mask as itkImage */ + ITKDoseImageType::ConstPointer _mask; + + IDType _maskUID; + + GeometricInfoPtr _geoInfo; + + /*! vector containing list of mask voxels*/ + MaskVoxelListPointer _spRelevantVoxelVector; + + /*! @brief get all required data from the itk image contained in _dose + @exception InvalidDoseException if PixelSpacing is 0 or size in any dimension is 0. + */ + bool assembleGeometricInfo(); + + + public: + + ~ITKImagMaskAccessor(); + + // import of structure sets (loading from data) is done elsewhere. Structures are only voxelized here. + // here the original RTToolbox voxelization shall be implemented + ITKImagMaskAccessor(ITKDoseImageType::ConstPointer aMaskImage); + + /*! @brief voxelization of the given structures according to the original RTToolbox algorithm*/ + void updateMask(); + + /*! @brief get vector conatining al relevant voxels that are inside the given structure*/ + MaskVoxelListPointer getRelevantVoxelVector(); + /*! @brief get vector conatining al relevant voxels that have a relevant volume above the given threshold and are inside the given structure*/ + MaskVoxelListPointer getRelevantVoxelVector(float lowerThreshold); + + /*!@brief determine how a given voxel on the dose grid is masked + * @param aID ID of the voxel in grid. + * @param voxel Reference to the voxel. + * @post after a valid call voxel containes the information of the specified grid voxel. If aID is not valid, voxel values are undefined. + * The relevant volume fraction will be set to zero. + * @return Indicates of the voxel exists and therefore if parameter voxel containes valid values.*/ + bool getMaskAt(const VoxelGridID aID, core::MaskVoxel& voxel) const; + + bool getMaskAt(const VoxelGridIndex3D& aIndex, core::MaskVoxel& voxel) const; + + /*! @brief give access to GeometricInfo*/ + const core::GeometricInfo& getGeometricInfo() const; + + /* @ brief is true if dose is on a homogeneous grid */ + // Inhomogeneous grids are not supported at the moment, but if they will + // be supported in the future the interface does not need to change. + bool isGridHomogeneous() const + { + return true; + }; + + IDType getMaskUID() const + { + return _maskUID; + }; + + }; + + } + } +} + +#endif diff --git a/code/io/mask/rttbITKImageMaskAccessorConverter.cpp b/code/io/mask/rttbITKImageMaskAccessorConverter.cpp new file mode 100644 index 0000000..cf0b123 --- /dev/null +++ b/code/io/mask/rttbITKImageMaskAccessorConverter.cpp @@ -0,0 +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: 747 $ (last changed revision) +// @date $Date: 2014-09-17 12:01:00 +0200 (Mi, 17 Sep 2014) $ (last change date) +// @author $Author: hentsch $ (last changed by) +*/ + +#include + +#include + +#include "rttbITKImageMaskAccessorConverter.h" +#include "rttbException.h" +#include "rttbInvalidDoseException.h" +#include "rttbGeometricInfo.h" + +namespace rttb +{ + namespace io + { + namespace mask + { + + + + }//end namespace mask + }//end namespace io +}//end namespace rttb + diff --git a/code/io/mask/rttbITKImageMaskAccessorConverter.h b/code/io/mask/rttbITKImageMaskAccessorConverter.h new file mode 100644 index 0000000..f4986ef --- /dev/null +++ b/code/io/mask/rttbITKImageMaskAccessorConverter.h @@ -0,0 +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: 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) +*/ +#ifndef __ITK_IMAGE_MASK_ACCESSOR_CONVERTER_H +#define __ITK_IMAGE_MASK_ACCESSOR_CONVERTER_H + +#include + +#include "rttbITKImageMaskAccessor.h" + +namespace rttb +{ + namespace io + { + namespace mask + { + + class ITKImageMaskAccessorConverter + { + + }; + } + } +} +#endif diff --git a/code/io/mask/rttbITKImageMaskAccessorGenerator.cpp b/code/io/mask/rttbITKImageMaskAccessorGenerator.cpp new file mode 100644 index 0000000..d9bcdb4 --- /dev/null +++ b/code/io/mask/rttbITKImageMaskAccessorGenerator.cpp @@ -0,0 +1,40 @@ +// ----------------------------------------------------------------------- +// 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 "rttbITKImageMaskAccessorGenerator.h" +#include "rttbException.h" +#include "rttbInvalidDoseException.h" + + +namespace rttb{ + namespace io{ + namespace mask{ + + + }//end namespace mask + }//end namespace io +}//end namespace rttb + diff --git a/code/io/mask/rttbITKImageMaskAccessorGenerator.h b/code/io/mask/rttbITKImageMaskAccessorGenerator.h new file mode 100644 index 0000000..d4fc4e4 --- /dev/null +++ b/code/io/mask/rttbITKImageMaskAccessorGenerator.h @@ -0,0 +1,48 @@ +// ----------------------------------------------------------------------- +// 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) +*/ +#ifndef __ITK_IMAGE_MASK_ACCESSOR_GENERATOR_H +#define __ITK_IMAGE_MASK_ACCESSOR_GENERATOR_H + +#include +#include + +#include "rttbDoseAccessorGeneratorBase.h" +#include "rttbBaseType.h" +#include "rttbITKImageMaskAccessor.h" + +#include "itkImage.h" + +namespace rttb +{ + namespace io + { + namespace mask + { + + class ITKImageMaskAccessorGenerator + { + + }; + } + } +} + +#endif