diff --git a/code/interpolation/CMakeLists.txt b/code/interpolation/CMakeLists.txt index d511e1c..083e4c8 100644 --- a/code/interpolation/CMakeLists.txt +++ b/code/interpolation/CMakeLists.txt @@ -1,12 +1,16 @@ OPTION(BUILD_MatchPointBinding "Determine if the MatchPoint binding for dose interpolation classes will be generated." OFF) OPTION(BUILD_ITKBinding "Determine if the ITK binding for dose interpolation classes will be generated." OFF) IF(BUILD_MatchPointBinding) ADD_SUBDIRECTORY(MatchPointBinding) ENDIF(BUILD_MatchPointBinding) IF(BUILD_ITKBinding) ADD_SUBDIRECTORY(ITKBinding) ENDIF(BUILD_ITKBinding) -RTTB_CREATE_MODULE(RTTBInterpolation DEPENDS RTTBCore PACKAGE_DEPENDS Boost) \ No newline at end of file +RTTB_CREATE_MODULE(RTTBInterpolation DEPENDS RTTBCore PACKAGE_DEPENDS Boost) +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") +ENDIF() diff --git a/code/interpolation/MatchPointBinding/CMakeLists.txt b/code/interpolation/MatchPointBinding/CMakeLists.txt index baa2ca0..da68e95 100644 --- a/code/interpolation/MatchPointBinding/CMakeLists.txt +++ b/code/interpolation/MatchPointBinding/CMakeLists.txt @@ -1 +1 @@ -RTTB_CREATE_MODULE(RTTBMatchPointBinding DEPENDS RTTBCore RTTBInterpolation PACKAGE_DEPENDS Boost MatchPoint ITK) \ No newline at end of file +RTTB_CREATE_MODULE(RTTBMatchPointBinding DEPENDS RTTBCore RTTBInterpolation PACKAGE_DEPENDS Boost MatchPoint ITK) diff --git a/code/interpolation/rttbInterpolationBase.cpp b/code/interpolation/rttbInterpolationBase.cpp index 3d95507..5d18704 100644 --- a/code/interpolation/rttbInterpolationBase.cpp +++ b/code/interpolation/rttbInterpolationBase.cpp @@ -1,196 +1,196 @@ // ----------------------------------------------------------------------- // 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 "rttbInterpolationBase.h" #include "rttbInvalidParameterException.h" #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace interpolation { void InterpolationBase::setDoseAccessorPointer(const DoseAccessorPointer originalDose) { if (originalDose != NULL) { _spOriginalDose = originalDose; } else { throw core::NullPointerException("originalDose is NULL!"); } }; void InterpolationBase::getNeighborhoodVoxelValues( const WorldCoordinate3D& aWorldCoordinate, unsigned int neighborhood, boost::array& target, boost::shared_ptr values) const { if (_spOriginalDose == NULL) { throw core::NullPointerException("originalDose is NULL!"); } //Determine target (abs(desired worldCoordinate- corner pixel world coordinate/pixel spacing) and values of corner pixels (from originalDose) VoxelGridIndex3D aIndex; if (_spOriginalDose->getGeometricInfo().worldCoordinateToIndex(aWorldCoordinate, aIndex)) { //determine just the nearest voxel to the world coordinate if (neighborhood == 0) { values[0] = _spOriginalDose->getDoseAt(aIndex); } //determine the 8 voxels around the world coordinate else if (neighborhood == 8) { std::list cornerPoints; WorldCoordinate3D theNextVoxel; _spOriginalDose->getGeometricInfo().indexToWorldCoordinate(aIndex, theNextVoxel); SpacingVectorType3D pixelSpacing = (_spOriginalDose->getGeometricInfo()).getSpacing(); VoxelGridIndex3D leftTopFrontCoordinate; //find the voxel with the smallest coordinate values in each dimension. This defines the standard cube for (int i = 0; i < 3; i++) { if (aWorldCoordinate[i] < theNextVoxel[i]) { if (aIndex[i] > 0) { leftTopFrontCoordinate[i] = aIndex[i] - 1; target[i] = (aWorldCoordinate[i] - (theNextVoxel[i] - pixelSpacing[i])) / pixelSpacing[i]; } //@todo: this is a workaround, not a good solution else { leftTopFrontCoordinate[i] = aIndex[i]; target[i] = (aWorldCoordinate[i] - (theNextVoxel[i] - pixelSpacing[i])) / pixelSpacing[i]; } } else { leftTopFrontCoordinate[i] = aIndex[i]; target[i] = (aWorldCoordinate[i] - theNextVoxel[i]) / pixelSpacing[i]; } } for (int zIncr = 0; zIncr < 2; zIncr++) { for (int yIncr = 0; yIncr < 2; yIncr++) { for (int xIncr = 0; xIncr < 2; xIncr++) { cornerPoints.push_back(VoxelGridIndex3D(leftTopFrontCoordinate[0] + xIncr, leftTopFrontCoordinate[1] + yIncr, leftTopFrontCoordinate[2] + zIncr)); } } } //target range has to be always [0,1] for (int i = 0; i < 3; i++) { assert(target[i] >= 0.0 && target[i] <= 1.0); } unsigned int count = 0; //now just get the values of all (dose) voxels and store them in values - for (auto cornerPointsIterator = std::begin(cornerPoints); cornerPointsIterator != std::end(cornerPoints); + for (auto cornerPointsIterator = cornerPoints.begin(); cornerPointsIterator != cornerPoints.end(); ++cornerPointsIterator, ++count) { if (_spOriginalDose->getGeometricInfo().isInside(*cornerPointsIterator)) { values[count] = _spOriginalDose->getDoseAt(*cornerPointsIterator); } else { //outside value! boundary treatment values[count] = getNearestInsideVoxelValue(*cornerPointsIterator); } assert(values[count] != -1); } } else { throw core::InvalidParameterException("neighborhoods other than 0 and 8 not yet supported in Interpolation"); } } else { throw core::MappingOutsideOfImageException("Error in conversion from world coordinates to index"); } } DoseTypeGy InterpolationBase::getNearestInsideVoxelValue(const VoxelGridIndex3D& currentVoxelIndex) const { VoxelGridIndex3D voxelChangedXYZ[] = {currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex, currentVoxelIndex}; int runningIndex; //x,y,z for (runningIndex = 0; runningIndex < 3; ++runningIndex) { voxelChangedXYZ[runningIndex][runningIndex] -= 1; } //xy voxelChangedXYZ[runningIndex][0] -= 1; voxelChangedXYZ[runningIndex][1] -= 1; ++runningIndex; //xz voxelChangedXYZ[runningIndex][0] -= 1; voxelChangedXYZ[runningIndex][2] -= 1; ++runningIndex; //yz voxelChangedXYZ[runningIndex][1] -= 1; voxelChangedXYZ[runningIndex][2] -= 1; ++runningIndex; //xyz voxelChangedXYZ[runningIndex][0] -= 1; voxelChangedXYZ[runningIndex][1] -= 1; voxelChangedXYZ[runningIndex][2] -= 1; ++runningIndex; int replacementVoxelIndex = 0; while (replacementVoxelIndex < runningIndex) { if (_spOriginalDose->getGeometricInfo().validIndex(voxelChangedXYZ[replacementVoxelIndex])) { return _spOriginalDose->getDoseAt(voxelChangedXYZ[replacementVoxelIndex]); } ++replacementVoxelIndex; } return -1; } }//end namespace core }//end namespace rttb diff --git a/code/interpolation/rttbRosuMappableDoseAccessor.cpp b/code/interpolation/rttbRosuMappableDoseAccessor.cpp index 2ad8876..44d4b8a 100644 --- a/code/interpolation/rttbRosuMappableDoseAccessor.cpp +++ b/code/interpolation/rttbRosuMappableDoseAccessor.cpp @@ -1,174 +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$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "rttbRosuMappableDoseAccessor.h" #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" #include "rttbLinearInterpolation.h" namespace rttb { namespace interpolation { RosuMappableDoseAccessor::RosuMappableDoseAccessor(const core::GeometricInfo& geoInfoTargetImage, const DoseAccessorPointer doseMovingImage, const TransformationInterface::Pointer aTransformation, bool acceptPadding, DoseTypeGy defaultOutsideValue): MappableDoseAccessorInterface(geoInfoTargetImage, doseMovingImage, aTransformation, acceptPadding, defaultOutsideValue) { //define linear interpolation InterpolationBase::Pointer interpolationLinear = InterpolationBase::Pointer( new LinearInterpolation()); _spInterpolation = interpolationLinear; _spInterpolation->setDoseAccessorPointer(_spOriginalDoseDataMovingImage); } DoseTypeGy RosuMappableDoseAccessor::getDoseAt(const VoxelGridID aID) const { VoxelGridIndex3D aVoxelGridIndex3D; if (_geoInfoTargetImage.convert(aID, aVoxelGridIndex3D)) { return getDoseAt(aVoxelGridIndex3D); } else { if (_acceptPadding) { return _defaultOutsideValue; } else { throw core::MappingOutsideOfImageException("Error in conversion from index to world coordinates"); return -1; } } } DoseTypeGy RosuMappableDoseAccessor::getDoseAt(const VoxelGridIndex3D& aIndex) const { //Transform requested voxel coordinates of original image into world coordinates with RTTB WorldCoordinate3D worldCoordinateTarget; if (_geoInfoTargetImage.indexToWorldCoordinate(aIndex, worldCoordinateTarget)) { std::vector octants = getOctants(worldCoordinateTarget); if (octants.size() > 2) { DoseTypeGy interpolatedDoseValue = 0.0; //get trilinear interpolation value of every octant point - for (std::vector::const_iterator octantIterator = std::begin(octants); - octantIterator != std::end(octants); + for (std::vector::const_iterator octantIterator = octants.begin(); + octantIterator != octants.end(); ++octantIterator) { //transform coordinates WorldCoordinate3D worldCoordinateMoving; WorldCoordinate3D worldCoordinateTargetOctant = *octantIterator; _spTransformation->transformInverse(worldCoordinateTargetOctant, worldCoordinateMoving); try { interpolatedDoseValue += _spInterpolation->getValue(worldCoordinateMoving); } //Mapped outside of image? Check if padding is allowed catch (core::MappingOutsideOfImageException& /*e*/) { if (_acceptPadding) { interpolatedDoseValue += _defaultOutsideValue; } else { throw core::MappingOutsideOfImageException("Mapping outside of image"); } } catch (core::Exception& e) { std::cout << e.what() << std::endl; return -1; } } return interpolatedDoseValue / (DoseTypeGy)octants.size(); } else { if (_acceptPadding) { return _defaultOutsideValue; } else { throw core::MappingOutsideOfImageException("Too many samples are mapped outside the image!"); return -1; } } } else { if (_acceptPadding) { return _defaultOutsideValue; } else { throw core::MappingOutsideOfImageException("Error in conversion from index to world coordinates"); return -1; } } } std::vector RosuMappableDoseAccessor::getOctants( const WorldCoordinate3D& aCoordinate) const { std::vector octants; SpacingVectorType3D spacingTargetImage = _geoInfoTargetImage.getSpacing(); core::GeometricInfo geometricInfoDoseData = _spOriginalDoseDataMovingImage->getGeometricInfo(); //as the corner point is the coordinate of the voxel (grid), 0.25 and 0.75 are the center of the subvoxels for (double xOct = -0.25; xOct <= 0.25; xOct += 0.5) { for (double yOct = -0.25; yOct <= 0.25; yOct += 0.5) { for (double zOct = -0.25; zOct <= 0.25; zOct += 0.5) { WorldCoordinate3D aWorldCoordinate(aCoordinate.x() + (xOct * spacingTargetImage.x()), aCoordinate.y() + (yOct * spacingTargetImage.y()), aCoordinate.z() + (zOct * spacingTargetImage.z())); if (geometricInfoDoseData.isInside(aWorldCoordinate)) { octants.push_back(aWorldCoordinate); } } } } return octants; } }//end namespace interpolation }//end namespace rttb diff --git a/code/io/itk/rttbGenericImageReader.h b/code/io/itk/rttbGenericImageReader.h index cca2863..1eea8cb 100644 --- a/code/io/itk/rttbGenericImageReader.h +++ b/code/io/itk/rttbGenericImageReader.h @@ -1,163 +1,163 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/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) // Subversion HeadURL: $HeadURL: https://svn/sbr/Sources/SBR-Projects/MatchPoint/trunk/Code/IO/include/mapGenericImageReader.h $ */ #ifndef __RTTB_GENERIC_IMAGE_READER_H #define __RTTB_GENERIC_IMAGE_READER_H #include "rttbImageReader.h" namespace rttb { namespace io { namespace itk { /** @class ImageReader * @brief Helper class manages the generic loading (unspecified dimension and pixel type) of 2D/3D images ... * * GenericImageReader uses the ImageReader class and dispatches the dimension and pixel type information from the specified image file. * GenericImageReader supports 2D and 3D images and the following pixel types: * - (unsigned) char * - (unsigned) short * - (unsigned) int * - (unsigned) long * - float * - double * . * Due to the fact that it builds upon the itk io infrastructure, all formats supported by ITK * can be read. * For further information regarding the usage see documentation of ImageReader. * @sa ImageReader * @note code copied from MatchPoint, see documentation (http://sourceforge.net/projects/matchpoint/) */ class GenericImageReader : public ::itk::Object { public: typedef GenericImageReader Self; typedef ::itk::Object Superclass; typedef ::itk::SmartPointer Pointer; typedef ::itk::SmartPointer ConstPointer; itkTypeMacro(GenericImageReader, ::itk::Object); itkNewMacro(Self); typedef ::itk::DataObject GenericOutputImageType; typedef ::itk::ImageIOBase::IOPixelType LoadedPixelType; typedef ::itk::ImageIOBase::IOComponentType LoadedComponentType; - typedef std::vector<::itk::MetaDataDictionary> MetaDataDictionaryArrayType; + typedef std::vector< ::itk::MetaDataDictionary> MetaDataDictionaryArrayType; private: /** Loaded Image.*/ GenericOutputImageType::Pointer _spImage; /** The file name of the image. */ FileNameString _fileName; /** The upper limit for the searching of series files in the path.*/ unsigned int _upperSeriesLimit; /** Indicates if the image data is up to date or should be read again.*/ bool _upToDate; /** Defines if the specified image file is part of a series and the * whole series should be read into one image. Only relevant for 3D images.*/ ImageSeriesReadStyle::Type _seriesReadStyle; unsigned int _loadedDimensions; LoadedPixelType _loadedPixelType; LoadedComponentType _loadedComponentType; std::string _loadedComponentTypeStr; std::string _loadedPixelTypeStr; MetaDataDictionaryArrayType _dictionaryArray; /** Loads the image. First identifies pixel type and dimension and then deligates according * to the pixel type. * @exception map::core::ExceptionObject If no ImageIO is found. * @exception map::core::ExceptionObject If dimension of the image is not supported. Only 2D/3D is supported. * @exception map::core::ExceptionObject If pixel type is not supported. Currently only scalar pixels are supported. */ void load(); /** Loads an scalar image. * @exception map::core::ExceptionObject If pixel component type is not supported. */ template void loadScalar(); //template //void loadRGB(); public: /** Function to access the member variable _FileName. _FileName represents the filename of the * headerfile. The path must be included, the file extension may left away. * @return File name of the header file.*/ const FileNameString& getFileName() const; /** Function to access the member variable _FileName. _FileName represents the filename of the * headerfile. The path must be included, the file extension may left away. * @param [in] sFileName The file name of the header file.*/ void setFileName(const FileNameString& sFileName); /** Function to access the member variable _upperSeriesLimit. _upperSeriesLimit represents * the upper limit for the series file search. * @return The upper limit of the series search.*/ const unsigned int getUpperSeriesLimit() const; /** Function to access the member variable _upperSeriesLimit. _upperSeriesLimit represents * the upper limit for the series file search. Changing the series limit out dates the ImageReader. * @remark It is only relevant if series style is set to "Numeric". * @param [in] upperLimit The upper limit of the header file.*/ void setUpperSeriesLimit(const unsigned int upperLimit); /** Function to access the member variable _seriesReadStyle (see member description for more information).*/ const ImageSeriesReadStyle::Type getSeriesReadStyle() const; /** Function to access the member variable _seriesReadStyle (see member description for more information). * Changing the style out dates the ImageReader.*/ void setSeriesReadStyle(ImageSeriesReadStyle::Type readStyle); /** Function loads the image if needed and returns the data. * @return Pointer to loaded image. * @exception map::core::ExceptionObject If no ImageIO is found. * @exception map::core::ExceptionObject If dimension of the image is not supported. Only 2D/3D is supported. * @exception map::core::ExceptionObject If pixel type is not supported. Currently only scalar pixels are supported. * @exception map::core::ExceptionObject If pixel component type is not supported. */ GenericOutputImageType* GetOutput(unsigned int& loadedDimensions, LoadedPixelType& loadedPixelType, LoadedComponentType& loadedComponentType); /** Function returns the reference to the meta data dictionary(ies) of the latest file(s) loaded by this class. * Array may be empty if no MetaDictionary exists.*/ const MetaDataDictionaryArrayType& getMetaDictionaryArray(); protected: GenericImageReader(); virtual ~GenericImageReader(); }; }//end namespace itk }//end namespace io }//end namespace rttb #endif diff --git a/code/io/itk/rttbITKIOHelper.tpp b/code/io/itk/rttbITKIOHelper.tpp index 83f9171..38be7e4 100644 --- a/code/io/itk/rttbITKIOHelper.tpp +++ b/code/io/itk/rttbITKIOHelper.tpp @@ -1,66 +1,66 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/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) // Subversion HeadURL: $HeadURL: https://svn/sbr/Sources/SBR-Projects/MatchPoint/trunk/Code/IO/include/mapImageReader.tpp $ */ #ifndef __RTTB_ITK_IMAGE_FILE_DOSE_ACCESSOR_GENERATOR_TPP #define __RTTB_ITK_IMAGE_FILE_DOSE_ACCESSOR_GENERATOR_TPP #include "rttbITKImageFileDoseAccessorGenerator.h" #include "rttbInvalidParameterException.h" #include "rttbInvalidDoseException.h" #include "rttbITKImageDoseAccessor.h" namespace rttb { namespace io { namespace itk { template ITKDoseImageType::Pointer doCasting(GenericImageReader::GenericOutputImageType* genericImage) { ITKDoseImageType::Pointer itkDoubleImage; typedef ::itk::Image InputImageType; typedef ITKDoseImageType OutputImageType; - InputImageType::Pointer pCastedInput = dynamic_cast(genericImage); + typename InputImageType::Pointer pCastedInput = dynamic_cast(genericImage); typedef ::itk::CastImageFilter CastFilterType; - CastFilterType::Pointer castFilter = CastFilterType::New(); + typename CastFilterType::Pointer castFilter = CastFilterType::New(); castFilter->SetInput(pCastedInput); try { //important to update the filter! castFilter->Update(); itkDoubleImage = castFilter->GetOutput(); } catch (::itk::ExceptionObject& e) { std::cerr << "ITK Error!!!" << std::endl; std::cerr << e << std::endl; } return itkDoubleImage; } } } } #endif diff --git a/code/io/itk/rttbImageReader.h b/code/io/itk/rttbImageReader.h index 2ea3025..34c1901 100644 --- a/code/io/itk/rttbImageReader.h +++ b/code/io/itk/rttbImageReader.h @@ -1,224 +1,224 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/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) // Subversion HeadURL: $HeadURL: https://svn/sbr/Sources/SBR-Projects/MatchPoint/trunk/Code/IO/include/mapImageReader.h $ */ #ifndef __RTTB_IMAGE_READER_H #define __RTTB_IMAGE_READER_H #include "itkImage.h" #include "itkImageSource.h" namespace rttb { namespace io { namespace itk { struct ImageSeriesReadStyle { enum Type { Default = 0, //* - Depending on the file extension (DICOM images (*.dcm, *.ima): Dicom; others: None; No image file: Dicom) None = 1, //* - No series reading, only the specified file Dicom = 2, //* - Use series reader and DCMTKSeriesFileNames Numeric = 3, //* - Use series reader and NumericSeriesFileNames GDCM = 4 //* - Use series reader and GDCMSeriesFileNames }; }; /** @class ImageReader * @brief Helper class manages the loading of 2D/3D images based on itk but with some convenience features ... * * ImageReader is used to load 2D or 3D images in an itk like style, but also offers * some convenience features and the specialties of different formats into account.\n * 2D images will be loaded directly by the IO classes of itk, so in this case the * ImageReader is only a layer of abstraction.\n * 3D images will be handled different, depending on the type of files and the chosen * series read style:\n * - Default: Depending on the file extension (DICOM images (*.dcm, *.ima): Dicom; others: None; No image file: Dicom * - None: directly by the itk io (no series reading) * - Dicom: uses itk series reader, currently a list of files will be generated that is similar to GDCM (old ::itk::DICOMKSeriesFileNames is not supported any more by itk > 4.3.x.) * - GDCM: uses itk series reader, the list of files will be generated * by the ::itk::GDCMSeriesFileNames in the specified path ordered by * imagePositionPatient. * - Numeric: Will be considered as series of images. The list of files will be * created by ::itk::NumericSeriesFileNames, so in this case the given * file name is already masked by %d for the increasing index within * the file name. * . * @todo implement Reader as an ::itk::ImageSource in the behavior. * @note code copied from MatchPoint, see documentation (http://sourceforge.net/projects/matchpoint/) */ template class ImageReader { public: typedef ::itk::Image InputImageType; typedef ::itk::Image OutputImageType; typedef TInputPixel RescaleValueType; - typedef std::vector<::itk::MetaDataDictionary> MetaDataDictionaryArrayType; + typedef std::vector< ::itk::MetaDataDictionary> MetaDataDictionaryArrayType; typedef std::string String; typedef std::ostringstream OStringStream; typedef std::istringstream IStringStream; virtual const char* GetNameOfClass() const { return "ImageReader"; } private: /** Loaded Image.*/ typename OutputImageType::Pointer _spImage; /** The file name of the image. */ String _fileName; /** The upper limit for the searching of series files in the path.*/ unsigned int _upperSeriesLimit; /** Indicates if the image data is up to date or should be read again.*/ bool _upToDate; /** Indicates if the output image intensity should be rescaled.*/ bool _rescaleImage; /** Indicates the minimum of the output.*/ RescaleValueType _rescaleMin; /** Indicates the maximum of the output.*/ RescaleValueType _rescaleMax; /** Defines if the specified image file is part of a series and the * whole series should be read into one image. Only relevant for 3D images.*/ typename ImageSeriesReadStyle::Type _seriesReadStyle; MetaDataDictionaryArrayType _dictionaryArray; void load2D(); typename ::itk::ImageSource::Pointer prepareNumericSource() const; typename ::itk::ImageSource::Pointer prepareDICOMSource() const; typename ::itk::ImageSource::Pointer prepareNormalSource() const; typename ::itk::ImageSource::Pointer prepareGDCMSource() const; void load3D(); - typedef std::vector<::itk::MetaDataDictionary*> ITKMetaDataDictionaryArray; + typedef std::vector< ::itk::MetaDataDictionary*> ITKMetaDataDictionaryArray; void copyMetaDictionaryArray(const ITKMetaDataDictionaryArray* fromArray, MetaDataDictionaryArrayType& toArray); public: /** Function to access the member variable _FileName. _FileName represents the filename of the * headerfile. The path must be included, the file extension may left away. * @return File name of the header file.*/ const String& getFileName() const; /** Function to access the member variable _FileName. _FileName represents the filename of the * headerfile. The path must be included, the file extension may left away. * @param [in] sFileName The file name of the header file.*/ void setFileName(const String& sFileName); /** Function to access the member variable _rescaleMin. _rescaleMin represents * the minimum of the intensity rescale filter. * @return The minimum of the intensity rescale filter.*/ const RescaleValueType& getRescaleMinimum() const; /** Function to access the member variable _rescaleMin. _rescaleMin represents * the minimum of the intensity rescale filter. Changing the rescale minimum out dates the ImageReader. * @param [in] dRescaleMin The minimum of the intensity rescale filter.*/ void setRescaleMinimum(const RescaleValueType& rescaleMin); /** Function to access the member variable _rescaleMin. _rescaleMax represents * the minimum of the intensity rescale filter. * @return The minimum of the intensity rescale filter.*/ const RescaleValueType& getRescaleMaximum() const; /** Function to access the member variable _rescaleMin. _rescaleMax represents * the minimum of the intensity rescale filter. Changing the rescale maximum out dates the ImageReader. * @param [in] dRescaleMax The minimum of the intensity rescale filter.*/ void setRescaleMaximum(const RescaleValueType& rescaleMax); /** Function to access the member variable _rescaleImage. _rescaleImage indicates if a * loaded image should be rescaled regarding its intensities. * @return If the ImageReader converts images to iso-voxel.*/ const bool getRescaleImage() const; /** Function to access the member variable _rescaleImage. _rescaleImage indicates if a * loaded image should be rescaled regarding its intensities. Changing the rescale option out dates the ImageReader. * @param [in] rescaleImage Specifies if image should be converted to isovoxel.*/ void setRescaleImage(const bool rescaleImage); /** Function to access the member variable _upperSeriesLimit. _upperSeriesLimit represents * the upper limit for the series file search. * @return The upper limit of the series search.*/ const unsigned int getUpperSeriesLimit() const; /** Function to access the member variable _upperSeriesLimit. _upperSeriesLimit represents * the upper limit for the series file search. Changing the series limit out dates the ImageReader. * @remark It is only relevant if series style is set to "Numeric". * @param [in] upperLimit The upper limit of the header file.*/ void setUpperSeriesLimit(const unsigned int upperLimit); /** Function to access the member variable _seriesReadStyle (see member description for more information).*/ const typename ImageSeriesReadStyle::Type getSeriesReadStyle() const; /** Function to access the member variable _seriesReadStyle (see member description for more information). * Changing the style out dates the ImageReader.*/ void setSeriesReadStyle(typename ImageSeriesReadStyle::Type readStyle); /** Function loads the image if needed and returns the data. * @return Pointer to loaded image.*/ OutputImageType* GetOutput(void); /** Function returns the reference to the meta data dictionary(ies) of the latest file(s) loaded by this class. * Array may be empty if no MetaDictionary exists.*/ const MetaDataDictionaryArrayType& getMetaDictionaryArray(); ImageReader(); virtual ~ImageReader(); }; /** * @brief Helper function for the use of ImageReader in on statement ... * * for specific informations please see the documentation of ImageReader. * @param pLoadedDictArray Pass a pointer to valid array to receive the meta dictionaries * loaded with the image. If the pointer is null, no dictionaries will be transfered. The array * will be reseted before the loaded dictionaries will be added. * @sa ImageReader * @ingroup Utils */ template typename ImageReader::OutputImageType::Pointer readImage(const std::string& fileName, ImageSeriesReadStyle::Type readStyle = ImageSeriesReadStyle::Default, bool rescaleImage = false, typename ImageReader::RescaleValueType rescaleMin = 0, typename ImageReader::RescaleValueType rescaleMax = 255, unsigned int upperNumericSeriesLimit = 100, typename ImageReader::MetaDataDictionaryArrayType* pLoadedDictArray = NULL); }//end namespace itk }//end namespace io }//end namespace rttb #include "rttbImageReader.tpp" #endif diff --git a/code/io/itk/rttbImageReader.tpp b/code/io/itk/rttbImageReader.tpp index cf71e4f..f687f91 100644 --- a/code/io/itk/rttbImageReader.tpp +++ b/code/io/itk/rttbImageReader.tpp @@ -1,533 +1,533 @@ // ----------------------------------------------------------------------- // MatchPoint - DKFZ translational registration framework // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See mapCopyright.txt or // http://www.dkfz.de/en/sidt/projects/MatchPoint/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) // Subversion HeadURL: $HeadURL: https://svn/sbr/Sources/SBR-Projects/MatchPoint/trunk/Code/IO/include/mapImageReader.tpp $ */ #ifndef __RTTB_IMAGE_READER_TPP #define __RTTB_IMAGE_READER_TPP #include "rttbImageReader.h" #include "rttbFileDispatch.h" #ifdef RTTB_DISABLE_ITK_IO_FACTORY_AUTO_REGISTER #undef ITK_IO_FACTORY_REGISTER_MANAGER -#endif RTTB_DISABLE_ITK_IO_FACTORY_AUTO_REGISTER +#endif #include "itkImageFileReader.h" #include "itkImageFileWriter.h" #include "itkImageSeriesReader.h" #include "itkImageSeriesWriter.h" #include "itkNumericSeriesFileNames.h" #include "itkGDCMSeriesFileNames.h" #include "itkRescaleIntensityImageFilter.h" #include "itkCastImageFilter.h" #include "itkFixedArray.h" #include "itksys/SystemTools.hxx" #include #include namespace rttb { namespace io { namespace itk { template void ImageReader:: load2D() { typedef ::itk::ImageFileReader< InputImageType > ImageReaderType; typedef ::itk::RescaleIntensityImageFilter< InputImageType, InputImageType > RescaleFilterType; typedef ::itk::CastImageFilter< InputImageType, OutputImageType > CastFilterType; typename CastFilterType::Pointer imageCaster = CastFilterType::New(); typename ImageReaderType::Pointer imageReader = ImageReaderType::New(); typename RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); rescaleFilter->SetOutputMinimum(static_cast(_rescaleMin)); rescaleFilter->SetOutputMaximum(static_cast(_rescaleMax)); imageReader->SetFileName(_fileName.c_str()); rescaleFilter->SetInput(imageReader->GetOutput()); if (_rescaleImage) { imageCaster->SetInput(rescaleFilter->GetOutput()); } else { imageCaster->SetInput(imageReader->GetOutput()); } _spImage = imageCaster->GetOutput(); imageCaster->Update(); _dictionaryArray.clear(); _dictionaryArray.push_back(imageReader->GetImageIO()->GetMetaDataDictionary()); _upToDate = true; }; template const typename ImageReader::MetaDataDictionaryArrayType& ImageReader:: getMetaDictionaryArray() { return _dictionaryArray; }; template void ImageReader:: copyMetaDictionaryArray(const ITKMetaDataDictionaryArray* fromArray, MetaDataDictionaryArrayType& toArray) { toArray.clear(); ITKMetaDataDictionaryArray::const_iterator itr = fromArray->begin(); ITKMetaDataDictionaryArray::const_iterator end = fromArray->end(); while (itr != end) { toArray.push_back(*(*itr)); ++itr; } }; template typename ::itk::ImageSource::InputImageType>::Pointer ImageReader:: prepareNumericSource() const { //mumeric series image reader typedef ::itk::ImageSeriesReader< InputImageType > SeriesReaderType; typedef ::itk::NumericSeriesFileNames NamesType; typename SeriesReaderType::Pointer seriesReader = SeriesReaderType::New(); NamesType::Pointer names = NamesType::New(); names->SetStartIndex(1); names->SetEndIndex(_upperSeriesLimit); names->SetSeriesFormat(_fileName.c_str()); seriesReader->SetFileNames(names->GetFileNames()); if (seriesReader->GetFileNames().size() == 0) { throw ::itk::ExceptionObject("Image reader is not correctly configured. Preparing a series reading of a numeric source no(!) files were found."); } typename ::itk::ImageSource::InputImageType>::Pointer genericReader = seriesReader.GetPointer(); return genericReader; }; template typename ::itk::ImageSource::InputImageType>::Pointer ImageReader:: prepareDICOMSource() const { //ITK > v4.3.x removed old DICOMSeriesFileNames. Thus currently only support GDCM as source by default return prepareGDCMSource(); /**@TODO Add support for DCMTKSeriesFileNames too*/ }; template typename ::itk::ImageSource::InputImageType>::Pointer ImageReader:: prepareGDCMSource() const { core::FileDispatch dispatch(_fileName); FileNameString dir = dispatch.getPath(); FileNameString strippedFileName = dispatch.getFullName(); typedef ::itk::GDCMSeriesFileNames NamesGeneratorType; NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New(); nameGenerator->SetInputDirectory(dir); nameGenerator->SetUseSeriesDetails(true); ::itk::FilenamesContainer fileNames; if (strippedFileName.empty()) { std::cerr << "No file name specified. Use first DICOM series found in directory." << std::endl; fileNames = nameGenerator->GetInputFileNames(); } else { ::itk::SerieUIDContainer seriesUIDs = nameGenerator->GetSeriesUIDs(); std::cerr << "Checking found DICOM series." << std::endl; //check the found series for the filename to pick the right series correlated to the passed filename while (seriesUIDs.size() > 0) { fileNames = nameGenerator->GetFileNames(seriesUIDs.back()); std::cerr << "Checking series: " << seriesUIDs.back() << " (file count: " << fileNames.size() << ")" << std::endl; seriesUIDs.pop_back(); for (::itk::SerieUIDContainer::const_iterator pos = fileNames.begin(); pos != fileNames.end(); ++pos) { if (pos->find(strippedFileName) != FileNameString::npos) { //this series containes the passed filename -> //we have the right block of files -> we are done. std::cerr << "Found right series!" << std::endl; seriesUIDs.clear(); break; } } } } typedef ::itk::ImageSeriesReader< InputImageType > SeriesReaderType; typename SeriesReaderType::Pointer seriesReader = SeriesReaderType::New(); seriesReader->SetFileNames(fileNames); if (seriesReader->GetFileNames().size() == 0) { throw ::itk::ExceptionObject("Image reader is not correctly configured. Preparing a series reading of a DICOM source no(!) dicom files were found. search location: " + _fileName); } typename ::itk::ImageSource::InputImageType>::Pointer genericReader = seriesReader.GetPointer(); return genericReader; }; template typename ::itk::ImageSource::InputImageType>::Pointer ImageReader:: prepareNormalSource() const { //Normal image reader (no series read style) typedef ::itk::ImageFileReader< InputImageType > ImageReaderType; typename ImageReaderType::Pointer imageReader = ImageReaderType::New(); imageReader->SetFileName(_fileName.c_str()); typename ::itk::ImageSource::InputImageType>::Pointer genericReader = imageReader.GetPointer(); return genericReader; }; template void ImageReader:: load3D() { core::FileDispatch dispatch(_fileName); FileNameString sTemp = dispatch.getExtension(); //Convert to lowercase for (FileNameString::iterator spos = sTemp.begin(); spos != sTemp.end(); ++spos) { (*spos) = std::tolower((*spos), std::locale("")); } typedef ::itk::RescaleIntensityImageFilter< InputImageType, InputImageType > RescaleFilterType; typedef ::itk::CastImageFilter< InputImageType, OutputImageType > CastFilterType; typename CastFilterType::Pointer imageCaster = CastFilterType::New(); typename RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); typename ::itk::ImageSource::Pointer spReader; rescaleFilter->SetOutputMinimum(static_cast(_rescaleMin)); rescaleFilter->SetOutputMaximum(static_cast(_rescaleMax)); if (_seriesReadStyle == ImageSeriesReadStyle::Numeric) { spReader = prepareNumericSource(); } else if (_seriesReadStyle == ImageSeriesReadStyle::Dicom) { spReader = prepareDICOMSource(); } else if (_seriesReadStyle == ImageSeriesReadStyle::GDCM) { spReader = prepareGDCMSource(); } else if (_seriesReadStyle == ImageSeriesReadStyle::Default) { bool isDir = itksys::SystemTools::FileIsDirectory(_fileName.c_str()); if (isDir || sTemp == ".dcm" || sTemp == ".ima") { spReader = prepareDICOMSource(); } else { spReader = prepareNormalSource(); } } else { //style is none spReader = prepareNormalSource(); } if (_rescaleImage) { rescaleFilter->SetInput(spReader->GetOutput()); imageCaster->SetInput(rescaleFilter->GetOutput()); } else { imageCaster->SetInput(spReader->GetOutput()); } imageCaster->Update(); _spImage = imageCaster->GetOutput(); typedef ::itk::ImageFileReader< InputImageType > ImageReaderType; typedef ::itk::ImageSeriesReader< InputImageType > ImageSeriesReaderType; ImageReaderType* pFileReader = dynamic_cast(spReader.GetPointer()); ImageSeriesReaderType* pSeriesReader = dynamic_cast(spReader.GetPointer()); if (pFileReader) { _dictionaryArray.clear(); _dictionaryArray.push_back(pFileReader->GetImageIO()->GetMetaDataDictionary()); } else if (pSeriesReader) { copyMetaDictionaryArray(pSeriesReader->GetMetaDataDictionaryArray(), _dictionaryArray); } else { throw ::itk::ExceptionObject("Image reader is not valid. Internal reader seams not to be itk::ImageFileReader or itk::ImageSeriesReader."); } _upToDate = true; }; template const FileNameString& ImageReader:: getFileName() const { return _fileName; }; template void ImageReader:: setFileName(const FileNameString& fileName) { if (fileName != _fileName) { _upToDate = false; _fileName = fileName; } } template const typename ImageReader::RescaleValueType& ImageReader:: getRescaleMinimum() const { return _rescaleMin; }; template void ImageReader:: setRescaleMinimum(const RescaleValueType& dRescaleMin) { if (dRescaleMin != _rescaleMin) { _upToDate = false; _rescaleMin = dRescaleMin; }; }; template const typename ImageReader::RescaleValueType& ImageReader:: getRescaleMaximum() const { return _rescaleMax; }; template void ImageReader:: setRescaleMaximum(const RescaleValueType& dRescaleMax) { if (dRescaleMax != _rescaleMax) { _upToDate = false; _rescaleMax = dRescaleMax; }; }; template const bool ImageReader:: getRescaleImage() const { return _rescaleImage; }; template void ImageReader:: setRescaleImage(const bool rescaleImage) { if (rescaleImage != _rescaleImage) { _upToDate = false; _rescaleImage = rescaleImage; }; }; template const unsigned int ImageReader:: getUpperSeriesLimit() const { return _upperSeriesLimit; }; template void ImageReader:: setUpperSeriesLimit(const unsigned int upperLimit) { if (upperLimit != _upperSeriesLimit) { _upToDate = false; _upperSeriesLimit = upperLimit; }; }; template const ImageSeriesReadStyle::Type ImageReader:: getSeriesReadStyle() const { return _seriesReadStyle; }; template void ImageReader:: setSeriesReadStyle(ImageSeriesReadStyle::Type readStyle) { if (readStyle != _seriesReadStyle) { _upToDate = false; _seriesReadStyle = readStyle; }; }; template typename ImageReader::OutputImageType* ImageReader:: GetOutput(void) { if (!_upToDate) { switch (OutputImageType::GetImageDimension()) { case 2: load2D(); break; case 3: load3D(); break; default: throw ::itk::ExceptionObject("Image reader only accepts 2 or 3 dimensional images."); }; }; return _spImage; }; template ImageReader:: ImageReader() { _fileName = ""; _upperSeriesLimit = 255; _upToDate = false; _rescaleImage = false; _rescaleMax = 255; _rescaleMin = 0; _seriesReadStyle = ImageSeriesReadStyle::Default; }; template ImageReader:: ~ImageReader() { }; template typename ImageReader::OutputImageType::Pointer readImage( const FileNameString& fileName, ImageSeriesReadStyle::Type readStyle, bool rescaleImage, typename ImageReader::RescaleValueType rescaleMin, typename ImageReader::RescaleValueType rescaleMax, unsigned int upperNumericSeriesLimit, typename ImageReader::MetaDataDictionaryArrayType* pLoadedDictArray) { ImageReader reader; reader.setFileName(fileName); reader.setSeriesReadStyle(readStyle); reader.setRescaleImage(rescaleImage); reader.setRescaleMaximum(rescaleMax); reader.setRescaleMinimum(rescaleMin); reader.setUpperSeriesLimit(upperNumericSeriesLimit); typename ImageReader::OutputImageType::Pointer spResult = reader.GetOutput(); if (pLoadedDictArray) { *pLoadedDictArray = reader.getMetaDictionaryArray(); }; return spResult; }; } } } #endif diff --git a/testing/interpolation/CMakeLists.txt b/testing/interpolation/CMakeLists.txt index 816a47b..0ad2ec3 100644 --- a/testing/interpolation/CMakeLists.txt +++ b/testing/interpolation/CMakeLists.txt @@ -1,26 +1,30 @@ #----------------------------------------------------------------------------- # Setup the system information test. Write out some basic failsafe # information in case the test doesn't run. #----------------------------------------------------------------------------- SET(INTERPOLATION_TESTS ${EXECUTABLE_OUTPUT_PATH}/rttbInterpolationTests) SET(TEST_DATA_ROOT ${RTTBTesting_SOURCE_DIR}/data) SET(TEMP ${RTTBTesting_BINARY_DIR}/temporary) #----------------------------------------------------------------------------- ADD_TEST(SimpleMappableDoseAccessorTest ${INTERPOLATION_TESTS} SimpleMappableDoseAccessorTest "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwo.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/LinearIncreaseX.dcm") ADD_TEST(RosuMappableDoseAccessorTest ${INTERPOLATION_TESTS} RosuMappableDoseAccessorTest "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwo.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/LinearIncreaseX.dcm") ADD_TEST(InterpolationTest ${INTERPOLATION_TESTS} InterpolationTest "${TEST_DATA_ROOT}/DICOM/TestDose/ConstantTwo.dcm" "${TEST_DATA_ROOT}/DICOM/TestDose/LinearIncreaseX.dcm") IF(BUILD_ITKBinding) ADD_SUBDIRECTORY(ITKBinding) ENDIF(BUILD_ITKBinding) IF(BUILD_MatchPointBinding) ADD_SUBDIRECTORY(MatchPointBinding) ENDIF(BUILD_MatchPointBinding) RTTB_CREATE_TEST_MODULE(rttbInterpolation DEPENDS RTTBInterpolation RTTBDicomIO PACKAGE_DEPENDS Litmus) +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") +ENDIF() diff --git a/testing/interpolation/ITKBinding/SimpleMappableDoseAccessorWithITKTest.cpp b/testing/interpolation/ITKBinding/SimpleMappableDoseAccessorWithITKTest.cpp index eeb7a39..28243c2 100644 --- a/testing/interpolation/ITKBinding/SimpleMappableDoseAccessorWithITKTest.cpp +++ b/testing/interpolation/ITKBinding/SimpleMappableDoseAccessorWithITKTest.cpp @@ -1,186 +1,186 @@ // ----------------------------------------------------------------------- // 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: 741 $ (last changed revision) // @date $Date: 2014-09-16 16:34:22 +0200 (Di, 16 Sep 2014) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbSimpleMappableDoseAccessor.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbLinearInterpolation.h" #include "rttbTransformationInterface.h" #include "rttbITKTransformation.h" #include "rttbNullPointerException.h" #include "itkTranslationTransform.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef rttb::interpolation::SimpleMappableDoseAccessor SimpleMappableDoseAccessor; typedef rttb::interpolation::NearestNeighborInterpolation NearestNeighborInterpolation; typedef rttb::interpolation::LinearInterpolation LinearInterpolation; typedef rttb::interpolation::TransformationInterface TransformationInterface; typedef rttb::interpolation::ITKTransformation ITKTransformation; typedef itk::TranslationTransform TranslationTransformType; /*! @brief SimpleMappableDoseAccessorWithITKTest - test the API of SimpleMappableDoseAccessor with ITK transformation 1) Test constructor 2) test getDoseAt() a) with Identity transform b) with translation transform */ int SimpleMappableDoseAccessorWithITKTest(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 SimpleMappableDoseAccessorWithITKTest are expected" << std::endl; return -1; } const double doseGridScaling = 2.822386e-005; 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(); - auto interpolationNN = + NearestNeighborInterpolation::Pointer interpolationNN = NearestNeighborInterpolation::Pointer(new NearestNeighborInterpolation()); - auto interpolationLinear = boost::shared_ptr + LinearInterpolation::Pointer interpolationLinear = LinearInterpolation::Pointer (new LinearInterpolation()); //auto transformITKIdentity = TransformationInterface::Pointer(new ITKTransformation( // IdentityTransformType::New())); TranslationTransformType::Pointer transformITKIdentityTemporary = TranslationTransformType::New(); TranslationTransformType::OutputVectorType translationIdentity; translationIdentity[0] = 0.0; translationIdentity[1] = 0.0; translationIdentity[2] = 0.0; transformITKIdentityTemporary->Translate(translationIdentity); - auto transformITKIdentity = TransformationInterface::Pointer(new ITKTransformation( + TransformationInterface::Pointer transformITKIdentity = TransformationInterface::Pointer(new ITKTransformation( transformITKIdentityTemporary)); TranslationTransformType::Pointer transformITKTranslationTemporary = TranslationTransformType::New(); TranslationTransformType::OutputVectorType translation; translation[0] = 5.0; translation[1] = 5.0; translation[2] = 5.0; transformITKTranslationTemporary->Translate(translation); - auto transformITKTranslation = TransformationInterface::Pointer(new ITKTransformation( + TransformationInterface::Pointer transformITKTranslation = TransformationInterface::Pointer(new ITKTransformation( transformITKTranslationTemporary)); - auto aSimpleMappableDoseAccessorITKIdentity = new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformITKIdentity, interpolationLinear); - auto aSimpleMappableDoseAccessorITKTranslation = new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformITKTranslation, interpolationLinear); + SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorITKIdentity = SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor( + doseAccessor1GeometricInfo, doseAccessor2, transformITKIdentity, interpolationLinear)); + SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorITKTranslation = SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor( + doseAccessor1GeometricInfo, doseAccessor2, transformITKTranslation, interpolationLinear)); //1) Test constructor CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1GeometricInfo, doseAccessor2, transformITKIdentity, interpolationLinear)); CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1GeometricInfo, doseAccessor2, transformITKTranslation, interpolationLinear)); CHECK_NO_THROW(ITKTransformation(transformITKTranslationTemporary.GetPointer())); CHECK_THROW_EXPLICIT(ITKTransformation(NULL), core::NullPointerException); //2) test getDoseAt() // a) with Identity transform //test valid voxels std::vector voxelsAsIndexToTest; std::vector expectedValues; voxelsAsIndexToTest.push_back(VoxelGridIndex3D(5, 9, 8)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(22, 15, 10)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(30, 20, 7)); expectedValues.push_back(5.0 * doseGridScaling); expectedValues.push_back(22.0 * doseGridScaling); expectedValues.push_back(30.0 * doseGridScaling); //convert VoxelGridIndex3D to VoxelGridID for (int i = 0; i < voxelsAsIndexToTest.size(); i++) { VoxelGridID currentId; doseAccessor1GeometricInfo.convert(voxelsAsIndexToTest.at(i), currentId); //test if the expected interpolation values are computed CHECK_EQUAL(aSimpleMappableDoseAccessorITKIdentity->getDoseAt(voxelsAsIndexToTest.at(i)), expectedValues.at(i)); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aSimpleMappableDoseAccessorITKIdentity->getDoseAt(voxelsAsIndexToTest.at(i)), aSimpleMappableDoseAccessorITKIdentity->getDoseAt(currentId)); } //no tests with invalid IDs, this has been done already tested in SimpleMappableDoseAccessorTest //b) with translation transform //translation of one voxel in each direction expectedValues.clear(); expectedValues.push_back(6.0 * doseGridScaling); expectedValues.push_back(23.0 * doseGridScaling); expectedValues.push_back(31.0 * doseGridScaling); for (int i = 0; i < voxelsAsIndexToTest.size(); i++) { VoxelGridID currentId; doseAccessor1GeometricInfo.convert(voxelsAsIndexToTest.at(i), currentId); //test if the expected interpolation values are computed CHECK_EQUAL(aSimpleMappableDoseAccessorITKTranslation->getDoseAt(voxelsAsIndexToTest.at(i)), expectedValues.at(i)); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aSimpleMappableDoseAccessorITKTranslation->getDoseAt(voxelsAsIndexToTest.at(i)), aSimpleMappableDoseAccessorITKTranslation->getDoseAt(currentId)); } RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/interpolation/InterpolationTest.cpp b/testing/interpolation/InterpolationTest.cpp index 112f795..6db13a7 100644 --- a/testing/interpolation/InterpolationTest.cpp +++ b/testing/interpolation/InterpolationTest.cpp @@ -1,224 +1,224 @@ // ----------------------------------------------------------------------- // 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 #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbLinearInterpolation.h" #include "rttbDicomDoseAccessor.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace testing { typedef rttb::interpolation::NearestNeighborInterpolation NearestNeighborInterpolation; typedef rttb::interpolation::LinearInterpolation LinearInterpolation; typedef rttb::core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; /*! @brief InterpolationTest - tests only interpolation 1) test both interpolation types with simple image (Dose = 2) 2) test both interpolation types with increasing x image values image (Dose = y value) 3) test exception handling */ int InterpolationTest(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 InterpolationTest expected" << std::endl; return -1; } rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1( RTDOSE_FILENAME_CONSTANT_TWO.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); DoseAccessorPointer doseAccessorNull; rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2( RTDOSE_FILENAME_INCREASE_X.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); //doseAccessor1 is used as dose image boost::shared_ptr interpolationNN = boost::shared_ptr(new NearestNeighborInterpolation()); interpolationNN->setDoseAccessorPointer(doseAccessor1); boost::shared_ptr interpolationLinear = boost::shared_ptr (new LinearInterpolation()); interpolationLinear->setDoseAccessorPointer(doseAccessor1); //doseAccessor2 is used as dose image. //RTDOSE_FILENAME_INCREASE_X and RTDOSE_FILENAME_CONSTANT_TWO have the same GeometricInfo boost::shared_ptr interpolationNN2 = boost::shared_ptr(new NearestNeighborInterpolation()); interpolationNN2->setDoseAccessorPointer(doseAccessor2); boost::shared_ptr interpolationLinear2 = boost::shared_ptr(new LinearInterpolation()); interpolationLinear2->setDoseAccessorPointer(doseAccessor2); boost::shared_ptr interpolationNullNN = boost::shared_ptr(new NearestNeighborInterpolation()); boost::shared_ptr interpolationNullLinear = boost::shared_ptr(new LinearInterpolation()); rttb::WorldCoordinate3D imagePositionPatient = doseAccessor1->getGeometricInfo().getImagePositionPatient(); rttb::SpacingVectorType3D pixelSpacing = doseAccessor1->getGeometricInfo().getSpacing(); int size[] = {doseAccessor1->getGeometricInfo().getNumColumns(), doseAccessor1->getGeometricInfo().getNumRows(), doseAccessor1->getGeometricInfo().getNumSlices()}; //check position [0 0 0], [max/2, max/2, max/2], [max max max] and combinations (as pixel positions are given at middle, correct with PixelSpacing/2) //outermost position of the image max_x = (coordinatesZeroAndMaxX.at(0) + (size[0]*pixelSpacing.x()) can't be used, because this is already outside of the image, thus test max-0.001. std::vector coordinatesZeroAndMaxX; coordinatesZeroAndMaxX.push_back(imagePositionPatient.x() - (pixelSpacing.x() * 0.5)); coordinatesZeroAndMaxX.push_back(coordinatesZeroAndMaxX.at(0) + (size[0] *pixelSpacing.x() - 0.001)); coordinatesZeroAndMaxX.push_back(coordinatesZeroAndMaxX.at(0) + ((size[0] - 1)*pixelSpacing.x() * 0.5)); std::vector coordinatesZeroAndMaxY; coordinatesZeroAndMaxY.push_back(imagePositionPatient.y() - (pixelSpacing.y() * 0.5)); coordinatesZeroAndMaxY.push_back(coordinatesZeroAndMaxY.at(0) + (size[1] *pixelSpacing.y() - 0.001)); coordinatesZeroAndMaxY.push_back(coordinatesZeroAndMaxY.at(0) + ((size[1] - 1)*pixelSpacing.y() * 0.5)); std::vector coordinatesZeroAndMaxZ; coordinatesZeroAndMaxZ.push_back(imagePositionPatient.z() - (pixelSpacing.z() * 0.5)); coordinatesZeroAndMaxZ.push_back(coordinatesZeroAndMaxZ.at(0) + (size[2] *pixelSpacing.z() - 0.001)); coordinatesZeroAndMaxZ.push_back(coordinatesZeroAndMaxZ.at(0) + ((size[2] - 1)*pixelSpacing.z() * 0.5)); std::vector coordinatesToCheck; for (int x = 0; x < coordinatesZeroAndMaxX.size(); x++) { for (int y = 0; y < coordinatesZeroAndMaxY.size(); y++) { for (int z = 0; z < coordinatesZeroAndMaxZ.size(); z++) { coordinatesToCheck.push_back(rttb::WorldCoordinate3D(coordinatesZeroAndMaxX.at(x), coordinatesZeroAndMaxY.at(y), coordinatesZeroAndMaxZ.at(z))); } } } rttb::WorldCoordinate3D positionOutsideOfImageLeft = imagePositionPatient - rttb::WorldCoordinate3D( pixelSpacing.x() * 2.0, pixelSpacing.y() * 2.0, pixelSpacing.z() * 2.0); rttb::WorldCoordinate3D positionOutsideOfImageRight = imagePositionPatient + rttb::WorldCoordinate3D(size[0] * pixelSpacing.x(), size[1] * pixelSpacing.y(), size[2] * pixelSpacing.z()) + rttb::WorldCoordinate3D(pixelSpacing.x() * 2.0, pixelSpacing.y() * 2.0, pixelSpacing.z() * 2.0); //precomputed values for Nearest neighbor + Linear interpolator double expectedDoseIncreaseXNearest[27]; double expectedDoseIncreaseXLinear[27]; for (int i = 0; i < 27; i++) { if (i < 9) { expectedDoseIncreaseXNearest[i] = 0.0; expectedDoseIncreaseXLinear[i] = 0.0; } else if (i < 18) { expectedDoseIncreaseXNearest[i] = 0.00186277; expectedDoseIncreaseXLinear[i] = 0.00186277; } else { expectedDoseIncreaseXNearest[i] = 0.000931387; expectedDoseIncreaseXLinear[i] = 0.000931387; } } //TEST 1) RTDOSE_FILENAME_CONSTANT_TWO contains Dose 2.0 Gy for each pixel, so for every interpolation, 2.0 has to be the result std::vector::const_iterator iterCoordinates = coordinatesToCheck.cbegin(); while (iterCoordinates != coordinatesToCheck.cend()) { CHECK_EQUAL(interpolationNN->getValue(*iterCoordinates), 2.0); CHECK_EQUAL(interpolationLinear->getValue(*iterCoordinates), 2.0); ++iterCoordinates; } //TEST 2) RTDOSE_FILENAME_INCREASE_X contains a Dose gradient file, correct interpolation values have been computed manually. To avoid floating point inaccuracy, CHECK_CLOSE is used iterCoordinates = coordinatesToCheck.cbegin(); unsigned int index = 0; while (iterCoordinates != coordinatesToCheck.cend() && index < 27) { CHECK_CLOSE(interpolationNN2->getValue(*iterCoordinates), expectedDoseIncreaseXNearest[index], errorConstant); CHECK_CLOSE(interpolationLinear2->getValue(*iterCoordinates), expectedDoseIncreaseXLinear[index], errorConstant); ++iterCoordinates; ++index; } //TEST 3) Exception handling //Check that core::MappingOutOfImageException is thrown if requested position is outside image CHECK_THROW_EXPLICIT(interpolationNN->getValue(positionOutsideOfImageLeft), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(interpolationNN->getValue(positionOutsideOfImageRight), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(interpolationLinear->getValue(positionOutsideOfImageLeft), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(interpolationLinear->getValue(positionOutsideOfImageRight), core::MappingOutsideOfImageException); //Check that core::NullPointerException is thrown if Null Pointers are given to interpolator CHECK_THROW_EXPLICIT(interpolationNullLinear->setDoseAccessorPointer(doseAccessorNull), core::NullPointerException); CHECK_THROW_EXPLICIT(interpolationNullNN->setDoseAccessorPointer(doseAccessorNull), core::NullPointerException); CHECK_THROW_EXPLICIT(interpolationNullLinear->getValue(coordinatesToCheck.front()), core::NullPointerException); CHECK_THROW_EXPLICIT(interpolationNullNN->getValue(coordinatesToCheck.front()), core::NullPointerException); //Check that no exception is thrown otherwise - CHECK_NO_THROW(NearestNeighborInterpolation::NearestNeighborInterpolation()); - CHECK_NO_THROW(LinearInterpolation::LinearInterpolation()); + CHECK_NO_THROW(new NearestNeighborInterpolation()); + CHECK_NO_THROW(new LinearInterpolation()); RETURN_AND_REPORT_TEST_SUCCESS; } } -} \ No newline at end of file +} diff --git a/testing/interpolation/MatchPointBinding/SimpleMappableDoseAccessorWithMatchPointTest.cpp b/testing/interpolation/MatchPointBinding/SimpleMappableDoseAccessorWithMatchPointTest.cpp index ac38381..562725e 100644 --- a/testing/interpolation/MatchPointBinding/SimpleMappableDoseAccessorWithMatchPointTest.cpp +++ b/testing/interpolation/MatchPointBinding/SimpleMappableDoseAccessorWithMatchPointTest.cpp @@ -1,248 +1,248 @@ // ----------------------------------------------------------------------- // 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: 741 $ (last changed revision) // @date $Date: 2014-09-16 16:34:22 +0200 (Di, 16 Sep 2014) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbSimpleMappableDoseAccessor.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbLinearInterpolation.h" #include "rttbGeometricInfo.h" #include "rttbTransformationInterface.h" #include "rttbMatchPointTransformation.h" #include "rttbNullPointerException.h" #include "registrationTest.h" #include "simpleRegistrationWorkflow.h" namespace rttb { namespace testing { static const unsigned int TargetDimension3D = 3; static const unsigned int MovingDimension3D = 3; typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef rttb::interpolation::SimpleMappableDoseAccessor SimpleMappableDoseAccessor; typedef map::core::RegistrationTest Registration3D3DTypeTest; typedef Registration3D3DTypeTest::Pointer Registration3D3DTypeTestPointer; typedef map::core::Registration Registration3D3DType; typedef Registration3D3DType::Pointer Registration3D3DPointer; typedef rttb::interpolation::NearestNeighborInterpolation NearestNeighborInterpolation; typedef rttb::interpolation::LinearInterpolation LinearInterpolation; typedef rttb::interpolation::TransformationInterface TransformationInterface; typedef rttb::interpolation::MatchPointTransformation MatchPointTransformation; /*! @brief SimpleMappableDoseAccessorWithMatchPointTest - test the API of SimpleMappableDoseAccessor with MatchPoint transform 1) Test constructor 2) test getDoseAt() a) with Identity transform b) with translation transform [3) test with rigid registration optional (if filenames are given as argument)] */ int SimpleMappableDoseAccessorWithMatchPointTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; std::string RTDOSE_FILENAME_CONSTANT_TWO; std::string RTDOSE_FILENAME_INCREASE_X; std::string RTDOSE_FILENAME_REALISTIC = ""; std::string CT_PLANNING = ""; std::string CT_FRACTION = ""; if (argc > 2) { RTDOSE_FILENAME_CONSTANT_TWO = argv[1]; RTDOSE_FILENAME_INCREASE_X = argv[2]; } else { std::cout << "at least two parameters for SimpleMappableDoseAccessorWithMatchPointTest are expected" << std::endl; return -1; } if (argc > 5) { RTDOSE_FILENAME_REALISTIC = argv[3]; CT_PLANNING = argv[4]; CT_FRACTION = argv[5]; } rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1( RTDOSE_FILENAME_CONSTANT_TWO.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); DoseAccessorPointer doseAccessorNull; rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2( RTDOSE_FILENAME_INCREASE_X.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); core::GeometricInfo doseAccessor1GeometricInfo = doseAccessor1->getGeometricInfo(); Registration3D3DTypeTestPointer registration = Registration3D3DTypeTest::New(); double translation[] = {0.0, 0.0, 0.0}; registration->_translation = translation; registration->_limitedTarget = false; - auto interpolationNN = + NearestNeighborInterpolation::Pointer interpolationNN = NearestNeighborInterpolation::Pointer(new NearestNeighborInterpolation()); - auto interpolationLinear = boost::shared_ptr + LinearInterpolation::Pointer interpolationLinear = LinearInterpolation::Pointer (new LinearInterpolation()); - boost::shared_ptr interpolationNull; + NearestNeighborInterpolation::Pointer interpolationNull; - auto transformMP = TransformationInterface::Pointer(new MatchPointTransformation( + TransformationInterface::Pointer transformMP = TransformationInterface::Pointer(new MatchPointTransformation( registration.GetPointer())); - auto aSimpleMappableDoseAccessorMPIdentityLinear = new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear); - auto aSimpleMappableDoseAccessorMPIdentityNN = new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN); + SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorMPIdentityLinear = SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor( + doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear)); + SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorMPIdentityNN = SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor( + doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN)); //1) Test constructor CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear)); CHECK_NO_THROW(SimpleMappableDoseAccessor( doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN)); CHECK_NO_THROW(MatchPointTransformation(registration.GetPointer())); CHECK_THROW_EXPLICIT(MatchPointTransformation(NULL), core::NullPointerException); //2) test getDoseAt() // a) with Identity transform double vectorDoseAccessorStartEnd = 0.0; while (vectorDoseAccessorStartEnd <= 1.0) { VoxelGridID runningID = (VoxelGridID)(vectorDoseAccessorStartEnd * (double)aSimpleMappableDoseAccessorMPIdentityLinear->getGridSize()); CHECK_EQUAL(aSimpleMappableDoseAccessorMPIdentityLinear->getDoseAt(runningID), doseAccessor2->getDoseAt(runningID)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPIdentityNN->getDoseAt(runningID), doseAccessor2->getDoseAt(runningID)); vectorDoseAccessorStartEnd += 0.1; } // b) with translation transform //Second: Translation (5mm/5mm/5mm) --> in voxel: (1/1/1) as pixelspacing = 5 mm translation[0] = translation[1] = translation[2] = 5.0; registration->_translation = translation; - auto aSimpleMappableDoseAccessorMPTranslationLinear = new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear); - auto aSimpleMappableDoseAccessorMPTranslationNN = new SimpleMappableDoseAccessor( - doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN); + SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorMPTranslationLinear = SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor( + doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationLinear)); + SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorMPTranslationNN = SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor( + doseAccessor1GeometricInfo, doseAccessor2, transformMP, interpolationNN)); rttb::VoxelGridIndex3D aIndexBeforeTransformation(0, 0, 0); rttb::VoxelGridIndex3D aIndexAfterTransformation(1, 1, 1); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationLinear->getDoseAt(aIndexBeforeTransformation), doseAccessor2->getDoseAt(aIndexAfterTransformation)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationNN->getDoseAt(aIndexBeforeTransformation), doseAccessor2->getDoseAt(aIndexAfterTransformation)); rttb::VoxelGridIndex3D aIndexBeforeTransformation2(20, 10, 10); rttb::VoxelGridIndex3D aIndexAfterTransformation2(21, 11, 11); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationLinear->getDoseAt(aIndexBeforeTransformation2), doseAccessor2->getDoseAt(aIndexAfterTransformation2)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationNN->getDoseAt(aIndexBeforeTransformation2), doseAccessor2->getDoseAt(aIndexAfterTransformation2)); rttb::VoxelGridIndex3D aIndexBeforeTransformation3( aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumColumns() - 2, aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumRows() - 2, aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumSlices() - 2); rttb::VoxelGridIndex3D aIndexAfterTransformation3( aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumColumns() - 1, aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumRows() - 1, aSimpleMappableDoseAccessorMPTranslationLinear->getGeometricInfo().getNumSlices() - 1); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationLinear->getDoseAt(aIndexBeforeTransformation3), doseAccessor2->getDoseAt(aIndexAfterTransformation3)); CHECK_EQUAL(aSimpleMappableDoseAccessorMPTranslationNN->getDoseAt(aIndexBeforeTransformation3), doseAccessor2->getDoseAt(aIndexAfterTransformation3)); if (RTDOSE_FILENAME_REALISTIC != "" && CT_FRACTION != "" && CT_PLANNING != "") { //3) test with rigid registration //realistic background: registration from BP-CT to fraction CT, apply on planning dose that is based on BP-CT (proof of concept) //Target image: fraction CT, Moving image: planning CT simpleRegistrationWorkflow prepareRegistrationRealisticScenario(CT_FRACTION, CT_PLANNING, true); Registration3D3DPointer registrationRealisticScenario = prepareRegistrationRealisticScenario.getRegistration(); - auto transformRealistic = TransformationInterface::Pointer(new MatchPointTransformation( + TransformationInterface::Pointer transformRealistic = TransformationInterface::Pointer(new MatchPointTransformation( registrationRealisticScenario)); io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator3(RTDOSE_FILENAME_REALISTIC.c_str()); DoseAccessorPointer doseAccessor3(doseAccessorGenerator3.generateDoseAccessor()); core::GeometricInfo geoInfoRealistic; geoInfoRealistic.setNumColumns( prepareRegistrationRealisticScenario.getTargetImage()->GetLargestPossibleRegion().GetSize()[0]); geoInfoRealistic.setNumRows( prepareRegistrationRealisticScenario.getTargetImage()->GetLargestPossibleRegion().GetSize()[1]); geoInfoRealistic.setNumSlices( prepareRegistrationRealisticScenario.getTargetImage()->GetLargestPossibleRegion().GetSize()[2]); //Dose is related to BP-CT, map dose to fraction CT geometry - auto aSimpleMappableDoseAccessorRealisticScenarioLinear = - new SimpleMappableDoseAccessor(geoInfoRealistic, - doseAccessor3, transformRealistic, interpolationLinear); + SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorRealisticScenarioLinear = + SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor(geoInfoRealistic, + doseAccessor3, transformRealistic, interpolationLinear)); //combination of 0, size/2 and size to check as coordinates std::vector coordinatesToCheckX, coordinatesToCheckY, coordinatesToCheckZ; coordinatesToCheckX.push_back(0); coordinatesToCheckX.push_back(geoInfoRealistic.getNumColumns() / 2); coordinatesToCheckX.push_back(geoInfoRealistic.getNumColumns() - 1); coordinatesToCheckY.push_back(0); coordinatesToCheckY.push_back(geoInfoRealistic.getNumRows() / 2); coordinatesToCheckY.push_back(geoInfoRealistic.getNumRows() - 1); coordinatesToCheckZ.push_back(0); coordinatesToCheckZ.push_back(geoInfoRealistic.getNumSlices() / 2); coordinatesToCheckZ.push_back(geoInfoRealistic.getNumSlices() - 1); //Pixels are inside the fraction CT image and mapping should work (even if they map outside of doseAccessor3) for (unsigned int i = 0; i < coordinatesToCheckX.size(); ++i) { for (unsigned int j = 0; j < coordinatesToCheckY.size(); ++j) { for (unsigned int k = 0; k < coordinatesToCheckZ.size(); ++k) { CHECK_NO_THROW(aSimpleMappableDoseAccessorRealisticScenarioLinear->getDoseAt(VoxelGridIndex3D( coordinatesToCheckX.at(i), coordinatesToCheckY.at(j), coordinatesToCheckZ.at(k)))); } } } } RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/interpolation/MatchPointBinding/registrationTest.h b/testing/interpolation/MatchPointBinding/registrationTest.h index ab3a4a9..131c9ff 100644 --- a/testing/interpolation/MatchPointBinding/registrationTest.h +++ b/testing/interpolation/MatchPointBinding/registrationTest.h @@ -1,79 +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: 741 $ (last changed revision) // @date $Date: 2014-09-16 16:34:22 +0200 (Di, 16 Sep 2014) $ (last change date) // @author $Author: hentsch $ (last changed by) */ #ifndef __REGISTRATION_TEST_H #define __REGISTRATION_TEST_H #include "mapRegistration.h" namespace map { namespace core { /*! @class TestRegistration @brief Simple implementation of MatchPoint Registration class with direct access to mapping. */ template class RegistrationTest: public Registration { public: typedef RegistrationTest Self; typedef RegistrationBase Superclass; typedef itk::SmartPointer Pointer; typedef itk::SmartPointer ConstPointer; + typedef typename Registration::TargetPointType TargetPointType; + typedef typename Registration::MovingPointType MovingPointType; + itkTypeMacro(RegistrationTest, Registration); itkNewMacro(Self); bool _limitedTarget; double* _translation; RegistrationTest() {}; ~RegistrationTest() { }; virtual bool mapPointInverse(const TargetPointType& inPoint, MovingPointType& outPoint) const { for (unsigned int i = 0; i < VTargetDimensions; i++) { outPoint[i] = inPoint[i] + _translation[i]; } return true; }; virtual bool hasLimitedTargetRepresentation() const { return _limitedTarget; } private: RegistrationTest(const Self& source); //purposely not implemented void operator=(const Self&); //purposely not implemented }; } } -#endif \ No newline at end of file +#endif diff --git a/testing/interpolation/SimpleMappableDoseAccessorTest.cpp b/testing/interpolation/SimpleMappableDoseAccessorTest.cpp index 84ad44d..4df9b43 100644 --- a/testing/interpolation/SimpleMappableDoseAccessorTest.cpp +++ b/testing/interpolation/SimpleMappableDoseAccessorTest.cpp @@ -1,165 +1,164 @@ // ----------------------------------------------------------------------- // 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 "rttbBaseType.h" #include "rttbGenericDoseIterator.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbSimpleMappableDoseAccessor.h" #include "rttbNearestNeighborInterpolation.h" #include "rttbLinearInterpolation.h" #include "rttbTransformationInterface.h" #include "DummyTransformation.h" #include "rttbNullPointerException.h" #include "rttbMappingOutsideOfImageException.h" namespace rttb { namespace testing { typedef core::GenericDoseIterator::DoseAccessorPointer DoseAccessorPointer; typedef rttb::interpolation::SimpleMappableDoseAccessor SimpleMappableDoseAccessor; typedef rttb::interpolation::TransformationInterface TransformationInterface; typedef rttb::interpolation::LinearInterpolation LinearInterpolation; typedef rttb::interpolation::NearestNeighborInterpolation NearestNeighborInterpolation; /*! @brief SimpleMappableDoseAccessorTest - test the API of SimpleMappableDoseAccessor 1) Test constructor 2) test getDoseAt() */ int SimpleMappableDoseAccessorTest(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 SimpleMappableDoseAccessorTest are expected" << std::endl; return -1; } const double doseGridScaling = 2.822386e-005; rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1( RTDOSE_FILENAME_CONSTANT_TWO.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); core::GeometricInfo doseAccessor1GeometricInfo = doseAccessor1->getGeometricInfo(); rttb::io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2( RTDOSE_FILENAME_INCREASE_X.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); DoseAccessorPointer doseAccessorNull; - auto transformDummy = TransformationInterface::Pointer(new DummyTransformation()); + TransformationInterface::Pointer transformDummy = TransformationInterface::Pointer(new DummyTransformation()); TransformationInterface::Pointer transformNull; - auto interpolationNN = + NearestNeighborInterpolation::Pointer interpolationNN = NearestNeighborInterpolation::Pointer(new NearestNeighborInterpolation()); - auto interpolationLinear = boost::shared_ptr - (new LinearInterpolation()); + LinearInterpolation::Pointer interpolationLinear = LinearInterpolation::Pointer(new LinearInterpolation()); boost::shared_ptr interpolationNull; - auto aSimpleMappableDoseAccessorDefault = new SimpleMappableDoseAccessor( - doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear); - auto aSimpleMappableDoseAccessorNoPadding = new SimpleMappableDoseAccessor( - doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear, false); + SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorDefault = SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor( + doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear)); + SimpleMappableDoseAccessor::Pointer aSimpleMappableDoseAccessorNoPadding = SimpleMappableDoseAccessor::Pointer(new SimpleMappableDoseAccessor( + doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear, false)); //1) Test constructor CHECK_NO_THROW(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear)); CHECK_NO_THROW(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear, false)); CHECK_NO_THROW(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformDummy, interpolationLinear, true, 5.0)); CHECK_NO_THROW(SimpleMappableDoseAccessor(doseAccessor1GeometricInfo, doseAccessor2, transformDummy, interpolationNN)); CHECK_THROW_EXPLICIT(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessorNull, transformDummy, interpolationLinear), core::NullPointerException); CHECK_THROW_EXPLICIT(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessor2, transformNull, interpolationLinear), core::NullPointerException); CHECK_THROW_EXPLICIT(SimpleMappableDoseAccessor test(doseAccessor1->getGeometricInfo(), doseAccessorNull, transformNull, interpolationLinear), core::NullPointerException); CHECK_THROW_EXPLICIT(SimpleMappableDoseAccessor(doseAccessor1GeometricInfo, doseAccessor2, transformDummy, interpolationNull), core::NullPointerException); //2) test getGeometricInfo(), getGridSize(), getDoseUID() function CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getGeometricInfo(), doseAccessor1->getGeometricInfo()); CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getGridSize(), doseAccessor1->getGeometricInfo().getNumberOfVoxels()); CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getDoseUID(), doseAccessor2->getDoseUID()); //3) test getDoseAt() //test valid voxels std::vector voxelsAsIndexToTest; std::vector expectedValues; voxelsAsIndexToTest.push_back(VoxelGridIndex3D(5, 9, 8)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(22, 15, 10)); voxelsAsIndexToTest.push_back(VoxelGridIndex3D(30, 20, 7)); expectedValues.push_back(5.0 * doseGridScaling); expectedValues.push_back(22.0 * doseGridScaling); expectedValues.push_back(30.0 * doseGridScaling); for (int i = 0; i < voxelsAsIndexToTest.size(); i++) { VoxelGridID currentId; doseAccessor1GeometricInfo.convert(voxelsAsIndexToTest.at(i), currentId); //test if the expected interpolation values are computed CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getDoseAt(currentId), expectedValues.at(i)); //test if getDoseAt(VoxelGridIndex3D) and getDoseAt(VoxelGridD) lead to the same results CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getDoseAt(currentId), aSimpleMappableDoseAccessorDefault->getDoseAt(voxelsAsIndexToTest.at(i))); } //test invalid voxels VoxelGridID invalidID(doseAccessor1GeometricInfo.getNumberOfVoxels() + 1); VoxelGridIndex3D invalidIndex(doseAccessor1GeometricInfo.getNumColumns() + 1, doseAccessor1GeometricInfo.getNumRows() + 1, doseAccessor1GeometricInfo.getNumSlices() + 1); CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getDoseAt(invalidID), 0.0); CHECK_EQUAL(aSimpleMappableDoseAccessorDefault->getDoseAt(invalidIndex), 0.0); CHECK_THROW_EXPLICIT(aSimpleMappableDoseAccessorNoPadding->getDoseAt(invalidID), core::MappingOutsideOfImageException); CHECK_THROW_EXPLICIT(aSimpleMappableDoseAccessorNoPadding->getDoseAt(invalidIndex), core::MappingOutsideOfImageException); RETURN_AND_REPORT_TEST_SUCCESS; } }//end namespace testing }//end namespace rttb diff --git a/testing/io/itk/ITKDoseAccessorGeneratorTest.cpp b/testing/io/itk/ITKDoseAccessorGeneratorTest.cpp index d443382..2172089 100644 --- a/testing/io/itk/ITKDoseAccessorGeneratorTest.cpp +++ b/testing/io/itk/ITKDoseAccessorGeneratorTest.cpp @@ -1,95 +1,95 @@ // ----------------------------------------------------------------------- // 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) */ // 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 "rttbITKImageDoseAccessor.h" #include "rttbITKImageFileDoseAccessorGenerator.h" #include "rttbITKImageDoseAccessorGenerator.h" #include "rttbInvalidDoseException.h" namespace rttb { namespace testing { /*!@brief ITKDoseAccessorGeneratorTest - test the generators for dicom data 1) test itk file generator generateDoseAccessor() 2) test itk generator generateDoseAccessor() */ int ITKDoseAccessorGeneratorTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: // 1: mhd/raw file name std::string RTDOSE_FILENAME; if (argc > 1) { RTDOSE_FILENAME = argv[1]; } /* test ITKFileDoseAccessorGenerator generateDoseAccessor()*/ CHECK_THROW_EXPLICIT(io::itk::ITKImageFileDoseAccessorGenerator("test.test").generateDoseAccessor(), core::InvalidDoseException); CHECK_NO_THROW(io::itk::ITKImageFileDoseAccessorGenerator( RTDOSE_FILENAME.c_str()).generateDoseAccessor()); /* test ITKDoseAccessorGenerator generateDoseAccessor()*/ typedef itk::Image< DoseTypeGy, 3 > DoseImageType; typedef itk::ImageFileReader ReaderType; - DoseImageType::ConstPointer invalidDose = DoseImageType::New(); + DoseImageType::Pointer invalidDose = DoseImageType::New(); ReaderType::Pointer reader = ReaderType::New(); CHECK_THROW_EXPLICIT(io::itk::ITKImageDoseAccessorGenerator( invalidDose.GetPointer()).generateDoseAccessor(), core::InvalidDoseException); reader->SetFileName(RTDOSE_FILENAME); //important to update the reader (won't work without) reader->Update(); CHECK_NO_THROW(io::itk::ITKImageDoseAccessorGenerator(reader->GetOutput()).generateDoseAccessor()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/itk/ITKMaskAccessorConverterTest.cpp b/testing/io/itk/ITKMaskAccessorConverterTest.cpp index 60b0e1e..4b8f48d 100644 --- a/testing/io/itk/ITKMaskAccessorConverterTest.cpp +++ b/testing/io/itk/ITKMaskAccessorConverterTest.cpp @@ -1,162 +1,162 @@ // ----------------------------------------------------------------------- // 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" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbITKImageMaskAccessorConverter.h" #include "rttbITKImageFileMaskAccessorGenerator.h" #include "rttbOTBMaskAccessor.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 ITKMaskAccessorConverterTest(int argc, char* argv[]) { typedef core::DoseIteratorInterface::DoseAccessorPointer DoseAccessorPointer; typedef core::StructureSetGeneratorInterface::StructureSetPointer StructureSetPointer; typedef core::MaskAccessorInterface::MaskAccessorPointer MaskAccessorPointer; typedef io::itk::ITKImageMaskAccessor::ITKMaskImageType::Pointer ITKImageTypePointer; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: //ARGUMENTS: 1: structure file name // 2: dose1 file name std::string RTStr_FILENAME; std::string RTDose_FILENAME; std::string Mask_FILENAME; if (argc > 3) { RTStr_FILENAME = argv[1]; RTDose_FILENAME = argv[2]; Mask_FILENAME = argv[3]; } //1) Read dicomFile and test getITKImage() io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1(RTDose_FILENAME.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); StructureSetPointer rtStructureSet = io::dicom::DicomFileStructureSetGenerator( RTStr_FILENAME.c_str()).generateStructureSet(); MaskAccessorPointer maskAccessorPtr = boost::make_shared(rtStructureSet->getStructure(0), doseAccessor1->getGeometricInfo()); maskAccessorPtr->updateMask();//!Important: Update the mask before conversion. io::itk::ITKImageMaskAccessorConverter maskAccessorConverter(maskAccessorPtr); CHECK_NO_THROW(maskAccessorConverter.process()); CHECK_NO_THROW(maskAccessorConverter.getITKImage()); //2) Read itk image, generate mask and convert it back to itk image, check equal MaskAccessorPointer maskAccessorPtr2 = io::itk::ITKImageFileMaskAccessorGenerator(Mask_FILENAME.c_str()).generateMaskAccessor(); maskAccessorPtr2->updateMask();//!Important: Update the mask before conversion. io::itk::ITKImageMaskAccessorConverter maskAccessorConverter2(maskAccessorPtr2); maskAccessorConverter2.process(); typedef itk::Image< DoseTypeGy, 3 > MaskImageType; typedef itk::ImageFileReader ReaderType; ITKImageTypePointer convertedImagePtr = maskAccessorConverter2.getITKImage(); - io::itk::ITKImageMaskAccessor::ITKMaskImageType::ConstPointer expectedImage = + io::itk::ITKImageMaskAccessor::ITKMaskImageType::Pointer expectedImage = lit::TestImageIO::readImage( Mask_FILENAME); CHECK_EQUAL(convertedImagePtr->GetOrigin()[0], expectedImage->GetOrigin()[0]); CHECK_EQUAL(convertedImagePtr->GetOrigin()[1], expectedImage->GetOrigin()[1]); CHECK_EQUAL(convertedImagePtr->GetOrigin()[2], expectedImage->GetOrigin()[2]); CHECK_EQUAL(convertedImagePtr->GetSpacing()[0], expectedImage->GetSpacing()[0]); CHECK_EQUAL(convertedImagePtr->GetSpacing()[1], expectedImage->GetSpacing()[1]); CHECK_EQUAL(convertedImagePtr->GetSpacing()[2], expectedImage->GetSpacing()[2]); int sizeX = convertedImagePtr->GetLargestPossibleRegion().GetSize()[0]; int sizeY = convertedImagePtr->GetLargestPossibleRegion().GetSize()[1]; int sizeZ = convertedImagePtr->GetLargestPossibleRegion().GetSize()[2]; io::itk::ITKImageMaskAccessor::ITKMaskImageType::IndexType index; for(unsigned int i=0; i<20 && iGetPixel(index) >= 0 && expectedImage->GetPixel(index)<=1){ CHECK_EQUAL(convertedImagePtr->GetPixel(index), expectedImage->GetPixel(index)); } } for(unsigned int i=0; i<20; i++){ index[0] = sizeX -1-i; index[1] = sizeY -1-i; index[2] = sizeZ -1-i; if(expectedImage->GetPixel(index) >= 0 && expectedImage->GetPixel(index)<=1){ CHECK_EQUAL(convertedImagePtr->GetPixel(index), expectedImage->GetPixel(index)); } } for(unsigned int i=0; i<20 && (sizeX/2 -i) < sizeX && (sizeY/2 -i) < sizeY && (sizeZ/2 -i) < sizeZ; i++){ index[0] = sizeX/2 -i; index[1] = sizeY/2 -i; index[2] = sizeZ/2 -i; if(expectedImage->GetPixel(index) >= 0 && expectedImage->GetPixel(index)<=1){ CHECK_EQUAL(convertedImagePtr->GetPixel(index), expectedImage->GetPixel(index)); } } RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/itk/ITKMaskAccessorGeneratorTest.cpp b/testing/io/itk/ITKMaskAccessorGeneratorTest.cpp index f162d78..b807b6d 100644 --- a/testing/io/itk/ITKMaskAccessorGeneratorTest.cpp +++ b/testing/io/itk/ITKMaskAccessorGeneratorTest.cpp @@ -1,97 +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: 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 ITKMaskAccessorGeneratorTest(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 ITKImageFileMaskAccessorGenerator generateDoseAccessor()*/ CHECK_THROW_EXPLICIT(io::itk::ITKImageFileMaskAccessorGenerator("test.test").generateMaskAccessor(), core::InvalidDoseException); CHECK_NO_THROW(io::itk::ITKImageFileMaskAccessorGenerator( Mask_FILENAME.c_str()).generateMaskAccessor()); /* test ITKImageMaskAccessorGenerator generateDoseAccessor()*/ typedef itk::Image< DoseTypeGy, 3 > MaskImageType; typedef itk::ImageFileReader ReaderType; - MaskImageType::ConstPointer invalidDose = MaskImageType::New(); + MaskImageType::Pointer invalidDose = MaskImageType::New(); ReaderType::Pointer reader = ReaderType::New(); CHECK_THROW_EXPLICIT(io::itk::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::itk::ITKImageMaskAccessorGenerator(reader->GetOutput()).generateMaskAccessor()); io::itk::ITKImageMaskAccessorGenerator::MaskAccessorPointer maskAcc = io::itk::ITKImageMaskAccessorGenerator(reader->GetOutput()).generateMaskAccessor(); CHECK_NO_THROW( maskAcc->getRelevantVoxelVector()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb