diff --git a/code/io/itk/files.cmake b/code/io/itk/files.cmake index 9c20e7c..ff05187 100644 --- a/code/io/itk/files.cmake +++ b/code/io/itk/files.cmake @@ -1,39 +1,41 @@ SET(CPP_FILES rttbFileDispatch.cpp rttbGenericImageReader.cpp rttbImageWriter.cpp rttbITKException.cpp rttbITKImageAccessor.cpp rttbITKImageAccessorConverter.cpp rttbITKImageAccessorGenerator.cpp rttbITKImageFileAccessorGenerator.cpp rttbITKImageFileMaskAccessorGenerator.cpp rttbITKImageMaskAccessor.cpp rttbITKImageMaskAccessorGenerator.cpp rttbITKImageMaskAccessorConverter.cpp rttbITKIOHelper.cpp itkDoseAccessorImageFilter.cpp + itkMaskAccessorImageSource.cpp ) SET(H_FILES rttbDoseAccessorConversionSettingInterface.h rttbDoseAccessorProcessorBase.h rttbDoseAccessorProcessorInterface.h rttbFileDispatch.h rttbGenericImageReader.h rttbImageReader.h rttbImageReader.tpp rttbImageWriter.h rttbITKException.h rttbITKImageAccessor.h rttbITKImageAccessorConverter.h rttbITKImageAccessorGenerator.h rttbITKImageFileAccessorGenerator.h rttbITKImageFileMaskAccessorGenerator.h rttbITKImageMaskAccessor.h rttbITKImageMaskAccessorConverter.h rttbITKImageMaskAccessorGenerator.h rttbITKIOHelper.h rttbITKIOHelper.tpp itkDoseAccessorImageFilter.h + itkMaskAccessorImageSource.h ) diff --git a/code/io/itk/itkMaskAccessorImageSource.cpp b/code/io/itk/itkMaskAccessorImageSource.cpp new file mode 100644 index 0000000..0ab61c9 --- /dev/null +++ b/code/io/itk/itkMaskAccessorImageSource.cpp @@ -0,0 +1,107 @@ +// ----------------------------------------------------------------------- +// 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 "itkMaskAccessorImageSource.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIteratorWithIndex.h" +#include "itkProgressReporter.h" +#include "itkExceptionObject.h" + +namespace itk +{ + /** + * Constructor + */ + MaskAccessorImageSource + ::MaskAccessorImageSource() : m_FailsOnInvalidIDs(true), m_InvalidMaskValue(0) + { + } + + void + MaskAccessorImageSource + ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, + ThreadIdType threadId) + { + ProgressReporter progress(this, threadId, + outputRegionForThread.GetNumberOfPixels()); + + typedef ImageRegionIterator< OutputImageType > OutputImageRegionIteratorType; + + OutputImagePointer outputPtr = dynamic_cast< OutputImageType* >(ProcessObject::GetOutput(0)); + OutputImageRegionIteratorType outputItr; + + if (outputPtr) + { + outputItr = OutputImageRegionIteratorType(outputPtr, outputRegionForThread); + + for (; !(outputItr.IsAtEnd()); ++outputItr) + { + OutputImageType::IndexType index = outputItr.GetIndex(); + rttb::VoxelGridIndex3D maskIndex(index[0], index[1], index[2]); + rttb::VoxelGridID id = 0; + + if (m_Accessor->getGeometricInfo().convert(maskIndex, id)) + { + auto finding = m_idMap.find(id); + if (finding != m_idMap.end()) + { + // Set the current pixel + outputItr.Set(m_MaskedVoxels->at(finding->second).getRelevantVolumeFraction()); + } + } + else + { + if (m_FailsOnInvalidIDs) + { + itkExceptionMacro(<<"invalid Mask index. Index:"<(ProcessObject::GetOutput(0)); + outputPtr->FillBuffer(0.0); + + //The id map approach and working with relevant voxel vector is a workarround till task T22067 is solved and and can be used again. + m_MaskedVoxels = m_Accessor->getRelevantVoxelVector(); + + m_idMap.clear(); + + for (rttb::core::MaskAccessorInterface::MaskVoxelList::size_type pos = 0; pos < m_MaskedVoxels->size(); ++pos) + { + m_idMap.insert(std::make_pair((*m_MaskedVoxels)[pos].getVoxelGridID(), pos)); + } + } +} // end namespace itk + diff --git a/code/io/itk/itkMaskAccessorImageSource.h b/code/io/itk/itkMaskAccessorImageSource.h new file mode 100644 index 0000000..51a20b9 --- /dev/null +++ b/code/io/itk/itkMaskAccessorImageSource.h @@ -0,0 +1,111 @@ +// ----------------------------------------------------------------------- +// 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) +*/ + +#ifndef __itkMaskAccessorImageSource_h +#define __itkMaskAccessorImageSource_h + +#include "itkGenerateImageSource.h" + +#include "rttbMaskAccessorInterface.h" +#include "rttbITKImageMaskAccessor.h" + +namespace itk +{ + /** \class MaskAccessorImageSource + * \brief Converts a given mask accessor into an itk image. + * + */ + + typedef rttb::io::itk::ITKImageMaskAccessor::ITKMaskImageType RTTBMaskImageType; + + class ITK_EXPORT MaskAccessorImageSource: + public GenerateImageSource< RTTBMaskImageType> + + { + public: + /** Standard class typedefs. */ + typedef MaskAccessorImageSource Self; + typedef GenerateImageSource< RTTBMaskImageType > Superclass; + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(MaskAccessorImageSource, ImageToImageFilter); + + /** Some typedefs. */ + typedef RTTBMaskImageType OutputImageType; + typedef OutputImageType::Pointer OutputImagePointer; + typedef OutputImageType::RegionType OutputImageRegionType; + typedef OutputImageType::PixelType OutputImagePixelType; + + typedef rttb::core::MaskAccessorInterface AccessorType; + typedef rttb::core::MaskAccessorInterface::MaskAccessorPointer AccessorPointer; + + /** Get the accessor pointer. */ + itkGetConstMacro(Accessor, AccessorPointer); + + /** Set the accessor pointer. */ + void SetAccessor(AccessorPointer accessor) + { + if (m_Accessor != accessor) + { + m_Accessor = accessor; + this->Modified(); + } + } + + itkSetMacro(FailsOnInvalidIDs, bool); + itkGetConstMacro(FailsOnInvalidIDs, bool); + + itkSetMacro(InvalidMaskValue, OutputImageType::ValueType); + itkGetConstMacro(InvalidMaskValue, OutputImageType::ValueType); + + /** ImageDimension constants */ + itkStaticConstMacro( + OutputImageDimension, unsigned int, OutputImageType::ImageDimension); + + protected: + MaskAccessorImageSource(); + virtual ~MaskAccessorImageSource() {} + + void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, + ThreadIdType threadId); + + virtual void BeforeThreadedGenerateData(); + + private: + MaskAccessorImageSource(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + typedef std::map VoxelMapType; + VoxelMapType m_idMap; + rttb::core::MaskAccessorInterface::MaskVoxelListPointer m_MaskedVoxels; + + AccessorPointer m_Accessor; + bool m_FailsOnInvalidIDs; + OutputImageType::ValueType m_InvalidMaskValue; + }; +} // end namespace itk + + +#endif diff --git a/code/io/itk/rttbITKImageMaskAccessorConverter.cpp b/code/io/itk/rttbITKImageMaskAccessorConverter.cpp index 4f0e80a..381526a 100644 --- a/code/io/itk/rttbITKImageMaskAccessorConverter.cpp +++ b/code/io/itk/rttbITKImageMaskAccessorConverter.cpp @@ -1,126 +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) */ #include #include "rttbITKImageMaskAccessorConverter.h" -#include "rttbInvalidDoseException.h" #include "rttbGeometricInfo.h" -#include "itkImageRegionIterator.h" #include "rttbITKImageMaskAccessor.h" +#include "itkMaskAccessorImageSource.h" namespace rttb { namespace io { namespace itk { ITKImageMaskAccessorConverter::ITKImageMaskAccessorConverter(MaskAccessorPointer accessor) { setMaskAccessor(accessor); } bool ITKImageMaskAccessorConverter::process() { //Transfer GeometricInfo to ITK Properties core::GeometricInfo geoInfo = _maskAccessor->getGeometricInfo(); - ITKImageMaskAccessor::ITKMaskImageType::RegionType region; - ITKImageMaskAccessor::ITKMaskImageType::IndexType start = {{0, 0, 0}}; ITKImageMaskAccessor::ITKMaskImageType::SizeType size = {{geoInfo.getNumColumns(), geoInfo.getNumRows(), geoInfo.getNumSlices()}}; ITKImageMaskAccessor::ITKMaskImageType::SpacingType spacing; for (unsigned int i = 0; i < 3; ++i) { spacing[i] = geoInfo.getSpacing()[i]; } ITKImageMaskAccessor::ITKMaskImageType::PointType origin; for (unsigned int i = 0; i < 3; ++i) { origin[i] = geoInfo.getImagePositionPatient()[i]; } ITKImageMaskAccessor::ITKMaskImageType::DirectionType direction; OrientationMatrix OM = geoInfo.getOrientationMatrix(); for (unsigned int col = 0; col < 3; ++col) { for (unsigned int row = 0; row < 3; ++row) { direction(col, row) = OM(col, row); } } - //Create image, assign properties - region.SetSize(size); - region.SetIndex(start); - - _itkImage = ITKImageMaskAccessor::ITKMaskImageType::New(); - _itkImage->SetRegions(region); - _itkImage->SetSpacing(spacing); - _itkImage->SetDirection(direction); - _itkImage->SetOrigin(origin); - _itkImage->Allocate(); - - ::itk::ImageRegionIterator imageIterator(_itkImage, region); - VoxelGridID id = 0; - - //Transfer Mask values to itk image - //Large advantage: rttbVoxelGridId ordering is the same as itk ordering - while (!imageIterator.IsAtEnd()) - { - VoxelGridIndex3D aIndex; - if (_maskAccessor->getGeometricInfo().validID(id)) - { - rttb::core::MaskVoxel maskVoxel = core::MaskVoxel(id);; - _maskAccessor->getMaskAt(id, maskVoxel); - // Set the current pixel - imageIterator.Set(maskVoxel.getRelevantVolumeFraction()); - } - else - { - if (failsOnInvalidIDs()) - { - throw core::InvalidDoseException("invalid Mask id!"); - return false; - } - else - { - imageIterator.Set(_invalidDoseValue); - } - } + ::itk::MaskAccessorImageSource::Pointer imagesource = ::itk::MaskAccessorImageSource::New(); + + imagesource->SetSize(size); + imagesource->SetSpacing(spacing); + imagesource->SetDirection(direction); + imagesource->SetOrigin(origin); + imagesource->SetAccessor(_maskAccessor); + imagesource->SetFailsOnInvalidIDs(failsOnInvalidIDs()); + imagesource->SetInvalidMaskValue(_invalidDoseValue); + imagesource->Update(); + _itkImage = imagesource->GetOutput(); - ++imageIterator; - ++id; - } return true; } }//end namespace mask }//end namespace io }//end namespace rttb