diff --git a/code/io/dicom/rttbDVHDicomFileReader.cpp b/code/io/dicom/rttbDVHDicomFileReader.cpp index 481a53f..fe0a5f1 100644 --- a/code/io/dicom/rttbDVHDicomFileReader.cpp +++ b/code/io/dicom/rttbDVHDicomFileReader.cpp @@ -1,51 +1,45 @@ // ----------------------------------------------------------------------- // 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 "rttbDVHDicomFileReader.h" #include "rttbException.h" namespace rttb { namespace io { namespace dicom { DVHDicomFileReader::DVHDicomFileReader(FileNameString aFileName) { this->setFileName(aFileName); this->createDVH(); } void DVHDicomFileReader::setFileName(FileNameString aFileName) { _fileName = aFileName; } void DVHDicomFileReader::createDVH() { assert(false); throw rttb::core::Exception("DICOM DVH reader currently not implemented."); }; } } } diff --git a/code/io/dicom/rttbDVHDicomFileReader.h b/code/io/dicom/rttbDVHDicomFileReader.h index 5b004d9..15fb9e8 100644 --- a/code/io/dicom/rttbDVHDicomFileReader.h +++ b/code/io/dicom/rttbDVHDicomFileReader.h @@ -1,58 +1,53 @@ // ----------------------------------------------------------------------- // 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) -*/ + #ifndef __DVH_DICOM_FILE_READER_H #define __DVH_DICOM_FILE_READER_H #include "rttbBaseType.h" #include "rttbDVHGeneratorInterface.h" namespace rttb { namespace io { namespace dicom { /*! @class DVHDicomFileReader @brief Read DVH data from a dicom file and create corresponding DVH object. */ class DVHDicomFileReader: public core::DVHGeneratorInterface { private: FileNameString _fileName; void createDVH(); public: /*! @brief DVHDicomFileReader Constructor @param aFileName the dicom dvh file name */ DVHDicomFileReader(FileNameString aFileName); /*! @brief Set the dicom dvh file name (triggers data import) @param aFileName the dicom dvh file name */ void setFileName(FileNameString aFileName); }; } } } #endif diff --git a/code/io/dicom/rttbDcmrtException.h b/code/io/dicom/rttbDcmrtException.h index 1707420..ecda6e8 100644 --- a/code/io/dicom/rttbDcmrtException.h +++ b/code/io/dicom/rttbDcmrtException.h @@ -1,49 +1,43 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ #ifndef __DCMRT_EXCEPTION_H #define __DCMRT_EXCEPTION_H #include #include "rttbException.h" namespace rttb { namespace io { namespace dicom { /*! @class DcmrtException @brief This class represents a DcmrtException. Any dcmrt error will throw this exception. */ class DcmrtException: public core::Exception { public: DcmrtException(const std::string& aWhat): Exception(aWhat) {} }; } } } #endif diff --git a/code/io/dicom/rttbDicomDoseAccessor.cpp b/code/io/dicom/rttbDicomDoseAccessor.cpp index 8616ded..a018e77 100644 --- a/code/io/dicom/rttbDicomDoseAccessor.cpp +++ b/code/io/dicom/rttbDicomDoseAccessor.cpp @@ -1,293 +1,285 @@ // ----------------------------------------------------------------------- // 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 "drtdose.h" #include #include #include "rttbDicomDoseAccessor.h" #include "rttbNullPointerException.h" #include "rttbInvalidDoseException.h" #include "rttbDcmrtException.h" #include "rttbIndexOutOfBoundsException.h" - - namespace rttb { namespace io { namespace dicom { DicomDoseAccessor::~DicomDoseAccessor() = default; DicomDoseAccessor::DicomDoseAccessor(DRTDoseIODPtr aDRTDoseIODP, DcmItemPtr aDcmDataset) { _dose = aDRTDoseIODP; _dataSet = aDcmDataset; OFString uid; _dose->getSeriesInstanceUID(uid); _doseUID = uid.c_str(); this->begin(); } bool DicomDoseAccessor::begin() { assembleGeometricInfo(); doseData.clear(); OFString doseGridScalingStr; this->_dose->getDoseGridScaling(doseGridScalingStr); try { _doseGridScaling = boost::lexical_cast(doseGridScalingStr.c_str()); } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("Dose grid scaling not readable or = 0!") ; } OFCondition status; unsigned long count; const Uint16* pixelData; status = _dataSet->findAndGetUint16Array(DcmTagKey(0x7fe0, 0x0010), pixelData, &count); if (status.good()) { for (unsigned int i = 0; i < static_cast(this->_geoInfo.getNumberOfVoxels()); i++) { this->doseData.push_back(pixelData[i]); } return true; } else { throw io::dicom::DcmrtException("Read Pixel Data (7FE0,0010) failed!"); } } void DicomDoseAccessor::assembleGeometricInfo() { Uint16 temp = 0; this->_dose->getColumns(temp); _geoInfo.setNumColumns(temp); temp = 0; this->_dose->getRows(temp); _geoInfo.setNumRows(temp); if (_geoInfo.getNumColumns() == 0 || _geoInfo.getNumRows() == 0) { throw core::InvalidDoseException("Empty dicom dose!") ; } OFString numberOfFramesStr; OFString imageOrientationRowX, imageOrientationRowY, imageOrientationRowZ; OFString imageOrientationColumnX, imageOrientationColumnY, imageOrientationColumnZ; WorldCoordinate3D imageOrientationRow; WorldCoordinate3D imageOrientationColumn; try { this->_dose->getNumberOfFrames(numberOfFramesStr); _geoInfo.setNumSlices(boost::lexical_cast(numberOfFramesStr.c_str())); _dose->getImageOrientationPatient(imageOrientationRowX, 0); _dose->getImageOrientationPatient(imageOrientationRowY, 1); _dose->getImageOrientationPatient(imageOrientationRowZ, 2); _dose->getImageOrientationPatient(imageOrientationColumnX, 3); _dose->getImageOrientationPatient(imageOrientationColumnY, 4); _dose->getImageOrientationPatient(imageOrientationColumnZ, 5); imageOrientationRow(0) = boost::lexical_cast(imageOrientationRowX.c_str()); imageOrientationRow(1) = boost::lexical_cast(imageOrientationRowY.c_str()); imageOrientationRow(2) = boost::lexical_cast(imageOrientationRowZ.c_str()); imageOrientationColumn(0) = boost::lexical_cast(imageOrientationColumnX.c_str()); imageOrientationColumn(1) = boost::lexical_cast(imageOrientationColumnY.c_str()); imageOrientationColumn(2) = boost::lexical_cast(imageOrientationColumnZ.c_str()); } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("boost::lexical_cast failed! Empty dicom dose!") ; } /*Get orientation*/ OrientationMatrix orientation; orientation(0, 0) = imageOrientationRow.x(); orientation(1, 0) = imageOrientationRow.y(); orientation(2, 0) = imageOrientationRow.z(); orientation(0, 1) = imageOrientationColumn.x(); orientation(1, 1) = imageOrientationColumn.y(); orientation(2, 1) = imageOrientationColumn.z(); WorldCoordinate3D perpendicular = imageOrientationRow.cross(imageOrientationColumn); orientation(0, 2) = perpendicular.x(); orientation(1, 2) = perpendicular.y(); orientation(2, 2) = perpendicular.z(); _geoInfo.setOrientationMatrix(orientation); OFString imagePositionX, imagePositionY, imagePositionZ; _dose->getImagePositionPatient(imagePositionX, 0); _dose->getImagePositionPatient(imagePositionY, 1); _dose->getImagePositionPatient(imagePositionZ, 2); WorldCoordinate3D imagePositionPatient; try { imagePositionPatient(0) = boost::lexical_cast(imagePositionX.c_str()); imagePositionPatient(1) = boost::lexical_cast(imagePositionY.c_str()); imagePositionPatient(2) = boost::lexical_cast(imagePositionZ.c_str()); } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("Can not read image position X/Y/Z!") ; } _geoInfo.setImagePositionPatient(imagePositionPatient); /*Get spacing*/ SpacingVectorType3D spacingVector; OFString pixelSpacingRowStr, pixelSpacingColumnStr, sliceThicknessStr; _dose->getPixelSpacing(pixelSpacingRowStr, 0); _dose->getPixelSpacing(pixelSpacingColumnStr, 1); try { spacingVector(1) = boost::lexical_cast(pixelSpacingRowStr.c_str()); spacingVector(0) = boost::lexical_cast(pixelSpacingColumnStr.c_str()); } catch (boost::bad_lexical_cast&) { throw core::InvalidDoseException("Can not read Pixel Spacing Row/Column!") ; } _geoInfo.setSpacing(spacingVector); if (_geoInfo.getSpacing()(0) == 0 || _geoInfo.getSpacing()(1) == 0) { throw core::InvalidDoseException("Pixel spacing is 0!"); } _dose->getSliceThickness(sliceThicknessStr); try { spacingVector(2) = boost::lexical_cast(sliceThicknessStr.c_str()); } catch (boost::bad_lexical_cast&) { spacingVector(2) = 0 ; } if (spacingVector(2) == 0) { OFVector gridFrameOffsetVector; _dose->getGridFrameOffsetVector(gridFrameOffsetVector); if (gridFrameOffsetVector.size() >= 2) { spacingVector(2) = gridFrameOffsetVector.at(1) - gridFrameOffsetVector.at( 0); //read slice thickness from GridFrameOffsetVector (3004,000c) } if (spacingVector(2) == 0) { OFCondition status; DcmItem doseitem; OFString pixelSpacingBetweenSlices; status = _dose->write(doseitem); if (status.good()) { status = doseitem.findAndGetOFString(DcmTagKey(0x0018, 0x0088), pixelSpacingBetweenSlices); try { spacingVector(2) = boost::lexical_cast (pixelSpacingBetweenSlices.c_str());//read slice thickness from PixelSpacingBetweenSlices (0018,0088) } catch (boost::bad_lexical_cast&) { spacingVector(2) = 0 ; } } //if no useful tags to compute slicing -> set slice thickness to spacingVector(0) if (spacingVector(2) == 0) { std::cerr << "sliceThickness == 0! It wird be replaced with pixelSpacingRow=" << _geoInfo.getSpacing()(0) << "!" << std::endl; spacingVector(2) = spacingVector(0); } } } _geoInfo.setSpacing(spacingVector); } GenericValueType DicomDoseAccessor::getValueAt(const VoxelGridID aID) const { return doseData.at(aID) * _doseGridScaling; } GenericValueType DicomDoseAccessor::getValueAt(const VoxelGridIndex3D& aIndex) const { VoxelGridID aVoxelGridID; if (_geoInfo.convert(aIndex, aVoxelGridID)) { return getValueAt(aVoxelGridID); } else { return -1; } } } } } diff --git a/code/io/dicom/rttbDicomDoseAccessor.h b/code/io/dicom/rttbDicomDoseAccessor.h index 2358d28..5e54f62 100644 --- a/code/io/dicom/rttbDicomDoseAccessor.h +++ b/code/io/dicom/rttbDicomDoseAccessor.h @@ -1,99 +1,93 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notices for more information. // //------------------------------------------------------------------------ -/*! -// @file -// @version $Revision$ (last changed revision) -// @date $Date$ (last change date) -// @author $Author$ (last changed by) -*/ + #ifndef __DICOM_DOSE_ACCESSOR_H #define __DICOM_DOSE_ACCESSOR_H #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "drtdose.h" #include #include #include #include "rttbAccessorWithGeoInfoBase.h" #include "rttbBaseType.h" - namespace rttb { namespace io { namespace dicom { /*! @class DicomDoseAccessor @brief This class gives access to dose information from DRTDoseIOD and DcmItem */ class DicomDoseAccessor: public core::AccessorWithGeoInfoBase { public: using DRTDoseIODPtr = boost::shared_ptr; using DcmItemPtr = boost::shared_ptr; private: DRTDoseIODPtr _dose; DcmItemPtr _dataSet; /*! vector of dose data(absolute Gy dose/doseGridScaling)*/ std::vector doseData; double _doseGridScaling; IDType _doseUID; DicomDoseAccessor() = delete; protected: /*! @brief Initialize dose data @exception InvalidDoseException Thrown if _dose is invalid: one of column/row/numberOfFrames/doseGridScaling/pixelSpacing=0 @exception DcmrtException Throw if dcmrt error @exception boost/bad_lexical_cast Thrown if the imported header tags are not numerical. */ bool begin(); /*! @brief get all required data from dicom information contained in _dose @exception boost/bad_lexical_cast Thrown if the imported header tags are not numerical. */ void assembleGeometricInfo() override; public: ~DicomDoseAccessor() override; /*! @brief Constructor. Initialisation with a boost::shared_ptr of DRTDoseIOD and of DcmItem to get the pixel data @exception DcmrtException Throw if dcmrt error */ DicomDoseAccessor(DRTDoseIODPtr aDRTDoseIODP, DcmItemPtr aDcmDataset); GenericValueType getValueAt(const VoxelGridID aID) const override; GenericValueType getValueAt(const VoxelGridIndex3D& aIndex) const override; const IDType getUID() const override { return _doseUID; }; }; } } } #endif diff --git a/code/io/dicom/rttbDicomFileDoseAccessorGenerator.h b/code/io/dicom/rttbDicomFileDoseAccessorGenerator.h index 0526098..4846b62 100644 --- a/code/io/dicom/rttbDicomFileDoseAccessorGenerator.h +++ b/code/io/dicom/rttbDicomFileDoseAccessorGenerator.h @@ -1,77 +1,71 @@ // ----------------------------------------------------------------------- // 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) -*/ + #ifndef __DICOM_FILE_DOSE_ACCESSOR_GENERATOR_H #define __DICOM_FILE_DOSE_ACCESSOR_GENERATOR_H #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "drtdose.h" #include "rttbDoseAccessorGeneratorBase.h" #include "rttbBaseType.h" - namespace rttb { namespace io { namespace dicom { /*! @class DicomFileDoseAccessorGenerator @brief Load dose data from dicom file and generate DicomDoseAccessor. */ class DicomFileDoseAccessorGenerator: public core::DoseAccessorGeneratorBase { public: using DRTDoseIODPtr = boost::shared_ptr; using DcmItemPtr = boost::shared_ptr; private: FileNameType _dicomDoseFileName; DicomFileDoseAccessorGenerator() = delete; protected: public: ~DicomFileDoseAccessorGenerator() override; /*! @brief Constructor. Initialization with a DICOM-RT dose file or a directory name @param aDICOMRTDoseFileName a DICOM-RT dose file name or a directory name @exception InvalidParameterException thrown if the file does not exist or the directory has no dicom dose file @exception DcmrtException thrown if load and read file failed */ DicomFileDoseAccessorGenerator(FileNameType aDICOMRTDoseFileName); /*! @brief Generate DoseAccessor @return Return shared pointer of DoseAccessor. @exception InvalidDoseException Thrown if the loaded dose is invalid: one of column/row/numberOfFrames/doseGridScaling/pixelSpacing=0 @exception DcmrtException Throw if dcmrt error */ DoseAccessorPointer generateDoseAccessor() override ; }; } } } #endif diff --git a/code/io/dicom/rttbDicomFileDoseAccessorWriter.cpp b/code/io/dicom/rttbDicomFileDoseAccessorWriter.cpp index 55e3b0a..9543f80 100644 --- a/code/io/dicom/rttbDicomFileDoseAccessorWriter.cpp +++ b/code/io/dicom/rttbDicomFileDoseAccessorWriter.cpp @@ -1,257 +1,250 @@ // ----------------------------------------------------------------------- // 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 #include #include "rttbDicomFileDoseAccessorWriter.h" #include "rttbInvalidDoseException.h" #include "rttbGeometricInfo.h" #include "rttbGenericDoseIterator.h" #include "rttbDoseStatisticsCalculator.h" namespace rttb { namespace io { namespace dicom { DicomFileDoseAccessorWriter::DicomFileDoseAccessorWriter() { _doseIOD = boost::make_shared(); _dataset = _fileformat.getDataset(); } void DicomFileDoseAccessorWriter::setFileName(DICOMRTFileNameString aFileName) { _fileName = aFileName; } bool DicomFileDoseAccessorWriter::process() { OFCondition status; /* Prepare dcmtk */ DcmItem* dcm_item = nullptr; //get geometric info rttb::core::GeometricInfo geometricInfo = _doseAccessor->getGeometricInfo(); /* ----------------------------------------------------------------- */ /* Part 1 -- General header */ /* ----------------------------------------------------------------- */ OFString CreationUID(_doseAccessor->getUID().c_str()); _dataset->putAndInsertString(DCM_ImageType, R"(DERIVED\SECONDARY\REFORMATTED)"); _dataset->putAndInsertOFStringArray(DCM_InstanceCreationDate, "");//Creation Date _dataset->putAndInsertOFStringArray(DCM_InstanceCreationTime, "");//Creation Time _dataset->putAndInsertOFStringArray(DCM_InstanceCreatorUID, CreationUID); _dataset->putAndInsertString(DCM_SOPClassUID, UID_RTDoseStorage); _dataset->putAndInsertString(DCM_SOPInstanceUID, _doseAccessor->getUID().c_str()); _dataset->putAndInsertOFStringArray(DCM_StudyDate, ""); _dataset->putAndInsertOFStringArray(DCM_StudyTime, ""); _dataset->putAndInsertOFStringArray(DCM_AccessionNumber, ""); _dataset->putAndInsertOFStringArray(DCM_Modality, "RTDOSE"); _dataset->putAndInsertString(DCM_Manufacturer, "RTToolbox"); _dataset->putAndInsertString(DCM_InstitutionName, ""); _dataset->putAndInsertString(DCM_ReferringPhysicianName, ""); _dataset->putAndInsertString(DCM_StationName, ""); _dataset->putAndInsertString(DCM_ManufacturerModelName, "RTToolbox"); /* (0008,1140) DCM_ReferencedImageSequence -- MIM likes this */ dcm_item = nullptr; _dataset->findOrCreateSequenceItem( DCM_ReferencedImageSequence, dcm_item, -2); dcm_item->putAndInsertString(DCM_ReferencedSOPClassUID, UID_CTImageStorage); dcm_item->putAndInsertString(DCM_ReferencedSOPInstanceUID, ""); _dataset->putAndInsertString(DCM_PatientName, ""); _dataset->putAndInsertString(DCM_PatientID, ""); _dataset->putAndInsertString(DCM_PatientBirthDate, ""); _dataset->putAndInsertString(DCM_PatientSex, "O"); _dataset->putAndInsertString(DCM_SliceThickness, boost::lexical_cast(geometricInfo.getSpacing()(2)).c_str()); _dataset->putAndInsertString(DCM_SoftwareVersions, ""); _dataset->putAndInsertString(DCM_StudyInstanceUID, ""); _dataset->putAndInsertString(DCM_SeriesInstanceUID, ""); _dataset->putAndInsertString(DCM_StudyID, "10001"); _dataset->putAndInsertString(DCM_SeriesNumber, ""); _dataset->putAndInsertString(DCM_InstanceNumber, "1"); /* GCS FIX: PatientOrientation */ std::ostringstream sstr; sstr << geometricInfo.getImagePositionPatient().x() << R"(\)" << geometricInfo.getImagePositionPatient().y() << R"(\)" << geometricInfo.getImagePositionPatient().z(); _dataset->putAndInsertString(DCM_PatientOrientation, "L/P"); _dataset->putAndInsertString(DCM_ImagePositionPatient, sstr.str().c_str()); auto orientationMatrix = geometricInfo.getOrientationMatrix(); sstr.str(""); sstr << orientationMatrix(0,0) << R"(\)" << orientationMatrix(1,0) << R"(\)" << orientationMatrix(2,0) << R"(\)" << orientationMatrix(0,1) << R"(\)" << orientationMatrix(1,1) << R"(\)" << orientationMatrix(2,1); _dataset->putAndInsertString(DCM_ImageOrientationPatient, sstr.str().c_str()); _dataset->putAndInsertString(DCM_FrameOfReferenceUID, ""); _dataset->putAndInsertString(DCM_SamplesPerPixel, "1"); _dataset->putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME2"); sstr.str(""); sstr << geometricInfo.getNumSlices(); _dataset->putAndInsertString(DCM_NumberOfFrames, sstr.str().c_str()); /* GCS FIX: Add FrameIncrementPointer */ _dataset->putAndInsertString(DCM_FrameIncrementPointer, "(3004,000c)"); _dataset->putAndInsertUint16(DCM_Rows, static_cast(geometricInfo.getNumRows())); _dataset->putAndInsertUint16(DCM_Columns, static_cast(geometricInfo.getNumColumns())); sstr.str(""); sstr << geometricInfo.getSpacing()(1) << R"(\)" << geometricInfo.getSpacing()(0); _dataset->putAndInsertString(DCM_PixelSpacing, sstr.str().c_str()); _dataset->putAndInsertString(DCM_BitsAllocated, "32"); _dataset->putAndInsertString(DCM_BitsStored, "32"); _dataset->putAndInsertString(DCM_HighBit, "31"); _dataset->putAndInsertString(DCM_DoseUnits, "GY"); _dataset->putAndInsertString(DCM_DoseSummationType, "PLAN"); sstr.str("0"); for (unsigned int i = 1; i < geometricInfo.getNumSlices(); i++) { sstr << R"(\)" << i* geometricInfo.getSpacing()(2); } _dataset->putAndInsertString(DCM_GridFrameOffsetVector, sstr.str().c_str()); /* We need to convert image to uint16_t, but first we need to scale it so that the maximum dose fits in a 16-bit unsigned integer. Compute an appropriate scaling factor based on the maximum dose. */ /* Find the maximum value in the image */ boost::shared_ptr spTestDoseIterator = boost::make_shared(_doseAccessor); rttb::core::GenericDoseIterator::DoseIteratorPointer spDoseIterator(spTestDoseIterator); rttb::algorithms::DoseStatisticsCalculator myDoseStatsCalculator(spDoseIterator); auto doseStatistics = myDoseStatsCalculator.calculateDoseStatistics(); double maxDose = doseStatistics->getMaximum(); /* Find scale factor */ double dose_scale; dose_scale = maxDose / PixelDataMaxValue; /* Scale the image and add scale factor to _dataset */ sstr.str(""); sstr << dose_scale; _dataset->putAndInsertString(DCM_DoseGridScaling, sstr.str().c_str()); /* (300c,0002) ReferencedRTPlanSequence -- for future expansion */ dcm_item = nullptr; _dataset->findOrCreateSequenceItem( DCM_ReferencedRTPlanSequence, dcm_item, -2); dcm_item->putAndInsertString(DCM_ReferencedSOPClassUID, UID_RTPlanStorage); dcm_item->putAndInsertString(DCM_ReferencedSOPInstanceUID, ""); /* (300c,0060) DCM_ReferencedStructureSetSequence -- MIM likes this */ dcm_item = nullptr; _dataset->findOrCreateSequenceItem( DCM_ReferencedStructureSetSequence, dcm_item, -2); dcm_item->putAndInsertString(DCM_ReferencedSOPClassUID, UID_RTStructureSetStorage); dcm_item->putAndInsertString(DCM_ReferencedSOPInstanceUID, ""); /* Convert image bytes to integer, then add to _dataset */ Uint16* pixelData; auto pixelCount = static_cast(geometricInfo.getNumRows() * geometricInfo.getNumColumns() * geometricInfo.getNumSlices()); pixelData = new Uint16[pixelCount]; for (unsigned int i = 0; i < pixelCount; ++i) { double doseValue = _doseAccessor->getValueAt(i); double pixelValue = doseValue / dose_scale; if (pixelValue > PixelDataMaxValue) { pixelValue = PixelDataMaxValue; } pixelData[i] = boost::numeric_cast(pixelValue); } status = _dataset->putAndInsertUint16Array(DCM_PixelData, pixelData, pixelCount); if (!status.good()) { throw core::InvalidDoseException("Error: put and insert pixel data failed!"); } //Write dose to file status = _fileformat.saveFile(_fileName.c_str(), EXS_LittleEndianExplicit); if (status.bad()) { std::cerr << "Error: cannot write DICOM RTDOSE!" << std::endl; } return true; } }//end namespace itk }//end namespace io }//end namespace rttb diff --git a/code/io/dicom/rttbDicomFileDoseAccessorWriter.h b/code/io/dicom/rttbDicomFileDoseAccessorWriter.h index 8f58ac4..db43ac5 100644 --- a/code/io/dicom/rttbDicomFileDoseAccessorWriter.h +++ b/code/io/dicom/rttbDicomFileDoseAccessorWriter.h @@ -1,82 +1,77 @@ // ----------------------------------------------------------------------- // 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) -*/ + #ifndef __DICOM_FILE_DOSE_ACCESSOR_WRITER_H #define __DICOM_FILE_DOSE_ACCESSOR_WRITER_H #include "../itk/rttbDoseAccessorProcessorBase.h" #include "../itk/rttbDoseAccessorConversionSettingInterface.h" #include "rttbDicomDoseAccessor.h" //pixel data max value UINT16_MAX #define PixelDataMaxValue 0xffff namespace rttb { namespace io { namespace dicom { /*! @class DicomFileDoseAccessorWriter @brief Class converts/dumps the processed accessor into an dicom file @remark DoseAccessorConversionInterface defines how the converter should react on non valid dose values. */ class DicomFileDoseAccessorWriter: public core::DoseAccessorProcessorBase, public core::DoseAccessorConversionSettingInterface { public: using DoseAccessorPointer = core::DoseAccessorInterface::Pointer; using DRTDoseIODPointer = DicomDoseAccessor::DRTDoseIODPtr; /*! @brief Standard Constructor. */ DicomFileDoseAccessorWriter(); ~DicomFileDoseAccessorWriter() override = default; /*! Set a file name to write the dose @param aFileName a file name to write the dose */ void setFileName(DICOMRTFileNameString aFileName); /*! @brief Convert the accessor into dicom dataset and write dicom dataset to a file @exception InvalidDoseException thrown if put and insert pixel data into dicom dataset failed */ bool process() override; private: DicomFileDoseAccessorWriter(const DicomFileDoseAccessorWriter&) = delete; //not implemented on purpose -> non-copyable DicomFileDoseAccessorWriter& operator=(const DicomFileDoseAccessorWriter&) = delete;//not implemented on purpose -> non-copyable DRTDoseIODPointer _doseIOD; DICOMRTFileNameString _fileName; DcmFileFormat _fileformat; DcmDataset* _dataset; }; } } } #endif diff --git a/code/io/dicom/rttbDicomFileReaderHelper.h b/code/io/dicom/rttbDicomFileReaderHelper.h index 63e067a..739d4ca 100644 --- a/code/io/dicom/rttbDicomFileReaderHelper.h +++ b/code/io/dicom/rttbDicomFileReaderHelper.h @@ -1,75 +1,74 @@ // ----------------------------------------------------------------------- // 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. // //------------------------------------------------------------------------ #ifndef __DICOM_FILE_READER_HELPER_H #define __DICOM_FILE_READER_HELPER_H #include #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "drtdose.h" #include "rttbBaseType.h" #include "boost/shared_ptr.hpp" - namespace rttb { namespace io { namespace dicom { struct Modality { enum Type { RTDOSE = 1, RTSTRUCT = 2, RTPLAN = 3, UserDefined = 128 } Type; }; using DRTDoseIODPtr = boost::shared_ptr; using DcmDataSetPtr = boost::shared_ptr; /*! Return the vector of all files with the same UID in the given directory, the UID is defined by the first file with the modality. @exception InvalidParameterException thrown if the file/directory does not exist or the modality is invalid @exception DcmrtException thrown if load/read file failed */ std::vector getFileNamesWithSameUID(FileNameType aDirName, Modality aModality); /*! Return the vector of all files with the same UID in the directory of the given file @exception InvalidParameterException thrown if the file does not exist @exception DcmrtException thrown if load/read file failed */ std::vector getFileNames(FileNameType aFileName); /*! Return modality DcmTagKey(0x0008, 0x0060) @exception DcmrtException thrown if reading modality failed*/ OFString getModality(DcmDataSetPtr aDcmDataSet); /*! Return uid DcmTagKey(0x0020, 0x000e) @exception DcmrtException thrown if reading uid failed*/ OFString getUID(DcmDataSetPtr aDcmDataSet); }; } } #endif diff --git a/code/io/dicom/rttbDicomFileStructureSetGenerator.h b/code/io/dicom/rttbDicomFileStructureSetGenerator.h index 8da25cf..659495e 100644 --- a/code/io/dicom/rttbDicomFileStructureSetGenerator.h +++ b/code/io/dicom/rttbDicomFileStructureSetGenerator.h @@ -1,95 +1,89 @@ // ----------------------------------------------------------------------- // 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) -*/ /* Changes in Architecture: The DICOM specific classes will be removed and transfered to the corresponding IO classes. This class should only provide general structure functionality. */ #ifndef __DICOM_FILE_STRUCTURE_SET_GENERATOR_H #define __DICOM_FILE_STRUCTURE_SET_GENERATOR_H #include #include #include "drtstrct.h" #include "rttbBaseType.h" #include "rttbStrVectorStructureSetGenerator.h" #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4251) #endif namespace rttb { namespace io { namespace dicom { /*! @class DicomFileStructureSetGenerator @brief Generate a structure set from a corresponding dicomRT file. */ class DicomFileStructureSetGenerator: public core::StrVectorStructureSetGenerator { public: using StructTypePointer = core::Structure::Pointer; using StructureSetPointer = core::StructureSet::Pointer; using DRTStrSetIODPtr = boost::shared_ptr; private: IDType _UID; DICOMRTFileNameString _fileName; DicomFileStructureSetGenerator() = default; public: /*! @brief Constructor @param aDICOMRTStrSetFileName a DICOM-RT Structure set file name or a directory name @exception InvalidParameterException thrown if the file does not exist or the directory has no dicom structure file @exception DcmrtException thrown if load and read file failed */ DicomFileStructureSetGenerator(DICOMRTFileNameString aDICOMRTStrSetFileName); /*! @brief Destructor */ ~DicomFileStructureSetGenerator() override; /*! @brief generate structure set @return return shared pointer of StructureSet @exception DcmrtException Thrown if loadFile and read failed @exception InvalidParameterException throw if the imported header tags are not numerical. */ StructureSetPointer generateStructureSet() override; }; } } } #ifdef _MSC_VER #pragma warning(pop) #endif #endif diff --git a/code/io/dicom/rttbDicomIODDoseAccessorGenerator.cpp b/code/io/dicom/rttbDicomIODDoseAccessorGenerator.cpp index c86b317..700514c 100644 --- a/code/io/dicom/rttbDicomIODDoseAccessorGenerator.cpp +++ b/code/io/dicom/rttbDicomIODDoseAccessorGenerator.cpp @@ -1,71 +1,65 @@ // ----------------------------------------------------------------------- // 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 "rttbDicomIODDoseAccessorGenerator.h" #include "rttbDicomDoseAccessor.h" #include "rttbNullPointerException.h" #include "rttbInvalidDoseException.h" #include "rttbDcmrtException.h" #include "rttbIndexOutOfBoundsException.h" namespace rttb { namespace io { namespace dicom { DicomIODDoseAccessorGenerator::~DicomIODDoseAccessorGenerator() = default; DicomIODDoseAccessorGenerator::DicomIODDoseAccessorGenerator(DRTDoseIODPtr aDRTDoseIODP) { _doseIODPtr = aDRTDoseIODP; } core::DoseAccessorGeneratorInterface::DoseAccessorPointer DicomIODDoseAccessorGenerator::generateDoseAccessor() { DcmItem doseitem; OFCondition status; status = _doseIODPtr->write(doseitem);//write DoseIOD to DcmItem to get pixel data if (status.good()) { DcmItemPtr dataSetPtr = boost::make_shared(doseitem); _doseAccessor = boost::make_shared(_doseIODPtr, dataSetPtr); return _doseAccessor; } else { throw io::dicom::DcmrtException("Write DICOM RT Dose to DcmItem failed!"); } } } } } diff --git a/code/io/dicom/rttbDicomIODDoseAccessorGenerator.h b/code/io/dicom/rttbDicomIODDoseAccessorGenerator.h index 409a615..e2eaf11 100644 --- a/code/io/dicom/rttbDicomIODDoseAccessorGenerator.h +++ b/code/io/dicom/rttbDicomIODDoseAccessorGenerator.h @@ -1,75 +1,69 @@ // ----------------------------------------------------------------------- // 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) -*/ + #ifndef __DICOM_IOD_DOSE_ACCESSOR_GENERATOR_H #define __DICOM_IOD_DOSE_ACCESSOR_GENERATOR_H #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "drtdose.h" #include "rttbDoseAccessorGeneratorBase.h" - namespace rttb { namespace io { namespace dicom { /*! @class DicomIODDoseAccessorGenerator @brief Generate DicomDoseAccessor with a DRTDoseIOD. */ class DicomIODDoseAccessorGenerator: public core::DoseAccessorGeneratorBase { public: using DRTDoseIODPtr = boost::shared_ptr; using DcmItemPtr = boost::shared_ptr; protected: private: DRTDoseIODPtr _doseIODPtr; DicomIODDoseAccessorGenerator() = delete; public: ~DicomIODDoseAccessorGenerator() override; /*! @brief Constructor. Initialization with a boost shared pointer of DRTDoseIOD */ DicomIODDoseAccessorGenerator(DRTDoseIODPtr aDRTDoseIODP); /*! @brief Generate DoseAccessor @return Return shared pointer of DoseAccessor. @exception InvalidDoseException Thrown if aDRTDoseIODP is invalid: one of column/row/numberOfFrames/doseGridScaling/pixelSpacing=0 @exception DcmrtException Throw if dcmrt error */ DoseAccessorPointer generateDoseAccessor() override ; }; } } } #endif diff --git a/code/io/dicom/rttbDicomIODStructureSetGenerator.cpp b/code/io/dicom/rttbDicomIODStructureSetGenerator.cpp index 11b89f4..2960fdf 100644 --- a/code/io/dicom/rttbDicomIODStructureSetGenerator.cpp +++ b/code/io/dicom/rttbDicomIODStructureSetGenerator.cpp @@ -1,208 +1,201 @@ // ----------------------------------------------------------------------- // 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 #include #include #include #include #include "rttbStructure.h" #include "rttbDicomIODStructureSetGenerator.h" #include "rttbDcmrtException.h" #include "rttbInvalidParameterException.h" - namespace rttb { namespace io { namespace dicom { DicomIODStructureSetGenerator::DicomIODStructureSetGenerator(DRTStrSetIODPtr aDRTStructureSetIOD) { _drtStrSetIOD = aDRTStructureSetIOD; } void DicomIODStructureSetGenerator::readStrSet() { OFString uid; _drtStrSetIOD->getSeriesInstanceUID(uid); _UID = uid.c_str(); OFString uid2; _drtStrSetIOD->getPatientID(uid2); _patientUID = uid2.c_str(); DRTStructureSetROISequence* rois = &_drtStrSetIOD->getStructureSetROISequence(); //generate map of relevant ROIs std::map filteredROIs; std::regex e(this->getFilterRegEx()); for (unsigned long i = 0; i < rois->getNumberOfItems(); i++) { DRTStructureSetROISequence::Item* roisItem = &rois->getItem(i); OFString roiNumber; roisItem->getROINumber(roiNumber); OFString ofRoiName; roisItem->getROIName(ofRoiName); std::string roiName(ofRoiName.c_str()); //replace wrongly 'á' character by ' ' in ROI name correctSpacesInROIName(roiName); if (!this->getStructureLabelFilterActive() || std::regex_match(roiName, e)) { filteredROIs.emplace(roiNumber, roiName); } } /*A structure is a DRTROIContourSequence::Item. Each Item defines a roi. Each ROI contains a sequence of one or more contours, where a contour is either a single point (for a point ROI) or more than one point (representing an open or closed polygon). */ DRTROIContourSequence* rcs; rcs = &_drtStrSetIOD->getROIContourSequence(); DRTROIContourSequence::Item* rcsItem; long numberOfStructures = rcs->getNumberOfItems(); bool isEmpty = rcs->isEmpty(); if (numberOfStructures == 0 || isEmpty) { throw core::InvalidParameterException("Empty Structure Set!") ; } int structureNo = 0; for (rcs->gotoFirstItem(); (rcs->getCurrentItem(rcsItem)).good(); rcs->gotoNextItem()) { OFString refROINumber; rcsItem->getReferencedROINumber(refROINumber); //check if ROI number is in the filtered ROIS if (filteredROIs.find(refROINumber) != filteredROIs.end()) { DRTContourSequence* cs; cs = &rcsItem->getContourSequence(); unsigned long no2 = cs->getNumberOfItems(); PolygonSequenceType structureVector; for (unsigned long j = 0; j < no2; j++) { /*DRTContourSequence::Item represents a contour (either a single point (for a point ROI) or more than one point (representing an open or closed polygon))*/ DRTContourSequence::Item* csItem; csItem = &cs->getItem(j); OFString contourData; OFString numberOfContourPoints; csItem->getNumberOfContourPoints(numberOfContourPoints); unsigned int numberOfContourPointsInt; std::stringstream is(numberOfContourPoints.c_str()); is >> numberOfContourPointsInt; OFString countourNumber; csItem->getContourNumber(countourNumber); PolygonType contourVector; char* pEnd; for (unsigned int k = 0; k < numberOfContourPointsInt; k++) { WorldCoordinate3D point; for (unsigned int i = 0; i < 3; i++) { csItem->getContourData(contourData, k * 3 + i); WorldCoordinate value = strtod(contourData.c_str(), &pEnd); if (*pEnd != '\0') { throw core::InvalidParameterException("Contour data not readable!") ; } if (i == 0) { point(0) = value; } else if (i == 1) { point(1) = value; } else { point(2) = value; } } contourVector.push_back(point); } structureVector.push_back(contourVector); } boost::shared_ptr spStruct = boost::make_shared(structureVector); StructTypePointer str(spStruct); str->setLabel(filteredROIs[refROINumber]); std::cout << filteredROIs[refROINumber].c_str() << " read" << std::endl; std::stringstream sstr; sstr << structureNo; str->setUID(sstr.str()); _strVector.push_back(str); } ++structureNo; } } DicomIODStructureSetGenerator::~DicomIODStructureSetGenerator() = default; DicomIODStructureSetGenerator::StructureSetPointer DicomIODStructureSetGenerator::generateStructureSet() { this->readStrSet(); return boost::make_shared(_strVector, _patientUID, _UID); } void DicomIODStructureSetGenerator::correctSpacesInROIName(std::string& roiName) { for (auto& character : roiName) { if (character == -96) { character = ' '; } } } }//end namespace dicom }//end namespace io }//end namespace rttb diff --git a/code/io/dicom/rttbDicomIODStructureSetGenerator.h b/code/io/dicom/rttbDicomIODStructureSetGenerator.h index 2be016c..05334ca 100644 --- a/code/io/dicom/rttbDicomIODStructureSetGenerator.h +++ b/code/io/dicom/rttbDicomIODStructureSetGenerator.h @@ -1,91 +1,84 @@ // ----------------------------------------------------------------------- // 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) -*/ /* Changes in Architecture: The DICOM specific classes will be removed and transfered to the corresponding IO classes. This class should only provide general structure functionality. */ #ifndef __DICOM_IOD_STRUCTURE_SET_GENERATOR_H #define __DICOM_IOD_STRUCTURE_SET_GENERATOR_H #include #include "drtstrct.h" #include "rttbBaseType.h" #include "rttbStrVectorStructureSetGenerator.h" - namespace rttb { namespace io { namespace dicom { /*! @class DicomIODStructureSetGenerator @brief Generate a structure set from a DRTStructureSetIOD pointer. */ class DicomIODStructureSetGenerator: public core::StrVectorStructureSetGenerator { public: using StructTypePointer = core::Structure::Pointer; using StructureSetPointer = core::StructureSet::Pointer; using DRTStrSetIODPtr = boost::shared_ptr; private: DRTStrSetIODPtr _drtStrSetIOD; IDType _UID; /*! Import Structure data from file. @exception InvalidParameterException Thrown if the imported header tags are not numerical. */ void readStrSet(); /*! Replaces the character 'á' ((int)-96) to ' ' ((int)32) in a string. */ void correctSpacesInROIName(std::string& roiName); public: /*! @brief Structure Constructor Get the vector of structures from DRTStructureSetIOD object @exception NullPointerException Thrown if structureSet is nullptr */ DicomIODStructureSetGenerator(DRTStrSetIODPtr aDRTStructureSetIOD); /*! @brief Destructor */ ~DicomIODStructureSetGenerator() override; /*! @brief generate structure set @return return shared pointer of StructureSet @exception InvalidParameterException throw if the imported header tags are not numerical. */ StructureSetPointer generateStructureSet() override; }; } } } #endif diff --git a/testing/io/dicom/DicomDoseAccessorConverterTest.cpp b/testing/io/dicom/DicomDoseAccessorConverterTest.cpp index 56c43e0..685b816 100644 --- a/testing/io/dicom/DicomDoseAccessorConverterTest.cpp +++ b/testing/io/dicom/DicomDoseAccessorConverterTest.cpp @@ -1,130 +1,123 @@ // ----------------------------------------------------------------------- // 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 #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomFileDoseAccessorWriter.h" #include "rttbInvalidDoseException.h" #include "rttbDcmrtException.h" #include "rttbInvalidParameterException.h" - namespace rttb { namespace testing { /*!@brief DicomDoseAccessorGeneratorTest - test the generators for dicom data 1) test dicom file generator generateDoseAccessor() 2) test dicom IOD generator generateDoseAccessor() */ int DicomDoseAccessorConverterTest(int argc, char* argv[]) { typedef rttb::core::DoseAccessorInterface::Pointer DoseAccessorPointer; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: // 1: the file name of the dose to read // 2: the file name of the dose to write std::string RTDOSE_FILENAME_R; std::string RTDOSE_FILENAME_W; if (argc > 2) { RTDOSE_FILENAME_R = argv[1]; RTDOSE_FILENAME_W = argv[2]; } double errorConstantDDA = 1e-3; DoseAccessorPointer doseAccessor_r = io::dicom::DicomFileDoseAccessorGenerator( RTDOSE_FILENAME_R.c_str()).generateDoseAccessor(); CHECK_NO_THROW(io::dicom::DicomFileDoseAccessorWriter()); io::dicom::DicomFileDoseAccessorWriter doseConverter; CHECK_NO_THROW(doseConverter.setDoseAccessor(doseAccessor_r)); CHECK_NO_THROW(doseConverter.setFileName(RTDOSE_FILENAME_W)); CHECK_EQUAL(doseConverter.process(), true); DoseAccessorPointer doseAccessor_w = io::dicom::DicomFileDoseAccessorGenerator( RTDOSE_FILENAME_W).generateDoseAccessor(); //Check geometricinfo CHECK(doseAccessor_r->getGeometricInfo().getImagePositionPatient().equalsAlmost( doseAccessor_w->getGeometricInfo().getImagePositionPatient(), errorConstantDDA)); CHECK(doseAccessor_r->getGeometricInfo().getOrientationMatrix().equalsAlmost( doseAccessor_w->getGeometricInfo().getOrientationMatrix(), errorConstantDDA)); CHECK(doseAccessor_r->getGeometricInfo().getSpacing().equalsAlmost( doseAccessor_w->getGeometricInfo().getSpacing(), errorConstantDDA)); CHECK_CLOSE(doseAccessor_r->getGeometricInfo().getNumColumns(), doseAccessor_w->getGeometricInfo().getNumColumns(), errorConstantDDA); CHECK_CLOSE(doseAccessor_r->getGeometricInfo().getNumRows(), doseAccessor_w->getGeometricInfo().getNumRows(), errorConstantDDA); CHECK_CLOSE(doseAccessor_r->getGeometricInfo().getNumSlices(), doseAccessor_w->getGeometricInfo().getNumSlices(), errorConstantDDA); //Check pixel data unsigned int size = doseAccessor_r->getGeometricInfo().getNumColumns() * doseAccessor_r->getGeometricInfo().getNumRows() * doseAccessor_r->getGeometricInfo().getNumSlices() ; for (unsigned int index = 0; index < 30; index++) { CHECK_CLOSE(doseAccessor_r->getValueAt(index), doseAccessor_w->getValueAt(index), errorConstantDDA); if (size / 2 - index >= 0 && size / 2 - index < size) { CHECK_CLOSE(doseAccessor_r->getValueAt(size / 2 - index), doseAccessor_w->getValueAt(size / 2 - index), errorConstantDDA); } CHECK_CLOSE(doseAccessor_r->getValueAt(size - index - 1), doseAccessor_w->getValueAt(size - index - 1), errorConstantDDA); } RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/dicom/DicomDoseAccessorGeneratorTest.cpp b/testing/io/dicom/DicomDoseAccessorGeneratorTest.cpp index 65c6cb6..a5d1106 100644 --- a/testing/io/dicom/DicomDoseAccessorGeneratorTest.cpp +++ b/testing/io/dicom/DicomDoseAccessorGeneratorTest.cpp @@ -1,115 +1,108 @@ // ----------------------------------------------------------------------- // 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 #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomIODDoseAccessorGenerator.h" #include "rttbInvalidDoseException.h" #include "rttbDcmrtException.h" #include "rttbInvalidParameterException.h" - namespace rttb { namespace testing { /*!@brief DicomDoseAccessorGeneratorTest - test the generators for dicom data 1) test dicom file generator generateDoseAccessor() 2) test dicom IOD generator generateDoseAccessor() */ int DicomDoseAccessorGeneratorTest(int argc, char* argv[]) { typedef boost::shared_ptr DRTDoseIODPtr; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: // 1: dose1 file name // 2: dose2 file name // 3: dose3 file name std::string RTDOSE_FILENAME; std::string RTDOSE2_FILENAME; std::string RTDOSE3_FILENAME; if (argc > 1) { RTDOSE_FILENAME = argv[1]; } if (argc > 2) { RTDOSE2_FILENAME = argv[2]; } if (argc > 3) { RTDOSE3_FILENAME = argv[3]; } OFCondition status; DcmFileFormat fileformat; /* test DicomFileDoseAccessorGenerator generateDoseAccessor()*/ CHECK_THROW_EXPLICIT(io::dicom::DicomFileDoseAccessorGenerator("test.test").generateDoseAccessor(), core::InvalidParameterException); CHECK_NO_THROW(io::dicom::DicomFileDoseAccessorGenerator( RTDOSE_FILENAME.c_str()).generateDoseAccessor()); CHECK_NO_THROW(io::dicom::DicomFileDoseAccessorGenerator( RTDOSE2_FILENAME.c_str()).generateDoseAccessor()); CHECK_NO_THROW(io::dicom::DicomFileDoseAccessorGenerator( RTDOSE3_FILENAME.c_str()).generateDoseAccessor()); /* test DicomIODDoseAccessorGenerator generateDoseAccessor()*/ DRTDoseIODPtr dose = boost::make_shared(); CHECK_THROW_EXPLICIT(io::dicom::DicomIODDoseAccessorGenerator(dose).generateDoseAccessor(), io::dicom::DcmrtException); fileformat.loadFile(RTDOSE_FILENAME.c_str()); dose->read(*fileformat.getDataset()); CHECK_NO_THROW(io::dicom::DicomIODDoseAccessorGenerator(dose).generateDoseAccessor()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/dicom/DicomFileReaderHelperTest.cpp b/testing/io/dicom/DicomFileReaderHelperTest.cpp index 208edbc..6457efa 100644 --- a/testing/io/dicom/DicomFileReaderHelperTest.cpp +++ b/testing/io/dicom/DicomFileReaderHelperTest.cpp @@ -1,98 +1,91 @@ // ----------------------------------------------------------------------- // 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 #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbDicomFileReaderHelper.h" - namespace rttb { namespace testing { /*!@brief DicomDoseAccessorGeneratorTest - test the generators for dicom data 1) test getFileNamesWithSameUID() with a directory name 2) test getFileNames() with a RTDOSE file name and check equal with getFileNamesWithSameUID() 3) test getFileNames() with a RTSTRUCT file name */ int DicomFileReaderHelperTest(int argc, char* argv[]) { typedef boost::shared_ptr DRTDoseIODPtr; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: // 1: helax directory name // 2: dose file name // 3: structure file name std::string RT_DIRNAME; std::string RTDOSE_FILENAME; std::string RTStr_FILENAME; if (argc > 3) { RT_DIRNAME = argv[1]; RTDOSE_FILENAME = argv[2]; RTStr_FILENAME = argv[3]; } rttb::io::dicom::Modality doseModality = {rttb::io::dicom::Modality::RTDOSE}; rttb::io::dicom::Modality strModality = {rttb::io::dicom::Modality::RTSTRUCT}; //1) test getFileNamesWithSameUID() with a directory name std::vector fileVector = rttb::io::dicom::getFileNamesWithSameUID(RT_DIRNAME, doseModality); CHECK_EQUAL(fileVector.size(), 52); //2) test getFileNames() with a RTDOSE file name and check equal with getFileNamesWithSameUID() std::vector fileVector2 = rttb::io::dicom::getFileNames(RTDOSE_FILENAME); for (size_t i = 0; i < fileVector.size(); i++) { CHECK_EQUAL(fileVector.at(i), fileVector2.at(i)); } //3) test getFileNames() with a RTSTRUCT file name fileVector2 = rttb::io::dicom::getFileNames(RTStr_FILENAME); CHECK_EQUAL(fileVector2.size(), 1); fileVector = rttb::io::dicom::getFileNamesWithSameUID(RT_DIRNAME, strModality); CHECK_EQUAL(fileVector.size(), 1); CHECK_EQUAL(fileVector.at(0), fileVector2.at(0)); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/dicom/DicomIOTest.cpp b/testing/io/dicom/DicomIOTest.cpp index 6e303c5..3d7bb6c 100644 --- a/testing/io/dicom/DicomIOTest.cpp +++ b/testing/io/dicom/DicomIOTest.cpp @@ -1,241 +1,234 @@ // ----------------------------------------------------------------------- // 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 #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbGeometricInfo.h" #include "rttbDoseIteratorInterface.h" #include "rttbDicomDoseAccessor.h" #include "rttbDicomFileDoseAccessorGenerator.h" #include "rttbDicomIODDoseAccessorGenerator.h" #include "rttbDicomFileStructureSetGenerator.h" - namespace rttb { namespace testing { /*!@brief DicomIOTest - test the IO for dicom data 1) test dicom dose import if geometric info was set correctly 2) test dicom dose import accessing dose data and converting 3) check if dicom tags are correctly read 4) test structure import WARNING: The values for comparison need to be adjusted if the input files are changed! */ int DicomIOTest(int argc, char* argv[]) { typedef core::DoseIteratorInterface::DoseAccessorPointer DoseAccessorPointer; typedef core::StructureSet::Pointer StructureSetPointer; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: 1: structure file name // 2: dose1 file name // 3: dose2 file name // 4: dose3 file name // 5: dose4 file name // 6: dose5 file name std::string RTSTRUCT_FILENAME; std::string RTDOSE_FILENAME; std::string RTDOSE2_FILENAME; std::string RTDOSE3_FILENAME; std::string RTDOSE4_FILENAME; std::string RTDOSE5_FILENAME; if (argc > 1) { RTSTRUCT_FILENAME = argv[1]; } if (argc > 2) { RTDOSE_FILENAME = argv[2]; } if (argc > 3) { RTDOSE2_FILENAME = argv[3]; } if (argc > 4) { RTDOSE3_FILENAME = argv[4]; } if (argc > 5) { RTDOSE4_FILENAME = argv[5]; } if (argc > 6) { RTDOSE5_FILENAME = argv[6]; } OFCondition status; DcmFileFormat fileformat; /* read dicom-rt dose */ io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator1(RTDOSE_FILENAME.c_str()); DoseAccessorPointer doseAccessor1(doseAccessorGenerator1.generateDoseAccessor()); //1) test dicom dose import if geometric info was set correctly core::GeometricInfo geoInfo = doseAccessor1->getGeometricInfo(); CHECK_EQUAL(45, geoInfo.getNumRows()); CHECK_EQUAL(67, geoInfo.getNumColumns()); CHECK_EQUAL(64, geoInfo.getNumSlices()); CHECK_EQUAL(OrientationMatrix(), geoInfo.getOrientationMatrix()); SpacingVectorType3D pixelSpacing(5, 5, 5); CHECK_EQUAL(pixelSpacing, geoInfo.getSpacing()); WorldCoordinate3D imagePositionPatient(-170.556642, -273.431642, -674); CHECK_EQUAL(imagePositionPatient, geoInfo.getImagePositionPatient()); //test geometric info of an inhomogeneous dose grid io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator5(RTDOSE5_FILENAME.c_str()); DoseAccessorPointer doseAccessor5(doseAccessorGenerator5.generateDoseAccessor()); SpacingVectorType3D pixelSpacing5(2, 3, 2); CHECK_EQUAL(pixelSpacing5, doseAccessor5->getGeometricInfo().getSpacing()); const VoxelGridID start = 0; const VoxelGridIndex3D start3D(0); VoxelGridID end, inbetween; VoxelGridIndex3D end3D, inbetween3D; //2) test dicom dose import accessing dose data and converting CHECK_EQUAL(2, doseAccessor1->getValueAt(start)); CHECK_EQUAL(2, doseAccessor1-> getValueAt(start3D)); CHECK_EQUAL(doseAccessor1->getValueAt(start), doseAccessor1-> getValueAt(start3D)); inbetween = int(std::floor(doseAccessor1->getGridSize() / 2.0)); doseAccessor1->getGeometricInfo().convert(inbetween, inbetween3D); CHECK_EQUAL(2, doseAccessor1->getValueAt(inbetween)); CHECK_EQUAL(2, doseAccessor1-> getValueAt(inbetween3D)); CHECK_EQUAL(doseAccessor1->getValueAt(inbetween), doseAccessor1-> getValueAt(inbetween3D)); end = doseAccessor1->getGridSize() - 1; doseAccessor1->getGeometricInfo().convert(end, end3D); CHECK_EQUAL(2, doseAccessor1->getValueAt(end)); CHECK_EQUAL(2, doseAccessor1-> getValueAt(end3D)); CHECK_EQUAL(doseAccessor1->getValueAt(end), doseAccessor1-> getValueAt(end3D)); ::DRTDoseIOD rtdose2; io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator2(RTDOSE2_FILENAME.c_str()); DoseAccessorPointer doseAccessor2(doseAccessorGenerator2.generateDoseAccessor()); //2) test dicom dose import accessing dose data and converting CHECK_EQUAL(50, doseAccessor2->getValueAt(start)); CHECK_EQUAL(50, doseAccessor2-> getValueAt(start3D)); CHECK_EQUAL(doseAccessor2->getValueAt(start), doseAccessor2-> getValueAt(start3D)); inbetween = int(std::floor(doseAccessor2->getGridSize() / 2.0)); doseAccessor2->getGeometricInfo().convert(inbetween, inbetween3D); CHECK_EQUAL(50, doseAccessor2->getValueAt(inbetween)); CHECK_EQUAL(50, doseAccessor2-> getValueAt(inbetween3D)); CHECK_EQUAL(doseAccessor2->getValueAt(inbetween), doseAccessor2-> getValueAt(inbetween3D)); end = doseAccessor2->getGridSize() - 1; doseAccessor2->getGeometricInfo().convert(end, end3D); CHECK_EQUAL(50, doseAccessor2->getValueAt(end)); CHECK_EQUAL(50, doseAccessor2-> getValueAt(end3D)); CHECK_EQUAL(doseAccessor2->getValueAt(end), doseAccessor2-> getValueAt(end3D)); ::DRTDoseIOD rtdose3; io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator3(RTDOSE3_FILENAME.c_str()); DoseAccessorPointer doseAccessor3(doseAccessorGenerator3.generateDoseAccessor()); //2) test dicom dose import accessing dose data and converting CHECK_EQUAL(0, doseAccessor3->getValueAt(start)); CHECK_EQUAL(0, doseAccessor3-> getValueAt(start3D)); CHECK_EQUAL(doseAccessor3->getValueAt(start), doseAccessor3-> getValueAt(start3D)); inbetween = int(std::floor(doseAccessor3->getGridSize() / 2.0)); doseAccessor3->getGeometricInfo().convert(inbetween, inbetween3D); CHECK_EQUAL(0, doseAccessor3->getValueAt(inbetween)); CHECK_EQUAL(0, doseAccessor3-> getValueAt(inbetween3D)); CHECK_EQUAL(doseAccessor3->getValueAt(inbetween), doseAccessor3-> getValueAt(inbetween3D)); end = doseAccessor3->getGridSize() - 1; doseAccessor3->getGeometricInfo().convert(end, end3D); CHECK_CLOSE(1.46425, doseAccessor3->getValueAt(end), errorConstant); CHECK_CLOSE(1.46425, doseAccessor3-> getValueAt(end3D), errorConstant); CHECK_EQUAL(doseAccessor3->getValueAt(end), doseAccessor3-> getValueAt(end3D)); /* structure set */ StructureSetPointer rtStructureSet = io::dicom::DicomFileStructureSetGenerator( RTSTRUCT_FILENAME.c_str()).generateStructureSet(); //4) test structure import CHECK_EQUAL(10, rtStructureSet->getNumberOfStructures()); CHECK_EQUAL("Aussenkontur", (rtStructureSet->getStructure(0))->getLabel()); CHECK_EQUAL("Rueckenmark", (rtStructureSet->getStructure(1))->getLabel()); CHECK_EQUAL("Niere re.", (rtStructureSet->getStructure(2))->getLabel()); CHECK_EQUAL("Niere li.", (rtStructureSet->getStructure(3))->getLabel()); CHECK_EQUAL("Magen/DD", (rtStructureSet->getStructure(4))->getLabel()); CHECK_EQUAL("Leber", (rtStructureSet->getStructure(5))->getLabel()); CHECK_EQUAL("Darm", (rtStructureSet->getStructure(6))->getLabel()); CHECK_EQUAL("Ref.Pkt.", (rtStructureSet->getStructure(7))->getLabel()); CHECK_EQUAL("PTV", (rtStructureSet->getStructure(8))->getLabel()); CHECK_EQUAL("Boost", (rtStructureSet->getStructure(9))->getLabel()); //4) Test other tags (GridFrameOffsetVector(3004,000c) and PixelSpacingBetweenSlices(0018, 0088)) to compute dose slicing io::dicom::DicomFileDoseAccessorGenerator doseAccessorGenerator4(RTDOSE4_FILENAME.c_str()); DoseAccessorPointer doseAccessor4(doseAccessorGenerator4.generateDoseAccessor()); rttb::SpacingVectorType3D spacingVec = doseAccessor4->getGeometricInfo().getSpacing(); CHECK_EQUAL(2.5, spacingVec.x()); CHECK_EQUAL(2.5, spacingVec.y()); CHECK_EQUAL(3, spacingVec.z()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/dicom/DicomStructureSetGeneratorTest.cpp b/testing/io/dicom/DicomStructureSetGeneratorTest.cpp index 4aea224..c8d7296 100644 --- a/testing/io/dicom/DicomStructureSetGeneratorTest.cpp +++ b/testing/io/dicom/DicomStructureSetGeneratorTest.cpp @@ -1,104 +1,98 @@ // ----------------------------------------------------------------------- // 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 #include "litCheckMacros.h" #include "rttbBaseType.h" #include "rttbDicomFileStructureSetGenerator.h" #include "rttbDicomIODStructureSetGenerator.h" #include "rttbDcmrtException.h" #include "rttbInvalidParameterException.h" namespace rttb { namespace testing { /*!@brief DicomIOTest - test structure set generator for dicom data 1) test dicom file structure set generator 2) test dicom IOD structure set generator */ int DicomStructureSetGeneratorTest(int argc, char* argv[]) { typedef core::StructureSet::Pointer StructureSetPointer; PREPARE_DEFAULT_TEST_REPORTING; //ARGUMENTS: 1: structure file name std::string RTSTRUCT_FILENAME; if (argc > 1) { RTSTRUCT_FILENAME = argv[1]; } /* structure set */ //1) test dicom file structure set generator CHECK_NO_THROW(io::dicom::DicomFileStructureSetGenerator("")); CHECK_NO_THROW(io::dicom::DicomFileStructureSetGenerator("Test.test")); CHECK_THROW_EXPLICIT(io::dicom::DicomFileStructureSetGenerator("Test.test").generateStructureSet(), rttb::core::InvalidParameterException); CHECK_NO_THROW(io::dicom::DicomFileStructureSetGenerator(RTSTRUCT_FILENAME.c_str())); StructureSetPointer rtStructureSet = io::dicom::DicomFileStructureSetGenerator( RTSTRUCT_FILENAME.c_str()).generateStructureSet(); //2) test dicom IOD structure set generator OFCondition status; DcmFileFormat fileformat; boost::shared_ptr drtStrSetIOD = boost::make_shared(); CHECK_NO_THROW(io::dicom::DicomIODStructureSetGenerator generator1(drtStrSetIOD)); CHECK_THROW_EXPLICIT(io::dicom::DicomIODStructureSetGenerator(drtStrSetIOD).generateStructureSet(), core::InvalidParameterException); fileformat.loadFile(RTSTRUCT_FILENAME.c_str()); drtStrSetIOD->read(*fileformat.getDataset()); CHECK_NO_THROW(io::dicom::DicomIODStructureSetGenerator generator2(drtStrSetIOD)); CHECK_NO_THROW(io::dicom::DicomIODStructureSetGenerator(drtStrSetIOD).generateStructureSet()); StructureSetPointer rtStructureSet2 = io::dicom::DicomIODStructureSetGenerator( drtStrSetIOD).generateStructureSet(); CHECK_EQUAL(rtStructureSet2->getNumberOfStructures(), rtStructureSet->getNumberOfStructures()); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb diff --git a/testing/io/dicom/rttbIOTests.cpp b/testing/io/dicom/rttbIOTests.cpp index 5f11f7b..5449c87 100644 --- a/testing/io/dicom/rttbIOTests.cpp +++ b/testing/io/dicom/rttbIOTests.cpp @@ -1,65 +1,59 @@ // ----------------------------------------------------------------------- // 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 #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif #include "litMultiTestsMain.h" namespace rttb { namespace testing { void registerTests() { LIT_REGISTER_TEST(DicomDoseAccessorConverterTest); LIT_REGISTER_TEST(DicomDoseAccessorGeneratorTest); LIT_REGISTER_TEST(DicomFileReaderHelperTest); LIT_REGISTER_TEST(DicomIOTest); LIT_REGISTER_TEST(DicomStructureSetGeneratorTest); } } } int main(int argc, char* argv[]) { int result = 0; rttb::testing::registerTests(); try { result = lit::multiTestsMain(argc, argv); } catch (...) { result = -1; } return result; }